Coverage Report

Created: 2026-01-06 06:52

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