Coverage Report

Created: 2026-07-22 06:50

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