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-2024 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.4.4
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  context->a[5] = 0;
74  context->a[6] = 0;
75  context->a[7] = 0;
76 
77  //Number of bytes in the buffer
78  context->size = 0;
79 }
80 
81 
82 /**
83  * @brief Update Poly1305 message-authentication code computation
84  * @param[in] context Pointer to the Poly1305 context
85  * @param[in] data Pointer to the input message
86  * @param[in] length Length of the input message
87  **/
88 
89 void poly1305Update(Poly1305Context *context, const void *data, size_t length)
90 {
91  size_t n;
92 
93  //Process the incoming data
94  while(length > 0)
95  {
96  //The buffer can hold at most 16 bytes
97  n = MIN(length, 16 - context->size);
98 
99  //Copy the data to the buffer
100  osMemcpy(context->buffer + context->size, data, n);
101 
102  //Update the Poly1305 context
103  context->size += n;
104  //Advance the data pointer
105  data = (uint8_t *) data + n;
106  //Remaining bytes to process
107  length -= n;
108 
109  //Process message in 16-byte blocks
110  if(context->size == 16)
111  {
112  //Transform the 16-byte block
113  poly1305ProcessBlock(context);
114  //Empty the buffer
115  context->size = 0;
116  }
117  }
118 }
119 
120 
121 /**
122  * @brief Finalize Poly1305 message-authentication code computation
123  * @param[in] context Pointer to the Poly1305 context
124  * @param[out] tag Calculated message-authentication code
125  **/
126 
127 void poly1305Final(Poly1305Context *context, uint8_t *tag)
128 {
129  uint32_t mask;
130  uint32_t b[4];
131 
132  //Process the last block
133  if(context->size != 0)
134  poly1305ProcessBlock(context);
135 
136  //Save the accumulator
137  b[0] = context->a[0] & 0xFFFFFFFF;
138  b[1] = context->a[1] & 0xFFFFFFFF;
139  b[2] = context->a[2] & 0xFFFFFFFF;
140  b[3] = context->a[3] & 0xFFFFFFFF;
141 
142  //Compute a + 5
143  context->a[0] += 5;
144 
145  //Propagate the carry
146  context->a[1] += context->a[0] >> 32;
147  context->a[2] += context->a[1] >> 32;
148  context->a[3] += context->a[2] >> 32;
149  context->a[4] += context->a[3] >> 32;
150 
151  //If (a + 5) >= 2^130, form a mask with the value 0x00000000. Else,
152  //form a mask with the value 0xffffffff
153  mask = ((context->a[4] & 0x04) >> 2) - 1;
154 
155  //Select between ((a - (2^130 - 5)) % 2^128) and (a % 2^128)
156  context->a[0] = (context->a[0] & ~mask) | (b[0] & mask);
157  context->a[1] = (context->a[1] & ~mask) | (b[1] & mask);
158  context->a[2] = (context->a[2] & ~mask) | (b[2] & mask);
159  context->a[3] = (context->a[3] & ~mask) | (b[3] & mask);
160 
161  //Finally, the value of the secret key s is added to the accumulator
162  context->a[0] += context->s[0];
163  context->a[1] += context->s[1];
164  context->a[2] += context->s[2];
165  context->a[3] += context->s[3];
166 
167  //Propagate the carry
168  context->a[1] += context->a[0] >> 32;
169  context->a[2] += context->a[1] >> 32;
170  context->a[3] += context->a[2] >> 32;
171  context->a[4] += context->a[3] >> 32;
172 
173  //We only consider the least significant bits
174  b[0] = context->a[0] & 0xFFFFFFFF;
175  b[1] = context->a[1] & 0xFFFFFFFF;
176  b[2] = context->a[2] & 0xFFFFFFFF;
177  b[3] = context->a[3] & 0xFFFFFFFF;
178 
179  //The result is serialized as a little-endian number, producing
180  //the 16 byte tag
181  STORE32LE(b[0], tag);
182  STORE32LE(b[1], tag + 4);
183  STORE32LE(b[2], tag + 8);
184  STORE32LE(b[3], tag + 12);
185 
186  //Clear the accumulator
187  context->a[0] = 0;
188  context->a[1] = 0;
189  context->a[2] = 0;
190  context->a[3] = 0;
191  context->a[4] = 0;
192  context->a[5] = 0;
193  context->a[6] = 0;
194  context->a[7] = 0;
195 
196  //Clear r and s
197  context->r[0] = 0;
198  context->r[1] = 0;
199  context->r[2] = 0;
200  context->r[3] = 0;
201  context->s[0] = 0;
202  context->s[1] = 0;
203  context->s[2] = 0;
204  context->s[3] = 0;
205 }
206 
207 
208 /**
209  * @brief Process message in 16-byte blocks
210  * @param[in] context Pointer to the Poly1305 context
211  **/
212 
214 {
215  uint32_t a[5];
216  uint32_t r[4];
217  uint_t n;
218 
219  //Retrieve the length of the last block
220  n = context->size;
221 
222  //Add one bit beyond the number of octets. For a 16-byte block,
223  //this is equivalent to adding 2^128 to the number. For the shorter
224  //block, it can be 2^120, 2^112, or any power of two that is evenly
225  //divisible by 8, all the way down to 2^8
226  context->buffer[n++] = 0x01;
227 
228  //If the resulting block is not 17 bytes long (the last block),
229  //pad it with zeros
230  while(n < 17)
231  {
232  context->buffer[n++] = 0x00;
233  }
234 
235  //Read the block as a little-endian number
236  a[0] = LOAD32LE(context->buffer);
237  a[1] = LOAD32LE(context->buffer + 4);
238  a[2] = LOAD32LE(context->buffer + 8);
239  a[3] = LOAD32LE(context->buffer + 12);
240  a[4] = context->buffer[16];
241 
242  //Add this number to the accumulator
243  context->a[0] += a[0];
244  context->a[1] += a[1];
245  context->a[2] += a[2];
246  context->a[3] += a[3];
247  context->a[4] += a[4];
248 
249  //Propagate the carry
250  context->a[1] += context->a[0] >> 32;
251  context->a[2] += context->a[1] >> 32;
252  context->a[3] += context->a[2] >> 32;
253  context->a[4] += context->a[3] >> 32;
254 
255  //We only consider the least significant bits
256  a[0] = context->a[0] & 0xFFFFFFFF;
257  a[1] = context->a[1] & 0xFFFFFFFF;
258  a[2] = context->a[2] & 0xFFFFFFFF;
259  a[3] = context->a[3] & 0xFFFFFFFF;
260  a[4] = context->a[4] & 0xFFFFFFFF;
261 
262  //Copy r
263  r[0] = context->r[0];
264  r[1] = context->r[1];
265  r[2] = context->r[2];
266  r[3] = context->r[3];
267 
268  //Multiply the accumulator by r
269  context->a[0] = (uint64_t) a[0] * r[0];
270  context->a[1] = (uint64_t) a[0] * r[1] + (uint64_t) a[1] * r[0];
271  context->a[2] = (uint64_t) a[0] * r[2] + (uint64_t) a[1] * r[1] + (uint64_t) a[2] * r[0];
272  context->a[3] = (uint64_t) a[0] * r[3] + (uint64_t) a[1] * r[2] + (uint64_t) a[2] * r[1] + (uint64_t) a[3] * r[0];
273  context->a[4] = (uint64_t) a[1] * r[3] + (uint64_t) a[2] * r[2] + (uint64_t) a[3] * r[1] + (uint64_t) a[4] * r[0];
274  context->a[5] = (uint64_t) a[2] * r[3] + (uint64_t) a[3] * r[2] + (uint64_t) a[4] * r[1];
275  context->a[6] = (uint64_t) a[3] * r[3] + (uint64_t) a[4] * r[2];
276  context->a[7] = (uint64_t) a[4] * r[3];
277 
278  //Propagate the carry
279  context->a[1] += context->a[0] >> 32;
280  context->a[2] += context->a[1] >> 32;
281  context->a[3] += context->a[2] >> 32;
282  context->a[4] += context->a[3] >> 32;
283  context->a[5] += context->a[4] >> 32;
284  context->a[6] += context->a[5] >> 32;
285  context->a[7] += context->a[6] >> 32;
286 
287  //Save the high part of the accumulator
288  a[0] = context->a[4] & 0xFFFFFFFC;
289  a[1] = context->a[5] & 0xFFFFFFFF;
290  a[2] = context->a[6] & 0xFFFFFFFF;
291  a[3] = context->a[7] & 0xFFFFFFFF;
292 
293  //We only consider the least significant bits
294  context->a[0] &= 0xFFFFFFFF;
295  context->a[1] &= 0xFFFFFFFF;
296  context->a[2] &= 0xFFFFFFFF;
297  context->a[3] &= 0xFFFFFFFF;
298  context->a[4] &= 0x00000003;
299 
300  //Perform fast modular reduction (first pass)
301  context->a[0] += a[0];
302  context->a[0] += (a[0] >> 2) | (a[1] << 30);
303  context->a[1] += a[1];
304  context->a[1] += (a[1] >> 2) | (a[2] << 30);
305  context->a[2] += a[2];
306  context->a[2] += (a[2] >> 2) | (a[3] << 30);
307  context->a[3] += a[3];
308  context->a[3] += (a[3] >> 2);
309 
310  //Propagate the carry
311  context->a[1] += context->a[0] >> 32;
312  context->a[2] += context->a[1] >> 32;
313  context->a[3] += context->a[2] >> 32;
314  context->a[4] += context->a[3] >> 32;
315 
316  //Save the high part of the accumulator
317  a[0] = context->a[4] & 0xFFFFFFFC;
318 
319  //We only consider the least significant bits
320  context->a[0] &= 0xFFFFFFFF;
321  context->a[1] &= 0xFFFFFFFF;
322  context->a[2] &= 0xFFFFFFFF;
323  context->a[3] &= 0xFFFFFFFF;
324  context->a[4] &= 0x00000003;
325 
326  //Perform fast modular reduction (second pass)
327  context->a[0] += a[0];
328  context->a[0] += a[0] >> 2;
329 
330  //Propagate the carry
331  context->a[1] += context->a[0] >> 32;
332  context->a[2] += context->a[1] >> 32;
333  context->a[3] += context->a[2] >> 32;
334  context->a[4] += context->a[3] >> 32;
335 
336  //We only consider the least significant bits
337  context->a[0] &= 0xFFFFFFFF;
338  context->a[1] &= 0xFFFFFFFF;
339  context->a[2] &= 0xFFFFFFFF;
340  context->a[3] &= 0xFFFFFFFF;
341  context->a[4] &= 0x00000003;
342 }
343 
344 #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
uint8_t a
Definition: ndp.h:411
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
uint8_t r
Definition: ndp.h:346
uint64_t a[8]
Definition: poly1305.h:51
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
Poly1305 message-authentication code.
General definitions for cryptographic algorithms.
uint8_t mask
Definition: web_socket.h:319
uint8_t length
Definition: tcp.h:368
#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:213
void poly1305Final(Poly1305Context *context, uint8_t *tag)
Finalize Poly1305 message-authentication code computation.
Definition: poly1305.c:127
void poly1305Update(Poly1305Context *context, const void *data, size_t length)
Update Poly1305 message-authentication code computation.
Definition: poly1305.c:89
#define LOAD32LE(p)
Definition: cpu_endian.h:203
unsigned int uint_t
Definition: compiler_port.h:50
size_t size
Definition: poly1305.h:53
Debugging facilities.