Coverage Report

Created: 2025-11-16 07:15

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