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.0
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] contextLen Length of the context, in bytes
454  * @param[in] flag Prehash flag for Ed25519ph scheme
455  * @param[in] signature EdDSA signature (64 bytes)
456  * @return Error code
457  **/
458 
459 error_t ed25519VerifySignatureEx(const uint8_t *publicKey,
460  const DataChunk *message, uint_t messageLen, const void *context,
461  uint8_t contextLen, uint8_t flag, const uint8_t *signature)
462 {
463  uint_t i;
464  uint32_t ret;
465 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
467 #else
469 #endif
470 
471  //Check parameters
472  if(publicKey == NULL || message == NULL || signature == NULL)
474 
475  //The context is an optional constant string specified by the protocol using
476  //it (refer to RFC 8032, section 8.3)
477  if(context == NULL && contextLen != 0)
479 
480 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
481  //Allocate working state
483  //Failed to allocate memory?
484  if(state == NULL)
485  return ERROR_OUT_OF_MEMORY;
486 #endif
487 
488  //First split the signature into two 32-octet halves. Decode the first
489  //half as a point R
490  osMemcpy(state->r, signature, ED25519_SIGNATURE_LEN / 2);
491 
492  //Decode the second half as an integer S, in the range 0 <= s < L
493  osMemcpy(state->s, signature + ED25519_SIGNATURE_LEN / 2,
495 
496  //Ed25519 signatures are not malleable due to the verification check that
497  //decoded S is smaller than L (refer to RFC 8032, section 8.4)
498  ret = 1 ^ ed25519SubInt(state->p, state->s, ED25519_L,
500 
501  //Decode the public key A as point A'
502  ret |= ed25519Decode(&state->a, publicKey);
503 
504  //Initialize SHA-512 context
505  sha512Init(&state->sha512Context);
506 
507  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
508  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
509  //where x is in range 0-255 and y is an octet string of at most 255 octets
510  if(context != NULL || flag != 0)
511  {
512  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
513  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
514  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
515  sha512Update(&state->sha512Context, context, contextLen);
516  }
517 
518  //Digest R || A
519  sha512Update(&state->sha512Context, state->r, ED25519_SIGNATURE_LEN / 2);
521 
522  //The message is split over multiple chunks
523  for(i = 0; i < messageLen; i++)
524  {
525  //Digest current chunk
526  sha512Update(&state->sha512Context, message[i].buffer,
527  message[i].length);
528  }
529 
530  //Compute SHA512(dom2(F, C) || R || A || PH(M)) and interpret the 64-octet
531  //digest as a little-endian integer k
532  sha512Final(&state->sha512Context, state->k);
533 
534  //For efficiency, reduce k modulo L first
535  ed25519RedInt(state->k, state->k);
536 
537  //Compute -A'
538  curve25519Sub(state->a.x, ED25519_ZERO, state->a.x);
539  curve25519Sub(state->a.t, ED25519_ZERO, state->a.t);
540 
541  //Compute the point P = s * B - k * A'
542  ed25519TwinMul(&state->subState, &state->a, state->s, &ED25519_B, state->k,
543  &state->a);
544 
545  //Encode of the resulting point P
546  ed25519Encode(&state->a, state->p);
547 
548  //If P = R, then the signature is verified. If P does not equal R,
549  //then the message or the signature may have been modified
550  ret |= ed25519CompInt(state->p, signature, ED25519_SIGNATURE_LEN / 2);
551 
552  //Erase working state
553  osMemset(state, 0, sizeof(Ed25519VerifySignatureState));
554 
555 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
556  //Release working state
557  cryptoFreeMem(state);
558 #endif
559 
560  //Return status code
561  return (ret == 0) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
562 }
563 
564 
565 /**
566  * @brief Scalar multiplication (regular calculation)
567  * @param[in] state Pointer to the working state
568  * @param[out] r Resulting point R = k * P
569  * @param[in] k Input scalar
570  * @param[in] p Input point
571  **/
572 
573 __weak_func void ed25519Mul(Ed25519SubState *state, Ed25519Point *r,
574  const uint8_t *k, const Ed25519Point *p)
575 {
576  int_t i;
577  uint8_t b;
578 
579  //The neutral element is represented by (0, 1, 1, 0)
580  curve25519SetInt(state->u.x, 0);
581  curve25519SetInt(state->u.y, 1);
582  curve25519SetInt(state->u.z, 1);
583  curve25519SetInt(state->u.t, 0);
584 
585  //Perform scalar multiplication
586  for(i = CURVE25519_BIT_LEN - 1; i >= 0; i--)
587  {
588  //The scalar is processed in a left-to-right fashion
589  b = (k[i / 8] >> (i % 8)) & 1;
590 
591  //Compute U = 2 * U
592  ed25519Double(state, &state->u, &state->u);
593  //Compute V = U + P
594  ed25519Add(state, &state->v, &state->u, p);
595 
596  //If b is set, then U = V
597  curve25519Select(state->u.x, state->u.x, state->v.x, b);
598  curve25519Select(state->u.y, state->u.y, state->v.y, b);
599  curve25519Select(state->u.z, state->u.z, state->v.z, b);
600  curve25519Select(state->u.t, state->u.t, state->v.t, b);
601  }
602 
603  //Copy result
604  curve25519Copy(r->x, state->u.x);
605  curve25519Copy(r->y, state->u.y);
606  curve25519Copy(r->z, state->u.z);
607  curve25519Copy(r->t, state->u.t);
608 }
609 
610 
611 /**
612  * @brief Twin multiplication
613  * @param[in] state Pointer to the working state
614  * @param[out] r Resulting point R = k1 * P + k2 * Q
615  * @param[in] k1 First input scalar
616  * @param[in] p First input point
617  * @param[in] k2 Second input scalar
618  * @param[in] q Second input point
619  **/
620 
621 __weak_func void ed25519TwinMul(Ed25519SubState *state, Ed25519Point *r,
622  const uint8_t *k1, const Ed25519Point *p, const uint8_t *k2,
623  const Ed25519Point *q)
624 {
625  int_t i;
626  uint8_t b1;
627  uint8_t b2;
628 
629  //Pre-compute V = P + Q
630  ed25519Add(state, &state->v, p, q);
631 
632  //The neutral element is represented by (0, 1, 1, 0)
633  curve25519SetInt(state->u.x, 0);
634  curve25519SetInt(state->u.y, 1);
635  curve25519SetInt(state->u.z, 1);
636  curve25519SetInt(state->u.t, 0);
637 
638  //Calculate both multiplications at the same time
639  for(i = CURVE25519_BIT_LEN - 1; i >= 0; i--)
640  {
641  //The scalars are processed in a left-to-right fashion
642  b1 = (k1[i / 8] >> (i % 8)) & 1;
643  b2 = (k2[i / 8] >> (i % 8)) & 1;
644 
645  //Compute U = 2 * U
646  ed25519Double(state, &state->u, &state->u);
647 
648  //Check k1(i) and k2(i)
649  if(b1 == 1 && b2 == 0)
650  {
651  //Compute U = U + P
652  ed25519Add(state, &state->u, &state->u, p);
653  }
654  else if(b1 == 0 && b2 == 1)
655  {
656  //Compute U = U + Q
657  ed25519Add(state, &state->u, &state->u, q);
658  }
659  else if(b1 == 1 && b2 == 1)
660  {
661  //Compute U = U + V
662  ed25519Add(state, &state->u, &state->u, &state->v);
663  }
664  else
665  {
666  }
667  }
668 
669  //Copy result
670  curve25519Copy(r->x, state->u.x);
671  curve25519Copy(r->y, state->u.y);
672  curve25519Copy(r->z, state->u.z);
673  curve25519Copy(r->t, state->u.t);
674 }
675 
676 
677 /**
678  * @brief Point addition
679  * @param[in] state Pointer to the working state
680  * @param[out] r Resulting point R = P + Q
681  * @param[in] p First operand
682  * @param[in] q Second operand
683  **/
684 
686  const Ed25519Point *q)
687 {
688  //Compute A = (Y1 + X1) * (Y2 + X2)
689  curve25519Add(state->c, p->y, p->x);
690  curve25519Add(state->d, q->y, q->x);
691  curve25519Mul(state->a, state->c, state->d);
692 
693  //Compute B = (Y1 - X1) * (Y2 - X2)
694  curve25519Sub(state->c, p->y, p->x);
695  curve25519Sub(state->d, q->y, q->x);
696  curve25519Mul(state->b, state->c, state->d);
697 
698  //Compute C = 2 * Z1 * Z2
699  curve25519Mul(state->c, p->z, q->z);
700  curve25519Add(state->c, state->c, state->c);
701 
702  //Compute D = (2 * d) * T1 * T2
703  curve25519Mul(state->d, p->t, q->t);
704  curve25519Mul(state->d, state->d, ED25519_2D);
705 
706  //Compute E = A + B
707  curve25519Add(state->e, state->a, state->b);
708  //Compute F = A - B
709  curve25519Sub(state->f, state->a, state->b);
710  //Compute G = C + D
711  curve25519Add(state->g, state->c, state->d);
712  //Compute H = C - D
713  curve25519Sub(state->h, state->c, state->d);
714  //Compute X3 = F * H
715  curve25519Mul(r->x, state->f, state->h);
716  //Compute Y3 = E * G
717  curve25519Mul(r->y, state->e, state->g);
718  //Compute Z3 = G * H
719  curve25519Mul(r->z, state->g, state->h);
720  //Compute T3 = E * F
721  curve25519Mul(r->t, state->e, state->f);
722 }
723 
724 
725 /**
726  * @brief Point doubling
727  * @param[in] state Pointer to the working state
728  * @param[out] r Resulting point R = 2 * P
729  * @param[in] p Input point P
730  **/
731 
733  const Ed25519Point *p)
734 {
735  //Compute A = X1^2
736  curve25519Sqr(state->a, p->x);
737  //Compute B = Y1^2
738  curve25519Sqr(state->b, p->y);
739 
740  //Compute C = 2 * Z1^2
741  curve25519Sqr(state->c, p->z);
742  curve25519Add(state->c, state->c, state->c);
743 
744  //Compute E = A + B
745  curve25519Add(state->e, state->a, state->b);
746 
747  //Compute F = E - (X1 + Y1)^2
748  curve25519Add(state->f, p->x, p->y);
749  curve25519Sqr(state->f, state->f);
750  curve25519Sub(state->f, state->e, state->f);
751 
752  //Compute G = A - B
753  curve25519Sub(state->g, state->a, state->b);
754  //Compute H = C + G
755  curve25519Add(state->h, state->c, state->g);
756  //Compute X3 = F * H
757  curve25519Mul(r->x, state->f, state->h);
758  //Compute Y3 = E * G
759  curve25519Mul(r->y, state->e, state->g);
760  //Compute Z3 = G * H
761  curve25519Mul(r->z, state->g, state->h);
762  //Compute T3 = E * F
763  curve25519Mul(r->t, state->e, state->f);
764 }
765 
766 
767 /**
768  * @brief Point encoding
769  * @param[in] p Point representation
770  * @param[out] data Octet string resulting from the conversion
771  **/
772 
774 {
775  //Retrieve affine representation
776  curve25519Inv(p->z, p->z);
777  curve25519Mul(p->x, p->x, p->z);
778  curve25519Mul(p->y, p->y, p->z);
779  curve25519SetInt(p->z, 1);
780  curve25519Mul(p->t, p->x, p->y);
781 
782  //Reduce non-canonical values
783  curve25519Canonicalize(p->x, p->x);
784  curve25519Canonicalize(p->y, p->y);
785  curve25519Canonicalize(p->t, p->t);
786 
787  //Encode the y-coordinate as a little-endian string of 32 octets. The most
788  //significant bit of the final octet is always zero
789  curve25519Export(p->y, data);
790 
791  //Copy the least significant bit of the x-coordinate to the most significant
792  //bit of the final octet
793  data[31] |= (p->x[0] & 1) << 7;
794 }
795 
796 
797 /**
798  * @brief Point decoding
799  * @param[out] p Point representation
800  * @param[in] data Octet string to be converted
801  **/
802 
803 uint32_t ed25519Decode(Ed25519Point *p, const uint8_t *data)
804 {
805  uint_t i;
806  uint8_t x0;
807  uint32_t ret;
808  int32_t temp;
809  int32_t u[9];
810  int32_t v[9];
811 
812  //First, interpret the string as an integer in little-endian representation.
813  //Bit 255 of this number is the least significant bit of the x-coordinate
814  //and denote this value x_0
815  x0 = data[31] >> 7;
816 
817  //The y-coordinate is recovered simply by clearing this bit
818  curve25519Import(p->y, data);
819  p->y[8] &= 0x007FFFFF;
820 
821  //Compute u = y + 19
822  for(temp = 19, i = 0; i < 8; i++)
823  {
824  temp += p->y[i];
825  u[i] = temp & 0x1FFFFFFF;
826  temp >>= 29;
827  }
828 
829  temp += p->y[8];
830  u[8] = temp & 0x007FFFFF;
831  temp >>= 23;
832 
833  //If the y-coordinate is >= p, decoding fails
834  ret = CRYPTO_TEST_NZ_32(temp);
835 
836  //The curve equation implies x^2 = (y^2 - 1) / (d * y^2 + 1) mod p
837  //Let u = y^2 - 1 and v = d * y^2 + 1
838  curve25519Sqr(v, p->y);
839  curve25519SubInt(u, v, 1);
840  curve25519Mul(v, v, ED25519_D);
841  curve25519AddInt(v, v, 1);
842 
843  //Compute u = sqrt(u / v)
844  ret |= curve25519Sqrt(u, u, v);
845 
846  //If x = 0, and x_0 = 1, decoding fails
847  ret |= (curve25519Comp(u, ED25519_ZERO) ^ 1) & x0;
848 
849  //Compute v = p - u
850  curve25519Sub(v, ED25519_ZERO, u);
851 
852  //Finally, use the x_0 bit to select the right square root
853  curve25519Select(p->x, u, v, (x0 ^ u[0]) & 1);
854 
855  //Calculate extended point representation
856  curve25519SetInt(p->z, 1);
857  curve25519Mul(p->t, p->x, p->y);
858 
859  //Return 0 if the point has been successfully decoded, else 1
860  return ret;
861 }
862 
863 
864 /**
865  * @brief Reduce an integer modulo L
866  *
867  * This function implements Barrett reduction with b = 2^8 and k = 32. The
868  * algorithm requires the precomputation of the quantity mu = b^(2 * k) / L
869  *
870  * @param[out] r Resulting integer R = A mod L
871  * @param[in] a An integer such as 0 <= A < b^(2 * k)
872  **/
873 
874 void ed25519RedInt(uint8_t *r, const uint8_t *a)
875 {
876  uint8_t c;
877  uint8_t u[33];
878  uint8_t v[33];
879 
880  //Compute the estimate of the quotient u = ((a / b^(k - 1)) * mu) / b^(k + 1)
881  ed25519MulInt(NULL, u, a + 31, ED25519_MU, 33);
882  //Compute v = u * L mod b^(k + 1)
883  ed25519MulInt(v, NULL, u, ED25519_L, 33);
884 
885  //Compute the estimate of the remainder u = a mod b^(k + 1) - v
886  //If u < 0, then u = u + b^(k + 1)
887  ed25519SubInt(u, a, v, 33);
888 
889  //This estimation implies that at most two subtractions of L are required to
890  //obtain the correct remainder r
891  c = ed25519SubInt(v, u, ED25519_L, 33);
892  ed25519SelectInt(u, v, u, c, 33);
893  c = ed25519SubInt(v, u, ED25519_L, 33);
894  ed25519SelectInt(u, v, u, c, 33);
895 
896  //Copy the resulting remainder
897  ed25519CopyInt(r, u, 32);
898 }
899 
900 
901 /**
902  * @brief Addition of two integers
903  * @param[out] r Resulting integer R = A + B
904  * @param[in] a An integer such as 0 <= A < (2^8)^n
905  * @param[in] b An integer such as 0 <= B < (2^8)^n
906  * @param[in] n Size of the operands, in bytes
907  **/
908 
909 void ed25519AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
910 {
911  uint_t i;
912  uint16_t temp;
913 
914  //Compute R = A + B
915  for(temp = 0, i = 0; i < n; i++)
916  {
917  temp += a[i];
918  temp += b[i];
919  r[i] = temp & 0xFF;
920  temp >>= 8;
921  }
922 }
923 
924 
925 /**
926  * @brief Subtraction 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  * @return 1 if the result is negative, else 0
932  **/
933 
934 uint8_t ed25519SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
935 {
936  uint_t i;
937  int16_t temp;
938 
939  //Compute R = A - B
940  for(temp = 0, i = 0; i < n; i++)
941  {
942  temp += a[i];
943  temp -= b[i];
944  r[i] = temp & 0xFF;
945  temp >>= 8;
946  }
947 
948  //Return 1 if the result of the subtraction is negative
949  return temp & 1;
950 }
951 
952 
953 /**
954  * @brief Multiplication of two integers
955  * @param[out] rl Low part of the result R = (A * B) mod (2^8)^n
956  * @param[out] rh High part of the result R = (A * B) / (2^8)^n
957  * @param[in] a An integer such as 0 <= A < (2^8)^n
958  * @param[in] b An integer such as 0 <= B < (2^8)^n
959  * @param[in] n Size of the operands, in bytes
960  **/
961 
962 void ed25519MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a,
963  const uint8_t *b, uint_t n)
964 {
965  uint_t i;
966  uint_t j;
967  uint32_t temp;
968 
969  //Compute the low part of the multiplication
970  for(temp = 0, i = 0; i < n; i++)
971  {
972  //The Comba's algorithm computes the products, column by column
973  for(j = 0; j <= i; j++)
974  {
975  temp += (uint16_t) a[j] * b[i - j];
976  }
977 
978  //At the bottom of each column, the final result is written to memory
979  if(rl != NULL)
980  {
981  rl[i] = temp & 0xFF;
982  }
983 
984  //Propagate the carry upwards
985  temp >>= 8;
986  }
987 
988  //Check whether the high part of the multiplication should be calculated
989  if(rh != NULL)
990  {
991  //Compute the high part of the multiplication
992  for(i = n; i < (2 * n); i++)
993  {
994  //The Comba's algorithm computes the products, column by column
995  for(j = i + 1 - n; j < n; j++)
996  {
997  temp += (uint16_t) a[j] * b[i - j];
998  }
999 
1000  //At the bottom of each column, the final result is written to memory
1001  rh[i - n] = temp & 0xFF;
1002 
1003  //Propagate the carry upwards
1004  temp >>= 8;
1005  }
1006  }
1007 }
1008 
1009 
1010 /**
1011  * @brief Copy an integer
1012  * @param[out] a Pointer to the destination integer
1013  * @param[in] b Pointer to the source integer
1014  * @param[in] n Size of the integers, in bytes
1015  **/
1016 
1017 void ed25519CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
1018 {
1019  uint_t i;
1020 
1021  //Copy the value of the integer
1022  for(i = 0; i < n; i++)
1023  {
1024  a[i] = b[i];
1025  }
1026 }
1027 
1028 
1029 /**
1030  * @brief Select an integer
1031  * @param[out] r Pointer to the destination integer
1032  * @param[in] a Pointer to the first source integer
1033  * @param[in] b Pointer to the second source integer
1034  * @param[in] c Condition variable
1035  * @param[in] n Size of the integers, in bytes
1036  **/
1037 
1038 void ed25519SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b,
1039  uint8_t c, uint_t n)
1040 {
1041  uint_t i;
1042  uint8_t mask;
1043 
1044  //The mask is the all-1 or all-0 word
1045  mask = c - 1;
1046 
1047  //Select between A and B
1048  for(i = 0; i < n; i++)
1049  {
1050  //Constant time implementation
1051  r[i] = (a[i] & mask) | (b[i] & ~mask);
1052  }
1053 }
1054 
1055 
1056 /**
1057  * @brief Compare integers
1058  * @param[in] a Pointer to the first integer
1059  * @param[in] b Pointer to the second integer
1060  * @param[in] n Size of the integers, in bytes
1061  * @return The function returns 0 if the A = B, else 1
1062  **/
1063 
1064 uint8_t ed25519CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
1065 {
1066  uint_t i;
1067  uint8_t mask;
1068 
1069  //Initialize mask
1070  mask = 0;
1071 
1072  //Compare A and B
1073  for(i = 0; i < n; i++)
1074  {
1075  //Constant time implementation
1076  mask |= a[i] ^ b[i];
1077  }
1078 
1079  //Return 0 if A = B, else 1
1080  return ((uint8_t) (mask | (~mask + 1))) >> 7;
1081 }
1082 
1083 #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:573
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:973
#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:803
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:1038
int32_t c[9]
Definition: ed25519.h:80
uint8_t data[]
Definition: ethernet.h:222
const void * buffer
Definition: crypto.h:1018
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:621
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:773
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:936
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:909
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:1017
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:962
void ed25519RedInt(uint8_t *r, const uint8_t *a)
Reduce an integer modulo L.
Definition: ed25519.c:874
#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:1017
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:826
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:821
size_t length
Definition: crypto.h:1019
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:732
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:1064
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:934
@ 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:685
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:459