Coverage Report

Created: 2026-05-18 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/wolfcrypt/src/curve25519.c
Line
Count
Source
1
/* curve25519.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
23
 /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */
24
25
/*
26
 * X25519 configuration macros:
27
 *
28
 * WC_X25519_NONBLOCK: Enable non-blocking support for key gen and shared
29
 *                     secret. Requires CURVE25519_SMALL. Default: off.
30
 */
31
32
 #include <wolfssl/wolfcrypt/libwolfssl_sources.h>
33
34
#ifdef NO_CURVED25519_X64
35
    #undef USE_INTEL_SPEEDUP
36
#endif
37
38
#ifdef HAVE_CURVE25519
39
40
#include <wolfssl/wolfcrypt/curve25519.h>
41
#include <wolfssl/wolfcrypt/ge_operations.h>
42
#include <wolfssl/wolfcrypt/error-crypt.h>
43
#include <wolfssl/wolfcrypt/logging.h>
44
#ifdef NO_INLINE
45
    #include <wolfssl/wolfcrypt/misc.h>
46
#else
47
    #define WOLFSSL_MISC_INCLUDED
48
    #include <wolfcrypt/src/misc.c>
49
#endif
50
51
#if defined(FREESCALE_LTC_ECC)
52
    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
53
#endif
54
#ifdef WOLFSSL_SE050
55
    #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
56
#endif
57
58
#ifdef WOLF_CRYPTO_CB
59
    #include <wolfssl/wolfcrypt/cryptocb.h>
60
#endif
61
62
#if defined(WOLFSSL_CURVE25519_BLINDING)
63
    #if defined(CURVE25519_SMALL)
64
        #error "Blinding not needed nor available for small implementation"
65
    #elif defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM)
66
        #error "Blinding not needed nor available for assembly implementation"
67
    #elif defined(WOLFSSL_CURVE25519_USE_ED25519)
68
        #error "Ed25519 base scalar mult cannot be used with blinding "
69
    #endif
70
#endif
71
72
#if defined(WOLFSSL_USE_SAVE_VECTOR_REGISTERS) && !defined(USE_INTEL_SPEEDUP)
73
    /* force off unneeded vector register save/restore. */
74
    #undef SAVE_VECTOR_REGISTERS
75
    #define SAVE_VECTOR_REGISTERS(fail_clause) SAVE_NO_VECTOR_REGISTERS(fail_clause)
76
    #undef RESTORE_VECTOR_REGISTERS
77
    #define RESTORE_VECTOR_REGISTERS() RESTORE_NO_VECTOR_REGISTERS()
78
#endif
79
80
const curve25519_set_type curve25519_sets[] = {
81
    {
82
        CURVE25519_KEYSIZE,
83
        "CURVE25519",
84
    }
85
};
86
87
#if (!defined(WOLFSSL_CURVE25519_USE_ED25519) && \
88
     !(defined(CURVED25519_X64) || (defined(WOLFSSL_ARMASM) && \
89
     defined(__aarch64__)))) || defined(WOLFSSL_CURVE25519_BLINDING) || \
90
     defined(WC_X25519_NONBLOCK)
91
static const word32 kCurve25519BasePoint[CURVE25519_KEYSIZE/sizeof(word32)] = {
92
#ifdef BIG_ENDIAN_ORDER
93
    0x09000000
94
#else
95
    9
96
#endif
97
};
98
#endif /* !WOLFSSL_CURVE25519_USE_ED25519 || WOLFSSL_CURVE25519_BLINDING */
99
100
/* Curve25519 private key must be less than order */
101
/* These functions clamp private k and check it */
102
static WC_INLINE int curve25519_priv_clamp(byte* priv)
103
3.79k
{
104
3.79k
    priv[0]  &= 248;
105
3.79k
    priv[CURVE25519_KEYSIZE-1] &= 127;
106
3.79k
    priv[CURVE25519_KEYSIZE-1] |= 64;
107
3.79k
    return 0;
108
3.79k
}
109
static WC_INLINE int curve25519_priv_clamp_check(const byte* priv)
110
4.16k
{
111
    /* check that private part of key has been clamped per RFC 7748 section 5:
112
     *   bits 0-2 of byte 0 must be clear  (priv[0] &= 248)
113
     *   bit 7 of byte 31 must be clear    (priv[31] &= 127)
114
     *   bit 6 of byte 31 must be set      (priv[31] |= 64)  */
115
4.16k
    int ret = 0;
116
4.16k
    if ((priv[0] & ~248) ||
117
4.16k
        (priv[CURVE25519_KEYSIZE-1] & 128) ||
118
4.16k
        !(priv[CURVE25519_KEYSIZE-1] & 64)) {
119
0
        ret = ECC_BAD_ARG_E;
120
0
    }
121
4.16k
    return ret;
122
4.16k
}
123
124
static WC_INLINE void curve25519_copy_point(byte* out, const byte* point,
125
    int endian)
126
4.42k
{
127
4.42k
    if (endian == EC25519_BIG_ENDIAN) {
128
3
        int i;
129
        /* put shared secret key in Big Endian format */
130
99
        for (i = 0; i < CURVE25519_KEYSIZE; i++) {
131
96
            out[i] = point[CURVE25519_KEYSIZE - i -1];
132
96
        }
133
3
    }
134
4.42k
    else { /* put shared secret key in Little Endian format */
135
4.42k
        XMEMCPY(out, point, CURVE25519_KEYSIZE);
136
4.42k
    }
137
4.42k
}
138
139
/* compute the public key from an existing private key, using bare vectors.
140
 *
141
 * return value is propagated from curve25519() (0 on success), or
142
 * ECC_BAD_ARG_E, and the byte vectors are little endian.
143
 */
144
int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
145
                           const byte* priv)
146
226
{
147
226
    int ret;
148
#ifdef FREESCALE_LTC_ECC
149
    const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
150
    ECPoint wc_pub;
151
#endif
152
153
226
    if ( (public_size != CURVE25519_KEYSIZE) ||
154
226
        (private_size != CURVE25519_KEYSIZE)) {
155
0
        return ECC_BAD_ARG_E;
156
0
    }
157
226
    if ((pub == NULL) || (priv == NULL)) {
158
0
        return ECC_BAD_ARG_E;
159
0
    }
160
161
    /* check clamping */
162
226
    ret = curve25519_priv_clamp_check(priv);
163
226
    if (ret != 0)
164
0
        return ret;
165
166
#ifdef FREESCALE_LTC_ECC
167
    /* input basepoint on Weierstrass curve */
168
    ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
169
    if (ret == 0) {
170
        XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE);
171
    }
172
#else
173
#ifndef WOLFSSL_CURVE25519_BLINDING
174
    fe_init();
175
176
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
177
178
#if defined(WOLFSSL_CURVE25519_USE_ED25519)
179
    {
180
        ge_p3 A;
181
182
        ge_scalarmult_base(&A, priv);
183
    #ifndef CURVE25519_SMALL
184
        fe_add(A.X, A.Z, A.Y);
185
        fe_sub(A.T, A.Z, A.Y);
186
        fe_invert(A.T, A.T);
187
        fe_mul(A.T, A.X, A.T);
188
        fe_tobytes(pub, A.T);
189
    #else
190
        lm_add(A.X, A.Z, A.Y);
191
        lm_sub(A.T, A.Z, A.Y);
192
        lm_invert(A.T, A.T);
193
        lm_mul(pub, A.X, A.T);
194
    #endif
195
        ret = 0;
196
    }
197
#elif defined(CURVED25519_X64) || (defined(WOLFSSL_ARMASM) && \
198
    defined(__aarch64__))
199
    ret = curve25519_base(pub, priv);
200
#else
201
    ret = curve25519(pub, priv, (byte*)kCurve25519BasePoint);
202
#endif
203
204
    RESTORE_VECTOR_REGISTERS();
205
#else
206
226
    {
207
226
        WC_RNG rng;
208
209
226
        ret = wc_InitRng(&rng);
210
226
        if (ret == 0) {
211
144
            ret = wc_curve25519_make_pub_blind(public_size, pub, private_size,
212
144
                priv, &rng);
213
214
144
            wc_FreeRng(&rng);
215
144
        }
216
226
    }
217
226
#endif /* !WOLFSSL_CURVE25519_BLINDING */
218
226
#endif /* FREESCALE_LTC_ECC */
219
220
/* If WOLFSSL_CURVE25519_BLINDING is defined, this check is run in
221
 * wc_curve25519_make_pub_blind since it could be called directly. */
222
#if !defined(WOLFSSL_CURVE25519_BLINDING) || defined(FREESCALE_LTC_ECC)
223
    if (ret == 0) {
224
        ret = wc_curve25519_check_public(pub, (word32)public_size,
225
                                    EC25519_LITTLE_ENDIAN);
226
    }
227
#endif
228
229
226
    return ret;
230
226
}
231
232
#ifdef WOLFSSL_CURVE25519_BLINDING
233
#ifndef FREESCALE_LTC_ECC
234
#ifndef WOLFSSL_CURVE25519_BLINDING_RAND_CNT
235
8.39k
    #define WOLFSSL_CURVE25519_BLINDING_RAND_CNT    10
236
#endif
237
static int curve25519_smul_blind(byte* rp, const byte* n, const byte* p,
238
    WC_RNG* rng)
239
4.19k
{
240
4.19k
    int ret;
241
4.19k
    byte a[CURVE25519_KEYSIZE];
242
4.19k
    byte n_a[CURVE25519_KEYSIZE];
243
4.19k
    byte rz[CURVE25519_KEYSIZE];
244
4.19k
    int i;
245
4.19k
    int cnt;
246
247
4.19k
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
248
249
    /* Generate random z. */
250
4.21k
    for (cnt = 0; cnt < WOLFSSL_CURVE25519_BLINDING_RAND_CNT; cnt++) {
251
4.21k
        ret = wc_RNG_GenerateBlock(rng, rz, sizeof(rz));
252
4.21k
        if (ret < 0) {
253
19
            goto cleanup;
254
19
        }
255
4.89k
        for (i = CURVE25519_KEYSIZE - 1; i >= 0; i--) {
256
4.87k
            if (rz[i] != 0xff)
257
4.17k
                break;
258
4.87k
        }
259
4.19k
        if ((i >= 0) || (rz[0] <= 0xec)) {
260
4.17k
            break;
261
4.17k
        }
262
4.19k
    }
263
4.17k
    if (cnt == WOLFSSL_CURVE25519_BLINDING_RAND_CNT) {
264
0
        ret = RNG_FAILURE_E;
265
0
        goto cleanup;
266
0
    }
267
268
    /* Generate 253 random bits. */
269
4.17k
    ret = wc_RNG_GenerateBlock(rng, a, sizeof(a));
270
4.17k
    if (ret != 0)
271
18
        goto cleanup;
272
4.16k
    a[CURVE25519_KEYSIZE-1] &= 0x7f;
273
    /* k' = k ^ 2k ^ a */
274
4.16k
    n_a[0] = n[0] ^ (byte)(n[0] << 1) ^ a[0];
275
133k
    for (i = 1; i < CURVE25519_KEYSIZE; i++) {
276
128k
        byte b1, b2, b3;
277
128k
        b1 = n[i] ^ a[i];
278
128k
        b2 = (byte)(n[i] << 1) ^ a[i];
279
128k
        b3 = (n[i-1] >> 7) ^ a[i];
280
128k
        n_a[i] = b1 ^ b2 ^ b3;
281
128k
    }
282
    /* Scalar multiple blinded scalar with blinding value. */
283
4.16k
    ret = curve25519_blind(rp, n_a, a, p, rz);
284
285
4.19k
cleanup:
286
4.19k
    ForceZero(a, sizeof(a));
287
4.19k
    ForceZero(n_a, sizeof(n_a));
288
4.19k
    ForceZero(rz, sizeof(rz));
289
290
4.19k
    RESTORE_VECTOR_REGISTERS();
291
292
4.19k
    return ret;
293
4.16k
}
294
#endif
295
296
int wc_curve25519_make_pub_blind(int public_size, byte* pub, int private_size,
297
                                 const byte* priv, WC_RNG* rng)
298
3.93k
{
299
3.93k
    int ret;
300
#ifdef FREESCALE_LTC_ECC
301
    const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
302
    ECPoint wc_pub;
303
#endif
304
305
3.93k
    if ( (public_size != CURVE25519_KEYSIZE) ||
306
3.93k
        (private_size != CURVE25519_KEYSIZE)) {
307
0
        return ECC_BAD_ARG_E;
308
0
    }
309
3.93k
    if ((pub == NULL) || (priv == NULL)) {
310
0
        return ECC_BAD_ARG_E;
311
0
    }
312
3.93k
#ifndef FREESCALE_LTC_ECC
313
3.93k
    if (rng == NULL) {
314
0
        return ECC_BAD_ARG_E;
315
0
    }
316
3.93k
#endif
317
318
    /* check clamping */
319
3.93k
    ret = curve25519_priv_clamp_check(priv);
320
3.93k
    if (ret != 0)
321
0
        return ret;
322
323
#ifdef FREESCALE_LTC_ECC
324
    /* input basepoint on Weierstrass curve */
325
    ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
326
    if (ret == 0) {
327
        XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE);
328
    }
329
#else
330
3.93k
    fe_init();
331
332
3.93k
    ret = curve25519_smul_blind(pub, priv, (const byte*)kCurve25519BasePoint,
333
3.93k
                                rng);
334
3.93k
#endif
335
336
3.93k
    if (ret == 0) {
337
3.90k
        ret = wc_curve25519_check_public(pub, (word32)public_size,
338
3.90k
                                    EC25519_LITTLE_ENDIAN);
339
3.90k
    }
340
341
3.93k
    return ret;
342
3.93k
}
343
#endif
344
345
/* compute the public key from an existing private key, with supplied basepoint,
346
 * using bare vectors.
347
 *
348
 * return value is propagated from curve25519() (0 on success),
349
 * and the byte vectors are little endian.
350
 */
351
int wc_curve25519_generic(int public_size, byte* pub,
352
                          int private_size, const byte* priv,
353
                          int basepoint_size, const byte* basepoint)
354
0
{
355
#ifdef FREESCALE_LTC_ECC
356
    /* unsupported with NXP LTC, only supports single basepoint with
357
     * nxp_ltc_curve25519_GetBasePoint() */
358
    return WC_HW_E;
359
#else
360
#ifndef WOLFSSL_CURVE25519_BLINDING
361
    int ret;
362
363
    if ((public_size != CURVE25519_KEYSIZE) ||
364
        (private_size != CURVE25519_KEYSIZE) ||
365
        (basepoint_size != CURVE25519_KEYSIZE)) {
366
        return ECC_BAD_ARG_E;
367
    }
368
    if ((pub == NULL) || (priv == NULL) || (basepoint == NULL))
369
        return ECC_BAD_ARG_E;
370
371
    /* check clamping */
372
    ret = curve25519_priv_clamp_check(priv);
373
    if (ret != 0)
374
        return ret;
375
376
    fe_init();
377
378
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
379
380
    ret = curve25519(pub, priv, basepoint);
381
382
    RESTORE_VECTOR_REGISTERS();
383
384
    return ret;
385
#else
386
0
    WC_RNG rng;
387
0
    int ret;
388
389
0
    ret = wc_InitRng(&rng);
390
0
    if (ret == 0) {
391
0
        ret = wc_curve25519_generic_blind(public_size, pub, private_size, priv,
392
0
            basepoint_size, basepoint, &rng);
393
394
0
        wc_FreeRng(&rng);
395
0
    }
396
397
0
    return ret;
398
0
#endif
399
0
#endif /* FREESCALE_LTC_ECC */
400
0
}
401
402
#ifdef WOLFSSL_CURVE25519_BLINDING
403
/* compute the public key from an existing private key, with supplied basepoint,
404
 * using bare vectors.
405
 *
406
 * return value is propagated from curve25519() (0 on success),
407
 * and the byte vectors are little endian.
408
 */
409
int wc_curve25519_generic_blind(int public_size, byte* pub,
410
                                int private_size, const byte* priv,
411
                                int basepoint_size, const byte* basepoint,
412
                                WC_RNG* rng)
413
0
{
414
#ifdef FREESCALE_LTC_ECC
415
    /* unsupported with NXP LTC, only supports single basepoint with
416
     * nxp_ltc_curve25519_GetBasePoint() */
417
    return WC_HW_E;
418
#else
419
0
    int ret;
420
421
0
    if ((public_size != CURVE25519_KEYSIZE) ||
422
0
        (private_size != CURVE25519_KEYSIZE) ||
423
0
        (basepoint_size != CURVE25519_KEYSIZE)) {
424
0
        return ECC_BAD_ARG_E;
425
0
    }
426
0
    if ((pub == NULL) || (priv == NULL) || (basepoint == NULL))
427
0
        return ECC_BAD_ARG_E;
428
0
    if (rng == NULL) {
429
0
        return ECC_BAD_ARG_E;
430
0
    }
431
432
    /* check clamping */
433
0
    ret = curve25519_priv_clamp_check(priv);
434
0
    if (ret != 0)
435
0
        return ret;
436
437
0
    fe_init();
438
439
0
    ret = curve25519_smul_blind(pub, priv, basepoint, rng);
440
441
0
    return ret;
442
0
#endif /* FREESCALE_LTC_ECC */
443
0
}
444
#endif
445
446
/* generate a new private key, as a bare vector.
447
 *
448
 * return value is propagated from wc_RNG_GenerateBlock(() (0 on success),
449
 * or BAD_FUNC_ARG/ECC_BAD_ARG_E, and the byte vector is little endian.
450
 */
451
int wc_curve25519_make_priv(WC_RNG* rng, int keysize, byte* key)
452
3.84k
{
453
3.84k
    int ret;
454
455
3.84k
    if (key == NULL || rng == NULL)
456
0
        return BAD_FUNC_ARG;
457
458
    /* currently only a key size of 32 bytes is used */
459
3.84k
    if (keysize != CURVE25519_KEYSIZE)
460
0
        return ECC_BAD_ARG_E;
461
462
    /* random number for private key */
463
3.84k
    ret = wc_RNG_GenerateBlock(rng, key, (word32)keysize);
464
3.84k
    if (ret == 0) {
465
        /* Clamp the private key */
466
3.79k
        ret = curve25519_priv_clamp(key);
467
3.79k
    }
468
469
3.84k
    return ret;
470
3.84k
}
471
472
#ifdef WC_X25519_NONBLOCK
473
474
static int wc_curve25519_make_pub_nb(curve25519_key* key)
475
{
476
    int ret = 0;
477
478
    if (key == NULL) {
479
        ret = BAD_FUNC_ARG;
480
    }
481
    else if (key->nb_ctx == NULL) {
482
        WOLFSSL_MSG("wc_curve25519_make_pub_nb called with NULL non-blocking "
483
            "context.");
484
        ret = BAD_FUNC_ARG;
485
    }
486
487
    if (ret == 0 && key->nb_ctx->state == 0) {
488
        /* check clamping */
489
        ret = curve25519_priv_clamp_check(key->k);
490
        if (ret == 0) {
491
            fe_init();
492
        }
493
    }
494
    if (ret == 0) {
495
        ret = curve25519_nb(key->p.point, key->k, (byte*)kCurve25519BasePoint,
496
                  key->nb_ctx);
497
    }
498
499
    return ret;
500
}
501
502
static int wc_curve25519_make_key_nb(WC_RNG* rng, int keysize,
503
    curve25519_key* key)
504
{
505
    int ret = 0;
506
507
    if (key == NULL || rng == NULL) {
508
        ret = BAD_FUNC_ARG;
509
    }
510
    else if (key->nb_ctx == NULL) {
511
        WOLFSSL_MSG("wc_curve25519_make_key_nb called with NULL non-blocking "
512
            "context.");
513
        ret = BAD_FUNC_ARG;
514
    }
515
516
    if (ret == 0 && key->nb_ctx->state == 0) {
517
        ret = wc_curve25519_make_priv(rng, keysize, key->k);
518
        if (ret == 0) {
519
            key->privSet = 1;
520
        }
521
    }
522
    if (ret == 0) {
523
        ret = wc_curve25519_make_pub_nb(key);
524
        if (ret == 0)  {
525
            key->pubSet = 1;
526
        }
527
    }
528
529
    return ret;
530
}
531
532
int wc_curve25519_set_nonblock(curve25519_key* key, x25519_nb_ctx_t* ctx)
533
{
534
    if (key == NULL) {
535
        return BAD_FUNC_ARG;
536
    }
537
    /* If a different context is already set, clear it before replacing.
538
     * The caller is responsible for freeing any heap-allocated context. */
539
    if (key->nb_ctx != NULL && key->nb_ctx != ctx) {
540
        XMEMSET(key->nb_ctx, 0, sizeof(x25519_nb_ctx_t));
541
    }
542
    if (ctx != NULL) {
543
        XMEMSET(ctx, 0, sizeof(x25519_nb_ctx_t));
544
    }
545
    key->nb_ctx = ctx;
546
    return 0;
547
}
548
549
#endif /* WC_X25519_NONBLOCK */
550
551
/* generate a new keypair.
552
 *
553
 * return value is propagated from wc_curve25519_make_private() or
554
 * wc_curve25519_make_pub() (0 on success).
555
 */
556
int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key)
557
3.84k
{
558
3.84k
    int ret;
559
560
3.84k
    if (key == NULL || rng == NULL)
561
0
        return BAD_FUNC_ARG;
562
563
3.84k
#ifdef WOLF_CRYPTO_CB
564
3.84k
    if (key->devId != INVALID_DEVID) {
565
0
        ret = wc_CryptoCb_Curve25519Gen(rng, keysize, key);
566
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
567
0
            return ret;
568
        /* fall-through when unavailable */
569
0
    }
570
3.84k
#endif
571
572
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_X25519) && \
573
    defined(WOLFSSL_ASYNC_CRYPT_SW)
574
    if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_X25519) {
575
        if (wc_AsyncSwInit(&key->asyncDev, ASYNC_SW_X25519_MAKE)) {
576
            WC_ASYNC_SW* sw = &key->asyncDev.sw;
577
            sw->x25519Make.rng = rng;
578
            sw->x25519Make.size = keysize;
579
            sw->x25519Make.key = key;
580
            return WC_PENDING_E;
581
        }
582
    }
583
#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_X25519 &&
584
        * WOLFSSL_ASYNC_CRYPT_SW */
585
586
#ifdef WOLFSSL_SE050
587
    ret = se050_curve25519_create_key(key, keysize);
588
#elif defined(WC_X25519_NONBLOCK)
589
    if (key->nb_ctx != NULL) {
590
        ret = wc_curve25519_make_key_nb(rng, keysize, key);
591
    }
592
    else
593
#endif
594
3.84k
#if !defined(WOLFSSL_SE050)
595
3.84k
    {
596
3.84k
        ret = wc_curve25519_make_priv(rng, keysize, key->k);
597
3.84k
        if (ret == 0) {
598
3.79k
            key->privSet = 1;
599
3.79k
#ifdef WOLFSSL_CURVE25519_BLINDING
600
3.79k
            ret = wc_curve25519_make_pub_blind((int)sizeof(key->p.point),
601
3.79k
                      key->p.point, (int)sizeof(key->k), key->k, rng);
602
3.79k
            if (ret == 0) {
603
3.75k
                ret = wc_curve25519_set_rng(key, rng);
604
3.75k
            }
605
#else
606
            ret = wc_curve25519_make_pub((int)sizeof(key->p.point),
607
                      key->p.point, (int)sizeof(key->k), key->k);
608
#endif
609
3.79k
            key->pubSet = (ret == 0);
610
3.79k
        }
611
3.84k
    }
612
3.84k
#endif /* !WOLFSSL_SE050 */
613
614
3.84k
    return ret;
615
3.84k
}
616
617
#ifdef HAVE_CURVE25519_SHARED_SECRET
618
619
int wc_curve25519_shared_secret(curve25519_key* private_key,
620
                                curve25519_key* public_key,
621
                                byte* out, word32* outlen)
622
0
{
623
0
    return wc_curve25519_shared_secret_ex(private_key, public_key,
624
0
                                          out, outlen, EC25519_BIG_ENDIAN);
625
0
}
626
627
#ifdef WC_X25519_NONBLOCK
628
629
static int wc_curve25519_shared_secret_nb(curve25519_key* privKey,
630
    curve25519_key* pubKey, byte* out, word32* outlen, int endian)
631
{
632
    int ret = FP_WOULDBLOCK;
633
634
    switch (privKey->nb_ctx->ssState) {
635
        case 0:
636
            XMEMSET(&privKey->nb_ctx->o, 0, sizeof(privKey->nb_ctx->o));
637
            privKey->nb_ctx->ssState = 1;
638
            break;
639
        case 1:
640
            ret = curve25519_nb(privKey->nb_ctx->o.point, privKey->k,
641
                      pubKey->p.point, privKey->nb_ctx);
642
            if (ret == 0) {
643
                ret = FP_WOULDBLOCK;
644
                privKey->nb_ctx->ssState = 2;
645
            }
646
            break;
647
        case 2:
648
        #ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
649
            {
650
                int i;
651
                byte t = 0;
652
653
                for (i = 0; i < CURVE25519_KEYSIZE; i++) {
654
                    t |= privKey->nb_ctx->o.point[i];
655
                }
656
                if (t == 0) {
657
                    ret = ECC_OUT_OF_RANGE_E;
658
                }
659
                else
660
        #endif /* WOLFSSL_ECDHX_SHARED_NOT_ZERO */
661
                {
662
                    curve25519_copy_point(out, privKey->nb_ctx->o.point, endian);
663
                    *outlen = CURVE25519_KEYSIZE;
664
                    ret = 0;
665
                }
666
        #ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
667
            }
668
        #endif
669
            break;
670
    }
671
672
    if (ret != FP_WOULDBLOCK) {
673
        XMEMSET(privKey->nb_ctx, 0, sizeof(x25519_nb_ctx_t));
674
    }
675
676
    return ret;
677
}
678
679
#endif /* WC_X25519_NONBLOCK */
680
681
int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
682
                                   curve25519_key* public_key,
683
                                   byte* out, word32* outlen, int endian)
684
261
{
685
261
    int ret = 0;
686
687
    /* sanity check */
688
261
    if (private_key == NULL || public_key == NULL ||
689
261
        out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE) {
690
0
        return BAD_FUNC_ARG;
691
0
    }
692
693
    /* make sure we have a populated private and public key */
694
261
    if (!public_key->pubSet
695
261
    #ifndef WOLFSSL_SE050
696
261
        || !private_key->privSet
697
261
    #endif
698
261
    ) {
699
0
        return ECC_BAD_ARG_E;
700
0
    }
701
702
    /* avoid implementation fingerprinting - make sure signed bit is not set */
703
261
    if (public_key->p.point[CURVE25519_KEYSIZE-1] & 0x80) {
704
0
        return ECC_BAD_ARG_E;
705
0
    }
706
707
261
#ifdef WOLF_CRYPTO_CB
708
261
    if (private_key->devId != INVALID_DEVID) {
709
0
        ret = wc_CryptoCb_Curve25519(private_key, public_key, out, outlen,
710
0
            endian);
711
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
712
0
            return ret;
713
        /* fall-through when unavailable */
714
0
    }
715
261
#endif
716
717
#ifdef WC_X25519_NONBLOCK
718
719
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_X25519) && \
720
    defined(WOLFSSL_ASYNC_CRYPT_SW)
721
    if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_X25519) {
722
        if (wc_AsyncSwInit(&private_key->asyncDev,
723
                ASYNC_SW_X25519_SHARED_SEC)) {
724
            WC_ASYNC_SW* sw = &private_key->asyncDev.sw;
725
            sw->x25519SharedSec.priv = private_key;
726
            sw->x25519SharedSec.pub = public_key;
727
            sw->x25519SharedSec.out = out;
728
            sw->x25519SharedSec.outLen = outlen;
729
            sw->x25519SharedSec.endian = endian;
730
            return WC_PENDING_E;
731
        }
732
    }
733
#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_X25519 &&
734
        * WOLFSSL_ASYNC_CRYPT_SW */
735
736
    if (private_key->nb_ctx != NULL) {
737
        ret = wc_curve25519_shared_secret_nb(private_key, public_key, out,
738
                  outlen, endian);
739
    }
740
    else
741
#endif /* WC_X25519_NONBLOCK */
742
261
    {
743
261
        ECPoint o;
744
745
261
        XMEMSET(&o, 0, sizeof(o));
746
747
#ifdef FREESCALE_LTC_ECC
748
        /* input point P on Curve25519 */
749
        ret = nxp_ltc_curve25519(&o, private_key->k, &public_key->p,
750
            kLTC_Curve25519);
751
#else
752
    #ifdef WOLFSSL_SE050
753
        if (!private_key->privSet) {
754
            /* use NXP SE050: "privSet" is not set */
755
            ret = se050_curve25519_shared_secret(private_key, public_key, &o);
756
        }
757
        else
758
    #endif /* WOLFSSL_SE050 */
759
261
        {
760
#ifndef WOLFSSL_CURVE25519_BLINDING
761
            SAVE_VECTOR_REGISTERS(return _svr_ret;);
762
763
            ret = curve25519(o.point, private_key->k, public_key->p.point);
764
765
            RESTORE_VECTOR_REGISTERS();
766
#else
767
261
            ret = curve25519_smul_blind(o.point, private_key->k,
768
261
                      public_key->p.point, private_key->rng);
769
261
#endif
770
261
        }
771
261
#endif /* FREESCALE_LTC_ECC */
772
#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
773
        if (ret == 0) {
774
            int i;
775
            byte t = 0;
776
            for (i = 0; i < CURVE25519_KEYSIZE; i++) {
777
                t |= o.point[i];
778
            }
779
            if (t == 0) {
780
                ret = ECC_OUT_OF_RANGE_E;
781
            }
782
        }
783
#endif /* WOLFSSL_ECDHX_SHARED_NOT_ZERO */
784
261
        if (ret == 0) {
785
261
            curve25519_copy_point(out, o.point, endian);
786
261
            *outlen = CURVE25519_KEYSIZE;
787
261
        }
788
789
261
        ForceZero(&o, sizeof(o));
790
261
    }
791
792
261
    return ret;
793
261
}
794
795
#endif /* HAVE_CURVE25519_SHARED_SECRET */
796
797
#ifdef HAVE_CURVE25519_KEY_EXPORT
798
799
/* export curve25519 public key (Big endian)
800
 * return 0 on success */
801
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
802
1
{
803
1
    return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN);
804
1
}
805
806
/* export curve25519 public key (Big or Little endian)
807
 * return 0 on success */
808
int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
809
                                   word32* outLen, int endian)
810
3.67k
{
811
3.67k
    int ret = 0;
812
813
3.67k
    if (key == NULL || out == NULL || outLen == NULL) {
814
12
        return BAD_FUNC_ARG;
815
12
    }
816
817
    /* check and set outgoing key size */
818
3.66k
    if (*outLen < CURVE25519_KEYSIZE) {
819
3
        *outLen = CURVE25519_KEYSIZE;
820
3
        return ECC_BAD_ARG_E;
821
3
    }
822
823
    /* calculate public if missing */
824
3.65k
    if (!key->pubSet) {
825
0
#ifdef WOLFSSL_CURVE25519_BLINDING
826
0
        ret = wc_curve25519_make_pub_blind((int)sizeof(key->p.point),
827
0
                                           key->p.point, (int)sizeof(key->k),
828
0
                                           key->k, key->rng);
829
#else
830
        ret = wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
831
                                     (int)sizeof(key->k), key->k);
832
#endif
833
0
        key->pubSet = (ret == 0);
834
0
    }
835
    /* export public point with endianness */
836
3.65k
    curve25519_copy_point(out, key->p.point, endian);
837
3.65k
    *outLen = CURVE25519_KEYSIZE;
838
839
3.65k
    return ret;
840
3.66k
}
841
842
#endif /* HAVE_CURVE25519_KEY_EXPORT */
843
844
#ifdef HAVE_CURVE25519_KEY_IMPORT
845
846
/* import curve25519 public key (Big endian)
847
 *  return 0 on success */
848
int wc_curve25519_import_public(const byte* in, word32 inLen,
849
                                curve25519_key* key)
850
11
{
851
11
    return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN);
852
11
}
853
854
/* import curve25519 public key (Big or Little endian)
855
 * return 0 on success */
856
int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
857
                                curve25519_key* key, int endian)
858
464
{
859
#ifdef FREESCALE_LTC_ECC
860
    ltc_pkha_ecc_point_t ltcPoint;
861
#endif
862
863
    /* sanity check */
864
464
    if (key == NULL || in == NULL) {
865
1
        return BAD_FUNC_ARG;
866
1
    }
867
868
    /* check size of incoming keys */
869
463
    if (inLen != CURVE25519_KEYSIZE) {
870
10
       return ECC_BAD_ARG_E;
871
10
    }
872
873
    /* import public point with endianness */
874
453
    curve25519_copy_point(key->p.point, in, endian);
875
453
    key->pubSet = 1;
876
877
453
    key->dp = &curve25519_sets[0];
878
879
    /* LTC needs also Y coordinate - let's compute it */
880
#ifdef FREESCALE_LTC_ECC
881
    ltcPoint.X = &key->p.point[0];
882
    ltcPoint.Y = &key->p.pointY[0];
883
    LTC_PKHA_Curve25519ComputeY(&ltcPoint);
884
#endif
885
886
453
    return 0;
887
463
}
888
889
/* Check the public key value (big or little endian)
890
 *
891
 * pub     Public key bytes.
892
 * pubSz   Size of public key in bytes.
893
 * endian  Public key bytes passed in as big-endian or little-endian.
894
 * returns BAD_FUNC_ARGS when pub is NULL,
895
 *         BUFFER_E when size of public key is zero;
896
 *         ECC_OUT_OF_RANGE_E if the high bit is set;
897
 *         ECC_BAD_ARG_E if key length is not 32 bytes, public key value is
898
 *         zero or one; and
899
 *         0 otherwise.
900
 */
901
int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian)
902
4.74k
{
903
4.74k
    word32 i;
904
905
4.74k
    if (pub == NULL)
906
0
        return BAD_FUNC_ARG;
907
908
    /* Check for empty key data */
909
4.74k
    if (pubSz == 0)
910
6
        return BUFFER_E;
911
912
    /* Check key length */
913
4.73k
    if (pubSz != CURVE25519_KEYSIZE)
914
83
        return ECC_BAD_ARG_E;
915
916
917
4.65k
    if (endian == EC25519_LITTLE_ENDIAN) {
918
        /* Check for value of zero or one */
919
5.43k
        for (i = CURVE25519_KEYSIZE - 1; i > 0; i--) {
920
5.41k
            if (pub[i] != 0)
921
4.55k
                break;
922
5.41k
        }
923
4.57k
        if (i == 0 && (pub[0] == 0 || pub[0] == 1))
924
9
            return ECC_BAD_ARG_E;
925
926
        /* Check high bit set */
927
4.56k
        if (pub[CURVE25519_KEYSIZE - 1] & 0x80)
928
26
            return ECC_OUT_OF_RANGE_E;
929
930
        /* Check for order-1 or higher. */
931
4.53k
        if (pub[CURVE25519_KEYSIZE - 1] == 0x7f) {
932
664
            for (i = CURVE25519_KEYSIZE - 2; i > 0; i--) {
933
649
                if (pub[i] != 0xff)
934
72
                    break;
935
649
            }
936
87
            if (i == 0 && (pub[0] >= 0xec))
937
3
                return ECC_BAD_ARG_E;
938
87
         }
939
4.53k
    }
940
83
    else {
941
        /* Check for value of zero or one */
942
498
        for (i = 0; i < CURVE25519_KEYSIZE - 1; i++) {
943
488
            if (pub[i] != 0)
944
73
                break;
945
488
        }
946
83
        if (i == CURVE25519_KEYSIZE - 1 && (pub[i] == 0 || pub[i] == 1))
947
2
            return ECC_BAD_ARG_E;
948
949
        /* Check high bit set */
950
81
        if (pub[0] & 0x80)
951
14
            return ECC_OUT_OF_RANGE_E;
952
953
        /* Check for order-1 or higher. */
954
67
        if (pub[0] == 0x7f) {
955
484
            for (i = 1; i < CURVE25519_KEYSIZE - 1; i++) {
956
472
                if (pub[i] != 0)
957
15
                    break;
958
472
            }
959
27
            if (i == CURVE25519_KEYSIZE - 1 && (pub[i] >= 0xec))
960
2
                return ECC_BAD_ARG_E;
961
27
         }
962
67
    }
963
964
4.59k
    return 0;
965
4.65k
}
966
967
#endif /* HAVE_CURVE25519_KEY_IMPORT */
968
969
970
#ifdef HAVE_CURVE25519_KEY_EXPORT
971
972
/* export curve25519 private key only raw (Big endian)
973
 * outLen is in/out size
974
 * return 0 on success */
975
int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
976
                                     word32* outLen)
977
0
{
978
0
    return wc_curve25519_export_private_raw_ex(key, out, outLen,
979
0
                                               EC25519_BIG_ENDIAN);
980
0
}
981
982
/* export curve25519 private key only raw (Big or Little endian)
983
 * outLen is in/out size
984
 * return 0 on success */
985
int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
986
                                        word32* outLen, int endian)
987
122
{
988
    /* sanity check */
989
122
    if (key == NULL || out == NULL || outLen == NULL)
990
62
        return BAD_FUNC_ARG;
991
992
60
    if (!key->privSet)
993
0
        return ECC_BAD_ARG_E;
994
995
    /* check size of outgoing buffer */
996
60
    if (*outLen < CURVE25519_KEYSIZE) {
997
3
        *outLen = CURVE25519_KEYSIZE;
998
3
        return ECC_BAD_ARG_E;
999
3
    }
1000
1001
    /* export private scalar with endianness */
1002
57
    curve25519_copy_point(out, key->k, endian);
1003
57
    *outLen = CURVE25519_KEYSIZE;
1004
1005
57
    return 0;
1006
60
}
1007
1008
/* curve25519 key pair export (Big or Little endian)
1009
 * return 0 on success */
1010
int wc_curve25519_export_key_raw(curve25519_key* key,
1011
                                 byte* priv, word32 *privSz,
1012
                                 byte* pub, word32 *pubSz)
1013
0
{
1014
0
    return wc_curve25519_export_key_raw_ex(key, priv, privSz,
1015
0
                                           pub, pubSz, EC25519_BIG_ENDIAN);
1016
0
}
1017
1018
/* curve25519 key pair export (Big or Little endian)
1019
 * return 0 on success */
1020
int wc_curve25519_export_key_raw_ex(curve25519_key* key,
1021
                                    byte* priv, word32 *privSz,
1022
                                    byte* pub, word32 *pubSz,
1023
                                    int endian)
1024
0
{
1025
0
    int ret;
1026
1027
    /* export private part */
1028
0
    ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
1029
0
    if (ret != 0)
1030
0
        return ret;
1031
1032
    /* export public part */
1033
0
    return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
1034
0
}
1035
1036
#endif /* HAVE_CURVE25519_KEY_EXPORT */
1037
1038
#ifdef HAVE_CURVE25519_KEY_IMPORT
1039
1040
/* curve25519 private key import (Big endian)
1041
 * Public key to match private key needs to be imported too
1042
 * return 0 on success */
1043
int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
1044
                                     const byte* pub, word32 pubSz,
1045
                                     curve25519_key* key)
1046
10
{
1047
10
    return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz,
1048
10
                                               key, EC25519_BIG_ENDIAN);
1049
10
}
1050
1051
/* curve25519 private key import (Big or Little endian)
1052
 * Public key to match private key needs to be imported too
1053
 * return 0 on success */
1054
int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
1055
                                        const byte* pub, word32 pubSz,
1056
                                        curve25519_key* key, int endian)
1057
10
{
1058
10
    int ret;
1059
1060
    /* import private part */
1061
10
    ret = wc_curve25519_import_private_ex(priv, privSz, key, endian);
1062
10
    if (ret != 0)
1063
9
        return ret;
1064
1065
    /* import public part */
1066
1
    return wc_curve25519_import_public_ex(pub, pubSz, key, endian);
1067
10
}
1068
1069
/* curve25519 private key import only. (Big endian)
1070
 * return 0 on success */
1071
int wc_curve25519_import_private(const byte* priv, word32 privSz,
1072
                                 curve25519_key* key)
1073
0
{
1074
0
    return wc_curve25519_import_private_ex(priv, privSz,
1075
0
                                           key, EC25519_BIG_ENDIAN);
1076
0
}
1077
1078
/* curve25519 private key import only. (Big or Little endian)
1079
 * return 0 on success */
1080
int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
1081
                                    curve25519_key* key, int endian)
1082
10
{
1083
    /* sanity check */
1084
10
    if (key == NULL || priv == NULL) {
1085
0
        return BAD_FUNC_ARG;
1086
0
    }
1087
1088
    /* check size of incoming keys */
1089
10
    if ((int)privSz != CURVE25519_KEYSIZE) {
1090
9
        return ECC_BAD_ARG_E;
1091
9
    }
1092
1093
#ifdef WOLFSSL_SE050
1094
#ifdef WOLFSSL_SE050_AUTO_ERASE
1095
    wc_se050_erase_object(key->keyId);
1096
#endif
1097
    /* release NXP resources if set */
1098
    se050_curve25519_free_key(key);
1099
#endif
1100
1101
    /* import private scalar with endianness */
1102
1
    curve25519_copy_point(key->k, priv, endian);
1103
1
    key->privSet = 1;
1104
1105
1
    key->dp = &curve25519_sets[0];
1106
1107
    /* Clamp the key */
1108
1
    return curve25519_priv_clamp(key->k);
1109
10
}
1110
1111
#endif /* HAVE_CURVE25519_KEY_IMPORT */
1112
1113
#ifndef WC_NO_CONSTRUCTORS
1114
curve25519_key* wc_curve25519_new(void* heap, int devId, int *result_code)
1115
0
{
1116
0
    int ret;
1117
0
    curve25519_key* key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), heap,
1118
0
                           DYNAMIC_TYPE_CURVE25519);
1119
0
    if (key == NULL) {
1120
0
        ret = MEMORY_E;
1121
0
    }
1122
0
    else {
1123
0
        ret = wc_curve25519_init_ex(key, heap, devId);
1124
0
        if (ret != 0) {
1125
0
            XFREE(key, heap, DYNAMIC_TYPE_CURVE25519);
1126
0
            key = NULL;
1127
0
        }
1128
0
    }
1129
1130
0
    if (result_code != NULL)
1131
0
        *result_code = ret;
1132
1133
0
    return key;
1134
0
}
1135
1136
0
int wc_curve25519_delete(curve25519_key* key, curve25519_key** key_p) {
1137
0
    void* heap;
1138
0
    if (key == NULL)
1139
0
        return BAD_FUNC_ARG;
1140
0
    heap = key->heap;
1141
0
    wc_curve25519_free(key);
1142
0
    XFREE(key, heap, DYNAMIC_TYPE_CURVE25519);
1143
0
    if (key_p != NULL)
1144
0
        *key_p = NULL;
1145
0
    return 0;
1146
0
}
1147
#endif /* !WC_NO_CONSTRUCTORS */
1148
1149
int wc_curve25519_init_ex(curve25519_key* key, void* heap, int devId)
1150
4.35k
{
1151
4.35k
    int ret = 0;
1152
1153
4.35k
    if (key == NULL) {
1154
0
       ret = BAD_FUNC_ARG;
1155
0
    }
1156
4.35k
    else {
1157
4.35k
        XMEMSET(key, 0, sizeof(*key));
1158
1159
        /* currently the format for curve25519 */
1160
4.35k
        key->dp = &curve25519_sets[0];
1161
1162
4.35k
    #ifdef WOLF_CRYPTO_CB
1163
4.35k
        key->devId = devId;
1164
    #else
1165
        (void)devId;
1166
    #endif
1167
4.35k
        (void)heap; /* if needed for XMALLOC/XFREE in future */
1168
1169
4.35k
    #ifndef FREESCALE_LTC_ECC
1170
4.35k
        fe_init();
1171
4.35k
    #endif
1172
1173
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1174
        wc_MemZero_Add("wc_curve25519_init_ex key->k", key->k,
1175
            CURVE25519_KEYSIZE);
1176
    #endif
1177
1178
    #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_X25519)
1179
        ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_X25519,
1180
                  heap, devId);
1181
    #endif
1182
4.35k
    }
1183
1184
4.35k
    return ret;
1185
4.35k
}
1186
1187
int wc_curve25519_init(curve25519_key* key)
1188
327
{
1189
327
    return wc_curve25519_init_ex(key, NULL, INVALID_DEVID);
1190
327
}
1191
1192
/* Clean the memory of a key */
1193
void wc_curve25519_free(curve25519_key* key)
1194
7.82k
{
1195
7.82k
    if (key == NULL)
1196
3.47k
       return;
1197
1198
#ifdef WOLFSSL_SE050
1199
    se050_curve25519_free_key(key);
1200
#endif
1201
1202
4.35k
    ForceZero(key, sizeof(*key));
1203
1204
#ifdef WOLFSSL_CHECK_MEM_ZERO
1205
    wc_MemZero_Check(key, sizeof(curve25519_key));
1206
#endif
1207
4.35k
}
1208
1209
#ifdef WOLFSSL_CURVE25519_BLINDING
1210
int wc_curve25519_set_rng(curve25519_key* key, WC_RNG* rng)
1211
4.01k
{
1212
4.01k
    if (key == NULL)
1213
0
        return BAD_FUNC_ARG;
1214
4.01k
    key->rng = rng;
1215
4.01k
    return 0;
1216
4.01k
}
1217
#endif
1218
1219
/* get key size */
1220
int wc_curve25519_size(curve25519_key* key)
1221
0
{
1222
0
    if (key == NULL)
1223
0
        return 0;
1224
1225
0
    return key->dp->size;
1226
0
}
1227
1228
#endif /*HAVE_CURVE25519*/