ed25519.c
Go to the documentation of this file.
1 /**
2  * @file ed25519.c
3  * @brief Ed25519 elliptic curve (constant-time implementation)
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.2
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->read(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 EdDSA signature generation
223  * @param[in] privateKey Signer's EdDSA private key (32 bytes)
224  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
225  * @param[in] message Pointer to the message to be signed
226  * @param[in] messageLen Length of the message, in bytes
227  * @param[in] context Constant string specified by the protocol using it
228  * @param[in] contextLen Length of the context, in bytes
229  * @param[in] flag Prehash flag for Ed25519ph scheme
230  * @param[out] signature EdDSA signature (64 bytes)
231  * @return Error code
232  **/
233 
234 error_t ed25519GenerateSignature(const uint8_t *privateKey,
235  const uint8_t *publicKey, const void *message, size_t messageLen,
236  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
237 {
238  error_t error;
239  DataChunk messageChunks[1];
240 
241  //The message fits in a single chunk
242  messageChunks[0].buffer = message;
243  messageChunks[0].length = messageLen;
244 
245  //Ed25519 signature generation
246  error = ed25519GenerateSignatureEx(privateKey, publicKey, messageChunks,
247  arraysize(messageChunks), context, contextLen, flag, signature);
248 
249  //Return status code
250  return error;
251 }
252 
253 
254 /**
255  * @brief EdDSA signature generation
256  * @param[in] privateKey Signer's EdDSA private key (32 bytes)
257  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
258  * @param[in] message Array of data chunks representing the message to be
259  * signed
260  * @param[in] messageLen Number of data chunks representing the message
261  * @param[in] context Constant string specified by the protocol using it
262  * @param[in] contextLen Length of the context, in bytes
263  * @param[in] flag Prehash flag for Ed25519ph scheme
264  * @param[out] signature EdDSA signature (64 bytes)
265  * @return Error code
266  **/
267 
268 error_t ed25519GenerateSignatureEx(const uint8_t *privateKey,
269  const uint8_t *publicKey, const DataChunk *message, uint_t messageLen,
270  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
271 {
272  uint_t i;
273  uint8_t c;
274 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
276 #else
278 #endif
279 
280  //Check parameters
281  if(privateKey == NULL || message == NULL || signature == NULL)
283 
284  //The context is an optional constant string specified by the protocol using
285  //it (refer to RFC 8032, section 8.3)
286  if(context == NULL && contextLen != 0)
288 
289 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
290  //Allocate working state
292  //Failed to allocate memory?
293  if(state == NULL)
294  return ERROR_OUT_OF_MEMORY;
295 #endif
296 
297  //Hash the private key, 32 octets, using SHA-512. Let h denote the
298  //resulting digest
299  sha512Init(&state->sha512Context);
300  sha512Update(&state->sha512Context, privateKey, ED25519_PRIVATE_KEY_LEN);
301  sha512Final(&state->sha512Context, state->h);
302 
303  //Construct the secret scalar s from the first half of the digest
304  osMemcpy(state->s, state->h, 32);
305 
306  //The lowest three bits of the first octet are cleared, the highest bit
307  //of the last octet is cleared, and the second highest bit of the last
308  //octet is set
309  state->s[0] &= 0xF8;
310  state->s[31] &= 0x7F;
311  state->s[31] |= 0x40;
312 
313  //The public key is optional
314  if(publicKey == NULL)
315  {
316  //Perform a fixed-base scalar multiplication s * B
317  ed25519Mul(&state->subState, &state->a, state->s, &ED25519_B);
318  //The public key A is the encoding of the point s * B
319  ed25519Encode(&state->a, state->k);
320  //Point to the resulting public key
321  publicKey = state->k;
322  }
323 
324  //Let prefix denote the second half of the hash digest
325  osMemcpy(state->p, state->h + 32, 32);
326 
327  //Initialize SHA-512 context
328  sha512Init(&state->sha512Context);
329 
330  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
331  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
332  //where x is in range 0-255 and y is an octet string of at most 255 octets
333  if(context != NULL || flag != 0)
334  {
335  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
336  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
337  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
338  sha512Update(&state->sha512Context, context, contextLen);
339  }
340 
341  //Digest prefix
342  sha512Update(&state->sha512Context, state->p, 32);
343 
344  //The message is split over multiple chunks
345  for(i = 0; i < messageLen; i++)
346  {
347  //Digest current chunk
348  sha512Update(&state->sha512Context, message[i].buffer,
349  message[i].length);
350  }
351 
352  //Compute SHA-512(dom2(F, C) || prefix || PH(M))
353  sha512Final(&state->sha512Context, state->h);
354 
355  //Reduce the 64-octet digest as a little-endian integer r
356  ed25519RedInt(state->r, state->h);
357  //Compute the point r * B
358  ed25519Mul(&state->subState, &state->a, state->r, &ED25519_B);
359  //Let the string R be the encoding of this point
360  ed25519Encode(&state->a, signature);
361 
362  //Initialize SHA-512 context
363  sha512Init(&state->sha512Context);
364 
365  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
366  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
367  //where x is in range 0-255 and y is an octet string of at most 255 octets
368  if(context != NULL || flag != 0)
369  {
370  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
371  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
372  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
373  sha512Update(&state->sha512Context, context, contextLen);
374  }
375 
376  //Digest R || A
377  sha512Update(&state->sha512Context, signature, ED25519_SIGNATURE_LEN / 2);
379 
380  //The message is split over multiple chunks
381  for(i = 0; i < messageLen; i++)
382  {
383  //Digest current chunk
384  sha512Update(&state->sha512Context, message[i].buffer,
385  message[i].length);
386  }
387 
388  //Compute SHA512(dom2(F, C) || R || A || PH(M)) and interpret the 64-octet
389  //digest as a little-endian integer k
390  sha512Final(&state->sha512Context, state->k);
391 
392  //Compute S = (r + k * s) mod L. For efficiency, reduce k modulo L first
393  ed25519RedInt(state->p, state->k);
394  ed25519MulInt(state->k, state->k + 32, state->p, state->s, 32);
395  ed25519RedInt(state->p, state->k);
396  ed25519AddInt(state->s, state->p, state->r, 32);
397 
398  //Perform modular reduction
399  c = ed25519SubInt(state->p, state->s, ED25519_L, 32);
400  ed25519SelectInt(signature + 32, state->p, state->s, c, 32);
401 
402  //Erase working state
403  osMemset(state, 0, sizeof(Ed25519GenerateSignatureState));
404 
405 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
406  //Release working state
407  cryptoFreeMem(state);
408 #endif
409 
410  //Successful processing
411  return NO_ERROR;
412 }
413 
414 
415 /**
416  * @brief EdDSA signature verification
417  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
418  * @param[in] message Message whose signature is to be verified
419  * @param[in] messageLen Length of the message, in bytes
420  * @param[in] context Constant string specified by the protocol using it
421  * @param[in] contextLen Length of the context, in bytes
422  * @param[in] flag Prehash flag for Ed25519ph scheme
423  * @param[in] signature EdDSA signature (64 bytes)
424  * @return Error code
425  **/
426 
427 error_t ed25519VerifySignature(const uint8_t *publicKey, const void *message,
428  size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag,
429  const uint8_t *signature)
430 {
431  error_t error;
432  DataChunk messageChunks[1];
433 
434  //The message fits in a single chunk
435  messageChunks[0].buffer = message;
436  messageChunks[0].length = messageLen;
437 
438  //Ed25519 signature verification
439  error = ed25519VerifySignatureEx(publicKey, messageChunks,
440  arraysize(messageChunks), context, contextLen, flag, signature);
441 
442  //Return status code
443  return error;
444 }
445 
446 
447 /**
448  * @brief EdDSA signature verification
449  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
450  * @param[in] message Array of data chunks representing the message whose
451  * signature is to be verified
452  * @param[in] messageLen Number of data chunks representing the message
453  * @param[in] context Constant string specified by the protocol using it
454  * @param[in] contextLen Length of the context, in bytes
455  * @param[in] flag Prehash flag for Ed25519ph scheme
456  * @param[in] signature EdDSA signature (64 bytes)
457  * @return Error code
458  **/
459 
460 error_t ed25519VerifySignatureEx(const uint8_t *publicKey,
461  const DataChunk *message, uint_t messageLen, const void *context,
462  uint8_t contextLen, uint8_t flag, const uint8_t *signature)
463 {
464  uint_t i;
465  uint32_t ret;
466 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
468 #else
470 #endif
471 
472  //Check parameters
473  if(publicKey == NULL || message == NULL || signature == NULL)
475 
476  //The context is an optional constant string specified by the protocol using
477  //it (refer to RFC 8032, section 8.3)
478  if(context == NULL && contextLen != 0)
480 
481 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
482  //Allocate working state
484  //Failed to allocate memory?
485  if(state == NULL)
486  return ERROR_OUT_OF_MEMORY;
487 #endif
488 
489  //First split the signature into two 32-octet halves. Decode the first
490  //half as a point R
491  osMemcpy(state->r, signature, ED25519_SIGNATURE_LEN / 2);
492 
493  //Decode the second half as an integer S, in the range 0 <= s < L
494  osMemcpy(state->s, signature + ED25519_SIGNATURE_LEN / 2,
496 
497  //Ed25519 signatures are not malleable due to the verification check that
498  //decoded S is smaller than L (refer to RFC 8032, section 8.4)
499  ret = 1 ^ ed25519SubInt(state->p, state->s, ED25519_L,
501 
502  //Decode the public key A as point A'
503  ret |= ed25519Decode(&state->a, publicKey);
504 
505  //Initialize SHA-512 context
506  sha512Init(&state->sha512Context);
507 
508  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
509  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
510  //where x is in range 0-255 and y is an octet string of at most 255 octets
511  if(context != NULL || flag != 0)
512  {
513  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
514  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
515  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
516  sha512Update(&state->sha512Context, context, contextLen);
517  }
518 
519  //Digest R || A
520  sha512Update(&state->sha512Context, state->r, ED25519_SIGNATURE_LEN / 2);
522 
523  //The message is split over multiple chunks
524  for(i = 0; i < messageLen; i++)
525  {
526  //Digest current chunk
527  sha512Update(&state->sha512Context, message[i].buffer,
528  message[i].length);
529  }
530 
531  //Compute SHA512(dom2(F, C) || R || A || PH(M)) and interpret the 64-octet
532  //digest as a little-endian integer k
533  sha512Final(&state->sha512Context, state->k);
534 
535  //For efficiency, reduce k modulo L first
536  ed25519RedInt(state->k, state->k);
537 
538  //Compute -A'
539  curve25519Sub(state->a.x, ED25519_ZERO, state->a.x);
540  curve25519Sub(state->a.t, ED25519_ZERO, state->a.t);
541 
542  //Compute the point P = s * B - k * A'
543  ed25519TwinMul(&state->subState, &state->a, state->s, &ED25519_B, state->k,
544  &state->a);
545 
546  //Encode of the resulting point P
547  ed25519Encode(&state->a, state->p);
548 
549  //If P = R, then the signature is verified. If P does not equal R,
550  //then the message or the signature may have been modified
551  ret |= ed25519CompInt(state->p, signature, ED25519_SIGNATURE_LEN / 2);
552 
553  //Erase working state
554  osMemset(state, 0, sizeof(Ed25519VerifySignatureState));
555 
556 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
557  //Release working state
558  cryptoFreeMem(state);
559 #endif
560 
561  //Return status code
562  return (ret == 0) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
563 }
564 
565 
566 /**
567  * @brief Scalar multiplication (regular calculation)
568  * @param[in] state Pointer to the working state
569  * @param[out] r Resulting point R = k * P
570  * @param[in] k Input scalar
571  * @param[in] p Input point
572  **/
573 
574 __weak_func void ed25519Mul(Ed25519SubState *state, Ed25519Point *r,
575  const uint8_t *k, const Ed25519Point *p)
576 {
577  int_t i;
578  uint8_t b;
579 
580  //The neutral element is represented by (0, 1, 1, 0)
581  curve25519SetInt(state->u.x, 0);
582  curve25519SetInt(state->u.y, 1);
583  curve25519SetInt(state->u.z, 1);
584  curve25519SetInt(state->u.t, 0);
585 
586  //Perform scalar multiplication
587  for(i = CURVE25519_BIT_LEN - 1; i >= 0; i--)
588  {
589  //The scalar is processed in a left-to-right fashion
590  b = (k[i / 8] >> (i % 8)) & 1;
591 
592  //Compute U = 2 * U
593  ed25519Double(state, &state->u, &state->u);
594  //Compute V = U + P
595  ed25519Add(state, &state->v, &state->u, p);
596 
597  //If b is set, then U = V
598  curve25519Select(state->u.x, state->u.x, state->v.x, b);
599  curve25519Select(state->u.y, state->u.y, state->v.y, b);
600  curve25519Select(state->u.z, state->u.z, state->v.z, b);
601  curve25519Select(state->u.t, state->u.t, state->v.t, b);
602  }
603 
604  //Copy result
605  curve25519Copy(r->x, state->u.x);
606  curve25519Copy(r->y, state->u.y);
607  curve25519Copy(r->z, state->u.z);
608  curve25519Copy(r->t, state->u.t);
609 }
610 
611 
612 /**
613  * @brief Twin multiplication
614  * @param[in] state Pointer to the working state
615  * @param[out] r Resulting point R = k1 * P + k2 * Q
616  * @param[in] k1 First input scalar
617  * @param[in] p First input point
618  * @param[in] k2 Second input scalar
619  * @param[in] q Second input point
620  **/
621 
622 __weak_func void ed25519TwinMul(Ed25519SubState *state, Ed25519Point *r,
623  const uint8_t *k1, const Ed25519Point *p, const uint8_t *k2,
624  const Ed25519Point *q)
625 {
626  int_t i;
627  uint8_t b1;
628  uint8_t b2;
629 
630  //Pre-compute V = P + Q
631  ed25519Add(state, &state->v, p, q);
632 
633  //The neutral element is represented by (0, 1, 1, 0)
634  curve25519SetInt(state->u.x, 0);
635  curve25519SetInt(state->u.y, 1);
636  curve25519SetInt(state->u.z, 1);
637  curve25519SetInt(state->u.t, 0);
638 
639  //Calculate both multiplications at the same time
640  for(i = CURVE25519_BIT_LEN - 1; i >= 0; i--)
641  {
642  //The scalars are processed in a left-to-right fashion
643  b1 = (k1[i / 8] >> (i % 8)) & 1;
644  b2 = (k2[i / 8] >> (i % 8)) & 1;
645 
646  //Compute U = 2 * U
647  ed25519Double(state, &state->u, &state->u);
648 
649  //Check k1(i) and k2(i)
650  if(b1 == 1 && b2 == 0)
651  {
652  //Compute U = U + P
653  ed25519Add(state, &state->u, &state->u, p);
654  }
655  else if(b1 == 0 && b2 == 1)
656  {
657  //Compute U = U + Q
658  ed25519Add(state, &state->u, &state->u, q);
659  }
660  else if(b1 == 1 && b2 == 1)
661  {
662  //Compute U = U + V
663  ed25519Add(state, &state->u, &state->u, &state->v);
664  }
665  else
666  {
667  }
668  }
669 
670  //Copy result
671  curve25519Copy(r->x, state->u.x);
672  curve25519Copy(r->y, state->u.y);
673  curve25519Copy(r->z, state->u.z);
674  curve25519Copy(r->t, state->u.t);
675 }
676 
677 
678 /**
679  * @brief Point addition
680  * @param[in] state Pointer to the working state
681  * @param[out] r Resulting point R = P + Q
682  * @param[in] p First operand
683  * @param[in] q Second operand
684  **/
685 
687  const Ed25519Point *q)
688 {
689  //Compute A = (Y1 + X1) * (Y2 + X2)
690  curve25519Add(state->c, p->y, p->x);
691  curve25519Add(state->d, q->y, q->x);
692  curve25519Mul(state->a, state->c, state->d);
693 
694  //Compute B = (Y1 - X1) * (Y2 - X2)
695  curve25519Sub(state->c, p->y, p->x);
696  curve25519Sub(state->d, q->y, q->x);
697  curve25519Mul(state->b, state->c, state->d);
698 
699  //Compute C = 2 * Z1 * Z2
700  curve25519Mul(state->c, p->z, q->z);
701  curve25519Add(state->c, state->c, state->c);
702 
703  //Compute D = (2 * d) * T1 * T2
704  curve25519Mul(state->d, p->t, q->t);
705  curve25519Mul(state->d, state->d, ED25519_2D);
706 
707  //Compute E = A + B
708  curve25519Add(state->e, state->a, state->b);
709  //Compute F = A - B
710  curve25519Sub(state->f, state->a, state->b);
711  //Compute G = C + D
712  curve25519Add(state->g, state->c, state->d);
713  //Compute H = C - D
714  curve25519Sub(state->h, state->c, state->d);
715  //Compute X3 = F * H
716  curve25519Mul(r->x, state->f, state->h);
717  //Compute Y3 = E * G
718  curve25519Mul(r->y, state->e, state->g);
719  //Compute Z3 = G * H
720  curve25519Mul(r->z, state->g, state->h);
721  //Compute T3 = E * F
722  curve25519Mul(r->t, state->e, state->f);
723 }
724 
725 
726 /**
727  * @brief Point doubling
728  * @param[in] state Pointer to the working state
729  * @param[out] r Resulting point R = 2 * P
730  * @param[in] p Input point P
731  **/
732 
734  const Ed25519Point *p)
735 {
736  //Compute A = X1^2
737  curve25519Sqr(state->a, p->x);
738  //Compute B = Y1^2
739  curve25519Sqr(state->b, p->y);
740 
741  //Compute C = 2 * Z1^2
742  curve25519Sqr(state->c, p->z);
743  curve25519Add(state->c, state->c, state->c);
744 
745  //Compute E = A + B
746  curve25519Add(state->e, state->a, state->b);
747 
748  //Compute F = E - (X1 + Y1)^2
749  curve25519Add(state->f, p->x, p->y);
750  curve25519Sqr(state->f, state->f);
751  curve25519Sub(state->f, state->e, state->f);
752 
753  //Compute G = A - B
754  curve25519Sub(state->g, state->a, state->b);
755  //Compute H = C + G
756  curve25519Add(state->h, state->c, state->g);
757  //Compute X3 = F * H
758  curve25519Mul(r->x, state->f, state->h);
759  //Compute Y3 = E * G
760  curve25519Mul(r->y, state->e, state->g);
761  //Compute Z3 = G * H
762  curve25519Mul(r->z, state->g, state->h);
763  //Compute T3 = E * F
764  curve25519Mul(r->t, state->e, state->f);
765 }
766 
767 
768 /**
769  * @brief Point encoding
770  * @param[in] p Point representation
771  * @param[out] data Octet string resulting from the conversion
772  **/
773 
775 {
776  //Retrieve affine representation
777  curve25519Inv(p->z, p->z);
778  curve25519Mul(p->x, p->x, p->z);
779  curve25519Mul(p->y, p->y, p->z);
780  curve25519SetInt(p->z, 1);
781  curve25519Mul(p->t, p->x, p->y);
782 
783  //Reduce non-canonical values
784  curve25519Canonicalize(p->x, p->x);
785  curve25519Canonicalize(p->y, p->y);
786  curve25519Canonicalize(p->t, p->t);
787 
788  //Encode the y-coordinate as a little-endian string of 32 octets. The most
789  //significant bit of the final octet is always zero
790  curve25519Export(p->y, data);
791 
792  //Copy the least significant bit of the x-coordinate to the most significant
793  //bit of the final octet
794  data[31] |= (p->x[0] & 1) << 7;
795 }
796 
797 
798 /**
799  * @brief Point decoding
800  * @param[out] p Point representation
801  * @param[in] data Octet string to be converted
802  **/
803 
804 uint32_t ed25519Decode(Ed25519Point *p, const uint8_t *data)
805 {
806  uint_t i;
807  uint8_t x0;
808  uint32_t ret;
809  int32_t temp;
810  int32_t u[9];
811  int32_t v[9];
812 
813  //First, interpret the string as an integer in little-endian representation.
814  //Bit 255 of this number is the least significant bit of the x-coordinate
815  //and denote this value x_0
816  x0 = data[31] >> 7;
817 
818  //The y-coordinate is recovered simply by clearing this bit
819  curve25519Import(p->y, data);
820  p->y[8] &= 0x007FFFFF;
821 
822  //Compute u = y + 19
823  for(temp = 19, i = 0; i < 8; i++)
824  {
825  temp += p->y[i];
826  u[i] = temp & 0x1FFFFFFF;
827  temp >>= 29;
828  }
829 
830  temp += p->y[8];
831  u[8] = temp & 0x007FFFFF;
832  temp >>= 23;
833 
834  //If the y-coordinate is >= p, decoding fails
835  ret = CRYPTO_TEST_NZ_32(temp);
836 
837  //The curve equation implies x^2 = (y^2 - 1) / (d * y^2 + 1) mod p
838  //Let u = y^2 - 1 and v = d * y^2 + 1
839  curve25519Sqr(v, p->y);
840  curve25519SubInt(u, v, 1);
841  curve25519Mul(v, v, ED25519_D);
842  curve25519AddInt(v, v, 1);
843 
844  //Compute u = sqrt(u / v)
845  ret |= curve25519Sqrt(u, u, v);
846 
847  //If x = 0, and x_0 = 1, decoding fails
848  ret |= (curve25519Comp(u, ED25519_ZERO) ^ 1) & x0;
849 
850  //Compute v = p - u
851  curve25519Sub(v, ED25519_ZERO, u);
852 
853  //Finally, use the x_0 bit to select the right square root
854  curve25519Select(p->x, u, v, (x0 ^ u[0]) & 1);
855 
856  //Calculate extended point representation
857  curve25519SetInt(p->z, 1);
858  curve25519Mul(p->t, p->x, p->y);
859 
860  //Return 0 if the point has been successfully decoded, else 1
861  return ret;
862 }
863 
864 
865 /**
866  * @brief Reduce an integer modulo L
867  *
868  * This function implements Barrett reduction with b = 2^8 and k = 32. The
869  * algorithm requires the precomputation of the quantity mu = b^(2 * k) / L
870  *
871  * @param[out] r Resulting integer R = A mod L
872  * @param[in] a An integer such as 0 <= A < b^(2 * k)
873  **/
874 
875 void ed25519RedInt(uint8_t *r, const uint8_t *a)
876 {
877  uint8_t c;
878  uint8_t u[33];
879  uint8_t v[33];
880 
881  //Compute the estimate of the quotient u = ((a / b^(k - 1)) * mu) / b^(k + 1)
882  ed25519MulInt(NULL, u, a + 31, ED25519_MU, 33);
883  //Compute v = u * L mod b^(k + 1)
884  ed25519MulInt(v, NULL, u, ED25519_L, 33);
885 
886  //Compute the estimate of the remainder u = a mod b^(k + 1) - v
887  //If u < 0, then u = u + b^(k + 1)
888  ed25519SubInt(u, a, v, 33);
889 
890  //This estimation implies that at most two subtractions of L are required to
891  //obtain the correct remainder r
892  c = ed25519SubInt(v, u, ED25519_L, 33);
893  ed25519SelectInt(u, v, u, c, 33);
894  c = ed25519SubInt(v, u, ED25519_L, 33);
895  ed25519SelectInt(u, v, u, c, 33);
896 
897  //Copy the resulting remainder
898  ed25519CopyInt(r, u, 32);
899 }
900 
901 
902 /**
903  * @brief Addition of two integers
904  * @param[out] r Resulting integer R = A + B
905  * @param[in] a An integer such as 0 <= A < (2^8)^n
906  * @param[in] b An integer such as 0 <= B < (2^8)^n
907  * @param[in] n Size of the operands, in bytes
908  **/
909 
910 void ed25519AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
911 {
912  uint_t i;
913  uint16_t temp;
914 
915  //Compute R = A + B
916  for(temp = 0, i = 0; i < n; i++)
917  {
918  temp += a[i];
919  temp += b[i];
920  r[i] = temp & 0xFF;
921  temp >>= 8;
922  }
923 }
924 
925 
926 /**
927  * @brief Subtraction of two integers
928  * @param[out] r Resulting integer R = A - B
929  * @param[in] a An integer such as 0 <= A < (2^8)^n
930  * @param[in] b An integer such as 0 <= B < (2^8)^n
931  * @param[in] n Size of the operands, in bytes
932  * @return 1 if the result is negative, else 0
933  **/
934 
935 uint8_t ed25519SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
936 {
937  uint_t i;
938  int16_t temp;
939 
940  //Compute R = A - B
941  for(temp = 0, i = 0; i < n; i++)
942  {
943  temp += a[i];
944  temp -= b[i];
945  r[i] = temp & 0xFF;
946  temp >>= 8;
947  }
948 
949  //Return 1 if the result of the subtraction is negative
950  return temp & 1;
951 }
952 
953 
954 /**
955  * @brief Multiplication of two integers
956  * @param[out] rl Low part of the result R = (A * B) mod (2^8)^n
957  * @param[out] rh High part of the result R = (A * B) / (2^8)^n
958  * @param[in] a An integer such as 0 <= A < (2^8)^n
959  * @param[in] b An integer such as 0 <= B < (2^8)^n
960  * @param[in] n Size of the operands, in bytes
961  **/
962 
963 void ed25519MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a,
964  const uint8_t *b, uint_t n)
965 {
966  uint_t i;
967  uint_t j;
968  uint32_t temp;
969 
970  //Compute the low part of the multiplication
971  for(temp = 0, i = 0; i < n; i++)
972  {
973  //The Comba's algorithm computes the products, column by column
974  for(j = 0; j <= i; j++)
975  {
976  temp += (uint16_t) a[j] * b[i - j];
977  }
978 
979  //At the bottom of each column, the final result is written to memory
980  if(rl != NULL)
981  {
982  rl[i] = temp & 0xFF;
983  }
984 
985  //Propagate the carry upwards
986  temp >>= 8;
987  }
988 
989  //Check whether the high part of the multiplication should be calculated
990  if(rh != NULL)
991  {
992  //Compute the high part of the multiplication
993  for(i = n; i < (2 * n); i++)
994  {
995  //The Comba's algorithm computes the products, column by column
996  for(j = i + 1 - n; j < n; j++)
997  {
998  temp += (uint16_t) a[j] * b[i - j];
999  }
1000 
1001  //At the bottom of each column, the final result is written to memory
1002  rh[i - n] = temp & 0xFF;
1003 
1004  //Propagate the carry upwards
1005  temp >>= 8;
1006  }
1007  }
1008 }
1009 
1010 
1011 /**
1012  * @brief Copy an integer
1013  * @param[out] a Pointer to the destination integer
1014  * @param[in] b Pointer to the source integer
1015  * @param[in] n Size of the integers, in bytes
1016  **/
1017 
1018 void ed25519CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
1019 {
1020  uint_t i;
1021 
1022  //Copy the value of the integer
1023  for(i = 0; i < n; i++)
1024  {
1025  a[i] = b[i];
1026  }
1027 }
1028 
1029 
1030 /**
1031  * @brief Select an integer
1032  * @param[out] r Pointer to the destination integer
1033  * @param[in] a Pointer to the first source integer
1034  * @param[in] b Pointer to the second source integer
1035  * @param[in] c Condition variable
1036  * @param[in] n Size of the integers, in bytes
1037  **/
1038 
1039 void ed25519SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b,
1040  uint8_t c, uint_t n)
1041 {
1042  uint_t i;
1043  uint8_t mask;
1044 
1045  //The mask is the all-1 or all-0 word
1046  mask = c - 1;
1047 
1048  //Select between A and B
1049  for(i = 0; i < n; i++)
1050  {
1051  //Constant time implementation
1052  r[i] = (a[i] & mask) | (b[i] & ~mask);
1053  }
1054 }
1055 
1056 
1057 /**
1058  * @brief Compare integers
1059  * @param[in] a Pointer to the first integer
1060  * @param[in] b Pointer to the second integer
1061  * @param[in] n Size of the integers, in bytes
1062  * @return The function returns 0 if the A = B, else 1
1063  **/
1064 
1065 uint8_t ed25519CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
1066 {
1067  uint_t i;
1068  uint8_t mask;
1069 
1070  //Initialize mask
1071  mask = 0;
1072 
1073  //Compare A and B
1074  for(i = 0; i < n; i++)
1075  {
1076  //Constant time implementation
1077  mask |= a[i] ^ b[i];
1078  }
1079 
1080  //Return 0 if A = B, else 1
1081  return ((uint8_t) (mask | (~mask + 1))) >> 7;
1082 }
1083 
1084 #endif
Ed25519 elliptic curve (constant-time implementation)
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:749
uint8_t b
Definition: nbns_common.h:104
__weak_func void ed25519Mul(Ed25519SubState *state, Ed25519Point *r, const uint8_t *k, const Ed25519Point *p)
Scalar multiplication (regular calculation)
Definition: ed25519.c:574
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:917
#define PrngAlgo
Definition: crypto.h:980
#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:804
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:1039
int32_t c[9]
Definition: ed25519.h:80
uint8_t data[]
Definition: ethernet.h:224
const void * buffer
Definition: crypto.h:1025
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:845
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:656
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:622
uint32_t curve25519Comp(const int32_t *a, const int32_t *b)
Compare integers.
Definition: curve25519.c:870
Ed25519SubState subState
Definition: ed25519.h:98
int32_t g[9]
Definition: ed25519.h:84
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:234
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
error_t
Error codes.
Definition: error.h:43
void ed25519Encode(Ed25519Point *p, uint8_t *data)
Point encoding.
Definition: ed25519.c:774
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:943
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:910
int32_t t[9]
Definition: ed25519.h:66
Sha512Context sha512Context
Definition: ed25519.h:95
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:1018
Ed25519Point v
Definition: ed25519.h:77
__weak_func void curve25519Sqr(int32_t *r, const int32_t *a)
Modular squaring.
Definition: curve25519.c:571
uint8_t mask
Definition: web_socket.h:319
void curve25519Copy(int32_t *a, const int32_t *b)
Copy an integer.
Definition: curve25519.c:798
uint8_t u
Definition: lldp_ext_med.h:213
int32_t h[9]
Definition: ed25519.h:85
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:963
void ed25519RedInt(uint8_t *r, const uint8_t *a)
Reduce an integer modulo L.
Definition: ed25519.c:875
#define CURVE25519_BIT_LEN
Definition: curve25519.h:45
Ed25519SubState subState
Definition: ed25519.h:115
void curve25519SetInt(int32_t *a, int32_t b)
Set integer value.
Definition: curve25519.c:57
Data chunk descriptor.
Definition: crypto.h:1024
void curve25519Inv(int32_t *r, const int32_t *a)
Modular multiplicative inverse.
Definition: curve25519.c:606
void curve25519Sub(int32_t *r, const int32_t *a, const int32_t *b)
Modular subtraction.
Definition: curve25519.c:173
int32_t x[9]
Definition: ed25519.h:63
error_t ed25519GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataChunk *message, uint_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed25519.c:268
Sha512Context sha512Context
Definition: ed25519.h:125
uint8_t n
Ed25519SubState subState
Definition: ed25519.h:131
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:833
int32_t f[9]
Definition: ed25519.h:83
Sha512Context sha512Context
Definition: ed25519.h:108
void sha512Init(Sha512Context *context)
Initialize SHA-512 message digest context.
Curve25519 elliptic curve (constant-time implementation)
int32_t e[9]
Definition: ed25519.h:82
#define cryptoAllocMem(size)
Definition: crypto.h:828
size_t length
Definition: crypto.h:1026
void curve25519AddInt(int32_t *r, const int32_t *a, int32_t b)
Modular addition.
Definition: curve25519.c:144
void curve25519Import(int32_t *a, const uint8_t *data)
Import an octet string.
Definition: curve25519.c:896
error_t ed25519GeneratePublicKey(const uint8_t *privateKey, uint8_t *publicKey)
Derive the public key from an EdDSA private key.
Definition: ed25519.c:168
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:427
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:267
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:138
void ed25519Double(Ed25519SubState *state, Ed25519Point *r, const Ed25519Point *p)
Point doubling.
Definition: ed25519.c:733
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:1065
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:935
@ 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:686
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:238
error_t ed25519VerifySignatureEx(const uint8_t *publicKey, const DataChunk *message, uint_t messageLen, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed25519.c:460