eddsa.c
Go to the documentation of this file.
1 /**
2  * @file eddsa.c
3  * @brief EdDSA (Edwards-Curve Digital Signature Algorithm)
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/eddsa.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (ED25519_SUPPORT == ENABLED || ED448_SUPPORT == ENABLED)
41 
42 
43 /**
44  * @brief Initialize an EdDSA public key
45  * @param[in] key Pointer to the EdDSA public key to initialize
46  **/
47 
49 {
50  //Initialize elliptic curve parameters
51  key->curve = NULL;
52 
53  //Initialize public key
55 }
56 
57 
58 /**
59  * @brief Release an EdDSA public key
60  * @param[in] key Pointer to the EdDSA public key to free
61  **/
62 
64 {
65  //Clear public key
66  osMemset(key, 0, sizeof(EddsaPublicKey));
67 }
68 
69 
70 /**
71  * @brief Initialize an EdDSA private key
72  * @param[in] key Pointer to the EdDSA private key to initialize
73  **/
74 
76 {
77  //Initialize elliptic curve parameters
78  key->curve = NULL;
79 
80  //Initialize private key
82  //Initialize private key slot
83  key->slot = -1;
84 
85  //Initialize public key
86  eddsaInitPublicKey(&key->q);
87 }
88 
89 
90 /**
91  * @brief Release an EdDSA private key
92  * @param[in] key Pointer to the EdDSA public key to free
93  **/
94 
96 {
97  //Clear public key
98  osMemset(key, 0, sizeof(EddsaPrivateKey));
99 }
100 
101 
102 /**
103  * @brief EdDSA key pair generation
104  * @param[in] prngAlgo PRNG algorithm
105  * @param[in] prngContext Pointer to the PRNG context
106  * @param[in] curve Elliptic curve parameters
107  * @param[out] privateKey EdDSA private key
108  * @param[out] publicKey EdDSA public key (optional parameter)
109  * @return Error code
110  **/
111 
112 error_t eddsaGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext,
113  const EcCurve *curve, EddsaPrivateKey *privateKey,
114  EddsaPublicKey *publicKey)
115 {
116  error_t error;
117 
118  //Generate a private key
119  error = eddsaGeneratePrivateKey(prngAlgo, prngContext, curve,
120  privateKey);
121 
122  //Check status code
123  if(!error)
124  {
125  //Derive the public key from the private key
126  error = eddsaGeneratePublicKey(privateKey, &privateKey->q);
127  }
128 
129  //Check status code
130  if(!error)
131  {
132  //The parameter is optional
133  if(publicKey != NULL)
134  {
135  //Copy the resulting public key
136  *publicKey = privateKey->q;
137  }
138  }
139 
140  //Return status code
141  return error;
142 }
143 
144 
145 /**
146  * @brief EdDSA private key generation
147  * @param[in] prngAlgo PRNG algorithm
148  * @param[in] prngContext Pointer to the PRNG context
149  * @param[in] curve Elliptic curve parameters
150  * @param[out] privateKey EdDSA private key
151  * @return Error code
152  **/
153 
154 error_t eddsaGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext,
155  const EcCurve *curve, EddsaPrivateKey *privateKey)
156 {
157  error_t error;
158 
159  //Check parameters
160  if(curve != NULL && privateKey != NULL)
161  {
162  //Initialize private key
163  osMemset(privateKey->d, 0, EDDSA_MAX_PRIVATE_KEY_LEN);
164  //Initialize public key
165  eddsaInitPublicKey(&privateKey->q);
166 
167 #if (ED25519_SUPPORT == ENABLED)
168  //Ed25519 elliptic curve?
169  if(curve == ED25519_CURVE)
170  {
171  //Save elliptic curve parameters
172  privateKey->curve = ED25519_CURVE;
173 
174  //Generate an Ed25519 private key
175  error = ed25519GeneratePrivateKey(prngAlgo, prngContext,
176  privateKey->d);
177  }
178  else
179 #endif
180 #if (ED448_SUPPORT == ENABLED)
181  //Ed448 elliptic curve?
182  if(curve == ED448_CURVE)
183  {
184  //Save elliptic curve parameters
185  privateKey->curve = ED448_CURVE;
186 
187  //Generate an Ed448 private key
188  error = ed448GeneratePrivateKey(prngAlgo, prngContext,
189  privateKey->d);
190  }
191  else
192 #endif
193  //Unknown algorithm?
194  {
195  //Report an error
197  }
198  }
199  else
200  {
201  //Report an error
202  error = ERROR_INVALID_PARAMETER;
203  }
204 
205  //Return status code
206  return error;
207 }
208 
209 
210 /**
211  * @brief Derive the public key from an EdDSA private key
212  * @param[in] privateKey EdDSA private key
213  * @param[out] publicKey EdDSA public key
214  * @return Error code
215  **/
216 
218  EddsaPublicKey *publicKey)
219 {
220  error_t error;
221 
222  //Check parameters
223  if(privateKey != NULL && publicKey != NULL)
224  {
225 #if (ED25519_SUPPORT == ENABLED)
226  //Ed25519 elliptic curve?
227  if(privateKey->curve == ED25519_CURVE)
228  {
229  //Save elliptic curve parameters
230  publicKey->curve = ED25519_CURVE;
231 
232  //Derive the public key from the private key
233  error = ed25519GeneratePublicKey(privateKey->d, publicKey->q);
234  }
235  else
236 #endif
237 #if (ED448_SUPPORT == ENABLED)
238  //Ed448 elliptic curve?
239  if(privateKey->curve == ED448_CURVE)
240  {
241  //Save elliptic curve parameters
242  publicKey->curve = ED448_CURVE;
243 
244  //Derive the public key from the private key
245  error = ed448GeneratePublicKey(privateKey->d, publicKey->q);
246  }
247  else
248 #endif
249  //Unknown algorithm?
250  {
251  //Report an error
253  }
254  }
255  else
256  {
257  //Report an error
258  error = ERROR_INVALID_PARAMETER;
259  }
260 
261  //Return status code
262  return error;
263 }
264 
265 
266 /**
267  * @brief Import an EdDSA public key
268  * @param[out] key EdDSA public key
269  * @param[in] curve Elliptic curve parameters
270  * @param[in] input Pointer to the octet string
271  * @param[in] length Length of the octet string, in bytes
272  * @return Error code
273  **/
274 
276  const uint8_t *input, size_t length)
277 {
278  error_t error;
279 
280  //Initialize status code
281  error = NO_ERROR;
282 
283  //Check parameters
284  if(key != NULL && curve != NULL && input != NULL)
285  {
286  //Edwards elliptic curve?
287  if(curve->type == EC_CURVE_TYPE_EDWARDS)
288  {
289  //Check the length of the public key
290  if(length == ((curve->fieldSize / 8) + 1))
291  {
292  //Save elliptic curve parameters
293  key->curve = curve;
294  //Copy the public key
295  osMemcpy(key->q, input, length);
296  }
297  else
298  {
299  //The length of the public key is not acceptable
300  error = ERROR_INVALID_KEY_LENGTH;
301  }
302  }
303  else
304  {
305  //Invalid elliptic curve
307  }
308  }
309  else
310  {
311  //Report an error
312  error = ERROR_INVALID_PARAMETER;
313  }
314 
315  //Return status code
316  return error;
317 }
318 
319 
320 /**
321  * @brief Export an EdDSA public key
322  * @param[in] key EdDSA public key
323  * @param[out] output Pointer to the octet string (optional parameter)
324  * @param[out] written Length of the resulting octet string, in bytes
325  * @return Error code
326  **/
327 
328 error_t eddsaExportPublicKey(const EddsaPublicKey *key, uint8_t *output,
329  size_t *written)
330 {
331  error_t error;
332  size_t n;
333 
334  //Initialize status code
335  error = NO_ERROR;
336 
337  //Check parameters
338  if(key != NULL && written != NULL)
339  {
340  //Edwards elliptic curve?
341  if(key->curve != NULL && key->curve->type == EC_CURVE_TYPE_EDWARDS)
342  {
343  //Determine the length of the public key
344  n = (key->curve->fieldSize / 8) + 1;
345 
346  //If the output parameter is NULL, then the function calculates the
347  //length of the octet string without copying any data
348  if(output != NULL)
349  {
350  //Copy the public key
351  osMemcpy(output, key->q, n);
352  }
353 
354  //Length of the resulting octet string
355  *written = n;
356  }
357  else
358  {
359  //Invalid elliptic curve
361  }
362  }
363  else
364  {
365  //Report an error
366  error = ERROR_INVALID_PARAMETER;
367  }
368 
369  //Return status code
370  return error;
371 }
372 
373 
374 /**
375  * @brief Import an EdDSA private key
376  * @param[out] key EdDSA private key
377  * @param[in] curve Elliptic curve parameters
378  * @param[in] data Pointer to the octet string
379  * @param[in] length Length of the octet string, in bytes
380  * @return Error code
381  **/
382 
384  const uint8_t *data, size_t length)
385 {
386  error_t error;
387 
388  //Initialize status code
389  error = NO_ERROR;
390 
391  //Check parameters
392  if(key != NULL && curve != NULL && data != NULL)
393  {
394  //Edwards elliptic curve?
395  if(curve->type == EC_CURVE_TYPE_EDWARDS)
396  {
397  //Check the length of the private key
398  if(length == ((curve->fieldSize / 8) + 1))
399  {
400  //Save elliptic curve parameters
401  key->curve = curve;
402  //Copy the private key
403  osMemcpy(key->d, data, length);
404  }
405  else
406  {
407  //The length of the public key is not acceptable
408  error = ERROR_INVALID_KEY_LENGTH;
409  }
410  }
411  else
412  {
413  //Invalid elliptic curve
415  }
416  }
417  else
418  {
419  //Report an error
420  error = ERROR_INVALID_PARAMETER;
421  }
422 
423  //Return status code
424  return error;
425 }
426 
427 
428 /**
429  * @brief Export an EdDSA private key
430  * @param[in] key EdDSA private key
431  * @param[out] output Pointer to the octet string (optional parameter)
432  * @param[out] written Length of the octet string, in bytes
433  * @return Error code
434  **/
435 
436 error_t eddsaExportPrivateKey(const EddsaPrivateKey *key, uint8_t *output,
437  size_t *written)
438 {
439  error_t error;
440  size_t n;
441 
442  //Initialize status code
443  error = NO_ERROR;
444 
445  //Check parameters
446  if(key != NULL && written != NULL)
447  {
448  //Edwards elliptic curve?
449  if(key->curve != NULL && key->curve->type == EC_CURVE_TYPE_EDWARDS)
450  {
451  //Determine the length of the private key
452  n = (key->curve->fieldSize / 8) + 1;
453 
454  //If the output parameter is NULL, then the function calculates the
455  //length of the octet string without copying any data
456  if(output != NULL)
457  {
458  //Copy the private key
459  osMemcpy(output, key->d, n);
460  }
461 
462  //Length of the resulting octet string
463  *written = n;
464  }
465  else
466  {
467  //Invalid elliptic curve
469  }
470  }
471  else
472  {
473  //Report an error
474  error = ERROR_INVALID_PARAMETER;
475  }
476 
477  //Return status code
478  return error;
479 }
480 
481 #endif
error_t ed448GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey)
EdDSA private key generation.
Definition: ed448.c:131
@ ERROR_UNSUPPORTED_ELLIPTIC_CURVE
Definition: error.h:133
#define EDDSA_MAX_PRIVATE_KEY_LEN
Definition: eddsa.h:48
@ EC_CURVE_TYPE_EDWARDS
Definition: ec.h:364
#define EDDSA_MAX_PUBLIC_KEY_LEN
Definition: eddsa.h:41
uint8_t d[EDDSA_MAX_PRIVATE_KEY_LEN]
Private key.
Definition: eddsa.h:77
#define PrngAlgo
Definition: crypto.h:980
const EcCurve * curve
Elliptic curve parameters.
Definition: eddsa.h:76
void eddsaFreePrivateKey(EddsaPrivateKey *key)
Release an EdDSA private key.
Definition: eddsa.c:95
void eddsaInitPrivateKey(EddsaPrivateKey *key)
Initialize an EdDSA private key.
Definition: eddsa.c:75
uint8_t data[]
Definition: ethernet.h:224
#define ED25519_CURVE
Definition: ec_curves.h:72
#define ED448_CURVE
Definition: ec_curves.h:73
error_t eddsaGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, const EcCurve *curve, EddsaPrivateKey *privateKey, EddsaPublicKey *publicKey)
EdDSA key pair generation.
Definition: eddsa.c:112
error_t eddsaExportPublicKey(const EddsaPublicKey *key, uint8_t *output, size_t *written)
Export an EdDSA public key.
Definition: eddsa.c:328
uint8_t q[EDDSA_MAX_PUBLIC_KEY_LEN]
Public key.
Definition: eddsa.h:66
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
#define osMemcpy(dest, src, length)
Definition: os_port.h:144
const EcCurve * curve
Elliptic curve parameters.
Definition: eddsa.h:65
error_t
Error codes.
Definition: error.h:43
error_t ed25519GeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, uint8_t *privateKey)
EdDSA private key generation.
Definition: ed25519.c:144
EdDSA public key.
Definition: eddsa.h:64
int_t slot
Private key slot.
Definition: eddsa.h:78
EdDSA (Edwards-Curve Digital Signature Algorithm)
@ ERROR_INVALID_KEY_LENGTH
Definition: error.h:107
General definitions for cryptographic algorithms.
error_t eddsaExportPrivateKey(const EddsaPrivateKey *key, uint8_t *output, size_t *written)
Export an EdDSA private key.
Definition: eddsa.c:436
error_t eddsaGeneratePrivateKey(const PrngAlgo *prngAlgo, void *prngContext, const EcCurve *curve, EddsaPrivateKey *privateKey)
EdDSA private key generation.
Definition: eddsa.c:154
error_t ed448GeneratePublicKey(const uint8_t *privateKey, uint8_t *publicKey)
Derive the public key from an EdDSA private key.
Definition: ed448.c:155
uint8_t length
Definition: tcp.h:375
EdDSA private key.
Definition: eddsa.h:75
uint8_t n
error_t eddsaGeneratePublicKey(const EddsaPrivateKey *privateKey, EddsaPublicKey *publicKey)
Derive the public key from an EdDSA private key.
Definition: eddsa.c:217
void eddsaFreePublicKey(EddsaPublicKey *key)
Release an EdDSA public key.
Definition: eddsa.c:63
EddsaPublicKey q
Public key.
Definition: eddsa.h:79
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 eddsaImportPublicKey(EddsaPublicKey *key, const EcCurve *curve, const uint8_t *input, size_t length)
Import an EdDSA public key.
Definition: eddsa.c:275
error_t eddsaImportPrivateKey(EddsaPrivateKey *key, const EcCurve *curve, const uint8_t *data, size_t length)
Import an EdDSA private key.
Definition: eddsa.c:383
#define EcCurve
Definition: ec.h:346
#define osMemset(p, value, length)
Definition: os_port.h:138
void eddsaInitPublicKey(EddsaPublicKey *key)
Initialize an EdDSA public key.
Definition: eddsa.c:48
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.