Coverage Report

Created: 2026-04-05 07:22

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