Coverage Report

Created: 2026-08-15 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-heapmath/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 NO_INLINE
48
    #include <wolfssl/wolfcrypt/misc.h>
49
#else
50
    #define WOLFSSL_MISC_INCLUDED
51
    #include <wolfcrypt/src/misc.c>
52
#endif
53
54
int wc_curve448_make_pub(int public_size, byte* pub, int private_size,
55
    const byte* priv)
56
1.13k
{
57
1.13k
    int ret;
58
1.13k
    unsigned char basepoint[CURVE448_KEY_SIZE] = {5};
59
60
1.13k
    if ((pub == NULL) || (priv == NULL)) {
61
0
        return ECC_BAD_ARG_E;
62
0
    }
63
1.13k
    if ((public_size  != CURVE448_PUB_KEY_SIZE) ||
64
1.13k
        (private_size != CURVE448_KEY_SIZE)) {
65
0
        return ECC_BAD_ARG_E;
66
0
    }
67
68
1.13k
    fe448_init();
69
70
    /* compute public key */
71
1.13k
    ret = curve448(pub, priv, basepoint);
72
73
1.13k
    return ret;
74
1.13k
}
75
76
77
/* Make a new curve448 private/public key.
78
 *
79
 * rng      [in]  Random number generator.
80
 * keysize  [in]  Size of the key to generate.
81
 * key      [in]  Curve448 key object.
82
 * returns BAD_FUNC_ARG when rng or key are NULL,
83
 *         ECC_BAD_ARG_E when keysize is not CURVE448_KEY_SIZE,
84
 *         0 otherwise.
85
 */
86
int wc_curve448_make_key(WC_RNG* rng, int keysize, curve448_key* key)
87
1.26k
{
88
1.26k
    int  ret = 0;
89
90
1.26k
    if ((key == NULL) || (rng == NULL)) {
91
0
        ret = BAD_FUNC_ARG;
92
0
    }
93
94
    /* currently only a key size of 56 bytes is used */
95
1.26k
    if ((ret == 0) && (keysize != CURVE448_KEY_SIZE)) {
96
0
        ret = ECC_BAD_ARG_E;
97
0
    }
98
99
1.26k
    if (ret == 0) {
100
        /* random number for private key */
101
1.26k
        ret = wc_RNG_GenerateBlock(rng, key->k, (word32)keysize);
102
1.26k
    }
103
1.26k
    if (ret == 0) {
104
1.13k
        key->privSet = 1;
105
106
        /* clamp private */
107
1.13k
        key->k[0] &= 0xfc;
108
1.13k
        key->k[CURVE448_KEY_SIZE-1] |= 0x80;
109
110
        /* compute public */
111
1.13k
        ret = wc_curve448_make_pub((int)sizeof(key->p), key->p,
112
1.13k
                                   (int)sizeof(key->k), key->k);
113
1.13k
        if (ret == 0) {
114
1.13k
            key->pubSet = 1;
115
1.13k
        }
116
0
        else {
117
0
            ForceZero(key->k, sizeof(key->k));
118
0
            XMEMSET(key->p, 0, sizeof(key->p));
119
0
        }
120
1.13k
    }
121
122
1.26k
    return ret;
123
1.26k
}
124
125
#ifdef HAVE_CURVE448_SHARED_SECRET
126
127
/* Calculate the shared secret from the private key and peer's public key.
128
 * Calculation over curve448.
129
 * Secret encoded big-endian.
130
 *
131
 * private_key  [in]      Curve448 private key.
132
 * public_key   [in]      Curve448 public key.
133
 * out          [in]      Array to hold shared secret.
134
 * outLen       [in/out]  On in, the number of bytes in array.
135
 *                        On out, the number bytes put into array.
136
 * returns BAD_FUNC_ARG when a parameter is NULL or outLen is less than
137
 *         CURVE448_KEY_SIZE,
138
 *         0 otherwise.
139
 */
140
int wc_curve448_shared_secret(curve448_key* private_key,
141
                              curve448_key* public_key,
142
                              byte* out, word32* outLen)
143
0
{
144
0
    return wc_curve448_shared_secret_ex(private_key, public_key, out, outLen,
145
0
                                        EC448_BIG_ENDIAN);
146
0
}
147
148
/* Calculate the shared secret from the private key and peer's public key.
149
 * Calculation over curve448.
150
 *
151
 * private_key  [in]      Curve448 private key.
152
 * public_key   [in]      Curve448 public key.
153
 * out          [in]      Array to hold shared secret.
154
 * outLen       [in/out]  On in, the number of bytes in array.
155
 *                        On out, the number bytes put into array.
156
 * endian       [in]      Endianness to use when encoding number in array.
157
 * returns BAD_FUNC_ARG when a parameter is NULL or outLen is less than
158
 *         CURVE448_PUB_KEY_SIZE,
159
 *         0 otherwise.
160
 */
161
int wc_curve448_shared_secret_ex(curve448_key* private_key,
162
                                 curve448_key* public_key,
163
                                 byte* out, word32* outLen, int endian)
164
44
{
165
44
    unsigned char o[CURVE448_PUB_KEY_SIZE];
166
44
    int ret = 0;
167
44
    int i;
168
169
#ifdef WOLFSSL_CHECK_MEM_ZERO
170
    /* Register the shared-secret buffer up front (no early return bypasses the
171
     * cleanup ForceZero) so every path is checked. XMEMSET makes it defined. */
172
    XMEMSET(o, 0, sizeof(o));
173
    wc_MemZero_Add("wc_curve448_shared_secret_ex o", o, CURVE448_PUB_KEY_SIZE);
174
#endif
175
176
    /* sanity check */
177
44
    if ((private_key == NULL) || (public_key == NULL) || (out == NULL) ||
178
44
                        (outLen == NULL) || (*outLen < CURVE448_PUB_KEY_SIZE)) {
179
0
        ret = BAD_FUNC_ARG;
180
0
    }
181
    /* make sure we have a populated private and public key */
182
44
    if (ret == 0 && (!private_key->privSet || !public_key->pubSet)) {
183
0
        ret = ECC_BAD_ARG_E;
184
0
    }
185
186
44
    if (ret == 0) {
187
44
        ret = curve448(o, private_key->k, public_key->p);
188
44
    }
189
44
#ifndef WOLFSSL_NO_ECDHX_SHARED_ZERO_CHECK
190
44
    if (ret == 0) {
191
44
        byte t = 0;
192
2.50k
        for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
193
2.46k
            t |= o[i];
194
2.46k
        }
195
44
        if (t == 0) {
196
0
            ret = ECC_OUT_OF_RANGE_E;
197
0
        }
198
44
    }
199
44
#endif
200
44
    if (ret == 0) {
201
44
        if (endian == EC448_BIG_ENDIAN) {
202
            /* put shared secret key in Big Endian format */
203
0
            for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
204
0
                 out[i] = o[CURVE448_PUB_KEY_SIZE - i -1];
205
0
            }
206
0
        }
207
44
        else {
208
            /* put shared secret key in Little Endian format */
209
44
            XMEMCPY(out, o, CURVE448_PUB_KEY_SIZE);
210
44
        }
211
212
44
        *outLen = CURVE448_PUB_KEY_SIZE;
213
44
    }
214
215
44
    ForceZero(o, CURVE448_PUB_KEY_SIZE);
216
#ifdef WOLFSSL_CHECK_MEM_ZERO
217
    wc_MemZero_Check(o, CURVE448_PUB_KEY_SIZE);
218
#endif
219
220
44
    return ret;
221
44
}
222
223
#endif /* HAVE_CURVE448_SHARED_SECRET */
224
225
#ifdef HAVE_CURVE448_KEY_EXPORT
226
227
/* Export the curve448 public key.
228
 * Public key encoded big-endian.
229
 *
230
 * key     [in]      Curve448 public key.
231
 * out     [in]      Array to hold public key.
232
 * outLen  [in/out]  On in, the number of bytes in array.
233
 *                   On out, the number bytes put into array.
234
 * returns BAD_FUNC_ARG when a parameter is NULL,
235
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE or
236
 *         neither the public nor the private key has been set,
237
 *         0 otherwise.
238
 */
239
int wc_curve448_export_public(curve448_key* key, byte* out, word32* outLen)
240
1
{
241
1
    return wc_curve448_export_public_ex(key, out, outLen, EC448_BIG_ENDIAN);
242
1
}
243
244
/* Export the curve448 public key.
245
 *
246
 * key     [in]      Curve448 public key.
247
 * out     [in]      Array to hold public key.
248
 * outLen  [in/out]  On in, the number of bytes in array.
249
 *                   On out, the number bytes put into array.
250
 * endian  [in]      Endianness to use when encoding number in array.
251
 * returns BAD_FUNC_ARG when a parameter is NULL,
252
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_PUB_KEY_SIZE or
253
 *         neither the public nor the private key has been set,
254
 *         0 otherwise.
255
 */
256
int wc_curve448_export_public_ex(curve448_key* key, byte* out, word32* outLen,
257
                                 int endian)
258
942
{
259
942
    int ret = 0;
260
261
942
    if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
262
61
        ret = BAD_FUNC_ARG;
263
61
    }
264
265
    /* check and set outgoing key size */
266
942
    if ((ret == 0) && (*outLen < CURVE448_PUB_KEY_SIZE)) {
267
24
        *outLen = CURVE448_PUB_KEY_SIZE;
268
24
        ret = ECC_BAD_ARG_E;
269
24
    }
270
271
    /* no public key to export and no private key to derive it from */
272
942
    if ((ret == 0) && (!key->pubSet) && (!key->privSet)) {
273
0
        ret = ECC_BAD_ARG_E;
274
0
    }
275
942
    if (ret == 0) {
276
        /* calculate public if missing */
277
857
        if (!key->pubSet) {
278
0
            ret = wc_curve448_make_pub((int)sizeof(key->p), key->p,
279
0
                                       (int)sizeof(key->k), key->k);
280
0
            key->pubSet = (ret == 0);
281
0
        }
282
857
    }
283
942
    if (ret == 0) {
284
857
        *outLen = CURVE448_PUB_KEY_SIZE;
285
857
        if (endian == EC448_BIG_ENDIAN) {
286
1
            int i;
287
            /* read keys in Big Endian format */
288
57
            for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
289
56
                out[i] = key->p[CURVE448_PUB_KEY_SIZE - i - 1];
290
56
            }
291
1
        }
292
856
        else {
293
856
            XMEMCPY(out, key->p, CURVE448_PUB_KEY_SIZE);
294
856
        }
295
857
    }
296
297
942
    return ret;
298
942
}
299
300
#endif /* HAVE_CURVE448_KEY_EXPORT */
301
302
#ifdef HAVE_CURVE448_KEY_IMPORT
303
304
/* Import a curve448 public key from a byte array.
305
 * Public key encoded in big-endian.
306
 *
307
 * in      [in]  Array holding public key.
308
 * inLen   [in]  Number of bytes of data in array.
309
 * key     [in]  Curve448 public key.
310
 * returns BAD_FUNC_ARG when a parameter is NULL,
311
 *         ECC_BAD_ARG_E when inLen is less than CURVE448_PUB_KEY_SIZE,
312
 *         0 otherwise.
313
 */
314
int wc_curve448_import_public(const byte* in, word32 inLen, curve448_key* key)
315
23
{
316
23
    return wc_curve448_import_public_ex(in, inLen, key, EC448_BIG_ENDIAN);
317
23
}
318
319
/* Import a curve448 public key from a byte array.
320
 *
321
 * in      [in]  Array holding public key.
322
 * inLen   [in]  Number of bytes of data in array.
323
 * key     [in]  Curve448 public key.
324
 * endian  [in]  Endianness of encoded number in byte array.
325
 * returns BAD_FUNC_ARG when a parameter is NULL,
326
 *         ECC_BAD_ARG_E when inLen is less than CURVE448_PUB_KEY_SIZE,
327
 *         0 otherwise.
328
 */
329
int wc_curve448_import_public_ex(const byte* in, word32 inLen,
330
                                 curve448_key* key, int endian)
331
92
{
332
92
    int ret = 0;
333
334
    /* sanity check */
335
92
    if ((key == NULL) || (in == NULL)) {
336
1
        ret = BAD_FUNC_ARG;
337
1
    }
338
339
    /* check size of incoming keys */
340
92
    if ((ret == 0) && (inLen != CURVE448_PUB_KEY_SIZE)) {
341
22
       ret = ECC_BAD_ARG_E;
342
22
    }
343
344
92
    if (ret == 0) {
345
69
        if (endian == EC448_BIG_ENDIAN) {
346
1
            int i;
347
            /* read keys in Big Endian format */
348
57
            for (i = 0; i < CURVE448_PUB_KEY_SIZE; i++) {
349
56
                key->p[i] = in[CURVE448_PUB_KEY_SIZE - i - 1];
350
56
            }
351
1
        }
352
68
        else
353
68
            XMEMCPY(key->p, in, inLen);
354
69
        key->pubSet = 1;
355
69
    }
356
357
92
    return ret;
358
92
}
359
360
/* Check the public key value (big or little endian)
361
 *
362
 * pub     [in]  Public key bytes.
363
 * pubSz   [in]  Size of public key in bytes.
364
 * endian  [in]  Public key bytes passed in as big-endian or little-endian.
365
 * returns BAD_FUNC_ARGS when pub is NULL,
366
 *         ECC_BAD_ARG_E when key length is not 56 bytes, public key value is
367
 *         zero or one;
368
 *         BUFFER_E when size of public key is zero;
369
 *         0 otherwise.
370
 */
371
int wc_curve448_check_public(const byte* pub, word32 pubSz, int endian)
372
719
{
373
719
    int ret = 0;
374
375
719
    if (pub == NULL) {
376
0
        ret = BAD_FUNC_ARG;
377
0
    }
378
379
    /* Check for empty key data */
380
719
    if ((ret == 0) && (pubSz == 0)) {
381
4
        ret = BUFFER_E;
382
4
    }
383
384
    /* Check key length */
385
719
    if ((ret == 0) && (pubSz != CURVE448_PUB_KEY_SIZE)) {
386
61
        ret = ECC_BAD_ARG_E;
387
61
    }
388
389
719
    if (ret == 0) {
390
654
        word32 i;
391
392
654
        if (endian == EC448_LITTLE_ENDIAN) {
393
            /* Check for value of zero or one */
394
1.02k
            for (i = CURVE448_PUB_KEY_SIZE - 1; i > 0; i--) {
395
1.01k
                if (pub[i] != 0) {
396
149
                    break;
397
149
                }
398
1.01k
            }
399
161
            if ((i == 0) && (pub[0] == 0 || pub[0] == 1)) {
400
6
                return ECC_BAD_ARG_E;
401
6
            }
402
            /* Check for order-1 or higher */
403
2.23k
            for (i = CURVE448_PUB_KEY_SIZE - 1; i > 28; i--) {
404
2.16k
                if (pub[i] != 0xff) {
405
91
                    break;
406
91
                }
407
2.16k
            }
408
155
            if ((i == 28) && (pub[i] == 0xff)) {
409
7
                return ECC_BAD_ARG_E;
410
7
            }
411
148
            if ((i == 28) && (pub[i] == 0xfe)) {
412
407
                for (--i; i > 0; i--) {
413
399
                    if (pub[i] != 0xff) {
414
26
                        break;
415
26
                    }
416
399
                }
417
34
                if ((i == 0) && (pub[i] >= 0xfe)) {
418
2
                    return ECC_BAD_ARG_E;
419
2
                }
420
34
            }
421
148
        }
422
493
        else {
423
            /* Check for value of zero or one */
424
1.20k
            for (i = 0; i < CURVE448_PUB_KEY_SIZE-1; i++) {
425
1.19k
                if (pub[i] != 0) {
426
483
                    break;
427
483
                }
428
1.19k
            }
429
493
            if ((i == CURVE448_PUB_KEY_SIZE - 1) &&
430
10
                (pub[i] == 0 || pub[i] == 1)) {
431
2
                ret = ECC_BAD_ARG_E;
432
2
            }
433
            /* Check for order-1 or higher */
434
1.41k
            for (i = 0; i < 27; i++) {
435
1.38k
                if (pub[i] != 0xff) {
436
468
                    break;
437
468
                }
438
1.38k
            }
439
493
            if ((i == 27) && (pub[i] == 0xff)) {
440
3
                return ECC_BAD_ARG_E;
441
3
            }
442
490
            if ((i == 27) && (pub[i] == 0xfe)) {
443
114
                for (++i; i < CURVE448_PUB_KEY_SIZE - 1; i++) {
444
111
                    if (pub[i] != 0xff) {
445
5
                        break;
446
5
                    }
447
111
                }
448
8
                if ((i == CURVE448_PUB_KEY_SIZE - 1) && (pub[i] >= 0xfe)) {
449
2
                    return ECC_BAD_ARG_E;
450
2
                }
451
8
            }
452
490
        }
453
654
    }
454
455
699
    return ret;
456
719
}
457
458
#endif /* HAVE_CURVE448_KEY_IMPORT */
459
460
461
#ifdef HAVE_CURVE448_KEY_EXPORT
462
463
/* Export the curve448 private key raw form.
464
 * Private key encoded big-endian.
465
 *
466
 * key     [in]      Curve448 private key.
467
 * out     [in]      Array to hold private key.
468
 * outLen  [in/out]  On in, the number of bytes in array.
469
 *                   On out, the number bytes put into array.
470
 * returns BAD_FUNC_ARG when a parameter is NULL,
471
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_KEY_SIZE,
472
 *         0 otherwise.
473
 */
474
int wc_curve448_export_private_raw(curve448_key* key, byte* out, word32* outLen)
475
0
{
476
0
    return wc_curve448_export_private_raw_ex(key, out, outLen,
477
0
                                             EC448_BIG_ENDIAN);
478
0
}
479
480
/* Export the curve448 private key raw form.
481
 *
482
 * key     [in]      Curve448 private key.
483
 * out     [in]      Array to hold private key.
484
 * outLen  [in/out]  On in, the number of bytes in array.
485
 *                   On out, the number bytes put into array.
486
 * endian  [in]      Endianness to use when encoding number in array.
487
 * returns BAD_FUNC_ARG when a parameter is NULL,
488
 *         ECC_BAD_ARG_E when outLen is less than CURVE448_KEY_SIZE,
489
 *         0 otherwise.
490
 */
491
int wc_curve448_export_private_raw_ex(curve448_key* key, byte* out,
492
                                      word32* outLen, int endian)
493
408
{
494
408
    int ret = 0;
495
496
    /* sanity check */
497
408
    if ((key == NULL) || (out == NULL) || (outLen == NULL)) {
498
130
        ret = BAD_FUNC_ARG;
499
130
    }
500
501
408
    if ((ret == 0) && (!key->privSet)) {
502
0
        ret = ECC_BAD_ARG_E;
503
0
    }
504
505
    /* check size of outgoing buffer */
506
408
    if ((ret == 0) && (*outLen < CURVE448_KEY_SIZE)) {
507
24
        *outLen = CURVE448_KEY_SIZE;
508
24
        ret = ECC_BAD_ARG_E;
509
24
    }
510
408
    if (ret == 0) {
511
254
        *outLen = CURVE448_KEY_SIZE;
512
513
254
        if (endian == EC448_BIG_ENDIAN) {
514
0
            int i;
515
            /* put the key in Big Endian format */
516
0
            for (i = 0; i < CURVE448_KEY_SIZE; i++) {
517
0
                out[i] = key->k[CURVE448_KEY_SIZE - i - 1];
518
0
            }
519
0
        }
520
254
        else {
521
254
            XMEMCPY(out, key->k, CURVE448_KEY_SIZE);
522
254
        }
523
254
    }
524
525
408
    return ret;
526
408
}
527
528
/* Export the curve448 private and public keys in raw form.
529
 * Private and public key encoded big-endian.
530
 *
531
 * key     [in]      Curve448 private key.
532
 * priv    [in]      Array to hold private key.
533
 * privSz  [in/out]  On in, the number of bytes in private key array.
534
 *                   On out, the number bytes put into private key array.
535
 * pub     [in]      Array to hold public key.
536
 * pubSz   [in/out]  On in, the number of bytes in public key array.
537
 *                   On out, the number bytes put into public key array.
538
 * returns BAD_FUNC_ARG when a parameter is NULL,
539
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
540
 *         less than CURVE448_PUB_KEY_SIZE,
541
 *         0 otherwise.
542
 */
543
int wc_curve448_export_key_raw(curve448_key* key, byte* priv, word32 *privSz,
544
                               byte* pub, word32 *pubSz)
545
0
{
546
0
    return wc_curve448_export_key_raw_ex(key, priv, privSz, pub, pubSz,
547
0
                                         EC448_BIG_ENDIAN);
548
0
}
549
550
/* Export the curve448 private and public keys in raw form.
551
 *
552
 * key     [in]      Curve448 private key.
553
 * priv    [in]      Array to hold private key.
554
 * privSz  [in/out]  On in, the number of bytes in private key array.
555
 *                   On out, the number bytes put into private key array.
556
 * pub     [in]      Array to hold public key.
557
 * pubSz   [in/out]  On in, the number of bytes in public key array.
558
 *                   On out, the number bytes put into public key array.
559
 * endian  [in]      Endianness to use when encoding number in array.
560
 * returns BAD_FUNC_ARG when a parameter is NULL,
561
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
562
 *         less than CURVE448_PUB_KEY_SIZE,
563
 *         0 otherwise.
564
 */
565
int wc_curve448_export_key_raw_ex(curve448_key* key, byte* priv, word32 *privSz,
566
                                  byte* pub, word32 *pubSz, int endian)
567
0
{
568
0
    int ret;
569
570
    /* export private part */
571
0
    ret = wc_curve448_export_private_raw_ex(key, priv, privSz, endian);
572
0
    if (ret == 0) {
573
        /* export public part */
574
0
        ret = wc_curve448_export_public_ex(key, pub, pubSz, endian);
575
0
    }
576
577
0
    return ret;
578
0
}
579
580
#endif /* HAVE_CURVE448_KEY_EXPORT */
581
582
#ifdef HAVE_CURVE448_KEY_IMPORT
583
584
/* Import curve448 private and public keys from a byte arrays.
585
 * Private and public keys encoded in big-endian.
586
 *
587
 * piv     [in]  Array holding private key.
588
 * privSz  [in]  Number of bytes of data in private key array.
589
 * pub     [in]  Array holding public key.
590
 * pubSz   [in]  Number of bytes of data in public key array.
591
 * key     [in]  Curve448 private/public key.
592
 * returns BAD_FUNC_ARG when a parameter is NULL,
593
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
594
 *         less than CURVE448_PUB_KEY_SIZE,
595
 *         0 otherwise.
596
 */
597
int wc_curve448_import_private_raw(const byte* priv, word32 privSz,
598
                                   const byte* pub, word32 pubSz,
599
                                   curve448_key* key)
600
25
{
601
25
    return wc_curve448_import_private_raw_ex(priv, privSz, pub, pubSz, key,
602
25
                                             EC448_BIG_ENDIAN);
603
25
}
604
605
/* Import curve448 private and public keys from a byte arrays.
606
 *
607
 * piv     [in]  Array holding private key.
608
 * privSz  [in]  Number of bytes of data in private key array.
609
 * pub     [in]  Array holding public key.
610
 * pubSz   [in]  Number of bytes of data in public key array.
611
 * key     [in]  Curve448 private/public key.
612
 * endian  [in]  Endianness of encoded numbers in byte arrays.
613
 * returns BAD_FUNC_ARG when a parameter is NULL,
614
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE or pubSz is
615
 *         less than CURVE448_PUB_KEY_SIZE,
616
 *         0 otherwise.
617
 */
618
int wc_curve448_import_private_raw_ex(const byte* priv, word32 privSz,
619
                                      const byte* pub, word32 pubSz,
620
                                      curve448_key* key, int endian)
621
25
{
622
25
    int ret;
623
624
    /* import private part */
625
25
    ret = wc_curve448_import_private_ex(priv, privSz, key, endian);
626
25
    if (ret == 0) {
627
        /* import public part */
628
1
        return wc_curve448_import_public_ex(pub, pubSz, key, endian);
629
1
    }
630
631
24
    return ret;
632
25
}
633
634
/* Import curve448 private key from a byte array.
635
 * Private key encoded in big-endian.
636
 *
637
 * piv     [in]  Array holding private key.
638
 * privSz  [in]  Number of bytes of data in private key array.
639
 * key     [in]  Curve448 private/public key.
640
 * returns BAD_FUNC_ARG when a parameter is NULL,
641
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE,
642
 *         0 otherwise.
643
 */
644
int wc_curve448_import_private(const byte* priv, word32 privSz,
645
                               curve448_key* key)
646
0
{
647
0
    return wc_curve448_import_private_ex(priv, privSz, key, EC448_BIG_ENDIAN);
648
0
}
649
650
/* Import curve448 private key from a byte array.
651
 *
652
 * piv     [in]  Array holding private key.
653
 * privSz  [in]  Number of bytes of data in private key array.
654
 * key     [in]  Curve448 private/public key.
655
 * endian  [in]  Endianness of encoded number in byte array.
656
 * returns BAD_FUNC_ARG when a parameter is NULL,
657
 *         ECC_BAD_ARG_E when privSz is less than CURVE448_KEY_SIZE,
658
 *         0 otherwise.
659
 */
660
int wc_curve448_import_private_ex(const byte* priv, word32 privSz,
661
                                  curve448_key* key, int endian)
662
25
{
663
25
    int ret = 0;
664
665
    /* sanity check */
666
25
    if ((key == NULL) || (priv == NULL)) {
667
0
        ret = BAD_FUNC_ARG;
668
0
    }
669
670
    /* check size of incoming keys */
671
25
    if ((ret == 0) && ((int)privSz != CURVE448_KEY_SIZE)) {
672
24
        ret = ECC_BAD_ARG_E;
673
24
    }
674
675
25
    if (ret == 0) {
676
1
        if (endian == EC448_BIG_ENDIAN) {
677
1
            int i;
678
            /* read the key in Big Endian format */
679
57
            for (i = 0; i < CURVE448_KEY_SIZE; i++) {
680
56
                key->k[i] = priv[CURVE448_KEY_SIZE - i - 1];
681
56
            }
682
1
        }
683
0
        else {
684
0
            XMEMCPY(key->k, priv, CURVE448_KEY_SIZE);
685
0
        }
686
687
        /* Clamp the key */
688
1
        key->k[0] &= 0xfc;
689
1
        key->k[CURVE448_KEY_SIZE-1] |= 0x80;
690
691
1
        key->privSet = 1;
692
1
    }
693
694
25
    return ret;
695
25
}
696
697
#endif /* HAVE_CURVE448_KEY_IMPORT */
698
699
700
/* Initialize the curve448 key.
701
 *
702
 * key  [in]  Curve448 key object.
703
 * returns BAD_FUNC_ARG when key is NULL,
704
 *         0 otherwise.
705
 */
706
int wc_curve448_init(curve448_key* key)
707
1.40k
{
708
1.40k
    int ret = 0;
709
710
1.40k
    if (key == NULL) {
711
0
       ret = BAD_FUNC_ARG;
712
0
    }
713
714
1.40k
    if (ret == 0) {
715
1.40k
        XMEMSET(key, 0, sizeof(*key));
716
717
1.40k
        fe448_init();
718
719
    #ifdef WOLFSSL_CHECK_MEM_ZERO
720
        wc_MemZero_Add("wc_curve448_init key->k", &key->k, CURVE448_KEY_SIZE);
721
    #endif
722
1.40k
    }
723
724
1.40k
    return ret;
725
1.40k
}
726
727
728
/* Clears the curve448 key data.
729
 *
730
 * key  [in]  Curve448 key object.
731
 */
732
void wc_curve448_free(curve448_key* key)
733
1.46k
{
734
1.46k
    if (key != NULL) {
735
1.40k
        ForceZero(key->k, sizeof(key->k));
736
1.40k
        XMEMSET(key->p, 0, sizeof(key->p));
737
1.40k
        key->pubSet = 0;
738
1.40k
        key->privSet = 0;
739
    #ifdef WOLFSSL_CHECK_MEM_ZERO
740
        wc_MemZero_Check(key, sizeof(curve448_key));
741
    #endif
742
1.40k
    }
743
1.46k
}
744
745
746
/* Get the curve448 key's size.
747
 *
748
 * key  [in]  Curve448 key object.
749
 * returns 0 if key is NULL,
750
 *         CURVE448_KEY_SIZE otherwise.
751
 */
752
int wc_curve448_size(curve448_key* key)
753
0
{
754
0
    int ret = 0;
755
756
0
    if (key != NULL) {
757
0
        ret = CURVE448_KEY_SIZE;
758
0
    }
759
760
0
    return ret;
761
0
}
762
763
#endif /* HAVE_CURVE448 */
764