/src/wolfssl-openssl-api/wolfcrypt/src/ed448.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ed448.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 | | /* Implemented to: RFC 8032 */ |
23 | | |
24 | | /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. |
25 | | * Reworked for curve448 by Sean Parkinson. |
26 | | */ |
27 | | |
28 | | /* Possible Ed448 enable options: |
29 | | * WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN Default: OFF |
30 | | * Check that the private key didn't change during the signing operations. |
31 | | */ |
32 | | |
33 | | #include <wolfssl/wolfcrypt/libwolfssl_sources.h> |
34 | | |
35 | | #ifdef HAVE_ED448 |
36 | | #if FIPS_VERSION3_GE(6,0,0) |
37 | | /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ |
38 | | #define FIPS_NO_WRAPPERS |
39 | | |
40 | | #ifdef USE_WINDOWS_API |
41 | | #pragma code_seg(".fipsA$f") |
42 | | #pragma const_seg(".fipsB$f") |
43 | | #endif |
44 | | #endif |
45 | | |
46 | | #include <wolfssl/wolfcrypt/ed448.h> |
47 | | #include <wolfssl/wolfcrypt/hash.h> |
48 | | #ifdef NO_INLINE |
49 | | #include <wolfssl/wolfcrypt/misc.h> |
50 | | #else |
51 | | #define WOLFSSL_MISC_INCLUDED |
52 | | #include <wolfcrypt/src/misc.c> |
53 | | #endif |
54 | | |
55 | | #if defined(HAVE_ED448_SIGN) || defined(HAVE_ED448_VERIFY) |
56 | | /* Size of context bytes to use with hash when signing and verifying. */ |
57 | 2.31k | #define ED448CTX_SIZE 8 |
58 | | /* Context to pass to hash when signing and verifying. */ |
59 | | static const byte ed448Ctx[ED448CTX_SIZE+1] = "SigEd448"; |
60 | | #endif |
61 | | |
62 | | #if FIPS_VERSION3_GE(6,0,0) |
63 | | const unsigned int wolfCrypt_FIPS_ed448_ro_sanity[2] = |
64 | | { 0x1a2b3c4d, 0x00000007 }; |
65 | | int wolfCrypt_FIPS_ED448_sanity(void) |
66 | | { |
67 | | return 0; |
68 | | } |
69 | | #endif |
70 | | |
71 | | static int ed448_hash_init(ed448_key* key, wc_Shake *sha) |
72 | 2.43k | { |
73 | 2.43k | int ret; |
74 | | |
75 | 2.43k | ret = wc_InitShake256(sha, key->heap, |
76 | 2.43k | #if defined(WOLF_CRYPTO_CB) |
77 | 2.43k | key->devId |
78 | | #else |
79 | | INVALID_DEVID |
80 | | #endif |
81 | 2.43k | ); |
82 | | |
83 | 2.43k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
84 | 2.43k | if (ret == 0) |
85 | 2.43k | key->sha_clean_flag = 1; |
86 | 2.43k | #endif |
87 | | |
88 | 2.43k | return ret; |
89 | 2.43k | } |
90 | | |
91 | | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
92 | | static int ed448_hash_reset(ed448_key* key) |
93 | 3.45k | { |
94 | 3.45k | int ret; |
95 | | |
96 | 3.45k | if (key->sha_clean_flag) |
97 | 3.45k | ret = 0; |
98 | 0 | else { |
99 | 0 | wc_Shake256_Free(&key->sha); |
100 | 0 | ret = wc_InitShake256(&key->sha, key->heap, |
101 | 0 | #if defined(WOLF_CRYPTO_CB) |
102 | 0 | key->devId |
103 | | #else |
104 | | INVALID_DEVID |
105 | | #endif |
106 | 0 | ); |
107 | 0 | if (ret == 0) |
108 | 0 | key->sha_clean_flag = 1; |
109 | 0 | } |
110 | 3.45k | return ret; |
111 | 3.45k | } |
112 | | #endif /* WOLFSSL_ED448_PERSISTENT_SHA */ |
113 | | |
114 | | static int ed448_hash_update(ed448_key* key, wc_Shake *sha, const byte* data, |
115 | | word32 len) |
116 | 52.0k | { |
117 | 52.0k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
118 | 52.0k | if (key->sha_clean_flag) |
119 | 4.70k | key->sha_clean_flag = 0; |
120 | | #else |
121 | | (void)key; |
122 | | #endif |
123 | 52.0k | return wc_Shake256_Update(sha, data, len); |
124 | 52.0k | } |
125 | | |
126 | | static int ed448_hash_final(ed448_key* key, wc_Shake *sha, byte* hash, |
127 | | word32 hashLen) |
128 | 4.60k | { |
129 | 4.60k | int ret = wc_Shake256_Final(sha, hash, hashLen); |
130 | 4.60k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
131 | 4.60k | if (ret == 0) |
132 | 4.60k | key->sha_clean_flag = 1; |
133 | | #else |
134 | | (void)key; |
135 | | #endif |
136 | 4.60k | return ret; |
137 | 4.60k | } |
138 | | |
139 | | static void ed448_hash_free(ed448_key* key, wc_Shake *sha) |
140 | 2.43k | { |
141 | 2.43k | wc_Shake256_Free(sha); |
142 | 2.43k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
143 | 2.43k | key->sha_clean_flag = 0; |
144 | | #else |
145 | | (void)key; |
146 | | #endif |
147 | 2.43k | } |
148 | | |
149 | | |
150 | | static int ed448_hash(ed448_key* key, const byte* in, word32 inLen, |
151 | | byte* hash, word32 hashLen) |
152 | 2.39k | { |
153 | 2.39k | int ret; |
154 | | #ifndef WOLFSSL_ED448_PERSISTENT_SHA |
155 | | wc_Shake sha[1]; |
156 | | #else |
157 | 2.39k | wc_Shake *sha; |
158 | 2.39k | #endif |
159 | | |
160 | 2.39k | if (key == NULL || (in == NULL && inLen > 0) || hash == NULL) { |
161 | 0 | return BAD_FUNC_ARG; |
162 | 0 | } |
163 | | |
164 | 2.39k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
165 | 2.39k | sha = &key->sha; |
166 | 2.39k | ret = ed448_hash_reset(key); |
167 | | #else |
168 | | ret = ed448_hash_init(key, sha); |
169 | | #endif |
170 | 2.39k | if (ret < 0) |
171 | 0 | return ret; |
172 | | |
173 | 2.39k | ret = ed448_hash_update(key, sha, in, inLen); |
174 | 2.39k | if (ret == 0) |
175 | 2.39k | ret = ed448_hash_final(key, sha, hash, hashLen); |
176 | | |
177 | | #ifndef WOLFSSL_ED448_PERSISTENT_SHA |
178 | | ed448_hash_free(key, sha); |
179 | | #endif |
180 | | |
181 | 2.39k | return ret; |
182 | 2.39k | } |
183 | | |
184 | | #if FIPS_VERSION3_GE(6,0,0) |
185 | | /* Performs a Pairwise Consistency Test on an Ed448 key pair. |
186 | | * |
187 | | * @param [in] key Ed448 key to test. |
188 | | * @param [in] rng Random number generator to use to create random digest. |
189 | | * @return 0 on success. |
190 | | * @return ECC_PCT_E when signing or verification fail. |
191 | | * @return Other -ve when random number generation fails. |
192 | | */ |
193 | | static int ed448_pairwise_consistency_test(ed448_key* key, WC_RNG* rng) |
194 | | { |
195 | | int err = 0; |
196 | | byte digest[WC_SHA256_DIGEST_SIZE]; |
197 | | word32 digestLen = WC_SHA256_DIGEST_SIZE; |
198 | | byte sig[ED448_SIG_SIZE]; |
199 | | word32 sigLen = ED448_SIG_SIZE; |
200 | | int res = 0; |
201 | | |
202 | | /* Generate a random digest to sign. */ |
203 | | err = wc_RNG_GenerateBlock(rng, digest, digestLen); |
204 | | if (err == 0) { |
205 | | /* Sign digest without context. */ |
206 | | err = wc_ed448_sign_msg_ex(digest, digestLen, sig, &sigLen, key, Ed448, |
207 | | NULL, 0); |
208 | | if (err != 0) { |
209 | | /* Any sign failure means test failed. */ |
210 | | err = ECC_PCT_E; |
211 | | } |
212 | | } |
213 | | if (err == 0) { |
214 | | /* Verify digest without context. */ |
215 | | err = wc_ed448_verify_msg_ex(sig, sigLen, digest, digestLen, &res, key, |
216 | | Ed448, NULL, 0); |
217 | | if (err != 0) { |
218 | | /* Any verification operation failure means test failed. */ |
219 | | err = ECC_PCT_E; |
220 | | } |
221 | | /* Check whether the signature verified. */ |
222 | | else if (res == 0) { |
223 | | /* Test failed. */ |
224 | | err = ECC_PCT_E; |
225 | | } |
226 | | } |
227 | | |
228 | | ForceZero(sig, sigLen); |
229 | | |
230 | | return err; |
231 | | } |
232 | | #endif |
233 | | |
234 | | /* Derive the public key for the private key. |
235 | | * |
236 | | * key [in] Ed448 key object. |
237 | | * pubKey [in] Byte array to hold the public key. |
238 | | * pubKeySz [in] Size of the array in bytes. |
239 | | * returns BAD_FUNC_ARG when key is NULL or pubKeySz is not equal to |
240 | | * ED448_PUB_KEY_SIZE, |
241 | | * other -ve value on hash failure, |
242 | | * 0 otherwise. |
243 | | */ |
244 | | int wc_ed448_make_public(ed448_key* key, unsigned char* pubKey, word32 pubKeySz) |
245 | 1.77k | { |
246 | 1.77k | int ret = 0; |
247 | 1.77k | byte az[ED448_PRV_KEY_SIZE]; |
248 | 1.77k | ge448_p2 A; |
249 | | |
250 | 1.77k | if ((key == NULL) || (pubKey == NULL) || (pubKeySz != ED448_PUB_KEY_SIZE)) { |
251 | 0 | ret = BAD_FUNC_ARG; |
252 | 0 | } |
253 | | |
254 | 1.77k | if ((ret == 0) && (!key->privKeySet)) { |
255 | 22 | ret = ECC_PRIV_KEY_E; |
256 | 22 | } |
257 | | |
258 | 1.77k | if (ret == 0) |
259 | 1.75k | ret = ed448_hash(key, key->k, ED448_KEY_SIZE, az, sizeof(az)); |
260 | | |
261 | 1.77k | if (ret == 0) { |
262 | | /* apply clamp */ |
263 | 1.75k | az[0] &= 0xfc; |
264 | 1.75k | az[55] |= 0x80; |
265 | 1.75k | az[56] = 0x00; |
266 | | |
267 | 1.75k | ret = ge448_scalarmult_base(&A, az); |
268 | 1.75k | } |
269 | | |
270 | 1.77k | if (ret == 0) { |
271 | 1.55k | ge448_to_bytes(pubKey, &A); |
272 | | |
273 | 1.55k | key->pubKeySet = 1; |
274 | 1.55k | } |
275 | | |
276 | 1.77k | return ret; |
277 | 1.77k | } |
278 | | |
279 | | /* Make a new ed448 private/public key. |
280 | | * |
281 | | * rng [in] Random number generator. |
282 | | * keysize [in] Size of the key to generate. |
283 | | * key [in] Ed448 key object. |
284 | | * returns BAD_FUNC_ARG when rng or key is NULL or keySz is not equal to |
285 | | * ED448_KEY_SIZE, |
286 | | * other -ve value on random number or hash failure, |
287 | | * 0 otherwise. |
288 | | */ |
289 | | int wc_ed448_make_key(WC_RNG* rng, int keySz, ed448_key* key) |
290 | 222 | { |
291 | 222 | int ret = 0; |
292 | | |
293 | 222 | if ((rng == NULL) || (key == NULL)) { |
294 | 0 | ret = BAD_FUNC_ARG; |
295 | 0 | } |
296 | | |
297 | | /* ed448 has 57 byte key sizes */ |
298 | 222 | if ((ret == 0) && (keySz != ED448_KEY_SIZE)) { |
299 | 0 | ret = BAD_FUNC_ARG; |
300 | 0 | } |
301 | | |
302 | 222 | if (ret == 0) { |
303 | 222 | key->pubKeySet = 0; |
304 | 222 | key->privKeySet = 0; |
305 | | |
306 | 222 | ret = wc_RNG_GenerateBlock(rng, key->k, ED448_KEY_SIZE); |
307 | 222 | } |
308 | 222 | if (ret == 0) { |
309 | 175 | key->privKeySet = 1; |
310 | 175 | ret = wc_ed448_make_public(key, key->p, ED448_PUB_KEY_SIZE); |
311 | 175 | if (ret != 0) { |
312 | 49 | key->privKeySet = 0; |
313 | 49 | ForceZero(key->k, ED448_KEY_SIZE); |
314 | 49 | } |
315 | 175 | } |
316 | 222 | if (ret == 0) { |
317 | | /* put public key after private key, on the same buffer */ |
318 | 126 | XMEMMOVE(key->k + ED448_KEY_SIZE, key->p, ED448_PUB_KEY_SIZE); |
319 | | |
320 | | #if FIPS_VERSION3_GE(6,0,0) |
321 | | ret = wc_ed448_check_key(key); |
322 | | if (ret == 0) { |
323 | | ret = ed448_pairwise_consistency_test(key, rng); |
324 | | } |
325 | | #endif |
326 | 126 | } |
327 | | |
328 | 222 | return ret; |
329 | 222 | } |
330 | | |
331 | | #ifdef HAVE_ED448_SIGN |
332 | | /* Sign the message using the ed448 private key. |
333 | | * |
334 | | * in [in] Message to sign. |
335 | | * inLen [in] Length of the message in bytes. |
336 | | * out [in] Buffer to write signature into. |
337 | | * outLen [in/out] On in, size of buffer. |
338 | | * On out, the length of the signature in bytes. |
339 | | * key [in] Ed448 key to use when signing |
340 | | * type [in] Type of signature to perform: Ed448 or Ed448ph |
341 | | * context [in] Context of signing. |
342 | | * contextLen [in] Length of context in bytes. |
343 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
344 | | * context is not NULL or public key not set, |
345 | | * BUFFER_E when outLen is less than ED448_SIG_SIZE, |
346 | | * other -ve values when hash fails, |
347 | | * 0 otherwise. |
348 | | */ |
349 | | int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out, |
350 | | word32 *outLen, ed448_key* key, byte type, |
351 | | const byte* context, byte contextLen) |
352 | 665 | { |
353 | 665 | ge448_p2 R; |
354 | 665 | byte nonce[ED448_SIG_SIZE]; |
355 | 665 | byte hram[ED448_SIG_SIZE]; |
356 | 665 | byte az[ED448_PRV_KEY_SIZE]; |
357 | 665 | int ret = 0; |
358 | | #ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN |
359 | | byte orig_k[ED448_KEY_SIZE]; |
360 | | #endif |
361 | | |
362 | | /* sanity check on arguments */ |
363 | 665 | if ((in == NULL) || (out == NULL) || (outLen == NULL) || (key == NULL) || |
364 | 665 | ((context == NULL) && (contextLen != 0))) { |
365 | 26 | ret = BAD_FUNC_ARG; |
366 | 26 | } |
367 | 665 | if ((ret == 0) && (!key->pubKeySet)) { |
368 | 0 | ret = BAD_FUNC_ARG; |
369 | 0 | } |
370 | | |
371 | | /* check and set up out length */ |
372 | 665 | if ((ret == 0) && (*outLen < ED448_SIG_SIZE)) { |
373 | 0 | *outLen = ED448_SIG_SIZE; |
374 | 0 | ret = BUFFER_E; |
375 | 0 | } |
376 | | |
377 | 665 | if (ret == 0) { |
378 | 639 | *outLen = ED448_SIG_SIZE; |
379 | | |
380 | | #ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN |
381 | | XMEMCPY(orig_k, key->k, ED448_KEY_SIZE); |
382 | | #endif |
383 | | |
384 | | /* step 1: create nonce to use where nonce is r in |
385 | | r = H(h_b, ... ,h_2b-1,M) */ |
386 | 639 | ret = ed448_hash(key, key->k, ED448_KEY_SIZE, az, sizeof(az)); |
387 | 639 | } |
388 | 665 | if (ret == 0) { |
389 | 639 | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
390 | 639 | wc_Shake *sha = &key->sha; |
391 | | #else |
392 | | wc_Shake sha[1]; |
393 | | ret = ed448_hash_init(key, sha); |
394 | | if (ret < 0) |
395 | | return ret; |
396 | | #endif |
397 | | /* apply clamp */ |
398 | 639 | az[0] &= 0xfc; |
399 | 639 | az[55] |= 0x80; |
400 | 639 | az[56] = 0x00; |
401 | | |
402 | 639 | ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); |
403 | | |
404 | 639 | if (ret == 0) { |
405 | 639 | ret = ed448_hash_update(key, sha, &type, sizeof(type)); |
406 | 639 | } |
407 | 639 | if (ret == 0) { |
408 | 639 | ret = ed448_hash_update(key, sha, &contextLen, sizeof(contextLen)); |
409 | 639 | } |
410 | 639 | if ((ret == 0) && (context != NULL)) { |
411 | 0 | ret = ed448_hash_update(key, sha, context, contextLen); |
412 | 0 | } |
413 | 639 | if (ret == 0) { |
414 | 639 | ret = ed448_hash_update(key, sha, az + ED448_KEY_SIZE, ED448_KEY_SIZE); |
415 | 639 | } |
416 | 639 | if (ret == 0) { |
417 | 639 | ret = ed448_hash_update(key, sha, in, inLen); |
418 | 639 | } |
419 | 639 | if (ret == 0) { |
420 | 639 | ret = ed448_hash_final(key, sha, nonce, sizeof(nonce)); |
421 | 639 | } |
422 | | #ifndef WOLFSSL_ED448_PERSISTENT_SHA |
423 | | ed448_hash_free(key, sha); |
424 | | #endif |
425 | 639 | } |
426 | 665 | if (ret == 0) { |
427 | 639 | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
428 | 639 | wc_Shake *sha = &key->sha; |
429 | | #else |
430 | | wc_Shake sha[1]; |
431 | | ret = ed448_hash_init(key, sha); |
432 | | if (ret < 0) |
433 | | return ret; |
434 | | #endif |
435 | 639 | sc448_reduce(nonce); |
436 | | |
437 | | /* step 2: computing R = rB where rB is the scalar multiplication of |
438 | | r and B */ |
439 | 639 | ret = ge448_scalarmult_base(&R,nonce); |
440 | | |
441 | | /* step 3: hash R + public key + message getting H(R,A,M) then |
442 | | creating S = (r + H(R,A,M)a) mod l */ |
443 | 639 | if (ret == 0) { |
444 | 617 | ge448_to_bytes(out,&R); |
445 | | |
446 | 617 | ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); |
447 | 617 | } |
448 | 639 | if (ret == 0) { |
449 | 617 | ret = ed448_hash_update(key, sha, &type, sizeof(type)); |
450 | 617 | } |
451 | 639 | if (ret == 0) { |
452 | 617 | ret = ed448_hash_update(key, sha, &contextLen, sizeof(contextLen)); |
453 | 617 | } |
454 | 639 | if ((ret == 0) && (context != NULL)) { |
455 | 0 | ret = ed448_hash_update(key, sha, context, contextLen); |
456 | 0 | } |
457 | 639 | if (ret == 0) { |
458 | 617 | ret = ed448_hash_update(key, sha, out, ED448_SIG_SIZE/2); |
459 | 617 | } |
460 | 639 | if (ret == 0) { |
461 | 617 | ret = ed448_hash_update(key, sha, key->p, ED448_PUB_KEY_SIZE); |
462 | 617 | } |
463 | 639 | if (ret == 0) { |
464 | 617 | ret = ed448_hash_update(key, sha, in, inLen); |
465 | 617 | } |
466 | 639 | if (ret == 0) { |
467 | 617 | ret = ed448_hash_final(key, sha, hram, sizeof(hram)); |
468 | 617 | } |
469 | | #ifndef WOLFSSL_ED448_PERSISTENT_SHA |
470 | | ed448_hash_free(key, sha); |
471 | | #endif |
472 | 639 | } |
473 | | |
474 | 665 | if (ret == 0) { |
475 | 617 | sc448_reduce(hram); |
476 | 617 | sc448_muladd(out + (ED448_SIG_SIZE/2), hram, az, nonce); |
477 | 617 | } |
478 | | |
479 | | #ifdef WOLFSSL_EDDSA_CHECK_PRIV_ON_SIGN |
480 | | if (ret == 0) { |
481 | | int i; |
482 | | byte c = 0; |
483 | | for (i = 0; i < ED448_KEY_SIZE; i++) { |
484 | | c |= key->k[i] ^ orig_k[i]; |
485 | | } |
486 | | ret = ctMaskGT(c, 0) & SIG_VERIFY_E; |
487 | | } |
488 | | #endif |
489 | | |
490 | 665 | return ret; |
491 | 665 | } |
492 | | |
493 | | /* Sign the message using the ed448 private key. |
494 | | * Signature type is Ed448. |
495 | | * |
496 | | * in [in] Message to sign. |
497 | | * inLen [in] Length of the message in bytes. |
498 | | * out [in] Buffer to write signature into. |
499 | | * outLen [in/out] On in, size of buffer. |
500 | | * On out, the length of the signature in bytes. |
501 | | * key [in] Ed448 key to use when signing |
502 | | * context [in] Context of signing. |
503 | | * contextLen [in] Length of context in bytes. |
504 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
505 | | * context is not NULL or public key not set, |
506 | | * BUFFER_E when outLen is less than ED448_SIG_SIZE, |
507 | | * other -ve values when hash fails, |
508 | | * 0 otherwise. |
509 | | */ |
510 | | int wc_ed448_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, |
511 | | ed448_key* key, const byte* context, byte contextLen) |
512 | 665 | { |
513 | 665 | return wc_ed448_sign_msg_ex(in, inLen, out, outLen, key, Ed448, context, |
514 | 665 | contextLen); |
515 | 665 | } |
516 | | |
517 | | /* Sign the hash using the ed448 private key. |
518 | | * Signature type is Ed448ph. |
519 | | * |
520 | | * hash [in] Hash of message to sign. |
521 | | * hashLen [in] Length of hash of message in bytes. |
522 | | * out [in] Buffer to write signature into. |
523 | | * outLen [in/out] On in, size of buffer. |
524 | | * On out, the length of the signature in bytes. |
525 | | * key [in] Ed448 key to use when signing |
526 | | * context [in] Context of signing. |
527 | | * contextLen [in] Length of context in bytes. |
528 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
529 | | * context is not NULL or public key not set, |
530 | | * BUFFER_E when outLen is less than ED448_SIG_SIZE, |
531 | | * other -ve values when hash fails, |
532 | | * 0 otherwise. |
533 | | */ |
534 | | int wc_ed448ph_sign_hash(const byte* hash, word32 hashLen, byte* out, |
535 | | word32 *outLen, ed448_key* key, |
536 | | const byte* context, byte contextLen) |
537 | 0 | { |
538 | 0 | return wc_ed448_sign_msg_ex(hash, hashLen, out, outLen, key, Ed448ph, |
539 | 0 | context, contextLen); |
540 | 0 | } |
541 | | |
542 | | /* Sign the message using the ed448 private key. |
543 | | * Signature type is Ed448ph. |
544 | | * |
545 | | * in [in] Message to sign. |
546 | | * inLen [in] Length of the message to sign in bytes. |
547 | | * out [in] Buffer to write signature into. |
548 | | * outLen [in/out] On in, size of buffer. |
549 | | * On out, the length of the signature in bytes. |
550 | | * key [in] Ed448 key to use when signing |
551 | | * context [in] Context of signing. |
552 | | * contextLen [in] Length of context in bytes. |
553 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
554 | | * context is not NULL or public key not set, |
555 | | * BUFFER_E when outLen is less than ED448_SIG_SIZE, |
556 | | * other -ve values when hash fails, |
557 | | * 0 otherwise. |
558 | | */ |
559 | | int wc_ed448ph_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, |
560 | | ed448_key* key, const byte* context, byte contextLen) |
561 | 0 | { |
562 | 0 | int ret; |
563 | 0 | byte hash[ED448_PREHASH_SIZE]; |
564 | |
|
565 | 0 | ret = ed448_hash(key, in, inLen, hash, sizeof(hash)); |
566 | |
|
567 | 0 | if (ret == 0) { |
568 | 0 | ret = wc_ed448ph_sign_hash(hash, sizeof(hash), out, outLen, key, |
569 | 0 | context, contextLen); |
570 | 0 | } |
571 | |
|
572 | 0 | return ret; |
573 | 0 | } |
574 | | #endif /* HAVE_ED448_SIGN */ |
575 | | |
576 | | #ifdef HAVE_ED448_VERIFY |
577 | | |
578 | | /* Verify the message using the ed448 public key. |
579 | | * |
580 | | * sig [in] Signature to verify. |
581 | | * sigLen [in] Size of signature in bytes. |
582 | | * key [in] Ed448 key to use to verify. |
583 | | * type [in] Type of signature to verify: Ed448 or Ed448ph |
584 | | * context [in] Context of verification. |
585 | | * contextLen [in] Length of context in bytes. |
586 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
587 | | * context is not NULL or public key not set, |
588 | | * BUFFER_E when sigLen is less than ED448_SIG_SIZE, |
589 | | * other -ve values when hash fails, |
590 | | * 0 otherwise. |
591 | | */ |
592 | | |
593 | | static int ed448_verify_msg_init_with_sha(const byte* sig, word32 sigLen, |
594 | | ed448_key* key, wc_Shake *sha, byte type, |
595 | | const byte* context, byte contextLen) |
596 | 1.05k | { |
597 | 1.05k | int ret; |
598 | | |
599 | | /* sanity check on arguments */ |
600 | 1.05k | if ((sig == NULL) || (key == NULL) || |
601 | 1.05k | ((context == NULL) && (contextLen != 0))) { |
602 | 0 | return BAD_FUNC_ARG; |
603 | 0 | } |
604 | | |
605 | | /* check on basics needed to verify signature */ |
606 | 1.05k | if (sigLen != ED448_SIG_SIZE) { |
607 | 0 | return BAD_FUNC_ARG; |
608 | 0 | } |
609 | | |
610 | | /* find H(R,A,M) and store it as h */ |
611 | 1.05k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
612 | 1.05k | ret = ed448_hash_reset(key); |
613 | 1.05k | if (ret < 0) |
614 | 0 | return ret; |
615 | 1.05k | #endif |
616 | | |
617 | 1.05k | ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); |
618 | 1.05k | if (ret == 0) { |
619 | 1.05k | ret = ed448_hash_update(key, sha, &type, sizeof(type)); |
620 | 1.05k | } |
621 | 1.05k | if (ret == 0) { |
622 | 1.05k | ret = ed448_hash_update(key, sha, &contextLen, sizeof(contextLen)); |
623 | 1.05k | } |
624 | 1.05k | if ((ret == 0) && (context != NULL)) { |
625 | 0 | ret = ed448_hash_update(key, sha, context, contextLen); |
626 | 0 | } |
627 | 1.05k | if (ret == 0) { |
628 | 1.05k | ret = ed448_hash_update(key, sha, sig, ED448_SIG_SIZE/2); |
629 | 1.05k | } |
630 | 1.05k | if (ret == 0) { |
631 | 1.05k | ret = ed448_hash_update(key, sha, key->p, ED448_PUB_KEY_SIZE); |
632 | 1.05k | } |
633 | | |
634 | 1.05k | return ret; |
635 | 1.05k | } |
636 | | |
637 | | /* |
638 | | msgSegment an array of bytes containing a message segment |
639 | | msgSegmentLen length of msgSegment |
640 | | key Ed448 public key |
641 | | return 0 on success |
642 | | */ |
643 | | static int ed448_verify_msg_update_with_sha(const byte* msgSegment, |
644 | | word32 msgSegmentLen, |
645 | | ed448_key* key, |
646 | | wc_Shake *sha) |
647 | 37.5k | { |
648 | | /* sanity check on arguments */ |
649 | 37.5k | if (msgSegment == NULL || key == NULL) |
650 | 10 | return BAD_FUNC_ARG; |
651 | | |
652 | 37.4k | return ed448_hash_update(key, sha, msgSegment, msgSegmentLen); |
653 | 37.5k | } |
654 | | |
655 | | /* Order of the ed448 curve - little endian. */ |
656 | | static const byte ed448_order[] = { |
657 | | 0xf3, 0x44, 0x58, 0xab, 0x92, 0xc2, 0x78, 0x23, |
658 | | 0x55, 0x8f, 0xc5, 0x8d, 0x72, 0xc2, 0x6c, 0x21, |
659 | | 0x90, 0x36, 0xd6, 0xae, 0x49, 0xdb, 0x4e, 0xc4, |
660 | | 0xe9, 0x23, 0xca, 0x7c, 0xff, 0xff, 0xff, 0xff, |
661 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
662 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, |
663 | | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, |
664 | | 0x00 |
665 | | }; |
666 | | |
667 | | /* Verify the message using the ed448 public key. |
668 | | * |
669 | | * sig [in] Signature to verify. |
670 | | * sigLen [in] Size of signature in bytes. |
671 | | * res [out] *res is set to 1 on successful verification. |
672 | | * key [in] Ed448 key to use to verify. |
673 | | * returns BAD_FUNC_ARG when a parameter is NULL or public key not set, |
674 | | * BUFFER_E when sigLen is less than ED448_SIG_SIZE, |
675 | | * other -ve values when hash fails, |
676 | | * 0 otherwise. |
677 | | */ |
678 | | static int ed448_verify_msg_final_with_sha(const byte* sig, word32 sigLen, |
679 | | int* res, ed448_key* key, wc_Shake *sha) |
680 | 1.04k | { |
681 | 1.04k | byte rcheck[ED448_KEY_SIZE]; |
682 | 1.04k | byte h[ED448_SIG_SIZE]; |
683 | 1.04k | ge448_p2 A; |
684 | 1.04k | ge448_p2 R; |
685 | 1.04k | int ret; |
686 | 1.04k | int i; |
687 | | |
688 | | /* sanity check on arguments */ |
689 | 1.04k | if ((sig == NULL) || (res == NULL) || (key == NULL)) |
690 | 0 | return BAD_FUNC_ARG; |
691 | | |
692 | | /* set verification failed by default */ |
693 | 1.04k | *res = 0; |
694 | | |
695 | | /* check on basics needed to verify signature */ |
696 | 1.04k | if (sigLen != ED448_SIG_SIZE) |
697 | 0 | return BAD_FUNC_ARG; |
698 | | /* Check S is not larger than or equal to order. */ |
699 | 2.06k | for (i = (int)sizeof(ed448_order) - 1; i >= 0; i--) { |
700 | | /* Bigger than order. */ |
701 | 2.06k | if (sig[ED448_SIG_SIZE/2 + i] > ed448_order[i]) |
702 | 89 | return BAD_FUNC_ARG; |
703 | | /* Less than order. */ |
704 | 1.97k | if (sig[ED448_SIG_SIZE/2 + i] < ed448_order[i]) |
705 | 960 | break; |
706 | 1.97k | } |
707 | | /* Same value as order. */ |
708 | 960 | if (i == -1) |
709 | 0 | return BAD_FUNC_ARG; |
710 | | |
711 | | /* uncompress A (public key), test if valid, and negate it */ |
712 | 960 | if (ge448_from_bytes_negate_vartime(&A, key->p) != 0) |
713 | 0 | return BAD_FUNC_ARG; |
714 | | |
715 | 960 | ret = ed448_hash_final(key, sha, h, sizeof(h)); |
716 | 960 | if (ret != 0) |
717 | 0 | return ret; |
718 | | |
719 | 960 | sc448_reduce(h); |
720 | | |
721 | | /* Uses a fast single-signature verification SB = R + H(R,A,M)A becomes |
722 | | * SB - H(R,A,M)A saving decompression of R |
723 | | */ |
724 | 960 | ret = ge448_double_scalarmult_vartime(&R, h, &A, |
725 | 960 | sig + (ED448_SIG_SIZE/2)); |
726 | 960 | if (ret != 0) |
727 | 150 | return ret; |
728 | | |
729 | 810 | ge448_to_bytes(rcheck, &R); |
730 | | |
731 | | /* comparison of R created to R in sig */ |
732 | 810 | if (ConstantCompare(rcheck, sig, ED448_SIG_SIZE/2) != 0) { |
733 | 269 | ret = SIG_VERIFY_E; |
734 | 269 | } |
735 | 541 | else { |
736 | | /* set the verification status */ |
737 | 541 | *res = 1; |
738 | 541 | } |
739 | | |
740 | 810 | return ret; |
741 | 960 | } |
742 | | |
743 | | #ifdef WOLFSSL_ED448_STREAMING_VERIFY |
744 | | int wc_ed448_verify_msg_init(const byte* sig, word32 sigLen, ed448_key* key, |
745 | | byte type, const byte* context, byte contextLen) |
746 | 332 | { |
747 | 332 | return ed448_verify_msg_init_with_sha(sig, sigLen, key, &key->sha, type, |
748 | 332 | context, contextLen); |
749 | 332 | } |
750 | | |
751 | | int wc_ed448_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, |
752 | | ed448_key* key) |
753 | 36.7k | { |
754 | 36.7k | return ed448_verify_msg_update_with_sha(msgSegment, msgSegmentLen, key, |
755 | 36.7k | &key->sha); |
756 | 36.7k | } |
757 | | |
758 | | int wc_ed448_verify_msg_final(const byte* sig, word32 sigLen, |
759 | | int* res, ed448_key* key) |
760 | 331 | { |
761 | 331 | return ed448_verify_msg_final_with_sha(sig, sigLen, res, key, &key->sha); |
762 | 331 | } |
763 | | #endif |
764 | | |
765 | | /* Verify the message using the ed448 public key. |
766 | | * |
767 | | * sig [in] Signature to verify. |
768 | | * sigLen [in] Size of signature in bytes. |
769 | | * msg [in] Message to verify. |
770 | | * msgLen [in] Length of the message in bytes. |
771 | | * res [out] *res is set to 1 on successful verification. |
772 | | * key [in] Ed448 key to use to verify. |
773 | | * type [in] Type of signature to verify: Ed448 or Ed448ph |
774 | | * context [in] Context of verification. |
775 | | * contextLen [in] Length of context in bytes. |
776 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
777 | | * context is not NULL or public key not set, |
778 | | * BUFFER_E when sigLen is less than ED448_SIG_SIZE, |
779 | | * other -ve values when hash fails, |
780 | | * 0 otherwise. |
781 | | */ |
782 | | int wc_ed448_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, |
783 | | word32 msgLen, int* res, ed448_key* key, |
784 | | byte type, const byte* context, byte contextLen) |
785 | 727 | { |
786 | 727 | int ret; |
787 | 727 | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
788 | 727 | wc_Shake *sha; |
789 | | #else |
790 | | wc_Shake sha[1]; |
791 | | #endif |
792 | | |
793 | 727 | if (key == NULL) |
794 | 0 | return BAD_FUNC_ARG; |
795 | | |
796 | 727 | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
797 | 727 | sha = &key->sha; |
798 | | #else |
799 | | ret = ed448_hash_init(key, sha); |
800 | | if (ret < 0) |
801 | | return ret; |
802 | | #endif |
803 | | |
804 | 727 | ret = ed448_verify_msg_init_with_sha(sig, sigLen, key, sha, |
805 | 727 | type, context, contextLen); |
806 | 727 | if (ret == 0) |
807 | 727 | ret = ed448_verify_msg_update_with_sha(msg, msgLen, key, sha); |
808 | 727 | if (ret == 0) |
809 | 718 | ret = ed448_verify_msg_final_with_sha(sig, sigLen, res, key, sha); |
810 | | |
811 | | #ifndef WOLFSSL_ED448_PERSISTENT_SHA |
812 | | ed448_hash_free(key, sha); |
813 | | #endif |
814 | | |
815 | 727 | return ret; |
816 | 727 | } |
817 | | |
818 | | /* Verify the message using the ed448 public key. |
819 | | * Signature type is Ed448. |
820 | | * |
821 | | * sig [in] Signature to verify. |
822 | | * sigLen [in] Size of signature in bytes. |
823 | | * msg [in] Message to verify. |
824 | | * msgLen [in] Length of the message in bytes. |
825 | | * key [in] Ed448 key to use to verify. |
826 | | * context [in] Context of verification. |
827 | | * contextLen [in] Length of context in bytes. |
828 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
829 | | * context is not NULL or public key not set, |
830 | | * BUFFER_E when sigLen is less than ED448_SIG_SIZE, |
831 | | * other -ve values when hash fails, |
832 | | * 0 otherwise. |
833 | | */ |
834 | | int wc_ed448_verify_msg(const byte* sig, word32 sigLen, const byte* msg, |
835 | | word32 msgLen, int* res, ed448_key* key, |
836 | | const byte* context, byte contextLen) |
837 | 727 | { |
838 | 727 | return wc_ed448_verify_msg_ex(sig, sigLen, msg, msgLen, res, key, Ed448, |
839 | 727 | context, contextLen); |
840 | 727 | } |
841 | | |
842 | | /* Verify the hash using the ed448 public key. |
843 | | * Signature type is Ed448ph. |
844 | | * |
845 | | * sig [in] Signature to verify. |
846 | | * sigLen [in] Size of signature in bytes. |
847 | | * hash [in] Hash of message to verify. |
848 | | * hashLen [in] Length of the hash in bytes. |
849 | | * key [in] Ed448 key to use to verify. |
850 | | * context [in] Context of verification. |
851 | | * contextLen [in] Length of context in bytes. |
852 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
853 | | * context is not NULL or public key not set, |
854 | | * BUFFER_E when sigLen is less than ED448_SIG_SIZE, |
855 | | * other -ve values when hash fails, |
856 | | * 0 otherwise. |
857 | | */ |
858 | | int wc_ed448ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, |
859 | | word32 hashLen, int* res, ed448_key* key, |
860 | | const byte* context, byte contextLen) |
861 | 0 | { |
862 | 0 | return wc_ed448_verify_msg_ex(sig, sigLen, hash, hashLen, res, key, Ed448ph, |
863 | 0 | context, contextLen); |
864 | 0 | } |
865 | | |
866 | | /* Verify the message using the ed448 public key. |
867 | | * Signature type is Ed448ph. |
868 | | * |
869 | | * sig [in] Signature to verify. |
870 | | * sigLen [in] Size of signature in bytes. |
871 | | * msg [in] Message to verify. |
872 | | * msgLen [in] Length of the message in bytes. |
873 | | * key [in] Ed448 key to use to verify. |
874 | | * context [in] Context of verification. |
875 | | * contextLen [in] Length of context in bytes. |
876 | | * returns BAD_FUNC_ARG when a parameter is NULL or contextLen is zero when and |
877 | | * context is not NULL or public key not set, |
878 | | * BUFFER_E when sigLen is less than ED448_SIG_SIZE, |
879 | | * other -ve values when hash fails, |
880 | | * 0 otherwise. |
881 | | */ |
882 | | int wc_ed448ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, |
883 | | word32 msgLen, int* res, ed448_key* key, |
884 | | const byte* context, byte contextLen) |
885 | 0 | { |
886 | 0 | int ret = 0; |
887 | 0 | byte hash[ED448_PREHASH_SIZE]; |
888 | |
|
889 | 0 | ret = ed448_hash(key, msg, msgLen, hash, sizeof(hash)); |
890 | |
|
891 | 0 | if (ret == 0) { |
892 | 0 | ret = wc_ed448ph_verify_hash(sig, sigLen, hash, sizeof(hash), res, key, |
893 | 0 | context, contextLen); |
894 | 0 | } |
895 | |
|
896 | 0 | return ret; |
897 | 0 | } |
898 | | #endif /* HAVE_ED448_VERIFY */ |
899 | | |
900 | | /* Initialize the ed448 private/public key. |
901 | | * |
902 | | * key [in] Ed448 key. |
903 | | * heap [in] heap pointer to pass to wc_InitShake256(). |
904 | | * returns BAD_FUNC_ARG when key is NULL |
905 | | */ |
906 | | int wc_ed448_init_ex(ed448_key* key, void *heap, int devId) |
907 | 2.43k | { |
908 | 2.43k | if (key == NULL) |
909 | 0 | return BAD_FUNC_ARG; |
910 | | |
911 | 2.43k | XMEMSET(key, 0, sizeof(ed448_key)); |
912 | | |
913 | 2.43k | #ifdef WOLF_CRYPTO_CB |
914 | 2.43k | key->devId = devId; |
915 | | #else |
916 | | (void)devId; |
917 | | #endif |
918 | 2.43k | key->heap = heap; |
919 | | |
920 | 2.43k | fe448_init(); |
921 | | |
922 | | #ifdef WOLFSSL_CHECK_MEM_ZERO |
923 | | wc_MemZero_Add("wc_ed448_init_ex key->k", &key->k, sizeof(key->k)); |
924 | | #endif |
925 | | |
926 | 2.43k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
927 | 2.43k | return ed448_hash_init(key, &key->sha); |
928 | | #else /* !WOLFSSL_ED448_PERSISTENT_SHA */ |
929 | | return 0; |
930 | | #endif /* WOLFSSL_ED448_PERSISTENT_SHA */ |
931 | 2.43k | } |
932 | | |
933 | | /* Initialize the ed448 private/public key. |
934 | | * |
935 | | * key [in] Ed448 key. |
936 | | * returns BAD_FUNC_ARG when key is NULL |
937 | | */ |
938 | 2.43k | int wc_ed448_init(ed448_key* key) { |
939 | 2.43k | return wc_ed448_init_ex(key, NULL, INVALID_DEVID); |
940 | 2.43k | } |
941 | | |
942 | | /* Clears the ed448 key data |
943 | | * |
944 | | * key [in] Ed448 key. |
945 | | */ |
946 | | void wc_ed448_free(ed448_key* key) |
947 | 2.43k | { |
948 | 2.43k | if (key != NULL) { |
949 | 2.43k | #ifdef WOLFSSL_ED448_PERSISTENT_SHA |
950 | 2.43k | ed448_hash_free(key, &key->sha); |
951 | 2.43k | #endif |
952 | 2.43k | ForceZero(key, sizeof(ed448_key)); |
953 | | #ifdef WOLFSSL_CHECK_MEM_ZERO |
954 | | wc_MemZero_Check(key, sizeof(ed448_key)); |
955 | | #endif |
956 | 2.43k | } |
957 | 2.43k | } |
958 | | |
959 | | |
960 | | #ifdef HAVE_ED448_KEY_EXPORT |
961 | | |
962 | | /* Export the ed448 public key. |
963 | | * |
964 | | * key [in] Ed448 public key. |
965 | | * out [in] Array to hold public key. |
966 | | * outLen [in/out] On in, the number of bytes in array. |
967 | | * On out, the number bytes put into array. |
968 | | * returns BAD_FUNC_ARG when a parameter is NULL, |
969 | | * ECC_BAD_ARG_E when outLen is less than ED448_PUB_KEY_SIZE, |
970 | | * 0 otherwise. |
971 | | */ |
972 | | int wc_ed448_export_public(ed448_key* key, byte* out, word32* outLen) |
973 | 60 | { |
974 | 60 | int ret = 0; |
975 | | |
976 | | /* sanity check on arguments */ |
977 | 60 | if ((key == NULL) || (out == NULL) || (outLen == NULL)) { |
978 | 24 | ret = BAD_FUNC_ARG; |
979 | 24 | } |
980 | | |
981 | 60 | if ((ret == 0) && (*outLen < ED448_PUB_KEY_SIZE)) { |
982 | 3 | *outLen = ED448_PUB_KEY_SIZE; |
983 | 3 | ret = BUFFER_E; |
984 | 3 | } |
985 | | |
986 | 60 | if (ret == 0) { |
987 | 33 | *outLen = ED448_PUB_KEY_SIZE; |
988 | 33 | XMEMCPY(out, key->p, ED448_PUB_KEY_SIZE); |
989 | 33 | } |
990 | | |
991 | 60 | return ret; |
992 | 60 | } |
993 | | |
994 | | #endif /* HAVE_ED448_KEY_EXPORT */ |
995 | | |
996 | | |
997 | | #ifdef HAVE_ED448_KEY_IMPORT |
998 | | /* Import a compressed or uncompressed ed448 public key from a byte array. |
999 | | * Public key encoded in big-endian. |
1000 | | * |
1001 | | * in [in] Array holding public key. |
1002 | | * inLen [in] Number of bytes of data in array. |
1003 | | * key [in] Ed448 public key. |
1004 | | * trusted [in] Indicates whether the public key data is trusted. |
1005 | | * When 0, checks public key matches private key. |
1006 | | * When 1, doesn't check public key matches private key. |
1007 | | * returns BAD_FUNC_ARG when a parameter is NULL or key format is not supported, |
1008 | | * 0 otherwise. |
1009 | | */ |
1010 | | int wc_ed448_import_public_ex(const byte* in, word32 inLen, ed448_key* key, |
1011 | | int trusted) |
1012 | 1.22k | { |
1013 | 1.22k | int ret = 0; |
1014 | | |
1015 | | /* sanity check on arguments */ |
1016 | 1.22k | if ((in == NULL) || (key == NULL)) { |
1017 | 0 | ret = BAD_FUNC_ARG; |
1018 | 0 | } |
1019 | | |
1020 | 1.22k | if ((inLen != ED448_PUB_KEY_SIZE) && (inLen != ED448_PUB_KEY_SIZE + 1)) { |
1021 | 25 | ret = BAD_FUNC_ARG; |
1022 | 25 | } |
1023 | | |
1024 | 1.22k | if (ret == 0) { |
1025 | | /* compressed prefix according to draft |
1026 | | * https://tools.ietf.org/html/draft-ietf-openpgp-rfc4880bis-06 */ |
1027 | 1.20k | if (in[0] == 0x40 && inLen > ED448_PUB_KEY_SIZE) { |
1028 | | /* key is stored in compressed format so just copy in */ |
1029 | 1 | XMEMCPY(key->p, (in + 1), ED448_PUB_KEY_SIZE); |
1030 | 1 | } |
1031 | | /* importing uncompressed public key */ |
1032 | 1.20k | else if (in[0] == 0x04 && inLen > 2*ED448_PUB_KEY_SIZE) { |
1033 | | /* pass in (x,y) and store compressed key */ |
1034 | 0 | ret = ge448_compress_key(key->p, in+1, in+1+ED448_PUB_KEY_SIZE); |
1035 | 0 | } |
1036 | 1.20k | else if (inLen == ED448_PUB_KEY_SIZE) { |
1037 | | /* if not specified compressed or uncompressed check key size |
1038 | | * if key size is equal to compressed key size copy in key */ |
1039 | 1.19k | XMEMCPY(key->p, in, ED448_PUB_KEY_SIZE); |
1040 | 1.19k | } |
1041 | 2 | else { |
1042 | | /* bad public key format */ |
1043 | 2 | ret = BAD_FUNC_ARG; |
1044 | 2 | } |
1045 | 1.20k | } |
1046 | | |
1047 | 1.22k | if (ret == 0) { |
1048 | 1.19k | key->pubKeySet = 1; |
1049 | 1.19k | if (!trusted) { |
1050 | | /* Check untrusted public key data matches private key. */ |
1051 | 1.19k | ret = wc_ed448_check_key(key); |
1052 | 1.19k | } |
1053 | 1.19k | } |
1054 | | |
1055 | 1.22k | if ((ret != 0) && (key != NULL)) { |
1056 | | /* No public key set on failure. */ |
1057 | 99 | key->pubKeySet = 0; |
1058 | 99 | } |
1059 | | |
1060 | 1.22k | return ret; |
1061 | 1.22k | } |
1062 | | |
1063 | | /* Import a compressed or uncompressed ed448 public key from a byte array. |
1064 | | * |
1065 | | * Public key encoded in big-endian. |
1066 | | * Public key is not trusted and is checked against private key if set. |
1067 | | * |
1068 | | * in [in] Array holding public key. |
1069 | | * inLen [in] Number of bytes of data in array. |
1070 | | * key [in] Ed448 public key. |
1071 | | * returns BAD_FUNC_ARG when a parameter is NULL or key format is not supported, |
1072 | | * 0 otherwise. |
1073 | | */ |
1074 | | int wc_ed448_import_public(const byte* in, word32 inLen, ed448_key* key) |
1075 | 1.22k | { |
1076 | 1.22k | return wc_ed448_import_public_ex(in, inLen, key, 0); |
1077 | 1.22k | } |
1078 | | |
1079 | | /* Import an ed448 private key from a byte array. |
1080 | | * |
1081 | | * priv [in] Array holding private key. |
1082 | | * privSz [in] Number of bytes of data in array. |
1083 | | * key [in] Ed448 private key. |
1084 | | * returns BAD_FUNC_ARG when a parameter is NULL or privSz is less than |
1085 | | * ED448_KEY_SIZE, |
1086 | | * 0 otherwise. |
1087 | | */ |
1088 | | int wc_ed448_import_private_only(const byte* priv, word32 privSz, |
1089 | | ed448_key* key) |
1090 | 876 | { |
1091 | 876 | int ret = 0; |
1092 | | |
1093 | | /* sanity check on arguments */ |
1094 | 876 | if ((priv == NULL) || (key == NULL)) { |
1095 | 0 | ret = BAD_FUNC_ARG; |
1096 | 0 | } |
1097 | | |
1098 | | /* key size check */ |
1099 | 876 | if ((ret == 0) && (privSz != ED448_KEY_SIZE)) { |
1100 | 20 | ret = BAD_FUNC_ARG; |
1101 | 20 | } |
1102 | | |
1103 | 876 | if (ret == 0) { |
1104 | 856 | XMEMCPY(key->k, priv, ED448_KEY_SIZE); |
1105 | 856 | key->privKeySet = 1; |
1106 | 856 | } |
1107 | | |
1108 | 876 | if ((ret == 0) && key->pubKeySet) { |
1109 | | /* Validate loaded public key */ |
1110 | 0 | ret = wc_ed448_check_key(key); |
1111 | 0 | } |
1112 | | |
1113 | 876 | if ((ret != 0) && (key != NULL)) { |
1114 | | /* No private key set on error. */ |
1115 | 20 | key->privKeySet = 0; |
1116 | 20 | ForceZero(key->k, ED448_KEY_SIZE); |
1117 | 20 | } |
1118 | | |
1119 | 876 | return ret; |
1120 | 876 | } |
1121 | | |
1122 | | |
1123 | | /* Import an ed448 private and public keys from byte array(s). |
1124 | | * |
1125 | | * priv [in] Array holding private key from wc_ed448_export_private_only(), |
1126 | | * or private+public keys from wc_ed448_export_private(). |
1127 | | * privSz [in] Number of bytes of data in private key array. |
1128 | | * pub [in] Array holding public key (or NULL). |
1129 | | * pubSz [in] Number of bytes of data in public key array (or 0). |
1130 | | * key [in] Ed448 private/public key. |
1131 | | * trusted [in] Indicates whether the public key data is trusted. |
1132 | | * When 0, checks public key matches private key. |
1133 | | * When 1, doesn't check public key matches private key. |
1134 | | * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid |
1135 | | * combination of keys/lengths is supplied, 0 otherwise. |
1136 | | */ |
1137 | | int wc_ed448_import_private_key_ex(const byte* priv, word32 privSz, |
1138 | | const byte* pub, word32 pubSz, ed448_key* key, int trusted) |
1139 | 0 | { |
1140 | 0 | int ret; |
1141 | | |
1142 | | /* sanity check on arguments */ |
1143 | 0 | if (priv == NULL || key == NULL) |
1144 | 0 | return BAD_FUNC_ARG; |
1145 | | |
1146 | | /* key size check */ |
1147 | 0 | if (privSz != ED448_KEY_SIZE && privSz != ED448_PRV_KEY_SIZE) |
1148 | 0 | return BAD_FUNC_ARG; |
1149 | | |
1150 | 0 | if (pub == NULL) { |
1151 | 0 | if (pubSz != 0) |
1152 | 0 | return BAD_FUNC_ARG; |
1153 | 0 | if (privSz != ED448_PRV_KEY_SIZE) |
1154 | 0 | return BAD_FUNC_ARG; |
1155 | 0 | pub = priv + ED448_KEY_SIZE; |
1156 | 0 | pubSz = ED448_PUB_KEY_SIZE; |
1157 | 0 | } |
1158 | 0 | else if (pubSz < ED448_PUB_KEY_SIZE) { |
1159 | 0 | return BAD_FUNC_ARG; |
1160 | 0 | } |
1161 | | |
1162 | 0 | XMEMCPY(key->k, priv, ED448_KEY_SIZE); |
1163 | 0 | key->privKeySet = 1; |
1164 | | |
1165 | | /* import public key */ |
1166 | 0 | ret = wc_ed448_import_public_ex(pub, pubSz, key, trusted); |
1167 | 0 | if (ret != 0) { |
1168 | 0 | key->privKeySet = 0; |
1169 | 0 | ForceZero(key->k, ED448_KEY_SIZE); |
1170 | 0 | return ret; |
1171 | 0 | } |
1172 | | |
1173 | | /* make the private key (priv + pub) */ |
1174 | 0 | XMEMCPY(key->k + ED448_KEY_SIZE, key->p, ED448_PUB_KEY_SIZE); |
1175 | |
|
1176 | 0 | return ret; |
1177 | 0 | } |
1178 | | |
1179 | | /* Import an ed448 private and public keys from byte array(s). |
1180 | | * |
1181 | | * Public key is not trusted and is checked against private key. |
1182 | | * |
1183 | | * priv [in] Array holding private key from wc_ed448_export_private_only(), |
1184 | | * or private+public keys from wc_ed448_export_private(). |
1185 | | * privSz [in] Number of bytes of data in private key array. |
1186 | | * pub [in] Array holding public key (or NULL). |
1187 | | * pubSz [in] Number of bytes of data in public key array (or 0). |
1188 | | * key [in] Ed448 private/public key. |
1189 | | * returns BAD_FUNC_ARG when a required parameter is NULL or an invalid |
1190 | | * combination of keys/lengths is supplied, 0 otherwise. |
1191 | | */ |
1192 | | int wc_ed448_import_private_key(const byte* priv, word32 privSz, |
1193 | | const byte* pub, word32 pubSz, ed448_key* key) |
1194 | 0 | { |
1195 | 0 | return wc_ed448_import_private_key_ex(priv, privSz, pub, pubSz, key, 0); |
1196 | 0 | } |
1197 | | |
1198 | | #endif /* HAVE_ED448_KEY_IMPORT */ |
1199 | | |
1200 | | |
1201 | | #ifdef HAVE_ED448_KEY_EXPORT |
1202 | | |
1203 | | /* Export the ed448 private key. |
1204 | | * |
1205 | | * key [in] Ed448 private key. |
1206 | | * out [in] Array to hold private key. |
1207 | | * outLen [in/out] On in, the number of bytes in array. |
1208 | | * On out, the number bytes put into array. |
1209 | | * returns BAD_FUNC_ARG when a parameter is NULL, |
1210 | | * ECC_BAD_ARG_E when outLen is less than ED448_KEY_SIZE, |
1211 | | * 0 otherwise. |
1212 | | */ |
1213 | | int wc_ed448_export_private_only(ed448_key* key, byte* out, word32* outLen) |
1214 | 126 | { |
1215 | 126 | int ret = 0; |
1216 | | |
1217 | | /* sanity checks on arguments */ |
1218 | 126 | if ((key == NULL) || (out == NULL) || (outLen == NULL)) { |
1219 | 43 | ret = BAD_FUNC_ARG; |
1220 | 43 | } |
1221 | | |
1222 | 126 | if ((ret == 0) && (*outLen < ED448_KEY_SIZE)) { |
1223 | 4 | *outLen = ED448_KEY_SIZE; |
1224 | 4 | ret = BUFFER_E; |
1225 | 4 | } |
1226 | | |
1227 | 126 | if (ret == 0) { |
1228 | 79 | *outLen = ED448_KEY_SIZE; |
1229 | 79 | XMEMCPY(out, key->k, ED448_KEY_SIZE); |
1230 | 79 | } |
1231 | | |
1232 | 126 | return ret; |
1233 | 126 | } |
1234 | | |
1235 | | /* Export the ed448 private and public key. |
1236 | | * |
1237 | | * key [in] Ed448 private/public key. |
1238 | | * out [in] Array to hold private and public key. |
1239 | | * outLen [in/out] On in, the number of bytes in array. |
1240 | | * On out, the number bytes put into array. |
1241 | | * returns BAD_FUNC_ARG when a parameter is NULL, |
1242 | | * BUFFER_E when outLen is less than ED448_PRV_KEY_SIZE, |
1243 | | * 0 otherwise. |
1244 | | */ |
1245 | | int wc_ed448_export_private(ed448_key* key, byte* out, word32* outLen) |
1246 | 0 | { |
1247 | 0 | int ret = 0; |
1248 | | |
1249 | | /* sanity checks on arguments */ |
1250 | 0 | if ((key == NULL) || (out == NULL) || (outLen == NULL)) { |
1251 | 0 | ret = BAD_FUNC_ARG; |
1252 | 0 | } |
1253 | |
|
1254 | 0 | if ((ret == 0) && (*outLen < ED448_PRV_KEY_SIZE)) { |
1255 | 0 | *outLen = ED448_PRV_KEY_SIZE; |
1256 | 0 | ret = BUFFER_E; |
1257 | 0 | } |
1258 | |
|
1259 | 0 | if (ret == 0) { |
1260 | 0 | *outLen = ED448_PRV_KEY_SIZE; |
1261 | 0 | XMEMCPY(out, key->k, ED448_PRV_KEY_SIZE); |
1262 | 0 | } |
1263 | |
|
1264 | 0 | return ret; |
1265 | 0 | } |
1266 | | |
1267 | | /* Export the ed448 private and public key. |
1268 | | * |
1269 | | * key [in] Ed448 private/public key. |
1270 | | * priv [in] Array to hold private key. |
1271 | | * privSz [in/out] On in, the number of bytes in private key array. |
1272 | | * pub [in] Array to hold public key. |
1273 | | * pubSz [in/out] On in, the number of bytes in public key array. |
1274 | | * On out, the number bytes put into array. |
1275 | | * returns BAD_FUNC_ARG when a parameter is NULL, |
1276 | | * BUFFER_E when privSz is less than ED448_PRV_KEY_SIZE or pubSz is less |
1277 | | * than ED448_PUB_KEY_SIZE, |
1278 | | * 0 otherwise. |
1279 | | */ |
1280 | | int wc_ed448_export_key(ed448_key* key, byte* priv, word32 *privSz, |
1281 | | byte* pub, word32 *pubSz) |
1282 | 0 | { |
1283 | 0 | int ret = 0; |
1284 | | |
1285 | | /* export 'full' private part */ |
1286 | 0 | ret = wc_ed448_export_private(key, priv, privSz); |
1287 | 0 | if (ret == 0) { |
1288 | | /* export public part */ |
1289 | 0 | ret = wc_ed448_export_public(key, pub, pubSz); |
1290 | 0 | } |
1291 | |
|
1292 | 0 | return ret; |
1293 | 0 | } |
1294 | | |
1295 | | #endif /* HAVE_ED448_KEY_EXPORT */ |
1296 | | |
1297 | | /* Check the public key is valid. |
1298 | | * |
1299 | | * When private key available, check the calculated public key matches. |
1300 | | * When no private key, check Y is in range and an X is able to be calculated. |
1301 | | * |
1302 | | * @param [in] key Ed448 private/public key. |
1303 | | * @return 0 otherwise. |
1304 | | * @return BAD_FUNC_ARG when key is NULL. |
1305 | | * @return PUBLIC_KEY_E when the public key is not set, doesn't match or is |
1306 | | * invalid. |
1307 | | * @return other -ve value on hash failure. |
1308 | | */ |
1309 | | int wc_ed448_check_key(ed448_key* key) |
1310 | 1.32k | { |
1311 | 1.32k | int ret = 0; |
1312 | 1.32k | unsigned char pubKey[ED448_PUB_KEY_SIZE]; |
1313 | | |
1314 | | /* Validate parameter. */ |
1315 | 1.32k | if (key == NULL) { |
1316 | 0 | ret = BAD_FUNC_ARG; |
1317 | 0 | } |
1318 | | |
1319 | | /* Check we have a public key to check. */ |
1320 | 1.32k | if (ret == 0 && !key->pubKeySet) { |
1321 | 0 | ret = PUBLIC_KEY_E; |
1322 | 0 | } |
1323 | | |
1324 | | /* If we have a private key just make the public key and compare. */ |
1325 | 1.32k | if ((ret == 0) && key->privKeySet) { |
1326 | 126 | ret = wc_ed448_make_public(key, pubKey, sizeof(pubKey)); |
1327 | 126 | if ((ret == 0) && (XMEMCMP(pubKey, key->p, ED448_PUB_KEY_SIZE) != 0)) { |
1328 | 0 | ret = PUBLIC_KEY_E; |
1329 | 0 | } |
1330 | 126 | } |
1331 | | /* No private key, check Y is valid. */ |
1332 | 1.19k | else if ((ret == 0) && (!key->privKeySet)) { |
1333 | | /* Verify that Q is not identity element 0. |
1334 | | * 0 has no representation for Ed448. */ |
1335 | | |
1336 | | /* Verify that xQ and yQ are integers in the interval [0, p - 1]. |
1337 | | * Only have yQ so check that ordinate. |
1338 | | * p = 2^448-2^224-1 = 0xff..fe..ff |
1339 | | */ |
1340 | 1.19k | { |
1341 | 1.19k | int i; |
1342 | 1.19k | ret = PUBLIC_KEY_E; |
1343 | | |
1344 | | /* Check top part before 0xFE. */ |
1345 | 2.52k | for (i = ED448_PUB_KEY_SIZE - 1; i > ED448_PUB_KEY_SIZE/2; i--) { |
1346 | 2.48k | if (key->p[i] < 0xff) { |
1347 | 1.16k | ret = 0; |
1348 | 1.16k | break; |
1349 | 1.16k | } |
1350 | 2.48k | } |
1351 | 1.19k | if (ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E)) { |
1352 | | /* Check against 0xFE. */ |
1353 | 39 | if (key->p[ED448_PUB_KEY_SIZE/2] < 0xfe) { |
1354 | 7 | ret = 0; |
1355 | 7 | } |
1356 | 32 | else if (key->p[ED448_PUB_KEY_SIZE/2] == 0xfe) { |
1357 | | /* Check bottom part before last byte. */ |
1358 | 461 | for (i = ED448_PUB_KEY_SIZE/2 - 1; i > 0; i--) { |
1359 | 446 | if (key->p[i] != 0xff) { |
1360 | 16 | ret = 0; |
1361 | 16 | break; |
1362 | 16 | } |
1363 | 446 | } |
1364 | | /* Check last byte. */ |
1365 | 31 | if ((ret == WC_NO_ERR_TRACE(PUBLIC_KEY_E)) && |
1366 | 31 | (key->p[0] < 0xff)) { |
1367 | 14 | ret = 0; |
1368 | 14 | } |
1369 | 31 | } |
1370 | 39 | } |
1371 | 1.19k | } |
1372 | | |
1373 | 1.19k | if (ret == 0) { |
1374 | | /* Verify that Q is on the curve. |
1375 | | * Uncompressing the public key will validate yQ. */ |
1376 | 1.19k | ge448_p2 A; |
1377 | | |
1378 | 1.19k | if (ge448_from_bytes_negate_vartime(&A, key->p) != 0) { |
1379 | 70 | ret = PUBLIC_KEY_E; |
1380 | 70 | } |
1381 | 1.19k | } |
1382 | 1.19k | } |
1383 | | |
1384 | 1.32k | return ret; |
1385 | 1.32k | } |
1386 | | |
1387 | | /* Returns the size of an ed448 private key. |
1388 | | * |
1389 | | * key [in] Ed448 private/public key. |
1390 | | * returns BAD_FUNC_ARG when key is NULL, |
1391 | | * ED448_KEY_SIZE otherwise. |
1392 | | */ |
1393 | | int wc_ed448_size(ed448_key* key) |
1394 | 0 | { |
1395 | 0 | int ret = ED448_KEY_SIZE; |
1396 | |
|
1397 | 0 | if (key == NULL) { |
1398 | 0 | ret = BAD_FUNC_ARG; |
1399 | 0 | } |
1400 | |
|
1401 | 0 | return ret; |
1402 | 0 | } |
1403 | | |
1404 | | /* Returns the size of an ed448 private plus public key. |
1405 | | * |
1406 | | * key [in] Ed448 private/public key. |
1407 | | * returns BAD_FUNC_ARG when key is NULL, |
1408 | | * ED448_PRV_KEY_SIZE otherwise. |
1409 | | */ |
1410 | | int wc_ed448_priv_size(ed448_key* key) |
1411 | 0 | { |
1412 | 0 | int ret = ED448_PRV_KEY_SIZE; |
1413 | |
|
1414 | 0 | if (key == NULL) { |
1415 | 0 | ret = BAD_FUNC_ARG; |
1416 | 0 | } |
1417 | |
|
1418 | 0 | return ret; |
1419 | 0 | } |
1420 | | |
1421 | | /* Returns the size of an ed448 public key. |
1422 | | * |
1423 | | * key [in] Ed448 private/public key. |
1424 | | * returns BAD_FUNC_ARG when key is NULL, |
1425 | | * ED448_PUB_KEY_SIZE otherwise. |
1426 | | */ |
1427 | | int wc_ed448_pub_size(ed448_key* key) |
1428 | 0 | { |
1429 | 0 | int ret = ED448_PUB_KEY_SIZE; |
1430 | |
|
1431 | 0 | if (key == NULL) { |
1432 | 0 | ret = BAD_FUNC_ARG; |
1433 | 0 | } |
1434 | |
|
1435 | 0 | return ret; |
1436 | 0 | } |
1437 | | |
1438 | | /* Returns the size of an ed448 signature. |
1439 | | * |
1440 | | * key [in] Ed448 private/public key. |
1441 | | * returns BAD_FUNC_ARG when key is NULL, |
1442 | | * ED448_SIG_SIZE otherwise. |
1443 | | */ |
1444 | | int wc_ed448_sig_size(ed448_key* key) |
1445 | 0 | { |
1446 | 0 | int ret = ED448_SIG_SIZE; |
1447 | |
|
1448 | 0 | if (key == NULL) { |
1449 | 0 | ret = BAD_FUNC_ARG; |
1450 | 0 | } |
1451 | |
|
1452 | 0 | return ret; |
1453 | 0 | } |
1454 | | |
1455 | | #endif /* HAVE_ED448 */ |
1456 | | |