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.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/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] data Pointer to the octet string
270  * @param[in] length Length of the octet string, in bytes
271  * @return Error code
272  **/
273 
275  const uint8_t *data, size_t length)
276 {
277  error_t error;
278 
279  //Initialize status code
280  error = NO_ERROR;
281 
282  //Check parameters
283  if(key != NULL && curve != NULL && data != NULL)
284  {
285  //Edwards elliptic curve?
286  if(curve->type == EC_CURVE_TYPE_EDWARDS)
287  {
288  //Check the length of the public key
289  if(length == ((curve->fieldSize / 8) + 1))
290  {
291  //Save elliptic curve parameters
292  key->curve = curve;
293  //Copy the public key
294  osMemcpy(key->q, data, length);
295  }
296  else
297  {
298  //The length of the public key is not acceptable
299  error = ERROR_INVALID_KEY_LENGTH;
300  }
301  }
302  else
303  {
304  //Invalid elliptic curve
306  }
307  }
308  else
309  {
310  //Report an error
311  error = ERROR_INVALID_PARAMETER;
312  }
313 
314  //Return status code
315  return error;
316 }
317 
318 
319 /**
320  * @brief Export an EdDSA public key
321  * @param[in] key EdDSA public key
322  * @param[out] data Pointer to the octet string
323  * @param[out] length Length of the octet string, in bytes
324  * @return Error code
325  **/
326 
328  size_t *length)
329 {
330  error_t error;
331 
332  //Initialize status code
333  error = NO_ERROR;
334 
335  //Check parameters
336  if(key != NULL && data != NULL && length != NULL)
337  {
338  //Edwards elliptic curve?
339  if(key->curve != NULL && key->curve->type == EC_CURVE_TYPE_EDWARDS)
340  {
341  //Determine the length of the public key
342  *length = (key->curve->fieldSize / 8) + 1;
343  //Copy the public key
344  osMemcpy(data, key->q, *length);
345  }
346  else
347  {
348  //Invalid elliptic curve
350  }
351  }
352  else
353  {
354  //Report an error
355  error = ERROR_INVALID_PARAMETER;
356  }
357 
358  //Return status code
359  return error;
360 }
361 
362 
363 /**
364  * @brief Import an EdDSA private key
365  * @param[out] key EdDSA private key
366  * @param[in] data Pointer to the octet string
367  * @param[in] length Length of the octet string, in bytes
368  * @return Error code
369  **/
370 
372  const uint8_t *data, size_t length)
373 {
374  error_t error;
375 
376  //Initialize status code
377  error = NO_ERROR;
378 
379  //Check parameters
380  if(key != NULL && curve != NULL && data != NULL)
381  {
382  //Edwards elliptic curve?
383  if(curve->type == EC_CURVE_TYPE_EDWARDS)
384  {
385  //Check the length of the private key
386  if(length == ((curve->fieldSize / 8) + 1))
387  {
388  //Save elliptic curve parameters
389  key->curve = curve;
390  //Copy the private key
391  osMemcpy(key->d, data, length);
392  }
393  else
394  {
395  //The length of the public key is not acceptable
396  error = ERROR_INVALID_KEY_LENGTH;
397  }
398  }
399  else
400  {
401  //Invalid elliptic curve
403  }
404  }
405  else
406  {
407  //Report an error
408  error = ERROR_INVALID_PARAMETER;
409  }
410 
411  //Return status code
412  return error;
413 }
414 
415 
416 /**
417  * @brief Export an EdDSA private key
418  * @param[in] key EdDSA private key
419  * @param[out] data Pointer to the octet string
420  * @param[out] length Length of the octet string, in bytes
421  * @return Error code
422  **/
423 
425  size_t *length)
426 {
427  error_t error;
428 
429  //Initialize status code
430  error = NO_ERROR;
431 
432  //Check parameters
433  if(key != NULL && data != NULL && length != NULL)
434  {
435  //Edwards elliptic curve?
436  if(key->curve != NULL && key->curve->type == EC_CURVE_TYPE_EDWARDS)
437  {
438  //Determine the length of the private key
439  *length = (key->curve->fieldSize / 8) + 1;
440  //Copy the private key
441  osMemcpy(data, key->d, *length);
442  }
443  else
444  {
445  //Invalid elliptic curve
447  }
448  }
449  else
450  {
451  //Report an error
452  error = ERROR_INVALID_PARAMETER;
453  }
454 
455  //Return status code
456  return error;
457 }
458 
459 #endif
error_t eddsaImportPublicKey(EddsaPublicKey *key, const EcCurve *curve, const uint8_t *data, size_t length)
Import an EdDSA public key.
Definition: eddsa.c:274
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
error_t eddsaExportPrivateKey(const EddsaPrivateKey *key, uint8_t *data, size_t *length)
Export an EdDSA private key.
Definition: eddsa.c:424
uint8_t d[EDDSA_MAX_PRIVATE_KEY_LEN]
Private key.
Definition: eddsa.h:77
#define PrngAlgo
Definition: crypto.h:973
const EcCurve * curve
Elliptic curve parameters.
Definition: eddsa.h:76
error_t eddsaExportPublicKey(const EddsaPublicKey *key, uint8_t *data, size_t *length)
Export an EdDSA public key.
Definition: eddsa.c:327
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:222
#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
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 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
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 eddsaImportPrivateKey(EddsaPrivateKey *key, const EcCurve *curve, const uint8_t *data, size_t length)
Import an EdDSA private key.
Definition: eddsa.c:371
#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.