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/ed25519.c
Line
Count
Source
1
/* ed25519.c
2
 *
3
 * Copyright (C) 2006-2026 wolfSSL Inc.
4
 *
5
 * This file is part of wolfSSL.
6
 *
7
 * wolfSSL is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 3 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * wolfSSL is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20
 */
21
22
23
 /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */
24
25
26
/* Possible Ed25519 enable options:
27
 *   WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN                               Default: OFF
28
 *     Check that the private key didn't change during the signing operations.
29
 */
30
31
#define WC_FIPS_LL_CRYPTO
32
#define _WC_BUILDING_ED25519_C
33
34
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
35
36
#ifdef HAVE_ED25519
37
#if FIPS_VERSION3_GE(6,0,0)
38
       #ifdef USE_WINDOWS_API
39
               #pragma code_seg(".fipsA$f")
40
               #pragma const_seg(".fipsB$f")
41
       #endif
42
#endif
43
44
#include <wolfssl/wolfcrypt/ed25519.h>
45
#include <wolfssl/wolfcrypt/ge_operations.h>
46
#include <wolfssl/wolfcrypt/hash.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
#if FIPS_VERSION3_GE(6,0,0)
55
    const unsigned int wolfCrypt_FIPS_ed25519_ro_sanity[2] =
56
                                                     { 0x1a2b3c4d, 0x00000006 };
57
    int wolfCrypt_FIPS_ED25519_sanity(void)
58
    {
59
        return 0;
60
    }
61
#endif
62
63
#ifdef FREESCALE_LTC_ECC
64
    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
65
#endif
66
#ifdef WOLFSSL_SE050
67
    #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
68
#endif
69
70
#ifdef WOLF_CRYPTO_CB
71
    #include <wolfssl/wolfcrypt/cryptocb.h>
72
#endif
73
74
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_VERIFY)
75
    /* Set a static message string for "Sig No Collisions Message SNC".
76
    ** Note this is a static string per spec, see:
77
    ** https://datatracker.ietf.org/doc/rfc8032/
78
    */
79
    #define ED25519CTX_SNC_MESSAGE "SigEd25519 no Ed25519 collisions"
80
0
    #define ED25519CTX_SIZE 32 /* 32 chars: fixed length of SNC Message. */
81
82
    /* The 32 bytes of ED25519CTX_SIZE is used elsewhere, but we need one
83
    ** more char for saving the line ending in our ed25519Ctx[] here: */
84
    static const byte ed25519Ctx[ED25519CTX_SIZE + 1] = ED25519CTX_SNC_MESSAGE;
85
#endif
86
87
static int WC_ARG_NOT_NULL(1) WC_ARG_NOT_NULL(2)
88
    ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha)
89
5.43k
{
90
5.43k
    int ret;
91
92
5.43k
    ret = wc_InitSha512_ex(sha, key->heap,
93
5.43k
#if defined(WOLF_CRYPTO_CB)
94
5.43k
                           key->devId
95
#else
96
                           INVALID_DEVID
97
#endif
98
5.43k
        );
99
100
5.43k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
101
5.43k
    if (ret == 0) {
102
5.43k
        key->sha_clean_flag = 1;
103
5.43k
    }
104
5.43k
#endif
105
106
5.43k
    return ret;
107
5.43k
}
108
109
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
110
static int WC_ARG_NOT_NULL(1) ed25519_hash_reset(ed25519_key* key)
111
6.24k
{
112
6.24k
    int ret;
113
114
6.24k
    if (key->sha_clean_flag) {
115
6.24k
        ret = 0;
116
6.24k
    }
117
0
    else {
118
0
        wc_Sha512Free(&key->sha);
119
0
        ret = wc_InitSha512_ex(&key->sha, key->heap,
120
0
#if defined(WOLF_CRYPTO_CB)
121
0
                               key->devId
122
#else
123
                               INVALID_DEVID
124
#endif
125
0
            );
126
0
        if (ret == 0)
127
0
            key->sha_clean_flag = 1;
128
0
    }
129
130
6.24k
    return ret;
131
6.24k
}
132
#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
133
134
static int WC_ARG_NOT_NULL(1)
135
    ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha,
136
                        const byte* data, word32 len)
137
87.6k
{
138
87.6k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
139
87.6k
    if (key->sha_clean_flag) {
140
8.56k
        key->sha_clean_flag = 0;
141
8.56k
    }
142
#else
143
    (void)key;
144
#endif
145
87.6k
    return wc_Sha512Update(sha, data, len);
146
87.6k
}
147
148
static int WC_ARG_NOT_NULL(1)
149
    ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash)
150
8.36k
{
151
8.36k
    int ret = wc_Sha512Final(sha, hash);
152
8.36k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
153
8.36k
    if (ret == 0) {
154
7.89k
        key->sha_clean_flag = 1;
155
7.89k
    }
156
#else
157
    (void)key;
158
#endif
159
8.36k
    return ret;
160
8.36k
}
161
162
static void WC_ARG_NOT_NULL(1)
163
    ed25519_hash_free(ed25519_key* key, wc_Sha512 *sha)
164
5.43k
{
165
5.43k
    wc_Sha512Free(sha);
166
5.43k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
167
5.43k
    key->sha_clean_flag = 0;
168
#else
169
    (void)key;
170
#endif
171
5.43k
}
172
173
174
static int ed25519_hash(ed25519_key* key, const byte* in, word32 inLen,
175
    byte* hash)
176
4.65k
{
177
4.65k
    int ret;
178
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
179
    WC_DECLARE_VAR(sha, wc_Sha512, 1, key ? key->heap : NULL);
180
#else
181
4.65k
    wc_Sha512 *sha;
182
4.65k
#endif
183
184
4.65k
    if (key == NULL || (in == NULL && inLen > 0) || hash == NULL) {
185
0
        return BAD_FUNC_ARG;
186
0
    }
187
188
4.65k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
189
4.65k
    sha = &key->sha;
190
4.65k
    ret = ed25519_hash_reset(key);
191
#else
192
    WC_ALLOC_VAR_EX(sha, wc_Sha512, 1, key->heap, DYNAMIC_TYPE_HASHES,
193
                    return MEMORY_E);
194
    ret = ed25519_hash_init(key, sha);
195
#endif
196
4.65k
    if (ret == 0) {
197
4.65k
        ret = ed25519_hash_update(key, sha, in, inLen);
198
4.65k
        if (ret == 0)
199
4.65k
            ret = ed25519_hash_final(key, sha, hash);
200
201
    #ifndef WOLFSSL_ED25519_PERSISTENT_SHA
202
        ed25519_hash_free(key, sha);
203
    #endif
204
4.65k
    }
205
206
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
207
    WC_FREE_VAR_EX(sha, key->heap, DYNAMIC_TYPE_HASHES);
208
#endif
209
4.65k
    return ret;
210
4.65k
}
211
212
#ifndef WOLF_CRYPTO_CB_ONLY_ED25519
213
/* Reject small-order Ed25519 public keys: h*A vanishes during verification
214
 * so any (R = [S]B, S) verifies for an arbitrary message. */
215
static int ed25519_is_small_order(const byte p[ED25519_PUB_KEY_SIZE])
216
3.93k
{
217
    /* y-coordinates of every order-1/2/4/8 point plus the two non-canonical
218
     * encodings y = p / y = p+1. Sign bit masked before compare. Only
219
     * {y, y + p} fits in 32 bytes (2p overflows the 255-bit y field), so
220
     * listing y and y + p exhausts the reachable encodings for each
221
     * small-order y. */
222
3.93k
    static const byte small_order_y[][ED25519_PUB_KEY_SIZE] = {
223
        /* order 4: y = 0 */
224
3.93k
        {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
225
3.93k
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
226
3.93k
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
227
3.93k
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
228
        /* order 1: y = 1 (identity) */
229
3.93k
        {0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
230
3.93k
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
231
3.93k
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
232
3.93k
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
233
        /* order 8 */
234
3.93k
        {0x26,0xe8,0x95,0x8f,0xc2,0xb2,0x27,0xb0,
235
3.93k
         0x45,0xc3,0xf4,0x89,0xf2,0xef,0x98,0xf0,
236
3.93k
         0xd5,0xdf,0xac,0x05,0xd3,0xc6,0x33,0x39,
237
3.93k
         0xb1,0x38,0x02,0x88,0x6d,0x53,0xfc,0x05},
238
        /* order 8 */
239
3.93k
        {0xc7,0x17,0x6a,0x70,0x3d,0x4d,0xd8,0x4f,
240
3.93k
         0xba,0x3c,0x0b,0x76,0x0d,0x10,0x67,0x0f,
241
3.93k
         0x2a,0x20,0x53,0xfa,0x2c,0x39,0xcc,0xc6,
242
3.93k
         0x4e,0xc7,0xfd,0x77,0x92,0xac,0x03,0x7a},
243
        /* order 2: y = p - 1 */
244
3.93k
        {0xec,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
245
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
246
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
247
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f},
248
        /* non-canonical y = p (decodes to y = 0) */
249
3.93k
        {0xed,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
250
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
251
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
252
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f},
253
        /* non-canonical y = p + 1 (decodes to y = 1) */
254
3.93k
        {0xee,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
255
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
256
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
257
3.93k
         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f},
258
3.93k
    };
259
3.93k
    byte y[ED25519_PUB_KEY_SIZE];
260
3.93k
    word32 i;
261
262
3.93k
    XMEMCPY(y, p, ED25519_PUB_KEY_SIZE);
263
3.93k
    y[ED25519_PUB_KEY_SIZE - 1] &= 0x7f;
264
31.1k
    for (i = 0; i < sizeof(small_order_y) / ED25519_PUB_KEY_SIZE; i++) {
265
27.2k
        if (XMEMCMP(y, small_order_y[i], ED25519_PUB_KEY_SIZE) == 0)
266
53
            return 1;
267
27.2k
    }
268
3.88k
    return 0;
269
3.93k
}
270
#endif /* !WOLF_CRYPTO_CB_ONLY_ED25519 */
271
272
#ifdef HAVE_ED25519_MAKE_KEY
273
#if FIPS_VERSION3_GE(6,0,0)
274
/* Performs a Pairwise Consistency Test on an Ed25519 key pair.
275
 *
276
 * @param [in] key  Ed25519 key to test.
277
 * @param [in] rng  Random number generator to use to create random digest.
278
 * @return  0 on success.
279
 * @return  ECC_PCT_E when signing or verification fail.
280
 * @return  Other -ve when random number generation fails.
281
 */
282
static int ed25519_pairwise_consistency_test(ed25519_key* key, WC_RNG* rng)
283
{
284
    int err = 0;
285
    byte digest[WC_SHA512_DIGEST_SIZE];
286
    word32 digestLen = WC_SHA512_DIGEST_SIZE;
287
    byte sig[ED25519_SIG_SIZE];
288
    word32 sigLen = ED25519_SIG_SIZE;
289
    int res = 0;
290
291
    /* Generate a random digest to sign. */
292
    err = wc_RNG_GenerateBlock(rng, digest, digestLen);
293
    if (err == 0) {
294
        /* Sign digest without context. */
295
        err = wc_ed25519_sign_msg_ex(digest, digestLen, sig, &sigLen, key,
296
            (byte)Ed25519, NULL, 0);
297
        if (err != 0) {
298
            /* Any sign failure means test failed. */
299
            err = ECC_PCT_E;
300
        }
301
    }
302
    if (err == 0) {
303
        /* Verify digest without context. */
304
        err = wc_ed25519_verify_msg_ex(sig, sigLen, digest, digestLen, &res,
305
            key, (byte)Ed25519, NULL, 0);
306
        if (err != 0) {
307
            /* Any verification operation failure means test failed. */
308
            err = ECC_PCT_E;
309
        }
310
        /* Check whether the signature verified. */
311
        else if (res == 0) {
312
            /* Test failed. */
313
            err = ECC_PCT_E;
314
        }
315
    }
316
317
    ForceZero(sig, sigLen);
318
319
    return err;
320
}
321
#endif
322
323
int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey,
324
                           word32 pubKeySz)
325
3.49k
{
326
3.49k
    int   ret = 0;
327
3.49k
#ifndef WOLF_CRYPTO_CB_ONLY_ED25519
328
3.49k
    ALIGN16 byte az[ED25519_PRV_KEY_SIZE];
329
3.49k
#if !defined(FREESCALE_LTC_ECC)
330
3.49k
    ge_p3 A;
331
3.49k
#endif
332
3.49k
#endif /* !WOLF_CRYPTO_CB_ONLY_ED25519 */
333
334
3.49k
    if (key == NULL || pubKey == NULL || pubKeySz != ED25519_PUB_KEY_SIZE)
335
0
        ret = BAD_FUNC_ARG;
336
337
3.49k
    if ((ret == 0) && (!key->privKeySet)) {
338
65
        ret = ECC_PRIV_KEY_E;
339
65
    }
340
341
3.49k
#ifdef WOLF_CRYPTO_CB
342
    /* Device-first: offload the public-key derivation. Fall through to the
343
     * software path below only when the device reports the operation
344
     * unavailable. */
345
3.49k
    #ifndef WOLF_CRYPTO_CB_FIND
346
3.49k
    if ((ret == 0) && (key->devId != INVALID_DEVID))
347
    #else
348
    if (ret == 0)
349
    #endif
350
0
    {
351
0
        ret = wc_CryptoCb_Ed25519MakePub(key, pubKey, pubKeySz);
352
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
353
0
            if (ret == 0)
354
0
                key->pubKeySet = 1;
355
0
            return ret;
356
0
        }
357
0
        ret = 0; /* device declined the offload; fall back */
358
0
    }
359
3.49k
#endif
360
361
#ifdef WOLF_CRYPTO_CB_ONLY_ED25519
362
    /* software derivation is stripped and no device handled the op;
363
     * fail closed */
364
    if (ret == 0)
365
        ret = NO_VALID_DEVID;
366
#else
367
3.49k
    if (ret == 0)
368
3.42k
        ret = ed25519_hash(key, key->k, ED25519_KEY_SIZE, az);
369
3.49k
    if (ret == 0) {
370
        /* apply clamp */
371
3.15k
        az[0]  &= 248;
372
3.15k
        az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
373
3.15k
        az[31] |= 64;
374
375
    #ifdef FREESCALE_LTC_ECC
376
        ltc_pkha_ecc_point_t publicKey = {0};
377
        publicKey.X = key->pointX;
378
        publicKey.Y = key->pointY;
379
        LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), az,
380
            ED25519_KEY_SIZE, &publicKey, kLTC_Ed25519 /* result on Ed25519 */);
381
        LTC_PKHA_Ed25519_Compress(&publicKey, pubKey);
382
    #else
383
3.15k
        ge_scalarmult_base(&A, az);
384
3.15k
        ge_p3_tobytes(pubKey, &A);
385
3.15k
    #endif
386
387
3.15k
        key->pubKeySet = 1;
388
3.15k
    }
389
3.49k
#endif /* WOLF_CRYPTO_CB_ONLY_ED25519 */
390
391
3.49k
    return ret;
392
3.49k
}
393
394
/* generate an ed25519 key pair.
395
 * returns 0 on success
396
 */
397
int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
398
553
{
399
553
    int ret;
400
401
553
    if (rng == NULL || key == NULL)
402
0
        return BAD_FUNC_ARG;
403
404
    /* ed25519 has 32 byte key sizes */
405
553
    if (keySz != ED25519_KEY_SIZE)
406
0
        return BAD_FUNC_ARG;
407
408
553
    key->privKeySet = 0;
409
553
    key->pubKeySet = 0;
410
411
553
#ifdef WOLF_CRYPTO_CB
412
553
    #ifndef WOLF_CRYPTO_CB_FIND
413
553
    if (key->devId != INVALID_DEVID)
414
0
    #endif
415
0
    {
416
0
        ret = wc_CryptoCb_Ed25519Gen(rng, keySz, key);
417
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
418
0
            return ret;
419
        /* fall-through when unavailable */
420
0
    }
421
553
#endif
422
423
#ifdef WOLF_CRYPTO_CB_ONLY_ED25519
424
    return NO_VALID_DEVID;
425
#else
426
553
    ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE);
427
553
    if (ret != 0)
428
106
        return ret;
429
430
447
    key->privKeySet = 1;
431
447
    ret = wc_ed25519_make_public(key, key->p, ED25519_PUB_KEY_SIZE);
432
447
    if (ret != 0) {
433
33
        key->privKeySet = 0;
434
33
        ForceZero(key->k, ED25519_KEY_SIZE);
435
33
        return ret;
436
33
    }
437
438
    /* put public key after private key, on the same buffer */
439
414
    XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
440
441
#if FIPS_VERSION3_GE(6,0,0)
442
    ret = wc_ed25519_check_key(key);
443
    if (ret == 0) {
444
        ret = ed25519_pairwise_consistency_test(key, rng);
445
    }
446
#endif
447
448
414
    return ret;
449
447
#endif /* WOLF_CRYPTO_CB_ONLY_ED25519 */
450
447
}
451
#endif /* HAVE_ED25519_MAKE_KEY */
452
453
454
#ifdef HAVE_ED25519_SIGN
455
/*
456
    in          contains the message to sign
457
    inLen       is the length of the message to sign
458
    out         is the buffer to write the signature
459
    outLen      [in/out] input size of out buf
460
                          output gets set as the final length of out
461
    key         is the ed25519 key to use when signing
462
    type        one of Ed25519, Ed25519ctx or Ed25519ph
463
    context     extra signing data
464
    contextLen  length of extra signing data
465
    return 0 on success
466
 */
467
int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
468
                            word32 *outLen, ed25519_key* key, byte type,
469
                            const byte* context, byte contextLen)
470
1.26k
{
471
1.26k
    int    ret;
472
#if defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_ONLY_KEY_ID)
473
    (void)context;
474
    (void)contextLen;
475
    (void)type;
476
    ret = se050_ed25519_sign_msg(in, inLen, out, outLen, key);
477
#elif defined(WOLF_CRYPTO_CB_ONLY_ED25519)
478
    (void)ed25519Ctx;
479
    ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
480
481
    if (in == NULL || out == NULL || outLen == NULL || key == NULL ||
482
                                         (context == NULL && contextLen != 0)) {
483
        return BAD_FUNC_ARG;
484
    }
485
486
    if ((type == Ed25519ph) &&
487
        (inLen != WC_SHA512_DIGEST_SIZE))
488
    {
489
        return BAD_LENGTH_E;
490
    }
491
492
    #ifndef WOLF_CRYPTO_CB_FIND
493
    if (key->devId != INVALID_DEVID)
494
    #endif
495
    {
496
        ret = wc_CryptoCb_Ed25519Sign(in, inLen, out, outLen, key, type,
497
            context, contextLen);
498
    }
499
    if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
500
        ret = NO_VALID_DEVID;
501
    }
502
#else
503
#ifdef FREESCALE_LTC_ECC
504
    ALIGN16 byte tempBuf[ED25519_PRV_KEY_SIZE];
505
    ltc_pkha_ecc_point_t ltcPoint = {0};
506
#else
507
1.26k
    ge_p3  R;
508
1.26k
#endif
509
1.26k
    ALIGN16 byte nonce[WC_SHA512_DIGEST_SIZE];
510
1.26k
    ALIGN16 byte hram[WC_SHA512_DIGEST_SIZE];
511
1.26k
    ALIGN16 byte az[ED25519_PRV_KEY_SIZE];
512
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
513
    byte orig_k[ED25519_KEY_SIZE];
514
#endif
515
516
    /* sanity check on arguments */
517
1.26k
    if (in == NULL || out == NULL || outLen == NULL || key == NULL ||
518
1.22k
                                         (context == NULL && contextLen != 0)) {
519
44
        return BAD_FUNC_ARG;
520
44
    }
521
522
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_ONLY_KEY_ID)
523
    /* Key resident in the SE050: sign in hardware. Software keys fall through
524
     * to the wolfCrypt software implementation below. */
525
    if (key->keyIdSet) {
526
        /* The SE050 performs only PureEdDSA; it cannot apply the Ed25519ctx or
527
         * Ed25519ph variants, so reject them rather than silently signing with
528
         * the wrong scheme. */
529
        if (type == Ed25519ctx || type == Ed25519ph || contextLen != 0) {
530
            return BAD_FUNC_ARG;
531
        }
532
        return se050_ed25519_sign_msg(in, inLen, out, outLen, key);
533
    }
534
#endif
535
536
1.22k
    if ((type == Ed25519ph) &&
537
0
        (inLen != WC_SHA512_DIGEST_SIZE))
538
0
    {
539
0
        return BAD_LENGTH_E;
540
0
    }
541
542
1.22k
#ifdef WOLF_CRYPTO_CB
543
1.22k
    #ifndef WOLF_CRYPTO_CB_FIND
544
1.22k
    if (key->devId != INVALID_DEVID)
545
0
    #endif
546
0
    {
547
0
        ret = wc_CryptoCb_Ed25519Sign(in, inLen, out, outLen, key, type,
548
0
            context, contextLen);
549
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
550
0
            return ret;
551
        /* fall-through when unavailable */
552
0
    }
553
1.22k
#endif
554
555
1.22k
    if (!key->pubKeySet)
556
0
        return BAD_FUNC_ARG;
557
1.22k
    if (!key->privKeySet)
558
0
        return BAD_FUNC_ARG;
559
560
    /* check and set up out length */
561
1.22k
    if (*outLen < ED25519_SIG_SIZE) {
562
0
        *outLen = ED25519_SIG_SIZE;
563
0
        return BUFFER_E;
564
0
    }
565
1.22k
    *outLen = ED25519_SIG_SIZE;
566
567
#ifdef WOLFSSL_CHECK_MEM_ZERO
568
    /* Register the secret nonce/expanded-key buffers up front so that any exit
569
     * path from here to the ForceZero below is checked for proper zeroization.
570
     * XMEMSET gives them a defined value before the hash steps fill them. */
571
    XMEMSET(az, 0, sizeof(az));
572
    XMEMSET(nonce, 0, sizeof(nonce));
573
    wc_MemZero_Add("wc_ed25519_sign_msg_ex az", az, sizeof(az));
574
    wc_MemZero_Add("wc_ed25519_sign_msg_ex nonce", nonce, sizeof(nonce));
575
#endif
576
577
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
578
    XMEMCPY(orig_k, key->k, ED25519_KEY_SIZE);
579
#ifdef WOLFSSL_CHECK_MEM_ZERO
580
    wc_MemZero_Add("wc_ed25519_sign_msg_ex orig_k", orig_k, sizeof(orig_k));
581
#endif
582
#endif
583
584
    /* step 1: create nonce to use where nonce is r in
585
       r = H(h_b, ... ,h_2b-1,M) */
586
1.22k
    ret = ed25519_hash(key, key->k, ED25519_KEY_SIZE, az);
587
588
1.22k
    if (ret == 0) {
589
1.19k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
590
1.19k
        wc_Sha512 *sha = &key->sha;
591
#else
592
        WC_DECLARE_VAR(sha, wc_Sha512, 1, key->heap);
593
        WC_ALLOC_VAR_EX(sha, wc_Sha512, 1, key->heap, DYNAMIC_TYPE_HASHES,
594
                        ret = MEMORY_E);
595
        if (ret == 0)
596
            ret = ed25519_hash_init(key, sha);
597
#endif
598
599
        /* apply clamp */
600
1.19k
        az[0]  &= 248;
601
1.19k
        az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
602
1.19k
        az[31] |= 64;
603
604
1.19k
        if (ret == 0 && (type == Ed25519ctx || type == Ed25519ph)) {
605
0
            ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
606
0
            if (ret == 0)
607
0
                ret = ed25519_hash_update(key, sha, &type, sizeof(type));
608
0
            if (ret == 0)
609
0
                ret = ed25519_hash_update(key, sha, &contextLen,
610
0
                                          sizeof(contextLen));
611
0
            if (ret == 0 && context != NULL)
612
0
                ret = ed25519_hash_update(key, sha, context, contextLen);
613
0
        }
614
1.19k
        if (ret == 0)
615
1.19k
            ret = ed25519_hash_update(key, sha, az + ED25519_KEY_SIZE,
616
1.19k
                                      ED25519_KEY_SIZE);
617
1.19k
        if (ret == 0)
618
1.19k
            ret = ed25519_hash_update(key, sha, in, inLen);
619
1.19k
        if (ret == 0)
620
1.15k
            ret = ed25519_hash_final(key, sha, nonce);
621
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
622
        ed25519_hash_free(key, sha);
623
        WC_FREE_VAR_EX(sha, key->heap, DYNAMIC_TYPE_HASHES);
624
#endif
625
1.19k
    }
626
627
1.22k
    if (ret == 0) {
628
#ifdef FREESCALE_LTC_ECC
629
        ltcPoint.X = &tempBuf[0];
630
        ltcPoint.Y = &tempBuf[32];
631
        LTC_PKHA_sc_reduce(nonce);
632
        LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce,
633
               ED25519_KEY_SIZE, &ltcPoint,
634
               kLTC_Ed25519 /* result on Ed25519 */);
635
        LTC_PKHA_Ed25519_Compress(&ltcPoint, out);
636
#else
637
1.13k
        sc_reduce(nonce);
638
639
        /* step 2: computing R = rB where rB is the scalar multiplication of
640
           r and B */
641
1.13k
        ge_scalarmult_base(&R,nonce);
642
1.13k
        ge_p3_tobytes(out,&R);
643
1.13k
#endif
644
1.13k
    }
645
646
    /* step 3: hash R + public key + message getting H(R,A,M) then
647
       creating S = (r + H(R,A,M)a) mod l */
648
1.22k
    if (ret == 0) {
649
1.13k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
650
1.13k
        wc_Sha512 *sha = &key->sha;
651
#else
652
        WC_DECLARE_VAR(sha, wc_Sha512, 1, key->heap);
653
        WC_ALLOC_VAR_EX(sha, wc_Sha512, 1, key->heap, DYNAMIC_TYPE_HASHES,
654
                        ret = MEMORY_E);
655
        if (ret == 0)
656
            ret = ed25519_hash_init(key, sha);
657
#endif
658
659
1.13k
        if (ret == 0 && (type == Ed25519ctx || type == Ed25519ph)) {
660
0
            ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
661
0
            if (ret == 0)
662
0
                ret = ed25519_hash_update(key, sha, &type, sizeof(type));
663
0
            if (ret == 0)
664
0
                ret = ed25519_hash_update(key, sha, &contextLen,
665
0
                                          sizeof(contextLen));
666
0
            if (ret == 0 && context != NULL)
667
0
                ret = ed25519_hash_update(key, sha, context, contextLen);
668
0
        }
669
1.13k
        if (ret == 0)
670
1.13k
            ret = ed25519_hash_update(key, sha, out, ED25519_SIG_SIZE/2);
671
1.13k
        if (ret == 0)
672
1.13k
            ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);
673
1.13k
        if (ret == 0)
674
1.13k
            ret = ed25519_hash_update(key, sha, in, inLen);
675
1.13k
        if (ret == 0)
676
1.11k
            ret = ed25519_hash_final(key, sha, hram);
677
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
678
        ed25519_hash_free(key, sha);
679
        WC_FREE_VAR_EX(sha, key->heap, DYNAMIC_TYPE_HASHES);
680
#endif
681
1.13k
    }
682
683
1.22k
    if (ret == 0) {
684
#ifdef FREESCALE_LTC_ECC
685
        LTC_PKHA_sc_reduce(hram);
686
        LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
687
#else
688
1.07k
        sc_reduce(hram);
689
1.07k
        sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
690
1.07k
#endif
691
1.07k
    }
692
693
1.22k
    ForceZero(az, sizeof(az));
694
1.22k
    ForceZero(nonce, sizeof(nonce));
695
#ifdef WOLFSSL_CHECK_MEM_ZERO
696
    wc_MemZero_Check(nonce, sizeof(nonce));
697
    wc_MemZero_Check(az, sizeof(az));
698
#endif
699
700
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
701
    /* belongs to the software path: orig_k snapshots the key the software
702
     * math read, so there is nothing to compare when a device signs */
703
    if (ret == 0) {
704
        int  i;
705
        byte c = 0;
706
        for (i = 0; i < ED25519_KEY_SIZE; i++) {
707
            c |= key->k[i] ^ orig_k[i];
708
        }
709
        ret = ctMaskGT(c, 0) & SIG_VERIFY_E;
710
    }
711
    ForceZero(orig_k, sizeof(orig_k));
712
#ifdef WOLFSSL_CHECK_MEM_ZERO
713
    wc_MemZero_Check(orig_k, sizeof(orig_k));
714
#endif
715
#endif
716
1.22k
#endif /* WOLFSSL_SE050 */
717
718
1.22k
    return ret;
719
1.22k
}
720
721
/*
722
    in     contains the message to sign
723
    inLen  is the length of the message to sign
724
    out    is the buffer to write the signature
725
    outLen [in/out] input size of out buf
726
                     output gets set as the final length of out
727
    key    is the ed25519 key to use when signing
728
    return 0 on success
729
 */
730
int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out,
731
                        word32 *outLen, ed25519_key* key)
732
1.26k
{
733
1.26k
    return wc_ed25519_sign_msg_ex(in, inLen, out, outLen, key, (byte)Ed25519,
734
1.26k
        NULL, 0);
735
1.26k
}
736
737
/*
738
    in          contains the message to sign
739
    inLen       is the length of the message to sign
740
    out         is the buffer to write the signature
741
    outLen      [in/out] input size of out buf
742
                          output gets set as the final length of out
743
    key         is the ed25519 key to use when signing
744
    context     extra signing data
745
    contextLen  length of extra signing data
746
    return 0 on success
747
 */
748
int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out,
749
                           word32 *outLen, ed25519_key* key,
750
                           const byte* context, byte contextLen)
751
0
{
752
0
    return wc_ed25519_sign_msg_ex(in, inLen, out, outLen, key, Ed25519ctx,
753
0
                                                           context, contextLen);
754
0
}
755
756
/*
757
    hash        contains the SHA-512 hash of the message to sign
758
    hashLen     is the length of the SHA-512 hash of the message to sign
759
    out         is the buffer to write the signature
760
    outLen      [in/out] input size of out buf
761
                          output gets set as the final length of out
762
    key         is the ed25519 key to use when signing
763
    context     extra signing data
764
    contextLen  length of extra signing data
765
    return 0 on success
766
 */
767
int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out,
768
                           word32 *outLen, ed25519_key* key,
769
                           const byte* context, byte contextLen)
770
0
{
771
0
    return wc_ed25519_sign_msg_ex(hash, hashLen, out, outLen, key, Ed25519ph,
772
0
                                                           context, contextLen);
773
0
}
774
775
/*
776
    in          contains the message to sign
777
    inLen       is the length of the message to sign
778
    out         is the buffer to write the signature
779
    outLen      [in/out] input size of out buf
780
                          output gets set as the final length of out
781
    key         is the ed25519 key to use when signing
782
    context     extra signing data
783
    contextLen  length of extra signing data
784
    return 0 on success
785
 */
786
int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
787
                          word32 *outLen, ed25519_key* key,
788
                          const byte* context, byte contextLen)
789
0
{
790
0
    int  ret;
791
0
    byte hash[WC_SHA512_DIGEST_SIZE];
792
793
0
    ret = ed25519_hash(key, in, inLen, hash);
794
0
    if (ret != 0)
795
0
        return ret;
796
797
0
    return wc_ed25519_sign_msg_ex(hash, sizeof(hash), out, outLen, key,
798
0
                                                Ed25519ph, context, contextLen);
799
0
}
800
#endif /* HAVE_ED25519_SIGN */
801
802
#ifdef HAVE_ED25519_VERIFY
803
/* The software verify helpers are also needed under WOLFSSL_SE050_ONLY_KEY_ID
804
 * so that software keys (keyIdSet == 0) can be verified in wolfCrypt. */
805
#if (!defined(WOLFSSL_SE050) || defined(WOLFSSL_SE050_ONLY_KEY_ID)) && \
806
    !defined(WOLF_CRYPTO_CB_ONLY_ED25519)
807
808
#ifdef WOLFSSL_CHECK_VER_FAULTS
809
static const byte sha512_empty[] = {
810
    0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
811
    0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
812
    0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
813
    0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
814
    0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
815
    0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
816
    0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
817
    0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
818
};
819
820
/* sanity check that hash operation happened
821
 * returns 0 on success */
822
static int ed25519_hash_check(ed25519_key* key, byte* h)
823
{
824
    (void)key; /* passing in key in case other hash algroithms are used */
825
826
    if (XMEMCMP(h, sha512_empty, WC_SHA512_DIGEST_SIZE) != 0) {
827
        return 0;
828
    }
829
    else {
830
        return BAD_STATE_E;
831
    }
832
}
833
#endif
834
835
836
/*
837
   sig        is array of bytes containing the signature
838
   sigLen     is the length of sig byte array
839
   key        Ed25519 public key
840
   return     0 on success
841
   type       variant to use -- Ed25519, Ed25519ctx, or Ed25519ph
842
   context    extra signing data
843
   contextLen length of extra signing data
844
*/
845
static int ed25519_verify_msg_init_with_sha(const byte* sig, word32 sigLen,
846
                                            ed25519_key* key, wc_Sha512 *sha,
847
                                            byte type, const byte* context,
848
                                            byte contextLen)
849
1.72k
{
850
1.72k
    int ret;
851
852
    /* sanity check on arguments */
853
1.72k
    if (sig == NULL || key == NULL ||
854
1.72k
        (context == NULL && contextLen != 0)) {
855
0
        return BAD_FUNC_ARG;
856
0
    }
857
858
    /* check on basics needed to verify signature */
859
1.72k
    if (sigLen != ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224))
860
129
        return BAD_FUNC_ARG;
861
862
    /* find H(R,A,M) and store it as h */
863
864
1.59k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
865
1.59k
    ret = ed25519_hash_reset(key);
866
1.59k
    if (ret != 0)
867
0
        return ret;
868
#else
869
    ret = 0;
870
#endif
871
872
1.59k
    if (type == Ed25519ctx || type == Ed25519ph) {
873
0
        ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
874
0
        if (ret == 0)
875
0
            ret = ed25519_hash_update(key, sha, &type, sizeof(type));
876
0
        if (ret == 0)
877
0
            ret = ed25519_hash_update(key, sha, &contextLen, sizeof(contextLen));
878
0
        if (ret == 0 && context != NULL)
879
0
            ret = ed25519_hash_update(key, sha, context, contextLen);
880
0
    }
881
1.59k
    if (ret == 0)
882
1.59k
        ret = ed25519_hash_update(key, sha, sig, ED25519_SIG_SIZE/2);
883
884
#ifdef WOLFSSL_CHECK_VER_FAULTS
885
    /* sanity check that hash operation happened */
886
    if (ret == 0) {
887
        byte h[WC_MAX_DIGEST_SIZE];
888
889
        ret = wc_Sha512GetHash(sha, h);
890
        if (ret == 0) {
891
            ret = ed25519_hash_check(key, h);
892
            if (ret != 0) {
893
                WOLFSSL_MSG("Unexpected initial state of hash found");
894
            }
895
        }
896
    }
897
#endif
898
899
1.59k
    if (ret == 0)
900
1.59k
        ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);
901
902
1.59k
    return ret;
903
1.59k
}
904
905
/*
906
   msgSegment     an array of bytes containing a message segment
907
   msgSegmentLen  length of msgSegment
908
   key            Ed25519 public key
909
   return         0 on success
910
*/
911
static int ed25519_verify_msg_update_with_sha(const byte* msgSegment,
912
                                              word32 msgSegmentLen,
913
                                              ed25519_key* key,
914
74.0k
                                              wc_Sha512 *sha) {
915
    /* sanity check on arguments */
916
74.0k
    if (msgSegment == NULL || key == NULL)
917
0
        return BAD_FUNC_ARG;
918
919
74.0k
    return ed25519_hash_update(key, sha, msgSegment, msgSegmentLen);
920
74.0k
}
921
922
/* ed25519 order in little endian. */
923
static const byte ed25519_order[] = {
924
    0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
925
    0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
926
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
927
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
928
};
929
930
/*
931
   sig     is array of bytes containing the signature
932
   sigLen  is the length of sig byte array
933
   res     will be 1 on successful verify and 0 on unsuccessful
934
   key     Ed25519 public key
935
   return  0 and res of 1 on success
936
*/
937
static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen,
938
                                             int* res, ed25519_key* key,
939
                                             wc_Sha512 *sha)
940
1.50k
{
941
1.50k
    ALIGN16 byte rcheck[ED25519_KEY_SIZE];
942
1.50k
    ALIGN16 byte h[WC_SHA512_DIGEST_SIZE];
943
1.50k
#ifndef FREESCALE_LTC_ECC
944
1.50k
    ge_p3  A;
945
1.50k
    ge_p2  R;
946
1.50k
#endif
947
1.50k
    int    ret;
948
1.50k
    int    i;
949
950
    /* sanity check on arguments */
951
1.50k
    if (sig == NULL || res == NULL || key == NULL)
952
0
        return BAD_FUNC_ARG;
953
954
    /* set verification failed by default */
955
1.50k
    *res = 0;
956
957
    /* check on basics needed to verify signature */
958
1.50k
    if (sigLen != ED25519_SIG_SIZE)
959
0
        return BAD_FUNC_ARG;
960
    /* S is not larger or equal to the order:
961
     *     2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed
962
     *   = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
963
     */
964
965
    /* Check S is not larger than or equal to order. */
966
1.71k
    for (i = (int)sizeof(ed25519_order) - 1; i >= 0; i--) {
967
        /* Bigger than order. */
968
1.71k
        if (sig[ED25519_SIG_SIZE/2 + i] > ed25519_order[i])
969
68
            return BAD_FUNC_ARG;
970
        /* Less than order. */
971
1.64k
        if (sig[ED25519_SIG_SIZE/2 + i] < ed25519_order[i])
972
1.44k
            break;
973
1.64k
    }
974
    /* Check equal - all bytes match. */
975
1.44k
    if (i == -1)
976
0
        return BAD_FUNC_ARG;
977
978
    /* Defence in depth: also catch small-order keys imported with trusted=1. */
979
1.44k
    if (ed25519_is_small_order(key->p)) {
980
0
        WOLFSSL_MSG("Ed25519 small-order public key rejected during "
981
0
                    "signature verification");
982
0
        return BAD_FUNC_ARG;
983
0
    }
984
985
    /* uncompress A (public key), test if valid, and negate it */
986
1.44k
#ifndef FREESCALE_LTC_ECC
987
1.44k
    if (ge_frombytes_negate_vartime(&A, key->p) != 0)
988
0
        return BAD_FUNC_ARG;
989
1.44k
#endif
990
991
    /* find H(R,A,M) and store it as h */
992
993
1.44k
    ret = ed25519_hash_final(key, sha, h);
994
1.44k
    if (ret != 0)
995
99
        return ret;
996
997
#ifdef FREESCALE_LTC_ECC
998
    ret = LTC_PKHA_sc_reduce(h);
999
    if (ret != kStatus_Success)
1000
        return ret;
1001
    ret = LTC_PKHA_SignatureForVerify(rcheck, h, sig + (ED25519_SIG_SIZE/2), key);
1002
    if (ret != kStatus_Success)
1003
        return ret;
1004
#else
1005
1.34k
    sc_reduce(h);
1006
1007
    /*
1008
       Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
1009
       SB - H(R,A,M)A saving decompression of R
1010
    */
1011
1.34k
    ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2));
1012
1.34k
    if (ret != 0)
1013
29
        return ret;
1014
1015
1.31k
    ge_tobytes_nct(rcheck, &R);
1016
1.31k
#endif /* FREESCALE_LTC_ECC */
1017
1018
    /* comparison of R created to R in sig */
1019
1.31k
    ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2);
1020
1.31k
    if (ret != 0) {
1021
384
        ret = SIG_VERIFY_E;
1022
384
    }
1023
1024
#ifdef WOLFSSL_CHECK_VER_FAULTS
1025
    /* redundant comparison as sanity check that first one happened */
1026
    if (ret == 0 && ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2) != 0) {
1027
        ret = SIG_VERIFY_E;
1028
    }
1029
#endif
1030
1031
1.31k
    if (ret == 0) {
1032
        /* set the verification status */
1033
928
        *res = 1;
1034
928
    }
1035
1036
1.31k
    return ret;
1037
1.34k
}
1038
#endif /* (!WOLFSSL_SE050 || WOLFSSL_SE050_ONLY_KEY_ID) &&
1039
        * !WOLF_CRYPTO_CB_ONLY_ED25519 */
1040
1041
#if defined(WOLFSSL_ED25519_STREAMING_VERIFY) && \
1042
    (!defined(WOLFSSL_SE050) || defined(WOLFSSL_SE050_ONLY_KEY_ID))
1043
1044
int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key,
1045
614
                               byte type, const byte* context, byte contextLen) {
1046
614
    if (key == NULL)
1047
0
        return BAD_FUNC_ARG;
1048
614
    return ed25519_verify_msg_init_with_sha(sig, sigLen, key, &key->sha,
1049
614
                                        type, context, contextLen);
1050
614
}
1051
1052
int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen,
1053
72.9k
                                        ed25519_key* key) {
1054
72.9k
    if (key == NULL)
1055
0
        return BAD_FUNC_ARG;
1056
72.9k
    return ed25519_verify_msg_update_with_sha(msgSegment, msgSegmentLen,
1057
72.9k
                                          key, &key->sha);
1058
72.9k
}
1059
1060
int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res,
1061
533
                                ed25519_key* key) {
1062
533
    if (key == NULL)
1063
0
        return BAD_FUNC_ARG;
1064
533
    return ed25519_verify_msg_final_with_sha(sig, sigLen, res,
1065
533
                                         key, &key->sha);
1066
533
}
1067
1068
#endif /* WOLFSSL_ED25519_STREAMING_VERIFY &&
1069
        * (!WOLFSSL_SE050 || WOLFSSL_SE050_ONLY_KEY_ID) */
1070
1071
/*
1072
   sig     is array of bytes containing the signature
1073
   sigLen  is the length of sig byte array
1074
   msg     the array of bytes containing the message
1075
   msgLen  length of msg array
1076
   res     will be 1 on successful verify and 0 on unsuccessful
1077
   key     Ed25519 public key
1078
   return  0 and res of 1 on success
1079
*/
1080
int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg,
1081
                              word32 msgLen, int* res, ed25519_key* key,
1082
                              byte type, const byte* context, byte contextLen)
1083
1.11k
{
1084
1.11k
    int ret;
1085
#if defined(WOLFSSL_SE050) && !defined(WOLFSSL_SE050_ONLY_KEY_ID)
1086
    (void)type;
1087
    (void)context;
1088
    (void)contextLen;
1089
    (void)ed25519Ctx;
1090
    ret = se050_ed25519_verify_msg(sig, sigLen, msg, msgLen, key, res);
1091
#elif defined(WOLF_CRYPTO_CB_ONLY_ED25519)
1092
    (void)ed25519Ctx;
1093
    ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
1094
1095
    if (sig == NULL || msg == NULL || res == NULL || key == NULL ||
1096
                                         (context == NULL && contextLen != 0))
1097
        return BAD_FUNC_ARG;
1098
1099
    if ((type == Ed25519ph) &&
1100
        (msgLen != WC_SHA512_DIGEST_SIZE))
1101
    {
1102
        return BAD_LENGTH_E;
1103
    }
1104
1105
    #ifndef WOLF_CRYPTO_CB_FIND
1106
    if (key->devId != INVALID_DEVID)
1107
    #endif
1108
    {
1109
        ret = wc_CryptoCb_Ed25519Verify(sig, sigLen, msg, msgLen, res, key,
1110
            type, context, contextLen);
1111
    }
1112
    if (ret == WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) {
1113
        ret = NO_VALID_DEVID;
1114
    }
1115
#else
1116
1.11k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
1117
1.11k
    wc_Sha512 *sha;
1118
#else
1119
    WC_DECLARE_VAR(sha, wc_Sha512, 1, key ? key->heap : NULL);
1120
#endif
1121
1122
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_ONLY_KEY_ID)
1123
    /* Key resident in the SE050: verify in hardware. Software keys fall through
1124
     * to the wolfCrypt software implementation below. */
1125
    if (key != NULL && key->keyIdSet) {
1126
        /* The SE050 performs only PureEdDSA; it cannot apply the Ed25519ctx or
1127
         * Ed25519ph variants, so reject them rather than silently verifying
1128
         * against the wrong scheme. */
1129
        if (type == Ed25519ctx || type == Ed25519ph || contextLen != 0) {
1130
            return BAD_FUNC_ARG;
1131
        }
1132
        return se050_ed25519_verify_msg(sig, sigLen, msg, msgLen, key, res);
1133
    }
1134
#endif
1135
1136
    /* sanity check on arguments */
1137
1.11k
    if (sig == NULL || msg == NULL || res == NULL || key == NULL ||
1138
1.11k
                                         (context == NULL && contextLen != 0))
1139
3
        return BAD_FUNC_ARG;
1140
1141
1.11k
    if ((type == Ed25519ph) &&
1142
0
        (msgLen != WC_SHA512_DIGEST_SIZE))
1143
0
    {
1144
0
        return BAD_LENGTH_E;
1145
0
    }
1146
1147
1.11k
#ifdef WOLF_CRYPTO_CB
1148
1.11k
    #ifndef WOLF_CRYPTO_CB_FIND
1149
1.11k
    if (key->devId != INVALID_DEVID)
1150
0
    #endif
1151
0
    {
1152
0
        ret = wc_CryptoCb_Ed25519Verify(sig, sigLen, msg, msgLen, res, key,
1153
0
            type, context, contextLen);
1154
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
1155
0
            return ret;
1156
        /* fall-through when unavailable */
1157
0
    }
1158
1.11k
#endif
1159
1160
1.11k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
1161
1.11k
    sha = &key->sha;
1162
#else
1163
    WC_ALLOC_VAR_EX(sha, wc_Sha512, 1, key->heap, DYNAMIC_TYPE_HASHES,
1164
                    return MEMORY_E);
1165
    ret = ed25519_hash_init(key, sha);
1166
    if (ret < 0) {
1167
        WC_FREE_VAR_EX(sha, key->heap, DYNAMIC_TYPE_HASHES);
1168
        return ret;
1169
    }
1170
#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
1171
1172
1.11k
    ret = ed25519_verify_msg_init_with_sha(sig, sigLen, key, sha, type, context,
1173
1.11k
        contextLen);
1174
1.11k
    if (ret == 0)
1175
1.04k
        ret = ed25519_verify_msg_update_with_sha(msg, msgLen, key, sha);
1176
1.11k
    if (ret == 0)
1177
975
        ret = ed25519_verify_msg_final_with_sha(sig, sigLen, res, key, sha);
1178
1179
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
1180
    ed25519_hash_free(key, sha);
1181
    WC_FREE_VAR_EX(sha, key->heap, DYNAMIC_TYPE_HASHES);
1182
#endif
1183
1.11k
#endif /* WOLFSSL_SE050 */
1184
1.11k
    return ret;
1185
1.11k
}
1186
1187
/*
1188
   sig     is array of bytes containing the signature
1189
   sigLen  is the length of sig byte array
1190
   msg     the array of bytes containing the message
1191
   msgLen  length of msg array
1192
   res     will be 1 on successful verify and 0 on unsuccessful
1193
   key     Ed25519 public key
1194
   return  0 and res of 1 on success
1195
*/
1196
int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
1197
                          word32 msgLen, int* res, ed25519_key* key)
1198
1.11k
{
1199
1.11k
    return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key,
1200
1.11k
                                    (byte)Ed25519, NULL, 0);
1201
1.11k
}
1202
1203
/*
1204
   sig         is array of bytes containing the signature
1205
   sigLen      is the length of sig byte array
1206
   msg         the array of bytes containing the message
1207
   msgLen      length of msg array
1208
   res         will be 1 on successful verify and 0 on unsuccessful
1209
   key         Ed25519 public key
1210
   context     extra signing data
1211
   contextLen  length of extra signing data
1212
   return  0 and res of 1 on success
1213
*/
1214
int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
1215
                             word32 msgLen, int* res, ed25519_key* key,
1216
                             const byte* context, byte contextLen)
1217
0
{
1218
0
    return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key,
1219
0
                                    Ed25519ctx, context, contextLen);
1220
0
}
1221
1222
/*
1223
   sig         is array of bytes containing the signature
1224
   sigLen      is the length of sig byte array
1225
   hash        the array of bytes containing the SHA-512 hash of the message
1226
   hashLen     length of hash array
1227
   res         will be 1 on successful verify and 0 on unsuccessful
1228
   key         Ed25519 public key
1229
   context     extra signing data
1230
   contextLen  length of extra signing data
1231
   return  0 and res of 1 on success
1232
*/
1233
int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash,
1234
                             word32 hashLen, int* res, ed25519_key* key,
1235
                             const byte* context, byte contextLen)
1236
0
{
1237
0
    return wc_ed25519_verify_msg_ex(sig, sigLen, hash, hashLen, res, key,
1238
0
                                    Ed25519ph, context, contextLen);
1239
0
}
1240
1241
/*
1242
   sig         is array of bytes containing the signature
1243
   sigLen      is the length of sig byte array
1244
   msg         the array of bytes containing the message
1245
   msgLen      length of msg array
1246
   res         will be 1 on successful verify and 0 on unsuccessful
1247
   key         Ed25519 public key
1248
   context     extra signing data
1249
   contextLen  length of extra signing data
1250
   return  0 and res of 1 on success
1251
*/
1252
int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
1253
                            word32 msgLen, int* res, ed25519_key* key,
1254
                            const byte* context, byte contextLen)
1255
0
{
1256
0
    int  ret;
1257
0
    byte hash[WC_SHA512_DIGEST_SIZE];
1258
1259
0
    ret = ed25519_hash(key, msg, msgLen, hash);
1260
0
    if (ret != 0)
1261
0
        return ret;
1262
1263
0
    return wc_ed25519_verify_msg_ex(sig, sigLen, hash, sizeof(hash), res, key,
1264
0
                                    Ed25519ph, context, contextLen);
1265
0
}
1266
#endif /* HAVE_ED25519_VERIFY */
1267
1268
#ifndef WC_NO_CONSTRUCTORS
1269
ed25519_key* wc_ed25519_new(void* heap, int devId, int *result_code)
1270
1.07k
{
1271
1.07k
    int ret;
1272
1.07k
    ed25519_key* key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
1273
1.07k
                        DYNAMIC_TYPE_ED25519);
1274
1.07k
    if (key == NULL) {
1275
0
        ret = MEMORY_E;
1276
0
    }
1277
1.07k
    else {
1278
1.07k
        ret = wc_ed25519_init_ex(key, heap, devId);
1279
1.07k
        if (ret != 0) {
1280
0
            XFREE(key, heap, DYNAMIC_TYPE_ED25519);
1281
0
            key = NULL;
1282
0
        }
1283
1.07k
    }
1284
1285
1.07k
    if (result_code != NULL)
1286
0
        *result_code = ret;
1287
1288
1.07k
    return key;
1289
1.07k
}
1290
1291
1.07k
int wc_ed25519_delete(ed25519_key* key, ed25519_key** key_p) {
1292
1.07k
    void* heap;
1293
1.07k
    if (key == NULL)
1294
0
        return BAD_FUNC_ARG;
1295
1.07k
    heap = key->heap;
1296
1.07k
    wc_ed25519_free(key);
1297
1.07k
    XFREE(key, heap, DYNAMIC_TYPE_ED25519);
1298
1.07k
    if (key_p != NULL)
1299
0
        *key_p = NULL;
1300
1.07k
    return 0;
1301
1.07k
}
1302
#endif /* !WC_NO_CONSTRUCTORS */
1303
1304
/* initialize information and memory for key */
1305
int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId)
1306
5.43k
{
1307
5.43k
    if (key == NULL)
1308
0
        return BAD_FUNC_ARG;
1309
1310
    /* for init, ensure the key is zeroed*/
1311
5.43k
    XMEMSET(key, 0, sizeof(ed25519_key));
1312
1313
5.43k
#ifdef WOLF_CRYPTO_CB
1314
5.43k
    key->devId = devId;
1315
#else
1316
    (void)devId;
1317
#endif
1318
5.43k
    key->heap = heap;
1319
1320
/* no field math is linked when all Ed25519 ops route through the callback */
1321
5.43k
#if !defined(FREESCALE_LTC_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_ED25519)
1322
5.43k
    fe_init();
1323
5.43k
#endif
1324
1325
#ifdef WOLFSSL_CHECK_MEM_ZERO
1326
    wc_MemZero_Add("wc_ed25519_init_ex key->k", &key->k, sizeof(key->k));
1327
#endif
1328
1329
5.43k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
1330
5.43k
    return ed25519_hash_init(key, &key->sha);
1331
#else /* !WOLFSSL_ED25519_PERSISTENT_SHA */
1332
    return 0;
1333
#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
1334
5.43k
}
1335
1336
int wc_ed25519_init(ed25519_key* key)
1337
4.35k
{
1338
4.35k
    return wc_ed25519_init_ex(key, NULL, INVALID_DEVID);
1339
4.35k
}
1340
1341
/* clear memory of key */
1342
void wc_ed25519_free(ed25519_key* key)
1343
5.43k
{
1344
5.43k
    if (key == NULL)
1345
0
        return;
1346
1347
5.43k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
1348
5.43k
    ed25519_hash_free(key, &key->sha);
1349
5.43k
#endif
1350
1351
#ifdef WOLFSSL_SE050
1352
#ifdef WOLFSSL_SE050_AUTO_ERASE
1353
    wc_se050_erase_object(key->keyId);
1354
#endif
1355
    se050_ed25519_free_key(key);
1356
#endif
1357
1358
5.43k
    ForceZero(key, sizeof(ed25519_key));
1359
#ifdef WOLFSSL_CHECK_MEM_ZERO
1360
    wc_MemZero_Check(key, sizeof(ed25519_key));
1361
#endif
1362
5.43k
}
1363
1364
1365
#ifdef HAVE_ED25519_KEY_EXPORT
1366
1367
/*
1368
    outLen should contain the size of out buffer when input. outLen is than set
1369
    to the final output length.
1370
    returns 0 on success
1371
 */
1372
int wc_ed25519_export_public(const ed25519_key* key, byte* out, word32* outLen)
1373
252
{
1374
    /* sanity check on arguments */
1375
252
    if (key == NULL || out == NULL || outLen == NULL)
1376
100
        return BAD_FUNC_ARG;
1377
1378
152
    if (*outLen < ED25519_PUB_KEY_SIZE) {
1379
24
        *outLen = ED25519_PUB_KEY_SIZE;
1380
24
        return BUFFER_E;
1381
24
    }
1382
1383
128
    if (!key->pubKeySet)
1384
0
        return PUBLIC_KEY_E;
1385
1386
128
    *outLen = ED25519_PUB_KEY_SIZE;
1387
128
    XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE);
1388
1389
128
    return 0;
1390
128
}
1391
1392
#endif /* HAVE_ED25519_KEY_EXPORT */
1393
1394
1395
#ifdef HAVE_ED25519_KEY_IMPORT
1396
/*
1397
    Imports a compressed/uncompressed public key.
1398
    in       the byte array containing the public key
1399
    inLen    the length of the byte array being passed in
1400
    key      ed25519 key struct to put the public key in
1401
    trusted  whether the public key is trusted to match private key if set
1402
 */
1403
int wc_ed25519_import_public_ex(const byte* in, word32 inLen, ed25519_key* key,
1404
    int trusted)
1405
2.10k
{
1406
2.10k
    int ret = 0;
1407
1408
    /* sanity check on arguments */
1409
2.10k
    if (in == NULL || key == NULL)
1410
0
        return BAD_FUNC_ARG;
1411
1412
2.10k
    if (inLen < ED25519_PUB_KEY_SIZE)
1413
5
        return BAD_FUNC_ARG;
1414
1415
#ifdef WOLFSSL_SE050
1416
    /* Importing new key material invalidates any prior SE050 object binding;
1417
     * erase the old object (no-op when keyIdSet == 0) so the host and the
1418
     * secure element agree on what's bound. Clear the binding fields
1419
     * explicitly afterwards so a stale keyId never survives, even when
1420
     * se050_ed25519_free_key() returns early because the SE050 session isn't
1421
     * configured yet. */
1422
    se050_ed25519_free_key(key);
1423
    key->keyId    = 0;
1424
    key->keyIdSet = 0;
1425
#endif
1426
1427
    /* compressed prefix according to draft
1428
       http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
1429
2.10k
    if (in[0] == 0x40 && inLen == ED25519_PUB_KEY_SIZE + 1) {
1430
        /* key is stored in compressed format so just copy in */
1431
1
        XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE);
1432
#ifdef FREESCALE_LTC_ECC
1433
        /* recover X coordinate */
1434
        ltc_pkha_ecc_point_t pubKey;
1435
        pubKey.X = key->pointX;
1436
        pubKey.Y = key->pointY;
1437
        LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
1438
#endif
1439
1
    }
1440
    /* importing uncompressed public key */
1441
2.10k
    else if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) {
1442
#ifdef FREESCALE_LTC_ECC
1443
        /* reverse bytes for little endian byte order */
1444
        for (int i = 0; i < ED25519_KEY_SIZE; i++)
1445
        {
1446
            key->pointX[i] = *(in + ED25519_KEY_SIZE - i);
1447
            key->pointY[i] = *(in + 2*ED25519_KEY_SIZE - i);
1448
        }
1449
        XMEMCPY(key->p, key->pointY, ED25519_KEY_SIZE);
1450
#elif defined(WOLF_CRYPTO_CB_ONLY_ED25519)
1451
        {
1452
            /* Compress without the stripped curve math: y crosses reversed
1453
             * with its top bit replaced by the parity of x. Same byte
1454
             * transform as ge_compress_key minus the canonical reduction
1455
             * (as in the ED25519_SMALL variant); the key check below
1456
             * rejects non-canonical keys. This inlined code avoids pulling
1457
             * in ge_compress_key(), etc. */
1458
            const byte* xIn = in + 1;
1459
            const byte* yIn = in + 1 + ED25519_PUB_KEY_SIZE;
1460
            int i;
1461
1462
            for (i = 0; i < ED25519_PUB_KEY_SIZE; i++) {
1463
                key->p[i] = yIn[ED25519_PUB_KEY_SIZE - 1 - i];
1464
            }
1465
            key->p[0] = (byte)((key->p[0] & 0x7f) | ((xIn[0] & 1) << 7));
1466
        }
1467
#else
1468
        /* pass in (x,y) and store compressed key */
1469
2
        ret = ge_compress_key(key->p, in+1,
1470
2
                              in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE);
1471
2
#endif /* FREESCALE_LTC_ECC */
1472
2
    }
1473
    /* if not specified compressed or uncompressed check key size
1474
       if key size is equal to compressed key size copy in key */
1475
2.10k
    else if (inLen == ED25519_PUB_KEY_SIZE) {
1476
2.07k
        XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE);
1477
#ifdef FREESCALE_LTC_ECC
1478
        /* recover X coordinate */
1479
        ltc_pkha_ecc_point_t pubKey;
1480
        pubKey.X = key->pointX;
1481
        pubKey.Y = key->pointY;
1482
        LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
1483
#endif
1484
2.07k
    }
1485
22
    else {
1486
22
        ret = BAD_FUNC_ARG;
1487
22
    }
1488
1489
2.10k
    if (ret == 0) {
1490
2.08k
        key->pubKeySet = 1;
1491
2.08k
        if (!trusted) {
1492
2.08k
            ret = wc_ed25519_check_key(key);
1493
2.08k
        }
1494
2.08k
    }
1495
2.10k
    if (ret != 0) {
1496
221
        key->pubKeySet = 0;
1497
221
    }
1498
1499
    /* bad public key format */
1500
2.10k
    return ret;
1501
2.10k
}
1502
1503
/*
1504
    Imports a compressed/uncompressed public key.
1505
    in    the byte array containing the public key
1506
    inLen the length of the byte array being passed in
1507
    key   ed25519 key struct to put the public key in
1508
 */
1509
int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
1510
2.10k
{
1511
2.10k
    return wc_ed25519_import_public_ex(in, inLen, key, 0);
1512
2.10k
}
1513
1514
/*
1515
    For importing a private key.
1516
 */
1517
int wc_ed25519_import_private_only(const byte* priv, word32 privSz,
1518
                                                               ed25519_key* key)
1519
1.53k
{
1520
1.53k
    int ret = 0;
1521
1522
    /* sanity check on arguments */
1523
1.53k
    if (priv == NULL || key == NULL)
1524
0
        return BAD_FUNC_ARG;
1525
1526
    /* key size check */
1527
1.53k
    if (privSz != ED25519_KEY_SIZE)
1528
9
        return BAD_FUNC_ARG;
1529
1530
#ifdef WOLFSSL_SE050
1531
    /* Importing new key material invalidates any prior SE050 object binding;
1532
     * erase the old object (no-op when keyIdSet == 0) so the host and the
1533
     * secure element agree on what's bound. Clear the binding fields
1534
     * explicitly afterwards so a stale keyId never survives, even when
1535
     * se050_ed25519_free_key() returns early because the SE050 session isn't
1536
     * configured yet. */
1537
    se050_ed25519_free_key(key);
1538
    key->keyId    = 0;
1539
    key->keyIdSet = 0;
1540
#endif
1541
1542
1.52k
    XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
1543
1.52k
    key->privKeySet = 1;
1544
1545
1.52k
    if (key->pubKeySet) {
1546
        /* Validate loaded public key */
1547
0
        ret = wc_ed25519_check_key(key);
1548
0
    }
1549
1.52k
    if (ret != 0) {
1550
0
        key->privKeySet = 0;
1551
0
        ForceZero(key->k, ED25519_KEY_SIZE);
1552
0
    }
1553
1554
1.52k
    return ret;
1555
1.53k
}
1556
1557
1558
/* Import an ed25519 private and public keys from byte array(s).
1559
 *
1560
 * priv     [in]  Array holding private key from
1561
 *                wc_ed25519_export_private_only(), or private+public keys from
1562
 *                wc_ed25519_export_private().
1563
 * privSz   [in]  Number of bytes of data in private key array.
1564
 * pub      [in]  Array holding public key (or NULL).
1565
 * pubSz    [in]  Number of bytes of data in public key array (or 0).
1566
 * key      [in]  Ed25519 private/public key.
1567
 * trusted  [in]  Indicates whether the public key data is trusted.
1568
 *                When 0, checks public key matches private key.
1569
 *                When 1, doesn't check public key matches private key.
1570
 * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid
1571
 *         combination of keys/lengths is supplied, 0 otherwise.
1572
 */
1573
int wc_ed25519_import_private_key_ex(const byte* priv, word32 privSz,
1574
    const byte* pub, word32 pubSz, ed25519_key* key, int trusted)
1575
0
{
1576
0
    int ret;
1577
1578
    /* sanity check on arguments */
1579
0
    if (priv == NULL || key == NULL)
1580
0
        return BAD_FUNC_ARG;
1581
1582
    /* key size check */
1583
0
    if (privSz != ED25519_KEY_SIZE && privSz != ED25519_PRV_KEY_SIZE)
1584
0
        return BAD_FUNC_ARG;
1585
1586
0
    if (pub == NULL) {
1587
0
        if (pubSz != 0)
1588
0
            return BAD_FUNC_ARG;
1589
0
        if (privSz != ED25519_PRV_KEY_SIZE)
1590
0
            return BAD_FUNC_ARG;
1591
0
        pub = priv + ED25519_KEY_SIZE;
1592
0
        pubSz = ED25519_PUB_KEY_SIZE;
1593
0
    }
1594
0
    else if (pubSz < ED25519_PUB_KEY_SIZE) {
1595
0
        return BAD_FUNC_ARG;
1596
0
    }
1597
1598
#ifdef WOLFSSL_SE050
1599
    /* Importing new key material invalidates any prior SE050 object binding;
1600
     * erase the old object (no-op when keyIdSet == 0) so the host and the
1601
     * secure element agree on what's bound. key->k is overwritten before the
1602
     * wc_ed25519_import_public_ex() call below, so the binding must be
1603
     * dropped here first in case that function fails its own early-return
1604
     * argument checks before reaching its reset. Clear the binding fields
1605
     * explicitly afterwards so a stale keyId never survives, even when
1606
     * se050_ed25519_free_key() returns early because the SE050 session isn't
1607
     * configured yet. */
1608
    se050_ed25519_free_key(key);
1609
    key->keyId    = 0;
1610
    key->keyIdSet = 0;
1611
#endif
1612
1613
0
    XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
1614
0
    key->privKeySet = 1;
1615
1616
    /* import public key */
1617
0
    ret = wc_ed25519_import_public_ex(pub, pubSz, key, trusted);
1618
0
    if (ret != 0) {
1619
0
        key->privKeySet = 0;
1620
0
        ForceZero(key->k, ED25519_KEY_SIZE);
1621
0
        return ret;
1622
0
    }
1623
1624
    /* make the private key (priv + pub) */
1625
0
    XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
1626
1627
0
    return ret;
1628
0
}
1629
1630
/* Import an ed25519 private and public keys from byte array(s).
1631
 *
1632
 * priv    [in]  Array holding private key from wc_ed25519_export_private_only(),
1633
 *               or private+public keys from wc_ed25519_export_private().
1634
 * privSz  [in]  Number of bytes of data in private key array.
1635
 * pub     [in]  Array holding public key (or NULL).
1636
 * pubSz   [in]  Number of bytes of data in public key array (or 0).
1637
 * key     [in]  Ed25519 private/public key.
1638
 * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid
1639
 *         combination of keys/lengths is supplied, 0 otherwise.
1640
 */
1641
int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
1642
    const byte* pub, word32 pubSz, ed25519_key* key)
1643
0
{
1644
0
    return wc_ed25519_import_private_key_ex(priv, privSz, pub, pubSz, key, 0);
1645
0
}
1646
#endif /* HAVE_ED25519_KEY_IMPORT */
1647
1648
1649
#ifdef HAVE_ED25519_KEY_EXPORT
1650
1651
/*
1652
 export private key only (secret part so 32 bytes)
1653
 outLen should contain the size of out buffer when input. outLen is than set
1654
 to the final output length.
1655
 returns 0 on success
1656
 */
1657
int wc_ed25519_export_private_only(const ed25519_key* key, byte* out, word32* outLen)
1658
414
{
1659
    /* sanity checks on arguments */
1660
414
    if (key == NULL || !key->privKeySet || out == NULL || outLen == NULL)
1661
108
        return BAD_FUNC_ARG;
1662
1663
306
    if (*outLen < ED25519_KEY_SIZE) {
1664
16
        *outLen = ED25519_KEY_SIZE;
1665
16
        return BUFFER_E;
1666
16
    }
1667
1668
290
    *outLen = ED25519_KEY_SIZE;
1669
290
    XMEMCPY(out, key->k, ED25519_KEY_SIZE);
1670
1671
290
    return 0;
1672
306
}
1673
1674
/*
1675
 export private key, including public part
1676
 outLen should contain the size of out buffer when input. outLen is than set
1677
 to the final output length.
1678
 returns 0 on success
1679
 */
1680
int wc_ed25519_export_private(const ed25519_key* key, byte* out, word32* outLen)
1681
0
{
1682
    /* sanity checks on arguments */
1683
0
    if (key == NULL || !key->privKeySet || out == NULL || outLen == NULL)
1684
0
        return BAD_FUNC_ARG;
1685
1686
0
    if (*outLen < ED25519_PRV_KEY_SIZE) {
1687
0
        *outLen = ED25519_PRV_KEY_SIZE;
1688
0
        return BUFFER_E;
1689
0
    }
1690
1691
0
    *outLen = ED25519_PRV_KEY_SIZE;
1692
0
    XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE);
1693
1694
0
    return 0;
1695
0
}
1696
1697
/* export full private key and public key
1698
   return 0 on success
1699
 */
1700
int wc_ed25519_export_key(const ed25519_key* key,
1701
                          byte* priv, word32 *privSz,
1702
                          byte* pub, word32 *pubSz)
1703
0
{
1704
0
    int ret;
1705
1706
    /* export 'full' private part */
1707
0
    ret = wc_ed25519_export_private(key, priv, privSz);
1708
0
    if (ret == 0) {
1709
        /* export public part */
1710
0
        ret = wc_ed25519_export_public(key, pub, pubSz);
1711
0
    }
1712
1713
0
    return ret;
1714
0
}
1715
1716
#endif /* HAVE_ED25519_KEY_EXPORT */
1717
1718
/* Check the public key is valid.
1719
 *
1720
 * When private key available, check the calculated public key matches.
1721
 * When no private key, check Y is in range and an X is able to be calculated.
1722
 *
1723
 * @param [in] key  Ed25519 private/public key.
1724
 * @return  0 otherwise.
1725
 * @return  BAD_FUNC_ARG when key is NULL.
1726
 * @return  PUBLIC_KEY_E when the public key is not set, doesn't match or is
1727
 *          invalid.
1728
 * @return  other -ve value on hash failure.
1729
 */
1730
int wc_ed25519_check_key(ed25519_key* key)
1731
2.49k
{
1732
2.49k
    int ret = 0;
1733
1734
    /* Validate parameter. */
1735
2.49k
    if (key == NULL) {
1736
0
        ret = BAD_FUNC_ARG;
1737
0
    }
1738
1739
    /* Check we have a public key to check. */
1740
2.49k
    if ((ret == 0) && (!key->pubKeySet)) {
1741
0
        ret = PUBLIC_KEY_E;
1742
0
    }
1743
1744
2.49k
#ifdef WOLF_CRYPTO_CB
1745
    /* Device-first: let a configured device validate the key. Fall through
1746
     * to the software checks below only when the device reports the
1747
     * operation unavailable. */
1748
2.49k
    #ifndef WOLF_CRYPTO_CB_FIND
1749
2.49k
    if ((ret == 0) && (key->devId != INVALID_DEVID))
1750
    #else
1751
    if (ret == 0)
1752
    #endif
1753
0
    {
1754
0
        ret = wc_CryptoCb_Ed25519CheckKey(key);
1755
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
1756
0
            return ret;
1757
0
        ret = 0; /* device declined; fall through to software */
1758
0
    }
1759
2.49k
#endif
1760
1761
#ifdef WOLF_CRYPTO_CB_ONLY_ED25519
1762
    /* Software validation is stripped; the device-first check above either
1763
     * handled the key or reported the op unavailable, so fail closed rather
1764
     * than accept an unvalidated key. */
1765
    if (ret == 0)
1766
        ret = NO_VALID_DEVID;
1767
#else
1768
    /* Reject small-order pub key before the priv-vs-pub compare so the
1769
     * diagnostic isn't masked by a "mismatch" error. */
1770
2.49k
    if ((ret == 0) && ed25519_is_small_order(key->p)) {
1771
53
        WOLFSSL_MSG("Ed25519 small-order public key rejected during key check");
1772
53
        ret = PUBLIC_KEY_E;
1773
53
    }
1774
1775
2.49k
#ifdef HAVE_ED25519_MAKE_KEY
1776
    /* If we have a private key just make the public key and compare. */
1777
2.49k
    if ((ret == 0) && (key->privKeySet)) {
1778
414
        ALIGN16 unsigned char pubKey[ED25519_PUB_KEY_SIZE];
1779
1780
414
        ret = wc_ed25519_make_public(key, pubKey, sizeof(pubKey));
1781
414
        if (ret == 0 && XMEMCMP(pubKey, key->p, ED25519_PUB_KEY_SIZE) != 0)
1782
0
            ret = PUBLIC_KEY_E;
1783
414
    }
1784
#else
1785
    (void)key;
1786
#endif /* HAVE_ED25519_MAKE_KEY */
1787
1788
    /* No private key (or ability to make a public key), check Y is valid. */
1789
2.49k
    if (ret == 0
1790
2.30k
#ifdef HAVE_ED25519_MAKE_KEY
1791
2.30k
        && (!key->privKeySet)
1792
2.49k
#endif
1793
2.49k
        ) {
1794
        /* Verify that xQ and yQ are integers in the interval [0, p - 1].
1795
         * Only have yQ so check that ordinate. p = 2^255 - 19 */
1796
2.02k
        if ((key->p[ED25519_PUB_KEY_SIZE - 1] & 0x7f) == 0x7f) {
1797
175
            int i;
1798
1799
175
            ret = PUBLIC_KEY_E;
1800
            /* Check up to last byte. */
1801
1.23k
            for (i = ED25519_PUB_KEY_SIZE - 2; i > 0; i--) {
1802
1.22k
                if (key->p[i] != 0xff) {
1803
164
                    ret = 0;
1804
164
                    break;
1805
164
                }
1806
1.22k
            }
1807
            /* Bits are all one up to last byte - check less than -19. */
1808
175
            if ((ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E)) && (key->p[0] < 0xed)) {
1809
9
                ret = 0;
1810
9
            }
1811
175
        }
1812
1813
2.02k
        if (ret == 0) {
1814
            /* Verify that Q is on the curve.
1815
             * Uncompressing the public key will validate yQ. */
1816
2.02k
            ge_p3 A;
1817
1818
2.02k
            if (ge_frombytes_negate_vartime(&A, key->p) != 0) {
1819
144
                ret = PUBLIC_KEY_E;
1820
144
            }
1821
2.02k
        }
1822
2.02k
    }
1823
2.49k
#endif /* WOLF_CRYPTO_CB_ONLY_ED25519 */
1824
1825
2.49k
    return ret;
1826
2.49k
}
1827
1828
/* returns the private key size (secret only) in bytes */
1829
int wc_ed25519_size(const ed25519_key* key)
1830
0
{
1831
0
    if (key == NULL)
1832
0
        return BAD_FUNC_ARG;
1833
1834
0
    return ED25519_KEY_SIZE;
1835
0
}
1836
1837
/* returns the private key size (secret + public) in bytes */
1838
int wc_ed25519_priv_size(const ed25519_key* key)
1839
0
{
1840
0
    if (key == NULL)
1841
0
        return BAD_FUNC_ARG;
1842
1843
0
    return ED25519_PRV_KEY_SIZE;
1844
0
}
1845
1846
/* returns the compressed key size in bytes (public key) */
1847
int wc_ed25519_pub_size(const ed25519_key* key)
1848
0
{
1849
0
    if (key == NULL)
1850
0
        return BAD_FUNC_ARG;
1851
1852
0
    return ED25519_PUB_KEY_SIZE;
1853
0
}
1854
1855
/* returns the size of signature in bytes */
1856
int wc_ed25519_sig_size(const ed25519_key* key)
1857
0
{
1858
0
    if (key == NULL)
1859
0
        return BAD_FUNC_ARG;
1860
1861
0
    return ED25519_SIG_SIZE;
1862
0
}
1863
1864
#endif /* HAVE_ED25519 */