ed448.c
Go to the documentation of this file.
1 /**
2  * @file ed448.c
3  * @brief Ed448 elliptic curve
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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.6.6
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.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  0x070CC05E, 0x026A82BC, 0x00938E26, 0x080E18B0, 0x0511433B, 0x0F72AB66, 0x0412AE1A, 0x0A3D3A46,
49  0x0A6DE324, 0x00F1767E, 0x04657047, 0x036DA9E1, 0x05A622BF, 0x0ED221D1, 0x066BED0D, 0x04F1970C
50  },
51  {
52  0x0230FA14, 0x008795BF, 0x07C8AD98, 0x0132C4ED, 0x09C4FDBD, 0x01CE67C3, 0x073AD3FF, 0x005A0C2D,
53  0x07789C1E, 0x0A398408, 0x0A73736C, 0x0C7624BE, 0x003756C9, 0x02488762, 0x016EB6BC, 0x0693F467
54  },
55  {
56  0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
58  }
59 };
60 
61 //Zero (constant)
62 static const int32_t ED448_ZERO[16] =
63 {
64  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
65  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
66 };
67 
68 //Curve parameter d
69 static const int32_t ED448_D[16] =
70 {
71  0x0FFF6756, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF,
72  0x0FFFFFFE, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF, 0x0FFFFFFF
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->generate(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)
160 #else
162 #endif
163 
164  //Check parameters
165  if(privateKey == NULL || publicKey == NULL)
167 
168 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
169  //Allocate working state
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->subState, &state->a, s, &ED448_B);
194  //The public key A is the encoding of the point s * B
195  ed448Encode(&state->a, publicKey);
196 
197  //Erase working state
198  osMemset(state, 0, sizeof(Ed448GeneratePublicKeyState));
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 Check whether the EdDSA public key is valid
212  * @param[in] publicKey EdDSA public key (57 bytes)
213  * @return The function returns TRUE if the EdDSA public key is valid, else
214  * FALSE
215  **/
216 
217 bool_t ed448CheckPublicKey(const uint8_t *publicKey)
218 {
219  uint32_t ret;
220  Ed448Point p;
221 
222  //Decode the public key
223  ret = ed448Decode(&p, publicKey);
224 
225  //Return TRUE if the public key is valid
226  return (ret == 0) ? TRUE : FALSE;
227 }
228 
229 
230 /**
231  * @brief EdDSA signature generation
232  * @param[in] privateKey Signer's EdDSA private key (57 bytes)
233  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
234  * @param[in] message Pointer to the message to be signed
235  * @param[in] messageLen Length of the message, in bytes
236  * @param[in] context Constant string specified by the protocol using it
237  * @param[in] contextLen Length of the context, in bytes
238  * @param[in] flag Prehash flag for Ed448ph scheme (ED448_PH_FLAG)
239  * @param[out] signature EdDSA signature (114 bytes)
240  * @return Error code
241  **/
242 
243 error_t ed448GenerateSignature(const uint8_t *privateKey,
244  const uint8_t *publicKey, const void *message, size_t messageLen,
245  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
246 {
247  error_t error;
248  DataFrag messageFrags[1];
249 
250  //The message fits in a single fragment
251  messageFrags[0].buffer = message;
252  messageFrags[0].length = messageLen;
253 
254  //Ed448 signature generation
255  error = ed448GenerateSignatureEx(privateKey, publicKey, messageFrags,
256  arraysize(messageFrags), context, contextLen, flag, signature);
257 
258  //Return status code
259  return error;
260 }
261 
262 
263 /**
264  * @brief EdDSA signature generation
265  * @param[in] privateKey Signer's EdDSA private key (57 bytes)
266  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
267  * @param[in] messageFrags Array of fragments representing the message to be
268  * signed
269  * @param[in] messageNumFrags Number of fragments representing the message
270  * @param[in] context Constant string specified by the protocol using it
271  * @param[in] contextLen Length of the context, in bytes
272  * @param[in] flag Prehash flag for Ed448ph scheme (ED448_PH_FLAG)
273  * @param[out] signature EdDSA signature (114 bytes)
274  * @return Error code
275  **/
276 
277 error_t ed448GenerateSignatureEx(const uint8_t *privateKey,
278  const uint8_t *publicKey, const DataFrag *messageFrags,
279  uint_t messageNumFrags, const void *context, uint8_t contextLen,
280  uint8_t flag, uint8_t *signature)
281 {
282  uint_t i;
283  uint8_t c;
284 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
286 #else
288 #endif
289 
290  //Check parameters
291  if(privateKey == NULL || messageFrags == NULL || signature == NULL)
293 
294  //The context is an optional constant string specified by the protocol using
295  //it (refer to RFC 8032, section 8.3)
296  if(context == NULL && contextLen != 0)
298 
299 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
300  //Allocate working state
302  //Failed to allocate memory?
303  if(state == NULL)
304  return ERROR_OUT_OF_MEMORY;
305 #endif
306 
307  //Hash the private key, 57 octets, using SHAKE256(x, 114). Let h denote
308  //the resulting digest
309  shakeInit(&state->shakeContext, 256);
310  shakeAbsorb(&state->shakeContext, privateKey, ED448_PRIVATE_KEY_LEN);
311  shakeFinal(&state->shakeContext);
312 
313  //Construct the secret scalar s from the first half of the digest
314  shakeSqueeze(&state->shakeContext, state->s, 57);
315 
316  //The two least significant bits of the first octet are cleared, all eight
317  //bits the last octet are cleared, and the highest bit of the second to
318  //last octet is set
319  state->s[0] &= 0xFC;
320  state->s[56] = 0x00;
321  state->s[55] |= 0x80;
322 
323  //The public key is optional
324  if(publicKey == NULL)
325  {
326  //Perform a fixed-base scalar multiplication s * B
327  ed448Mul(&state->subState, &state->a, state->s, &ED448_B);
328  //The public key A is the encoding of the point s * B
329  ed448Encode(&state->a, state->t);
330  //Point to the resulting public key
331  publicKey = state->t;
332  }
333 
334  //Let prefix denote the second half of the hash digest
335  shakeSqueeze(&state->shakeContext, state->p, 57);
336 
337  //Initialize SHAKE256 context
338  shakeInit(&state->shakeContext, 256);
339 
340  //Absorb dom4(F, C) || prefix
341  shakeAbsorb(&state->shakeContext, "SigEd448", 8);
342  shakeAbsorb(&state->shakeContext, &flag, sizeof(uint8_t));
343  shakeAbsorb(&state->shakeContext, &contextLen, sizeof(uint8_t));
344  shakeAbsorb(&state->shakeContext, context, contextLen);
345  shakeAbsorb(&state->shakeContext, state->p, 57);
346 
347  //The message is split over multiple chunks
348  for(i = 0; i < messageNumFrags; i++)
349  {
350  //Absorb current chunk
351  shakeAbsorb(&state->shakeContext, messageFrags[i].buffer,
352  messageFrags[i].length);
353  }
354 
355  //Compute SHAKE256(dom4(F, C) || prefix || PH(M), 114)
356  shakeFinal(&state->shakeContext);
357  shakeSqueeze(&state->shakeContext, state->k, 114);
358 
359  //Reduce the 114-octet digest as a little-endian integer r
360  ed448RedInt(state->r, state->k);
361  //Compute the point r * B
362  ed448Mul(&state->subState, &state->a, state->r, &ED448_B);
363  //Let the string R be the encoding of this point
364  ed448Encode(&state->a, signature);
365 
366  //Initialize SHAKE256 context
367  shakeInit(&state->shakeContext, 256);
368 
369  //Absorb dom4(F, C) || R || A
370  shakeAbsorb(&state->shakeContext, "SigEd448", 8);
371  shakeAbsorb(&state->shakeContext, &flag, sizeof(uint8_t));
372  shakeAbsorb(&state->shakeContext, &contextLen, sizeof(uint8_t));
373  shakeAbsorb(&state->shakeContext, context, contextLen);
374  shakeAbsorb(&state->shakeContext, signature, ED448_SIGNATURE_LEN / 2);
375  shakeAbsorb(&state->shakeContext, publicKey, ED448_PUBLIC_KEY_LEN);
376 
377  //The message is split over multiple chunks
378  for(i = 0; i < messageNumFrags; i++)
379  {
380  //Absorb current chunk
381  shakeAbsorb(&state->shakeContext, messageFrags[i].buffer,
382  messageFrags[i].length);
383  }
384 
385  //Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114) and interpret the
386  //114-octet digest as a little-endian integer k
387  shakeFinal(&state->shakeContext);
388  shakeSqueeze(&state->shakeContext, state->k, 114);
389 
390  //Compute S = (r + k * s) mod L. For efficiency, reduce k modulo L first
391  ed448RedInt(state->p, state->k);
392  ed448MulInt(state->k, state->k + 57, state->p, state->s, 57);
393  ed448RedInt(state->p, state->k);
394  ed448AddInt(state->s, state->p, state->r, 57);
395 
396  //Perform modular reduction
397  c = ed448SubInt(state->p, state->s, ED448_L, 57);
398  ed448SelectInt(signature + 57, state->p, state->s, c, 57);
399 
400  //Erase working state
401  osMemset(state, 0, sizeof(Ed448GenerateSignatureState));
402 
403 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
404  //Release working state
405  cryptoFreeMem(state);
406 #endif
407 
408  //Successful processing
409  return NO_ERROR;
410 }
411 
412 
413 /**
414  * @brief EdDSA signature verification
415  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
416  * @param[in] message Message whose signature is to be verified
417  * @param[in] messageLen Length of the message, in bytes
418  * @param[in] context Constant string specified by the protocol using it
419  * @param[in] contextLen Length of the context, in bytes
420  * @param[in] flag Prehash flag for Ed448ph scheme (ED448_PH_FLAG)
421  * @param[in] signature EdDSA signature (114 bytes)
422  * @return Error code
423  **/
424 
425 error_t ed448VerifySignature(const uint8_t *publicKey, const void *message,
426  size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag,
427  const uint8_t *signature)
428 {
429  error_t error;
430  DataFrag messageFrags[1];
431 
432  //The message fits in a single fragment
433  messageFrags[0].buffer = message;
434  messageFrags[0].length = messageLen;
435 
436  //Ed448 signature verification
437  error = ed448VerifySignatureEx(publicKey, messageFrags,
438  arraysize(messageFrags), context, contextLen, flag, signature);
439 
440  //Return status code
441  return error;
442 }
443 
444 
445 /**
446  * @brief EdDSA signature verification
447  * @param[in] publicKey Signer's EdDSA public key (57 bytes)
448  * @param[in] message Array of fragments representing the message whose
449  * signature is to be verified
450  * @param[in] messageLen Number of fragments representing the message
451  * @param[in] context Constant string specified by the protocol using it
452  * @param[in] contextLen Length of the context, in bytes
453  * @param[in] flag Prehash flag for Ed448ph scheme (ED448_PH_FLAG)
454  * @param[in] signature EdDSA signature (114 bytes)
455  * @return Error code
456  **/
457 
458 error_t ed448VerifySignatureEx(const uint8_t *publicKey,
459  const DataFrag *messageFrags, uint_t messageNumFrags, const void *context,
460  uint8_t contextLen, uint8_t flag, const uint8_t *signature)
461 {
462  uint_t i;
463  uint32_t ret;
464 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
466 #else
467  Ed448VerifySignatureState state[1];
468 #endif
469 
470  //Check parameters
471  if(publicKey == NULL || messageFrags == NULL || signature == NULL)
473 
474  //The context is an optional constant string specified by the protocol using
475  //it (refer to RFC 8032, section 8.3)
476  if(context == NULL && contextLen != 0)
478 
479 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
480  //Allocate working state
481  state = cryptoAllocMem(sizeof(Ed448VerifySignatureState));
482  //Failed to allocate memory?
483  if(state == NULL)
484  return ERROR_OUT_OF_MEMORY;
485 #endif
486 
487  //First split the signature into two 32-octet halves. Decode the first
488  //half as a point R
489  osMemcpy(state->r, signature, ED448_SIGNATURE_LEN / 2);
490 
491  //Decode the second half as an integer S, in the range 0 <= s < L
492  osMemcpy(state->s, signature + ED448_SIGNATURE_LEN / 2,
493  ED448_SIGNATURE_LEN / 2);
494 
495  //Ed448 signatures are not malleable due to the verification check that
496  //decoded S is smaller than L (refer to RFC 8032, section 8.4)
497  ret = 1 ^ ed448SubInt(state->p, state->s, ED448_L, ED448_SIGNATURE_LEN / 2);
498 
499  //Decode the public key A as point A'
500  ret |= ed448Decode(&state->a, publicKey);
501 
502  //Initialize SHAKE256 context
503  shakeInit(&state->shakeContext, 256);
504 
505  //Absorb dom4(F, C) || R || A
506  shakeAbsorb(&state->shakeContext, "SigEd448", 8);
507  shakeAbsorb(&state->shakeContext, &flag, sizeof(uint8_t));
508  shakeAbsorb(&state->shakeContext, &contextLen, sizeof(uint8_t));
509  shakeAbsorb(&state->shakeContext, context, contextLen);
510  shakeAbsorb(&state->shakeContext, state->r, ED448_SIGNATURE_LEN / 2);
511  shakeAbsorb(&state->shakeContext, publicKey, ED448_PUBLIC_KEY_LEN);
512 
513  //The message is split over multiple chunks
514  for(i = 0; i < messageNumFrags; i++)
515  {
516  //Absorb current chunk
517  shakeAbsorb(&state->shakeContext, messageFrags[i].buffer,
518  messageFrags[i].length);
519  }
520 
521  //Compute SHAKE256(dom4(F, C) || R || A || PH(M), 114) and interpret the
522  //114-octet digest as a little-endian integer k
523  shakeFinal(&state->shakeContext);
524  shakeSqueeze(&state->shakeContext, state->k, 114);
525 
526  //For efficiency, reduce k modulo L first
527  ed448RedInt(state->k, state->k);
528 
529  //Compute -A'
530  curve448Sub(state->a.x, ED448_ZERO, state->a.x);
531 
532  //Compute the point P = s * B - k * A'
533  ed448TwinMul(&state->subState, &state->a, state->s, &ED448_B, state->k,
534  &state->a);
535 
536  //Encode of the resulting point P
537  ed448Encode(&state->a, state->p);
538 
539  //If P = R, then the signature is verified. If P does not equal R,
540  //then the message or the signature may have been modified
541  ret |= ed448CompInt(state->p, signature, ED448_SIGNATURE_LEN / 2);
542 
543  //Erase working state
544  osMemset(state, 0, sizeof(Ed448VerifySignatureState));
545 
546 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
547  //Release working state
548  cryptoFreeMem(state);
549 #endif
550 
551  //Return status code
552  return (ret == 0) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
553 }
554 
555 
556 /**
557  * @brief Scalar multiplication (regular calculation)
558  * @param[in] state Pointer to the working state
559  * @param[out] r Resulting point R = k * P
560  * @param[in] k Input scalar
561  * @param[in] p Input point
562  **/
563 
564 void ed448Mul(Ed448SubState *state, Ed448Point *r, const uint8_t *k,
565  const Ed448Point *p)
566 {
567  int_t i;
568  uint8_t b;
569 
570  //The neutral element is represented by (0, 1, 1)
571  curve448SetInt(state->u.x, 0);
572  curve448SetInt(state->u.y, 1);
573  curve448SetInt(state->u.z, 1);
574 
575  //Perform scalar multiplication
576  for(i = CURVE448_BIT_LEN - 1; i >= 0; i--)
577  {
578  //The scalar is processed in a left-to-right fashion
579  b = (k[i / 8] >> (i % 8)) & 1;
580 
581  //Compute U = 2 * U
582  ed448Double(state, &state->u, &state->u);
583  //Compute V = U + P
584  ed448Add(state, &state->v, &state->u, p);
585 
586  //If b is set, then U = V
587  curve448Select(state->u.x, state->u.x, state->v.x, b);
588  curve448Select(state->u.y, state->u.y, state->v.y, b);
589  curve448Select(state->u.z, state->u.z, state->v.z, b);
590  }
591 
592  //Copy result
593  curve448Copy(r->x, state->u.x);
594  curve448Copy(r->y, state->u.y);
595  curve448Copy(r->z, state->u.z);
596 }
597 
598 
599 /**
600  * @brief Twin multiplication
601  * @param[in] state Pointer to the working state
602  * @param[out] r Resulting point R = k1 * P + k2 * Q
603  * @param[in] k1 First input scalar
604  * @param[in] p First input point
605  * @param[in] k2 Second input scalar
606  * @param[in] q Second input point
607  **/
608 
609 void ed448TwinMul(Ed448SubState *state, Ed448Point *r, const uint8_t *k1,
610  const Ed448Point *p, const uint8_t *k2, const Ed448Point *q)
611 {
612  int_t i;
613  uint8_t b1;
614  uint8_t b2;
615 
616  //Pre-compute V = P + Q
617  ed448Add(state, &state->v, p, q);
618 
619  //The neutral element is represented by (0, 1, 1)
620  curve448SetInt(state->u.x, 0);
621  curve448SetInt(state->u.y, 1);
622  curve448SetInt(state->u.z, 1);
623 
624  //Calculate both multiplications at the same time
625  for(i = CURVE448_BIT_LEN - 1; i >= 0; i--)
626  {
627  //The scalars are processed in a left-to-right fashion
628  b1 = (k1[i / 8] >> (i % 8)) & 1;
629  b2 = (k2[i / 8] >> (i % 8)) & 1;
630 
631  //Compute U = 2 * U
632  ed448Double(state, &state->u, &state->u);
633 
634  //Check k1(i) and k2(i)
635  if(b1 == 1 && b2 == 0)
636  {
637  //Compute U = U + P
638  ed448Add(state, &state->u, &state->u, p);
639  }
640  else if(b1 == 0 && b2 == 1)
641  {
642  //Compute U = U + Q
643  ed448Add(state, &state->u, &state->u, q);
644  }
645  else if(b1 == 1 && b2 == 1)
646  {
647  //Compute U = U + V
648  ed448Add(state, &state->u, &state->u, &state->v);
649  }
650  else
651  {
652  }
653  }
654 
655  //Copy result
656  curve448Copy(r->x, state->u.x);
657  curve448Copy(r->y, state->u.y);
658  curve448Copy(r->z, state->u.z);
659 }
660 
661 
662 /**
663  * @brief Point addition
664  * @param[in] state Pointer to the working state
665  * @param[out] r Resulting point R = P + Q
666  * @param[in] p First operand
667  * @param[in] q Second operand
668  **/
669 
671  const Ed448Point *q)
672 {
673  //Compute A = X1 * X2
674  curve448Mul(state->a, p->x, q->x);
675  //Compute B = Y1 * Y2
676  curve448Mul(state->b, p->y, q->y);
677  //Compute C = Z1 * Z2
678  curve448Mul(state->c, p->z, q->z);
679  //Compute D = C^2
680  curve448Sqr(state->d, state->c);
681 
682  //Compute E = d * A * B
683  curve448Mul(state->e, state->a, state->b);
684  curve448Mul(state->e, state->e, ED448_D);
685 
686  //Compute F = D + E
687  curve448Add(state->f, state->d, state->e);
688  //Compute G = D - E
689  curve448Sub(state->g, state->d, state->e);
690 
691  //Compute D = (X1 + Y1) * (X2 + Y2)
692  curve448Add(state->d, p->x, p->y);
693  curve448Add(state->e, q->x, q->y);
694  curve448Mul(state->d, state->d, state->e);
695 
696  //Compute X3 = C * G * (D - A - B)
697  curve448Sub(state->d, state->d, state->a);
698  curve448Sub(state->d, state->d, state->b);
699  curve448Mul(state->d, state->d, state->c);
700  curve448Mul(r->x, state->d, state->g);
701 
702  //Compute Y3 = C * F * (B - A)
703  curve448Sub(state->b, state->b, state->a);
704  curve448Mul(state->b, state->b, state->c);
705  curve448Mul(r->y, state->b, state->f);
706 
707  //Compute Z3 = F * G
708  curve448Mul(r->z, state->f, state->g);
709 }
710 
711 
712 /**
713  * @brief Point doubling
714  * @param[in] state Pointer to the working state
715  * @param[out] r Resulting point R = 2 * P
716  * @param[in] p Input point P
717  **/
718 
720 {
721  //Compute A = X1 * X2
722  curve448Mul(state->a, p->x, p->x);
723  //Compute B = Y1 * Y2
724  curve448Mul(state->b, p->y, p->y);
725  //Compute C = Z1 * Z2
726  curve448Mul(state->c, p->z, p->z);
727  //Compute F = A + B
728  curve448Add(state->f, state->a, state->b);
729 
730  //Compute G = F - 2 * C
731  curve448Add(state->c, state->c, state->c);
732  curve448Sub(state->g, state->f, state->c);
733 
734  //Compute D = (X1 + Y1)^2
735  curve448Add(state->d, p->x, p->y);
736  curve448Sqr(state->d, state->d);
737 
738  //Compute X3 = G * (D - F)
739  curve448Sub(state->d, state->d, state->f);
740  curve448Mul(r->x, state->d, state->g);
741 
742  //Compute Y3 = F * (A - B)
743  curve448Sub(state->a, state->a, state->b);
744  curve448Mul(r->y, state->a, state->f);
745 
746  //Compute Z3 = F * G
747  curve448Mul(r->z, state->f, state->g);
748 }
749 
750 
751 /**
752  * @brief Point encoding
753  * @param[in] p Point representation
754  * @param[out] data Octet string resulting from the conversion
755  **/
756 
757 void ed448Encode(Ed448Point *p, uint8_t *data)
758 {
759  //Retrieve affine representation
760  curve448Inv(p->z, p->z);
761  curve448Mul(p->x, p->x, p->z);
762  curve448Mul(p->y, p->y, p->z);
763  curve448SetInt(p->z, 1);
764 
765  //Reduce non-canonical values
766  curve448Canonicalize(p->x, p->x);
767  curve448Canonicalize(p->y, p->y);
768 
769  //Encode the y-coordinate as a little-endian string of 57 octets. The final
770  //octet is always zero
771  curve448Export(p->y, data);
772  data[56] = 0;
773 
774  //Copy the least significant bit of the x-coordinate to the most significant
775  //bit of the final octet
776  data[56] |= (p->x[0] & 1) << 7;
777 }
778 
779 
780 /**
781  * @brief Point decoding
782  * @param[out] p Point representation
783  * @param[in] data Octet string to be converted
784  * @return The function returns 0 if the point has been successfully decoded,
785  * else 1
786  **/
787 
788 uint32_t ed448Decode(Ed448Point *p, const uint8_t *data)
789 {
790  uint_t i;
791  uint8_t x0;
792  uint32_t ret;
793  int32_t temp;
794  int32_t u[16];
795  int32_t v[16];
796 
797  //First, interpret the string as an integer in little-endian representation.
798  //Bit 455 of this number is the least significant bit of the x-coordinate
799  //and denote this value x_0
800  x0 = data[56] >> 7;
801 
802  //The y-coordinate is recovered simply by clearing this bit
803  curve448Import(p->y, data);
804 
805  //Compute u = y + 2^224 + 1
806  for(temp = 1, i = 0; i < 8; i++)
807  {
808  temp += p->y[i];
809  u[i] = temp & 0x0FFFFFFF;
810  temp >>= 28;
811  }
812 
813  for(temp += 1, i = 8; i < 16; i++)
814  {
815  temp += p->y[i];
816  u[i] = temp & 0x0FFFFFFF;
817  temp >>= 28;
818  }
819 
820  temp += data[56] & 0x7F;
821 
822  //If the y-coordinate is >= p, decoding fails
823  ret = CRYPTO_TEST_NZ_32(temp);
824 
825  //The curve equation implies x^2 = (y^2 - 1) / (d * y^2 - 1) mod p
826  //Let u = y^2 - 1 and v = d * y^2 - 1
827  curve448Sqr(v, p->y);
828  curve448SubInt(u, v, 1);
829  curve448Mul(v, v, ED448_D);
830  curve448SubInt(v, v, 1);
831 
832  //Compute u = sqrt(u / v)
833  ret |= curve448Sqrt(u, u, v);
834 
835  //If x = 0, and x_0 = 1, decoding fails
836  ret |= (curve448Comp(u, ED448_ZERO) ^ 1) & x0;
837 
838  //Compute v = p - u
839  curve448Sub(v, ED448_ZERO, u);
840 
841  //Finally, use the x_0 bit to select the right square root
842  curve448Select(p->x, u, v, (x0 ^ u[0]) & 1);
843 
844  //Initialize z-coordinate (projective representation)
845  curve448SetInt(p->z, 1);
846 
847  //Return 0 if the point has been successfully decoded, else 1
848  return ret;
849 }
850 
851 
852 /**
853  * @brief Reduce an integer modulo L
854  *
855  * This function implements Barrett reduction with b = 2^24 and k = 19. The
856  * algorithm requires the precomputation of the quantity mu = b^(2 * k) / L
857  *
858  * @param[out] r Resulting integer R = A mod L
859  * @param[in] a An integer such as 0 <= A < b^(2 * k)
860  **/
861 
862 void ed448RedInt(uint8_t *r, const uint8_t *a)
863 {
864  uint8_t c;
865  uint8_t u[60];
866  uint8_t v[60];
867 
868  //Compute the estimate of the quotient u = ((a / b^(k - 1)) * mu) / b^(k + 1)
869  ed448MulInt(NULL, u, a + 54, ED448_MU, 60);
870  //Compute v = u * L mod b^(k + 1)
871  ed448MulInt(v, NULL, u, ED448_L, 60);
872 
873  //Compute the estimate of the remainder u = a mod b^(k + 1) - v
874  //If u < 0, then u = u + b^(k + 1)
875  ed448SubInt(u, a, v, 60);
876 
877  //This estimation implies that at most two subtractions of L are required to
878  //obtain the correct remainder r
879  c = ed448SubInt(v, u, ED448_L, 60);
880  ed448SelectInt(u, v, u, c, 60);
881  c = ed448SubInt(v, u, ED448_L, 60);
882  ed448SelectInt(u, v, u, c, 60);
883 
884  //Copy the resulting remainder
885  ed448CopyInt(r, u, 57);
886 }
887 
888 
889 /**
890  * @brief Addition of two integers
891  * @param[out] r Resulting integer R = A + B
892  * @param[in] a An integer such as 0 <= A < (2^8)^n
893  * @param[in] b An integer such as 0 <= B < (2^8)^n
894  * @param[in] n Size of the operands, in bytes
895  **/
896 
897 void ed448AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
898 {
899  uint_t i;
900  uint16_t temp;
901 
902  //Compute R = A + B
903  for(temp = 0, i = 0; i < n; i++)
904  {
905  temp += a[i];
906  temp += b[i];
907  r[i] = temp & 0xFF;
908  temp >>= 8;
909  }
910 }
911 
912 
913 /**
914  * @brief Subtraction of two integers
915  * @param[out] r Resulting integer R = A - B
916  * @param[in] a An integer such as 0 <= A < (2^8)^n
917  * @param[in] b An integer such as 0 <= B < (2^8)^n
918  * @param[in] n Size of the operands, in bytes
919  * @return 1 if the result is negative, else 0
920  **/
921 
922 uint8_t ed448SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
923 {
924  uint_t i;
925  int16_t temp;
926 
927  //Compute R = A - B
928  for(temp = 0, i = 0; i < n; i++)
929  {
930  temp += a[i];
931  temp -= b[i];
932  r[i] = temp & 0xFF;
933  temp >>= 8;
934  }
935 
936  //Return 1 if the result of the subtraction is negative
937  return temp & 1;
938 }
939 
940 
941 /**
942  * @brief Multiplication of two integers
943  * @param[out] rl Low part of the result R = (A * B) mod (2^8)^n
944  * @param[out] rh High part of the result R = (A * B) / (2^8)^n
945  * @param[in] a An integer such as 0 <= A < (2^8)^n
946  * @param[in] b An integer such as 0 <= B < (2^8)^n
947  * @param[in] n Size of the operands, in bytes
948  **/
949 
950 void ed448MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a,
951  const uint8_t *b, uint_t n)
952 {
953  uint_t i;
954  uint_t j;
955  uint32_t c;
956  uint32_t d;
957  uint64_t temp;
958 
959  //Perform multiplication in base b = 2^24
960  n /= 3;
961 
962  //Compute the low part of the multiplication
963  for(temp = 0, i = 0; i < n; i++)
964  {
965  //The Comba's algorithm computes the products, column by column
966  for(j = 0; j <= i; j++)
967  {
968  c = LOAD24LE(a + 3 * j);
969  d = LOAD24LE(b + 3 * (i - j));
970  temp += (uint64_t) c * d;
971  }
972 
973  //At the bottom of each column, the final result is written to memory
974  if(rl != NULL)
975  {
976  STORE24LE(temp & 0xFFFFFF, rl + 3 * i);
977  }
978 
979  //Propagate the carry upwards
980  temp >>= 24;
981  }
982 
983  //Check whether the high part of the multiplication should be calculated
984  if(rh != NULL)
985  {
986  //Compute the high part of the multiplication
987  for(i = n; i < (2 * n); i++)
988  {
989  //The Comba's algorithm computes the products, column by column
990  for(j = i + 1 - n; j < n; j++)
991  {
992  c = LOAD24LE(a + 3 * j);
993  d = LOAD24LE(b + 3 * (i - j));
994  temp += (uint64_t) c * d;
995  }
996 
997  //At the bottom of each column, the final result is written to memory
998  STORE24LE(temp & 0xFFFFFF, rh + 3 * (i - n));
999 
1000  //Propagate the carry upwards
1001  temp >>= 24;
1002  }
1003  }
1004 }
1005 
1006 
1007 /**
1008  * @brief Copy an integer
1009  * @param[out] a Pointer to the destination integer
1010  * @param[in] b Pointer to the source integer
1011  * @param[in] n Size of the integers, in bytes
1012  **/
1013 
1014 void ed448CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
1015 {
1016  uint_t i;
1017 
1018  //Copy the value of the integer
1019  for(i = 0; i < n; i++)
1020  {
1021  a[i] = b[i];
1022  }
1023 }
1024 
1025 
1026 /**
1027  * @brief Select an integer
1028  * @param[out] r Pointer to the destination integer
1029  * @param[in] a Pointer to the first source integer
1030  * @param[in] b Pointer to the second source integer
1031  * @param[in] c Condition variable
1032  * @param[in] n Size of the integers, in bytes
1033  **/
1034 
1035 void ed448SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b,
1036  uint8_t c, uint_t n)
1037 {
1038  uint_t i;
1039  uint8_t mask;
1040 
1041  //The mask is the all-1 or all-0 word
1042  mask = c - 1;
1043 
1044  //Select between A and B
1045  for(i = 0; i < n; i++)
1046  {
1047  //Constant time implementation
1048  r[i] = (a[i] & mask) | (b[i] & ~mask);
1049  }
1050 }
1051 
1052 
1053 /**
1054  * @brief Compare integers
1055  * @param[in] a Pointer to the first integer
1056  * @param[in] b Pointer to the second integer
1057  * @param[in] n Size of the integers, in bytes
1058  * @return The function returns 0 if the A = B, else 1
1059  **/
1060 
1061 uint8_t ed448CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
1062 {
1063  uint_t i;
1064  uint8_t mask;
1065 
1066  //Initialize mask
1067  mask = 0;
1068 
1069  //Compare A and B
1070  for(i = 0; i < n; i++)
1071  {
1072  //Constant time implementation
1073  mask |= a[i] ^ b[i];
1074  }
1075 
1076  //Return 0 if A = B, else 1
1077  return ((uint8_t) (mask | (~mask + 1))) >> 7;
1078 }
1079 
1080 #endif
void curve448SubInt(int32_t *r, const int32_t *a, int32_t b)
Modular subtraction.
Definition: curve448.c:232
error_t ed448GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey)
EdDSA private key generation.
Definition: ed448.c:131
int32_t d[16]
Definition: ed448.h:80
int32_t a[16]
Definition: ed448.h:77
const void * buffer
Definition: crypto.h:1165
void ed448TwinMul(Ed448SubState *state, Ed448Point *r, const uint8_t *k1, const Ed448Point *p, const uint8_t *k2, const Ed448Point *q)
Twin multiplication.
Definition: ed448.c:609
Ed448SubState subState
Definition: ed448.h:112
int32_t e[16]
Definition: ed448.h:81
Curve448 elliptic curve.
int bool_t
Definition: compiler_port.h:63
uint8_t b
Definition: nbns_common.h:122
error_t ed448VerifySignatureEx(const uint8_t *publicKey, const DataFrag *messageFrags, uint_t messageNumFrags, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed448.c:458
void ed448CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
Copy an integer.
Definition: ed448.c:1014
uint32_t curve448Comp(const int32_t *a, const int32_t *b)
Compare integers.
Definition: curve448.c:792
uint8_t a
Definition: ndp.h:411
void curve448Select(int32_t *r, const int32_t *a, const int32_t *b, uint32_t c)
Select an integer.
Definition: curve448.c:767
signed int int_t
Definition: compiler_port.h:56
void ed448AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
Addition of two integers.
Definition: ed448.c:897
Working state (public key generation)
Definition: ed448.h:92
#define PrngAlgo
Definition: crypto.h:1140
#define CURVE448_BIT_LEN
Definition: curve448.h:38
void ed448Mul(Ed448SubState *state, Ed448Point *r, const uint8_t *k, const Ed448Point *p)
Scalar multiplication (regular calculation)
Definition: ed448.c:564
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
#define TRUE
Definition: os_port.h:50
#define ED448_PUBLIC_KEY_LEN
Definition: ed448.h:42
uint8_t data[]
Definition: ethernet.h:224
__weak_func void curve448Sqr(int32_t *r, const int32_t *a)
Modular squaring.
Definition: curve448.c:504
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:425
#define ED448_SIGNATURE_LEN
Definition: ed448.h:44
int32_t b[16]
Definition: ed448.h:78
int32_t g[16]
Definition: ed448.h:83
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
Working state (signature generation)
Definition: ed448.h:104
uint32_t curve448Sqrt(int32_t *r, const int32_t *a, const int32_t *b)
Compute the square root of (A / B) modulo p.
Definition: curve448.c:588
int32_t z[16]
Definition: ed448.h:65
Working state (scalar multiplication)
Definition: ed448.h:74
void curve448Inv(int32_t *r, const int32_t *a)
Modular multiplicative inverse.
Definition: curve448.c:539
uint8_t r
Definition: ndp.h:346
Ed448SubState subState
Definition: ed448.h:95
void ed448RedInt(uint8_t *r, const uint8_t *a)
Reduce an integer modulo L.
Definition: ed448.c:862
#define STORE24LE(a, p)
Definition: cpu_endian.h:267
int32_t c[16]
Definition: ed448.h:79
#define FALSE
Definition: os_port.h:46
void ed448Encode(Ed448Point *p, uint8_t *data)
Point encoding.
Definition: ed448.c:757
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
void ed448Double(Ed448SubState *state, Ed448Point *r, const Ed448Point *p)
Point doubling.
Definition: ed448.c:719
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
ShakeContext shakeContext
Definition: ed448.h:122
void curve448Canonicalize(int32_t *r, const int32_t *a)
Reduce non-canonical value.
Definition: curve448.c:669
error_t ed448GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataFrag *messageFrags, uint_t messageNumFrags, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed448.c:277
error_t
Error codes.
Definition: error.h:43
#define CRYPTO_TEST_NZ_32(a)
Definition: crypto.h:1103
uint32_t ed448Decode(Ed448Point *p, const uint8_t *data)
Point decoding.
Definition: ed448.c:788
uint8_t k[114]
Definition: ed448.h:123
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:950
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:1035
__weak_func void curve448Mul(int32_t *r, const int32_t *a, const int32_t *b)
Modular multiplication.
Definition: curve448.c:373
void curve448Copy(int32_t *a, const int32_t *b)
Copy an integer.
Definition: curve448.c:720
error_t shakeInit(ShakeContext *context, uint_t strength)
Initialize SHAKE context.
Definition: shake.c:187
Data fragment descriptor.
Definition: crypto.h:1164
void shakeAbsorb(ShakeContext *context, const void *input, size_t length)
Absorb data.
Definition: shake.c:241
General definitions for cryptographic algorithms.
void shakeSqueeze(ShakeContext *context, uint8_t *output, size_t length)
Extract data from the squeezing phase.
Definition: shake.c:267
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
int32_t y[16]
Definition: ed448.h:64
uint8_t u
Definition: lldp_ext_med.h:213
size_t length
Definition: crypto.h:1166
Ed448Point u
Definition: ed448.h:75
uint8_t ed448CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
Compare integers.
Definition: ed448.c:1061
void curve448Add(int32_t *r, const int32_t *a, const int32_t *b)
Modular addition.
Definition: curve448.c:72
bool_t ed448CheckPublicKey(const uint8_t *publicKey)
Check whether the EdDSA public key is valid.
Definition: ed448.c:217
ShakeContext shakeContext
Definition: ed448.h:105
#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:922
int32_t f[16]
Definition: ed448.h:82
Ed448SubState subState
Definition: ed448.h:128
Ed448Point v
Definition: ed448.h:76
error_t ed448GenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey, uint8_t *publicKey)
EdDSA key pair generation.
Definition: ed448.c:103
int32_t x[16]
Definition: ed448.h:63
Projective point representation.
Definition: ed448.h:62
uint8_t n
Working state (signature verification)
Definition: ed448.h:121
void curve448Export(int32_t *a, uint8_t *data)
Export an octet string.
Definition: curve448.c:846
#define cryptoFreeMem(p)
Definition: crypto.h:966
void curve448Sub(int32_t *r, const int32_t *a, const int32_t *b)
Modular subtraction.
Definition: curve448.c:165
#define cryptoAllocMem(size)
Definition: crypto.h:961
uint8_t s
Definition: igmp_common.h:234
void curve448SetInt(int32_t *a, int32_t b)
Set integer value.
Definition: curve448.c:50
void ed448Add(Ed448SubState *state, Ed448Point *r, const Ed448Point *p, const Ed448Point *q)
Point addition.
Definition: ed448.c:670
void shakeFinal(ShakeContext *context)
Finish absorbing phase.
Definition: shake.c:253
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:141
#define LOAD24LE(p)
Definition: cpu_endian.h:191
ECC (Elliptic Curve Cryptography)
@ ERROR_INVALID_SIGNATURE
Definition: error.h:228
Ed448 elliptic curve.
void curve448Import(int32_t *a, const uint8_t *data)
Import an octet string.
Definition: curve448.c:818
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:243
ShakeContext shakeContext
Definition: ed448.h:93
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
#define arraysize(a)
Definition: os_port.h:71