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, <cPoint, kLTC_Ed25519 /* result on Ed25519 */);
363 LTC_PKHA_Ed25519_Compress(<cPoint, 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