1 /* ed25519.c
2  *
3  * Copyright (C) 2006-2021 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 2 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 #ifdef HAVE_CONFIG_H
26     #include <config.h>
27 #endif
28 
29 /* in case user set HAVE_ED25519 there */
30 #include <wolfssl/wolfcrypt/settings.h>
31 
32 #ifdef HAVE_ED25519
33 
34 #include <wolfssl/wolfcrypt/ed25519.h>
35 #include <wolfssl/wolfcrypt/error-crypt.h>
36 #include <wolfssl/wolfcrypt/hash.h>
37 #ifdef NO_INLINE
38     #include <wolfssl/wolfcrypt/misc.h>
39 #else
40     #define WOLFSSL_MISC_INCLUDED
41     #include <wolfcrypt/src/misc.c>
42 #endif
43 
44 #ifdef FREESCALE_LTC_ECC
45     #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
46 #endif
47 #ifdef WOLFSSL_SE050
48     #include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
49 #endif
50 
51 #ifdef WOLF_CRYPTO_CB
52     #include <wolfssl/wolfcrypt/cryptocb.h>
53 #endif
54 
55 #if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_VERIFY)
56 #define ED25519CTX_SIZE    32
57 
58 static const byte ed25519Ctx[ED25519CTX_SIZE+1] =
59                                              "SigEd25519 no Ed25519 collisions";
60 #endif
61 
ed25519_hash_init(ed25519_key * key,wc_Sha512 * sha)62 static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha)
63 {
64     int ret;
65 
66     ret = wc_InitSha512_ex(sha, key->heap,
67 #if defined(WOLF_CRYPTO_CB)
68                            key->devId
69 #else
70                            INVALID_DEVID
71 #endif
72         );
73 
74 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
75     if (ret == 0)
76         key->sha_clean_flag = 1;
77 #endif
78 
79     return ret;
80 }
81 
82 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
ed25519_hash_reset(ed25519_key * key)83 static int ed25519_hash_reset(ed25519_key* key)
84 {
85     int ret;
86     if (key->sha_clean_flag)
87         ret = 0;
88     else {
89         wc_Sha512Free(&key->sha);
90         ret = wc_InitSha512_ex(&key->sha, key->heap,
91 #if defined(WOLF_CRYPTO_CB)
92                                key->devId
93 #else
94                                INVALID_DEVID
95 #endif
96             );
97         if (ret == 0)
98             key->sha_clean_flag = 1;
99     }
100     return ret;
101 }
102 #endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
103 
ed25519_hash_update(ed25519_key * key,wc_Sha512 * sha,const byte * data,word32 len)104 static int ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha,
105                                const byte* data, word32 len)
106 {
107 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
108     if (key->sha_clean_flag)
109         key->sha_clean_flag = 0;
110 #else
111     (void)key;
112 #endif
113     return wc_Sha512Update(sha, data, len);
114 }
115 
ed25519_hash_final(ed25519_key * key,wc_Sha512 * sha,byte * hash)116 static int ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash)
117 {
118     int ret = wc_Sha512Final(sha, hash);
119 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
120     if (ret == 0)
121         key->sha_clean_flag = 1;
122 #else
123     (void)key;
124 #endif
125     return ret;
126 }
127 
ed25519_hash_free(ed25519_key * key,wc_Sha512 * sha)128 static void ed25519_hash_free(ed25519_key* key, wc_Sha512 *sha)
129 {
130     wc_Sha512Free(sha);
131 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
132     key->sha_clean_flag = 0;
133 #else
134     (void)key;
135 #endif
136 }
137 
138 
ed25519_hash(ed25519_key * key,const byte * in,word32 inLen,byte * hash)139 static int ed25519_hash(ed25519_key* key, const byte* in, word32 inLen,
140     byte* hash)
141 {
142     int ret;
143 #ifndef WOLFSSL_ED25519_PERSISTENT_SHA
144     wc_Sha512 sha[1];
145 #else
146     wc_Sha512 *sha;
147 #endif
148 
149     if (key == NULL || (in == NULL && inLen > 0) || hash == NULL) {
150         return BAD_FUNC_ARG;
151     }
152 
153 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
154     sha = &key->sha;
155     ret = ed25519_hash_reset(key);
156 #else
157     ret = ed25519_hash_init(key, sha);
158 #endif
159     if (ret < 0)
160         return ret;
161 
162     ret = ed25519_hash_update(key, sha, in, inLen);
163     if (ret == 0)
164         ret = ed25519_hash_final(key, sha, hash);
165 
166 #ifndef WOLFSSL_ED25519_PERSISTENT_SHA
167     ed25519_hash_free(key, sha);
168 #endif
169 
170     return ret;
171 }
172 
wc_ed25519_make_public(ed25519_key * key,unsigned char * pubKey,word32 pubKeySz)173 int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey,
174                            word32 pubKeySz)
175 {
176     int   ret = 0;
177     byte  az[ED25519_PRV_KEY_SIZE];
178 #if !defined(FREESCALE_LTC_ECC)
179     ge_p3 A;
180 #endif
181 
182     if (key == NULL || pubKey == NULL || pubKeySz != ED25519_PUB_KEY_SIZE)
183         ret = BAD_FUNC_ARG;
184 
185     if (ret == 0)
186         ret = ed25519_hash(key, key->k, ED25519_KEY_SIZE, az);
187     if (ret == 0) {
188         /* apply clamp */
189         az[0]  &= 248;
190         az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
191         az[31] |= 64;
192 
193     #ifdef FREESCALE_LTC_ECC
194         ltc_pkha_ecc_point_t publicKey = {0};
195         publicKey.X = key->pointX;
196         publicKey.Y = key->pointY;
197         LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), az,
198             ED25519_KEY_SIZE, &publicKey, kLTC_Ed25519 /* result on Ed25519 */);
199         LTC_PKHA_Ed25519_Compress(&publicKey, pubKey);
200     #else
201         ge_scalarmult_base(&A, az);
202         ge_p3_tobytes(pubKey, &A);
203     #endif
204     }
205 
206     return ret;
207 }
208 
209 /* generate an ed25519 key pair.
210  * returns 0 on success
211  */
wc_ed25519_make_key(WC_RNG * rng,int keySz,ed25519_key * key)212 int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key)
213 {
214     int ret;
215 
216     if (rng == NULL || key == NULL)
217         return BAD_FUNC_ARG;
218 
219     /* ed25519 has 32 byte key sizes */
220     if (keySz != ED25519_KEY_SIZE)
221         return BAD_FUNC_ARG;
222 
223 #ifdef WOLF_CRYPTO_CB
224     if (key->devId != INVALID_DEVID) {
225         ret = wc_CryptoCb_Ed25519Gen(rng, keySz, key);
226         if (ret != CRYPTOCB_UNAVAILABLE)
227             return ret;
228         /* fall-through when unavailable */
229     }
230 #endif
231 
232     ret  = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE);
233     if (ret != 0)
234         return ret;
235 
236     ret = wc_ed25519_make_public(key, key->p, ED25519_PUB_KEY_SIZE);
237     if (ret != 0) {
238         ForceZero(key->k, ED25519_KEY_SIZE);
239         return ret;
240     }
241 
242     /* put public key after private key, on the same buffer */
243     XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
244 
245     key->pubKeySet = 1;
246 
247     return ret;
248 }
249 
250 
251 #ifdef HAVE_ED25519_SIGN
252 /*
253     in          contains the message to sign
254     inLen       is the length of the message to sign
255     out         is the buffer to write the signature
256     outLen      [in/out] input size of out buf
257                           output gets set as the final length of out
258     key         is the ed25519 key to use when signing
259     type        one of Ed25519, Ed25519ctx or Ed25519ph
260     context     extra signing data
261     contextLen  length of extra signing data
262     return 0 on success
263  */
wc_ed25519_sign_msg_ex(const byte * in,word32 inLen,byte * out,word32 * outLen,ed25519_key * key,byte type,const byte * context,byte contextLen)264 int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out,
265                             word32 *outLen, ed25519_key* key, byte type,
266                             const byte* context, byte contextLen)
267 {
268     int    ret;
269 #ifdef WOLFSSL_SE050
270     (void)context;
271     (void)contextLen;
272     (void)type;
273     ret = se050_ed25519_sign_msg(in, inLen, out, outLen, key);
274 #else
275 #ifdef FREESCALE_LTC_ECC
276     byte   tempBuf[ED25519_PRV_KEY_SIZE];
277     ltc_pkha_ecc_point_t ltcPoint = {0};
278 #else
279     ge_p3  R;
280 #endif
281     byte   nonce[WC_SHA512_DIGEST_SIZE];
282     byte   hram[WC_SHA512_DIGEST_SIZE];
283     byte   az[ED25519_PRV_KEY_SIZE];
284 
285     /* sanity check on arguments */
286     if (in == NULL || out == NULL || outLen == NULL || key == NULL ||
287                                          (context == NULL && contextLen != 0)) {
288         return BAD_FUNC_ARG;
289     }
290 
291 #ifdef WOLF_CRYPTO_CB
292     if (key->devId != INVALID_DEVID) {
293         ret = wc_CryptoCb_Ed25519Sign(in, inLen, out, outLen, key, type,
294             context, contextLen);
295         if (ret != CRYPTOCB_UNAVAILABLE)
296             return ret;
297         /* fall-through when unavailable */
298     }
299 #endif
300 
301     if (!key->pubKeySet)
302         return BAD_FUNC_ARG;
303 
304     /* check and set up out length */
305     if (*outLen < ED25519_SIG_SIZE) {
306         *outLen = ED25519_SIG_SIZE;
307         return BUFFER_E;
308     }
309     *outLen = ED25519_SIG_SIZE;
310 
311     /* step 1: create nonce to use where nonce is r in
312        r = H(h_b, ... ,h_2b-1,M) */
313     ret = ed25519_hash(key, key->k, ED25519_KEY_SIZE, az);
314     if (ret != 0)
315         return ret;
316 
317     /* apply clamp */
318     az[0]  &= 248;
319     az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */
320     az[31] |= 64;
321 
322     {
323 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
324         wc_Sha512 *sha = &key->sha;
325 #else
326         wc_Sha512 sha[1];
327         ret = ed25519_hash_init(key, sha);
328         if (ret < 0)
329             return ret;
330 #endif
331 
332         if (type == Ed25519ctx || type == Ed25519ph) {
333             ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
334             if (ret == 0)
335                 ret = ed25519_hash_update(key, sha, &type, sizeof(type));
336             if (ret == 0)
337                 ret = ed25519_hash_update(key, sha, &contextLen,
338                                           sizeof(contextLen));
339             if (ret == 0 && context != NULL)
340                 ret = ed25519_hash_update(key, sha, context, contextLen);
341         }
342         if (ret == 0)
343             ret = ed25519_hash_update(key, sha, az + ED25519_KEY_SIZE,
344                                       ED25519_KEY_SIZE);
345         if (ret == 0)
346             ret = ed25519_hash_update(key, sha, in, inLen);
347         if (ret == 0)
348             ret = ed25519_hash_final(key, sha, nonce);
349 #ifndef WOLFSSL_ED25519_PERSISTENT_SHA
350         ed25519_hash_free(key, sha);
351 #endif
352     }
353 
354     if (ret != 0)
355         return ret;
356 
357 #ifdef FREESCALE_LTC_ECC
358     ltcPoint.X = &tempBuf[0];
359     ltcPoint.Y = &tempBuf[32];
360     LTC_PKHA_sc_reduce(nonce);
361     LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce,
362            ED25519_KEY_SIZE, &ltcPoint, kLTC_Ed25519 /* result on Ed25519 */);
363     LTC_PKHA_Ed25519_Compress(&ltcPoint, out);
364 #else
365     sc_reduce(nonce);
366 
367     /* step 2: computing R = rB where rB is the scalar multiplication of
368        r and B */
369     ge_scalarmult_base(&R,nonce);
370     ge_p3_tobytes(out,&R);
371 #endif
372 
373     /* step 3: hash R + public key + message getting H(R,A,M) then
374        creating S = (r + H(R,A,M)a) mod l */
375     {
376 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
377         wc_Sha512 *sha = &key->sha;
378 #else
379         wc_Sha512 sha[1];
380         ret = ed25519_hash_init(key, sha);
381         if (ret < 0)
382             return ret;
383 #endif
384 
385         if (type == Ed25519ctx || type == Ed25519ph) {
386             ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
387             if (ret == 0)
388                 ret = ed25519_hash_update(key, sha, &type, sizeof(type));
389             if (ret == 0)
390                 ret = ed25519_hash_update(key, sha, &contextLen,
391                                           sizeof(contextLen));
392             if (ret == 0 && context != NULL)
393                 ret = ed25519_hash_update(key, sha, context, contextLen);
394         }
395         if (ret == 0)
396             ret = ed25519_hash_update(key, sha, out, ED25519_SIG_SIZE/2);
397         if (ret == 0)
398             ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);
399         if (ret == 0)
400             ret = ed25519_hash_update(key, sha, in, inLen);
401         if (ret == 0)
402             ret = ed25519_hash_final(key, sha, hram);
403 #ifndef WOLFSSL_ED25519_PERSISTENT_SHA
404         ed25519_hash_free(key, sha);
405 #endif
406     }
407 
408     if (ret != 0)
409         return ret;
410 
411 #ifdef FREESCALE_LTC_ECC
412     LTC_PKHA_sc_reduce(hram);
413     LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
414 #else
415     sc_reduce(hram);
416     sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce);
417 #endif
418 #endif /* WOLFSSL_SE050 */
419     return ret;
420 }
421 
422 /*
423     in     contains the message to sign
424     inLen  is the length of the message to sign
425     out    is the buffer to write the signature
426     outLen [in/out] input size of out buf
427                      output gets set as the final length of out
428     key    is the ed25519 key to use when signing
429     return 0 on success
430  */
wc_ed25519_sign_msg(const byte * in,word32 inLen,byte * out,word32 * outLen,ed25519_key * key)431 int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out,
432                         word32 *outLen, ed25519_key* key)
433 {
434     return wc_ed25519_sign_msg_ex(in, inLen, out, outLen, key, (byte)Ed25519,
435         NULL, 0);
436 }
437 
438 /*
439     in          contains the message to sign
440     inLen       is the length of the message to sign
441     out         is the buffer to write the signature
442     outLen      [in/out] input size of out buf
443                           output gets set as the final length of out
444     key         is the ed25519 key to use when signing
445     context     extra signing data
446     contextLen  length of extra signing data
447     return 0 on success
448  */
wc_ed25519ctx_sign_msg(const byte * in,word32 inLen,byte * out,word32 * outLen,ed25519_key * key,const byte * context,byte contextLen)449 int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out,
450                            word32 *outLen, ed25519_key* key,
451                            const byte* context, byte contextLen)
452 {
453     return wc_ed25519_sign_msg_ex(in, inLen, out, outLen, key, Ed25519ctx,
454                                                            context, contextLen);
455 }
456 
457 /*
458     hash        contains the SHA-512 hash of the message to sign
459     hashLen     is the length of the SHA-512 hash of the message to sign
460     out         is the buffer to write the signature
461     outLen      [in/out] input size of out buf
462                           output gets set as the final length of out
463     key         is the ed25519 key to use when signing
464     context     extra signing data
465     contextLen  length of extra signing data
466     return 0 on success
467  */
wc_ed25519ph_sign_hash(const byte * hash,word32 hashLen,byte * out,word32 * outLen,ed25519_key * key,const byte * context,byte contextLen)468 int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out,
469                            word32 *outLen, ed25519_key* key,
470                            const byte* context, byte contextLen)
471 {
472     return wc_ed25519_sign_msg_ex(hash, hashLen, out, outLen, key, Ed25519ph,
473                                                            context, contextLen);
474 }
475 
476 /*
477     in          contains the message to sign
478     inLen       is the length of the message to sign
479     out         is the buffer to write the signature
480     outLen      [in/out] input size of out buf
481                           output gets set as the final length of out
482     key         is the ed25519 key to use when signing
483     context     extra signing data
484     contextLen  length of extra signing data
485     return 0 on success
486  */
wc_ed25519ph_sign_msg(const byte * in,word32 inLen,byte * out,word32 * outLen,ed25519_key * key,const byte * context,byte contextLen)487 int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out,
488                           word32 *outLen, ed25519_key* key,
489                           const byte* context, byte contextLen)
490 {
491     int  ret;
492     byte hash[WC_SHA512_DIGEST_SIZE];
493 
494     ret = ed25519_hash(key, in, inLen, hash);
495     if (ret != 0)
496         return ret;
497 
498     return wc_ed25519_sign_msg_ex(hash, sizeof(hash), out, outLen, key,
499                                                 Ed25519ph, context, contextLen);
500 }
501 #endif /* HAVE_ED25519_SIGN */
502 
503 #ifdef HAVE_ED25519_VERIFY
504 #ifndef WOLFSSL_SE050
505 /*
506    sig        is array of bytes containing the signature
507    sigLen     is the length of sig byte array
508    key        Ed25519 public key
509    return     0 on success
510    type       variant to use -- Ed25519, Ed25519ctx, or Ed25519ph
511    context    extra signing data
512    contextLen length of extra signing data
513 */
ed25519_verify_msg_init_with_sha(const byte * sig,word32 sigLen,ed25519_key * key,wc_Sha512 * sha,byte type,const byte * context,byte contextLen)514 static int ed25519_verify_msg_init_with_sha(const byte* sig, word32 sigLen,
515                                             ed25519_key* key, wc_Sha512 *sha,
516                                             byte type, const byte* context,
517                                             byte contextLen)
518 {
519     int ret;
520 
521     /* sanity check on arguments */
522     if (sig == NULL || key == NULL ||
523         (context == NULL && contextLen != 0)) {
524         return BAD_FUNC_ARG;
525     }
526 
527     /* check on basics needed to verify signature */
528     if (sigLen != ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224))
529         return BAD_FUNC_ARG;
530 
531     /* find H(R,A,M) and store it as h */
532 
533 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
534     ret = ed25519_hash_reset(key);
535     if (ret != 0)
536         return ret;
537 #else
538     ret = 0;
539 #endif
540 
541     if (type == Ed25519ctx || type == Ed25519ph) {
542         ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE);
543         if (ret == 0)
544             ret = ed25519_hash_update(key, sha, &type, sizeof(type));
545         if (ret == 0)
546             ret = ed25519_hash_update(key, sha, &contextLen, sizeof(contextLen));
547         if (ret == 0 && context != NULL)
548             ret = ed25519_hash_update(key, sha, context, contextLen);
549     }
550     if (ret == 0)
551         ret = ed25519_hash_update(key, sha, sig, ED25519_SIG_SIZE/2);
552     if (ret == 0)
553         ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE);
554 
555     return ret;
556 }
557 
558 /*
559    msgSegment     an array of bytes containing a message segment
560    msgSegmentLen  length of msgSegment
561    key            Ed25519 public key
562    return         0 on success
563 */
ed25519_verify_msg_update_with_sha(const byte * msgSegment,word32 msgSegmentLen,ed25519_key * key,wc_Sha512 * sha)564 static int ed25519_verify_msg_update_with_sha(const byte* msgSegment,
565                                               word32 msgSegmentLen,
566                                               ed25519_key* key,
567                                               wc_Sha512 *sha) {
568     /* sanity check on arguments */
569     if (msgSegment == NULL || key == NULL)
570         return BAD_FUNC_ARG;
571 
572     return ed25519_hash_update(key, sha, msgSegment, msgSegmentLen);
573 }
574 
575 /*
576    sig     is array of bytes containing the signature
577    sigLen  is the length of sig byte array
578    res     will be 1 on successful verify and 0 on unsuccessful
579    key     Ed25519 public key
580    return  0 and res of 1 on success
581 */
ed25519_verify_msg_final_with_sha(const byte * sig,word32 sigLen,int * res,ed25519_key * key,wc_Sha512 * sha)582 static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen,
583                                              int* res, ed25519_key* key,
584                                              wc_Sha512 *sha)
585 {
586     byte   rcheck[ED25519_KEY_SIZE];
587     byte   h[WC_SHA512_DIGEST_SIZE];
588 #ifndef FREESCALE_LTC_ECC
589     ge_p3  A;
590     ge_p2  R;
591 #endif
592     int    ret;
593 
594     /* sanity check on arguments */
595     if (sig == NULL || res == NULL || key == NULL)
596         return BAD_FUNC_ARG;
597 
598     /* set verification failed by default */
599     *res = 0;
600 
601     /* check on basics needed to verify signature */
602     if (sigLen != ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224))
603         return BAD_FUNC_ARG;
604 
605     /* uncompress A (public key), test if valid, and negate it */
606 #ifndef FREESCALE_LTC_ECC
607     if (ge_frombytes_negate_vartime(&A, key->p) != 0)
608         return BAD_FUNC_ARG;
609 #endif
610 
611     /* find H(R,A,M) and store it as h */
612 
613     ret = ed25519_hash_final(key, sha, h);
614     if (ret != 0)
615         return ret;
616 
617 #ifdef FREESCALE_LTC_ECC
618     LTC_PKHA_sc_reduce(h);
619     LTC_PKHA_SignatureForVerify(rcheck, h, sig + (ED25519_SIG_SIZE/2), key);
620 #else
621     sc_reduce(h);
622 
623     /*
624        Uses a fast single-signature verification SB = R + H(R,A,M)A becomes
625        SB - H(R,A,M)A saving decompression of R
626     */
627     ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2));
628     if (ret != 0)
629         return ret;
630 
631     ge_tobytes(rcheck, &R);
632 #endif /* FREESCALE_LTC_ECC */
633 
634     /* comparison of R created to R in sig */
635     ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2);
636     if (ret != 0) {
637         ret = SIG_VERIFY_E;
638     } else {
639         /* set the verification status */
640         *res = 1;
641     }
642 
643     return ret;
644 }
645 #endif /* WOLFSSL_SE050 */
646 
647 #ifdef WOLFSSL_ED25519_STREAMING_VERIFY
648 
wc_ed25519_verify_msg_init(const byte * sig,word32 sigLen,ed25519_key * key,byte type,const byte * context,byte contextLen)649 int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key,
650                                byte type, const byte* context, byte contextLen) {
651     return ed25519_verify_msg_init_with_sha(sig, sigLen, key, &key->sha,
652                                         type, context, contextLen);
653 }
654 
wc_ed25519_verify_msg_update(const byte * msgSegment,word32 msgSegmentLen,ed25519_key * key)655 int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen,
656                                         ed25519_key* key) {
657     return ed25519_verify_msg_update_with_sha(msgSegment, msgSegmentLen,
658                                           key, &key->sha);
659 }
660 
wc_ed25519_verify_msg_final(const byte * sig,word32 sigLen,int * res,ed25519_key * key)661 int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res,
662                                 ed25519_key* key) {
663     return ed25519_verify_msg_final_with_sha(sig, sigLen, res,
664                                          key, &key->sha);
665 }
666 
667 #endif /* WOLFSSL_ED25519_STREAMING_VERIFY */
668 
669 /*
670    sig     is array of bytes containing the signature
671    sigLen  is the length of sig byte array
672    msg     the array of bytes containing the message
673    msgLen  length of msg array
674    res     will be 1 on successful verify and 0 on unsuccessful
675    key     Ed25519 public key
676    return  0 and res of 1 on success
677 */
wc_ed25519_verify_msg_ex(const byte * sig,word32 sigLen,const byte * msg,word32 msgLen,int * res,ed25519_key * key,byte type,const byte * context,byte contextLen)678 int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg,
679                               word32 msgLen, int* res, ed25519_key* key,
680                               byte type, const byte* context, byte contextLen)
681 {
682     int ret;
683 #ifdef WOLFSSL_SE050
684     (void)type;
685     (void)context;
686     (void)contextLen;
687     (void)ed25519Ctx;
688     ret = se050_ed25519_verify_msg(sig, sigLen, msg, msgLen, key, res);
689 #else
690 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
691     wc_Sha512 *sha;
692 #else
693     wc_Sha512 sha[1];
694 #endif
695 
696     /* sanity check on arguments */
697     if (sig == NULL || msg == NULL || res == NULL || key == NULL ||
698                                          (context == NULL && contextLen != 0))
699         return BAD_FUNC_ARG;
700 
701 #ifdef WOLF_CRYPTO_CB
702     if (key->devId != INVALID_DEVID) {
703         ret = wc_CryptoCb_Ed25519Verify(sig, sigLen, msg, msgLen, res, key,
704             type, context, contextLen);
705         if (ret != CRYPTOCB_UNAVAILABLE)
706             return ret;
707         /* fall-through when unavailable */
708     }
709 #endif
710 
711 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
712     sha = &key->sha;
713 #else
714     ret = ed25519_hash_init(key, sha);
715     if (ret < 0)
716         return ret;
717 #endif
718 
719     ret = ed25519_verify_msg_init_with_sha(sig, sigLen, key, sha, type, context,
720         contextLen);
721     if (ret == 0)
722         ret = ed25519_verify_msg_update_with_sha(msg, msgLen, key, sha);
723     if (ret == 0)
724         ret = ed25519_verify_msg_final_with_sha(sig, sigLen, res, key, sha);
725 
726 #ifndef WOLFSSL_ED25519_PERSISTENT_SHA
727     ed25519_hash_free(key, sha);
728 #endif
729 #endif /* WOLFSSL_SE050 */
730     return ret;
731 }
732 
733 /*
734    sig     is array of bytes containing the signature
735    sigLen  is the length of sig byte array
736    msg     the array of bytes containing the message
737    msgLen  length of msg array
738    res     will be 1 on successful verify and 0 on unsuccessful
739    key     Ed25519 public key
740    return  0 and res of 1 on success
741 */
wc_ed25519_verify_msg(const byte * sig,word32 sigLen,const byte * msg,word32 msgLen,int * res,ed25519_key * key)742 int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
743                           word32 msgLen, int* res, ed25519_key* key)
744 {
745     return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key,
746                                     (byte)Ed25519, NULL, 0);
747 }
748 
749 /*
750    sig         is array of bytes containing the signature
751    sigLen      is the length of sig byte array
752    msg         the array of bytes containing the message
753    msgLen      length of msg array
754    res         will be 1 on successful verify and 0 on unsuccessful
755    key         Ed25519 public key
756    context     extra signing data
757    contextLen  length of extra signing data
758    return  0 and res of 1 on success
759 */
wc_ed25519ctx_verify_msg(const byte * sig,word32 sigLen,const byte * msg,word32 msgLen,int * res,ed25519_key * key,const byte * context,byte contextLen)760 int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
761                              word32 msgLen, int* res, ed25519_key* key,
762                              const byte* context, byte contextLen)
763 {
764     return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key,
765                                     Ed25519ctx, context, contextLen);
766 }
767 
768 /*
769    sig         is array of bytes containing the signature
770    sigLen      is the length of sig byte array
771    hash        the array of bytes containing the SHA-512 hash of the message
772    hashLen     length of hash array
773    res         will be 1 on successful verify and 0 on unsuccessful
774    key         Ed25519 public key
775    context     extra signing data
776    contextLen  length of extra signing data
777    return  0 and res of 1 on success
778 */
wc_ed25519ph_verify_hash(const byte * sig,word32 sigLen,const byte * hash,word32 hashLen,int * res,ed25519_key * key,const byte * context,byte contextLen)779 int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash,
780                              word32 hashLen, int* res, ed25519_key* key,
781                              const byte* context, byte contextLen)
782 {
783     return wc_ed25519_verify_msg_ex(sig, sigLen, hash, hashLen, res, key,
784                                     Ed25519ph, context, contextLen);
785 }
786 
787 /*
788    sig         is array of bytes containing the signature
789    sigLen      is the length of sig byte array
790    msg         the array of bytes containing the message
791    msgLen      length of msg array
792    res         will be 1 on successful verify and 0 on unsuccessful
793    key         Ed25519 public key
794    context     extra signing data
795    contextLen  length of extra signing data
796    return  0 and res of 1 on success
797 */
wc_ed25519ph_verify_msg(const byte * sig,word32 sigLen,const byte * msg,word32 msgLen,int * res,ed25519_key * key,const byte * context,byte contextLen)798 int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg,
799                             word32 msgLen, int* res, ed25519_key* key,
800                             const byte* context, byte contextLen)
801 {
802     int  ret;
803     byte hash[WC_SHA512_DIGEST_SIZE];
804 
805     ret = ed25519_hash(key, msg, msgLen, hash);
806     if (ret != 0)
807         return ret;
808 
809     return wc_ed25519_verify_msg_ex(sig, sigLen, hash, sizeof(hash), res, key,
810                                     Ed25519ph, context, contextLen);
811 }
812 #endif /* HAVE_ED25519_VERIFY */
813 
814 
815 /* initialize information and memory for key */
wc_ed25519_init_ex(ed25519_key * key,void * heap,int devId)816 int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId)
817 {
818     if (key == NULL)
819         return BAD_FUNC_ARG;
820 
821     XMEMSET(key, 0, sizeof(ed25519_key));
822 #ifdef WOLF_CRYPTO_CB
823     key->devId = devId;
824 #else
825     (void)devId;
826 #endif
827     key->heap = heap;
828 
829 #ifndef FREESCALE_LTC_ECC
830     fe_init();
831 #endif
832 
833 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
834     return ed25519_hash_init(key, &key->sha);
835 #else /* !WOLFSSL_ED25519_PERSISTENT_SHA */
836     return 0;
837 #endif /* WOLFSSL_ED25519_PERSISTENT_SHA */
838 }
839 
wc_ed25519_init(ed25519_key * key)840 int wc_ed25519_init(ed25519_key* key)
841 {
842     return wc_ed25519_init_ex(key, NULL, INVALID_DEVID);
843 }
844 
845 /* clear memory of key */
wc_ed25519_free(ed25519_key * key)846 void wc_ed25519_free(ed25519_key* key)
847 {
848     if (key == NULL)
849         return;
850 
851 #ifdef WOLFSSL_ED25519_PERSISTENT_SHA
852     ed25519_hash_free(key, &key->sha);
853 #endif
854 
855 #ifdef WOLFSSL_SE050
856     se050_ed25519_free_key(key);
857 #endif
858 
859     ForceZero(key, sizeof(ed25519_key));
860 }
861 
862 
863 #ifdef HAVE_ED25519_KEY_EXPORT
864 
865 /*
866     outLen should contain the size of out buffer when input. outLen is than set
867     to the final output length.
868     returns 0 on success
869  */
wc_ed25519_export_public(ed25519_key * key,byte * out,word32 * outLen)870 int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen)
871 {
872     /* sanity check on arguments */
873     if (key == NULL || out == NULL || outLen == NULL)
874         return BAD_FUNC_ARG;
875 
876     if (*outLen < ED25519_PUB_KEY_SIZE) {
877         *outLen = ED25519_PUB_KEY_SIZE;
878         return BUFFER_E;
879     }
880 
881     *outLen = ED25519_PUB_KEY_SIZE;
882     XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE);
883 
884     return 0;
885 }
886 
887 #endif /* HAVE_ED25519_KEY_EXPORT */
888 
889 
890 #ifdef HAVE_ED25519_KEY_IMPORT
891 /*
892     Imports a compressed/uncompressed public key.
893     in    the byte array containing the public key
894     inLen the length of the byte array being passed in
895     key   ed25519 key struct to put the public key in
896  */
wc_ed25519_import_public(const byte * in,word32 inLen,ed25519_key * key)897 int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key)
898 {
899     int    ret;
900 
901     /* sanity check on arguments */
902     if (in == NULL || key == NULL)
903         return BAD_FUNC_ARG;
904 
905     if (inLen < ED25519_PUB_KEY_SIZE)
906         return BAD_FUNC_ARG;
907 
908     /* compressed prefix according to draft
909        http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */
910     if (in[0] == 0x40 && inLen > ED25519_PUB_KEY_SIZE) {
911         /* key is stored in compressed format so just copy in */
912         XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE);
913 #ifdef FREESCALE_LTC_ECC
914         /* recover X coordinate */
915         ltc_pkha_ecc_point_t pubKey;
916         pubKey.X = key->pointX;
917         pubKey.Y = key->pointY;
918         LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
919 #endif
920         key->pubKeySet = 1;
921         return 0;
922     }
923 
924     /* importing uncompressed public key */
925     if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) {
926 #ifdef FREESCALE_LTC_ECC
927         /* reverse bytes for little endian byte order */
928         for (int i = 0; i < ED25519_KEY_SIZE; i++)
929         {
930             key->pointX[i] = *(in + ED25519_KEY_SIZE - i);
931             key->pointY[i] = *(in + 2*ED25519_KEY_SIZE - i);
932         }
933         XMEMCPY(key->p, key->pointY, ED25519_KEY_SIZE);
934         key->pubKeySet = 1;
935         ret = 0;
936 #else
937         /* pass in (x,y) and store compressed key */
938         ret = ge_compress_key(key->p, in+1,
939                               in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE);
940         if (ret == 0)
941             key->pubKeySet = 1;
942 #endif /* FREESCALE_LTC_ECC */
943         return ret;
944     }
945 
946     /* if not specified compressed or uncompressed check key size
947        if key size is equal to compressed key size copy in key */
948     if (inLen == ED25519_PUB_KEY_SIZE) {
949         XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE);
950 #ifdef FREESCALE_LTC_ECC
951         /* recover X coordinate */
952         ltc_pkha_ecc_point_t pubKey;
953         pubKey.X = key->pointX;
954         pubKey.Y = key->pointY;
955         LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey);
956 #endif
957         key->pubKeySet = 1;
958         return 0;
959     }
960 
961     /* bad public key format */
962     return BAD_FUNC_ARG;
963 }
964 
965 
966 /*
967     For importing a private key.
968  */
wc_ed25519_import_private_only(const byte * priv,word32 privSz,ed25519_key * key)969 int wc_ed25519_import_private_only(const byte* priv, word32 privSz,
970                                                                ed25519_key* key)
971 {
972     /* sanity check on arguments */
973     if (priv == NULL || key == NULL)
974         return BAD_FUNC_ARG;
975 
976     /* key size check */
977     if (privSz < ED25519_KEY_SIZE)
978         return BAD_FUNC_ARG;
979 
980     XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
981 
982     return 0;
983 }
984 
985 
986 /* Import an ed25519 private and public keys from byte array(s).
987  *
988  * priv    [in]  Array holding private key from wc_ed25519_export_private_only(),
989  *               or private+public keys from wc_ed25519_export_private().
990  * privSz  [in]  Number of bytes of data in private key array.
991  * pub     [in]  Array holding public key (or NULL).
992  * pubSz   [in]  Number of bytes of data in public key array (or 0).
993  * key     [in]  Ed25519 private/public key.
994  * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid
995  *         combination of keys/lengths is supplied, 0 otherwise.
996  */
wc_ed25519_import_private_key(const byte * priv,word32 privSz,const byte * pub,word32 pubSz,ed25519_key * key)997 int wc_ed25519_import_private_key(const byte* priv, word32 privSz,
998                                 const byte* pub, word32 pubSz, ed25519_key* key)
999 {
1000     int    ret;
1001 
1002     /* sanity check on arguments */
1003     if (priv == NULL || key == NULL)
1004         return BAD_FUNC_ARG;
1005 
1006     /* key size check */
1007     if (privSz < ED25519_KEY_SIZE)
1008         return BAD_FUNC_ARG;
1009 
1010     if (pub == NULL) {
1011         if (pubSz != 0)
1012             return BAD_FUNC_ARG;
1013         if (privSz < ED25519_PRV_KEY_SIZE)
1014             return BAD_FUNC_ARG;
1015         pub = priv + ED25519_KEY_SIZE;
1016         pubSz = ED25519_PUB_KEY_SIZE;
1017     } else if (pubSz < ED25519_PUB_KEY_SIZE) {
1018         return BAD_FUNC_ARG;
1019     }
1020 
1021     /* import public key */
1022     ret = wc_ed25519_import_public(pub, pubSz, key);
1023     if (ret != 0)
1024         return ret;
1025 
1026     /* make the private key (priv + pub) */
1027     XMEMCPY(key->k, priv, ED25519_KEY_SIZE);
1028     XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE);
1029 
1030     return ret;
1031 }
1032 
1033 #endif /* HAVE_ED25519_KEY_IMPORT */
1034 
1035 
1036 #ifdef HAVE_ED25519_KEY_EXPORT
1037 
1038 /*
1039  export private key only (secret part so 32 bytes)
1040  outLen should contain the size of out buffer when input. outLen is than set
1041  to the final output length.
1042  returns 0 on success
1043  */
wc_ed25519_export_private_only(ed25519_key * key,byte * out,word32 * outLen)1044 int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen)
1045 {
1046     /* sanity checks on arguments */
1047     if (key == NULL || out == NULL || outLen == NULL)
1048         return BAD_FUNC_ARG;
1049 
1050     if (*outLen < ED25519_KEY_SIZE) {
1051         *outLen = ED25519_KEY_SIZE;
1052         return BUFFER_E;
1053     }
1054 
1055     *outLen = ED25519_KEY_SIZE;
1056     XMEMCPY(out, key->k, ED25519_KEY_SIZE);
1057 
1058     return 0;
1059 }
1060 
1061 /*
1062  export private key, including public part
1063  outLen should contain the size of out buffer when input. outLen is than set
1064  to the final output length.
1065  returns 0 on success
1066  */
wc_ed25519_export_private(ed25519_key * key,byte * out,word32 * outLen)1067 int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen)
1068 {
1069     /* sanity checks on arguments */
1070     if (key == NULL || out == NULL || outLen == NULL)
1071         return BAD_FUNC_ARG;
1072 
1073     if (*outLen < ED25519_PRV_KEY_SIZE) {
1074         *outLen = ED25519_PRV_KEY_SIZE;
1075         return BUFFER_E;
1076     }
1077 
1078     *outLen = ED25519_PRV_KEY_SIZE;
1079     XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE);
1080 
1081     return 0;
1082 }
1083 
1084 /* export full private key and public key
1085    return 0 on success
1086  */
wc_ed25519_export_key(ed25519_key * key,byte * priv,word32 * privSz,byte * pub,word32 * pubSz)1087 int wc_ed25519_export_key(ed25519_key* key,
1088                           byte* priv, word32 *privSz,
1089                           byte* pub, word32 *pubSz)
1090 {
1091     int ret;
1092 
1093     /* export 'full' private part */
1094     ret = wc_ed25519_export_private(key, priv, privSz);
1095     if (ret != 0)
1096         return ret;
1097 
1098     /* export public part */
1099     ret = wc_ed25519_export_public(key, pub, pubSz);
1100 
1101     return ret;
1102 }
1103 
1104 #endif /* HAVE_ED25519_KEY_EXPORT */
1105 
1106 /* check the private and public keys match */
wc_ed25519_check_key(ed25519_key * key)1107 int wc_ed25519_check_key(ed25519_key* key)
1108 {
1109     int ret = 0;
1110     unsigned char pubKey[ED25519_PUB_KEY_SIZE];
1111 
1112     if (!key->pubKeySet)
1113         ret = PUBLIC_KEY_E;
1114     if (ret == 0)
1115         ret = wc_ed25519_make_public(key, pubKey, sizeof(pubKey));
1116     if (ret == 0 && XMEMCMP(pubKey, key->p, ED25519_PUB_KEY_SIZE) != 0)
1117         ret = PUBLIC_KEY_E;
1118 
1119     return ret;
1120 }
1121 
1122 /* returns the private key size (secret only) in bytes */
wc_ed25519_size(ed25519_key * key)1123 int wc_ed25519_size(ed25519_key* key)
1124 {
1125     if (key == NULL)
1126         return BAD_FUNC_ARG;
1127 
1128     return ED25519_KEY_SIZE;
1129 }
1130 
1131 /* returns the private key size (secret + public) in bytes */
wc_ed25519_priv_size(ed25519_key * key)1132 int wc_ed25519_priv_size(ed25519_key* key)
1133 {
1134     if (key == NULL)
1135         return BAD_FUNC_ARG;
1136 
1137     return ED25519_PRV_KEY_SIZE;
1138 }
1139 
1140 /* returns the compressed key size in bytes (public key) */
wc_ed25519_pub_size(ed25519_key * key)1141 int wc_ed25519_pub_size(ed25519_key* key)
1142 {
1143     if (key == NULL)
1144         return BAD_FUNC_ARG;
1145 
1146     return ED25519_PUB_KEY_SIZE;
1147 }
1148 
1149 /* returns the size of signature in bytes */
wc_ed25519_sig_size(ed25519_key * key)1150 int wc_ed25519_sig_size(ed25519_key* key)
1151 {
1152     if (key == NULL)
1153         return BAD_FUNC_ARG;
1154 
1155     return ED25519_SIG_SIZE;
1156 }
1157 
1158 #endif /* HAVE_ED25519 */
1159