ecdh.c
Go to the documentation of this file.
1 /**
2  * @file ecdh.c
3  * @brief ECDH (Elliptic Curve Diffie-Hellman) key exchange
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/ecdh.h"
37 #include "ecc/ec_misc.h"
38 #include "debug.h"
39 
40 //Check crypto library configuration
41 #if (ECDH_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Initialize ECDH context
46  * @param[in] context Pointer to the ECDH context
47  **/
48 
49 void ecdhInit(EcdhContext *context)
50 {
51  //Initialize elliptic curve parameters
52  context->curve = NULL;
53 
54  //Initialize private and public keys
55  ecInitPrivateKey(&context->da);
56  ecInitPublicKey(&context->qb);
57 }
58 
59 
60 /**
61  * @brief Release ECDH context
62  * @param[in] context Pointer to the ECDH context
63  **/
64 
65 void ecdhFree(EcdhContext *context)
66 {
67  //Release elliptic curve parameters
68  context->curve = NULL;
69 
70  //Release private and public keys
71  ecFreePrivateKey(&context->da);
72  ecFreePublicKey(&context->qb);
73 }
74 
75 
76 /**
77  * @brief Specify the elliptic curve to use
78  * @param[in] context Pointer to the ECDH context
79  * @param[in] curve Elliptic curve parameters
80  * @return Error code
81  **/
82 
83 error_t ecdhSetCurve(EcdhContext *context, const EcCurve *curve)
84 {
85  error_t error;
86 
87  //Initialize status code
88  error = NO_ERROR;
89 
90  //Check parameters
91  if(context != NULL && curve != NULL)
92  {
93  //Save elliptic curve parameters
94  context->curve = curve;
95  }
96  else
97  {
98  //Report an error
100  }
101 
102  //Return status code
103  return error;
104 }
105 
106 
107 /**
108  * @brief ECDH key pair generation
109  * @param[in] context Pointer to the ECDH context
110  * @param[in] prngAlgo PRNG algorithm
111  * @param[in] prngContext Pointer to the PRNG context
112  * @return Error code
113  **/
114 
116  void *prngContext)
117 {
118  error_t error;
119 
120  //Debug message
121  TRACE_DEBUG("Generating ECDH key pair...\r\n");
122 
123  //Weierstrass elliptic curve?
124  if(context->curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
125  context->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
126  context->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
127  {
128  //Generate an EC key pair
129  error = ecGenerateKeyPair(prngAlgo, prngContext, context->curve,
130  &context->da, NULL);
131  }
132 #if (X25519_SUPPORT == ENABLED)
133  //Curve25519 elliptic curve?
134  else if(context->curve->type == EC_CURVE_TYPE_MONTGOMERY &&
135  context->curve->fieldSize == CURVE25519_BIT_LEN)
136  {
137  uint8_t da[CURVE25519_BYTE_LEN];
138  uint8_t qa[CURVE25519_BYTE_LEN];
139  uint8_t g[CURVE25519_BYTE_LEN];
140 
141  //Generate 32 random bytes
142  error = prngAlgo->read(prngContext, da, CURVE25519_BYTE_LEN);
143 
144  //Check status code
145  if(!error)
146  {
147  //Debug message
148  TRACE_DEBUG(" Private key:\r\n");
150 
151  //Get the u-coordinate of the base point
152  error = ecScalarExport(context->curve->g.x, CURVE25519_WORD_LEN, g,
154  }
155 
156  //Check status code
157  if(!error)
158  {
159  //Generate the public value using X25519 function
160  error = x25519(qa, da, g);
161  }
162 
163  //Check status code
164  if(!error)
165  {
166  //Save private key
167  error = ecImportPrivateKey(&context->da, X25519_CURVE, da,
169  }
170 
171  //Check status code
172  if(!error)
173  {
174  //Debug message
175  TRACE_DEBUG(" Public key:\r\n");
177 
178  //Save public key
179  error = ecImportPublicKey(&context->da.q, X25519_CURVE, qa,
181  }
182  }
183 #endif
184 #if (X448_SUPPORT == ENABLED)
185  //Curve448 elliptic curve?
186  else if(context->curve->type == EC_CURVE_TYPE_MONTGOMERY &&
187  context->curve->fieldSize == CURVE448_BIT_LEN)
188  {
189  uint8_t da[CURVE448_BYTE_LEN];
190  uint8_t qa[CURVE448_BYTE_LEN];
191  uint8_t g[CURVE448_BYTE_LEN];
192 
193  //Generate 56 random bytes
194  error = prngAlgo->read(prngContext, da, CURVE448_BYTE_LEN);
195 
196  //Check status code
197  if(!error)
198  {
199  //Debug message
200  TRACE_DEBUG(" Private key:\r\n");
202 
203  //Get the u-coordinate of the base point
204  error = ecScalarExport(context->curve->g.x, CURVE448_WORD_LEN, g,
206  }
207 
208  //Check status code
209  if(!error)
210  {
211  //Generate the public value using X448 function
212  error = x448(qa, da, g);
213  }
214 
215  //Check status code
216  if(!error)
217  {
218  //Save private key
219  error = ecImportPrivateKey(&context->da, X448_CURVE, da,
221  }
222 
223  //Check status code
224  if(!error)
225  {
226  //Debug message
227  TRACE_DEBUG(" Public key:\r\n");
229 
230  //Save public key
231  error = ecImportPublicKey(&context->da.q, X448_CURVE, qa,
233  }
234  }
235 #endif
236  //Invalid elliptic curve?
237  else
238  {
239  //Report an error
240  error = ERROR_INVALID_TYPE;
241  }
242 
243  //Return status code
244  return error;
245 }
246 
247 
248 /**
249  * @brief Export our own public key
250  * @param[in] context Pointer to the ECDH context
251  * @param[out] output Pointer to the octet string
252  * @param[out] written Length of the octet string, in bytes
253  * @param[in] format EC public key format (X9.63 or raw format)
254  * @return Error code
255  **/
256 
257 error_t ecdhExportPublicKey(EcdhContext *context, uint8_t *output,
258  size_t *written, EcPublicKeyFormat format)
259 {
260  //Export our own public key
261  return ecExportPublicKey(&context->da.q, output, written, format);
262 }
263 
264 
265 /**
266  * @brief Import peer's public key
267  * @param[in] context Pointer to the ECDH context
268  * @param[in] input Pointer to the octet string
269  * @param[in] length Length of the octet string, in bytes
270  * @param[in] format EC public key format (X9.63 or raw format)
271  * @return Error code
272  **/
273 
274 error_t ecdhImportPeerPublicKey(EcdhContext *context, const uint8_t *input,
275  size_t length, EcPublicKeyFormat format)
276 {
277  error_t error;
278 
279  //Import peer's public key
280  error = ecImportPublicKey(&context->qb, context->curve, input, length, format);
281 
282  //Check status code
283  if(!error)
284  {
285  //Ensure the public key is acceptable
286  error = ecdhCheckPublicKey(context, &context->qb);
287  }
288 
289  //Return status code
290  return error;
291 }
292 
293 
294 /**
295  * @brief Check public key
296  * @param[in] context Pointer to the ECDH context
297  * @param[in] publicKey Public key to be checked
298  * @return Error code
299  **/
300 
302 {
303  bool_t valid;
304 
305  //Weierstrass elliptic curve?
306  if(context->curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
307  context->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
308  context->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
309  {
310  //Initialize flag
311  valid = TRUE;
312 
313  //Verify that the curve is valid
314  if(publicKey->curve != context->curve)
315  {
316  valid = FALSE;
317  }
318 
319  //Verify that 0 <= Qx < p
320  if(valid)
321  {
322  if(ecScalarComp(publicKey->q.x, context->curve->p,
323  EC_MAX_MODULUS_SIZE) >= 0)
324  {
325  valid = FALSE;
326  }
327  }
328 
329  //Verify that 0 <= Qy < p
330  if(valid)
331  {
332  if(ecScalarComp(publicKey->q.y, context->curve->p,
333  EC_MAX_MODULUS_SIZE) >= 0)
334  {
335  valid = FALSE;
336  }
337  }
338 
339  //Check whether the point is on the curve
340  if(valid)
341  {
342  valid = ecIsPointAffine(context->curve, &publicKey->q);
343  }
344 
345  //If the cofactor is not 1, the implementation must verify that n.Q is
346  //the point at the infinity
347  if(valid)
348  {
349  if(context->curve->h != 1)
350  {
351  error_t error;
352  uint_t pLen;
353  EcPoint3 r;
354 
355  //Initialize flag
356  valid = FALSE;
357 
358  //Get the length of the modulus, in words
359  pLen = (context->curve->fieldSize + 31) / 32;
360 
361  //Convert the public key to projective representation
362  ecProjectify(context->curve, &r, &publicKey->q);
363 
364  //Compute R = n.Q
365  error = ecMulFast(context->curve, &r, context->curve->q, &r);
366 
367  //Check status code
368  if(!error)
369  {
370  //Verify that the result is the point at the infinity
371  if(ecScalarCompInt(r.z, 0, pLen) == 0)
372  {
373  valid = TRUE;
374  }
375  }
376  }
377  }
378  }
379 #if (X25519_SUPPORT == ENABLED || X448_SUPPORT == ENABLED)
380  //Curve25519 or Curve448 elliptic curve?
381  else if(context->curve->type == EC_CURVE_TYPE_MONTGOMERY)
382  {
383  //The public key does not need to be validated
384  valid = TRUE;
385  }
386 #endif
387  //Invalid elliptic curve?
388  else
389  {
390  //Just for sanity
391  valid = FALSE;
392  }
393 
394  //Return status code
395  if(valid)
396  {
397  return NO_ERROR;
398  }
399  else
400  {
402  }
403 }
404 
405 
406 /**
407  * @brief Compute ECDH shared secret
408  * @param[in] context Pointer to the ECDH context
409  * @param[out] output Buffer where to store the shared secret
410  * @param[in] outputSize Size of the buffer in bytes
411  * @param[out] outputLen Length of the resulting shared secret
412  * @return Error code
413  **/
414 
415 error_t ecdhComputeSharedSecret(EcdhContext *context, uint8_t *output,
416  size_t outputSize, size_t *outputLen)
417 {
418  error_t error;
419 
420  //Debug message
421  TRACE_DEBUG("Computing Diffie-Hellman shared secret...\r\n");
422 
423  //Weierstrass elliptic curve?
424  if(context->curve->type == EC_CURVE_TYPE_WEIERSTRASS ||
425  context->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A0 ||
426  context->curve->type == EC_CURVE_TYPE_WEIERSTRASS_A3)
427  {
428  size_t k;
429  EcPoint3 q;
430  EcPoint3 z;
431 
432  //Get the length in octets of the prime modulus
433  k = (context->curve->fieldSize + 7) / 8;
434 
435  //Make sure that the output buffer is large enough
436  if(outputSize >= k)
437  {
438  //Length of the resulting shared secret
439  *outputLen = k;
440 
441  //Convert the peer's public key to projective representation
442  ecProjectify(context->curve, &q, &context->qb.q);
443 
444  //Compute Z = da.Qb
445  error = ecMulRegular(context->curve, &z, context->da.d, &q);
446 
447  //Check status code
448  if(!error)
449  {
450  //Convert Z to affine representation
451  error = ecAffinify(context->curve, &z, &z);
452  }
453 
454  //Check status code
455  if(!error)
456  {
457  //The shared secret is the x-coordinate of Z
458  error = ecScalarExport(z.x, (k + 3) / 4, output, k,
460  }
461  }
462  else
463  {
464  //Report an error
465  error = ERROR_INVALID_LENGTH;
466  }
467  }
468 #if (X25519_SUPPORT == ENABLED)
469  //Curve25519 elliptic curve?
470  else if(context->curve->type == EC_CURVE_TYPE_MONTGOMERY &&
471  context->curve->fieldSize == CURVE25519_BIT_LEN)
472  {
473  uint_t i;
474  uint8_t mask;
475  uint8_t da[CURVE25519_BYTE_LEN];
476  uint8_t qb[CURVE25519_BYTE_LEN];
477 
478  //Make sure that the output buffer is large enough
479  if(outputSize >= CURVE25519_BYTE_LEN)
480  {
481  //Length of the resulting shared secret
482  *outputLen = CURVE25519_BYTE_LEN;
483 
484  //Get private key
485  error = ecScalarExport(context->da.d, CURVE25519_WORD_LEN, da,
487 
488  //Check status code
489  if(!error)
490  {
491  //Get peer's public key
492  error = ecScalarExport(context->qb.q.x, CURVE25519_WORD_LEN, qb,
494  }
495 
496  //Check status code
497  if(!error)
498  {
499  //Generate shared secret K using X25519 function
500  error = x25519(output, da, qb);
501  }
502 
503  //Since Curve25519 has a cofactor of 8, an input point of small order
504  //will eliminate any contribution from the other party's private key
505  if(!error)
506  {
507  //This situation can be detected by checking for the all-zero output
508  for(mask = 0, i = 0; i < CURVE25519_BYTE_LEN; i++)
509  {
510  mask |= output[i];
511  }
512 
513  //Check whether K is the all-zero value and abort if so (refer to
514  //RFC 8422, sections 5.10 and 5.11)
515  if(mask == 0)
516  {
517  error = ERROR_ILLEGAL_PARAMETER;
518  }
519  }
520  }
521  else
522  {
523  //Report an error
524  error = ERROR_INVALID_LENGTH;
525  }
526  }
527 #endif
528 #if (X448_SUPPORT == ENABLED)
529  //Curve448 elliptic curve?
530  else if(context->curve->type == EC_CURVE_TYPE_MONTGOMERY &&
531  context->curve->fieldSize == CURVE448_BIT_LEN)
532  {
533  uint_t i;
534  uint8_t mask;
535  uint8_t da[CURVE448_BYTE_LEN];
536  uint8_t qb[CURVE448_BYTE_LEN];
537 
538  //Make sure that the output buffer is large enough
539  if(outputSize >= CURVE448_BYTE_LEN)
540  {
541  //Length of the resulting shared secret
542  *outputLen = CURVE448_BYTE_LEN;
543 
544  //Get private key
545  error = ecScalarExport(context->da.d, CURVE448_WORD_LEN, da,
547 
548  //Check status code
549  if(!error)
550  {
551  //Get peer's public key
552  error = ecScalarExport(context->qb.q.x, CURVE448_WORD_LEN, qb,
554  }
555 
556  //Check status code
557  if(!error)
558  {
559  //Generate shared secret K using X448 function
560  error = x448(output, da, qb);
561  }
562 
563  //Since Curve448 has a cofactor of 4, an input point of small order
564  //will eliminate any contribution from the other party's private key
565  if(!error)
566  {
567  //This situation can be detected by checking for the all-zero output
568  for(mask = 0, i = 0; i < CURVE448_BYTE_LEN; i++)
569  {
570  mask |= output[i];
571  }
572 
573  //Check whether K is the all-zero value and abort if so (refer to
574  //RFC 8422, sections 5.10 and 5.11)
575  if(mask == 0)
576  {
577  error = ERROR_ILLEGAL_PARAMETER;
578  }
579  }
580  }
581  else
582  {
583  //Report an error
584  error = ERROR_INVALID_LENGTH;
585  }
586  }
587 #endif
588  //Invalid elliptic curve?
589  else
590  {
591  //Report an error
592  error = ERROR_INVALID_TYPE;
593  }
594 
595  //Check status code
596  if(!error)
597  {
598  //Debug message
599  TRACE_DEBUG(" Shared secret (%" PRIuSIZE " bytes):\r\n", *outputLen);
600  TRACE_DEBUG_ARRAY(" ", output, *outputLen);
601  }
602 
603  //Return status code
604  return error;
605 }
606 
607 #endif
__weak_func error_t ecGenerateKeyPair(const PrngAlgo *prngAlgo, void *prngContext, const EcCurve *curve, EcPrivateKey *privateKey, EcPublicKey *publicKey)
EC key pair generation.
Definition: ec.c:117
@ EC_CURVE_TYPE_WEIERSTRASS_A3
Definition: ec.h:362
__weak_func error_t ecAffinify(const EcCurve *curve, EcPoint3 *r, const EcPoint3 *s)
Recover affine representation.
Definition: ec.c:791
@ EC_CURVE_TYPE_MONTGOMERY
Definition: ec.h:363
int bool_t
Definition: compiler_port.h:61
__weak_func error_t ecMulFast(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (fast calculation)
Definition: ec.c:1223
error_t ecScalarExport(const uint32_t *a, uint_t n, uint8_t *output, size_t length, EcScalarFormat format)
Integer to octet string conversion.
Definition: ec_misc.c:150
error_t x448(uint8_t *r, const uint8_t *k, const uint8_t *u)
X448 function (scalar multiplication on Curve448)
Definition: x448.c:53
#define PrngAlgo
Definition: crypto.h:980
#define CURVE448_BIT_LEN
Definition: curve448.h:45
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:244
#define TRUE
Definition: os_port.h:50
EcPublicKey qb
Peer's EC public key.
Definition: ecdh.h:63
void ecdhFree(EcdhContext *context)
Release ECDH context.
Definition: ecdh.c:65
error_t ecImportPublicKey(EcPublicKey *key, const EcCurve *curve, const uint8_t *input, size_t length, EcPublicKeyFormat format)
Import an EC public key.
Definition: ec.c:263
#define CURVE448_BYTE_LEN
Definition: curve448.h:46
ECDH (Elliptic Curve Diffie-Hellman) key exchange.
const EcCurve * curve
Elliptic curve parameters.
Definition: ecdh.h:61
error_t ecExportPublicKey(const EcPublicKey *key, uint8_t *output, size_t *written, EcPublicKeyFormat format)
Export an EC public key.
Definition: ec.c:378
uint32_t y[EC_MAX_MODULUS_SIZE]
y-coordinate
Definition: ec.h:400
__weak_func error_t x25519(uint8_t *r, const uint8_t *k, const uint8_t *u)
X25519 function (scalar multiplication on Curve25519)
Definition: x25519.c:53
uint8_t r
Definition: ndp.h:346
#define FALSE
Definition: os_port.h:46
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t ecdhCheckPublicKey(EcdhContext *context, const EcPublicKey *publicKey)
Check public key.
Definition: ecdh.c:301
error_t
Error codes.
Definition: error.h:43
#define CURVE25519_BYTE_LEN
Definition: curve25519.h:46
void ecInitPublicKey(EcPublicKey *key)
Initialize an EC public key.
Definition: ec.c:52
Helper routines for ECC.
#define CURVE448_WORD_LEN
Definition: curve448.h:47
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ EC_SCALAR_FORMAT_LITTLE_ENDIAN
Definition: ec_misc.h:50
error_t ecImportPrivateKey(EcPrivateKey *key, const EcCurve *curve, const uint8_t *input, size_t length)
Import an EC private key.
Definition: ec.c:514
EcPublicKeyFormat
EC public key format.
Definition: ec.h:385
General definitions for cryptographic algorithms.
EcPublicKey q
Public key.
Definition: ec.h:436
@ EC_PUBLIC_KEY_FORMAT_RAW
Definition: ec.h:387
uint8_t mask
Definition: web_socket.h:319
@ ERROR_INVALID_TYPE
Definition: error.h:115
void ecFreePrivateKey(EcPrivateKey *key)
Release an EC private key.
Definition: ec.c:100
uint8_t length
Definition: tcp.h:375
#define CURVE25519_BIT_LEN
Definition: curve25519.h:45
error_t ecdhComputeSharedSecret(EcdhContext *context, uint8_t *output, size_t outputSize, size_t *outputLen)
Compute ECDH shared secret.
Definition: ecdh.c:415
uint8_t z
Definition: dns_common.h:193
error_t ecdhImportPeerPublicKey(EcdhContext *context, const uint8_t *input, size_t length, EcPublicKeyFormat format)
Import peer's public key.
Definition: ecdh.c:274
EC public key.
Definition: ec.h:421
#define TRACE_DEBUG(...)
Definition: debug.h:119
void ecdhInit(EcdhContext *context)
Initialize ECDH context.
Definition: ecdh.c:49
__weak_func bool_t ecIsPointAffine(const EcCurve *curve, const EcPoint *s)
Check whether the affine point S is on the curve.
Definition: ec.c:840
EcPrivateKey da
One's own EC key pair.
Definition: ecdh.h:62
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:120
#define CURVE25519_WORD_LEN
Definition: curve25519.h:47
uint32_t d[EC_MAX_ORDER_SIZE]
Private key.
Definition: ec.h:434
int_t ecScalarCompInt(const uint32_t *a, uint32_t b, uint_t n)
Compare integers.
Definition: ec_misc.c:374
@ EC_SCALAR_FORMAT_BIG_ENDIAN
Definition: ec_misc.h:51
EC point (projective coordinates)
Definition: ec.h:409
void ecInitPrivateKey(EcPrivateKey *key)
Initialize an EC private key.
Definition: ec.c:80
void ecProjectify(const EcCurve *curve, EcPoint3 *r, const EcPoint *s)
Compute projective representation.
Definition: ec.c:762
__weak_func error_t ecMulRegular(const EcCurve *curve, EcPoint3 *r, const uint32_t *d, const EcPoint3 *s)
Scalar multiplication (regular calculation)
Definition: ec.c:1354
EcPoint q
Public key.
Definition: ec.h:423
#define X448_CURVE
Definition: ec_curves.h:71
@ EC_CURVE_TYPE_WEIERSTRASS
Definition: ec.h:360
error_t ecdhSetCurve(EcdhContext *context, const EcCurve *curve)
Specify the elliptic curve to use.
Definition: ecdh.c:83
#define EcCurve
Definition: ec.h:346
int_t ecScalarComp(const uint32_t *a, const uint32_t *b, uint_t n)
Compare integers.
Definition: ec_misc.c:337
#define PRIuSIZE
unsigned int uint_t
Definition: compiler_port.h:57
uint32_t x[EC_MAX_MODULUS_SIZE]
x-coordinate
Definition: ec.h:399
error_t ecdhExportPublicKey(EcdhContext *context, uint8_t *output, size_t *written, EcPublicKeyFormat format)
Export our own public key.
Definition: ecdh.c:257
const EcCurve * curve
Elliptic curve parameters.
Definition: ec.h:422
@ EC_CURVE_TYPE_WEIERSTRASS_A0
Definition: ec.h:361
ECDH context.
Definition: ecdh.h:60
#define EC_MAX_MODULUS_SIZE
Definition: ec.h:284
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
void ecFreePublicKey(EcPublicKey *key)
Release an EC public key.
Definition: ec.c:68
error_t ecdhGenerateKeyPair(EcdhContext *context, const PrngAlgo *prngAlgo, void *prngContext)
ECDH key pair generation.
Definition: ecdh.c:115
#define X25519_CURVE
Definition: ec_curves.h:70