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