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-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "ecc/ec_curves.h"
37 #include "ecc/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  0x8F25D51A, 0xC9562D60, 0x9525A7B2, 0x692CC760,
49  0xFDD6DC5C, 0xC0A4E231, 0xCD6E53FE, 0x216936D3
50  },
51  {
52  0x66666658, 0x66666666, 0x66666666, 0x66666666,
53  0x66666666, 0x66666666, 0x66666666, 0x66666666
54  },
55  {
56  0x00000001, 0x00000000, 0x00000000, 0x00000000,
57  0x00000000, 0x00000000, 0x00000000, 0x00000000
58  },
59  {
60  0xA5B7DDA3, 0x6DDE8AB3, 0x775152F5, 0x20F09F80,
61  0x64ABE37D, 0x66EA4E8E, 0xD78B7665, 0x67875F0F
62  }
63 };
64 
65 //Zero (constant)
66 static const uint32_t ED25519_ZERO[8] =
67 {
68  0x00000000, 0x00000000, 0x00000000, 0x00000000,
69  0x00000000, 0x00000000, 0x00000000, 0x00000000
70 };
71 
72 //Curve parameter d
73 static const uint32_t ED25519_D[8] =
74 {
75  0x135978A3, 0x75EB4DCA, 0x4141D8AB, 0x00700A4D,
76  0x7779E898, 0x8CC74079, 0x2B6FFE73, 0x52036CEE
77 };
78 
79 //Pre-computed value of 2 * d
80 static const uint32_t ED25519_2D[8] =
81 {
82  0x26B2F159, 0xEBD69B94, 0x8283B156, 0x00E0149A,
83  0xEEF3D130, 0x198E80F2, 0x56DFFCE7, 0x2406D9DC
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  uint8_t *s;
171 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
172  Ed25519State *state;
173 #else
174  Ed25519State state[1];
175 #endif
176 
177  //Check parameters
178  if(privateKey == NULL || publicKey == NULL)
180 
181 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
182  //Allocate working state
183  state = cryptoAllocMem(sizeof(Ed25519State));
184  //Failed to allocate memory?
185  if(state == NULL)
186  return ERROR_OUT_OF_MEMORY;
187 #endif
188 
189  //Hash the 32-byte private key using SHA-512
190  sha512Init(&state->sha512Context);
191  sha512Update(&state->sha512Context, privateKey, ED25519_PRIVATE_KEY_LEN);
192  sha512Final(&state->sha512Context, NULL);
193 
194  //Only the lower 32 bytes are used for generating the public key. Interpret
195  //the buffer as the little-endian integer, forming a secret scalar s
196  s = state->sha512Context.digest;
197 
198  //The lowest three bits of the first octet are cleared, the highest bit
199  //of the last octet is cleared, and the second highest bit of the last
200  //octet is set
201  s[0] &= 0xF8;
202  s[31] &= 0x7F;
203  s[31] |= 0x40;
204 
205  //Perform a fixed-base scalar multiplication s * B
206  ed25519Mul(state, &state->sb, s, &ED25519_B);
207  //The public key A is the encoding of the point s * B
208  ed25519Encode(&state->sb, publicKey);
209 
210  //Erase working state
211  osMemset(state, 0, sizeof(Ed25519State));
212 
213 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
214  //Release working state
215  cryptoFreeMem(state);
216 #endif
217 
218  //Successful processing
219  return NO_ERROR;
220 }
221 
222 
223 /**
224  * @brief EdDSA signature generation
225  * @param[in] privateKey Signer's EdDSA private key (32 bytes)
226  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
227  * @param[in] message Pointer to the message to be signed
228  * @param[in] messageLen Length of the message, in bytes
229  * @param[in] context Constant string specified by the protocol using it
230  * @param[in] contextLen Length of the context, in bytes
231  * @param[in] flag Prehash flag for Ed25519ph scheme
232  * @param[out] signature EdDSA signature (64 bytes)
233  * @return Error code
234  **/
235 
236 error_t ed25519GenerateSignature(const uint8_t *privateKey,
237  const uint8_t *publicKey, const void *message, size_t messageLen,
238  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
239 {
240  error_t error;
241  DataChunk messageChunks[2];
242 
243  //The message fits in a single chunk
244  messageChunks[0].buffer = message;
245  messageChunks[0].length = messageLen;
246  messageChunks[1].buffer = NULL;
247  messageChunks[1].length = 0;
248 
249  //Ed25519 signature generation
250  error = ed25519GenerateSignatureEx(privateKey, publicKey, messageChunks,
251  context, contextLen, flag, signature);
252 
253  //Return status code
254  return error;
255 }
256 
257 
258 /**
259  * @brief EdDSA signature generation
260  * @param[in] privateKey Signer's EdDSA private key (32 bytes)
261  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
262  * @param[in] messageChunks Array of data chunks representing the message
263  to be signed
264  * @param[in] context Constant string specified by the protocol using it
265  * @param[in] contextLen Length of the context, in bytes
266  * @param[in] flag Prehash flag for Ed25519ph scheme
267  * @param[out] signature EdDSA signature (64 bytes)
268  * @return Error code
269  **/
270 
271 error_t ed25519GenerateSignatureEx(const uint8_t *privateKey,
272  const uint8_t *publicKey, const DataChunk *messageChunks,
273  const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
274 {
275  uint_t i;
276  uint8_t c;
277 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
278  Ed25519State *state;
279 #else
280  Ed25519State state[1];
281 #endif
282 
283  //Check parameters
284  if(privateKey == NULL || signature == NULL)
286  if(messageChunks == NULL)
288  if(context == NULL && contextLen != 0)
290 
291 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
292  //Allocate working state
293  state = cryptoAllocMem(sizeof(Ed25519State));
294  //Failed to allocate memory?
295  if(state == NULL)
296  return ERROR_OUT_OF_MEMORY;
297 #endif
298 
299  //Hash the private key, 32 octets, using SHA-512. Let h denote the
300  //resulting digest
301  sha512Init(&state->sha512Context);
302  sha512Update(&state->sha512Context, privateKey, ED25519_PRIVATE_KEY_LEN);
303  sha512Final(&state->sha512Context, NULL);
304 
305  //Construct the secret scalar s from the first half of the digest
306  osMemcpy(state->s, state->sha512Context.digest, 32);
307 
308  //The lowest three bits of the first octet are cleared, the highest bit
309  //of the last octet is cleared, and the second highest bit of the last
310  //octet is set
311  state->s[0] &= 0xF8;
312  state->s[31] &= 0x7F;
313  state->s[31] |= 0x40;
314 
315  //The public key is optional
316  if(publicKey == NULL)
317  {
318  //Perform a fixed-base scalar multiplication s * B
319  ed25519Mul(state, &state->sb, state->s, &ED25519_B);
320  //The public key A is the encoding of the point s * B
321  ed25519Encode(&state->sb, state->k);
322  //Point to the resulting public key
323  publicKey = state->k;
324  }
325 
326  //Let prefix denote the second half of the hash digest
327  osMemcpy(state->p, state->sha512Context.digest + 32, 32);
328 
329  //Initialize SHA-512 context
330  sha512Init(&state->sha512Context);
331 
332  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
333  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
334  //where x is in range 0-255 and y is an octet string of at most 255 octets
335  if(context != NULL || flag != 0)
336  {
337  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
338  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
339  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
340  sha512Update(&state->sha512Context, context, contextLen);
341  }
342 
343  //Digest prefix
344  sha512Update(&state->sha512Context, state->p, 32);
345 
346  //The message is split over multiple chunks
347  for(i = 0; messageChunks[i].buffer != NULL; i++)
348  {
349  //Digest current chunk
350  sha512Update(&state->sha512Context, messageChunks[i].buffer,
351  messageChunks[i].length);
352  }
353 
354  //Compute SHA-512(dom2(F, C) || prefix || PH(M))
355  sha512Final(&state->sha512Context, NULL);
356 
357  //Reduce the 64-octet digest as a little-endian integer r
358  ed25519RedInt(state->r, state->sha512Context.digest);
359  //Compute the point r * B
360  ed25519Mul(state, &state->rb, state->r, &ED25519_B);
361  //Let the string R be the encoding of this point
362  ed25519Encode(&state->rb, signature);
363 
364  //Initialize SHA-512 context
365  sha512Init(&state->sha512Context);
366 
367  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
368  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
369  //where x is in range 0-255 and y is an octet string of at most 255 octets
370  if(context != NULL || flag != 0)
371  {
372  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
373  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
374  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
375  sha512Update(&state->sha512Context, context, contextLen);
376  }
377 
378  //Digest R || A
379  sha512Update(&state->sha512Context, signature, ED25519_SIGNATURE_LEN / 2);
381 
382  //The message is split over multiple chunks
383  for(i = 0; messageChunks[i].buffer != NULL; i++)
384  {
385  //Digest current chunk
386  sha512Update(&state->sha512Context, messageChunks[i].buffer,
387  messageChunks[i].length);
388  }
389 
390  //Compute SHA512(dom2(F, C) || R || A || PH(M)) and interpret the 64-octet
391  //digest as a little-endian integer k
392  sha512Final(&state->sha512Context, state->k);
393 
394  //Compute S = (r + k * s) mod L. For efficiency, reduce k modulo L first
395  ed25519RedInt(state->p, state->k);
396  ed25519MulInt(state->k, state->k + 32, state->p, state->s, 32);
397  ed25519RedInt(state->p, state->k);
398  ed25519AddInt(state->s, state->p, state->r, 32);
399 
400  //Perform modular reduction
401  c = ed25519SubInt(state->p, state->s, ED25519_L, 32);
402  ed25519SelectInt(signature + 32, state->p, state->s, c, 32);
403 
404  //Erase working state
405  osMemset(state, 0, sizeof(Ed25519State));
406 
407 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
408  //Release working state
409  cryptoFreeMem(state);
410 #endif
411 
412  //Successful processing
413  return NO_ERROR;
414 }
415 
416 
417 /**
418  * @brief EdDSA signature verification
419  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
420  * @param[in] message Message whose signature is to be verified
421  * @param[in] messageLen Length of the message, in bytes
422  * @param[in] context Constant string specified by the protocol using it
423  * @param[in] contextLen Length of the context, in bytes
424  * @param[in] flag Prehash flag for Ed25519ph scheme
425  * @param[in] signature EdDSA signature (64 bytes)
426  * @return Error code
427  **/
428 
429 error_t ed25519VerifySignature(const uint8_t *publicKey, const void *message,
430  size_t messageLen, const void *context, uint8_t contextLen, uint8_t flag,
431  const uint8_t *signature)
432 {
433  error_t error;
434  DataChunk messageChunks[2];
435 
436  //The message fits in a single chunk
437  messageChunks[0].buffer = message;
438  messageChunks[0].length = messageLen;
439  messageChunks[1].buffer = NULL;
440  messageChunks[1].length = 0;
441 
442  //Ed25519 signature verification
443  error = ed25519VerifySignatureEx(publicKey, messageChunks, context,
444  contextLen, flag, signature);
445 
446  //Return status code
447  return error;
448 }
449 
450 
451 /**
452  * @brief EdDSA signature verification
453  * @param[in] publicKey Signer's EdDSA public key (32 bytes)
454  * @param[in] messageChunks Array of data chunks representing the message
455  * whose signature is to be verified
456  * @param[in] context Constant string specified by the protocol using it
457  * @param[in] contextLen Length of the context, in bytes
458  * @param[in] flag Prehash flag for Ed25519ph scheme
459  * @param[in] signature EdDSA signature (64 bytes)
460  * @return Error code
461  **/
462 
463 error_t ed25519VerifySignatureEx(const uint8_t *publicKey,
464  const DataChunk *messageChunks, const void *context,
465  uint8_t contextLen, uint8_t flag, const uint8_t *signature)
466 {
467  uint_t i;
468  uint32_t ret;
469 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
470  Ed25519State *state;
471 #else
472  Ed25519State state[1];
473 #endif
474 
475  //Check parameters
476  if(publicKey == NULL || signature == NULL)
478  if(messageChunks == NULL)
480  if(context == NULL && contextLen != 0)
482 
483 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
484  //Allocate working state
485  state = cryptoAllocMem(sizeof(Ed25519State));
486  //Failed to allocate memory?
487  if(state == NULL)
488  return ERROR_OUT_OF_MEMORY;
489 #endif
490 
491  //First split the signature into two 32-octet halves. Decode the first
492  //half as a point R
493  osMemcpy(state->r, signature, ED25519_SIGNATURE_LEN / 2);
494 
495  //Decode the second half as an integer S, in the range 0 <= s < L
496  osMemcpy(state->s, signature + ED25519_SIGNATURE_LEN / 2,
498 
499  //Ed25519 signatures are not malleable due to the verification check that
500  //decoded S is smaller than L (refer to RFC 8032, section 8.4)
501  ret = 1 ^ ed25519SubInt(state->p, state->s, ED25519_L,
503 
504  //Decode the public key A as point A'
505  ret |= ed25519Decode(&state->ka, publicKey);
506 
507  //Initialize SHA-512 context
508  sha512Init(&state->sha512Context);
509 
510  //For Ed25519ctx and Ed25519ph schemes, dom2(x, y) is the octet string
511  //"SigEd25519 no Ed25519 collisions" || octet(x) || octet(OLEN(y)) || y,
512  //where x is in range 0-255 and y is an octet string of at most 255 octets
513  if(context != NULL || flag != 0)
514  {
515  sha512Update(&state->sha512Context, "SigEd25519 no Ed25519 collisions", 32);
516  sha512Update(&state->sha512Context, &flag, sizeof(uint8_t));
517  sha512Update(&state->sha512Context, &contextLen, sizeof(uint8_t));
518  sha512Update(&state->sha512Context, context, contextLen);
519  }
520 
521  //Digest R || A
522  sha512Update(&state->sha512Context, state->r, ED25519_SIGNATURE_LEN / 2);
524 
525  //The message is split over multiple chunks
526  for(i = 0; messageChunks[i].buffer != NULL; i++)
527  {
528  //Digest current chunk
529  sha512Update(&state->sha512Context, messageChunks[i].buffer,
530  messageChunks[i].length);
531  }
532 
533  //Compute SHA512(dom2(F, C) || R || A || PH(M)) and interpret the 64-octet
534  //digest as a little-endian integer k
535  sha512Final(&state->sha512Context, state->k);
536 
537  //For efficiency, reduce k modulo L first
538  ed25519RedInt(state->k, state->k);
539 
540  //Compute the point P = s * B - k * A'
541  curve25519Sub(state->ka.x, ED25519_ZERO, state->ka.x);
542  curve25519Sub(state->ka.t, ED25519_ZERO, state->ka.t);
543  ed25519Mul(state, &state->sb, state->s, &ED25519_B);
544  ed25519Mul(state, &state->ka, state->k, &state->ka);
545  ed25519Add(state, &state->ka, &state->sb, &state->ka);
546 
547  //Encode of the resulting point P
548  ed25519Encode(&state->ka, state->p);
549 
550  //If P = R, then the signature is verified. If P does not equal R,
551  //then the message or the signature may have been modified
552  ret |= ed25519CompInt(state->p, signature, ED25519_SIGNATURE_LEN / 2);
553 
554  //Erase working state
555  osMemset(state, 0, sizeof(Ed25519State));
556 
557 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
558  //Release working state
559  cryptoFreeMem(state);
560 #endif
561 
562  //Return status code
563  return (ret == 0) ? NO_ERROR : ERROR_INVALID_SIGNATURE;
564 }
565 
566 
567 /**
568  * @brief Scalar multiplication on Ed25519 curve
569  * @param[in] state Pointer to the working state
570  * @param[out] r Resulting point R = k * P
571  * @param[in] k Input scalar
572  * @param[in] p Input point
573  **/
574 
575 __weak_func void ed25519Mul(Ed25519State *state, Ed25519Point *r,
576  const uint8_t *k, const Ed25519Point *p)
577 {
578  int_t i;
579  uint8_t b;
580 
581  //The neutral element is represented by (0, 1, 1, 0)
582  curve25519SetInt(state->u.x, 0);
583  curve25519SetInt(state->u.y, 1);
584  curve25519SetInt(state->u.z, 1);
585  curve25519SetInt(state->u.t, 0);
586 
587  //Perform scalar multiplication
588  for(i = CURVE25519_BIT_LEN - 1; i >= 0; i--)
589  {
590  //The scalar is processed in a left-to-right fashion
591  b = (k[i / 8] >> (i % 8)) & 1;
592 
593  //Compute U = 2 * U
594  ed25519Double(state, &state->u, &state->u);
595  //Compute V = U + P
596  ed25519Add(state, &state->v, &state->u, p);
597 
598  //If b is set, then U = V
599  curve25519Select(state->u.x, state->u.x, state->v.x, b);
600  curve25519Select(state->u.y, state->u.y, state->v.y, b);
601  curve25519Select(state->u.z, state->u.z, state->v.z, b);
602  curve25519Select(state->u.t, state->u.t, state->v.t, b);
603  }
604 
605  //Copy result
606  curve25519Copy(r->x, state->u.x);
607  curve25519Copy(r->y, state->u.y);
608  curve25519Copy(r->z, state->u.z);
609  curve25519Copy(r->t, state->u.t);
610 }
611 
612 
613 /**
614  * @brief Point addition
615  * @param[in] state Pointer to the working state
616  * @param[out] r Resulting point R = P + Q
617  * @param[in] p First operand
618  * @param[in] q Second operand
619  **/
620 
622  const Ed25519Point *q)
623 {
624  //Compute A = (Y1 + X1) * (Y2 + X2)
625  curve25519Add(state->c, p->y, p->x);
626  curve25519Add(state->d, q->y, q->x);
627  curve25519Mul(state->a, state->c, state->d);
628  //Compute B = (Y1 - X1) * (Y2 - X2)
629  curve25519Sub(state->c, p->y, p->x);
630  curve25519Sub(state->d, q->y, q->x);
631  curve25519Mul(state->b, state->c, state->d);
632  //Compute C = 2 * Z1 * Z2
633  curve25519Mul(state->c, p->z, q->z);
634  curve25519Add(state->c, state->c, state->c);
635  //Compute D = (2 * d) * T1 * T2
636  curve25519Mul(state->d, p->t, q->t);
637  curve25519Mul(state->d, state->d, ED25519_2D);
638  //Compute E = A + B
639  curve25519Add(state->e, state->a, state->b);
640  //Compute F = A - B
641  curve25519Sub(state->f, state->a, state->b);
642  //Compute G = C + D
643  curve25519Add(state->g, state->c, state->d);
644  //Compute H = C - D
645  curve25519Sub(state->h, state->c, state->d);
646  //Compute X3 = F * H
647  curve25519Mul(r->x, state->f, state->h);
648  //Compute Y3 = E * G
649  curve25519Mul(r->y, state->e, state->g);
650  //Compute Z3 = G * H
651  curve25519Mul(r->z, state->g, state->h);
652  //Compute T3 = E * F
653  curve25519Mul(r->t, state->e, state->f);
654 }
655 
656 
657 /**
658  * @brief Point doubling
659  * @param[in] state Pointer to the working state
660  * @param[out] r Resulting point R = 2 * P
661  * @param[in] p Input point P
662  **/
663 
665 {
666  //Compute A = X1^2
667  curve25519Sqr(state->a, p->x);
668  //Compute B = Y1^2
669  curve25519Sqr(state->b, p->y);
670  //Compute C = 2 * Z1^2
671  curve25519Sqr(state->c, p->z);
672  curve25519Add(state->c, state->c, state->c);
673  //Compute E = A + B
674  curve25519Add(state->e, state->a, state->b);
675  //Compute F = E - (X1 + Y1)^2
676  curve25519Add(state->f, p->x, p->y);
677  curve25519Sqr(state->f, state->f);
678  curve25519Sub(state->f, state->e, state->f);
679  //Compute G = A - B
680  curve25519Sub(state->g, state->a, state->b);
681  //Compute H = C + G
682  curve25519Add(state->h, state->c, state->g);
683  //Compute X3 = F * H
684  curve25519Mul(r->x, state->f, state->h);
685  //Compute Y3 = E * G
686  curve25519Mul(r->y, state->e, state->g);
687  //Compute Z3 = G * H
688  curve25519Mul(r->z, state->g, state->h);
689  //Compute T3 = E * F
690  curve25519Mul(r->t, state->e, state->f);
691 }
692 
693 
694 /**
695  * @brief Point encoding
696  * @param[in] p Point representation
697  * @param[out] data Octet string resulting from the conversion
698  **/
699 
701 {
702  //Retrieve affine representation
703  curve25519Inv(p->z, p->z);
704  curve25519Mul(p->x, p->x, p->z);
705  curve25519Mul(p->y, p->y, p->z);
706  curve25519SetInt(p->z, 1);
707  curve25519Mul(p->t, p->x, p->y);
708 
709  //Encode the y-coordinate as a little-endian string of 32 octets. The most
710  //significant bit of the final octet is always zero
711  curve25519Export(p->y, data);
712 
713  //Copy the least significant bit of the x-coordinate to the most significant
714  //bit of the final octet
715  data[31] |= (p->x[0] & 1) << 7;
716 }
717 
718 
719 /**
720  * @brief Point decoding
721  * @param[in] p Point representation
722  * @param[out] data Octet string to be converted
723  **/
724 
725 uint32_t ed25519Decode(Ed25519Point *p, const uint8_t *data)
726 {
727  uint_t i;
728  uint8_t x0;
729  uint32_t ret;
730  uint64_t temp;
731  uint32_t u[8];
732  uint32_t v[8];
733 
734  //First, interpret the string as an integer in little-endian representation.
735  //Bit 255 of this number is the least significant bit of the x-coordinate
736  //and denote this value x_0
737  x0 = data[31] >> 7;
738 
739  //The y-coordinate is recovered simply by clearing this bit
740  curve25519Import(p->y, data);
741  p->y[7] &= 0x7FFFFFFF;
742 
743  //Compute u = y + 19
744  for(temp = 19, i = 0; i < 8; i++)
745  {
746  temp += p->y[i];
747  u[i] = temp & 0xFFFFFFFF;
748  temp >>= 32;
749  }
750 
751  //If the y-coordinate is >= p, decoding fails
752  ret = (u[7] >> 31) & 1;
753 
754  //The curve equation implies x^2 = (y^2 - 1) / (d * y^2 + 1) mod p
755  //Let u = y^2 - 1 and v = d * y^2 + 1
756  curve25519Sqr(v, p->y);
757  curve25519SubInt(u, v, 1);
758  curve25519Mul(v, v, ED25519_D);
759  curve25519AddInt(v, v, 1);
760 
761  //Compute u = sqrt(u / v)
762  ret |= curve25519Sqrt(u, u, v);
763 
764  //If x = 0, and x_0 = 1, decoding fails
765  ret |= (curve25519Comp(u, ED25519_ZERO) ^ 1) & x0;
766 
767  //Compute v = p - u
768  curve25519Sub(v, ED25519_ZERO, u);
769 
770  //Finally, use the x_0 bit to select the right square root
771  curve25519Select(p->x, u, v, (x0 ^ u[0]) & 1);
772 
773  //Calculate extended point representation
774  curve25519SetInt(p->z, 1);
775  curve25519Mul(p->t, p->x, p->y);
776 
777  //Return 0 if the point has been successfully decoded, else 1
778  return ret;
779 }
780 
781 
782 /**
783  * @brief Reduce an integer modulo L
784  *
785  * This function implements Barrett reduction with b = 2^8 and k = 32. The
786  * algorithm requires the precomputation of the quantity mu = b^(2 * k) / L
787  *
788  * @param[out] r Resulting integer R = A mod L
789  * @param[in] a An integer such as 0 <= A < b^(2 * k)
790  **/
791 
792 void ed25519RedInt(uint8_t *r, const uint8_t *a)
793 {
794  uint8_t c;
795  uint8_t u[33];
796  uint8_t v[33];
797 
798  //Compute the estimate of the quotient u = ((a / b^(k - 1)) * mu) / b^(k + 1)
799  ed25519MulInt(NULL, u, a + 31, ED25519_MU, 33);
800  //Compute v = u * L mod b^(k + 1)
801  ed25519MulInt(v, NULL, u, ED25519_L, 33);
802 
803  //Compute the estimate of the remainder u = a mod b^(k + 1) - v
804  //If u < 0, then u = u + b^(k + 1)
805  ed25519SubInt(u, a, v, 33);
806 
807  //This estimation implies that at most two subtractions of L are required to
808  //obtain the correct remainder r
809  c = ed25519SubInt(v, u, ED25519_L, 33);
810  ed25519SelectInt(u, v, u, c, 33);
811  c = ed25519SubInt(v, u, ED25519_L, 33);
812  ed25519SelectInt(u, v, u, c, 33);
813 
814  //Copy the resulting remainder
815  ed25519CopyInt(r, u, 32);
816 }
817 
818 
819 /**
820  * @brief Addition of two integers
821  * @param[out] r Resulting integer R = A + B
822  * @param[in] a An integer such as 0 <= A < (2^8)^n
823  * @param[in] b An integer such as 0 <= B < (2^8)^n
824  * @param[in] n Size of the operands, in bytes
825  **/
826 
827 void ed25519AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
828 {
829  uint_t i;
830  uint16_t temp;
831 
832  //Compute R = A + B
833  for(temp = 0, i = 0; i < n; i++)
834  {
835  temp += a[i];
836  temp += b[i];
837  r[i] = temp & 0xFF;
838  temp >>= 8;
839  }
840 }
841 
842 
843 /**
844  * @brief Subtraction of two integers
845  * @param[out] r Resulting integer R = A - B
846  * @param[in] a An integer such as 0 <= A < (2^8)^n
847  * @param[in] b An integer such as 0 <= B < (2^8)^n
848  * @param[in] n Size of the operands, in bytes
849  * @return 1 if the result is negative, else 0
850  **/
851 
852 uint8_t ed25519SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
853 {
854  uint_t i;
855  int16_t temp;
856 
857  //Compute R = A - B
858  for(temp = 0, i = 0; i < n; i++)
859  {
860  temp += a[i];
861  temp -= b[i];
862  r[i] = temp & 0xFF;
863  temp >>= 8;
864  }
865 
866  //Return 1 if the result of the subtraction is negative
867  return temp & 1;
868 }
869 
870 
871 /**
872  * @brief Multiplication of two integers
873  * @param[out] rl Low part of the result R = (A + B) mod (2^8)^n
874  * @param[out] rh High part of the result R = (A + B) / (2^8)^n
875  * @param[in] a An integer such as 0 <= A < (2^8)^n
876  * @param[in] b An integer such as 0 <= B < (2^8)^n
877  * @param[in] n Size of the operands, in bytes
878  **/
879 
880 void ed25519MulInt(uint8_t *rl, uint8_t *rh, const uint8_t *a,
881  const uint8_t *b, uint_t n)
882 {
883  uint_t i;
884  uint_t j;
885  uint32_t temp;
886 
887  //Compute the low part of the multiplication
888  for(temp = 0, i = 0; i < n; i++)
889  {
890  //The Comba's algorithm computes the products, column by column
891  for(j = 0; j <= i; j++)
892  {
893  temp += (uint16_t) a[j] * b[i - j];
894  }
895 
896  //At the bottom of each column, the final result is written to memory
897  if(rl != NULL)
898  {
899  rl[i] = temp & 0xFF;
900  }
901 
902  //Propagate the carry upwards
903  temp >>= 8;
904  }
905 
906  //Check whether the high part of the multiplication should be calculated
907  if(rh != NULL)
908  {
909  //Compute the high part of the multiplication
910  for(i = n; i < (2 * n); i++)
911  {
912  //The Comba's algorithm computes the products, column by column
913  for(j = i + 1 - n; j < n; j++)
914  {
915  temp += (uint16_t) a[j] * b[i - j];
916  }
917 
918  //At the bottom of each column, the final result is written to memory
919  rh[i - n] = temp & 0xFF;
920 
921  //Propagate the carry upwards
922  temp >>= 8;
923  }
924  }
925 }
926 
927 
928 /**
929  * @brief Copy an integer
930  * @param[out] a Pointer to the destination integer
931  * @param[in] b Pointer to the source integer
932  * @param[in] n Size of the integers, in bytes
933  **/
934 
935 void ed25519CopyInt(uint8_t *a, const uint8_t *b, uint_t n)
936 {
937  uint_t i;
938 
939  //Copy the value of the integer
940  for(i = 0; i < n; i++)
941  {
942  a[i] = b[i];
943  }
944 }
945 
946 
947 /**
948  * @brief Select an integer
949  * @param[out] r Pointer to the destination integer
950  * @param[in] a Pointer to the first source integer
951  * @param[in] b Pointer to the second source integer
952  * @param[in] c Condition variable
953  * @param[in] n Size of the integers, in bytes
954  **/
955 
956 void ed25519SelectInt(uint8_t *r, const uint8_t *a, const uint8_t *b,
957  uint8_t c, uint_t n)
958 {
959  uint_t i;
960  uint8_t mask;
961 
962  //The mask is the all-1 or all-0 word
963  mask = c - 1;
964 
965  //Select between A and B
966  for(i = 0; i < n; i++)
967  {
968  //Constant time implementation
969  r[i] = (a[i] & mask) | (b[i] & ~mask);
970  }
971 }
972 
973 
974 /**
975  * @brief Compare integers
976  * @param[in] a Pointer to the first integer
977  * @param[in] b Pointer to the second integer
978  * @param[in] n Size of the integers, in bytes
979  * @return The function returns 0 if the A = B, else 1
980  **/
981 
982 uint8_t ed25519CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
983 {
984  uint_t i;
985  uint8_t mask;
986 
987  //Initialize mask
988  mask = 0;
989 
990  //Compare A and B
991  for(i = 0; i < n; i++)
992  {
993  //Constant time implementation
994  mask |= a[i] ^ b[i];
995  }
996 
997  //Return 0 if A = B, else 1
998  return ((uint8_t) (mask | (~mask + 1))) >> 7;
999 }
1000 
1001 #endif
uint32_t z[8]
Definition: ed25519.h:65
Ed25519 working state.
Definition: ed25519.h:75
Ed25519 elliptic curve (constant-time implementation)
uint32_t f[8]
Definition: ed25519.h:91
uint32_t b[8]
Definition: ed25519.h:87
uint8_t b
Definition: nbns_common.h:104
__weak_func void curve25519Sqr(uint32_t *r, const uint32_t *a)
Modular squaring.
Definition: curve25519.c:317
Extended point representation.
Definition: ed25519.h:62
void ed25519Double(Ed25519State *state, Ed25519Point *r, const Ed25519Point *p)
Point doubling.
Definition: ed25519.c:664
uint8_t a
Definition: ndp.h:411
uint8_t k[64]
Definition: ed25519.h:77
uint8_t p[32]
Definition: ed25519.h:78
error_t ed25519GenerateSignatureEx(const uint8_t *privateKey, const uint8_t *publicKey, const DataChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, uint8_t *signature)
EdDSA signature generation.
Definition: ed25519.c:271
signed int int_t
Definition: compiler_port.h:49
uint32_t x[8]
Definition: ed25519.h:63
#define PrngAlgo
Definition: crypto.h:938
uint8_t s[32]
Definition: ed25519.h:80
#define ED25519_PUBLIC_KEY_LEN
Definition: ed25519.h:42
uint32_t a[8]
Definition: ed25519.h:86
uint8_t p
Definition: ndp.h:300
Ed25519Point rb
Definition: ed25519.h:82
uint8_t message[]
Definition: chap.h:154
uint32_t ed25519Decode(Ed25519Point *p, const uint8_t *data)
Point decoding.
Definition: ed25519.c:725
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:956
uint8_t data[]
Definition: ethernet.h:222
void ed25519Add(Ed25519State *state, Ed25519Point *r, const Ed25519Point *p, const Ed25519Point *q)
Point addition.
Definition: ed25519.c:621
__weak_func void ed25519Mul(Ed25519State *state, Ed25519Point *r, const uint8_t *k, const Ed25519Point *p)
Scalar multiplication on Ed25519 curve.
Definition: ed25519.c:575
const void * buffer
Definition: crypto.h:982
void curve25519SetInt(uint32_t *a, uint32_t b)
Set integer value.
Definition: curve25519.c:57
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
void curve25519Import(uint32_t *a, const uint8_t *data)
Import an octet string.
Definition: curve25519.c:613
void curve25519AddInt(uint32_t *r, const uint32_t *a, uint32_t b)
Modular addition.
Definition: curve25519.c:105
#define ED25519_SIGNATURE_LEN
Definition: ed25519.h:44
#define ED25519_PRIVATE_KEY_LEN
Definition: ed25519.h:40
uint8_t r
Definition: ndp.h:346
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:236
void curve25519Add(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular addition.
Definition: curve25519.c:79
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
error_t
Error codes.
Definition: error.h:43
void ed25519Encode(Ed25519Point *p, uint8_t *data)
Point encoding.
Definition: ed25519.c:700
error_t ed25519GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey)
EdDSA private key generation.
Definition: ed25519.c:144
uint32_t c[8]
Definition: ed25519.h:88
__weak_func void curve25519Mul(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular multiplication.
Definition: curve25519.c:191
void curve25519Copy(uint32_t *a, const uint32_t *b)
Copy an integer.
Definition: curve25519.c:515
void ed25519AddInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
Addition of two integers.
Definition: ed25519.c:827
Ed25519Point v
Definition: ed25519.h:85
uint32_t curve25519Sqrt(uint32_t *r, const uint32_t *a, const uint32_t *b)
Compute the square root of (A / B) modulo p.
Definition: curve25519.c:430
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:935
uint8_t mask
Definition: web_socket.h:319
uint32_t h[8]
Definition: ed25519.h:93
uint8_t u
Definition: lldp_ext_med.h:213
Sha512Context sha512Context
Definition: ed25519.h:76
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:880
void ed25519RedInt(uint8_t *r, const uint8_t *a)
Reduce an integer modulo L.
Definition: ed25519.c:792
#define CURVE25519_BIT_LEN
Definition: curve25519.h:38
Data chunk descriptor.
Definition: crypto.h:981
Ed25519Point u
Definition: ed25519.h:84
void curve25519Inv(uint32_t *r, const uint32_t *a)
Modular multiplicative inverse.
Definition: curve25519.c:380
uint32_t t[8]
Definition: ed25519.h:66
Ed25519Point ka
Definition: ed25519.h:81
uint32_t d[8]
Definition: ed25519.h:89
uint32_t y[8]
Definition: ed25519.h:64
uint8_t n
void sha512Final(Sha512Context *context, uint8_t *digest)
Finish the SHA-512 message digest.
#define cryptoFreeMem(p)
Definition: crypto.h:791
error_t ed25519VerifySignatureEx(const uint8_t *publicKey, const DataChunk *messageChunks, const void *context, uint8_t contextLen, uint8_t flag, const uint8_t *signature)
EdDSA signature verification.
Definition: ed25519.c:463
uint8_t digest[64]
Definition: sha512.h:66
void sha512Init(Sha512Context *context)
Initialize SHA-512 message digest context.
Curve25519 elliptic curve (constant-time implementation)
void curve25519Select(uint32_t *r, const uint32_t *a, const uint32_t *b, uint32_t c)
Select an integer.
Definition: curve25519.c:562
#define cryptoAllocMem(size)
Definition: crypto.h:786
uint8_t s
Definition: igmp_common.h:234
Ed25519Point sb
Definition: ed25519.h:83
size_t length
Definition: crypto.h:983
error_t ed25519GeneratePublicKey(const uint8_t *privateKey, uint8_t *publicKey)
Derive the public key from an EdDSA private key.
Definition: ed25519.c:168
void curve25519Export(uint32_t *a, uint8_t *data)
Export an octet string.
Definition: curve25519.c:634
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:429
uint8_t r[32]
Definition: ed25519.h:79
uint32_t g[8]
Definition: ed25519.h:92
void curve25519Sub(uint32_t *r, const uint32_t *a, const uint32_t *b)
Modular subtraction.
Definition: curve25519.c:130
unsigned int uint_t
Definition: compiler_port.h:50
Elliptic curves.
#define osMemset(p, value, length)
Definition: os_port.h:135
void curve25519SubInt(uint32_t *r, const uint32_t *a, uint32_t b)
Modular subtraction.
Definition: curve25519.c:159
uint32_t curve25519Comp(const uint32_t *a, const uint32_t *b)
Compare integers.
Definition: curve25519.c:587
uint8_t ed25519CompInt(const uint8_t *a, const uint8_t *b, uint_t n)
Compare integers.
Definition: ed25519.c:982
@ ERROR_INVALID_SIGNATURE
Definition: error.h:227
uint8_t ed25519SubInt(uint8_t *r, const uint8_t *a, const uint8_t *b, uint_t n)
Subtraction of two integers.
Definition: ed25519.c:852
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
uint32_t e[8]
Definition: ed25519.h:90
Debugging facilities.
void sha512Update(Sha512Context *context, const void *data, size_t length)
Update the SHA-512 context with a portion of the message being hashed.