poly1305.c
Go to the documentation of this file.
1 /**
2  * @file poly1305.c
3  * @brief Poly1305 message-authentication code
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "mac/poly1305.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (POLY1305_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Initialize Poly1305 message-authentication code computation
45  * @param[in] context Pointer to the Poly1305 context to initialize
46  * @param[in] key Pointer to the 256-bit key
47  **/
48 
49 void poly1305Init(Poly1305Context *context, const uint8_t *key)
50 {
51  //The 256-bit key is partitioned into two parts, called r and s
52  context->r[0] = LOAD32LE(key);
53  context->r[1] = LOAD32LE(key + 4);
54  context->r[2] = LOAD32LE(key + 8);
55  context->r[3] = LOAD32LE(key + 12);
56  context->s[0] = LOAD32LE(key + 16);
57  context->s[1] = LOAD32LE(key + 20);
58  context->s[2] = LOAD32LE(key + 24);
59  context->s[3] = LOAD32LE(key + 28);
60 
61  //Certain bits of r are required to be 0
62  context->r[0] &= 0x0FFFFFFF;
63  context->r[1] &= 0x0FFFFFFC;
64  context->r[2] &= 0x0FFFFFFC;
65  context->r[3] &= 0x0FFFFFFC;
66 
67  //The accumulator is set to zero
68  context->a[0] = 0;
69  context->a[1] = 0;
70  context->a[2] = 0;
71  context->a[3] = 0;
72  context->a[4] = 0;
73 
74  //Number of bytes in the buffer
75  context->size = 0;
76 }
77 
78 
79 /**
80  * @brief Update Poly1305 message-authentication code computation
81  * @param[in] context Pointer to the Poly1305 context
82  * @param[in] data Pointer to the input message
83  * @param[in] length Length of the input message
84  **/
85 
86 void poly1305Update(Poly1305Context *context, const void *data, size_t length)
87 {
88  size_t n;
89 
90  //Process the incoming data
91  while(length > 0)
92  {
93  //The buffer can hold at most 16 bytes
94  n = MIN(length, 16 - context->size);
95 
96  //Copy the data to the buffer
97  osMemcpy(context->buffer + context->size, data, n);
98 
99  //Update the Poly1305 context
100  context->size += n;
101  //Advance the data pointer
102  data = (uint8_t *) data + n;
103  //Remaining bytes to process
104  length -= n;
105 
106  //Process message in 16-byte blocks
107  if(context->size == 16)
108  {
109  //Transform the 16-byte block
110  poly1305ProcessBlock(context);
111  //Empty the buffer
112  context->size = 0;
113  }
114  }
115 }
116 
117 
118 /**
119  * @brief Finalize Poly1305 message-authentication code computation
120  * @param[in] context Pointer to the Poly1305 context
121  * @param[out] tag Calculated message-authentication code
122  **/
123 
124 void poly1305Final(Poly1305Context *context, uint8_t *tag)
125 {
126  uint64_t temp;
127  uint32_t mask;
128  uint32_t b[5];
129 
130  //Process the last block
131  if(context->size != 0)
132  {
133  poly1305ProcessBlock(context);
134  }
135 
136  //Perform modular reduction (2^130 = 5)
137  temp = context->a[4] & 0xFFFFFFFC;
138  temp += context->a[4] >> 2;
139  temp += context->a[0];
140  context->a[0] = temp & 0xFFFFFFFF;
141  temp >>= 32;
142  temp += context->a[1];
143  context->a[1] = temp & 0xFFFFFFFF;
144  temp >>= 32;
145  temp += context->a[2];
146  context->a[2] = temp & 0xFFFFFFFF;
147  temp >>= 32;
148  temp += context->a[3];
149  context->a[3] = temp & 0xFFFFFFFF;
150  temp >>= 32;
151  temp += context->a[4];
152  context->a[4] = temp & 0x00000003;
153 
154  //Compute b = a + 5
155  temp = 5;
156  temp += context->a[0];
157  b[0] = temp & 0xFFFFFFFF;
158  temp >>= 32;
159  temp += context->a[1];
160  b[1] = temp & 0xFFFFFFFF;
161  temp >>= 32;
162  temp += context->a[2];
163  b[2] = temp & 0xFFFFFFFF;
164  temp >>= 32;
165  temp += context->a[3];
166  b[3] = temp & 0xFFFFFFFF;
167  temp >>= 32;
168  temp += context->a[4];
169  b[4] = temp & 0xFFFFFFFF;
170 
171  //If (a + 5) >= 2^130, form a mask with the value 0x00000000. Else,
172  //form a mask with the value 0xffffffff
173  mask = ((b[4] & 0x04) >> 2) - 1;
174 
175  //Select between (a % 2^128) and (b % 2^128)
176  context->a[0] = (context->a[0] & mask) | (b[0] & ~mask);
177  context->a[1] = (context->a[1] & mask) | (b[1] & ~mask);
178  context->a[2] = (context->a[2] & mask) | (b[2] & ~mask);
179  context->a[3] = (context->a[3] & mask) | (b[3] & ~mask);
180 
181  //Finally, the value of the secret key s is added to the accumulator
182  temp = (uint64_t) context->a[0] + context->s[0];
183  b[0] = temp & 0xFFFFFFFF;
184  temp >>= 32;
185  temp += (uint64_t) context->a[1] + context->s[1];
186  b[1] = temp & 0xFFFFFFFF;
187  temp >>= 32;
188  temp += (uint64_t) context->a[2] + context->s[2];
189  b[2] = temp & 0xFFFFFFFF;
190  temp >>= 32;
191  temp += (uint64_t) context->a[3] + context->s[3];
192  b[3] = temp & 0xFFFFFFFF;
193 
194  //The result is serialized as a little-endian number, producing
195  //the 16 byte tag
196  STORE32LE(b[0], tag);
197  STORE32LE(b[1], tag + 4);
198  STORE32LE(b[2], tag + 8);
199  STORE32LE(b[3], tag + 12);
200 
201  //Clear the accumulator
202  context->a[0] = 0;
203  context->a[1] = 0;
204  context->a[2] = 0;
205  context->a[3] = 0;
206  context->a[4] = 0;
207 
208  //Clear r and s
209  context->r[0] = 0;
210  context->r[1] = 0;
211  context->r[2] = 0;
212  context->r[3] = 0;
213  context->s[0] = 0;
214  context->s[1] = 0;
215  context->s[2] = 0;
216  context->s[3] = 0;
217 }
218 
219 
220 /**
221  * @brief Process message in 16-byte blocks
222  * @param[in] context Pointer to the Poly1305 context
223  **/
224 
226 {
227  uint_t n;
228  uint64_t temp;
229  uint32_t u[8];
230 
231  //Retrieve the length of the last block
232  n = context->size;
233 
234  //Add one bit beyond the number of octets. For a 16-byte block,
235  //this is equivalent to adding 2^128 to the number. For the shorter
236  //block, it can be 2^120, 2^112, or any power of two that is evenly
237  //divisible by 8, all the way down to 2^8
238  context->buffer[n++] = 0x01;
239 
240  //If the resulting block is not 17 bytes long (the last block),
241  //pad it with zeros
242  while(n < 17)
243  {
244  context->buffer[n++] = 0x00;
245  }
246 
247  //Read the block as a little-endian number
248  u[0] = LOAD32LE(context->buffer);
249  u[1] = LOAD32LE(context->buffer + 4);
250  u[2] = LOAD32LE(context->buffer + 8);
251  u[3] = LOAD32LE(context->buffer + 12);
252  u[4] = context->buffer[16];
253 
254  //Add this number to the accumulator
255  temp = (uint64_t) context->a[0] + u[0];
256  context->a[0] = temp & 0xFFFFFFFF;
257  temp >>= 32;
258  temp += (uint64_t) context->a[1] + u[1];
259  context->a[1] = temp & 0xFFFFFFFF;
260  temp >>= 32;
261  temp += (uint64_t) context->a[2] + u[2];
262  context->a[2] = temp & 0xFFFFFFFF;
263  temp >>= 32;
264  temp += (uint64_t) context->a[3] + u[3];
265  context->a[3] = temp & 0xFFFFFFFF;
266  temp >>= 32;
267  temp += (uint64_t) context->a[4] + u[4];
268  context->a[4] = temp & 0xFFFFFFFF;
269 
270  //Multiply the accumulator by r
271  temp = (uint64_t) context->a[0] * context->r[0];
272  u[0] = temp & 0xFFFFFFFF;
273  temp >>= 32;
274  temp += (uint64_t) context->a[0] * context->r[1];
275  temp += (uint64_t) context->a[1] * context->r[0];
276  u[1] = temp & 0xFFFFFFFF;
277  temp >>= 32;
278  temp += (uint64_t) context->a[0] * context->r[2];
279  temp += (uint64_t) context->a[1] * context->r[1];
280  temp += (uint64_t) context->a[2] * context->r[0];
281  u[2] = temp & 0xFFFFFFFF;
282  temp >>= 32;
283  temp += (uint64_t) context->a[0] * context->r[3];
284  temp += (uint64_t) context->a[1] * context->r[2];
285  temp += (uint64_t) context->a[2] * context->r[1];
286  temp += (uint64_t) context->a[3] * context->r[0];
287  u[3] = temp & 0xFFFFFFFF;
288  temp >>= 32;
289  temp += (uint64_t) context->a[1] * context->r[3];
290  temp += (uint64_t) context->a[2] * context->r[2];
291  temp += (uint64_t) context->a[3] * context->r[1];
292  temp += (uint64_t) context->a[4] * context->r[0];
293  u[4] = temp & 0xFFFFFFFF;
294  temp >>= 32;
295  temp += (uint64_t) context->a[2] * context->r[3];
296  temp += (uint64_t) context->a[3] * context->r[2];
297  temp += (uint64_t) context->a[4] * context->r[1];
298  u[5] = temp & 0xFFFFFFFF;
299  temp >>= 32;
300  temp += (uint64_t) context->a[3] * context->r[3];
301  temp += (uint64_t) context->a[4] * context->r[2];
302  u[6] = temp & 0xFFFFFFFF;
303  temp >>= 32;
304  temp += (uint64_t) context->a[4] * context->r[3];
305  u[7] = temp & 0xFFFFFFFF;
306 
307  //Perform modular reduction
308  temp = u[0];
309  temp += u[4] & 0xFFFFFFFC;
310  temp += (u[4] >> 2) | (u[5] << 30);
311  context->a[0] = temp & 0xFFFFFFFF;
312  temp >>= 32;
313  temp += u[1];
314  temp += u[5];
315  temp += (u[5] >> 2) | (u[6] << 30);
316  context->a[1] = temp & 0xFFFFFFFF;
317  temp >>= 32;
318  temp += u[2];
319  temp += u[6];
320  temp += (u[6] >> 2) | (u[7] << 30);
321  context->a[2] = temp & 0xFFFFFFFF;
322  temp >>= 32;
323  temp += u[3];
324  temp += u[7];
325  temp += u[7] >> 2;
326  context->a[3] = temp & 0xFFFFFFFF;
327  temp >>= 32;
328  temp += u[4] & 0x00000003;
329  context->a[4] = temp & 0xFFFFFFFF;
330 }
331 
332 #endif
void poly1305Init(Poly1305Context *context, const uint8_t *key)
Initialize Poly1305 message-authentication code computation.
Definition: poly1305.c:49
uint8_t b
Definition: nbns_common.h:104
uint32_t r[4]
Definition: poly1305.h:49
uint8_t data[]
Definition: ethernet.h:222
Poly1305 context.
Definition: poly1305.h:48
#define STORE32LE(a, p)
Definition: cpu_endian.h:279
uint32_t s[4]
Definition: poly1305.h:50
uint8_t buffer[17]
Definition: poly1305.h:52
uint32_t a[5]
Definition: poly1305.h:51
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
Poly1305 message-authentication code.
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:319
uint8_t u
Definition: lldp_ext_med.h:213
uint8_t length
Definition: tcp.h:375
#define MIN(a, b)
Definition: os_port.h:63
uint8_t n
void poly1305ProcessBlock(Poly1305Context *context)
Process message in 16-byte blocks.
Definition: poly1305.c:225
void poly1305Final(Poly1305Context *context, uint8_t *tag)
Finalize Poly1305 message-authentication code computation.
Definition: poly1305.c:124
void poly1305Update(Poly1305Context *context, const void *data, size_t length)
Update Poly1305 message-authentication code computation.
Definition: poly1305.c:86
#define LOAD32LE(p)
Definition: cpu_endian.h:203
unsigned int uint_t
Definition: compiler_port.h:57
size_t size
Definition: poly1305.h:53
Debugging facilities.