Coverage Report

Created: 2026-11-12 06:59

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