Coverage Report

Created: 2026-09-20 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-fastmath/wolfcrypt/src/curve448.c
Line
Count
Source
1
/* curve448.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
/* Implemented to: RFC 7748 */
23
24
/* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work.
25
 * Reworked for curve448 by Sean Parkinson.
26
 */
27
28
/*
29
 * Curve448 Build Options:
30
 *
31
 * HAVE_CURVE448:            Enable Curve448 support                default: off
32
 * HAVE_CURVE448_SHARED_SECRET: Enable Curve448 shared secret      default: on
33
 *                            (when HAVE_CURVE448 is enabled)
34
 * HAVE_CURVE448_KEY_EXPORT: Enable Curve448 key export            default: on
35
 * HAVE_CURVE448_KEY_IMPORT: Enable Curve448 key import            default: on
36
 * WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK: Skip ECDH shared secret != 0 check
37
 *                                                                  default: off
38
 */
39
40
#define _WC_BUILDING_CURVE448_C
41
42
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
43
44
#ifdef HAVE_CURVE448
45
46
#include <wolfssl/wolfcrypt/curve448.h>
47
#ifdef WOLF_CRYPTO_CB
48
    #include <wolfssl/wolfcrypt/cryptocb.h>
49
#endif
50
#ifdef NO_INLINE
51
    #include <wolfssl/wolfcrypt/misc.h>
52
#else
53
    #define WOLFSSL_MISC_INCLUDED
54
    #include <wolfcrypt/src/misc.c>
55
#endif
56
57
/* Check the private scalar is clamped per RFC 7748 section 5:
58
 * low two bits of byte 0 clear and top bit of byte 55 set. */
59
static WC_INLINE int curve448_priv_clamp_check(const byte* priv)
60
1.01k
{
61
1.01k
    int ret = 0;
62
1.01k
    if ((priv[0] & 0x03) || !(priv[CURVE448_KEY_SIZE-1] & 0x80)) {
63
0
        ret = ECC_BAD_ARG_E;
64
0
    }
65
1.01k
    return ret;
66
1.01k
}
67
68
/* Compute pub = priv * basepoint(5).
69
 *
70
 * devId  [in]  Device to offload to, INVALID_DEVID for the caller's choice.
71
 * cbOk   [in]  Whether the private scalar may be offered to a crypto
72
 *              callback at all.  The keyless public API sets this, since it
73
 *              has no key to take a devId from; a key-owned scalar only sets
74
 *              it when the key is actually bound to a device, so an unbound
75
 *              key is never offloaded to whichever device happens to be
76
 *              registered first.
77
 */
78
static int curve448_make_pub_ex(int public_size, byte* pub, int private_size,
79
    const byte* priv, int devId, int cbOk)
80
1.01k
{
81
1.01k
    int ret;
82
1.01k
#ifndef WOLF_CRYPTO_CB_ONLY_CURVE448
83
1.01k
    unsigned char basepoint[CURVE448_KEY_SIZE] = {5};
84
1.01k
#endif
85
86
1.01k
    if ((pub == NULL) || (priv == NULL)) {
87
0
        return ECC_BAD_ARG_E;
88
0
    }
89
1.01k
    if ((public_size  != CURVE448_PUB_KEY_SIZE) ||
90
1.01k
        (private_size != CURVE448_KEY_SIZE)) {
91
0
        return ECC_BAD_ARG_E;
92
0
    }
93
94
    /* check clamping */
95
1.01k
    ret = curve448_priv_clamp_check(priv);
96
1.01k
    if (ret != 0)
97
0
        return ret;
98
99
1.01k
#ifdef WOLF_CRYPTO_CB
100
1.01k
    if (cbOk) {
101
0
        ret = wc_CryptoCb_Curve448MakePub(devId, public_size, pub,
102
0
            private_size, priv);
103
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
104
0
            return ret;
105
        /* fall-through when unavailable */
106
0
    }
107
#else
108
    (void)devId;
109
    (void)cbOk;
110
#endif
111
112
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE448
113
    ret = NO_VALID_DEVID;
114
#else
115
1.01k
    fe448_init();
116
117
    /* compute public key */
118
1.01k
    ret = curve448(pub, priv, basepoint);
119
1.01k
#endif /* WOLF_CRYPTO_CB_ONLY_CURVE448 */
120
121
1.01k
    return ret;
122
1.01k
}
123
124
/* Derive a key's public point from its own private scalar.
125
 *
126
 * Only wc_curve448_make_key() and the public key export use this, so it is
127
 * unreferenced when the software key generation is stripped out and export is
128
 * disabled.
129
 */
130
#if !defined(WOLF_CRYPTO_CB_ONLY_CURVE448) || \
131
    defined(HAVE_CURVE448_KEY_EXPORT)
132
static int curve448_key_make_pub(curve448_key* key)
133
1.01k
{
134
1.01k
#ifdef WOLF_CRYPTO_CB
135
    #ifdef WOLF_CRYPTO_CB_FIND
136
    /* the find callback gets to route unbound keys */
137
    const int cbOk = 1;
138
    #else
139
1.01k
    const int cbOk = (key->devId != INVALID_DEVID);
140
1.01k
    #endif
141
142
1.01k
    return curve448_make_pub_ex((int)sizeof(key->p), key->p,
143
1.01k
        (int)sizeof(key->k), key->k, key->devId, cbOk);
144
#else
145
    return curve448_make_pub_ex((int)sizeof(key->p), key->p,
146
        (int)sizeof(key->k), key->k, INVALID_DEVID, 0);
147
#endif
148
1.01k
}
149
#endif /* !WOLF_CRYPTO_CB_ONLY_CURVE448 || HAVE_CURVE448_KEY_EXPORT */
150
151
int wc_curve448_make_pub(int public_size, byte* pub, int private_size,
152
    const byte* priv)
153
0
{
154
    /* no key, so no device was selected: any registered one may serve it */
155
0
    return curve448_make_pub_ex(public_size, pub, private_size, priv,
156
0
        INVALID_DEVID, 1);
157
0
}
158
159
/* Is every byte of the curve448 result zero? Only reached when the caller's
160
 * basepoint is of small order, which leaks the result to anyone watching. */
161
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
162
static WC_INLINE int curve448_result_is_zero(const byte* out)
163
0
{
164
0
    int i;
165
0
    byte t = 0;
166
0
    for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
167
0
        t |= out[i];
168
0
    }
169
0
    return (t == 0);
170
0
}
171
#endif
172
173
/* Multiply a scalar (private key) against any basepoint over curve448.
174
 *
175
 * An all-zero result is rejected with ECC_OUT_OF_RANGE_E, matching
176
 * wc_curve448_shared_secret_ex; define WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK to
177
 * get the raw scalar multiplication result instead.
178
 */
179
int wc_curve448_generic(int public_size, byte* pub,
180
                        int private_size, const byte* priv,
181
                        int basepoint_size, const byte* basepoint)
182
0
{
183
0
    int ret;
184
185
0
    if ((pub == NULL) || (priv == NULL) || (basepoint == NULL)) {
186
0
        return ECC_BAD_ARG_E;
187
0
    }
188
0
    if ((public_size    != CURVE448_PUB_KEY_SIZE) ||
189
0
        (private_size   != CURVE448_KEY_SIZE) ||
190
0
        (basepoint_size != CURVE448_KEY_SIZE)) {
191
0
        return ECC_BAD_ARG_E;
192
0
    }
193
194
    /* check clamping */
195
0
    ret = curve448_priv_clamp_check(priv);
196
0
    if (ret != 0)
197
0
        return ret;
198
199
0
#ifdef WOLF_CRYPTO_CB
200
    /* no key, so no device was selected: any registered one may serve it */
201
0
    ret = wc_CryptoCb_Curve448Generic(INVALID_DEVID, public_size, pub,
202
0
        private_size, priv, basepoint_size, basepoint);
203
0
    if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
204
0
    #ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
205
        /* RFC 7748: reject an all-zero result from the callback too */
206
0
        if ((ret == 0) && curve448_result_is_zero(pub)) {
207
0
            ret = ECC_OUT_OF_RANGE_E;
208
0
        }
209
0
    #endif
210
0
        return ret;
211
0
    }
212
    /* fall-through when unavailable */
213
0
#endif
214
215
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE448
216
    ret = NO_VALID_DEVID;
217
#else
218
0
    fe448_init();
219
220
0
    ret = curve448(pub, priv, basepoint);
221
0
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
222
0
    if ((ret == 0) && curve448_result_is_zero(pub)) {
223
0
        ret = ECC_OUT_OF_RANGE_E;
224
0
    }
225
0
#endif
226
0
#endif /* WOLF_CRYPTO_CB_ONLY_CURVE448 */
227
228
0
    return ret;
229
0
}
230
231
232
/* Make a new curve448 private/public key.
233
 *
234
 * rng      [in]  Random number generator.
235
 * keysize  [in]  Size of the key to generate.
236
 * key      [in]  Curve448 key object.
237
 * returns BAD_FUNC_ARG when rng or key are NULL,
238
 *         ECC_BAD_ARG_E when keysize is not CURVE448_KEY_SIZE,
239
 *         0 otherwise.
240
 */
241
int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key)
242
1.14k
{
243
1.14k
    int  ret = 0;
244
245
1.14k
    if ((key == NULL) || (rng == NULL)) {
246
0
        ret = BAD_FUNC_ARG;
247
0
    }
248
249
    /* currently only a key size of 56 bytes is used */
250
1.14k
    if ((ret == 0) && (keysize != CURVE448_KEY_SIZE)) {
251
0
        ret = ECC_BAD_ARG_E;
252
0
    }
253
254
1.14k
#ifdef WOLF_CRYPTO_CB
255
1.14k
    if (ret == 0) {
256
1.14k
    #ifndef WOLF_CRYPTO_CB_FIND
257
1.14k
        if (key->devId != INVALID_DEVID)
258
0
    #endif
259
0
        {
260
0
            ret = wc_CryptoCb_Curve448Gen(rng, keysize, key);
261
0
            if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
262
0
                return ret;
263
            /* fall-through when unavailable */
264
0
            ret = 0;
265
0
        }
266
1.14k
    }
267
1.14k
#endif
268
269
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE448
270
    /* software path stripped; callback is the only provider */
271
    if (ret == 0) {
272
        ret = NO_VALID_DEVID;
273
    }
274
#else
275
1.14k
    if (ret == 0) {
276
        /* random number for private key */
277
1.14k
        ret = wc_RNG_GenerateBlock(rng, key->k, (word32)keysize);
278
1.14k
    }
279
1.14k
    if (ret == 0) {
280
1.01k
        key->privSet = 1;
281
282
        /* clamp private */
283
1.01k
        key->k[0] &= 0xfc;
284
1.01k
        key->k[CURVE448_KEY_SIZE-1] |= 0x80;
285
286
        /* compute public */
287
1.01k
        ret = curve448_key_make_pub(key);
288
1.01k
        if (ret == 0) {
289
1.01k
            key->pubSet = 1;
290
1.01k
        }
291
0
        else {
292
0
            ForceZero(key->k, sizeof(key->k));
293
0
            XMEMSET(key->p, 0, sizeof(key->p));
294
0
        }
295
1.01k
    }
296
1.14k
#endif /* WOLF_CRYPTO_CB_ONLY_CURVE448 */
297
298
1.14k
    return ret;
299
1.14k
}
300
301
#ifdef HAVE_CURVE448_SHARED_SECRET
302
303
/* Calculate the shared secret from the private key and peer's public key.
304
 * Calculation over curve448.
305
 * Secret encoded big-endian.
306
 *
307
 * private_key  [in]      Curve448 private key.
308
 * public_key   [in]      Curve448 public key.
309
 * out          [in]      Array to hold shared secret.
310
 * outLen       [in/out]  On in, the number of bytes in array.
311
 *                        On out, the number bytes put into array.
312
 * returns BAD_FUNC_ARG when a parameter is NULL or outLen is less than
313
 *         CURVE448_KEY_SIZE,
314
 *         0 otherwise.
315
 */
316
int wc_curve448_shared_secret(curve448_key* private_key,
317
                              curve448_key* public_key,
318
                              byte* out, word32* outLen)
319
0
{
320
0
    return wc_curve448_shared_secret_ex(private_key, public_key, out, outLen,
321
0
                                        EC448_BIG_ENDIAN);
322
0
}
323
324
/* Calculate the shared secret from the private key and peer's public key.
325
 * Calculation over curve448.
326
 *
327
 * private_key  [in]      Curve448 private key.
328
 * public_key   [in]      Curve448 public key.
329
 * out          [in]      Array to hold shared secret.
330
 * outLen       [in/out]  On in, the number of bytes in array.
331
 *                        On out, the number bytes put into array.
332
 * endian       [in]      Endianness to use when encoding number in array.
333
 * returns BAD_FUNC_ARG when a parameter is NULL or outLen is less than
334
 *         CURVE448_PUB_KEY_SIZE,
335
 *         0 otherwise.
336
 */
337
int wc_curve448_shared_secret_ex(curve448_key* private_key,
338
                                 curve448_key* public_key,
339
                                 byte* out, word32* outLen, int endian)
340
40
{
341
40
#ifndef WOLF_CRYPTO_CB_ONLY_CURVE448
342
40
    unsigned char o[CURVE448_PUB_KEY_SIZE];
343
40
    int i;
344
40
#endif
345
40
    int ret = 0;
346
347
    /* sanity check */
348
40
    if ((private_key == NULL) || (public_key == NULL) || (out == NULL) ||
349
40
                        (outLen == NULL) || (*outLen < CURVE448_PUB_KEY_SIZE)) {
350
0
        return BAD_FUNC_ARG;
351
0
    }
352
    /* make sure we have a populated private and public key */
353
40
    if (!private_key->privSet || !public_key->pubSet) {
354
0
        return ECC_BAD_ARG_E;
355
0
    }
356
357
40
#ifdef WOLF_CRYPTO_CB
358
40
    #ifndef WOLF_CRYPTO_CB_FIND
359
40
    if (private_key->devId != INVALID_DEVID)
360
0
    #endif
361
0
    {
362
0
        ret = wc_CryptoCb_Curve448(private_key, public_key, out, outLen,
363
0
            endian);
364
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
365
0
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
366
            /* RFC 7748: reject an all-zero secret from the callback too */
367
0
            if (ret == 0) {
368
0
                int j;
369
0
                byte t = 0;
370
0
                for (j = 0; j < CURVE448_PUB_KEY_SIZE; j++) {
371
0
                    t |= out[j];
372
0
                }
373
0
                if (t == 0) {
374
0
                    ret = ECC_OUT_OF_RANGE_E;
375
0
                }
376
0
            }
377
0
#endif
378
0
            return ret;
379
0
        }
380
        /* fall-through when unavailable */
381
0
        ret = 0;
382
0
    }
383
40
#endif
384
385
#ifdef WOLF_CRYPTO_CB_ONLY_CURVE448
386
    /* software path stripped; callback is the only provider */
387
    if (ret == 0) {
388
        ret = NO_VALID_DEVID;
389
    }
390
#else
391
#ifdef WOLFSSL_CHECK_MEM_ZERO
392
    /* Register the buffer after the early returns so every later path
393
     * reaches the cleanup ForceZero. XMEMSET makes it defined. */
394
    XMEMSET(o, 0, sizeof(o));
395
    wc_MemZero_Add("wc_curve448_shared_secret_ex o", o, CURVE448_PUB_KEY_SIZE);
396
#endif
397
398
40
    if (ret == 0) {
399
40
        ret = curve448(o, private_key->k, public_key->p);
400
40
    }
401
40
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
402
40
    if (ret == 0) {
403
40
        byte t = 0;
404
2.28k
        for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
405
2.24k
            t |= o[i];
406
2.24k
        }
407
40
        if (t == 0) {
408
0
            ret = ECC_OUT_OF_RANGE_E;
409
0
        }
410
40
    }
411
40
#endif
412
40
    if (ret == 0) {
413
40
        if (endian == EC448_BIG_ENDIAN) {
414
            /* put shared secret key in Big Endian format */
415
0
            for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
416
0
                 out[i] = o[CURVE448_PUB_KEY_SIZE - i -1];
417
0
            }
418
0
        }
419
40
        else {
420
            /* put shared secret key in Little Endian format */
421
40
            XMEMCPY(out, o, CURVE448_PUB_KEY_SIZE);
422
40
        }
423
424
40
        *outLen = CURVE448_PUB_KEY_SIZE;
425
40
    }
426
427
40
    ForceZero(o, CURVE448_PUB_KEY_SIZE);
428
#ifdef WOLFSSL_CHECK_MEM_ZERO
429
    wc_MemZero_Check(o, CURVE448_PUB_KEY_SIZE);
430
#endif
431
40
#endif /* WOLF_CRYPTO_CB_ONLY_CURVE448 */
432
433
40
    return ret;
434
40
}
435
436
#endif /* HAVE_CURVE448_SHARED_SECRET */
437
438
#ifdef HAVE_CURVE448_KEY_EXPORT
439
440
/* Export the curve448 public key.
441
 * Public key encoded big-endian.
442
 *
443
 * key     [in]      Curve448 public key.
444
 * out     [in]      Array to hold public key.
445
 * outLen  [in/out]  On in, the number of bytes in array.
446
 *                   On out, the number bytes put into array.
447
 * returns BAD_FUNC_ARG when a parameter is NULL,
448
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE or
449
 *         neither the public nor the private key has been set,
450
 *         0 otherwise.
451
 */
452
int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen)
453
1
{
454
1
    return wc_curve448_export_public_ex(key, out, outLen, EC448_BIG_ENDIAN);
455
1
}
456
457
/* Export the curve448 public key.
458
 *
459
 * key     [in]      Curve448 public key.
460
 * out     [in]      Array to hold public key.
461
 * outLen  [in/out]  On in, the number of bytes in array.
462
 *                   On out, the number bytes put into array.
463
 * endian  [in]      Endianness to use when encoding number in array.
464
 * returns BAD_FUNC_ARG when a parameter is NULL,
465
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE or
466
 *         neither the public nor the private key has been set,
467
 *         0 otherwise.
468
 */
469
int wc_curve448_export_public_ex(curve448_key* key, byte* out, word32* outLen,
470
                                 int endian)
471
834
{
472
834
    int ret = 0;
473
474
834
    if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
475
60
        ret = BAD_FUNC_ARG;
476
60
    }
477
478
    /* check and set outgoing key size */
479
834
    if ((ret == 0) && (*outLen < CURVE448_PUB_KEY_SIZE)) {
480
19
        *outLen = CURVE448_PUB_KEY_SIZE;
481
19
        ret = ECC_BAD_ARG_E;
482
19
    }
483
484
    /* no public key to export and no private key to derive it from */
485
834
    if ((ret == 0) && (!key->pubSet) && (!key->privSet)) {
486
0
        ret = ECC_BAD_ARG_E;
487
0
    }
488
834
    if (ret == 0) {
489
        /* calculate public if missing */
490
755
        if (!key->pubSet) {
491
0
            ret = curve448_key_make_pub(key);
492
0
            key->pubSet = (ret == 0);
493
0
        }
494
755
    }
495
834
    if (ret == 0) {
496
755
        *outLen = CURVE448_PUB_KEY_SIZE;
497
755
        if (endian == EC448_BIG_ENDIAN) {
498
1
            int i;
499
            /* read keys in Big Endian format */
500
57
            for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
501
56
                out[i] = key->p[CURVE448_PUB_KEY_SIZE - i - 1];
502
56
            }
503
1
        }
504
754
        else {
505
754
            XMEMCPY(out, key->p, CURVE448_PUB_KEY_SIZE);
506
754
        }
507
755
    }
508
509
834
    return ret;
510
834
}
511
512
#endif /* HAVE_CURVE448_KEY_EXPORT */
513
514
#ifdef HAVE_CURVE448_KEY_IMPORT
515
516
/* Import a curve448 public key from a byte array.
517
 * Public key encoded in big-endian.
518
 *
519
 * in      [in]  Array holding public key.
520
 * inLen   [in]  Number of bytes of data in array.
521
 * key     [in]  Curve448 public key.
522
 * returns BAD_FUNC_ARG when a parameter is NULL,
523
 *         ECC_BAD_ARG_E when inLen is less than CURVE448_PUB_KEY_SIZE,
524
 *         0 otherwise.
525
 */
526
int wc_curve448_import_public(const byte* in, word32 inLen, curve448_key* key)
527
23
{
528
23
    return wc_curve448_import_public_ex(in, inLen, key, EC448_BIG_ENDIAN);
529
23
}
530
531
/* Import a curve448 public key from a byte array.
532
 *
533
 * in      [in]  Array holding public key.
534
 * inLen   [in]  Number of bytes of data in array.
535
 * key     [in]  Curve448 public key.
536
 * endian  [in]  Endianness of encoded number in byte array.
537
 * returns BAD_FUNC_ARG when a parameter is NULL,
538
 *         ECC_BAD_ARG_E when inLen is less than CURVE448_PUB_KEY_SIZE,
539
 *         0 otherwise.
540
 */
541
int wc_curve448_import_public_ex(const byte* in, word32 inLen,
542
                                 curve448_key* key, int endian)
543
92
{
544
92
    int ret = 0;
545
546
    /* sanity check */
547
92
    if ((key == NULL) || (in == NULL)) {
548
1
        ret = BAD_FUNC_ARG;
549
1
    }
550
551
    /* check size of incoming keys */
552
92
    if ((ret == 0) && (inLen != CURVE448_PUB_KEY_SIZE)) {
553
22
       ret = ECC_BAD_ARG_E;
554
22
    }
555
556
92
    if (ret == 0) {
557
69
        if (endian == EC448_BIG_ENDIAN) {
558
1
            int i;
559
            /* read keys in Big Endian format */
560
57
            for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
561
56
                key->p[i] = in[CURVE448_PUB_KEY_SIZE - i - 1];
562
56
            }
563
1
        }
564
68
        else
565
68
            XMEMCPY(key->p, in, inLen);
566
69
        key->pubSet = 1;
567
69
    }
568
569
92
    return ret;
570
92
}
571
572
/* Check the public key value (big or little endian)
573
 *
574
 * pub     [in]  Public key bytes.
575
 * pubSz   [in]  Size of public key in bytes.
576
 * endian  [in]  Public key bytes passed in as big-endian or little-endian.
577
 * returns BAD_FUNC_ARGS when pub is NULL,
578
 *         ECC_BAD_ARG_E when key length is not 56 bytes, public key value is
579
 *         zero or one;
580
 *         BUFFER_E when size of public key is zero;
581
 *         0 otherwise.
582
 */
583
int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian)
584
765
{
585
765
    int ret = 0;
586
587
765
    if (pub == NULL) {
588
0
        ret = BAD_FUNC_ARG;
589
0
    }
590
591
    /* Check for empty key data */
592
765
    if ((ret == 0) && (pubSz == 0)) {
593
4
        ret = BUFFER_E;
594
4
    }
595
596
    /* Check key length */
597
765
    if ((ret == 0) && (pubSz != CURVE448_PUB_KEY_SIZE)) {
598
85
        ret = ECC_BAD_ARG_E;
599
85
    }
600
601
765
    if (ret == 0) {
602
676
        word32 i;
603
604
676
        if (endian == EC448_LITTLE_ENDIAN) {
605
            /* Check for value of zero or one */
606
1.14k
            for (i = CURVE448_PUB_KEY_SIZE - 1; i > 0; i--) {
607
1.13k
                if (pub[i] != 0) {
608
161
                    break;
609
161
                }
610
1.13k
            }
611
175
            if ((i == 0) && (pub[0] == 0 || pub[0] == 1)) {
612
6
                return ECC_BAD_ARG_E;
613
6
            }
614
            /* Check for order-1 or higher */
615
2.12k
            for (i = CURVE448_PUB_KEY_SIZE - 1; i > 28; i--) {
616
2.06k
                if (pub[i] != 0xff) {
617
105
                    break;
618
105
                }
619
2.06k
            }
620
169
            if ((i == 28) && (pub[i] == 0xff)) {
621
6
                return ECC_BAD_ARG_E;
622
6
            }
623
163
            if ((i == 28) && (pub[i] == 0xfe)) {
624
568
                for (--i; i > 0; i--) {
625
555
                    if (pub[i] != 0xff) {
626
26
                        break;
627
26
                    }
628
555
                }
629
39
                if ((i == 0) && (pub[i] >= 0xfe)) {
630
3
                    return ECC_BAD_ARG_E;
631
3
                }
632
39
            }
633
163
        }
634
501
        else {
635
            /* Check for value of zero or one */
636
1.22k
            for (i = 0; i < CURVE448_PUB_KEY_SIZE-1; i++) {
637
1.21k
                if (pub[i] != 0) {
638
491
                    break;
639
491
                }
640
1.21k
            }
641
501
            if ((i == CURVE448_PUB_KEY_SIZE - 1) &&
642
10
                (pub[i] == 0 || pub[i] == 1)) {
643
2
                ret = ECC_BAD_ARG_E;
644
2
            }
645
            /* Check for order-1 or higher */
646
1.81k
            for (i = 0; i < 27; i++) {
647
1.77k
                if (pub[i] != 0xff) {
648
461
                    break;
649
461
                }
650
1.77k
            }
651
501
            if ((i == 27) && (pub[i] == 0xff)) {
652
3
                return ECC_BAD_ARG_E;
653
3
            }
654
498
            if ((i == 27) && (pub[i] == 0xfe)) {
655
475
                for (++i; i < CURVE448_PUB_KEY_SIZE - 1; i++) {
656
463
                    if (pub[i] != 0xff) {
657
13
                        break;
658
13
                    }
659
463
                }
660
25
                if ((i == CURVE448_PUB_KEY_SIZE - 1) && (pub[i] >= 0xfe)) {
661
2
                    return ECC_BAD_ARG_E;
662
2
                }
663
25
            }
664
498
        }
665
676
    }
666
667
745
    return ret;
668
765
}
669
670
#endif /* HAVE_CURVE448_KEY_IMPORT */
671
672
673
#ifdef HAVE_CURVE448_KEY_EXPORT
674
675
/* Export the curve448 private key raw form.
676
 * Private key encoded big-endian.
677
 *
678
 * key     [in]      Curve448 private key.
679
 * out     [in]      Array to hold private key.
680
 * outLen  [in/out]  On in, the number of bytes in array.
681
 *                   On out, the number bytes put into array.
682
 * returns BAD_FUNC_ARG when a parameter is NULL,
683
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_KEY_SIZE,
684
 *         0 otherwise.
685
 */
686
int wc_curve448_export_private_raw(curve448_key* key, byte* out, word32* outLen)
687
0
{
688
0
    return wc_curve448_export_private_raw_ex(key, out, outLen,
689
0
                                             EC448_BIG_ENDIAN);
690
0
}
691
692
/* Export the curve448 private key raw form.
693
 *
694
 * key     [in]      Curve448 private key.
695
 * out     [in]      Array to hold private key.
696
 * outLen  [in/out]  On in, the number of bytes in array.
697
 *                   On out, the number bytes put into array.
698
 * endian  [in]      Endianness to use when encoding number in array.
699
 * returns BAD_FUNC_ARG when a parameter is NULL,
700
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_KEY_SIZE,
701
 *         0 otherwise.
702
 */
703
int wc_curve448_export_private_raw_ex(curve448_key* key, byte* out,
704
                                      word32* outLen, int endian)
705
403
{
706
403
    int ret = 0;
707
708
    /* sanity check */
709
403
    if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
710
120
        ret = BAD_FUNC_ARG;
711
120
    }
712
713
403
    if ((ret == 0) && (!key->privSet)) {
714
0
        ret = ECC_BAD_ARG_E;
715
0
    }
716
717
    /* check size of outgoing buffer */
718
403
    if ((ret == 0) && (*outLen < CURVE448_KEY_SIZE)) {
719
26
        *outLen = CURVE448_KEY_SIZE;
720
26
        ret = ECC_BAD_ARG_E;
721
26
    }
722
403
    if (ret == 0) {
723
257
        *outLen = CURVE448_KEY_SIZE;
724
725
257
        if (endian == EC448_BIG_ENDIAN) {
726
0
            int i;
727
            /* put the key in Big Endian format */
728
0
            for (i = 0; i < CURVE448_KEY_SIZE; i++) {
729
0
                out[i] = key->k[CURVE448_KEY_SIZE - i - 1];
730
0
            }
731
0
        }
732
257
        else {
733
257
            XMEMCPY(out, key->k, CURVE448_KEY_SIZE);
734
257
        }
735
257
    }
736
737
403
    return ret;
738
403
}
739
740
/* Export the curve448 private and public keys in raw form.
741
 * Private and public key encoded big-endian.
742
 *
743
 * key     [in]      Curve448 private key.
744
 * priv    [in]      Array to hold private key.
745
 * privSz  [in/out]  On in, the number of bytes in private key array.
746
 *                   On out, the number bytes put into private key array.
747
 * pub     [in]      Array to hold public key.
748
 * pubSz   [in/out]  On in, the number of bytes in public key array.
749
 *                   On out, the number bytes put into public key array.
750
 * returns BAD_FUNC_ARG when a parameter is NULL,
751
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
752
 *         less than CURVE448_PUB_KEY_SIZE,
753
 *         0 otherwise.
754
 */
755
int wc_curve448_export_key_raw(curve448_key* key, byte* priv, word32 *privSz,
756
                               byte* pub, word32 *pubSz)
757
0
{
758
0
    return wc_curve448_export_key_raw_ex(key, priv, privSz, pub, pubSz,
759
0
                                         EC448_BIG_ENDIAN);
760
0
}
761
762
/* Export the curve448 private and public keys in raw form.
763
 *
764
 * key     [in]      Curve448 private key.
765
 * priv    [in]      Array to hold private key.
766
 * privSz  [in/out]  On in, the number of bytes in private key array.
767
 *                   On out, the number bytes put into private key array.
768
 * pub     [in]      Array to hold public key.
769
 * pubSz   [in/out]  On in, the number of bytes in public key array.
770
 *                   On out, the number bytes put into public key array.
771
 * endian  [in]      Endianness to use when encoding number in array.
772
 * returns BAD_FUNC_ARG when a parameter is NULL,
773
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
774
 *         less than CURVE448_PUB_KEY_SIZE,
775
 *         0 otherwise.
776
 */
777
int wc_curve448_export_key_raw_ex(curve448_key* key, byte* priv, word32 *privSz,
778
                                  byte* pub, word32 *pubSz, int endian)
779
0
{
780
0
    int ret;
781
782
    /* export private part */
783
0
    ret = wc_curve448_export_private_raw_ex(key, priv, privSz, endian);
784
0
    if (ret == 0) {
785
        /* export public part */
786
0
        ret = wc_curve448_export_public_ex(key, pub, pubSz, endian);
787
0
    }
788
789
0
    return ret;
790
0
}
791
792
#endif /* HAVE_CURVE448_KEY_EXPORT */
793
794
#ifdef HAVE_CURVE448_KEY_IMPORT
795
796
/* Import curve448 private and public keys from a byte arrays.
797
 * Private and public keys encoded in big-endian.
798
 *
799
 * piv     [in]  Array holding private key.
800
 * privSz  [in]  Number of bytes of data in private key array.
801
 * pub     [in]  Array holding public key.
802
 * pubSz   [in]  Number of bytes of data in public key array.
803
 * key     [in]  Curve448 private/public key.
804
 * returns BAD_FUNC_ARG when a parameter is NULL,
805
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
806
 *         less than CURVE448_PUB_KEY_SIZE,
807
 *         0 otherwise.
808
 */
809
int wc_curve448_import_private_raw(const byte* priv, word32 privSz,
810
                                   const byte* pub, word32 pubSz,
811
                                   curve448_key* key)
812
22
{
813
22
    return wc_curve448_import_private_raw_ex(priv, privSz, pub, pubSz, key,
814
22
                                             EC448_BIG_ENDIAN);
815
22
}
816
817
/* Import curve448 private and public keys from a byte arrays.
818
 *
819
 * piv     [in]  Array holding private key.
820
 * privSz  [in]  Number of bytes of data in private key array.
821
 * pub     [in]  Array holding public key.
822
 * pubSz   [in]  Number of bytes of data in public key array.
823
 * key     [in]  Curve448 private/public key.
824
 * endian  [in]  Endianness of encoded numbers in byte arrays.
825
 * returns BAD_FUNC_ARG when a parameter is NULL,
826
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
827
 *         less than CURVE448_PUB_KEY_SIZE,
828
 *         0 otherwise.
829
 */
830
int wc_curve448_import_private_raw_ex(const byte* priv, word32 privSz,
831
                                      const byte* pub, word32 pubSz,
832
                                      curve448_key* key, int endian)
833
22
{
834
22
    int ret;
835
836
    /* import private part */
837
22
    ret = wc_curve448_import_private_ex(priv, privSz, key, endian);
838
22
    if (ret == 0) {
839
        /* import public part */
840
1
        return wc_curve448_import_public_ex(pub, pubSz, key, endian);
841
1
    }
842
843
21
    return ret;
844
22
}
845
846
/* Import curve448 private key from a byte array.
847
 * Private key encoded in big-endian.
848
 *
849
 * piv     [in]  Array holding private key.
850
 * privSz  [in]  Number of bytes of data in private key array.
851
 * key     [in]  Curve448 private/public key.
852
 * returns BAD_FUNC_ARG when a parameter is NULL,
853
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE,
854
 *         0 otherwise.
855
 */
856
int wc_curve448_import_private(const byte* priv, word32 privSz,
857
                               curve448_key* key)
858
0
{
859
0
    return wc_curve448_import_private_ex(priv, privSz, key, EC448_BIG_ENDIAN);
860
0
}
861
862
/* Import curve448 private key from a byte array.
863
 *
864
 * piv     [in]  Array holding private key.
865
 * privSz  [in]  Number of bytes of data in private key array.
866
 * key     [in]  Curve448 private/public key.
867
 * endian  [in]  Endianness of encoded number in byte array.
868
 * returns BAD_FUNC_ARG when a parameter is NULL,
869
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE,
870
 *         0 otherwise.
871
 */
872
int wc_curve448_import_private_ex(const byte* priv, word32 privSz,
873
                                  curve448_key* key, int endian)
874
22
{
875
22
    int ret = 0;
876
877
    /* sanity check */
878
22
    if ((key == NULL) || (priv == NULL)) {
879
0
        ret = BAD_FUNC_ARG;
880
0
    }
881
882
    /* check size of incoming keys */
883
22
    if ((ret == 0) && ((int)privSz != CURVE448_KEY_SIZE)) {
884
21
        ret = ECC_BAD_ARG_E;
885
21
    }
886
887
22
    if (ret == 0) {
888
1
        if (endian == EC448_BIG_ENDIAN) {
889
1
            int i;
890
            /* read the key in Big Endian format */
891
57
            for (i = 0; i < CURVE448_KEY_SIZE; i++) {
892
56
                key->k[i] = priv[CURVE448_KEY_SIZE - i - 1];
893
56
            }
894
1
        }
895
0
        else {
896
0
            XMEMCPY(key->k, priv, CURVE448_KEY_SIZE);
897
0
        }
898
899
        /* Clamp the key */
900
1
        key->k[0] &= 0xfc;
901
1
        key->k[CURVE448_KEY_SIZE-1] |= 0x80;
902
903
1
        key->privSet = 1;
904
1
    }
905
906
22
    return ret;
907
22
}
908
909
#endif /* HAVE_CURVE448_KEY_IMPORT */
910
911
912
#ifndef WC_NO_CONSTRUCTORS
913
curve448_key* wc_curve448_new(void* heap, int devId, int* result_code)
914
0
{
915
0
    int ret;
916
0
    curve448_key* key = (curve448_key*)XMALLOC(sizeof(curve448_key), heap,
917
0
                         DYNAMIC_TYPE_CURVE448);
918
0
    if (key == NULL) {
919
0
        ret = MEMORY_E;
920
0
    }
921
0
    else {
922
0
        ret = wc_curve448_init_ex(key, heap, devId);
923
0
        if (ret != 0) {
924
0
            XFREE(key, heap, DYNAMIC_TYPE_CURVE448);
925
0
            key = NULL;
926
0
        }
927
0
    }
928
929
0
    if (result_code != NULL)
930
0
        *result_code = ret;
931
932
0
    return key;
933
0
}
934
935
0
int wc_curve448_delete(curve448_key* key, curve448_key** key_p) {
936
0
    void* heap;
937
0
    if (key == NULL)
938
0
        return BAD_FUNC_ARG;
939
0
    heap = key->heap;
940
0
    wc_curve448_free(key);
941
0
    XFREE(key, heap, DYNAMIC_TYPE_CURVE448);
942
0
    if (key_p != NULL)
943
0
        *key_p = NULL;
944
0
    return 0;
945
0
}
946
#endif /* !WC_NO_CONSTRUCTORS */
947
948
/* Initialize the curve448 key with a heap hint and crypto callback devId. */
949
int wc_curve448_init_ex(curve448_key* key, void* heap, int devId)
950
1.27k
{
951
1.27k
    int ret = 0;
952
953
1.27k
    if (key == NULL) {
954
0
       ret = BAD_FUNC_ARG;
955
0
    }
956
957
1.27k
    if (ret == 0) {
958
1.27k
        XMEMSET(key, 0, sizeof(*key));
959
960
1.27k
    #ifdef WOLF_CRYPTO_CB
961
1.27k
        key->devId = devId;
962
    #else
963
        (void)devId;
964
    #endif
965
1.27k
        key->heap = heap;
966
967
    /* field math is implemented in the callback in crypto cb only */
968
1.27k
    #ifndef WOLF_CRYPTO_CB_ONLY_CURVE448
969
1.27k
        fe448_init();
970
1.27k
    #endif
971
972
    #ifdef WOLFSSL_CHECK_MEM_ZERO
973
        wc_MemZero_Add("wc_curve448_init key->k", &key->k, CURVE448_KEY_SIZE);
974
    #endif
975
1.27k
    }
976
977
1.27k
    return ret;
978
1.27k
}
979
980
/* Initialize the curve448 key.
981
 *
982
 * key  [in]  Curve448 key object.
983
 * returns BAD_FUNC_ARG when key is NULL,
984
 *         0 otherwise.
985
 */
986
int wc_curve448_init(curve448_key* key)
987
557
{
988
557
    return wc_curve448_init_ex(key, NULL, INVALID_DEVID);
989
557
}
990
991
992
/* Clears the curve448 key data.
993
 *
994
 * key  [in]  Curve448 key object.
995
 */
996
void wc_curve448_free(curve448_key* key)
997
1.32k
{
998
1.32k
    if (key != NULL) {
999
1.27k
        ForceZero(key->k, sizeof(key->k));
1000
1.27k
        XMEMSET(key->p, 0, sizeof(key->p));
1001
1.27k
        key->pubSet = 0;
1002
1.27k
        key->privSet = 0;
1003
    #ifdef WOLFSSL_CHECK_MEM_ZERO
1004
        wc_MemZero_Check(key, sizeof(curve448_key));
1005
    #endif
1006
1.27k
    }
1007
1.32k
}
1008
1009
1010
/* Get the curve448 key's size.
1011
 *
1012
 * key  [in]  Curve448 key object.
1013
 * returns 0 if key is NULL,
1014
 *         CURVE448_KEY_SIZE otherwise.
1015
 */
1016
int wc_curve448_size(curve448_key* key)
1017
0
{
1018
0
    int ret = 0;
1019
1020
0
    if (key != NULL) {
1021
0
        ret = CURVE448_KEY_SIZE;
1022
0
    }
1023
1024
0
    return ret;
1025
0
}
1026
1027
#endif /* HAVE_CURVE448 */
1028