Coverage Report

Created: 2026-09-20 06:33

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