Coverage Report

Created: 2026-04-05 07:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wolfssl-openssl-api/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
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
32
33
#ifdef HAVE_ED25519
34
#if FIPS_VERSION3_GE(6,0,0)
35
    /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
36
    #define FIPS_NO_WRAPPERS
37
38
       #ifdef USE_WINDOWS_API
39
               #pragma code_seg(".fipsA$f")
40
               #pragma const_seg(".fipsB$f")
41
       #endif
42
#endif
43
44
#include <wolfssl/wolfcrypt/ed25519.h>
45
#include <wolfssl/wolfcrypt/ge_operations.h>
46
#include <wolfssl/wolfcrypt/hash.h>
47
#ifdef NO_INLINE
48
    #include <wolfssl/wolfcrypt/misc.h>
49
#else
50
    #define WOLFSSL_MISC_INCLUDED
51
    #include <wolfcrypt/src/misc.c>
52
#endif
53
54
#if FIPS_VERSION3_GE(6,0,0)
55
    const unsigned int wolfCrypt_FIPS_ed25519_ro_sanity[2] =
56
                                                     { 0x1a2b3c4d, 0x00000006 };
57
    int wolfCrypt_FIPS_ED25519_sanity(void)
58
    {
59
        return 0;
60
    }
61
#endif
62
63
#ifdef FREESCALE_LTC_ECC
64
    #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
65
#endif
66
#ifdef WOLFSSL_SE050
67
    #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
68
#endif
69
70
#ifdef WOLF_CRYPTO_CB
71
    #include <wolfssl/wolfcrypt/cryptocb.h>
72
#endif
73
74
#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_VERIFY)
75
    /* Set a static message string for "Sig No Collisions Message SNC".
76
    ** Note this is a static string per spec, see:
77
    ** https://datatracker.ietf.org/doc/rfc8032/
78
    */
79
    #define ED25519CTX_SNC_MESSAGE "SigEd25519 no Ed25519 collisions"
80
0
    #define ED25519CTX_SIZE 32 /* 32 chars: fixed length of SNC Message. */
81
82
    /* The 32 bytes of ED25519CTX_SIZE is used elsewhere, but we need one
83
    ** more char for saving the line ending in our ed25519Ctx[] here: */
84
    static const byte ed25519Ctx[ED25519CTX_SIZE + 1] = ED25519CTX_SNC_MESSAGE;
85
#endif
86
87
static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha)
88
6.24k
{
89
6.24k
    int ret;
90
91
6.24k
    ret = wc_InitSha512_ex(sha, key->heap,
92
6.24k
#if defined(WOLF_CRYPTO_CB)
93
6.24k
                           key->devId
94
#else
95
                           INVALID_DEVID
96
#endif
97
6.24k
        );
98
99
6.24k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
100
6.24k
    if (ret == 0) {
101
6.24k
        key->sha_clean_flag = 1;
102
6.24k
    }
103
6.24k
#endif
104
105
6.24k
    return ret;
106
6.24k
}
107
108
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
109
static int ed25519_hash_reset(ed25519_key* key)
110
8.78k
{
111
8.78k
    int ret;
112
113
8.78k
    if (key->sha_clean_flag) {
114
8.78k
        ret = 0;
115
8.78k
    }
116
0
    else {
117
0
        wc_Sha512Free(&key->sha);
118
0
        ret = wc_InitSha512_ex(&key->sha, key->heap,
119
0
#if defined(WOLF_CRYPTO_CB)
120
0
                               key->devId
121
#else
122
                               INVALID_DEVID
123
#endif
124
0
            );
125
0
        if (ret == 0)
126
0
            key->sha_clean_flag = 1;
127
0
    }
128
129
8.78k
    return ret;
130
8.78k
}
131
#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
132
133
static int ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha,
134
                               const byte* data, word32 len)
135
193k
{
136
193k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
137
193k
    if (key->sha_clean_flag) {
138
11.9k
        key->sha_clean_flag = 0;
139
11.9k
    }
140
#else
141
    (void)key;
142
#endif
143
193k
    return wc_Sha512Update(sha, data, len);
144
193k
}
145
146
static int ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash)
147
11.6k
{
148
11.6k
    int ret = wc_Sha512Final(sha, hash);
149
11.6k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
150
11.6k
    if (ret == 0) {
151
11.0k
        key->sha_clean_flag = 1;
152
11.0k
    }
153
#else
154
    (void)key;
155
#endif
156
11.6k
    return ret;
157
11.6k
}
158
159
static void ed25519_hash_free(ed25519_key* key, wc_Sha512 *sha)
160
6.24k
{
161
6.24k
    wc_Sha512Free(sha);
162
6.24k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
163
6.24k
    key->sha_clean_flag = 0;
164
#else
165
    (void)key;
166
#endif
167
6.24k
}
168
169
170
static int ed25519_hash(ed25519_key* key, const byte* in, word32 inLen,
171
    byte* hash)
172
6.10k
{
173
6.10k
    int ret;
174
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
175
    wc_Sha512 sha[1];
176
#else
177
6.10k
    wc_Sha512 *sha;
178
6.10k
#endif
179
180
6.10k
    if (key == NULL || (in == NULL && inLen > 0) || hash == NULL) {
181
0
        return BAD_FUNC_ARG;
182
0
    }
183
184
6.10k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
185
6.10k
    sha = &key->sha;
186
6.10k
    ret = ed25519_hash_reset(key);
187
#else
188
    ret = ed25519_hash_init(key, sha);
189
#endif
190
6.10k
    if (ret == 0) {
191
6.10k
        ret = ed25519_hash_update(key, sha, in, inLen);
192
6.10k
        if (ret == 0)
193
6.10k
            ret = ed25519_hash_final(key, sha, hash);
194
195
    #ifndef WOLFSSL_ED25519_PERSISTENT_SHA
196
        ed25519_hash_free(key, sha);
197
    #endif
198
6.10k
    }
199
200
6.10k
    return ret;
201
6.10k
}
202
203
#ifdef HAVE_ED25519_MAKE_KEY
204
#if FIPS_VERSION3_GE(6,0,0)
205
/* Performs a Pairwise Consistency Test on an Ed25519 key pair.
206
 *
207
 * @param [in] key  Ed25519 key to test.
208
 * @param [in] rng  Random number generator to use to create random digest.
209
 * @return  0 on success.
210
 * @return  ECC_PCT_E when signing or verification fail.
211
 * @return  Other -ve when random number generation fails.
212
 */
213
static int ed25519_pairwise_consistency_test(ed25519_key* key, WC_RNG* rng)
214
{
215
    int err = 0;
216
    byte digest[WC_SHA512_DIGEST_SIZE];
217
    word32 digestLen = WC_SHA512_DIGEST_SIZE;
218
    byte sig[ED25519_SIG_SIZE];
219
    word32 sigLen = ED25519_SIG_SIZE;
220
    int res = 0;
221
222
    /* Generate a random digest to sign. */
223
    err = wc_RNG_GenerateBlock(rng, digest, digestLen);
224
    if (err == 0) {
225
        /* Sign digest without context. */
226
        err = wc_ed25519_sign_msg_ex(digest, digestLen, sig, &sigLen, key,
227
            (byte)Ed25519, NULL, 0);
228
        if (err != 0) {
229
            /* Any sign failure means test failed. */
230
            err = ECC_PCT_E;
231
        }
232
    }
233
    if (err == 0) {
234
        /* Verify digest without context. */
235
        err = wc_ed25519_verify_msg_ex(sig, sigLen, digest, digestLen, &res,
236
            key, (byte)Ed25519, NULL, 0);
237
        if (err != 0) {
238
            /* Any verification operation failure means test failed. */
239
            err = ECC_PCT_E;
240
        }
241
        /* Check whether the signature verified. */
242
        else if (res == 0) {
243
            /* Test failed. */
244
            err = ECC_PCT_E;
245
        }
246
    }
247
248
    ForceZero(sig, sigLen);
249
250
    return err;
251
}
252
#endif
253
254
int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey,
255
                           word32 pubKeySz)
256
4.49k
{
257
4.49k
    int   ret = 0;
258
4.49k
    ALIGN16 byte az[ED25519_PRV_KEY_SIZE];
259
4.49k
#if !defined(FREESCALE_LTC_ECC)
260
4.49k
    ge_p3 A;
261
4.49k
#endif
262
263
4.49k
    if (key == NULL || pubKey == NULL || pubKeySz != ED25519_PUB_KEY_SIZE)
264
0
        ret = BAD_FUNC_ARG;
265
266
4.49k
    if ((ret == 0) && (!key->privKeySet)) {
267
34
        ret = ECC_PRIV_KEY_E;
268
34
    }
269
270
4.49k
    if (ret == 0)
271
4.46k
        ret = ed25519_hash(key, key->k, ED25519_KEY_SIZE, az);
272
4.49k
    if (ret == 0) {
273
        /* apply clamp */
274
4.15k
        az[0]  &= 248;
275
4.15k
        az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
276
4.15k
        az[31] |= 64;
277
278
    #ifdef FREESCALE_LTC_ECC
279
        ltc_pkha_ecc_point_t publicKey = {0};
280
        publicKey.X = key->pointX;
281
        publicKey.Y = key->pointY;
282
        LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), az,
283
            ED25519_KEY_SIZE, &publicKey, kLTC_Ed25519 /* result on Ed25519 */);
284
        LTC_PKHA_Ed25519_Compress(&publicKey, pubKey);
285
    #else
286
4.15k
        ge_scalarmult_base(&A, az);
287
4.15k
        ge_p3_tobytes(pubKey, &A);
288
4.15k
    #endif
289
290
4.15k
        key->pubKeySet = 1;
291
4.15k
    }
292
293
4.49k
    return ret;
294
4.49k
}
295
296
/* generate an ed25519 key pair.
297
 * returns 0 on success
298
 */
299
int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
300
694
{
301
694
    int ret;
302
303
694
    if (rng == NULL || key == NULL)
304
0
        return BAD_FUNC_ARG;
305
306
    /* ed25519 has 32 byte key sizes */
307
694
    if (keySz != ED25519_KEY_SIZE)
308
0
        return BAD_FUNC_ARG;
309
310
694
    key->privKeySet = 0;
311
694
    key->pubKeySet = 0;
312
313
694
#ifdef WOLF_CRYPTO_CB
314
694
    if (key->devId != INVALID_DEVID) {
315
0
        ret = wc_CryptoCb_Ed25519Gen(rng, keySz, key);
316
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
317
0
            return ret;
318
        /* fall-through when unavailable */
319
0
    }
320
694
#endif
321
322
694
    ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE);
323
694
    if (ret != 0)
324
183
        return ret;
325
326
511
    key->privKeySet = 1;
327
511
    ret = wc_ed25519_make_public(key, key->p, ED25519_PUB_KEY_SIZE);
328
511
    if (ret != 0) {
329
40
        key->privKeySet = 0;
330
40
        ForceZero(key->k, ED25519_KEY_SIZE);
331
40
        return ret;
332
40
    }
333
334
    /* put public key after private key, on the same buffer */
335
471
    XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
336
337
#if FIPS_VERSION3_GE(6,0,0)
338
    ret = wc_ed25519_check_key(key);
339
    if (ret == 0) {
340
        ret = ed25519_pairwise_consistency_test(key, rng);
341
    }
342
#endif
343
344
471
    return ret;
345
511
}
346
#endif /* HAVE_ED25519_MAKE_KEY */
347
348
349
#ifdef HAVE_ED25519_SIGN
350
/*
351
    in          contains the message to sign
352
    inLen       is the length of the message to sign
353
    out         is the buffer to write the signature
354
    outLen      [in/out] input size of out buf
355
                          output gets set as the final length of out
356
    key         is the ed25519 key to use when signing
357
    type        one of Ed25519, Ed25519ctx or Ed25519ph
358
    context     extra signing data
359
    contextLen  length of extra signing data
360
    return 0 on success
361
 */
362
int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
363
                            word32 *outLen, ed25519_key* key, byte type,
364
                            const byte* context, byte contextLen)
365
1.70k
{
366
1.70k
    int    ret;
367
#ifdef WOLFSSL_SE050
368
    (void)context;
369
    (void)contextLen;
370
    (void)type;
371
    ret = se050_ed25519_sign_msg(in, inLen, out, outLen, key);
372
#else
373
#ifdef FREESCALE_LTC_ECC
374
    ALIGN16 byte tempBuf[ED25519_PRV_KEY_SIZE];
375
    ltc_pkha_ecc_point_t ltcPoint = {0};
376
#else
377
1.70k
    ge_p3  R;
378
1.70k
#endif
379
1.70k
    ALIGN16 byte nonce[WC_SHA512_DIGEST_SIZE];
380
1.70k
    ALIGN16 byte hram[WC_SHA512_DIGEST_SIZE];
381
1.70k
    ALIGN16 byte az[ED25519_PRV_KEY_SIZE];
382
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
383
    byte orig_k[ED25519_KEY_SIZE];
384
#endif
385
386
    /* sanity check on arguments */
387
1.70k
    if (in == NULL || out == NULL || outLen == NULL || key == NULL ||
388
1.64k
                                         (context == NULL && contextLen != 0)) {
389
63
        return BAD_FUNC_ARG;
390
63
    }
391
392
1.64k
#ifdef WOLF_CRYPTO_CB
393
1.64k
    if (key->devId != INVALID_DEVID) {
394
0
        ret = wc_CryptoCb_Ed25519Sign(in, inLen, out, outLen, key, type,
395
0
            context, contextLen);
396
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
397
0
            return ret;
398
        /* fall-through when unavailable */
399
0
    }
400
1.64k
#endif
401
402
1.64k
    if (!key->pubKeySet)
403
0
        return BAD_FUNC_ARG;
404
1.64k
    if (!key->privKeySet)
405
0
        return BAD_FUNC_ARG;
406
407
    /* check and set up out length */
408
1.64k
    if (*outLen < ED25519_SIG_SIZE) {
409
0
        *outLen = ED25519_SIG_SIZE;
410
0
        return BUFFER_E;
411
0
    }
412
1.64k
    *outLen = ED25519_SIG_SIZE;
413
414
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
415
    XMEMCPY(orig_k, key->k, ED25519_KEY_SIZE);
416
#endif
417
418
    /* step 1: create nonce to use where nonce is r in
419
       r = H(h_b, ... ,h_2b-1,M) */
420
1.64k
    ret = ed25519_hash(key, key->k, ED25519_KEY_SIZE, az);
421
422
1.64k
    if (ret == 0) {
423
1.60k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
424
1.60k
        wc_Sha512 *sha = &key->sha;
425
#else
426
        wc_Sha512 sha[1];
427
        ret = ed25519_hash_init(key, sha);
428
#endif
429
430
        /* apply clamp */
431
1.60k
        az[0]  &= 248;
432
1.60k
        az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
433
1.60k
        az[31] |= 64;
434
435
1.60k
        if (ret == 0 && (type == Ed25519ctx || type == Ed25519ph)) {
436
0
            ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
437
0
            if (ret == 0)
438
0
                ret = ed25519_hash_update(key, sha, &type, sizeof(type));
439
0
            if (ret == 0)
440
0
                ret = ed25519_hash_update(key, sha, &contextLen,
441
0
                                          sizeof(contextLen));
442
0
            if (ret == 0 && context != NULL)
443
0
                ret = ed25519_hash_update(key, sha, context, contextLen);
444
0
        }
445
1.60k
        if (ret == 0)
446
1.60k
            ret = ed25519_hash_update(key, sha, az + ED25519_KEY_SIZE,
447
1.60k
                                      ED25519_KEY_SIZE);
448
1.60k
        if (ret == 0)
449
1.60k
            ret = ed25519_hash_update(key, sha, in, inLen);
450
1.60k
        if (ret == 0)
451
1.57k
            ret = ed25519_hash_final(key, sha, nonce);
452
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
453
        ed25519_hash_free(key, sha);
454
#endif
455
1.60k
    }
456
457
1.64k
    if (ret == 0) {
458
#ifdef FREESCALE_LTC_ECC
459
        ltcPoint.X = &tempBuf[0];
460
        ltcPoint.Y = &tempBuf[32];
461
        LTC_PKHA_sc_reduce(nonce);
462
        LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce,
463
               ED25519_KEY_SIZE, &ltcPoint,
464
               kLTC_Ed25519 /* result on Ed25519 */);
465
        LTC_PKHA_Ed25519_Compress(&ltcPoint, out);
466
#else
467
1.54k
        sc_reduce(nonce);
468
469
        /* step 2: computing R = rB where rB is the scalar multiplication of
470
           r and B */
471
1.54k
        ge_scalarmult_base(&R,nonce);
472
1.54k
        ge_p3_tobytes(out,&R);
473
1.54k
#endif
474
1.54k
    }
475
476
    /* step 3: hash R + public key + message getting H(R,A,M) then
477
       creating S = (r + H(R,A,M)a) mod l */
478
1.64k
    if (ret == 0) {
479
1.54k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
480
1.54k
        wc_Sha512 *sha = &key->sha;
481
#else
482
        wc_Sha512 sha[1];
483
        ret = ed25519_hash_init(key, sha);
484
#endif
485
486
1.54k
        if (ret == 0 && (type == Ed25519ctx || type == Ed25519ph)) {
487
0
            ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
488
0
            if (ret == 0)
489
0
                ret = ed25519_hash_update(key, sha, &type, sizeof(type));
490
0
            if (ret == 0)
491
0
                ret = ed25519_hash_update(key, sha, &contextLen,
492
0
                                          sizeof(contextLen));
493
0
            if (ret == 0 && context != NULL)
494
0
                ret = ed25519_hash_update(key, sha, context, contextLen);
495
0
        }
496
1.54k
        if (ret == 0)
497
1.54k
            ret = ed25519_hash_update(key, sha, out, ED25519_SIG_SIZE/2);
498
1.54k
        if (ret == 0)
499
1.54k
            ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);
500
1.54k
        if (ret == 0)
501
1.54k
            ret = ed25519_hash_update(key, sha, in, inLen);
502
1.54k
        if (ret == 0)
503
1.52k
            ret = ed25519_hash_final(key, sha, hram);
504
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
505
        ed25519_hash_free(key, sha);
506
#endif
507
1.54k
    }
508
509
1.64k
    if (ret == 0) {
510
#ifdef FREESCALE_LTC_ECC
511
        LTC_PKHA_sc_reduce(hram);
512
        LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
513
#else
514
1.48k
        sc_reduce(hram);
515
1.48k
        sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
516
1.48k
#endif
517
1.48k
    }
518
519
1.64k
    ForceZero(az, sizeof(az));
520
1.64k
    ForceZero(nonce, sizeof(nonce));
521
1.64k
#endif /* WOLFSSL_SE050 */
522
523
#ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN
524
    if (ret == 0) {
525
        int  i;
526
        byte c = 0;
527
        for (i = 0; i < ED25519_KEY_SIZE; i++) {
528
            c |= key->k[i] ^ orig_k[i];
529
        }
530
        ret = ctMaskGT(c, 0) & SIG_VERIFY_E;
531
    }
532
#endif
533
534
1.64k
    return ret;
535
1.64k
}
536
537
/*
538
    in     contains the message to sign
539
    inLen  is the length of the message to sign
540
    out    is the buffer to write the signature
541
    outLen [in/out] input size of out buf
542
                     output gets set as the final length of out
543
    key    is the ed25519 key to use when signing
544
    return 0 on success
545
 */
546
int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out,
547
                        word32 *outLen, ed25519_key* key)
548
1.70k
{
549
1.70k
    return wc_ed25519_sign_msg_ex(in, inLen, out, outLen, key, (byte)Ed25519,
550
1.70k
        NULL, 0);
551
1.70k
}
552
553
/*
554
    in          contains the message to sign
555
    inLen       is the length of the message to sign
556
    out         is the buffer to write the signature
557
    outLen      [in/out] input size of out buf
558
                          output gets set as the final length of out
559
    key         is the ed25519 key to use when signing
560
    context     extra signing data
561
    contextLen  length of extra signing data
562
    return 0 on success
563
 */
564
int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out,
565
                           word32 *outLen, ed25519_key* key,
566
                           const byte* context, byte contextLen)
567
0
{
568
0
    return wc_ed25519_sign_msg_ex(in, inLen, out, outLen, key, Ed25519ctx,
569
0
                                                           context, contextLen);
570
0
}
571
572
/*
573
    hash        contains the SHA-512 hash of the message to sign
574
    hashLen     is the length of the SHA-512 hash of the message to sign
575
    out         is the buffer to write the signature
576
    outLen      [in/out] input size of out buf
577
                          output gets set as the final length of out
578
    key         is the ed25519 key to use when signing
579
    context     extra signing data
580
    contextLen  length of extra signing data
581
    return 0 on success
582
 */
583
int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out,
584
                           word32 *outLen, ed25519_key* key,
585
                           const byte* context, byte contextLen)
586
0
{
587
0
    return wc_ed25519_sign_msg_ex(hash, hashLen, out, outLen, key, Ed25519ph,
588
0
                                                           context, contextLen);
589
0
}
590
591
/*
592
    in          contains the message to sign
593
    inLen       is the length of the message to sign
594
    out         is the buffer to write the signature
595
    outLen      [in/out] input size of out buf
596
                          output gets set as the final length of out
597
    key         is the ed25519 key to use when signing
598
    context     extra signing data
599
    contextLen  length of extra signing data
600
    return 0 on success
601
 */
602
int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
603
                          word32 *outLen, ed25519_key* key,
604
                          const byte* context, byte contextLen)
605
0
{
606
0
    int  ret;
607
0
    byte hash[WC_SHA512_DIGEST_SIZE];
608
609
0
    ret = ed25519_hash(key, in, inLen, hash);
610
0
    if (ret != 0)
611
0
        return ret;
612
613
0
    return wc_ed25519_sign_msg_ex(hash, sizeof(hash), out, outLen, key,
614
0
                                                Ed25519ph, context, contextLen);
615
0
}
616
#endif /* HAVE_ED25519_SIGN */
617
618
#ifdef HAVE_ED25519_VERIFY
619
#ifndef WOLFSSL_SE050
620
621
#ifdef WOLFSSL_CHECK_VER_FAULTS
622
static const byte sha512_empty[] = {
623
    0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd,
624
    0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
625
    0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc,
626
    0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
627
    0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0,
628
    0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
629
    0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81,
630
    0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
631
};
632
633
/* sanity check that hash operation happened
634
 * returns 0 on success */
635
static int ed25519_hash_check(ed25519_key* key, byte* h)
636
{
637
    (void)key; /* passing in key in case other hash algroithms are used */
638
639
    if (XMEMCMP(h, sha512_empty, WC_SHA512_DIGEST_SIZE) != 0) {
640
        return 0;
641
    }
642
    else {
643
        return BAD_STATE_E;
644
    }
645
}
646
#endif
647
648
649
/*
650
   sig        is array of bytes containing the signature
651
   sigLen     is the length of sig byte array
652
   key        Ed25519 public key
653
   return     0 on success
654
   type       variant to use -- Ed25519, Ed25519ctx, or Ed25519ph
655
   context    extra signing data
656
   contextLen length of extra signing data
657
*/
658
static int ed25519_verify_msg_init_with_sha(const byte* sig, word32 sigLen,
659
                                            ed25519_key* key, wc_Sha512 *sha,
660
                                            byte type, const byte* context,
661
                                            byte contextLen)
662
2.82k
{
663
2.82k
    int ret;
664
665
    /* sanity check on arguments */
666
2.82k
    if (sig == NULL || key == NULL ||
667
2.82k
        (context == NULL && contextLen != 0)) {
668
0
        return BAD_FUNC_ARG;
669
0
    }
670
671
    /* check on basics needed to verify signature */
672
2.82k
    if (sigLen != ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224))
673
154
        return BAD_FUNC_ARG;
674
675
    /* find H(R,A,M) and store it as h */
676
677
2.67k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
678
2.67k
    ret = ed25519_hash_reset(key);
679
2.67k
    if (ret != 0)
680
0
        return ret;
681
#else
682
    ret = 0;
683
#endif
684
685
2.67k
    if (type == Ed25519ctx || type == Ed25519ph) {
686
0
        ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
687
0
        if (ret == 0)
688
0
            ret = ed25519_hash_update(key, sha, &type, sizeof(type));
689
0
        if (ret == 0)
690
0
            ret = ed25519_hash_update(key, sha, &contextLen, sizeof(contextLen));
691
0
        if (ret == 0 && context != NULL)
692
0
            ret = ed25519_hash_update(key, sha, context, contextLen);
693
0
    }
694
2.67k
    if (ret == 0)
695
2.67k
        ret = ed25519_hash_update(key, sha, sig, ED25519_SIG_SIZE/2);
696
697
#ifdef WOLFSSL_CHECK_VER_FAULTS
698
    /* sanity check that hash operation happened */
699
    if (ret == 0) {
700
        byte h[WC_MAX_DIGEST_SIZE];
701
702
        ret = wc_Sha512GetHash(sha, h);
703
        if (ret == 0) {
704
            ret = ed25519_hash_check(key, h);
705
            if (ret != 0) {
706
                WOLFSSL_MSG("Unexpected initial state of hash found");
707
            }
708
        }
709
    }
710
#endif
711
712
2.67k
    if (ret == 0)
713
2.67k
        ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);
714
715
2.67k
    return ret;
716
2.67k
}
717
718
/*
719
   msgSegment     an array of bytes containing a message segment
720
   msgSegmentLen  length of msgSegment
721
   key            Ed25519 public key
722
   return         0 on success
723
*/
724
static int ed25519_verify_msg_update_with_sha(const byte* msgSegment,
725
                                              word32 msgSegmentLen,
726
                                              ed25519_key* key,
727
173k
                                              wc_Sha512 *sha) {
728
    /* sanity check on arguments */
729
173k
    if (msgSegment == NULL || key == NULL)
730
32
        return BAD_FUNC_ARG;
731
732
173k
    return ed25519_hash_update(key, sha, msgSegment, msgSegmentLen);
733
173k
}
734
735
/* ed25519 order in little endian. */
736
static const byte ed25519_order[] = {
737
    0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
738
    0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
739
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
741
};
742
743
/*
744
   sig     is array of bytes containing the signature
745
   sigLen  is the length of sig byte array
746
   res     will be 1 on successful verify and 0 on unsuccessful
747
   key     Ed25519 public key
748
   return  0 and res of 1 on success
749
*/
750
static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen,
751
                                             int* res, ed25519_key* key,
752
                                             wc_Sha512 *sha)
753
2.51k
{
754
2.51k
    ALIGN16 byte rcheck[ED25519_KEY_SIZE];
755
2.51k
    ALIGN16 byte h[WC_SHA512_DIGEST_SIZE];
756
2.51k
#ifndef FREESCALE_LTC_ECC
757
2.51k
    ge_p3  A;
758
2.51k
    ge_p2  R;
759
2.51k
#endif
760
2.51k
    int    ret;
761
2.51k
    int    i;
762
763
    /* sanity check on arguments */
764
2.51k
    if (sig == NULL || res == NULL || key == NULL)
765
0
        return BAD_FUNC_ARG;
766
767
    /* set verification failed by default */
768
2.51k
    *res = 0;
769
770
    /* check on basics needed to verify signature */
771
2.51k
    if (sigLen != ED25519_SIG_SIZE)
772
0
        return BAD_FUNC_ARG;
773
    /* S is not larger or equal to the order:
774
     *     2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed
775
     *   = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed
776
     */
777
778
    /* Check S is not larger than or equal to order. */
779
2.87k
    for (i = (int)sizeof(ed25519_order) - 1; i >= 0; i--) {
780
        /* Bigger than order. */
781
2.87k
        if (sig[ED25519_SIG_SIZE/2 + i] > ed25519_order[i])
782
115
            return BAD_FUNC_ARG;
783
        /* Less than order. */
784
2.75k
        if (sig[ED25519_SIG_SIZE/2 + i] < ed25519_order[i])
785
2.40k
            break;
786
2.75k
    }
787
    /* Check equal - all bytes match. */
788
2.40k
    if (i == -1)
789
0
        return BAD_FUNC_ARG;
790
791
    /* uncompress A (public key), test if valid, and negate it */
792
2.40k
#ifndef FREESCALE_LTC_ECC
793
2.40k
    if (ge_frombytes_negate_vartime(&A, key->p) != 0)
794
0
        return BAD_FUNC_ARG;
795
2.40k
#endif
796
797
    /* find H(R,A,M) and store it as h */
798
799
2.40k
    ret = ed25519_hash_final(key, sha, h);
800
2.40k
    if (ret != 0)
801
171
        return ret;
802
803
#ifdef FREESCALE_LTC_ECC
804
    ret = LTC_PKHA_sc_reduce(h);
805
    if (ret != kStatus_Success)
806
        return ret;
807
    ret = LTC_PKHA_SignatureForVerify(rcheck, h, sig + (ED25519_SIG_SIZE/2), key);
808
    if (ret != kStatus_Success)
809
        return ret;
810
#else
811
2.23k
    sc_reduce(h);
812
813
    /*
814
       Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
815
       SB - H(R,A,M)A saving decompression of R
816
    */
817
2.23k
    ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2));
818
2.23k
    if (ret != 0)
819
180
        return ret;
820
821
2.05k
    ge_tobytes_nct(rcheck, &R);
822
2.05k
#endif /* FREESCALE_LTC_ECC */
823
824
    /* comparison of R created to R in sig */
825
2.05k
    ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2);
826
2.05k
    if (ret != 0) {
827
726
        ret = SIG_VERIFY_E;
828
726
    }
829
830
#ifdef WOLFSSL_CHECK_VER_FAULTS
831
    /* redundant comparison as sanity check that first one happened */
832
    if (ret == 0 && ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2) != 0) {
833
        ret = SIG_VERIFY_E;
834
    }
835
#endif
836
837
2.05k
    if (ret == 0) {
838
        /* set the verification status */
839
1.32k
        *res = 1;
840
1.32k
    }
841
842
2.05k
    return ret;
843
2.23k
}
844
#endif /* WOLFSSL_SE050 */
845
846
#if defined(WOLFSSL_ED25519_STREAMING_VERIFY) && !defined(WOLFSSL_SE050)
847
848
int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key,
849
846
                               byte type, const byte* context, byte contextLen) {
850
846
    return ed25519_verify_msg_init_with_sha(sig, sigLen, key, &key->sha,
851
846
                                        type, context, contextLen);
852
846
}
853
854
int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen,
855
172k
                                        ed25519_key* key) {
856
172k
    return ed25519_verify_msg_update_with_sha(msgSegment, msgSegmentLen,
857
172k
                                          key, &key->sha);
858
172k
}
859
860
int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res,
861
729
                                ed25519_key* key) {
862
729
    return ed25519_verify_msg_final_with_sha(sig, sigLen, res,
863
729
                                         key, &key->sha);
864
729
}
865
866
#endif /* WOLFSSL_ED25519_STREAMING_VERIFY && !WOLFSSL_SE050 */
867
868
/*
869
   sig     is array of bytes containing the signature
870
   sigLen  is the length of sig byte array
871
   msg     the array of bytes containing the message
872
   msgLen  length of msg array
873
   res     will be 1 on successful verify and 0 on unsuccessful
874
   key     Ed25519 public key
875
   return  0 and res of 1 on success
876
*/
877
int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg,
878
                              word32 msgLen, int* res, ed25519_key* key,
879
                              byte type, const byte* context, byte contextLen)
880
2.04k
{
881
2.04k
    int ret;
882
#ifdef WOLFSSL_SE050
883
    (void)type;
884
    (void)context;
885
    (void)contextLen;
886
    (void)ed25519Ctx;
887
    ret = se050_ed25519_verify_msg(sig, sigLen, msg, msgLen, key, res);
888
#else
889
2.04k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
890
2.04k
    wc_Sha512 *sha;
891
#else
892
    wc_Sha512 sha[1];
893
#endif
894
895
    /* sanity check on arguments */
896
2.04k
    if (sig == NULL || msg == NULL || res == NULL || key == NULL ||
897
1.98k
                                         (context == NULL && contextLen != 0))
898
65
        return BAD_FUNC_ARG;
899
900
1.98k
#ifdef WOLF_CRYPTO_CB
901
1.98k
    if (key->devId != INVALID_DEVID) {
902
0
        ret = wc_CryptoCb_Ed25519Verify(sig, sigLen, msg, msgLen, res, key,
903
0
            type, context, contextLen);
904
0
        if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
905
0
            return ret;
906
        /* fall-through when unavailable */
907
0
    }
908
1.98k
#endif
909
910
1.98k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
911
1.98k
    sha = &key->sha;
912
#else
913
    ret = ed25519_hash_init(key, sha);
914
    if (ret < 0) {
915
        return ret;
916
    }
917
#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
918
919
1.98k
    ret = ed25519_verify_msg_init_with_sha(sig, sigLen, key, sha, type, context,
920
1.98k
        contextLen);
921
1.98k
    if (ret == 0)
922
1.89k
        ret = ed25519_verify_msg_update_with_sha(msg, msgLen, key, sha);
923
1.98k
    if (ret == 0)
924
1.78k
        ret = ed25519_verify_msg_final_with_sha(sig, sigLen, res, key, sha);
925
926
#ifndef WOLFSSL_ED25519_PERSISTENT_SHA
927
    ed25519_hash_free(key, sha);
928
#endif
929
1.98k
#endif /* WOLFSSL_SE050 */
930
1.98k
    return ret;
931
1.98k
}
932
933
/*
934
   sig     is array of bytes containing the signature
935
   sigLen  is the length of sig byte array
936
   msg     the array of bytes containing the message
937
   msgLen  length of msg array
938
   res     will be 1 on successful verify and 0 on unsuccessful
939
   key     Ed25519 public key
940
   return  0 and res of 1 on success
941
*/
942
int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
943
                          word32 msgLen, int* res, ed25519_key* key)
944
2.04k
{
945
2.04k
    return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key,
946
2.04k
                                    (byte)Ed25519, NULL, 0);
947
2.04k
}
948
949
/*
950
   sig         is array of bytes containing the signature
951
   sigLen      is the length of sig byte array
952
   msg         the array of bytes containing the message
953
   msgLen      length of msg array
954
   res         will be 1 on successful verify and 0 on unsuccessful
955
   key         Ed25519 public key
956
   context     extra signing data
957
   contextLen  length of extra signing data
958
   return  0 and res of 1 on success
959
*/
960
int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
961
                             word32 msgLen, int* res, ed25519_key* key,
962
                             const byte* context, byte contextLen)
963
0
{
964
0
    return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key,
965
0
                                    Ed25519ctx, context, contextLen);
966
0
}
967
968
/*
969
   sig         is array of bytes containing the signature
970
   sigLen      is the length of sig byte array
971
   hash        the array of bytes containing the SHA-512 hash of the message
972
   hashLen     length of hash array
973
   res         will be 1 on successful verify and 0 on unsuccessful
974
   key         Ed25519 public key
975
   context     extra signing data
976
   contextLen  length of extra signing data
977
   return  0 and res of 1 on success
978
*/
979
int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash,
980
                             word32 hashLen, int* res, ed25519_key* key,
981
                             const byte* context, byte contextLen)
982
0
{
983
0
    return wc_ed25519_verify_msg_ex(sig, sigLen, hash, hashLen, res, key,
984
0
                                    Ed25519ph, context, contextLen);
985
0
}
986
987
/*
988
   sig         is array of bytes containing the signature
989
   sigLen      is the length of sig byte array
990
   msg         the array of bytes containing the message
991
   msgLen      length of msg array
992
   res         will be 1 on successful verify and 0 on unsuccessful
993
   key         Ed25519 public key
994
   context     extra signing data
995
   contextLen  length of extra signing data
996
   return  0 and res of 1 on success
997
*/
998
int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
999
                            word32 msgLen, int* res, ed25519_key* key,
1000
                            const byte* context, byte contextLen)
1001
0
{
1002
0
    int  ret;
1003
0
    byte hash[WC_SHA512_DIGEST_SIZE];
1004
1005
0
    ret = ed25519_hash(key, msg, msgLen, hash);
1006
0
    if (ret != 0)
1007
0
        return ret;
1008
1009
0
    return wc_ed25519_verify_msg_ex(sig, sigLen, hash, sizeof(hash), res, key,
1010
0
                                    Ed25519ph, context, contextLen);
1011
0
}
1012
#endif /* HAVE_ED25519_VERIFY */
1013
1014
#ifndef WC_NO_CONSTRUCTORS
1015
ed25519_key* wc_ed25519_new(void* heap, int devId, int *result_code)
1016
0
{
1017
0
    int ret;
1018
0
    ed25519_key* key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap,
1019
0
                        DYNAMIC_TYPE_ED25519);
1020
0
    if (key == NULL) {
1021
0
        ret = MEMORY_E;
1022
0
    }
1023
0
    else {
1024
0
        ret = wc_ed25519_init_ex(key, heap, devId);
1025
0
        if (ret != 0) {
1026
0
            XFREE(key, heap, DYNAMIC_TYPE_ED25519);
1027
0
            key = NULL;
1028
0
        }
1029
0
    }
1030
1031
0
    if (result_code != NULL)
1032
0
        *result_code = ret;
1033
1034
0
    return key;
1035
0
}
1036
1037
0
int wc_ed25519_delete(ed25519_key* key, ed25519_key** key_p) {
1038
0
    if (key == NULL)
1039
0
        return BAD_FUNC_ARG;
1040
0
    wc_ed25519_free(key);
1041
0
    XFREE(key, key->heap, DYNAMIC_TYPE_ED25519);
1042
0
    if (key_p != NULL)
1043
0
        *key_p = NULL;
1044
0
    return 0;
1045
0
}
1046
#endif /* !WC_NO_CONSTRUCTORS */
1047
1048
/* initialize information and memory for key */
1049
int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId)
1050
6.24k
{
1051
6.24k
    if (key == NULL)
1052
0
        return BAD_FUNC_ARG;
1053
1054
    /* for init, ensure the key is zeroed*/
1055
6.24k
    XMEMSET(key, 0, sizeof(ed25519_key));
1056
1057
6.24k
#ifdef WOLF_CRYPTO_CB
1058
6.24k
    key->devId = devId;
1059
#else
1060
    (void)devId;
1061
#endif
1062
6.24k
    key->heap = heap;
1063
1064
6.24k
#ifndef FREESCALE_LTC_ECC
1065
6.24k
    fe_init();
1066
6.24k
#endif
1067
1068
#ifdef WOLFSSL_CHECK_MEM_ZERO
1069
    wc_MemZero_Add("wc_ed25519_init_ex key->k", &key->k, sizeof(key->k));
1070
#endif
1071
1072
6.24k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
1073
6.24k
    return ed25519_hash_init(key, &key->sha);
1074
#else /* !WOLFSSL_ED25519_PERSISTENT_SHA */
1075
    return 0;
1076
#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
1077
6.24k
}
1078
1079
int wc_ed25519_init(ed25519_key* key)
1080
6.24k
{
1081
6.24k
    return wc_ed25519_init_ex(key, NULL, INVALID_DEVID);
1082
6.24k
}
1083
1084
/* clear memory of key */
1085
void wc_ed25519_free(ed25519_key* key)
1086
6.24k
{
1087
6.24k
    if (key == NULL)
1088
0
        return;
1089
1090
6.24k
#ifdef WOLFSSL_ED25519_PERSISTENT_SHA
1091
6.24k
    ed25519_hash_free(key, &key->sha);
1092
6.24k
#endif
1093
1094
#ifdef WOLFSSL_SE050
1095
#ifdef WOLFSSL_SE050_AUTO_ERASE
1096
    wc_se050_erase_object(key->keyId);
1097
#endif
1098
    se050_ed25519_free_key(key);
1099
#endif
1100
1101
6.24k
    ForceZero(key, sizeof(ed25519_key));
1102
#ifdef WOLFSSL_CHECK_MEM_ZERO
1103
    wc_MemZero_Check(key, sizeof(ed25519_key));
1104
#endif
1105
6.24k
}
1106
1107
1108
#ifdef HAVE_ED25519_KEY_EXPORT
1109
1110
/*
1111
    outLen should contain the size of out buffer when input. outLen is than set
1112
    to the final output length.
1113
    returns 0 on success
1114
 */
1115
int wc_ed25519_export_public(const ed25519_key* key, byte* out, word32* outLen)
1116
287
{
1117
    /* sanity check on arguments */
1118
287
    if (key == NULL || out == NULL || outLen == NULL)
1119
118
        return BAD_FUNC_ARG;
1120
1121
169
    if (*outLen < ED25519_PUB_KEY_SIZE) {
1122
20
        *outLen = ED25519_PUB_KEY_SIZE;
1123
20
        return BUFFER_E;
1124
20
    }
1125
1126
149
    if (!key->pubKeySet)
1127
0
        return PUBLIC_KEY_E;
1128
1129
149
    *outLen = ED25519_PUB_KEY_SIZE;
1130
149
    XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE);
1131
1132
149
    return 0;
1133
149
}
1134
1135
#endif /* HAVE_ED25519_KEY_EXPORT */
1136
1137
1138
#ifdef HAVE_ED25519_KEY_IMPORT
1139
/*
1140
    Imports a compressed/uncompressed public key.
1141
    in       the byte array containing the public key
1142
    inLen    the length of the byte array being passed in
1143
    key      ed25519 key struct to put the public key in
1144
    trusted  whether the public key is trusted to match private key if set
1145
 */
1146
int wc_ed25519_import_public_ex(const byte* in, word32 inLen, ed25519_key* key,
1147
    int trusted)
1148
3.24k
{
1149
3.24k
    int ret = 0;
1150
1151
    /* sanity check on arguments */
1152
3.24k
    if (in == NULL || key == NULL)
1153
0
        return BAD_FUNC_ARG;
1154
1155
3.24k
    if (inLen < ED25519_PUB_KEY_SIZE)
1156
9
        return BAD_FUNC_ARG;
1157
1158
    /* compressed prefix according to draft
1159
       http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
1160
3.23k
    if (in[0] == 0x40 && inLen == ED25519_PUB_KEY_SIZE + 1) {
1161
        /* key is stored in compressed format so just copy in */
1162
1
        XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE);
1163
#ifdef FREESCALE_LTC_ECC
1164
        /* recover X coordinate */
1165
        ltc_pkha_ecc_point_t pubKey;
1166
        pubKey.X = key->pointX;
1167
        pubKey.Y = key->pointY;
1168
        LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
1169
#endif
1170
1
    }
1171
    /* importing uncompressed public key */
1172
3.23k
    else if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) {
1173
#ifdef FREESCALE_LTC_ECC
1174
        /* reverse bytes for little endian byte order */
1175
        for (int i = 0; i < ED25519_KEY_SIZE; i++)
1176
        {
1177
            key->pointX[i] = *(in + ED25519_KEY_SIZE - i);
1178
            key->pointY[i] = *(in + 2*ED25519_KEY_SIZE - i);
1179
        }
1180
        XMEMCPY(key->p, key->pointY, ED25519_KEY_SIZE);
1181
#else
1182
        /* pass in (x,y) and store compressed key */
1183
28
        ret = ge_compress_key(key->p, in+1,
1184
28
                              in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE);
1185
28
#endif /* FREESCALE_LTC_ECC */
1186
28
    }
1187
    /* if not specified compressed or uncompressed check key size
1188
       if key size is equal to compressed key size copy in key */
1189
3.20k
    else if (inLen == ED25519_PUB_KEY_SIZE) {
1190
3.19k
        XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE);
1191
#ifdef FREESCALE_LTC_ECC
1192
        /* recover X coordinate */
1193
        ltc_pkha_ecc_point_t pubKey;
1194
        pubKey.X = key->pointX;
1195
        pubKey.Y = key->pointY;
1196
        LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
1197
#endif
1198
3.19k
    }
1199
17
    else {
1200
17
        ret = BAD_FUNC_ARG;
1201
17
    }
1202
1203
3.23k
    if (ret == 0) {
1204
3.22k
        key->pubKeySet = 1;
1205
3.22k
        if (!trusted) {
1206
3.22k
            ret = wc_ed25519_check_key(key);
1207
3.22k
        }
1208
3.22k
    }
1209
3.23k
    if (ret != 0) {
1210
172
        key->pubKeySet = 0;
1211
172
    }
1212
1213
    /* bad public key format */
1214
3.23k
    return ret;
1215
3.24k
}
1216
1217
/*
1218
    Imports a compressed/uncompressed public key.
1219
    in    the byte array containing the public key
1220
    inLen the length of the byte array being passed in
1221
    key   ed25519 key struct to put the public key in
1222
 */
1223
int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
1224
3.24k
{
1225
3.24k
    return wc_ed25519_import_public_ex(in, inLen, key, 0);
1226
3.24k
}
1227
1228
/*
1229
    For importing a private key.
1230
 */
1231
int wc_ed25519_import_private_only(const byte* priv, word32 privSz,
1232
                                                               ed25519_key* key)
1233
2.05k
{
1234
2.05k
    int ret = 0;
1235
1236
    /* sanity check on arguments */
1237
2.05k
    if (priv == NULL || key == NULL)
1238
0
        return BAD_FUNC_ARG;
1239
1240
    /* key size check */
1241
2.05k
    if (privSz != ED25519_KEY_SIZE)
1242
21
        return BAD_FUNC_ARG;
1243
1244
2.03k
    XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
1245
2.03k
    key->privKeySet = 1;
1246
1247
2.03k
    if (key->pubKeySet) {
1248
        /* Validate loaded public key */
1249
0
        ret = wc_ed25519_check_key(key);
1250
0
    }
1251
2.03k
    if (ret != 0) {
1252
0
        key->privKeySet = 0;
1253
0
        ForceZero(key->k, ED25519_KEY_SIZE);
1254
0
    }
1255
1256
2.03k
    return ret;
1257
2.05k
}
1258
1259
1260
/* Import an ed25519 private and public keys from byte array(s).
1261
 *
1262
 * priv     [in]  Array holding private key from
1263
 *                wc_ed25519_export_private_only(), or private+public keys from
1264
 *                wc_ed25519_export_private().
1265
 * privSz   [in]  Number of bytes of data in private key array.
1266
 * pub      [in]  Array holding public key (or NULL).
1267
 * pubSz    [in]  Number of bytes of data in public key array (or 0).
1268
 * key      [in]  Ed25519 private/public key.
1269
 * trusted  [in]  Indicates whether the public key data is trusted.
1270
 *                When 0, checks public key matches private key.
1271
 *                When 1, doesn't check public key matches private key.
1272
 * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid
1273
 *         combination of keys/lengths is supplied, 0 otherwise.
1274
 */
1275
int wc_ed25519_import_private_key_ex(const byte* priv, word32 privSz,
1276
    const byte* pub, word32 pubSz, ed25519_key* key, int trusted)
1277
0
{
1278
0
    int ret;
1279
1280
    /* sanity check on arguments */
1281
0
    if (priv == NULL || key == NULL)
1282
0
        return BAD_FUNC_ARG;
1283
1284
    /* key size check */
1285
0
    if (privSz != ED25519_KEY_SIZE && privSz != ED25519_PRV_KEY_SIZE)
1286
0
        return BAD_FUNC_ARG;
1287
1288
0
    if (pub == NULL) {
1289
0
        if (pubSz != 0)
1290
0
            return BAD_FUNC_ARG;
1291
0
        if (privSz != ED25519_PRV_KEY_SIZE)
1292
0
            return BAD_FUNC_ARG;
1293
0
        pub = priv + ED25519_KEY_SIZE;
1294
0
        pubSz = ED25519_PUB_KEY_SIZE;
1295
0
    }
1296
0
    else if (pubSz < ED25519_PUB_KEY_SIZE) {
1297
0
        return BAD_FUNC_ARG;
1298
0
    }
1299
1300
0
    XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
1301
0
    key->privKeySet = 1;
1302
1303
    /* import public key */
1304
0
    ret = wc_ed25519_import_public_ex(pub, pubSz, key, trusted);
1305
0
    if (ret != 0) {
1306
0
        key->privKeySet = 0;
1307
0
        ForceZero(key->k, ED25519_KEY_SIZE);
1308
0
        return ret;
1309
0
    }
1310
1311
    /* make the private key (priv + pub) */
1312
0
    XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
1313
1314
0
    return ret;
1315
0
}
1316
1317
/* Import an ed25519 private and public keys from byte array(s).
1318
 *
1319
 * priv    [in]  Array holding private key from wc_ed25519_export_private_only(),
1320
 *               or private+public keys from wc_ed25519_export_private().
1321
 * privSz  [in]  Number of bytes of data in private key array.
1322
 * pub     [in]  Array holding public key (or NULL).
1323
 * pubSz   [in]  Number of bytes of data in public key array (or 0).
1324
 * key     [in]  Ed25519 private/public key.
1325
 * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid
1326
 *         combination of keys/lengths is supplied, 0 otherwise.
1327
 */
1328
int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
1329
    const byte* pub, word32 pubSz, ed25519_key* key)
1330
0
{
1331
0
    return wc_ed25519_import_private_key_ex(priv, privSz, pub, pubSz, key, 0);
1332
0
}
1333
#endif /* HAVE_ED25519_KEY_IMPORT */
1334
1335
1336
#ifdef HAVE_ED25519_KEY_EXPORT
1337
1338
/*
1339
 export private key only (secret part so 32 bytes)
1340
 outLen should contain the size of out buffer when input. outLen is than set
1341
 to the final output length.
1342
 returns 0 on success
1343
 */
1344
int wc_ed25519_export_private_only(const ed25519_key* key, byte* out, word32* outLen)
1345
471
{
1346
    /* sanity checks on arguments */
1347
471
    if (key == NULL || out == NULL || outLen == NULL)
1348
121
        return BAD_FUNC_ARG;
1349
1350
350
    if (*outLen < ED25519_KEY_SIZE) {
1351
24
        *outLen = ED25519_KEY_SIZE;
1352
24
        return BUFFER_E;
1353
24
    }
1354
1355
326
    *outLen = ED25519_KEY_SIZE;
1356
326
    XMEMCPY(out, key->k, ED25519_KEY_SIZE);
1357
1358
326
    return 0;
1359
350
}
1360
1361
/*
1362
 export private key, including public part
1363
 outLen should contain the size of out buffer when input. outLen is than set
1364
 to the final output length.
1365
 returns 0 on success
1366
 */
1367
int wc_ed25519_export_private(const ed25519_key* key, byte* out, word32* outLen)
1368
0
{
1369
    /* sanity checks on arguments */
1370
0
    if (key == NULL || !key->privKeySet || out == NULL || outLen == NULL)
1371
0
        return BAD_FUNC_ARG;
1372
1373
0
    if (*outLen < ED25519_PRV_KEY_SIZE) {
1374
0
        *outLen = ED25519_PRV_KEY_SIZE;
1375
0
        return BUFFER_E;
1376
0
    }
1377
1378
0
    *outLen = ED25519_PRV_KEY_SIZE;
1379
0
    XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE);
1380
1381
0
    return 0;
1382
0
}
1383
1384
/* export full private key and public key
1385
   return 0 on success
1386
 */
1387
int wc_ed25519_export_key(const ed25519_key* key,
1388
                          byte* priv, word32 *privSz,
1389
                          byte* pub, word32 *pubSz)
1390
0
{
1391
0
    int ret;
1392
1393
    /* export 'full' private part */
1394
0
    ret = wc_ed25519_export_private(key, priv, privSz);
1395
0
    if (ret != 0)
1396
0
        return ret;
1397
1398
    /* export public part */
1399
0
    ret = wc_ed25519_export_public(key, pub, pubSz);
1400
0
    if (ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E))
1401
0
        ret = 0; /* ignore no public key */
1402
1403
0
    return ret;
1404
0
}
1405
1406
#endif /* HAVE_ED25519_KEY_EXPORT */
1407
1408
/* Check the public key is valid.
1409
 *
1410
 * When private key available, check the calculated public key matches.
1411
 * When no private key, check Y is in range and an X is able to be calculated.
1412
 *
1413
 * @param [in] key  Ed25519 private/public key.
1414
 * @return  0 otherwise.
1415
 * @return  BAD_FUNC_ARG when key is NULL.
1416
 * @return  PUBLIC_KEY_E when the public key is not set, doesn't match or is
1417
 *          invalid.
1418
 * @return  other -ve value on hash failure.
1419
 */
1420
int wc_ed25519_check_key(ed25519_key* key)
1421
3.69k
{
1422
3.69k
    int ret = 0;
1423
1424
    /* Validate parameter. */
1425
3.69k
    if (key == NULL) {
1426
0
        ret = BAD_FUNC_ARG;
1427
0
    }
1428
1429
    /* Check we have a public key to check. */
1430
3.69k
    if ((ret == 0) && (!key->pubKeySet)) {
1431
0
        ret = PUBLIC_KEY_E;
1432
0
    }
1433
1434
3.69k
#ifdef HAVE_ED25519_MAKE_KEY
1435
    /* If we have a private key just make the public key and compare. */
1436
3.69k
    if ((ret == 0) && (key->privKeySet)) {
1437
471
        ALIGN16 unsigned char pubKey[ED25519_PUB_KEY_SIZE];
1438
1439
471
        ret = wc_ed25519_make_public(key, pubKey, sizeof(pubKey));
1440
471
        if (ret == 0 && XMEMCMP(pubKey, key->p, ED25519_PUB_KEY_SIZE) != 0)
1441
0
            ret = PUBLIC_KEY_E;
1442
471
    }
1443
#else
1444
    (void)key;
1445
#endif /* HAVE_ED25519_MAKE_KEY */
1446
1447
    /* No private key (or ability to make a public key), check Y is valid. */
1448
3.69k
    if ((ret == 0)
1449
3.54k
#ifdef HAVE_ED25519_MAKE_KEY
1450
3.54k
        && (!key->privKeySet)
1451
3.69k
#endif
1452
3.69k
        ) {
1453
        /* Verify that Q is not identity element 0.
1454
         * 0 has no representation for Ed25519. */
1455
1456
        /* Verify that xQ and yQ are integers in the interval [0, p - 1].
1457
         * Only have yQ so check that ordinate. p = 2^255 - 19 */
1458
3.22k
        if ((key->p[ED25519_PUB_KEY_SIZE - 1] & 0x7f) == 0x7f) {
1459
172
            int i;
1460
1461
172
            ret = PUBLIC_KEY_E;
1462
            /* Check up to last byte. */
1463
1.31k
            for (i = ED25519_PUB_KEY_SIZE - 2; i > 0; i--) {
1464
1.29k
                if (key->p[i] != 0xff) {
1465
159
                    ret = 0;
1466
159
                    break;
1467
159
                }
1468
1.29k
            }
1469
            /* Bits are all one up to last byte - check less than -19. */
1470
172
            if ((ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E)) && (key->p[0] < 0xed)) {
1471
11
                ret = 0;
1472
11
            }
1473
172
        }
1474
1475
3.22k
        if (ret == 0) {
1476
            /* Verify that Q is on the curve.
1477
             * Uncompressing the public key will validate yQ. */
1478
3.21k
            ge_p3 A;
1479
1480
3.21k
            if (ge_frombytes_negate_vartime(&A, key->p) != 0) {
1481
153
                ret = PUBLIC_KEY_E;
1482
153
            }
1483
3.21k
        }
1484
3.22k
    }
1485
1486
3.69k
    return ret;
1487
3.69k
}
1488
1489
/* returns the private key size (secret only) in bytes */
1490
int wc_ed25519_size(const ed25519_key* key)
1491
0
{
1492
0
    if (key == NULL)
1493
0
        return BAD_FUNC_ARG;
1494
1495
0
    return ED25519_KEY_SIZE;
1496
0
}
1497
1498
/* returns the private key size (secret + public) in bytes */
1499
int wc_ed25519_priv_size(const ed25519_key* key)
1500
0
{
1501
0
    if (key == NULL)
1502
0
        return BAD_FUNC_ARG;
1503
1504
0
    return ED25519_PRV_KEY_SIZE;
1505
0
}
1506
1507
/* returns the compressed key size in bytes (public key) */
1508
int wc_ed25519_pub_size(const ed25519_key* key)
1509
0
{
1510
0
    if (key == NULL)
1511
0
        return BAD_FUNC_ARG;
1512
1513
0
    return ED25519_PUB_KEY_SIZE;
1514
0
}
1515
1516
/* returns the size of signature in bytes */
1517
int wc_ed25519_sig_size(const ed25519_key* key)
1518
0
{
1519
0
    if (key == NULL)
1520
0
        return BAD_FUNC_ARG;
1521
1522
0
    return ED25519_SIG_SIZE;
1523
0
}
1524
1525
#endif /* HAVE_ED25519 */