Coverage Report

Created: 2026-08-15 06:21

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