ed448.c
Go to the documentation of this file.
1 /**
2  * @file ed448.c
3  * @brief Ed448 elliptic curve (constant-time implementation)
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 "ecc/ec_curves.h"
37 #include "ecc/curve448.h"
38 #include "ecc/ed448.h"
39 #include "debug.h"
40 
41 //Check crypto library configuration
42 #if (ED448_SUPPORT == ENABLED)
43 
44 //Base point B
45 static const Ed448Point ED448_B =
46 {
47  {
48  0xC70CC05E, 0x2626A82B, 0x8B00938E, 0x433B80E1, 0x2AB66511, 0x12AE1AF7, 0xA3D3A464,
49  0xEA6DE324, 0x470F1767, 0x9E146570, 0x22BF36DA, 0x221D15A6, 0x6BED0DED, 0x4F1970C6
50  },
51  {
52  0xF230FA14, 0x9808795B, 0x4ED7C8AD, 0xFDBD132C, 0xE67C39C4, 0x3AD3FF1C, 0x05A0C2D7,
53  0x87789C1E, 0x6CA39840, 0x4BEA7373, 0x56C9C762, 0x88762037, 0x6EB6BC24, 0x693F4671
54  },
55  {
56  0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
58  }
59 };
60 
61 //Zero (constant)
62 static const uint32_t ED448_ZERO[14] =
63 {
64  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
65  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
66 };
67 
68 //Curve parameter d
69 static const uint32_t ED448_D[14] =
70 {
71  0xFFFF6756, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
72  0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
73 };
74 
75 //Order of the base point L
76 static const uint8_t ED448_L[60] =
77 {
78  0xF3, 0x44, 0x58, 0xAB, 0x92, 0xC2, 0x78, 0x23, 0x55, 0x8F, 0xC5, 0x8D, 0x72, 0xC2, 0x6C, 0x21,
79  0x90, 0x36, 0xD6, 0xAE, 0x49, 0xDB, 0x4E, 0xC4, 0xE9, 0x23, 0xCA, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF,
80  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
81  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00
82 };
83 
84 //Pre-computed value of mu = b^(2 * k) / L with b = 2^24 and k = 19
85 static const uint8_t ED448_MU[60] =
86 {
87  0x0A, 0xD0, 0xE0, 0xB0, 0x7B, 0x4A, 0xD5, 0xD6, 0x73, 0xC8, 0xAD, 0x0A, 0xA7, 0x23, 0xD7, 0xD8,
88  0x33, 0xE9, 0xFD, 0x96, 0x9C, 0x12, 0x65, 0x4B, 0x12, 0xBB, 0x63, 0xC1, 0x5D, 0x33, 0x08, 0x00,
89  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00
91 };
92 
93 
94 /**
95  * @brief EdDSA key pair generation
96  * @param[in] prngAlgo PRNG algorithm
97  * @param[in] prngContext Pointer to the PRNG context
98  * @param[out] privateKey EdDSA private key (57 bytes)
99  * @param[out] publicKey EdDSA public key (57 bytes)
100  * @return Error code
101  **/
102 
103 error_t ed448GenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext,
104  uint8_t *privateKey, uint8_t *publicKey)
105 {
106  error_t error;
107 
108  //Generate a private key
109  error = ed448GeneratePrivateKey(prngAlgo, prngContext, privateKey);
110 
111  //Check status code
112  if(!error)
113  {
114  //Derive the public key from the private key
115  error = ed448GeneratePublicKey(privateKey, publicKey);
116  }
117 
118  //Return status code
119  return error;
120 }
121 
122 
123 /**
124  * @brief EdDSA private key generation
125  * @param[in] prngAlgo PRNG algorithm
126  * @param[in] prngContext Pointer to the PRNG context
127  * @param[out] privateKey EdDSA private key (57 bytes)
128  * @return Error code
129  **/
130 
131 error_t ed448GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext,
132  uint8_t *privateKey)
133 {
134  error_t error;
135 
136  //Check parameters
137  if(prngAlgo == NULL || prngContext == NULL || privateKey == NULL)
139 
140  //The private key is 57 octets of cryptographically secure random data
141  error = prngAlgo->read(prngContext, privateKey, ED448_PRIVATE_KEY_LEN);
142 
143  //Return status code
144  return error;
145 }
146 
147 
148 /**
149  * @brief Derive the public key from an EdDSA private key
150  * @param[in] privateKey EdDSA private key (57 bytes)
151  * @param[out] publicKey EdDSA public key (57 bytes)
152  * @return Error code
153  **/
154 
155 error_t ed448GeneratePublicKey(const uint8_t *privateKey, uint8_t *publicKey)
156 {
157  uint8_t s[57];
158 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
159  Ed448State *state;
160 #else
161  Ed448State state[1];
162 #endif
163 
164  //Check parameters
165  if(privateKey == NULL || publicKey == NULL)
167 
168 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
169  //Allocate working state
170  state = cryptoAllocMem(sizeof(Ed448State));
171  //Failed to allocate memory?
172  if(state == NULL)
173  return ERROR_OUT_OF_MEMORY;
174 #endif
175 
176  //Hash the 57-byte private key using SHAKE256(x, 57)
177  shakeInit(&state->shakeContext, 256);
178  shakeAbsorb(&state->shakeContext, privateKey, ED448_PRIVATE_KEY_LEN);
179  shakeFinal(&state->shakeContext);
180 
181  //Only the lower 57 bytes are used for generating the public key. Interpret
182  //the buffer as the little-endian integer, forming a secret scalar s
183  shakeSqueeze(&state->shakeContext, s, 57);
184 
185  //The two least significant bits of the first octet are cleared, all eight
186  //bits the last octet are cleared, and the highest bit of the second to
187  //last octet is set
188  s[0] &= 0xFC;
189  s[56] = 0x00;
190  s[55] |= 0x80;
191 
192  //Perform a fixed-base scalar multiplication s * B
193  ed448Mul(state, &state->sb, s, &ED448_B);
194  //The public key A is the encoding of the point s * B
195  ed448Encode(&state->sb, publicKey);
196 
197  //Erase working state
198  osMemset(state, 0, sizeof(Ed448State));
199 
200 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
201  //Release working state
202  cryptoFreeMem(state);
203 #endif
204 
205  //Successful processing
206  return NO_ERROR;
207 }
208 
209 
210 /**
211  * @brief EdDSA signature generation
212  * @param[in] privateKey Signer's EdDSA private key (57 bytes)
213  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
214  * @param[in] message Pointer to the message to be signed
215  * @param[in] messageLen Length of the message, in bytes
216  * @param[in] context Constant string specified by the protocol using it
217  * @param[in] contextLen Length of the context, in bytes
218  * @param[in] flag Prehash flag for Ed448ph scheme
219  * @param[out] signature EdDSA signature (114 bytes)
220  * @return Error code
221  **/
222 
223 error_t ed448GenerateSignature(const uint8_t *privateKey,
224  const uint8_t *publicKey, const void *message, size_t messageLen,
225  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
226 {
227  error_t error;
228  DataChunk messageChunks[2];
229 
230  //The message fits in a single chunk
231  messageChunks[0].buffer = message;
232  messageChunks[0].length = messageLen;
233  messageChunks[1].buffer = NULL;
234  messageChunks[1].length = 0;
235 
236  //Ed448 signature generation
237  error = ed448GenerateSignatureEx(privateKey, publicKey, messageChunks,
238  context, contextLen, flag, signature);
239 
240  //Return status code
241  return error;
242 }
243 
244 
245 /**
246  * @brief EdDSA signature generation
247  * @param[in] privateKey Signer's EdDSA private key (57 bytes)
248  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
249  * @param[in] messageChunks Array of data chunks representing the message
250  * to be signed
251  * @param[in] context Constant string specified by the protocol using it
252  * @param[in] contextLen Length of the context, in bytes
253  * @param[in] flag Prehash flag for Ed448ph scheme
254  * @param[out] signature EdDSA signature (114 bytes)
255  * @return Error code
256  **/
257 
258 error_t ed448GenerateSignatureEx(const uint8_t *privateKey,
259  const uint8_t *publicKey, const DataChunk *messageChunks,
260  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
261 {
262  uint_t i;
263  uint8_t c;
264 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
265  Ed448State *state;
266 #else
267  Ed448State state[1];
268 #endif
269 
270  //Check parameters
271  if(privateKey == NULL || signature == NULL)
273  if(messageChunks == NULL)
275  if(context == NULL && contextLen != 0)
277 
278 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
279  //Allocate working state
280  state = cryptoAllocMem(sizeof(Ed448State));
281  //Failed to allocate memory?
282  if(state == NULL)
283  return ERROR_OUT_OF_MEMORY;
284 #endif
285 
286  //Hash the private key, 57 octets, using SHAKE256(x, 114). Let h denote
287  //the resulting digest
288  shakeInit(&state->shakeContext, 256);
289  shakeAbsorb(&state->shakeContext, privateKey, ED448_PRIVATE_KEY_LEN);
290  shakeFinal(&state->shakeContext);
291 
292  //Construct the secret scalar s from the first half of the digest
293  shakeSqueeze(&state->shakeContext, state->s, 57);
294 
295  //The two least significant bits of the first octet are cleared, all eight
296  //bits the last octet are cleared, and the highest bit of the second to
297  //last octet is set
298  state->s[0] &= 0xFC;
299  state->s[56] = 0x00;
300  state->s[55] |= 0x80;
301 
302  //The public key is optional
303  if(publicKey == NULL)
304  {
305  //Perform a fixed-base scalar multiplication s * B
306  ed448Mul(state, &state->sb, state->s, &ED448_B);
307  //The public key A is the encoding of the point s * B
308  ed448Encode(&state->sb, state->t);
309  //Point to the resulting public key
310  publicKey = state->t;
311  }
312 
313  //Let prefix denote the second half of the hash digest
314  shakeSqueeze(&state->shakeContext, state->p, 57);
315 
316  //Initialize SHAKE256 context
317  shakeInit(&state->shakeContext, 256);
318 
319  //Absorb dom4(F, C) || prefix
320  shakeAbsorb(&state->shakeContext, "SigEd448", 8);
321  shakeAbsorb(&state->shakeContext, &flag, sizeof(uint8_t));
322  shakeAbsorb(&state->shakeContext, &contextLen, sizeof(uint8_t));
323  shakeAbsorb(&state->shakeContext, context, contextLen);
324  shakeAbsorb(&state->shakeContext, state->p, 57);
325 
326  //The message is split over multiple chunks
327  for(i = 0; messageChunks[i].buffer != NULL; i++)
328  {
329  //Absorb current chunk
330  shakeAbsorb(&state->shakeContext, messageChunks[i].buffer,
331  messageChunks[i].length);
332  }
333 
334  //Compute SHAKE256(dom4(F, C) || prefix || PH(M), 114)
335  shakeFinal(&state->shakeContext);
336  shakeSqueeze(&state->shakeContext, state->k, 114);
337 
338  //Reduce the 114-octet digest as a little-endian integer r
339  ed448RedInt(state->r, state->k);
340  //Compute the point r * B
341  ed448Mul(state, &state->rb, state->r, &ED448_B);
342  //Let the string R be the encoding of this point
343  ed448Encode(&state->rb, signature);
344 
345  //Initialize SHAKE256 context
346  shakeInit(&state->shakeContext, 256);
347 
348  //Absorb dom4(F, C) || R || A
349  shakeAbsorb(&state->shakeContext, "SigEd448", 8);
350  shakeAbsorb(&state->shakeContext, &flag, sizeof(uint8_t));
351  shakeAbsorb(&state->shakeContext, &contextLen, sizeof(uint8_t));
352  shakeAbsorb(&state->shakeContext, context, contextLen);
353  shakeAbsorb(&state->shakeContext, signature, ED448_SIGNATURE_LEN / 2);
354  shakeAbsorb(&state->shakeContext, publicKey, ED448_PUBLIC_KEY_LEN);
355 
356  //The message is split over multiple chunks
357  for(i = 0; messageChunks[i].buffer != NULL; i++)
358  {
359  //Absorb current chunk
360  shakeAbsorb(&state->shakeContext, messageChunks[i].buffer,
361  messageChunks[i].length);
362  }
363 
364  //Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114) and interpret the
365  //114-octet digest as a little-endian integer k
366  shakeFinal(&state->shakeContext);
367  shakeSqueeze(&state->shakeContext, state->k, 114);
368 
369  //Compute S = (r + k * s) mod L. For efficiency, reduce k modulo L first
370  ed448RedInt(state->p, state->k);
371  ed448MulInt(state->k, state->k + 57, state->p, state->s, 57);
372  ed448RedInt(state->p, state->k);
373  ed448AddInt(state->s, state->p, state->r, 57);
374 
375  //Perform modular reduction
376  c = ed448SubInt(state->p, state->s, ED448_L, 57);
377  ed448SelectInt(signature + 57, state->p, state->s, c, 57);
378 
379  //Erase working state
380  osMemset(state, 0, sizeof(Ed448State));
381 
382 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
383  //Release working state
384  cryptoFreeMem(state);
385 #endif
386 
387  //Successful processing
388  return NO_ERROR;
389 }
390 
391 
392 /**
393  * @brief EdDSA signature verification
394  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
395  * @param[in] message Message whose signature is to be verified
396  * @param[in] messageLen Length of the message, in bytes
397  * @param[in] context Constant string specified by the protocol using it
398  * @param[in] contextLen Length of the context, in bytes
399  * @param[in] flag Prehash flag for Ed448ph scheme
400  * @param[in] signature EdDSA signature (114 bytes)
401  * @return Error code
402  **/
403 
404 error_t ed448VerifySignature(const uint8_t *publicKey, const void *message,
405  size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag,
406  const uint8_t *signature)
407 {
408  error_t error;
409  DataChunk messageChunks[2];
410 
411  //The message fits in a single chunk
412  messageChunks[0].buffer = message;
413  messageChunks[0].length = messageLen;
414  messageChunks[1].buffer = NULL;
415  messageChunks[1].length = 0;
416 
417  //Ed448 signature verification
418  error = ed448VerifySignatureEx(publicKey, messageChunks, context,
419  contextLen, flag, signature);
420 
421  //Return status code
422  return error;
423 }
424 
425 
426 /**
427  * @brief EdDSA signature verification
428  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
429  * @param[in] messageChunks Array of data chunks representing the message
430  * whose signature is to be verified
431  * @param[in] context Constant string specified by the protocol using it
432  * @param[in] contextLen Length of the context, in bytes
433  * @param[in] flag Prehash flag for Ed448ph scheme
434  * @param[in] signature EdDSA signature (114 bytes)
435  * @return Error code
436  **/
437 
438 error_t ed448VerifySignatureEx(const uint8_t *publicKey,
439  const DataChunk *messageChunks, const void *context,
440  uint8_t contextLen, uint8_t flag, const uint8_t *signature)
441 {
442  uint_t i;
443  uint32_t ret;
444 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
445  Ed448State *state;
446 #else
447  Ed448State state[1];
448 #endif
449 
450  //Check parameters
451  if(publicKey == NULL || signature == NULL)
453  if(messageChunks == NULL)
455  if(context == NULL && contextLen != 0)
457 
458 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
459  //Allocate working state
460  state = cryptoAllocMem(sizeof(Ed448State));
461  //Failed to allocate memory?
462  if(state == NULL)
463  return ERROR_OUT_OF_MEMORY;
464 #endif
465 
466  //First split the signature into two 32-octet halves. Decode the first
467  //half as a point R
468  osMemcpy(state->r, signature, ED448_SIGNATURE_LEN / 2);
469 
470  //Decode the second half as an integer S, in the range 0 <= s < L
471  osMemcpy(state->s, signature + ED448_SIGNATURE_LEN / 2,
472  ED448_SIGNATURE_LEN / 2);
473 
474  //Ed448 signatures are not malleable due to the verification check that
475  //decoded S is smaller than L (refer to RFC 8032, section 8.4)
476  ret = 1 ^ ed448SubInt(state->p, state->s, ED448_L, ED448_SIGNATURE_LEN / 2);
477 
478  //Decode the public key A as point A'
479  ret |= ed448Decode(&state->ka, publicKey);
480 
481  //Initialize SHAKE256 context
482  shakeInit(&state->shakeContext, 256);
483 
484  //Absorb dom4(F, C) || R || A
485  shakeAbsorb(&state->shakeContext, "SigEd448", 8);
486  shakeAbsorb(&state->shakeContext, &flag, sizeof(uint8_t));
487  shakeAbsorb(&state->shakeContext, &contextLen, sizeof(uint8_t));
488  shakeAbsorb(&state->shakeContext, context, contextLen);
489  shakeAbsorb(&state->shakeContext, state->r, ED448_SIGNATURE_LEN / 2);
490  shakeAbsorb(&state->shakeContext, publicKey, ED448_PUBLIC_KEY_LEN);
491 
492  //The message is split over multiple chunks
493  for(i = 0; messageChunks[i].buffer != NULL; i++)
494  {
495  //Absorb current chunk
496  shakeAbsorb(&state->shakeContext, messageChunks[i].buffer,
497  messageChunks[i].length);
498  }
499 
500  //Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114) and interpret the
501  //114-octet digest as a little-endian integer k
502  shakeFinal(&state->shakeContext);
503  shakeSqueeze(&state->shakeContext, state->k, 114);
504 
505  //For efficiency, reduce k modulo L first
506  ed448RedInt(state->k, state->k);
507 
508  //Compute the point P = s * B - k * A'
509  curve448Sub(state->ka.x, ED448_ZERO, state->ka.x);
510  ed448Mul(state, &state->sb, state->s, &ED448_B);
511  ed448Mul(state, &state->ka, state->k, &state->ka);
512  ed448Add(state, &state->ka, &state->sb, &state->ka);
513 
514  //Encode of the resulting point P
515  ed448Encode(&state->ka, state->p);
516 
517  //If P = R, then the signature is verified. If P does not equal R,
518  //then the message or the signature may have been modified
519  ret |= ed448CompInt(state->p, signature, ED448_SIGNATURE_LEN / 2);
520 
521  //Erase working state
522  osMemset(state, 0, sizeof(Ed448State));
523 
524 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
525  //Release working state
526  cryptoFreeMem(state);
527 #endif
528 
529  //Return status code
530  return (ret == 0) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
531 }
532 
533 
534 /**
535  * @brief Scalar multiplication on Ed448 curve
536  * @param[in] state Pointer to the working state
537  * @param[out] r Resulting point R = k * P
538  * @param[in] k Input scalar
539  * @param[in] p Input point
540  **/
541 
542 void ed448Mul(Ed448State *state, Ed448Point *r, const uint8_t *k,
543  const Ed448Point *p)
544 {
545  int_t i;
546  uint8_t b;
547 
548  //The neutral element is represented by (0, 1, 1)
549  curve448SetInt(state->u.x, 0);
550  curve448SetInt(state->u.y, 1);
551  curve448SetInt(state->u.z, 1);
552 
553  //Perform scalar multiplication
554  for(i = CURVE448_BIT_LEN - 1; i >= 0; i--)
555  {
556  //The scalar is processed in a left-to-right fashion
557  b = (k[i / 8] >> (i % 8)) & 1;
558 
559  //Compute U = 2 * U
560  ed448Double(state, &state->u, &state->u);
561  //Compute V = U + P
562  ed448Add(state, &state->v, &state->u, p);
563 
564  //If b is set, then U = V
565  curve448Select(state->u.x, state->u.x, state->v.x, b);
566  curve448Select(state->u.y, state->u.y, state->v.y, b);
567  curve448Select(state->u.z, state->u.z, state->v.z, b);
568  }
569 
570  //Copy result
571  curve448Copy(r->x, state->u.x);
572  curve448Copy(r->y, state->u.y);
573  curve448Copy(r->z, state->u.z);
574 }
575 
576 
577 /**
578  * @brief Point addition
579  * @param[in] state Pointer to the working state
580  * @param[out] r Resulting point R = P + Q
581  * @param[in] p First operand
582  * @param[in] q Second operand
583  **/
584 
585 void ed448Add(Ed448State *state, Ed448Point *r, const Ed448Point *p,
586  const Ed448Point *q)
587 {
588  //Compute A = X1 * X2
589  curve448Mul(state->a, p->x, q->x);
590  //Compute B = Y1 * Y2
591  curve448Mul(state->b, p->y, q->y);
592  //Compute C = Z1 * Z2
593  curve448Mul(state->c, p->z, q->z);
594  //Compute D = C^2
595  curve448Sqr(state->d, state->c);
596  //Compute E = d * A * B
597  curve448Mul(state->e, state->a, state->b);
598  curve448Mul(state->e, state->e, ED448_D);
599  //Compute F = D + E
600  curve448Add(state->f, state->d, state->e);
601  //Compute G = D - E
602  curve448Sub(state->g, state->d, state->e);
603  //Compute D = (X1 + Y1) * (X2 + Y2)
604  curve448Add(state->d, p->x, p->y);
605  curve448Add(state->e, q->x, q->y);
606  curve448Mul(state->d, state->d, state->e);
607  //Compute X3 = C * G * (D - A - B)
608  curve448Sub(state->d, state->d, state->a);
609  curve448Sub(state->d, state->d, state->b);
610  curve448Mul(state->d, state->d, state->c);
611  curve448Mul(r->x, state->d, state->g);
612  //Compute Y3 = C * F * (B - A)
613  curve448Sub(state->b, state->b, state->a);
614  curve448Mul(state->b, state->b, state->c);
615  curve448Mul(r->y, state->b, state->f);
616  //Compute Z3 = F * G
617  curve448Mul(r->z, state->f, state->g);
618 }
619 
620 
621 /**
622  * @brief Point doubling
623  * @param[in] state Pointer to the working state
624  * @param[out] r Resulting point R = 2 * P
625  * @param[in] p Input point P
626  **/
627 
629 {
630  //Compute A = X1 * X2
631  curve448Mul(state->a, p->x, p->x);
632  //Compute B = Y1 * Y2
633  curve448Mul(state->b, p->y, p->y);
634  //Compute C = Z1 * Z2
635  curve448Mul(state->c, p->z, p->z);
636  //Compute F = A + B
637  curve448Add(state->f, state->a, state->b);
638  //Compute G = F - 2 * C
639  curve448Add(state->c, state->c, state->c);
640  curve448Sub(state->g, state->f, state->c);
641  //Compute D = (X1 + Y1)^2
642  curve448Add(state->d, p->x, p->y);
643  curve448Sqr(state->d, state->d);
644  //Compute X3 = G * (D - F)
645  curve448Sub(state->d, state->d, state->f);
646  curve448Mul(r->x, state->d, state->g);
647  //Compute Y3 = F * (A - B)
648  curve448Sub(state->a, state->a, state->b);
649  curve448Mul(r->y, state->a, state->f);
650  //Compute Z3 = F * G
651  curve448Mul(r->z, state->f, state->g);
652 }
653 
654 
655 /**
656  * @brief Point encoding
657  * @param[in] p Point representation
658  * @param[out] data Octet string resulting from the conversion
659  **/
660 
661 void ed448Encode(Ed448Point *p, uint8_t *data)
662 {
663  //Retrieve affine representation
664  curve448Inv(p->z, p->z);
665  curve448Mul(p->x, p->x, p->z);
666  curve448Mul(p->y, p->y, p->z);
667  curve448SetInt(p->z, 1);
668 
669  //Encode the y-coordinate as a little-endian string of 57 octets. The final
670  //octet is always zero
671  curve448Export(p->y, data);
672  data[56] = 0;
673 
674  //Copy the least significant bit of the x-coordinate to the most significant
675  //bit of the final octet
676  data[56] |= (p->x[0] & 1) << 7;
677 }
678 
679 
680 /**
681  * @brief Point decoding
682  * @param[in] p Point representation
683  * @param[out] data Octet string to be converted
684  **/
685 
686 uint32_t ed448Decode(Ed448Point *p, const uint8_t *data)
687 {
688  uint_t i;
689  uint8_t x0;
690  uint32_t ret;
691  uint64_t temp;
692  uint32_t u[14];
693  uint32_t v[14];
694 
695  //First, interpret the string as an integer in little-endian representation.
696  //Bit 455 of this number is the least significant bit of the x-coordinate
697  //and denote this value x_0
698  x0 = data[56] >> 7;
699 
700  //The y-coordinate is recovered simply by clearing this bit
701  curve448Import(p->y, data);
702 
703  //Compute u = y + 2^224 + 1
704  for(temp = 1, i = 0; i < 7; i++)
705  {
706  temp += p->y[i];
707  u[i] = temp & 0xFFFFFFFF;
708  temp >>= 32;
709  }
710 
711  for(temp += 1, i = 7; i < 14; i++)
712  {
713  temp += p->y[i];
714  u[i] = temp & 0xFFFFFFFF;
715  temp >>= 32;
716  }
717 
718  temp += data[56] & 0x7F;
719  ret = temp & 0xFFFFFFFF;
720 
721  //If the y-coordinate is >= p, decoding fails
722  ret = (ret | (~ret + 1)) >> 31;
723 
724  //The curve equation implies x^2 = (y^2 - 1) / (d * y^2 - 1) mod p
725  //Let u = y^2 - 1 and v = d * y^2 - 1
726  curve448Sqr(v, p->y);
727  curve448SubInt(u, v, 1);
728  curve448Mul(v, v, ED448_D);
729  curve448SubInt(v, v, 1);
730 
731  //Compute u = sqrt(u / v)
732  ret |= curve448Sqrt(u, u, v);
733 
734  //If x = 0, and x_0 = 1, decoding fails
735  ret |= (curve448Comp(u, ED448_ZERO) ^ 1) & x0;
736 
737  //Compute v = p - u
738  curve448Sub(v, ED448_ZERO, u);
739 
740  //Finally, use the x_0 bit to select the right square root
741  curve448Select(p->x, u, v, (x0 ^ u[0]) & 1);
742 
743  //Initialize z-coordinate (projective representation)
744  curve448SetInt(p->z, 1);
745 
746  //Return 0 if the point has been successfully decoded, else 1
747  return ret;
748 }
749 
750 
751 /**
752  * @brief Reduce an integer modulo L
753  *
754  * This function implements Barrett reduction with b = 2^24 and k = 19. The
755  * algorithm requires the precomputation of the quantity mu = b^(2 * k) / L
756  *
757  * @param[out] r Resulting integer R = A mod L
758  * @param[in] a An integer such as 0 <= A < b^(2 * k)
759  **/
760 
761 void ed448RedInt(uint8_t *r, const uint8_t *a)
762 {
763  uint8_t c;
764  uint8_t u[60];
765  uint8_t v[60];
766 
767  //Compute the estimate of the quotient u = ((a / b^(k - 1)) * mu) / b^(k + 1)
768  ed448MulInt(NULL, u, a + 54, ED448_MU, 60);
769  //Compute v = u * L mod b^(k + 1)
770  ed448MulInt(v, NULL, u, ED448_L, 60);
771 
772  //Compute the estimate of the remainder u = a mod b^(k + 1) - v
773  //If u < 0, then u = u + b^(k + 1)
774  ed448SubInt(u, a, v, 60);
775 
776  //This estimation implies that at most two subtractions of L are required to
777  //obtain the correct remainder r
778  c = ed448SubInt(v, u, ED448_L, 60);
779  ed448SelectInt(u, v, u, c, 60);
780  c = ed448SubInt(v, u, ED448_L, 60);
781  ed448SelectInt(u, v, u, c, 60);
782 
783  //Copy the resulting remainder
784  ed448CopyInt(r, u, 57);
785 }
786 
787 
788 /**
789  * @brief Addition of two integers
790  * @param[out] r Resulting integer R = A + B
791  * @param[in] a An integer such as 0 <= A < (2^8)^n
792  * @param[in] b An integer such as 0 <= B < (2^8)^n
793  * @param[in] n Size of the operands, in bytes
794  **/
795 
796 void ed448AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
797 {
798  uint_t i;
799  uint16_t temp;
800 
801  //Compute R = A + B
802  for(temp = 0, i = 0; i < n; i++)
803  {
804  temp += a[i];
805  temp += b[i];
806  r[i] = temp & 0xFF;
807  temp >>= 8;
808  }
809 }
810 
811 
812 /**
813  * @brief Subtraction of two integers
814  * @param[out] r Resulting integer R = A - B
815  * @param[in] a An integer such as 0 <= A < (2^8)^n
816  * @param[in] b An integer such as 0 <= B < (2^8)^n
817  * @param[in] n Size of the operands, in bytes
818  * @return 1 if the result is negative, else 0
819  **/
820 
821 uint8_t ed448SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
822 {
823  uint_t i;
824  int16_t temp;
825 
826  //Compute R = A - B
827  for(temp = 0, i = 0; i < n; i++)
828  {
829  temp += a[i];
830  temp -= b[i];
831  r[i] = temp & 0xFF;
832  temp >>= 8;
833  }
834 
835  //Return 1 if the result of the subtraction is negative
836  return temp & 1;
837 }
838 
839 
840 /**
841  * @brief Multiplication of two integers
842  * @param[out] rl Low part of the result R = (A + B) mod (2^8)^n
843  * @param[out] rh High part of the result R = (A + B) / (2^8)^n
844  * @param[in] a An integer such as 0 <= A < (2^8)^n
845  * @param[in] b An integer such as 0 <= B < (2^8)^n
846  * @param[in] n Size of the operands, in bytes
847  **/
848 
849 void ed448MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a,
850  const uint8_t *b, uint_t n)
851 {
852  uint_t i;
853  uint_t j;
854  uint32_t c;
855  uint32_t d;
856  uint64_t temp;
857 
858  //Perform multiplication in base b = 2^24
859  n /= 3;
860 
861  //Compute the low part of the multiplication
862  for(temp = 0, i = 0; i < n; i++)
863  {
864  //The Comba's algorithm computes the products, column by column
865  for(j = 0; j <= i; j++)
866  {
867  c = LOAD24LE(a + 3 * j);
868  d = LOAD24LE(b + 3 * (i - j));
869  temp += (uint64_t) c * d;
870  }
871 
872  //At the bottom of each column, the final result is written to memory
873  if(rl != NULL)
874  {
875  STORE24LE(temp & 0xFFFFFF, rl + 3 * i);
876  }
877 
878  //Propagate the carry upwards
879  temp >>= 24;
880  }
881 
882  //Check whether the high part of the multiplication should be calculated
883  if(rh != NULL)
884  {
885  //Compute the high part of the multiplication
886  for(i = n; i < (2 * n); i++)
887  {
888  //The Comba's algorithm computes the products, column by column
889  for(j = i + 1 - n; j < n; j++)
890  {
891  c = LOAD24LE(a + 3 * j);
892  d = LOAD24LE(b + 3 * (i - j));
893  temp += (uint64_t) c * d;
894  }
895 
896  //At the bottom of each column, the final result is written to memory
897  STORE24LE(temp & 0xFFFFFF, rh + 3 * (i - n));
898 
899  //Propagate the carry upwards
900  temp >>= 24;
901  }
902  }
903 }
904 
905 
906 /**
907  * @brief Copy an integer
908  * @param[out] a Pointer to the destination integer
909  * @param[in] b Pointer to the source integer
910  * @param[in] n Size of the integers, in bytes
911  **/
912 
913 void ed448CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
914 {
915  uint_t i;
916 
917  //Copy the value of the integer
918  for(i = 0; i < n; i++)
919  {
920  a[i] = b[i];
921  }
922 }
923 
924 
925 /**
926  * @brief Select an integer
927  * @param[out] r Pointer to the destination integer
928  * @param[in] a Pointer to the first source integer
929  * @param[in] b Pointer to the second source integer
930  * @param[in] c Condition variable
931  * @param[in] n Size of the integers, in bytes
932  **/
933 
934 void ed448SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b,
935  uint8_t c, uint_t n)
936 {
937  uint_t i;
938  uint8_t mask;
939 
940  //The mask is the all-1 or all-0 word
941  mask = c - 1;
942 
943  //Select between A and B
944  for(i = 0; i < n; i++)
945  {
946  //Constant time implementation
947  r[i] = (a[i] & mask) | (b[i] & ~mask);
948  }
949 }
950 
951 
952 /**
953  * @brief Compare integers
954  * @param[in] a Pointer to the first integer
955  * @param[in] b Pointer to the second integer
956  * @param[in] n Size of the integers, in bytes
957  * @return The function returns 0 if the A = B, else 1
958  **/
959 
960 uint8_t ed448CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
961 {
962  uint_t i;
963  uint8_t mask;
964 
965  //Initialize mask
966  mask = 0;
967 
968  //Compare A and B
969  for(i = 0; i < n; i++)
970  {
971  //Constant time implementation
972  mask |= a[i] ^ b[i];
973  }
974 
975  //Return 0 if A = B, else 1
976  return ((uint8_t) (mask | (~mask + 1))) >> 7;
977 }
978 
979 #endif
error_t ed448GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey)
EdDSA private key generation.
Definition: ed448.c:131
Curve448 elliptic curve (constant-time implementation)
uint8_t b
Definition: nbns_common.h:104
void ed448CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
Copy an integer.
Definition: ed448.c:913
void ed448Mul(Ed448State *state, Ed448Point *r, const uint8_t *k, const Ed448Point *p)
Scalar multiplication on Ed448 curve.
Definition: ed448.c:542
uint8_t a
Definition: ndp.h:411
signed int int_t
Definition: compiler_port.h:49
void ed448AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
Addition of two integers.
Definition: ed448.c:796
void curve448Select(uint32_t *r, const uint32_t *a, const uint32_t *b, uint32_t c)
Select an integer.
Definition: curve448.c:574
uint32_t f[14]
Definition: ed448.h:91
#define PrngAlgo
Definition: crypto.h:938
#define CURVE448_BIT_LEN
Definition: curve448.h:38
uint8_t p
Definition: ndp.h:300
void curve448Export(uint32_t *a, uint8_t *data)
Export an octet string.
Definition: curve448.c:646
uint8_t message[]
Definition: chap.h:154
#define ED448_PUBLIC_KEY_LEN
Definition: ed448.h:42
uint8_t data[]
Definition: ethernet.h:222
void curve448Copy(uint32_t *a, const uint32_t *b)
Copy an integer.
Definition: curve448.c:527
const void * buffer
Definition: crypto.h:982
uint32_t e[14]
Definition: ed448.h:90
error_t ed448VerifySignature(const uint8_t *publicKey, const void *message, size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed448.c:404
#define ED448_SIGNATURE_LEN
Definition: ed448.h:44
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
void curve448SubInt(uint32_t *r, const uint32_t *a, uint32_t b)
Modular subtraction.
Definition: curve448.c:160
Ed448Point ka
Definition: ed448.h:81
uint8_t r
Definition: ndp.h:346
Ed448Point sb
Definition: ed448.h:83
void ed448RedInt(uint8_t *r, const uint8_t *a)
Reduce an integer modulo L.
Definition: ed448.c:761
#define STORE24LE(a, p)
Definition: cpu_endian.h:267
error_t ed448GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed448.c:258
void ed448Encode(Ed448Point *p, uint8_t *data)
Point encoding.
Definition: ed448.c:661
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
void curve448Import(uint32_t *a, const uint8_t *data)
Import an octet string.
Definition: curve448.c:625
uint32_t ed448Decode(Ed448Point *p, const uint8_t *data)
Point decoding.
Definition: ed448.c:686
uint32_t a[14]
Definition: ed448.h:86
void ed448MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a, const uint8_t *b, uint_t n)
Multiplication of two integers.
Definition: ed448.c:849
void curve448Inv(uint32_t *r, const uint32_t *a)
Modular multiplicative inverse.
Definition: curve448.c:402
uint32_t z[14]
Definition: ed448.h:65
void ed448SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint8_t c, uint_t n)
Select an integer.
Definition: ed448.c:934
error_t shakeInit(ShakeContext *context, uint_t strength)
Initialize SHAKE context.
Definition: shake.c:121
void curve448Sqr(uint32_t *r, const uint32_t *a)
Modular squaring.
Definition: curve448.c:331
error_t ed448VerifySignatureEx(const uint8_t *publicKey, const DataChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed448.c:438
void shakeAbsorb(ShakeContext *context, const void *input, size_t length)
Absorb data.
Definition: shake.c:149
Ed448Point rb
Definition: ed448.h:82
General definitions for cryptographic algorithms.
void shakeSqueeze(ShakeContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
Definition: shake.c:175
uint8_t t[57]
Definition: ed448.h:80
uint8_t mask
Definition: web_socket.h:319
error_t ed448GeneratePublicKey(const uint8_t *privateKey, uint8_t *publicKey)
Derive the public key from an EdDSA private key.
Definition: ed448.c:155
uint8_t s[57]
Definition: ed448.h:79
uint8_t u
Definition: lldp_ext_med.h:213
void curve448SetInt(uint32_t *a, uint32_t b)
Set integer value.
Definition: curve448.c:50
uint32_t d[14]
Definition: ed448.h:89
Ed448Point u
Definition: ed448.h:84
uint8_t ed448CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
Compare integers.
Definition: ed448.c:960
Ed448Point v
Definition: ed448.h:85
uint32_t x[14]
Definition: ed448.h:63
Data chunk descriptor.
Definition: crypto.h:981
#define ED448_PRIVATE_KEY_LEN
Definition: ed448.h:40
uint8_t ed448SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
Subtraction of two integers.
Definition: ed448.c:821
uint32_t y[14]
Definition: ed448.h:64
uint32_t curve448Sqrt(uint32_t *r, const uint32_t *a, const uint32_t *b)
Compute the square root of (A / B) modulo p.
Definition: curve448.c:451
error_t ed448GenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey, uint8_t *publicKey)
EdDSA key pair generation.
Definition: ed448.c:103
Projective point representation.
Definition: ed448.h:62
uint8_t n
#define cryptoFreeMem(p)
Definition: crypto.h:791
uint32_t b[14]
Definition: ed448.h:87
void curve448Add(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular addition.
Definition: curve448.c:72
void ed448Double(Ed448State *state, Ed448Point *r, const Ed448Point *p)
Point doubling.
Definition: ed448.c:628
#define cryptoAllocMem(size)
Definition: crypto.h:786
uint8_t s
Definition: igmp_common.h:234
size_t length
Definition: crypto.h:983
uint8_t r[57]
Definition: ed448.h:78
ShakeContext shakeContext
Definition: ed448.h:75
uint32_t g[14]
Definition: ed448.h:92
void curve448Sub(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular subtraction.
Definition: curve448.c:123
void shakeFinal(ShakeContext *context)
Finish absorbing phase.
Definition: shake.c:161
void ed448Add(Ed448State *state, Ed448Point *r, const Ed448Point *p, const Ed448Point *q)
Point addition.
Definition: ed448.c:585
uint8_t p[57]
Definition: ed448.h:77
unsigned int uint_t
Definition: compiler_port.h:50
Elliptic curves.
#define osMemset(p, value, length)
Definition: os_port.h:135
#define LOAD24LE(p)
Definition: cpu_endian.h:191
@ ERROR_INVALID_SIGNATURE
Definition: error.h:227
Ed448 elliptic curve (constant-time implementation)
error_t ed448GenerateSignature(const uint8_t *privateKey, const uint8_t *publicKey, const void *message, size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed448.c:223
Ed448 working state.
Definition: ed448.h:74
uint32_t c[14]
Definition: ed448.h:88
uint32_t curve448Comp(const uint32_t *a, const uint32_t *b)
Compare integers.
Definition: curve448.c:599
__weak_func void curve448Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular multiplication.
Definition: curve448.c:199
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
uint8_t k[114]
Definition: ed448.h:76