ed25519.c
Go to the documentation of this file.
1 /**
2  * @file ed25519.c
3  * @brief Ed25519 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/curve25519.h"
38 #include "ecc/ed25519.h"
39 #include "debug.h"
40 
41 //Check crypto library configuration
42 #if (ED25519_SUPPORT == ENABLED)
43 
44 //Base point B
45 static const Ed25519Point ED25519_B =
46 {
47  {
48  0x0F25D51A, 0x0AB16B04, 0x0969ECB2, 0x198EC12A, 0x0DC5C692,
49  0x1118FEEB, 0x0FFB0293, 0x1A79ADCA, 0x00216936
50  },
51  {
52  0x06666658, 0x13333333, 0x19999999, 0x0CCCCCCC, 0x06666666,
53  0x13333333, 0x19999999, 0x0CCCCCCC, 0x00666666
54  },
55  {
56  0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
57  0x00000000, 0x00000000, 0x00000000, 0x00000000
58  },
59  {
60  0x05B7DDA3, 0x0EF4559D, 0x1454BD5B, 0x013F00EE, 0x1E37D20F,
61  0x07473255, 0x19959BA9, 0x01FAF16E, 0x0067875F
62  }
63 };
64 
65 //Zero (constant)
66 static const int32_t ED25519_ZERO[9] =
67 {
68  0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
69  0x00000000, 0x00000000, 0x00000000, 0x00000000
70 };
71 
72 //Curve parameter d
73 static const int32_t ED25519_D[9] =
74 {
75  0x135978A3, 0x0F5A6E50, 0x10762ADD, 0x00149A82, 0x1E898007,
76  0x003CBBBC, 0x19CE331D, 0x1DC56DFF, 0x0052036C
77 };
78 
79 //Pre-computed value of 2 * d
80 static const int32_t ED25519_2D[9] =
81 {
82  0x06B2F159, 0x1EB4DCA1, 0x00EC55BA, 0x00293505, 0x1D13000E,
83  0x00797779, 0x139C663A, 0x1B8ADBFF, 0x002406D9
84 };
85 
86 //Order of the base point L
87 static const uint8_t ED25519_L[33] =
88 {
89  0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58,
90  0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14,
91  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
93  0x00,
94 };
95 
96 //Pre-computed value of mu = b^(2 * k) / L with b = 2^8 and k = 32
97 static const uint8_t ED25519_MU[33] =
98 {
99  0x1B, 0x13, 0x2C, 0x0A, 0xA3, 0xE5, 0x9C, 0xED,
100  0xA7, 0x29, 0x63, 0x08, 0x5D, 0x21, 0x06, 0x21,
101  0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
102  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
103  0x0F
104 };
105 
106 
107 /**
108  * @brief EdDSA key pair generation
109  * @param[in] prngAlgo PRNG algorithm
110  * @param[in] prngContext Pointer to the PRNG context
111  * @param[out] privateKey EdDSA private key (32 bytes)
112  * @param[out] publicKey EdDSA public key (32 bytes)
113  * @return Error code
114  **/
115 
116 error_t ed25519GenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext,
117  uint8_t *privateKey, uint8_t *publicKey)
118 {
119  error_t error;
120 
121  //Generate a private key
122  error = ed25519GeneratePrivateKey(prngAlgo, prngContext, privateKey);
123 
124  //Check status code
125  if(!error)
126  {
127  //Derive the public key from the private key
128  error = ed25519GeneratePublicKey(privateKey, publicKey);
129  }
130 
131  //Return status code
132  return error;
133 }
134 
135 
136 /**
137  * @brief EdDSA private key generation
138  * @param[in] prngAlgo PRNG algorithm
139  * @param[in] prngContext Pointer to the PRNG context
140  * @param[out] privateKey EdDSA private key (32 bytes)
141  * @return Error code
142  **/
143 
144 error_t ed25519GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext,
145  uint8_t *privateKey)
146 {
147  error_t error;
148 
149  //Check parameters
150  if(prngAlgo == NULL || prngContext == NULL || privateKey == NULL)
152 
153  //The private key is 32 octets of cryptographically secure random data
154  error = prngAlgo->generate(prngContext, privateKey, ED25519_PRIVATE_KEY_LEN);
155 
156  //Return status code
157  return error;
158 }
159 
160 
161 /**
162  * @brief Derive the public key from an EdDSA private key
163  * @param[in] privateKey EdDSA private key (32 bytes)
164  * @param[out] publicKey EdDSA public key (32 bytes)
165  * @return Error code
166  **/
167 
168 error_t ed25519GeneratePublicKey(const uint8_t *privateKey, uint8_t *publicKey)
169 {
170 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
172 #else
174 #endif
175 
176  //Check parameters
177  if(privateKey == NULL || publicKey == NULL)
179 
180 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
181  //Allocate working state
183  //Failed to allocate memory?
184  if(state == NULL)
185  return ERROR_OUT_OF_MEMORY;
186 #endif
187 
188  //Hash the 32-byte private key using SHA-512
189  sha512Init(&state->sha512Context);
190  sha512Update(&state->sha512Context, privateKey, ED25519_PRIVATE_KEY_LEN);
191 
192  //Only the lower 32 bytes are used for generating the public key. Interpret
193  //the buffer as the little-endian integer, forming a secret scalar s
194  sha512Final(&state->sha512Context, state->s);
195 
196  //The lowest three bits of the first octet are cleared, the highest bit
197  //of the last octet is cleared, and the second highest bit of the last
198  //octet is set
199  state->s[0] &= 0xF8;
200  state->s[31] &= 0x7F;
201  state->s[31] |= 0x40;
202 
203  //Perform a fixed-base scalar multiplication s * B
204  ed25519Mul(&state->subState, &state->a, state->s, &ED25519_B);
205  //The public key A is the encoding of the point s * B
206  ed25519Encode(&state->a, publicKey);
207 
208  //Erase working state
209  osMemset(state, 0, sizeof(Ed25519GeneratePublicKeyState));
210 
211 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
212  //Release working state
213  cryptoFreeMem(state);
214 #endif
215 
216  //Successful processing
217  return NO_ERROR;
218 }
219 
220 
221 /**
222  * @brief Check whether the EdDSA public key is valid
223  * @param[in] publicKey EdDSA public key (32 bytes)
224  * @return The function returns TRUE if the EdDSA public key is valid, else
225  * FALSE
226  **/
227 
228 bool_t ed25519CheckPublicKey(const uint8_t *publicKey)
229 {
230  uint32_t ret;
231  Ed25519Point p;
232 
233  //Decode the public key
234  ret = ed25519Decode(&p, publicKey);
235 
236  //Return TRUE if the public key is valid
237  return (ret == 0) ? TRUE : FALSE;
238 }
239 
240 
241 /**
242  * @brief EdDSA signature generation
243  * @param[in] privateKey Signer's EdDSA private key (32 bytes)
244  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
245  * @param[in] message Pointer to the message to be signed
246  * @param[in] messageLen Length of the message, in bytes
247  * @param[in] context Constant string specified by the protocol using it
248  * @param[in] contextLen Length of the context, in bytes
249  * @param[in] flag Prehash flag for Ed25519ph scheme (ED25519_PH_FLAG)
250  * @param[out] signature EdDSA signature (64 bytes)
251  * @return Error code
252  **/
253 
254 __weak_func error_t ed25519GenerateSignature(const uint8_t *privateKey,
255  const uint8_t *publicKey, const void *message, size_t messageLen,
256  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
257 {
258  error_t error;
259  DataFrag messageFrags[1];
260 
261  //The message fits in a single fragment
262  messageFrags[0].buffer = message;
263  messageFrags[0].length = messageLen;
264 
265  //Ed25519 signature generation
266  error = ed25519GenerateSignatureEx(privateKey, publicKey, messageFrags,
267  arraysize(messageFrags), context, contextLen, flag, signature);
268 
269  //Return status code
270  return error;
271 }
272 
273 
274 /**
275  * @brief EdDSA signature generation
276  * @param[in] privateKey Signer's EdDSA private key (32 bytes)
277  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
278  * @param[in] messageFrags Array of fragments representing the message to be
279  * signed
280  * @param[in] messageNumFrags Number of fragments representing the message
281  * @param[in] context Constant string specified by the protocol using it
282  * @param[in] contextLen Length of the context, in bytes
283  * @param[in] flag Prehash flag for Ed25519ph scheme (ED25519_PH_FLAG)
284  * @param[out] signature EdDSA signature (64 bytes)
285  * @return Error code
286  **/
287 
288 error_t ed25519GenerateSignatureEx(const uint8_t *privateKey,
289  const uint8_t *publicKey, const DataFrag *messageFrags,
290  uint_t messageNumFrags, const void *context, uint8_t contextLen,
291  uint8_t flag, uint8_t *signature)
292 {
293  uint_t i;
294  uint8_t c;
295 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
297 #else
299 #endif
300 
301  //Check parameters
302  if(privateKey == NULL || messageFrags == NULL || signature == NULL)
304 
305  //The context is an optional constant string specified by the protocol using
306  //it (refer to RFC 8032, section 8.3)
307  if(context == NULL && contextLen != 0)
309 
310 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
311  //Allocate working state
313  //Failed to allocate memory?
314  if(state == NULL)
315  return ERROR_OUT_OF_MEMORY;
316 #endif
317 
318  //Hash the private key, 32 octets, using SHA-512. Let h denote the
319  //resulting digest
320  sha512Init(&state->sha512Context);
321  sha512Update(&state->sha512Context, privateKey, ED25519_PRIVATE_KEY_LEN);
322  sha512Final(&state->sha512Context, state->h);
323 
324  //Construct the secret scalar s from the first half of the digest
325  osMemcpy(state->s, state->h, 32);
326 
327  //The lowest three bits of the first octet are cleared, the highest bit
328  //of the last octet is cleared, and the second highest bit of the last
329  //octet is set
330  state->s[0] &= 0xF8;
331  state->s[31] &= 0x7F;
332  state->s[31] |= 0x40;
333 
334  //The public key is optional
335  if(publicKey == NULL)
336  {
337  //Perform a fixed-base scalar multiplication s * B
338  ed25519Mul(&state->subState, &state->a, state->s, &ED25519_B);
339  //The public key A is the encoding of the point s * B
340  ed25519Encode(&state->a, state->k);
341  //Point to the resulting public key
342  publicKey = state->k;
343  }
344 
345  //Let prefix denote the second half of the hash digest
346  osMemcpy(state->p, state->h + 32, 32);
347 
348  //Initialize SHA-512 context
349  sha512Init(&state->sha512Context);
350 
351  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
352  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
353  //where x is in range 0-255 and y is an octet string of at most 255 octets
354  if(context != NULL || flag != 0)
355  {
356  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
357  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
358  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
359  sha512Update(&state->sha512Context, context, contextLen);
360  }
361 
362  //Digest prefix
363  sha512Update(&state->sha512Context, state->p, 32);
364 
365  //The message is split over multiple chunks
366  for(i = 0; i < messageNumFrags; i++)
367  {
368  //Digest current chunk
369  sha512Update(&state->sha512Context, messageFrags[i].buffer,
370  messageFrags[i].length);
371  }
372 
373  //Compute SHA-512(dom2(F, C) || prefix || PH(M))
374  sha512Final(&state->sha512Context, state->h);
375 
376  //Reduce the 64-octet digest as a little-endian integer r
377  ed25519RedInt(state->r, state->h);
378  //Compute the point r * B
379  ed25519Mul(&state->subState, &state->a, state->r, &ED25519_B);
380  //Let the string R be the encoding of this point
381  ed25519Encode(&state->a, signature);
382 
383  //Initialize SHA-512 context
384  sha512Init(&state->sha512Context);
385 
386  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
387  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
388  //where x is in range 0-255 and y is an octet string of at most 255 octets
389  if(context != NULL || flag != 0)
390  {
391  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
392  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
393  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
394  sha512Update(&state->sha512Context, context, contextLen);
395  }
396 
397  //Digest R || A
398  sha512Update(&state->sha512Context, signature, ED25519_SIGNATURE_LEN / 2);
400 
401  //The message is split over multiple chunks
402  for(i = 0; i < messageNumFrags; i++)
403  {
404  //Digest current chunk
405  sha512Update(&state->sha512Context, messageFrags[i].buffer,
406  messageFrags[i].length);
407  }
408 
409  //Compute SHA512(dom2(F, C) || R || A || PH(M)) and interpret the 64-octet
410  //digest as a little-endian integer k
411  sha512Final(&state->sha512Context, state->k);
412 
413  //Compute S = (r + k * s) mod L. For efficiency, reduce k modulo L first
414  ed25519RedInt(state->p, state->k);
415  ed25519MulInt(state->k, state->k + 32, state->p, state->s, 32);
416  ed25519RedInt(state->p, state->k);
417  ed25519AddInt(state->s, state->p, state->r, 32);
418 
419  //Perform modular reduction
420  c = ed25519SubInt(state->p, state->s, ED25519_L, 32);
421  ed25519SelectInt(signature + 32, state->p, state->s, c, 32);
422 
423  //Erase working state
424  osMemset(state, 0, sizeof(Ed25519GenerateSignatureState));
425 
426 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
427  //Release working state
428  cryptoFreeMem(state);
429 #endif
430 
431  //Successful processing
432  return NO_ERROR;
433 }
434 
435 
436 /**
437  * @brief EdDSA signature verification
438  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
439  * @param[in] message Message whose signature is to be verified
440  * @param[in] messageLen Length of the message, in bytes
441  * @param[in] context Constant string specified by the protocol using it
442  * @param[in] contextLen Length of the context, in bytes
443  * @param[in] flag Prehash flag for Ed25519ph scheme (ED25519_PH_FLAG)
444  * @param[in] signature EdDSA signature (64 bytes)
445  * @return Error code
446  **/
447 
448 __weak_func error_t ed25519VerifySignature(const uint8_t *publicKey,
449  const void *message, size_t messageLen, const void *context,
450  uint8_t contextLen, uint8_t flag, const uint8_t *signature)
451 {
452  error_t error;
453  DataFrag messageFrags[1];
454 
455  //The message fits in a single fragment
456  messageFrags[0].buffer = message;
457  messageFrags[0].length = messageLen;
458 
459  //Ed25519 signature verification
460  error = ed25519VerifySignatureEx(publicKey, messageFrags,
461  arraysize(messageFrags), context, contextLen, flag, signature);
462 
463  //Return status code
464  return error;
465 }
466 
467 
468 /**
469  * @brief EdDSA signature verification
470  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
471  * @param[in] messageFrags Array of fragments representing the message whose
472  * signature is to be verified
473  * @param[in] messageNumFrags Number of fragments representing the message
474  * @param[in] context Constant string specified by the protocol using it
475  * @param[in] contextLen Length of the context, in bytes
476  * @param[in] flag Prehash flag for Ed25519ph scheme (ED25519_PH_FLAG)
477  * @param[in] signature EdDSA signature (64 bytes)
478  * @return Error code
479  **/
480 
481 error_t ed25519VerifySignatureEx(const uint8_t *publicKey,
482  const DataFrag *messageFrags, uint_t messageNumFrags, const void *context,
483  uint8_t contextLen, uint8_t flag, const uint8_t *signature)
484 {
485  uint_t i;
486  uint32_t ret;
487 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
489 #else
491 #endif
492 
493  //Check parameters
494  if(publicKey == NULL || messageFrags == NULL || signature == NULL)
496 
497  //The context is an optional constant string specified by the protocol using
498  //it (refer to RFC 8032, section 8.3)
499  if(context == NULL && contextLen != 0)
501 
502 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
503  //Allocate working state
505  //Failed to allocate memory?
506  if(state == NULL)
507  return ERROR_OUT_OF_MEMORY;
508 #endif
509 
510  //First split the signature into two 32-octet halves. Decode the first
511  //half as a point R
512  osMemcpy(state->r, signature, ED25519_SIGNATURE_LEN / 2);
513 
514  //Decode the second half as an integer S, in the range 0 <= s < L
515  osMemcpy(state->s, signature + ED25519_SIGNATURE_LEN / 2,
517 
518  //Ed25519 signatures are not malleable due to the verification check that
519  //decoded S is smaller than L (refer to RFC 8032, section 8.4)
520  ret = 1 ^ ed25519SubInt(state->p, state->s, ED25519_L,
522 
523  //Decode the public key A as point A'
524  ret |= ed25519Decode(&state->a, publicKey);
525 
526  //Initialize SHA-512 context
527  sha512Init(&state->sha512Context);
528 
529  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
530  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
531  //where x is in range 0-255 and y is an octet string of at most 255 octets
532  if(context != NULL || flag != 0)
533  {
534  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
535  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
536  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
537  sha512Update(&state->sha512Context, context, contextLen);
538  }
539 
540  //Digest R || A
541  sha512Update(&state->sha512Context, state->r, ED25519_SIGNATURE_LEN / 2);
543 
544  //The message is split over multiple chunks
545  for(i = 0; i < messageNumFrags; i++)
546  {
547  //Digest current chunk
548  sha512Update(&state->sha512Context, messageFrags[i].buffer,
549  messageFrags[i].length);
550  }
551 
552  //Compute SHA512(dom2(F, C) || R || A || PH(M)) and interpret the 64-octet
553  //digest as a little-endian integer k
554  sha512Final(&state->sha512Context, state->k);
555 
556  //For efficiency, reduce k modulo L first
557  ed25519RedInt(state->k, state->k);
558 
559  //Compute -A'
560  curve25519Sub(state->a.x, ED25519_ZERO, state->a.x);
561  curve25519Sub(state->a.t, ED25519_ZERO, state->a.t);
562 
563  //Compute the point P = s * B - k * A'
564  ed25519TwinMul(&state->subState, &state->a, state->s, &ED25519_B, state->k,
565  &state->a);
566 
567  //Encode of the resulting point P
568  ed25519Encode(&state->a, state->p);
569 
570  //If P = R, then the signature is verified. If P does not equal R,
571  //then the message or the signature may have been modified
572  ret |= ed25519CompInt(state->p, signature, ED25519_SIGNATURE_LEN / 2);
573 
574  //Erase working state
575  osMemset(state, 0, sizeof(Ed25519VerifySignatureState));
576 
577 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
578  //Release working state
579  cryptoFreeMem(state);
580 #endif
581 
582  //Return status code
583  return (ret == 0) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
584 }
585 
586 
587 /**
588  * @brief Scalar multiplication (regular calculation)
589  * @param[in] state Pointer to the working state
590  * @param[out] r Resulting point R = k * P
591  * @param[in] k Input scalar
592  * @param[in] p Input point
593  **/
594 
595 __weak_func void ed25519Mul(Ed25519SubState *state, Ed25519Point *r,
596  const uint8_t *k, const Ed25519Point *p)
597 {
598  int_t i;
599  uint8_t b;
600 
601  //The neutral element is represented by (0, 1, 1, 0)
602  curve25519SetInt(state->u.x, 0);
603  curve25519SetInt(state->u.y, 1);
604  curve25519SetInt(state->u.z, 1);
605  curve25519SetInt(state->u.t, 0);
606 
607  //Perform scalar multiplication
608  for(i = CURVE25519_BIT_LEN - 1; i >= 0; i--)
609  {
610  //The scalar is processed in a left-to-right fashion
611  b = (k[i / 8] >> (i % 8)) & 1;
612 
613  //Compute U = 2 * U
614  ed25519Double(state, &state->u, &state->u);
615  //Compute V = U + P
616  ed25519Add(state, &state->v, &state->u, p);
617 
618  //If b is set, then U = V
619  curve25519Select(state->u.x, state->u.x, state->v.x, b);
620  curve25519Select(state->u.y, state->u.y, state->v.y, b);
621  curve25519Select(state->u.z, state->u.z, state->v.z, b);
622  curve25519Select(state->u.t, state->u.t, state->v.t, b);
623  }
624 
625  //Copy result
626  curve25519Copy(r->x, state->u.x);
627  curve25519Copy(r->y, state->u.y);
628  curve25519Copy(r->z, state->u.z);
629  curve25519Copy(r->t, state->u.t);
630 }
631 
632 
633 /**
634  * @brief Twin multiplication
635  * @param[in] state Pointer to the working state
636  * @param[out] r Resulting point R = k1 * P + k2 * Q
637  * @param[in] k1 First input scalar
638  * @param[in] p First input point
639  * @param[in] k2 Second input scalar
640  * @param[in] q Second input point
641  **/
642 
643 __weak_func void ed25519TwinMul(Ed25519SubState *state, Ed25519Point *r,
644  const uint8_t *k1, const Ed25519Point *p, const uint8_t *k2,
645  const Ed25519Point *q)
646 {
647  int_t i;
648  uint8_t b1;
649  uint8_t b2;
650 
651  //Pre-compute V = P + Q
652  ed25519Add(state, &state->v, p, q);
653 
654  //The neutral element is represented by (0, 1, 1, 0)
655  curve25519SetInt(state->u.x, 0);
656  curve25519SetInt(state->u.y, 1);
657  curve25519SetInt(state->u.z, 1);
658  curve25519SetInt(state->u.t, 0);
659 
660  //Calculate both multiplications at the same time
661  for(i = CURVE25519_BIT_LEN - 1; i >= 0; i--)
662  {
663  //The scalars are processed in a left-to-right fashion
664  b1 = (k1[i / 8] >> (i % 8)) & 1;
665  b2 = (k2[i / 8] >> (i % 8)) & 1;
666 
667  //Compute U = 2 * U
668  ed25519Double(state, &state->u, &state->u);
669 
670  //Check k1(i) and k2(i)
671  if(b1 == 1 && b2 == 0)
672  {
673  //Compute U = U + P
674  ed25519Add(state, &state->u, &state->u, p);
675  }
676  else if(b1 == 0 && b2 == 1)
677  {
678  //Compute U = U + Q
679  ed25519Add(state, &state->u, &state->u, q);
680  }
681  else if(b1 == 1 && b2 == 1)
682  {
683  //Compute U = U + V
684  ed25519Add(state, &state->u, &state->u, &state->v);
685  }
686  else
687  {
688  }
689  }
690 
691  //Copy result
692  curve25519Copy(r->x, state->u.x);
693  curve25519Copy(r->y, state->u.y);
694  curve25519Copy(r->z, state->u.z);
695  curve25519Copy(r->t, state->u.t);
696 }
697 
698 
699 /**
700  * @brief Point addition
701  * @param[in] state Pointer to the working state
702  * @param[out] r Resulting point R = P + Q
703  * @param[in] p First operand
704  * @param[in] q Second operand
705  **/
706 
708  const Ed25519Point *q)
709 {
710  //Compute A = (Y1 + X1) * (Y2 + X2)
711  curve25519Add(state->c, p->y, p->x);
712  curve25519Add(state->d, q->y, q->x);
713  curve25519Mul(state->a, state->c, state->d);
714 
715  //Compute B = (Y1 - X1) * (Y2 - X2)
716  curve25519Sub(state->c, p->y, p->x);
717  curve25519Sub(state->d, q->y, q->x);
718  curve25519Mul(state->b, state->c, state->d);
719 
720  //Compute C = 2 * Z1 * Z2
721  curve25519Mul(state->c, p->z, q->z);
722  curve25519Add(state->c, state->c, state->c);
723 
724  //Compute D = (2 * d) * T1 * T2
725  curve25519Mul(state->d, p->t, q->t);
726  curve25519Mul(state->d, state->d, ED25519_2D);
727 
728  //Compute E = A + B
729  curve25519Add(state->e, state->a, state->b);
730  //Compute F = A - B
731  curve25519Sub(state->f, state->a, state->b);
732  //Compute G = C + D
733  curve25519Add(state->g, state->c, state->d);
734  //Compute H = C - D
735  curve25519Sub(state->h, state->c, state->d);
736  //Compute X3 = F * H
737  curve25519Mul(r->x, state->f, state->h);
738  //Compute Y3 = E * G
739  curve25519Mul(r->y, state->e, state->g);
740  //Compute Z3 = G * H
741  curve25519Mul(r->z, state->g, state->h);
742  //Compute T3 = E * F
743  curve25519Mul(r->t, state->e, state->f);
744 }
745 
746 
747 /**
748  * @brief Point doubling
749  * @param[in] state Pointer to the working state
750  * @param[out] r Resulting point R = 2 * P
751  * @param[in] p Input point P
752  **/
753 
755  const Ed25519Point *p)
756 {
757  //Compute A = X1^2
758  curve25519Sqr(state->a, p->x);
759  //Compute B = Y1^2
760  curve25519Sqr(state->b, p->y);
761 
762  //Compute C = 2 * Z1^2
763  curve25519Sqr(state->c, p->z);
764  curve25519Add(state->c, state->c, state->c);
765 
766  //Compute E = A + B
767  curve25519Add(state->e, state->a, state->b);
768 
769  //Compute F = E - (X1 + Y1)^2
770  curve25519Add(state->f, p->x, p->y);
771  curve25519Sqr(state->f, state->f);
772  curve25519Sub(state->f, state->e, state->f);
773 
774  //Compute G = A - B
775  curve25519Sub(state->g, state->a, state->b);
776  //Compute H = C + G
777  curve25519Add(state->h, state->c, state->g);
778  //Compute X3 = F * H
779  curve25519Mul(r->x, state->f, state->h);
780  //Compute Y3 = E * G
781  curve25519Mul(r->y, state->e, state->g);
782  //Compute Z3 = G * H
783  curve25519Mul(r->z, state->g, state->h);
784  //Compute T3 = E * F
785  curve25519Mul(r->t, state->e, state->f);
786 }
787 
788 
789 /**
790  * @brief Point encoding
791  * @param[in] p Point representation
792  * @param[out] data Octet string resulting from the conversion
793  **/
794 
796 {
797  //Retrieve affine representation
798  curve25519Inv(p->z, p->z);
799  curve25519Mul(p->x, p->x, p->z);
800  curve25519Mul(p->y, p->y, p->z);
801  curve25519SetInt(p->z, 1);
802  curve25519Mul(p->t, p->x, p->y);
803 
804  //Reduce non-canonical values
805  curve25519Canonicalize(p->x, p->x);
806  curve25519Canonicalize(p->y, p->y);
807  curve25519Canonicalize(p->t, p->t);
808 
809  //Encode the y-coordinate as a little-endian string of 32 octets. The most
810  //significant bit of the final octet is always zero
811  curve25519Export(p->y, data);
812 
813  //Copy the least significant bit of the x-coordinate to the most significant
814  //bit of the final octet
815  data[31] |= (p->x[0] & 1) << 7;
816 }
817 
818 
819 /**
820  * @brief Point decoding
821  * @param[out] p Point representation
822  * @param[in] data Octet string to be converted
823  * @return The function returns 0 if the point has been successfully decoded,
824  * else 1
825  **/
826 
827 uint32_t ed25519Decode(Ed25519Point *p, const uint8_t *data)
828 {
829  uint_t i;
830  uint8_t x0;
831  uint32_t ret;
832  int32_t temp;
833  int32_t u[9];
834  int32_t v[9];
835 
836  //First, interpret the string as an integer in little-endian representation.
837  //Bit 255 of this number is the least significant bit of the x-coordinate
838  //and denote this value x_0
839  x0 = data[31] >> 7;
840 
841  //The y-coordinate is recovered simply by clearing this bit
842  curve25519Import(p->y, data);
843  p->y[8] &= 0x007FFFFF;
844 
845  //Compute u = y + 19
846  for(temp = 19, i = 0; i < 8; i++)
847  {
848  temp += p->y[i];
849  u[i] = temp & 0x1FFFFFFF;
850  temp >>= 29;
851  }
852 
853  temp += p->y[8];
854  u[8] = temp & 0x007FFFFF;
855  temp >>= 23;
856 
857  //If the y-coordinate is >= p, decoding fails
858  ret = CRYPTO_TEST_NZ_32(temp);
859 
860  //The curve equation implies x^2 = (y^2 - 1) / (d * y^2 + 1) mod p
861  //Let u = y^2 - 1 and v = d * y^2 + 1
862  curve25519Sqr(v, p->y);
863  curve25519SubInt(u, v, 1);
864  curve25519Mul(v, v, ED25519_D);
865  curve25519AddInt(v, v, 1);
866 
867  //Compute u = sqrt(u / v)
868  ret |= curve25519Sqrt(u, u, v);
869 
870  //If x = 0, and x_0 = 1, decoding fails
871  ret |= (curve25519Comp(u, ED25519_ZERO) ^ 1) & x0;
872 
873  //Compute v = p - u
874  curve25519Sub(v, ED25519_ZERO, u);
875 
876  //Finally, use the x_0 bit to select the right square root
877  curve25519Select(p->x, u, v, (x0 ^ u[0]) & 1);
878 
879  //Calculate extended point representation
880  curve25519SetInt(p->z, 1);
881  curve25519Mul(p->t, p->x, p->y);
882 
883  //Return 0 if the point has been successfully decoded, else 1
884  return ret;
885 }
886 
887 
888 /**
889  * @brief Reduce an integer modulo L
890  *
891  * This function implements Barrett reduction with b = 2^8 and k = 32. The
892  * algorithm requires the precomputation of the quantity mu = b^(2 * k) / L
893  *
894  * @param[out] r Resulting integer R = A mod L
895  * @param[in] a An integer such as 0 <= A < b^(2 * k)
896  **/
897 
898 void ed25519RedInt(uint8_t *r, const uint8_t *a)
899 {
900  uint8_t c;
901  uint8_t u[33];
902  uint8_t v[33];
903 
904  //Compute the estimate of the quotient u = ((a / b^(k - 1)) * mu) / b^(k + 1)
905  ed25519MulInt(NULL, u, a + 31, ED25519_MU, 33);
906  //Compute v = u * L mod b^(k + 1)
907  ed25519MulInt(v, NULL, u, ED25519_L, 33);
908 
909  //Compute the estimate of the remainder u = a mod b^(k + 1) - v
910  //If u < 0, then u = u + b^(k + 1)
911  ed25519SubInt(u, a, v, 33);
912 
913  //This estimation implies that at most two subtractions of L are required to
914  //obtain the correct remainder r
915  c = ed25519SubInt(v, u, ED25519_L, 33);
916  ed25519SelectInt(u, v, u, c, 33);
917  c = ed25519SubInt(v, u, ED25519_L, 33);
918  ed25519SelectInt(u, v, u, c, 33);
919 
920  //Copy the resulting remainder
921  ed25519CopyInt(r, u, 32);
922 }
923 
924 
925 /**
926  * @brief Addition of two integers
927  * @param[out] r Resulting integer R = A + B
928  * @param[in] a An integer such as 0 <= A < (2^8)^n
929  * @param[in] b An integer such as 0 <= B < (2^8)^n
930  * @param[in] n Size of the operands, in bytes
931  **/
932 
933 void ed25519AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
934 {
935  uint_t i;
936  uint16_t temp;
937 
938  //Compute R = A + B
939  for(temp = 0, i = 0; i < n; i++)
940  {
941  temp += a[i];
942  temp += b[i];
943  r[i] = temp & 0xFF;
944  temp >>= 8;
945  }
946 }
947 
948 
949 /**
950  * @brief Subtraction of two integers
951  * @param[out] r Resulting integer R = A - B
952  * @param[in] a An integer such as 0 <= A < (2^8)^n
953  * @param[in] b An integer such as 0 <= B < (2^8)^n
954  * @param[in] n Size of the operands, in bytes
955  * @return 1 if the result is negative, else 0
956  **/
957 
958 uint8_t ed25519SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
959 {
960  uint_t i;
961  int16_t temp;
962 
963  //Compute R = A - B
964  for(temp = 0, i = 0; i < n; i++)
965  {
966  temp += a[i];
967  temp -= b[i];
968  r[i] = temp & 0xFF;
969  temp >>= 8;
970  }
971 
972  //Return 1 if the result of the subtraction is negative
973  return temp & 1;
974 }
975 
976 
977 /**
978  * @brief Multiplication of two integers
979  * @param[out] rl Low part of the result R = (A * B) mod (2^8)^n
980  * @param[out] rh High part of the result R = (A * B) / (2^8)^n
981  * @param[in] a An integer such as 0 <= A < (2^8)^n
982  * @param[in] b An integer such as 0 <= B < (2^8)^n
983  * @param[in] n Size of the operands, in bytes
984  **/
985 
986 void ed25519MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a,
987  const uint8_t *b, uint_t n)
988 {
989  uint_t i;
990  uint_t j;
991  uint32_t temp;
992 
993  //Compute the low part of the multiplication
994  for(temp = 0, i = 0; i < n; i++)
995  {
996  //The Comba's algorithm computes the products, column by column
997  for(j = 0; j <= i; j++)
998  {
999  temp += (uint16_t) a[j] * b[i - j];
1000  }
1001 
1002  //At the bottom of each column, the final result is written to memory
1003  if(rl != NULL)
1004  {
1005  rl[i] = temp & 0xFF;
1006  }
1007 
1008  //Propagate the carry upwards
1009  temp >>= 8;
1010  }
1011 
1012  //Check whether the high part of the multiplication should be calculated
1013  if(rh != NULL)
1014  {
1015  //Compute the high part of the multiplication
1016  for(i = n; i < (2 * n); i++)
1017  {
1018  //The Comba's algorithm computes the products, column by column
1019  for(j = i + 1 - n; j < n; j++)
1020  {
1021  temp += (uint16_t) a[j] * b[i - j];
1022  }
1023 
1024  //At the bottom of each column, the final result is written to memory
1025  rh[i - n] = temp & 0xFF;
1026 
1027  //Propagate the carry upwards
1028  temp >>= 8;
1029  }
1030  }
1031 }
1032 
1033 
1034 /**
1035  * @brief Copy an integer
1036  * @param[out] a Pointer to the destination integer
1037  * @param[in] b Pointer to the source integer
1038  * @param[in] n Size of the integers, in bytes
1039  **/
1040 
1041 void ed25519CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
1042 {
1043  uint_t i;
1044 
1045  //Copy the value of the integer
1046  for(i = 0; i < n; i++)
1047  {
1048  a[i] = b[i];
1049  }
1050 }
1051 
1052 
1053 /**
1054  * @brief Select an integer
1055  * @param[out] r Pointer to the destination integer
1056  * @param[in] a Pointer to the first source integer
1057  * @param[in] b Pointer to the second source integer
1058  * @param[in] c Condition variable
1059  * @param[in] n Size of the integers, in bytes
1060  **/
1061 
1062 void ed25519SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b,
1063  uint8_t c, uint_t n)
1064 {
1065  uint_t i;
1066  uint8_t mask;
1067 
1068  //The mask is the all-1 or all-0 word
1069  mask = c - 1;
1070 
1071  //Select between A and B
1072  for(i = 0; i < n; i++)
1073  {
1074  //Constant time implementation
1075  r[i] = (a[i] & mask) | (b[i] & ~mask);
1076  }
1077 }
1078 
1079 
1080 /**
1081  * @brief Compare integers
1082  * @param[in] a Pointer to the first integer
1083  * @param[in] b Pointer to the second integer
1084  * @param[in] n Size of the integers, in bytes
1085  * @return The function returns 0 if the A = B, else 1
1086  **/
1087 
1088 uint8_t ed25519CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
1089 {
1090  uint_t i;
1091  uint8_t mask;
1092 
1093  //Initialize mask
1094  mask = 0;
1095 
1096  //Compare A and B
1097  for(i = 0; i < n; i++)
1098  {
1099  //Constant time implementation
1100  mask |= a[i] ^ b[i];
1101  }
1102 
1103  //Return 0 if A = B, else 1
1104  return ((uint8_t) (mask | (~mask + 1))) >> 7;
1105 }
1106 
1107 #endif
const void * buffer
Definition: crypto.h:1165
Ed25519 elliptic curve.
int32_t z[9]
Definition: ed25519.h:65
void curve25519Add(int32_t *r, const int32_t *a, const int32_t *b)
Modular addition.
Definition: curve25519.c:79
void curve25519Canonicalize(int32_t *r, const int32_t *a)
Reduce non-canonical value.
Definition: curve25519.c:630
int bool_t
Definition: compiler_port.h:63
uint8_t b
Definition: nbns_common.h:122
__weak_func void ed25519Mul(Ed25519SubState *state, Ed25519Point *r, const uint8_t *k, const Ed25519Point *p)
Scalar multiplication (regular calculation)
Definition: ed25519.c:595
Extended point representation.
Definition: ed25519.h:62
uint8_t a
Definition: ndp.h:411
signed int int_t
Definition: compiler_port.h:56
void curve25519Export(int32_t *a, uint8_t *data)
Export an octet string.
Definition: curve25519.c:798
#define PrngAlgo
Definition: crypto.h:1140
#define ED25519_PUBLIC_KEY_LEN
Definition: ed25519.h:42
uint8_t p
Definition: ndp.h:300
uint8_t message[]
Definition: chap.h:154
uint32_t ed25519Decode(Ed25519Point *p, const uint8_t *data)
Point decoding.
Definition: ed25519.c:827
#define TRUE
Definition: os_port.h:50
void ed25519SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint8_t c, uint_t n)
Select an integer.
Definition: ed25519.c:1062
int32_t c[9]
Definition: ed25519.h:80
uint8_t data[]
Definition: ethernet.h:224
int32_t y[9]
Definition: ed25519.h:64
Working state (signature generation)
Definition: ed25519.h:107
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:44
void curve25519Select(int32_t *r, const int32_t *a, const int32_t *b, uint32_t c)
Select an integer.
Definition: curve25519.c:726
int32_t b[9]
Definition: ed25519.h:79
#define ED25519_PRIVATE_KEY_LEN
Definition: ed25519.h:40
uint32_t curve25519Sqrt(int32_t *r, const int32_t *a, const int32_t *b)
Compute the square root of (A / B) modulo p.
Definition: curve25519.c:537
uint8_t r
Definition: ndp.h:346
__weak_func void ed25519TwinMul(Ed25519SubState *state, Ed25519Point *r, const uint8_t *k1, const Ed25519Point *p, const uint8_t *k2, const Ed25519Point *q)
Twin multiplication.
Definition: ed25519.c:643
uint32_t curve25519Comp(const int32_t *a, const int32_t *b)
Compare integers.
Definition: curve25519.c:751
Ed25519SubState subState
Definition: ed25519.h:98
int32_t g[9]
Definition: ed25519.h:84
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t ed25519VerifySignatureEx(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: ed25519.c:481
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
error_t
Error codes.
Definition: error.h:43
void ed25519Encode(Ed25519Point *p, uint8_t *data)
Point encoding.
Definition: ed25519.c:795
error_t ed25519GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey)
EdDSA private key generation.
Definition: ed25519.c:144
#define CRYPTO_TEST_NZ_32(a)
Definition: crypto.h:1103
Working state (scalar multiplication)
Definition: ed25519.h:75
void ed25519AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
Addition of two integers.
Definition: ed25519.c:933
int32_t t[9]
Definition: ed25519.h:66
Sha512Context sha512Context
Definition: ed25519.h:95
Data fragment descriptor.
Definition: crypto.h:1164
General definitions for cryptographic algorithms.
error_t ed25519GenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey, uint8_t *publicKey)
EdDSA key pair generation.
Definition: ed25519.c:116
void ed25519CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
Copy an integer.
Definition: ed25519.c:1041
Ed25519Point v
Definition: ed25519.h:77
__weak_func void curve25519Sqr(int32_t *r, const int32_t *a)
Modular squaring.
Definition: curve25519.c:452
uint8_t mask
Definition: web_socket.h:319
void curve25519Copy(int32_t *a, const int32_t *b)
Copy an integer.
Definition: curve25519.c:679
uint8_t u
Definition: lldp_ext_med.h:213
size_t length
Definition: crypto.h:1166
int32_t h[9]
Definition: ed25519.h:85
bool_t ed25519CheckPublicKey(const uint8_t *publicKey)
Check whether the EdDSA public key is valid.
Definition: ed25519.c:228
void ed25519MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a, const uint8_t *b, uint_t n)
Multiplication of two integers.
Definition: ed25519.c:986
void ed25519RedInt(uint8_t *r, const uint8_t *a)
Reduce an integer modulo L.
Definition: ed25519.c:898
#define CURVE25519_BIT_LEN
Definition: curve25519.h:38
Ed25519SubState subState
Definition: ed25519.h:115
void curve25519SetInt(int32_t *a, int32_t b)
Set integer value.
Definition: curve25519.c:57
void curve25519Inv(int32_t *r, const int32_t *a)
Modular multiplicative inverse.
Definition: curve25519.c:487
void curve25519Sub(int32_t *r, const int32_t *a, const int32_t *b)
Modular subtraction.
Definition: curve25519.c:153
int32_t x[9]
Definition: ed25519.h:63
Sha512Context sha512Context
Definition: ed25519.h:125
uint8_t n
Ed25519SubState subState
Definition: ed25519.h:131
error_t ed25519GenerateSignatureEx(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: ed25519.c:288
int32_t d[9]
Definition: ed25519.h:81
void sha512Final(Sha512Context *context, uint8_t *digest)
Finish the SHA-512 message digest.
#define cryptoFreeMem(p)
Definition: crypto.h:966
int32_t f[9]
Definition: ed25519.h:83
Sha512Context sha512Context
Definition: ed25519.h:108
__weak_func error_t ed25519VerifySignature(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: ed25519.c:448
void sha512Init(Sha512Context *context)
Initialize SHA-512 message digest context.
Curve25519 elliptic curve.
int32_t e[9]
Definition: ed25519.h:82
#define cryptoAllocMem(size)
Definition: crypto.h:961
void curve25519AddInt(int32_t *r, const int32_t *a, int32_t b)
Modular addition.
Definition: curve25519.c:124
__weak_func error_t ed25519GenerateSignature(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: ed25519.c:254
void curve25519Import(int32_t *a, const uint8_t *data)
Import an octet string.
Definition: curve25519.c:777
error_t ed25519GeneratePublicKey(const uint8_t *privateKey, uint8_t *publicKey)
Derive the public key from an EdDSA private key.
Definition: ed25519.c:168
int32_t a[9]
Definition: ed25519.h:78
__weak_func void curve25519Mul(int32_t *r, const int32_t *a, const int32_t *b)
Modular multiplication.
Definition: curve25519.c:227
Working state (signature verification)
Definition: ed25519.h:124
unsigned int uint_t
Definition: compiler_port.h:57
#define osMemset(p, value, length)
Definition: os_port.h:141
void ed25519Double(Ed25519SubState *state, Ed25519Point *r, const Ed25519Point *p)
Point doubling.
Definition: ed25519.c:754
Ed25519Point u
Definition: ed25519.h:76
uint8_t ed25519CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
Compare integers.
Definition: ed25519.c:1088
ECC (Elliptic Curve Cryptography)
@ ERROR_INVALID_SIGNATURE
Definition: error.h:228
uint8_t ed25519SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
Subtraction of two integers.
Definition: ed25519.c:958
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
#define arraysize(a)
Definition: os_port.h:71
void sha512Update(Sha512Context *context, const void *data, size_t length)
Update the SHA-512 context with a portion of the message being hashed.
void ed25519Add(Ed25519SubState *state, Ed25519Point *r, const Ed25519Point *p, const Ed25519Point *q)
Point addition.
Definition: ed25519.c:707
Working state (public key generation)
Definition: ed25519.h:94
void curve25519SubInt(int32_t *r, const int32_t *a, int32_t b)
Modular subtraction.
Definition: curve25519.c:198