Coverage Report

Created: 2025-07-23 06:59

/src/wolfssl-sp-math-all/wolfcrypt/src/curve25519.c
Line
Count
Source (jump to first uncovered line)
1
/* curve25519.c
2
 *
3
 * Copyright (C) 2006-2025 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
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
26
27
#ifdef NO_CURVED25519_X64
28
    #undef USE_INTEL_SPEEDUP
29
#endif
30
31
#ifdef HAVE_CURVE25519
32
33
#include <wolfssl/wolfcrypt/curve25519.h>
34
#ifdef NO_INLINE
35
    #include <wolfssl/wolfcrypt/misc.h>
36
#else
37
    #define WOLFSSL_MISC_INCLUDED
38
    #include <wolfcrypt/src/misc.c>
39
#endif
40
41
#if defined(FREESCALE_LTC_ECC)
42
    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
43
#endif
44
#ifdef WOLFSSL_SE050
45
    #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
46
#endif
47
48
#ifdef WOLF_CRYPTO_CB
49
    #include <wolfssl/wolfcrypt/cryptocb.h>
50
#endif
51
52
#if defined(WOLFSSL_CURVE25519_BLINDING)
53
    #if defined(CURVE25519_SMALL)
54
        #error "Blinding not needed nor available for small implementation"
55
    #elif defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_ARMASM)
56
        #error "Blinding not needed nor available for assembly implementation"
57
    #endif
58
#endif
59
60
#if defined(WOLFSSL_LINUXKM) && !defined(USE_INTEL_SPEEDUP)
61
    /* force off unneeded vector register save/restore. */
62
    #undef SAVE_VECTOR_REGISTERS
63
    #define SAVE_VECTOR_REGISTERS(fail_clause) WC_DO_NOTHING
64
    #undef RESTORE_VECTOR_REGISTERS
65
    #define RESTORE_VECTOR_REGISTERS() WC_DO_NOTHING
66
#endif
67
68
const curve25519_set_type curve25519_sets[] = {
69
    {
70
        CURVE25519_KEYSIZE,
71
        "CURVE25519",
72
    }
73
};
74
75
static const word32 kCurve25519BasePoint[CURVE25519_KEYSIZE/sizeof(word32)] = {
76
#ifdef BIG_ENDIAN_ORDER
77
    0x09000000
78
#else
79
    9
80
#endif
81
};
82
83
/* Curve25519 private key must be less than order */
84
/* These functions clamp private k and check it */
85
static WC_INLINE int curve25519_priv_clamp(byte* priv)
86
2.28k
{
87
2.28k
    priv[0]  &= 248;
88
2.28k
    priv[CURVE25519_KEYSIZE-1] &= 127;
89
2.28k
    priv[CURVE25519_KEYSIZE-1] |= 64;
90
2.28k
    return 0;
91
2.28k
}
92
static WC_INLINE int curve25519_priv_clamp_check(const byte* priv)
93
2.91k
{
94
    /* check that private part of key has been clamped */
95
2.91k
    int ret = 0;
96
2.91k
    if ((priv[0] & ~248) ||
97
2.91k
        (priv[CURVE25519_KEYSIZE-1] & 128)) {
98
0
        ret = ECC_BAD_ARG_E;
99
0
    }
100
2.91k
    return ret;
101
2.91k
}
102
103
static WC_INLINE void curve25519_copy_point(byte* out, const byte* point,
104
    int endian)
105
3.55k
{
106
3.55k
    if (endian == EC25519_BIG_ENDIAN) {
107
3
        int i;
108
        /* put shared secret key in Big Endian format */
109
99
        for (i = 0; i < CURVE25519_KEYSIZE; i++) {
110
96
            out[i] = point[CURVE25519_KEYSIZE - i -1];
111
96
        }
112
3
    }
113
3.55k
    else { /* put shared secret key in Little Endian format */
114
3.55k
        XMEMCPY(out, point, CURVE25519_KEYSIZE);
115
3.55k
    }
116
3.55k
}
117
118
/* compute the public key from an existing private key, using bare vectors.
119
 *
120
 * return value is propagated from curve25519() (0 on success), or
121
 * ECC_BAD_ARG_E, and the byte vectors are little endian.
122
 */
123
int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
124
                           const byte* priv)
125
352
{
126
352
    int ret;
127
#ifdef FREESCALE_LTC_ECC
128
    const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
129
    ECPoint wc_pub;
130
#endif
131
132
352
    if ( (public_size != CURVE25519_KEYSIZE) ||
133
352
        (private_size != CURVE25519_KEYSIZE)) {
134
0
        return ECC_BAD_ARG_E;
135
0
    }
136
352
    if ((pub == NULL) || (priv == NULL)) {
137
0
        return ECC_BAD_ARG_E;
138
0
    }
139
140
    /* check clamping */
141
352
    ret = curve25519_priv_clamp_check(priv);
142
352
    if (ret != 0)
143
0
        return ret;
144
145
#ifdef FREESCALE_LTC_ECC
146
    /* input basepoint on Weierstrass curve */
147
    ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
148
    if (ret == 0) {
149
        XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE);
150
    }
151
#else
152
#ifndef WOLFSSL_CURVE25519_BLINDING
153
    fe_init();
154
155
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
156
157
    ret = curve25519(pub, priv, (byte*)kCurve25519BasePoint);
158
159
    RESTORE_VECTOR_REGISTERS();
160
#else
161
352
    {
162
352
        WC_RNG rng;
163
164
352
        ret = wc_InitRng(&rng);
165
352
        if (ret == 0) {
166
279
            ret = wc_curve25519_make_pub_blind(public_size, pub, private_size,
167
279
                priv, &rng);
168
169
279
            wc_FreeRng(&rng);
170
279
        }
171
352
    }
172
352
#endif /* !WOLFSSL_CURVE25519_BLINDING */
173
352
#endif /* FREESCALE_LTC_ECC */
174
175
352
    return ret;
176
352
}
177
178
#ifdef WOLFSSL_CURVE25519_BLINDING
179
#ifndef FREESCALE_LTC_ECC
180
#ifndef WOLFSSL_CURVE25519_BLINDING_RAND_CNT
181
6.40k
    #define WOLFSSL_CURVE25519_BLINDING_RAND_CNT    10
182
#endif
183
static int curve25519_smul_blind(byte* rp, const byte* n, const byte* p,
184
    WC_RNG* rng)
185
3.24k
{
186
3.24k
    int ret;
187
3.24k
    byte a[CURVE25519_KEYSIZE];
188
3.24k
    byte n_a[CURVE25519_KEYSIZE];
189
3.24k
    byte rz[CURVE25519_KEYSIZE];
190
3.24k
    int i;
191
3.24k
    int cnt;
192
193
3.24k
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
194
195
    /* Generate random z. */
196
3.24k
    for (cnt = 0; cnt < WOLFSSL_CURVE25519_BLINDING_RAND_CNT; cnt++) {
197
3.24k
        ret = wc_RNG_GenerateBlock(rng, rz, sizeof(rz));
198
3.24k
        if (ret < 0) {
199
79
            return ret;
200
79
        }
201
3.33k
        for (i = CURVE25519_KEYSIZE - 1; i >= 0; i--) {
202
3.33k
            if (rz[i] != 0xff)
203
3.16k
                break;
204
3.33k
        }
205
3.16k
        if ((i >= 0) || (rz[0] <= 0xec)) {
206
3.16k
            break;
207
3.16k
        }
208
3.16k
    }
209
3.16k
    if (cnt == WOLFSSL_CURVE25519_BLINDING_RAND_CNT) {
210
0
        return RNG_FAILURE_E;
211
0
    }
212
213
    /* Generate 253 random bits. */
214
3.16k
    ret = wc_RNG_GenerateBlock(rng, a, sizeof(a));
215
3.16k
    if (ret != 0)
216
82
        return ret;
217
3.08k
    a[CURVE25519_KEYSIZE-1] &= 0x7f;
218
    /* k' = k ^ 2k ^ a */
219
3.08k
    n_a[0] = n[0] ^ (byte)(n[0] << 1) ^ a[0];
220
98.5k
    for (i = 1; i < CURVE25519_KEYSIZE; i++) {
221
95.5k
        byte b1, b2, b3;
222
95.5k
        b1 = n[i] ^ a[i];
223
95.5k
        b2 = (byte)(n[i] << 1) ^ a[i];
224
95.5k
        b3 = (n[i-1] >> 7) ^ a[i];
225
95.5k
        n_a[i] = b1 ^ b2 ^ b3;
226
95.5k
    }
227
    /* Scalar multiple blinded scalar with blinding value. */
228
3.08k
    ret = curve25519_blind(rp, n_a, a, p, rz);
229
230
3.08k
    RESTORE_VECTOR_REGISTERS();
231
232
3.08k
    return ret;
233
3.16k
}
234
#endif
235
236
int wc_curve25519_make_pub_blind(int public_size, byte* pub, int private_size,
237
                                 const byte* priv, WC_RNG* rng)
238
2.56k
{
239
2.56k
    int ret;
240
#ifdef FREESCALE_LTC_ECC
241
    const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
242
    ECPoint wc_pub;
243
#endif
244
245
2.56k
    if ( (public_size != CURVE25519_KEYSIZE) ||
246
2.56k
        (private_size != CURVE25519_KEYSIZE)) {
247
0
        return ECC_BAD_ARG_E;
248
0
    }
249
2.56k
    if ((pub == NULL) || (priv == NULL)) {
250
0
        return ECC_BAD_ARG_E;
251
0
    }
252
253
    /* check clamping */
254
2.56k
    ret = curve25519_priv_clamp_check(priv);
255
2.56k
    if (ret != 0)
256
0
        return ret;
257
258
#ifdef FREESCALE_LTC_ECC
259
    /* input basepoint on Weierstrass curve */
260
    ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
261
    if (ret == 0) {
262
        XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE);
263
    }
264
#else
265
2.56k
    fe_init();
266
267
2.56k
    ret = curve25519_smul_blind(pub, priv, (byte*)kCurve25519BasePoint, rng);
268
2.56k
#endif
269
270
2.56k
    return ret;
271
2.56k
}
272
#endif
273
274
/* compute the public key from an existing private key, with supplied basepoint,
275
 * using bare vectors.
276
 *
277
 * return value is propagated from curve25519() (0 on success),
278
 * and the byte vectors are little endian.
279
 */
280
int wc_curve25519_generic(int public_size, byte* pub,
281
                          int private_size, const byte* priv,
282
                          int basepoint_size, const byte* basepoint)
283
0
{
284
#ifdef FREESCALE_LTC_ECC
285
    /* unsupported with NXP LTC, only supports single basepoint with
286
     * nxp_ltc_curve25519_GetBasePoint() */
287
    return WC_HW_E;
288
#else
289
#ifndef WOLFSSL_CURVE25519_BLINDING
290
    int ret;
291
292
    if ((public_size != CURVE25519_KEYSIZE) ||
293
        (private_size != CURVE25519_KEYSIZE) ||
294
        (basepoint_size != CURVE25519_KEYSIZE)) {
295
        return ECC_BAD_ARG_E;
296
    }
297
    if ((pub == NULL) || (priv == NULL) || (basepoint == NULL))
298
        return ECC_BAD_ARG_E;
299
300
    /* check clamping */
301
    ret = curve25519_priv_clamp_check(priv);
302
    if (ret != 0)
303
        return ret;
304
305
    fe_init();
306
307
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
308
309
    ret = curve25519(pub, priv, basepoint);
310
311
    RESTORE_VECTOR_REGISTERS();
312
313
    return ret;
314
#else
315
0
    WC_RNG rng;
316
0
    int ret;
317
318
0
    ret = wc_InitRng(&rng);
319
0
    if (ret == 0) {
320
0
        ret = wc_curve25519_generic_blind(public_size, pub, private_size, priv,
321
0
            basepoint_size, basepoint, &rng);
322
323
0
        wc_FreeRng(&rng);
324
0
    }
325
326
0
    return ret;
327
0
#endif
328
0
#endif /* FREESCALE_LTC_ECC */
329
0
}
330
331
#ifdef WOLFSSL_CURVE25519_BLINDING
332
/* compute the public key from an existing private key, with supplied basepoint,
333
 * using bare vectors.
334
 *
335
 * return value is propagated from curve25519() (0 on success),
336
 * and the byte vectors are little endian.
337
 */
338
int wc_curve25519_generic_blind(int public_size, byte* pub,
339
                                int private_size, const byte* priv,
340
                                int basepoint_size, const byte* basepoint,
341
                                WC_RNG* rng)
342
0
{
343
#ifdef FREESCALE_LTC_ECC
344
    /* unsupported with NXP LTC, only supports single basepoint with
345
     * nxp_ltc_curve25519_GetBasePoint() */
346
    return WC_HW_E;
347
#else
348
0
    int ret;
349
350
0
    if ((public_size != CURVE25519_KEYSIZE) ||
351
0
        (private_size != CURVE25519_KEYSIZE) ||
352
0
        (basepoint_size != CURVE25519_KEYSIZE)) {
353
0
        return ECC_BAD_ARG_E;
354
0
    }
355
0
    if ((pub == NULL) || (priv == NULL) || (basepoint == NULL))
356
0
        return ECC_BAD_ARG_E;
357
358
    /* check clamping */
359
0
    ret = curve25519_priv_clamp_check(priv);
360
0
    if (ret != 0)
361
0
        return ret;
362
363
0
    fe_init();
364
365
0
    ret = curve25519_smul_blind(pub, priv, basepoint, rng);
366
367
0
    return ret;
368
0
#endif /* FREESCALE_LTC_ECC */
369
0
}
370
#endif
371
372
/* generate a new private key, as a bare vector.
373
 *
374
 * return value is propagated from wc_RNG_GenerateBlock(() (0 on success),
375
 * or BAD_FUNC_ARG/ECC_BAD_ARG_E, and the byte vector is little endian.
376
 */
377
int wc_curve25519_make_priv(WC_RNG* rng, int keysize, byte* key)
378
2.36k
{
379
2.36k
    int ret;
380
381
2.36k
    if (key == NULL || rng == NULL)
382
0
        return BAD_FUNC_ARG;
383
384
    /* currently only a key size of 32 bytes is used */
385
2.36k
    if (keysize != CURVE25519_KEYSIZE)
386
0
        return ECC_BAD_ARG_E;
387
388
    /* random number for private key */
389
2.36k
    ret = wc_RNG_GenerateBlock(rng, key, (word32)keysize);
390
2.36k
    if (ret == 0) {
391
        /* Clamp the private key */
392
2.28k
        ret = curve25519_priv_clamp(key);
393
2.28k
    }
394
395
2.36k
    return ret;
396
2.36k
}
397
398
/* generate a new keypair.
399
 *
400
 * return value is propagated from wc_curve25519_make_private() or
401
 * wc_curve25519_make_pub() (0 on success).
402
 */
403
int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key)
404
2.36k
{
405
2.36k
    int ret;
406
407
2.36k
    if (key == NULL || rng == NULL)
408
0
        return BAD_FUNC_ARG;
409
410
2.36k
#ifdef WOLF_CRYPTO_CB
411
2.36k
    if (key->devId != INVALID_DEVID) {
412
0
        ret = wc_CryptoCb_Curve25519Gen(rng, keysize, key);
413
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
414
0
            return ret;
415
        /* fall-through when unavailable */
416
0
    }
417
2.36k
#endif
418
419
#ifdef WOLFSSL_SE050
420
    ret = se050_curve25519_create_key(key, keysize);
421
#else
422
2.36k
    ret = wc_curve25519_make_priv(rng, keysize, key->k);
423
2.36k
    if (ret == 0) {
424
2.28k
        key->privSet = 1;
425
2.28k
#ifdef WOLFSSL_CURVE25519_BLINDING
426
2.28k
        ret = wc_curve25519_make_pub_blind((int)sizeof(key->p.point),
427
2.28k
                                           key->p.point, (int)sizeof(key->k),
428
2.28k
                                           key->k, rng);
429
2.28k
        if (ret == 0) {
430
2.14k
            ret = wc_curve25519_set_rng(key, rng);
431
2.14k
        }
432
#else
433
        ret = wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
434
                                     (int)sizeof(key->k), key->k);
435
#endif
436
2.28k
        key->pubSet = (ret == 0);
437
2.28k
    }
438
2.36k
#endif
439
2.36k
    return ret;
440
2.36k
}
441
442
#ifdef HAVE_CURVE25519_SHARED_SECRET
443
444
int wc_curve25519_shared_secret(curve25519_key* private_key,
445
                                curve25519_key* public_key,
446
                                byte* out, word32* outlen)
447
0
{
448
0
    return wc_curve25519_shared_secret_ex(private_key, public_key,
449
0
                                          out, outlen, EC25519_BIG_ENDIAN);
450
0
}
451
452
int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
453
                                   curve25519_key* public_key,
454
                                   byte* out, word32* outlen, int endian)
455
682
{
456
682
    int ret;
457
682
    ECPoint o;
458
459
    /* sanity check */
460
682
    if (private_key == NULL || public_key == NULL ||
461
682
        out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE) {
462
0
        return BAD_FUNC_ARG;
463
0
    }
464
465
    /* make sure we have a populated private and public key */
466
682
    if (!public_key->pubSet
467
682
    #ifndef WOLFSSL_SE050
468
682
        || !private_key->privSet
469
682
    #endif
470
682
    ) {
471
0
        return ECC_BAD_ARG_E;
472
0
    }
473
474
    /* avoid implementation fingerprinting - make sure signed bit is not set */
475
682
    if (public_key->p.point[CURVE25519_KEYSIZE-1] & 0x80) {
476
0
        return ECC_BAD_ARG_E;
477
0
    }
478
479
682
#ifdef WOLF_CRYPTO_CB
480
682
    if (private_key->devId != INVALID_DEVID) {
481
0
        ret = wc_CryptoCb_Curve25519(private_key, public_key, out, outlen,
482
0
            endian);
483
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
484
0
            return ret;
485
        /* fall-through when unavailable */
486
0
    }
487
682
#endif
488
489
682
    XMEMSET(&o, 0, sizeof(o));
490
491
#ifdef FREESCALE_LTC_ECC
492
    /* input point P on Curve25519 */
493
    ret = nxp_ltc_curve25519(&o, private_key->k, &public_key->p,
494
        kLTC_Curve25519);
495
#else
496
    #ifdef WOLFSSL_SE050
497
    if (!private_key->privSet) {
498
        /* use NXP SE050: "privSet" is not set */
499
        ret = se050_curve25519_shared_secret(private_key, public_key, &o);
500
    }
501
    else
502
    #endif
503
682
    {
504
#ifndef WOLFSSL_CURVE25519_BLINDING
505
    SAVE_VECTOR_REGISTERS(return _svr_ret;);
506
507
    ret = curve25519(o.point, private_key->k, public_key->p.point);
508
509
    RESTORE_VECTOR_REGISTERS();
510
#else
511
682
    ret = curve25519_smul_blind(o.point, private_key->k, public_key->p.point,
512
682
                                private_key->rng);
513
682
#endif
514
682
    }
515
682
#endif
516
#ifdef WOLFSSL_ECDHX_SHARED_NOT_ZERO
517
    if (ret == 0) {
518
        int i;
519
        byte t = 0;
520
        for (i = 0; i < CURVE25519_KEYSIZE; i++) {
521
            t |= o.point[i];
522
        }
523
        if (t == 0) {
524
            ret = ECC_OUT_OF_RANGE_E;
525
        }
526
    }
527
#endif
528
682
    if (ret == 0) {
529
661
        curve25519_copy_point(out, o.point, endian);
530
661
        *outlen = CURVE25519_KEYSIZE;
531
661
    }
532
533
682
    ForceZero(&o, sizeof(o));
534
535
682
    return ret;
536
682
}
537
538
#endif /* HAVE_CURVE25519_SHARED_SECRET */
539
540
#ifdef HAVE_CURVE25519_KEY_EXPORT
541
542
/* export curve25519 public key (Big endian)
543
 * return 0 on success */
544
int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
545
1
{
546
1
    return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN);
547
1
}
548
549
/* export curve25519 public key (Big or Little endian)
550
 * return 0 on success */
551
int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
552
                                   word32* outLen, int endian)
553
1.97k
{
554
1.97k
    int ret = 0;
555
556
1.97k
    if (key == NULL || out == NULL || outLen == NULL) {
557
17
        return BAD_FUNC_ARG;
558
17
    }
559
560
    /* check and set outgoing key size */
561
1.95k
    if (*outLen < CURVE25519_KEYSIZE) {
562
1
        *outLen = CURVE25519_KEYSIZE;
563
1
        return ECC_BAD_ARG_E;
564
1
    }
565
566
    /* calculate public if missing */
567
1.95k
    if (!key->pubSet) {
568
0
#ifdef WOLFSSL_CURVE25519_BLINDING
569
0
        ret = wc_curve25519_make_pub_blind((int)sizeof(key->p.point),
570
0
                                           key->p.point, (int)sizeof(key->k),
571
0
                                           key->k, key->rng);
572
#else
573
        ret = wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
574
                                     (int)sizeof(key->k), key->k);
575
#endif
576
0
        key->pubSet = (ret == 0);
577
0
    }
578
    /* export public point with endianness */
579
1.95k
    curve25519_copy_point(out, key->p.point, endian);
580
1.95k
    *outLen = CURVE25519_KEYSIZE;
581
582
1.95k
    return ret;
583
1.95k
}
584
585
#endif /* HAVE_CURVE25519_KEY_EXPORT */
586
587
#ifdef HAVE_CURVE25519_KEY_IMPORT
588
589
/* import curve25519 public key (Big endian)
590
 *  return 0 on success */
591
int wc_curve25519_import_public(const byte* in, word32 inLen,
592
                                curve25519_key* key)
593
25
{
594
25
    return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN);
595
25
}
596
597
/* import curve25519 public key (Big or Little endian)
598
 * return 0 on success */
599
int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
600
                                curve25519_key* key, int endian)
601
870
{
602
#ifdef FREESCALE_LTC_ECC
603
    ltc_pkha_ecc_point_t ltcPoint;
604
#endif
605
606
    /* sanity check */
607
870
    if (key == NULL || in == NULL) {
608
1
        return BAD_FUNC_ARG;
609
1
    }
610
611
    /* check size of incoming keys */
612
869
    if (inLen != CURVE25519_KEYSIZE) {
613
24
       return ECC_BAD_ARG_E;
614
24
    }
615
616
    /* import public point with endianness */
617
845
    curve25519_copy_point(key->p.point, in, endian);
618
845
    key->pubSet = 1;
619
620
845
    key->dp = &curve25519_sets[0];
621
622
    /* LTC needs also Y coordinate - let's compute it */
623
#ifdef FREESCALE_LTC_ECC
624
    ltcPoint.X = &key->p.point[0];
625
    ltcPoint.Y = &key->p.pointY[0];
626
    LTC_PKHA_Curve25519ComputeY(&ltcPoint);
627
#endif
628
629
845
    return 0;
630
869
}
631
632
/* Check the public key value (big or little endian)
633
 *
634
 * pub     Public key bytes.
635
 * pubSz   Size of public key in bytes.
636
 * endian  Public key bytes passed in as big-endian or little-endian.
637
 * returns BAD_FUNC_ARGS when pub is NULL,
638
 *         BUFFER_E when size of public key is zero;
639
 *         ECC_OUT_OF_RANGE_E if the high bit is set;
640
 *         ECC_BAD_ARG_E if key length is not 32 bytes, public key value is
641
 *         zero or one; and
642
 *         0 otherwise.
643
 */
644
int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian)
645
1.24k
{
646
1.24k
    word32 i;
647
648
1.24k
    if (pub == NULL)
649
0
        return BAD_FUNC_ARG;
650
651
    /* Check for empty key data */
652
1.24k
    if (pubSz == 0)
653
7
        return BUFFER_E;
654
655
    /* Check key length */
656
1.23k
    if (pubSz != CURVE25519_KEYSIZE)
657
24
        return ECC_BAD_ARG_E;
658
659
660
1.21k
    if (endian == EC25519_LITTLE_ENDIAN) {
661
        /* Check for value of zero or one */
662
2.50k
        for (i = CURVE25519_KEYSIZE - 1; i > 0; i--) {
663
2.47k
            if (pub[i] != 0)
664
1.11k
                break;
665
2.47k
        }
666
1.14k
        if (i == 0 && (pub[0] == 0 || pub[0] == 1))
667
8
            return ECC_BAD_ARG_E;
668
669
        /* Check high bit set */
670
1.13k
        if (pub[CURVE25519_KEYSIZE - 1] & 0x80)
671
28
            return ECC_OUT_OF_RANGE_E;
672
673
        /* Check for order-1 or higher. */
674
1.11k
        if (pub[CURVE25519_KEYSIZE - 1] == 0x7f) {
675
711
            for (i = CURVE25519_KEYSIZE - 2; i > 0; i--) {
676
696
                if (pub[i] != 0xff)
677
82
                    break;
678
696
            }
679
97
            if (i == 0 && (pub[0] >= 0xec))
680
4
                return ECC_BAD_ARG_E;
681
97
         }
682
1.11k
    }
683
65
    else {
684
        /* Check for value of zero or one */
685
233
        for (i = 0; i < CURVE25519_KEYSIZE - 1; i++) {
686
230
            if (pub[i] != 0)
687
62
                break;
688
230
        }
689
65
        if (i == CURVE25519_KEYSIZE - 1 && (pub[i] == 0 || pub[i] == 1))
690
2
            return ECC_BAD_ARG_E;
691
692
        /* Check high bit set */
693
63
        if (pub[0] & 0x80)
694
20
            return ECC_OUT_OF_RANGE_E;
695
696
        /* Check for order-1 or higher. */
697
43
        if (pub[0] == 0x7f) {
698
280
            for (i = 1; i < CURVE25519_KEYSIZE - 1; i++) {
699
275
                if (pub[i] != 0)
700
11
                    break;
701
275
            }
702
16
            if (i == CURVE25519_KEYSIZE - 1 && (pub[i] >= 0xec))
703
2
                return ECC_BAD_ARG_E;
704
16
         }
705
43
    }
706
707
1.14k
    return 0;
708
1.21k
}
709
710
#endif /* HAVE_CURVE25519_KEY_IMPORT */
711
712
713
#ifdef HAVE_CURVE25519_KEY_EXPORT
714
715
/* export curve25519 private key only raw (Big endian)
716
 * outLen is in/out size
717
 * return 0 on success */
718
int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
719
                                     word32* outLen)
720
0
{
721
0
    return wc_curve25519_export_private_raw_ex(key, out, outLen,
722
0
                                               EC25519_BIG_ENDIAN);
723
0
}
724
725
/* export curve25519 private key only raw (Big or Little endian)
726
 * outLen is in/out size
727
 * return 0 on success */
728
int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
729
                                        word32* outLen, int endian)
730
213
{
731
    /* sanity check */
732
213
    if (key == NULL || out == NULL || outLen == NULL)
733
117
        return BAD_FUNC_ARG;
734
735
    /* check size of outgoing buffer */
736
96
    if (*outLen < CURVE25519_KEYSIZE) {
737
2
        *outLen = CURVE25519_KEYSIZE;
738
2
        return ECC_BAD_ARG_E;
739
2
    }
740
741
    /* export private scalar with endianness */
742
94
    curve25519_copy_point(out, key->k, endian);
743
94
    *outLen = CURVE25519_KEYSIZE;
744
745
94
    return 0;
746
96
}
747
748
/* curve25519 key pair export (Big or Little endian)
749
 * return 0 on success */
750
int wc_curve25519_export_key_raw(curve25519_key* key,
751
                                 byte* priv, word32 *privSz,
752
                                 byte* pub, word32 *pubSz)
753
0
{
754
0
    return wc_curve25519_export_key_raw_ex(key, priv, privSz,
755
0
                                           pub, pubSz, EC25519_BIG_ENDIAN);
756
0
}
757
758
/* curve25519 key pair export (Big or Little endian)
759
 * return 0 on success */
760
int wc_curve25519_export_key_raw_ex(curve25519_key* key,
761
                                    byte* priv, word32 *privSz,
762
                                    byte* pub, word32 *pubSz,
763
                                    int endian)
764
0
{
765
0
    int ret;
766
767
    /* export private part */
768
0
    ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
769
0
    if (ret != 0)
770
0
        return ret;
771
772
    /* export public part */
773
0
    return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
774
0
}
775
776
#endif /* HAVE_CURVE25519_KEY_EXPORT */
777
778
#ifdef HAVE_CURVE25519_KEY_IMPORT
779
780
/* curve25519 private key import (Big endian)
781
 * Public key to match private key needs to be imported too
782
 * return 0 on success */
783
int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
784
                                     const byte* pub, word32 pubSz,
785
                                     curve25519_key* key)
786
24
{
787
24
    return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz,
788
24
                                               key, EC25519_BIG_ENDIAN);
789
24
}
790
791
/* curve25519 private key import (Big or Little endian)
792
 * Public key to match private key needs to be imported too
793
 * return 0 on success */
794
int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
795
                                        const byte* pub, word32 pubSz,
796
                                        curve25519_key* key, int endian)
797
24
{
798
24
    int ret;
799
800
    /* import private part */
801
24
    ret = wc_curve25519_import_private_ex(priv, privSz, key, endian);
802
24
    if (ret != 0)
803
23
        return ret;
804
805
    /* import public part */
806
1
    return wc_curve25519_import_public_ex(pub, pubSz, key, endian);
807
24
}
808
809
/* curve25519 private key import only. (Big endian)
810
 * return 0 on success */
811
int wc_curve25519_import_private(const byte* priv, word32 privSz,
812
                                 curve25519_key* key)
813
0
{
814
0
    return wc_curve25519_import_private_ex(priv, privSz,
815
0
                                           key, EC25519_BIG_ENDIAN);
816
0
}
817
818
/* curve25519 private key import only. (Big or Little endian)
819
 * return 0 on success */
820
int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
821
                                    curve25519_key* key, int endian)
822
24
{
823
    /* sanity check */
824
24
    if (key == NULL || priv == NULL) {
825
0
        return BAD_FUNC_ARG;
826
0
    }
827
828
    /* check size of incoming keys */
829
24
    if ((int)privSz != CURVE25519_KEYSIZE) {
830
23
        return ECC_BAD_ARG_E;
831
23
    }
832
833
#ifdef WOLFSSL_SE050
834
#ifdef WOLFSSL_SE050_AUTO_ERASE
835
    wc_se050_erase_object(key->keyId);
836
#endif
837
    /* release NXP resources if set */
838
    se050_curve25519_free_key(key);
839
#endif
840
841
    /* import private scalar with endianness */
842
1
    curve25519_copy_point(key->k, priv, endian);
843
1
    key->privSet = 1;
844
845
1
    key->dp = &curve25519_sets[0];
846
847
    /* Clamp the key */
848
1
    return curve25519_priv_clamp(key->k);
849
24
}
850
851
#endif /* HAVE_CURVE25519_KEY_IMPORT */
852
853
#ifndef WC_NO_CONSTRUCTORS
854
curve25519_key* wc_curve25519_new(void* heap, int devId, int *result_code)
855
0
{
856
0
    int ret;
857
0
    curve25519_key* key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), heap,
858
0
                           DYNAMIC_TYPE_CURVE25519);
859
0
    if (key == NULL) {
860
0
        ret = MEMORY_E;
861
0
    }
862
0
    else {
863
0
        ret = wc_curve25519_init_ex(key, heap, devId);
864
0
        if (ret != 0) {
865
0
            XFREE(key, heap, DYNAMIC_TYPE_CURVE25519);
866
0
            key = NULL;
867
0
        }
868
0
    }
869
870
0
    if (result_code != NULL)
871
0
        *result_code = ret;
872
873
0
    return key;
874
0
}
875
876
0
int wc_curve25519_delete(curve25519_key* key, curve25519_key** key_p) {
877
0
    if (key == NULL)
878
0
        return BAD_FUNC_ARG;
879
0
    wc_curve25519_free(key);
880
0
    XFREE(key, key->heap, DYNAMIC_TYPE_CURVE25519);
881
0
    if (key_p != NULL)
882
0
        *key_p = NULL;
883
0
    return 0;
884
0
}
885
#endif /* !WC_NO_CONSTRUCTORS */
886
887
int wc_curve25519_init_ex(curve25519_key* key, void* heap, int devId)
888
3.29k
{
889
3.29k
    if (key == NULL)
890
0
       return BAD_FUNC_ARG;
891
892
3.29k
    XMEMSET(key, 0, sizeof(*key));
893
894
    /* currently the format for curve25519 */
895
3.29k
    key->dp = &curve25519_sets[0];
896
897
3.29k
#ifdef WOLF_CRYPTO_CB
898
3.29k
    key->devId = devId;
899
#else
900
    (void)devId;
901
#endif
902
3.29k
    (void)heap; /* if needed for XMALLOC/XFREE in future */
903
904
3.29k
#ifndef FREESCALE_LTC_ECC
905
3.29k
    fe_init();
906
3.29k
#endif
907
908
#ifdef WOLFSSL_CHECK_MEM_ZERO
909
    wc_MemZero_Add("wc_curve25519_init_ex key->k", key->k, CURVE25519_KEYSIZE);
910
#endif
911
912
3.29k
    return 0;
913
3.29k
}
914
915
int wc_curve25519_init(curve25519_key* key)
916
946
{
917
946
    return wc_curve25519_init_ex(key, NULL, INVALID_DEVID);
918
946
}
919
920
/* Clean the memory of a key */
921
void wc_curve25519_free(curve25519_key* key)
922
4.68k
{
923
4.68k
    if (key == NULL)
924
1.39k
       return;
925
926
#ifdef WOLFSSL_SE050
927
    se050_curve25519_free_key(key);
928
#endif
929
930
3.29k
    ForceZero(key, sizeof(*key));
931
932
#ifdef WOLFSSL_CHECK_MEM_ZERO
933
    wc_MemZero_Check(key, sizeof(curve25519_key));
934
#endif
935
3.29k
}
936
937
#ifdef WOLFSSL_CURVE25519_BLINDING
938
int wc_curve25519_set_rng(curve25519_key* key, WC_RNG* rng)
939
2.82k
{
940
2.82k
    if (key == NULL)
941
0
        return BAD_FUNC_ARG;
942
2.82k
    key->rng = rng;
943
2.82k
    return 0;
944
2.82k
}
945
#endif
946
947
/* get key size */
948
int wc_curve25519_size(curve25519_key* key)
949
0
{
950
0
    if (key == NULL)
951
0
        return 0;
952
953
0
    return key->dp->size;
954
0
}
955
956
#endif /*HAVE_CURVE25519*/