From 5e8da2348fa6ae4d49fe090046708b784e0e7ac5 Mon Sep 17 00:00:00 2001 From: Daniel Pouzzner Date: Wed, 14 Jul 2021 15:32:33 -0500 Subject: [PATCH] ED: add --enable-ed25519-stream and --enable-ed448-stream to configure.ac, disabled by default, and add them to --enable-all and --enable-all-crypto lists, along with --enable-aesgcm-stream; report AES-GCM and ED* streaming API options in feature summary rendered at end; refactor ED routines to pivot on WOLFSSL_ED*_PERSISTENT_SHA and WOLFSSL_ED*_STREAMING_VERIFY macros, with sha state in the key struct only when WOLFSSL_ED*_PERSISTENT_SHA, otherwise on the stack as before; add ed*_hash_init() and ed*_hash_free() local helpers; ED* peer review: fix line lengths, remove superfluous retval checks, tweaks for efficiency, and add ED448_PREHASH_SIZE to ed448.h. --- configure.ac | 43 +++++- wolfcrypt/src/ed25519.c | 270 +++++++++++++++++++++++++--------- wolfcrypt/src/ed448.c | 274 +++++++++++++++++++++++++---------- wolfcrypt/test/test.c | 8 + wolfssl/wolfcrypt/ed25519.h | 4 + wolfssl/wolfcrypt/ed448.h | 5 + wolfssl/wolfcrypt/settings.h | 8 + 7 files changed, 462 insertions(+), 150 deletions(-) diff --git a/configure.ac b/configure.ac index b25fb2389..0caa104dd 100644 --- a/configure.ac +++ b/configure.ac @@ -350,6 +350,7 @@ then test "$enable_atomicuser" = "" && enable_atomicuser=yes test "$enable_pkcallbacks" = "" && enable_pkcallbacks=yes test "$enable_aesgcm" = "" && enable_aesgcm=yes + test "$enable_aesgcm_stream" = "" && enable_aesgcm_stream=yes test "$enable_aesccm" = "" && enable_aesccm=yes test "$enable_aesctr" = "" && enable_aesctr=yes test "$enable_aesofb" = "" && enable_aesofb=yes @@ -459,7 +460,9 @@ then test "$enable_scep" = "" && enable_scep=yes test "$enable_pkcs7" = "" && enable_pkcs7=yes test "$enable_ed25519" = "" && enable_ed25519=yes + test "$enable_ed25519_stream" = "" && enable_ed25519_stream=yes test "$enable_ed448" = "" && enable_ed448=yes + test "$enable_ed448_stream" = "" && enable_ed448_stream=yes if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" then @@ -493,6 +496,7 @@ then test "$enable_atomicuser" = "" && enable_atomicuser=yes test "$enable_pkcallbacks" = "" && enable_pkcallbacks=yes test "$enable_aesgcm" = "" && enable_aesgcm=yes + test "$enable_aesgcm_stream" = "" && enable_aesgcm_stream=yes test "$enable_aesccm" = "" && enable_aesccm=yes test "$enable_aesctr" = "" && enable_aesctr=yes test "$enable_aesofb" = "" && enable_aesofb=yes @@ -561,7 +565,9 @@ then then test "$enable_xchacha" = "" && enable_xchacha=yes test "$enable_ed25519" = "" && enable_ed25519=yes + test "$enable_ed25519_stream" = "" && enable_ed25519_stream=yes test "$enable_ed448" = "" && enable_ed448=yes + test "$enable_ed448_stream" = "" && enable_ed448_stream=yes test "$enable_pkcs7" = "" && enable_pkcs7=yes if test "$ENABLED_LINUXKM_DEFAULTS" != "yes" @@ -1311,7 +1317,7 @@ AC_ARG_ENABLE([aesgcm], [ ENABLED_AESGCM=yes ] ) AC_ARG_ENABLE([aesgcm-stream], - [AS_HELP_STRING([--enable-aesgcm-stream],[Enable wolfSSL AES-GCM support with streaming APIs (default: enabled)])], + [AS_HELP_STRING([--enable-aesgcm-stream],[Enable wolfSSL AES-GCM support with streaming APIs (default: disabled)])], [ ENABLED_AESGCM_STREAM=$enableval ], [ ENABLED_AESGCM_STREAM=no ] ) @@ -2141,6 +2147,11 @@ AC_ARG_ENABLE([ed25519], [ ENABLED_ED25519=$enableval ], [ ENABLED_ED25519=no ] ) +AC_ARG_ENABLE([ed25519-stream], + [AS_HELP_STRING([--enable-ed25519-stream],[Enable wolfSSL ED25519 support with streaming verify APIs (default: disabled)])], + [ ENABLED_ED25519_STREAM=$enableval ], + [ ENABLED_ED25519_STREAM=no ] + ) if test "$ENABLED_OPENSSH" = "yes" @@ -2169,6 +2180,17 @@ then ENABLED_CERTS=yes fi +if test "$ENABLED_ED25519_STREAM" != "no" +then + if test "$ENABLED_ED25519" = "no" + then + AC_MSG_ERROR([ED25519 verify streaming enabled but ED25519 is disabled]) + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ED25519_STREAMING_VERIFY" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_ED25519_STREAMING_VERIFY" + fi +fi + # for using memory optimization setting on both curve448 and ed448 ENABLED_CURVE448_SMALL=no @@ -2206,6 +2228,11 @@ AC_ARG_ENABLE([ed448], [ ENABLED_ED448=$enableval ], [ ENABLED_ED448=no ] ) +AC_ARG_ENABLE([ed448-stream], + [AS_HELP_STRING([--enable-ed448-stream],[Enable wolfSSL ED448 support with streaming verify APIs (default: disabled)])], + [ ENABLED_ED448_STREAM=$enableval ], + [ ENABLED_ED448_STREAM=no ] + ) if test "$ENABLED_ED448" != "no" && test "$ENABLED_32BIT" = "no" then @@ -2236,6 +2263,17 @@ then ENABLED_CERTS=yes fi +if test "$ENABLED_ED448_STREAM" != "no" +then + if test "$ENABLED_ED448" = "no" + then + AC_MSG_ERROR([ED448 verify streaming enabled but ED448 is disabled]) + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ED448_STREAMING_VERIFY" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_ED448_STREAMING_VERIFY" + fi +fi + # FP ECC, Fixed Point cache ECC @@ -6671,6 +6709,7 @@ echo " * AES-NI: $ENABLED_AESNI" echo " * AES-CBC: $ENABLED_AESCBC" echo " * AES-CBC length checks: $ENABLED_AESCBC_LENGTH_CHECKS" echo " * AES-GCM: $ENABLED_AESGCM" +echo " * AES-GCM streaming: $ENABLED_AESGCM_STREAM" echo " * AES-CCM: $ENABLED_AESCCM" echo " * AES-CTR: $ENABLED_AESCTR" echo " * AES-CFB: $ENABLED_AESCFB" @@ -6722,8 +6761,10 @@ echo " * ECC Custom Curves: $ENABLED_ECCCUSTCURVES" echo " * ECC Minimum Bits: $ENABLED_ECCMINSZ" echo " * CURVE25519: $ENABLED_CURVE25519" echo " * ED25519: $ENABLED_ED25519" +echo " * ED25519 streaming: $ENABLED_ED25519_STREAM" echo " * CURVE448: $ENABLED_CURVE448" echo " * ED448: $ENABLED_ED448" +echo " * ED448 streaming: $ENABLED_ED448_STREAM" echo " * FPECC: $ENABLED_FPECC" echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" echo " * ECCSI $ENABLED_ECCSI" diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index b24c9985d..9c31699a9 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -56,6 +56,27 @@ static const byte ed25519Ctx[ED25519CTX_SIZE+1] = "SigEd25519 no Ed25519 collisions"; #endif +static int ed25519_hash_init(ed25519_key* key, wc_Sha512 *sha) +{ + int ret; + + ret = wc_InitSha512_ex(sha, key->heap, +#if defined(WOLF_CRYPTO_CB) + key->devId +#else + INVALID_DEVID +#endif + ); + +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + if (ret == 0) + key->sha_clean_flag = 1; +#endif + + return ret; +} + +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA static int ed25519_hash_reset(ed25519_key* key) { int ret; @@ -75,36 +96,73 @@ static int ed25519_hash_reset(ed25519_key* key) } return ret; } +#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */ -static int ed25519_hash_update(ed25519_key* key, const byte* data, word32 len) +static int ed25519_hash_update(ed25519_key* key, wc_Sha512 *sha, + const byte* data, word32 len) { +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA if (key->sha_clean_flag) key->sha_clean_flag = 0; - return wc_Sha512Update(&key->sha, data, len); +#else + (void)key; +#endif + return wc_Sha512Update(sha, data, len); } -static int ed25519_hash_final(ed25519_key* key, byte* hash) +static int ed25519_hash_final(ed25519_key* key, wc_Sha512 *sha, byte* hash) { - int ret = wc_Sha512Final(&key->sha, hash); + int ret = wc_Sha512Final(sha, hash); +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA if (ret == 0) key->sha_clean_flag = 1; +#else + (void)key; +#endif return ret; } +static void ed25519_hash_free(ed25519_key* key, wc_Sha512 *sha) +{ + wc_Sha512Free(sha); +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + key->sha_clean_flag = 0; +#else + (void)key; +#endif +} + + static int ed25519_hash(ed25519_key* key, const byte* in, word32 inLen, byte* hash) { int ret; +#ifndef WOLFSSL_ED25519_PERSISTENT_SHA + wc_Sha512 sha[1]; +#else + wc_Sha512 *sha; +#endif if (key == NULL || (in == NULL && inLen > 0) || hash == NULL) { return BAD_FUNC_ARG; } +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + sha = &key->sha; ret = ed25519_hash_reset(key); +#else + ret = ed25519_hash_init(key, sha); +#endif + if (ret < 0) + return ret; + + ret = ed25519_hash_update(key, sha, in, inLen); if (ret == 0) - ret = ed25519_hash_update(key, in, inLen); - if (ret == 0) - ret = ed25519_hash_final(key, hash); + ret = ed25519_hash_final(key, sha, hash); + +#ifndef WOLFSSL_ED25519_PERSISTENT_SHA + ed25519_hash_free(key, sha); +#endif return ret; } @@ -252,23 +310,38 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out, az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ az[31] |= 64; - if (ret != 0) - return ret; - if (type == Ed25519ctx || type == Ed25519ph) { - ret = ed25519_hash_update(key, ed25519Ctx, ED25519CTX_SIZE); + { +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + wc_Sha512 *sha = &key->sha; +#else + wc_Sha512 sha[1]; + ret = ed25519_hash_init(key, sha); + if (ret < 0) + return ret; +#endif + + if (type == Ed25519ctx || type == Ed25519ph) { + ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = ed25519_hash_update(key, sha, &type, sizeof(type)); + if (ret == 0) + ret = ed25519_hash_update(key, sha, &contextLen, + sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = ed25519_hash_update(key, sha, context, contextLen); + } if (ret == 0) - ret = ed25519_hash_update(key, &type, sizeof(type)); + ret = ed25519_hash_update(key, sha, az + ED25519_KEY_SIZE, + ED25519_KEY_SIZE); if (ret == 0) - ret = ed25519_hash_update(key, &contextLen, sizeof(contextLen)); - if (ret == 0 && context != NULL) - ret = ed25519_hash_update(key, context, contextLen); + ret = ed25519_hash_update(key, sha, in, inLen); + if (ret == 0) + ret = ed25519_hash_final(key, sha, nonce); +#ifndef WOLFSSL_ED25519_PERSISTENT_SHA + ed25519_hash_free(key, sha); +#endif } - if (ret == 0) - ret = ed25519_hash_update(key, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE); - if (ret == 0) - ret = ed25519_hash_update(key, in, inLen); - if (ret == 0) - ret = ed25519_hash_final(key, nonce); + if (ret != 0) return ret; @@ -290,23 +363,39 @@ int wc_ed25519_sign_msg_ex(const byte* in, word32 inLen, byte* out, /* step 3: hash R + public key + message getting H(R,A,M) then creating S = (r + H(R,A,M)a) mod l */ - if (type == Ed25519ctx || type == Ed25519ph) { - ret = ed25519_hash_update(key, ed25519Ctx, ED25519CTX_SIZE); + { +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + wc_Sha512 *sha = &key->sha; +#else + wc_Sha512 sha[1]; + ret = ed25519_hash_init(key, sha); + if (ret < 0) + return ret; +#endif + + if (type == Ed25519ctx || type == Ed25519ph) { + ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = ed25519_hash_update(key, sha, &type, sizeof(type)); + if (ret == 0) + ret = ed25519_hash_update(key, sha, &contextLen, + sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = ed25519_hash_update(key, sha, context, contextLen); + } if (ret == 0) - ret = ed25519_hash_update(key, &type, sizeof(type)); + ret = ed25519_hash_update(key, sha, out, ED25519_SIG_SIZE/2); if (ret == 0) - ret = ed25519_hash_update(key, &contextLen, sizeof(contextLen)); - if (ret == 0 && context != NULL) - ret = ed25519_hash_update(key, context, contextLen); + ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE); + if (ret == 0) + ret = ed25519_hash_update(key, sha, in, inLen); + if (ret == 0) + ret = ed25519_hash_final(key, sha, hram); +#ifndef WOLFSSL_ED25519_PERSISTENT_SHA + ed25519_hash_free(key, sha); +#endif } - if (ret == 0) - ret = ed25519_hash_update(key, out, ED25519_SIG_SIZE/2); - if (ret == 0) - ret = ed25519_hash_update(key, key->p, ED25519_PUB_KEY_SIZE); - if (ret == 0) - ret = ed25519_hash_update(key, in, inLen); - if (ret == 0) - ret = ed25519_hash_final(key, hram); + if (ret != 0) return ret; @@ -413,10 +502,12 @@ int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out, context extra signing data contextLen length of extra signing data */ -int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key, - byte type, const byte* context, byte contextLen) +static int ed25519_verify_msg_init_with_sha(const byte* sig, word32 sigLen, + ed25519_key* key, wc_Sha512 *sha, + byte type, const byte* context, + byte contextLen) { - int ret; + int ret; /* sanity check on arguments */ if (sig == NULL || key == NULL || @@ -430,22 +521,27 @@ int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key, /* find H(R,A,M) and store it as h */ +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA ret = ed25519_hash_reset(key); if (ret != 0) return ret; +#else + ret = 0; +#endif + if (type == Ed25519ctx || type == Ed25519ph) { - ret = ed25519_hash_update(key, ed25519Ctx, ED25519CTX_SIZE); + ret = ed25519_hash_update(key, sha, ed25519Ctx, ED25519CTX_SIZE); if (ret == 0) - ret = ed25519_hash_update(key, &type, sizeof(type)); + ret = ed25519_hash_update(key, sha, &type, sizeof(type)); if (ret == 0) - ret = ed25519_hash_update(key, &contextLen, sizeof(contextLen)); + ret = ed25519_hash_update(key, sha, &contextLen, sizeof(contextLen)); if (ret == 0 && context != NULL) - ret = ed25519_hash_update(key, context, contextLen); + ret = ed25519_hash_update(key, sha, context, contextLen); } if (ret == 0) - ret = ed25519_hash_update(key, sig, ED25519_SIG_SIZE/2); + ret = ed25519_hash_update(key, sha, sig, ED25519_SIG_SIZE/2); if (ret == 0) - ret = ed25519_hash_update(key, key->p, ED25519_PUB_KEY_SIZE); + ret = ed25519_hash_update(key, sha, key->p, ED25519_PUB_KEY_SIZE); return ret; } @@ -456,13 +552,15 @@ int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key, key Ed25519 public key return 0 on success */ -int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, - ed25519_key* key) { +static int ed25519_verify_msg_update_with_sha(const byte* msgSegment, + word32 msgSegmentLen, + ed25519_key* key, + wc_Sha512 *sha) { /* sanity check on arguments */ if (msgSegment == NULL || key == NULL) return BAD_FUNC_ARG; - return ed25519_hash_update(key, msgSegment, msgSegmentLen); + return ed25519_hash_update(key, sha, msgSegment, msgSegmentLen); } /* @@ -472,8 +570,9 @@ int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, key Ed25519 public key return 0 and res of 1 on success */ -int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, - ed25519_key* key) +static int ed25519_verify_msg_final_with_sha(const byte* sig, word32 sigLen, + int* res, ed25519_key* key, + wc_Sha512 *sha) { byte rcheck[ED25519_KEY_SIZE]; byte h[WC_SHA512_DIGEST_SIZE]; @@ -502,7 +601,7 @@ int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, /* find H(R,A,M) and store it as h */ - ret = ed25519_hash_final(key, h); + ret = ed25519_hash_final(key, sha, h); if (ret != 0) return ret; @@ -535,6 +634,27 @@ int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, return ret; } +#ifdef WOLFSSL_ED25519_STREAMING_VERIFY + +int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key, + byte type, const byte* context, byte contextLen) { + return ed25519_verify_msg_init_with_sha(sig, sigLen, key, &key->sha, + type, context, contextLen); +} + +int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, + ed25519_key* key) { + return ed25519_verify_msg_update_with_sha(msgSegment, msgSegmentLen, + key, &key->sha); +} + +int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, + ed25519_key* key) { + return ed25519_verify_msg_final_with_sha(sig, sigLen, res, + key, &key->sha); +} + +#endif /* WOLFSSL_ED25519_STREAMING_VERIFY */ /* sig is array of bytes containing the signature @@ -550,6 +670,11 @@ int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, byte type, const byte* context, byte contextLen) { int ret; +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + wc_Sha512 *sha; +#else + wc_Sha512 sha[1]; +#endif /* sanity check on arguments */ if (sig == NULL || msg == NULL || res == NULL || key == NULL || @@ -566,16 +691,24 @@ int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, } #endif - ret = wc_ed25519_verify_msg_init(sig, sigLen, key, +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + sha = &key->sha; +#else + ret = ed25519_hash_init(key, sha); + if (ret < 0) + return ret; +#endif + + ret = ed25519_verify_msg_init_with_sha(sig, sigLen, key, sha, type, context, contextLen); if (ret < 0) return ret; - ret = wc_ed25519_verify_msg_update(msg, msgLen, key); + ret = ed25519_verify_msg_update_with_sha(msg, msgLen, key, sha); if (ret < 0) return ret; - return wc_ed25519_verify_msg_final(sig, sigLen, res, key); + return ed25519_verify_msg_final_with_sha(sig, sigLen, res, key, sha); } /* @@ -591,7 +724,7 @@ int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* res, ed25519_key* key) { return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key, - (byte)Ed25519, NULL, 0); + (byte)Ed25519, NULL, 0); } /* @@ -610,7 +743,7 @@ int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg, const byte* context, byte contextLen) { return wc_ed25519_verify_msg_ex(sig, sigLen, msg, msgLen, res, key, - Ed25519ctx, context, contextLen); + Ed25519ctx, context, contextLen); } /* @@ -629,7 +762,7 @@ int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, const byte* context, byte contextLen) { return wc_ed25519_verify_msg_ex(sig, sigLen, hash, hashLen, res, key, - Ed25519ph, context, contextLen); + Ed25519ph, context, contextLen); } /* @@ -655,7 +788,7 @@ int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, return ret; return wc_ed25519_verify_msg_ex(sig, sigLen, hash, sizeof(hash), res, key, - Ed25519ph, context, contextLen); + Ed25519ph, context, contextLen); } #endif /* HAVE_ED25519_VERIFY */ @@ -663,8 +796,6 @@ int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, /* initialize information and memory for key */ int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId) { - int ret; - if (key == NULL) return BAD_FUNC_ARG; @@ -680,18 +811,11 @@ int wc_ed25519_init_ex(ed25519_key* key, void* heap, int devId) fe_init(); #endif - ret = wc_InitSha512_ex(&key->sha, key->heap, -#if defined(WOLF_CRYPTO_CB) - key->devId -#else - INVALID_DEVID -#endif - ); - - if (ret == 0) - key->sha_clean_flag = 1; - - return ret; +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + return ed25519_hash_init(key, &key->sha); +#else /* !WOLFSSL_ED25519_PERSISTENT_SHA */ + return 0; +#endif /* WOLFSSL_ED25519_PERSISTENT_SHA */ } int wc_ed25519_init(ed25519_key* key) @@ -705,7 +829,9 @@ void wc_ed25519_free(ed25519_key* key) if (key == NULL) return; - wc_Sha512Free(&key->sha); +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA + ed25519_hash_free(key, &key->sha); +#endif ForceZero(key, sizeof(ed25519_key)); } diff --git a/wolfcrypt/src/ed448.c b/wolfcrypt/src/ed448.c index 44d62efb9..cdbb3111b 100644 --- a/wolfcrypt/src/ed448.c +++ b/wolfcrypt/src/ed448.c @@ -51,6 +51,28 @@ static const byte ed448Ctx[ED448CTX_SIZE+1] = "SigEd448"; #endif + +static int ed448_hash_init(ed448_key* key, wc_Shake *sha) +{ + int ret; + + ret = wc_InitShake256(sha, key->heap, +#if defined(WOLF_CRYPTO_CB) + key->devId +#else + INVALID_DEVID +#endif + ); + +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + if (ret == 0) + key->sha_clean_flag = 1; +#endif + + return ret; +} + +#ifdef WOLFSSL_ED448_PERSISTENT_SHA static int ed448_hash_reset(ed448_key* key) { int ret; @@ -71,36 +93,74 @@ static int ed448_hash_reset(ed448_key* key) } return ret; } +#endif /* WOLFSSL_ED448_PERSISTENT_SHA */ -static int ed448_hash_update(ed448_key* key, const byte* data, word32 len) +static int ed448_hash_update(ed448_key* key, wc_Shake *sha, const byte* data, + word32 len) { +#ifdef WOLFSSL_ED448_PERSISTENT_SHA if (key->sha_clean_flag) key->sha_clean_flag = 0; - return wc_Shake256_Update(&key->sha, data, len); +#else + (void)key; +#endif + return wc_Shake256_Update(sha, data, len); } -static int ed448_hash_final(ed448_key* key, byte* hash, word32 hashLen) +static int ed448_hash_final(ed448_key* key, wc_Shake *sha, byte* hash, + word32 hashLen) { - int ret = wc_Shake256_Final(&key->sha, hash, hashLen); + int ret = wc_Shake256_Final(sha, hash, hashLen); +#ifdef WOLFSSL_ED448_PERSISTENT_SHA if (ret == 0) key->sha_clean_flag = 1; +#else + (void)key; +#endif return ret; } +static void ed448_hash_free(ed448_key* key, wc_Shake *sha) +{ + wc_Shake256_Free(sha); +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + key->sha_clean_flag = 0; +#else + (void)key; +#endif +} + + static int ed448_hash(ed448_key* key, const byte* in, word32 inLen, byte* hash, word32 hashLen) { int ret; +#ifndef WOLFSSL_ED448_PERSISTENT_SHA + wc_Shake sha[1]; +#else + wc_Shake *sha; +#endif if (key == NULL || (in == NULL && inLen > 0) || hash == NULL) { return BAD_FUNC_ARG; } +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + sha = &key->sha; ret = ed448_hash_reset(key); +#else + ret = ed448_hash_init(key, sha); +#endif + if (ret < 0) + return ret; + + ret = ed448_hash_update(key, sha, in, inLen); if (ret == 0) - ret = ed448_hash_update(key, in, inLen); - if (ret == 0) - ret = ed448_hash_final(key, hash, hashLen); + ret = ed448_hash_final(key, sha, hash, hashLen); + +#ifndef WOLFSSL_ED448_PERSISTENT_SHA + ed448_hash_free(key, sha); +#endif return ret; } @@ -234,34 +294,52 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out, ret = ed448_hash(key, key->k, ED448_KEY_SIZE, az, sizeof(az)); } if (ret == 0) { +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + wc_Shake *sha = &key->sha; +#else + wc_Shake sha[1]; + ret = ed448_hash_init(key, sha); + if (ret < 0) + return ret; +#endif /* apply clamp */ az[0] &= 0xfc; az[55] |= 0x80; az[56] = 0x00; + ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); + if (ret == 0) { - ret = ed448_hash_update(key, ed448Ctx, ED448CTX_SIZE); + ret = ed448_hash_update(key, sha, &type, sizeof(type)); } if (ret == 0) { - ret = ed448_hash_update(key, &type, sizeof(type)); - } - if (ret == 0) { - ret = ed448_hash_update(key, &contextLen, sizeof(contextLen)); + ret = ed448_hash_update(key, sha, &contextLen, sizeof(contextLen)); } if ((ret == 0) && (context != NULL)) { - ret = ed448_hash_update(key, context, contextLen); + ret = ed448_hash_update(key, sha, context, contextLen); } if (ret == 0) { - ret = ed448_hash_update(key, az + ED448_KEY_SIZE, ED448_KEY_SIZE); + ret = ed448_hash_update(key, sha, az + ED448_KEY_SIZE, ED448_KEY_SIZE); } if (ret == 0) { - ret = ed448_hash_update(key, in, inLen); + ret = ed448_hash_update(key, sha, in, inLen); } if (ret == 0) { - ret = ed448_hash_final(key, nonce, sizeof(nonce)); + ret = ed448_hash_final(key, sha, nonce, sizeof(nonce)); } +#ifndef WOLFSSL_ED448_PERSISTENT_SHA + ed448_hash_free(key, sha); +#endif } if (ret == 0) { +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + wc_Shake *sha = &key->sha; +#else + wc_Shake sha[1]; + ret = ed448_hash_init(key, sha); + if (ret < 0) + return ret; +#endif sc448_reduce(nonce); /* step 2: computing R = rB where rB is the scalar multiplication of @@ -271,30 +349,32 @@ int wc_ed448_sign_msg_ex(const byte* in, word32 inLen, byte* out, /* step 3: hash R + public key + message getting H(R,A,M) then creating S = (r + H(R,A,M)a) mod l */ + + ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); if (ret == 0) { - ret = ed448_hash_update(key, ed448Ctx, ED448CTX_SIZE); - if (ret == 0) { - ret = ed448_hash_update(key, &type, sizeof(type)); - } - if (ret == 0) { - ret = ed448_hash_update(key, &contextLen, sizeof(contextLen)); - } - if ((ret == 0) && (context != NULL)) { - ret = ed448_hash_update(key, context, contextLen); - } - if (ret == 0) { - ret = ed448_hash_update(key, out, ED448_SIG_SIZE/2); - } - if (ret == 0) { - ret = ed448_hash_update(key, key->p, ED448_PUB_KEY_SIZE); - } - if (ret == 0) { - ret = ed448_hash_update(key, in, inLen); - } - if (ret == 0) { - ret = ed448_hash_final(key, hram, sizeof(hram)); - } + ret = ed448_hash_update(key, sha, &type, sizeof(type)); } + if (ret == 0) { + ret = ed448_hash_update(key, sha, &contextLen, sizeof(contextLen)); + } + if ((ret == 0) && (context != NULL)) { + ret = ed448_hash_update(key, sha, context, contextLen); + } + if (ret == 0) { + ret = ed448_hash_update(key, sha, out, ED448_SIG_SIZE/2); + } + if (ret == 0) { + ret = ed448_hash_update(key, sha, key->p, ED448_PUB_KEY_SIZE); + } + if (ret == 0) { + ret = ed448_hash_update(key, sha, in, inLen); + } + if (ret == 0) { + ret = ed448_hash_final(key, sha, hram, sizeof(hram)); + } +#ifndef WOLFSSL_ED448_PERSISTENT_SHA + ed448_hash_free(key, sha); +#endif } if (ret == 0) { @@ -374,8 +454,8 @@ int wc_ed448ph_sign_hash(const byte* hash, word32 hashLen, byte* out, int wc_ed448ph_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, ed448_key* key, const byte* context, byte contextLen) { - int ret = 0; - byte hash[64]; + int ret; + byte hash[ED448_PREHASH_SIZE]; ret = ed448_hash(key, in, inLen, hash, sizeof(hash)); @@ -404,8 +484,10 @@ int wc_ed448ph_sign_msg(const byte* in, word32 inLen, byte* out, word32 *outLen, * other -ve values when hash fails, * 0 otherwise. */ -int wc_ed448_verify_msg_init(const byte* sig, word32 sigLen, ed448_key* key, - byte type, const byte* context, byte contextLen) + +static int ed448_verify_msg_init_with_sha(const byte* sig, word32 sigLen, + ed448_key* key, wc_Shake *sha, byte type, + const byte* context, byte contextLen) { int ret; @@ -421,25 +503,27 @@ int wc_ed448_verify_msg_init(const byte* sig, word32 sigLen, ed448_key* key, } /* find H(R,A,M) and store it as h */ +#ifdef WOLFSSL_ED448_PERSISTENT_SHA ret = ed448_hash_reset(key); if (ret < 0) return ret; +#endif - ret = ed448_hash_update(key, ed448Ctx, ED448CTX_SIZE); + ret = ed448_hash_update(key, sha, ed448Ctx, ED448CTX_SIZE); if (ret == 0) { - ret = ed448_hash_update(key, &type, sizeof(type)); + ret = ed448_hash_update(key, sha, &type, sizeof(type)); } if (ret == 0) { - ret = ed448_hash_update(key, &contextLen, sizeof(contextLen)); + ret = ed448_hash_update(key, sha, &contextLen, sizeof(contextLen)); } if ((ret == 0) && (context != NULL)) { - ret = ed448_hash_update(key, context, contextLen); + ret = ed448_hash_update(key, sha, context, contextLen); } if (ret == 0) { - ret = ed448_hash_update(key, sig, ED448_SIG_SIZE/2); + ret = ed448_hash_update(key, sha, sig, ED448_SIG_SIZE/2); } if (ret == 0) { - ret = ed448_hash_update(key, key->p, ED448_PUB_KEY_SIZE); + ret = ed448_hash_update(key, sha, key->p, ED448_PUB_KEY_SIZE); } return ret; @@ -451,14 +535,16 @@ int wc_ed448_verify_msg_init(const byte* sig, word32 sigLen, ed448_key* key, key Ed448 public key return 0 on success */ -int wc_ed448_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, - ed448_key* key) +static int ed448_verify_msg_update_with_sha(const byte* msgSegment, + word32 msgSegmentLen, + ed448_key* key, + wc_Shake *sha) { /* sanity check on arguments */ if (msgSegment == NULL || key == NULL) return BAD_FUNC_ARG; - return ed448_hash_update(key, msgSegment, msgSegmentLen); + return ed448_hash_update(key, sha, msgSegment, msgSegmentLen); } /* Verify the message using the ed448 public key. @@ -472,8 +558,8 @@ int wc_ed448_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, * other -ve values when hash fails, * 0 otherwise. */ -int wc_ed448_verify_msg_final(const byte* sig, word32 sigLen, - int* res, ed448_key* key) +static int ed448_verify_msg_final_with_sha(const byte* sig, word32 sigLen, + int* res, ed448_key* key, wc_Shake *sha) { byte rcheck[ED448_KEY_SIZE]; byte h[ED448_SIG_SIZE]; @@ -496,7 +582,7 @@ int wc_ed448_verify_msg_final(const byte* sig, word32 sigLen, if (ge448_from_bytes_negate_vartime(&A, key->p) != 0) return BAD_FUNC_ARG; - ret = ed448_hash_final(key, h, sizeof(h)); + ret = ed448_hash_final(key, sha, h, sizeof(h)); if (ret != 0) return ret; @@ -524,6 +610,28 @@ int wc_ed448_verify_msg_final(const byte* sig, word32 sigLen, return ret; } +#ifdef WOLFSSL_ED448_STREAMING_VERIFY +int wc_ed448_verify_msg_init(const byte* sig, word32 sigLen, ed448_key* key, + byte type, const byte* context, byte contextLen) +{ + return ed448_verify_msg_init_with_sha(sig, sigLen, key, &key->sha, type, + context, contextLen); +} + +int wc_ed448_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, + ed448_key* key) +{ + return ed448_verify_msg_update_with_sha(msgSegment, msgSegmentLen, key, + &key->sha); +} + +int wc_ed448_verify_msg_final(const byte* sig, word32 sigLen, + int* res, ed448_key* key) +{ + return ed448_verify_msg_final_with_sha(sig, sigLen, res, key, &key->sha); +} +#endif + /* Verify the message using the ed448 public key. * * sig [in] Signature to verify. @@ -546,16 +654,35 @@ int wc_ed448_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, byte type, const byte* context, byte contextLen) { int ret; - ret = wc_ed448_verify_msg_init(sig, sigLen, key, +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + wc_Shake *sha; +#else + wc_Shake sha[1]; +#endif + + if (key == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + sha = &key->sha; +#else + ret = ed448_hash_init(key, sha); + if (ret < 0) + return ret; +#endif + + ret = ed448_verify_msg_init_with_sha(sig, sigLen, key, sha, type, context, contextLen); - if (ret < 0) - return ret; + if (ret == 0) + ret = ed448_verify_msg_update_with_sha(msg, msgLen, key, sha); + if (ret == 0) + ret = ed448_verify_msg_final_with_sha(sig, sigLen, res, key, sha); - ret = wc_ed448_verify_msg_update(msg, msgLen, key); - if (ret < 0) - return ret; +#ifndef WOLFSSL_ED448_PERSISTENT_SHA + ed448_hash_free(key, sha); +#endif - return wc_ed448_verify_msg_final(sig, sigLen, res, key); + return ret; } /* Verify the message using the ed448 public key. @@ -627,7 +754,7 @@ int wc_ed448ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, const byte* context, byte contextLen) { int ret = 0; - byte hash[64]; + byte hash[ED448_PREHASH_SIZE]; ret = ed448_hash(key, msg, msgLen, hash, sizeof(hash)); @@ -648,8 +775,6 @@ int wc_ed448ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, */ int wc_ed448_init_ex(ed448_key* key, void *heap, int devId) { - int ret; - if (key == NULL) return BAD_FUNC_ARG; @@ -664,18 +789,11 @@ int wc_ed448_init_ex(ed448_key* key, void *heap, int devId) fe448_init(); - ret = wc_InitShake256(&key->sha, heap, -#if defined(WOLF_CRYPTO_CB) - key->devId -#else - INVALID_DEVID -#endif - ); - - if (ret == 0) - key->sha_clean_flag = 1; - - return ret; +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + return ed448_hash_init(key, &key->sha); +#else /* !WOLFSSL_ED448_PERSISTENT_SHA */ + return 0; +#endif /* WOLFSSL_ED448_PERSISTENT_SHA */ } /* Initialize the ed448 private/public key. @@ -694,7 +812,9 @@ int wc_ed448_init(ed448_key* key) { void wc_ed448_free(ed448_key* key) { if (key != NULL) { - wc_Shake256_Free(&key->sha); +#ifdef WOLFSSL_ED448_PERSISTENT_SHA + ed448_hash_free(key, &key->sha); +#endif ForceZero(key, sizeof(ed448_key)); } } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 7452b0f49..e11194245 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -25143,7 +25143,9 @@ WOLFSSL_TEST_SUBROUTINE int ed25519_test(void) int i; word32 outlen; #ifdef HAVE_ED25519_VERIFY +#ifdef WOLFSSL_ED25519_STREAMING_VERIFY int j; +#endif int verify; #endif /* HAVE_ED25519_VERIFY */ #endif /* HAVE_ED25519_SIGN && HAVE_ED25519_KEY_EXPORT && HAVE_ED25519_KEY_IMPORT */ @@ -25551,6 +25553,7 @@ WOLFSSL_TEST_SUBROUTINE int ed25519_test(void) &key) != 0 || verify != 1) return -11031 - i; +#ifdef WOLFSSL_ED25519_STREAMING_VERIFY /* test verify on good msg using streaming interface directly */ if (wc_ed25519_verify_msg_init(out, outlen, &key, (byte)Ed25519, NULL, 0) != 0) @@ -25562,6 +25565,7 @@ WOLFSSL_TEST_SUBROUTINE int ed25519_test(void) if (wc_ed25519_verify_msg_final(out, outlen, &verify, &key) != 0 || verify != 1) return -11231 - i; +#endif /* WOLFSSL_ED25519_STREAMING_VERIFY */ /* test verify on bad msg */ out[outlen-1] = out[outlen-1] + 1; @@ -26455,7 +26459,9 @@ WOLFSSL_TEST_SUBROUTINE int ed448_test(void) int i; word32 outlen; #ifdef HAVE_ED448_VERIFY +#ifdef WOLFSSL_ED448_STREAMING_VERIFY int j; +#endif /* WOLFSSL_ED448_STREAMING_VERIFY */ int verify; #endif /* HAVE_ED448_VERIFY */ #endif /* HAVE_ED448_SIGN && HAVE_ED448_KEY_EXPORT && HAVE_ED448_KEY_IMPORT */ @@ -26966,6 +26972,7 @@ WOLFSSL_TEST_SUBROUTINE int ed448_test(void) return -11731 - i; } +#ifdef WOLFSSL_ED448_STREAMING_VERIFY /* test verify on good msg using streaming interface directly */ if (wc_ed448_verify_msg_init(out, outlen, &key, (byte)Ed448, NULL, 0) != 0) @@ -26977,6 +26984,7 @@ WOLFSSL_TEST_SUBROUTINE int ed448_test(void) if (wc_ed448_verify_msg_final(out, outlen, &verify, &key) != 0 || verify != 1) return -11931 - i; +#endif /* WOLFSSL_ED448_STREAMING_VERIFY */ /* test verify on bad msg */ out[outlen-2] = out[outlen-2] + 1; diff --git a/wolfssl/wolfcrypt/ed25519.h b/wolfssl/wolfcrypt/ed25519.h index 443459757..f944d8fec 100644 --- a/wolfssl/wolfcrypt/ed25519.h +++ b/wolfssl/wolfcrypt/ed25519.h @@ -94,8 +94,10 @@ struct ed25519_key { int devId; #endif void *heap; +#ifdef WOLFSSL_ED25519_PERSISTENT_SHA wc_Sha512 sha; int sha_clean_flag; +#endif }; @@ -145,6 +147,7 @@ WOLFSSL_API int wc_ed25519_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* res, ed25519_key* key, byte type, const byte* context, byte contextLen); +#ifdef WOLFSSL_ED25519_STREAMING_VERIFY WOLFSSL_API int wc_ed25519_verify_msg_init(const byte* sig, word32 sigLen, ed25519_key* key, byte type, const byte* context, byte contextLen); @@ -154,6 +157,7 @@ int wc_ed25519_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, WOLFSSL_API int wc_ed25519_verify_msg_final(const byte* sig, word32 sigLen, int* res, ed25519_key* key); +#endif /* WOLFSSL_ED25519_STREAMING_VERIFY */ #endif /* HAVE_ED25519_VERIFY */ diff --git a/wolfssl/wolfcrypt/ed448.h b/wolfssl/wolfcrypt/ed448.h index ff7caf88a..cb317111e 100644 --- a/wolfssl/wolfcrypt/ed448.h +++ b/wolfssl/wolfcrypt/ed448.h @@ -65,6 +65,7 @@ /* both private and public key */ #define ED448_PRV_KEY_SIZE (ED448_PUB_KEY_SIZE+ED448_KEY_SIZE) +#define ED448_PREHASH_SIZE 64 enum { Ed448 = 0, @@ -93,8 +94,10 @@ struct ed448_key { int devId; #endif void *heap; +#ifdef WOLFSSL_ED448_PERSISTENT_SHA wc_Shake sha; int sha_clean_flag; +#endif }; @@ -125,6 +128,7 @@ WOLFSSL_API int wc_ed448_verify_msg_ex(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* res, ed448_key* key, byte type, const byte* context, byte contextLen); +#ifdef WOLFSSL_ED448_STREAMING_VERIFY WOLFSSL_API int wc_ed448_verify_msg_init(const byte* sig, word32 sigLen, ed448_key* key, byte type, const byte* context, byte contextLen); @@ -134,6 +138,7 @@ int wc_ed448_verify_msg_update(const byte* msgSegment, word32 msgSegmentLen, WOLFSSL_API int wc_ed448_verify_msg_final(const byte* sig, word32 sigLen, int* stat, ed448_key* key); +#endif /* WOLFSSL_ED448_STREAMING_VERIFY */ WOLFSSL_API int wc_ed448_verify_msg(const byte* sig, word32 sigLen, const byte* msg, word32 msgLen, int* stat, ed448_key* key, diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 3a3dfae66..5c62e5758 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1867,6 +1867,10 @@ extern void uITRON4_free(void *p) ; #ifndef NO_ED25519_VERIFY #undef HAVE_ED25519_VERIFY #define HAVE_ED25519_VERIFY + #ifdef WOLFSSL_ED25519_STREAMING_VERIFY + #undef WOLFSSL_ED25519_PERSISTENT_SHA + #define WOLFSSL_ED25519_PERSISTENT_SHA + #endif #endif #ifndef NO_ED25519_KEY_EXPORT #undef HAVE_ED25519_KEY_EXPORT @@ -1905,6 +1909,10 @@ extern void uITRON4_free(void *p) ; #ifndef NO_ED448_VERIFY #undef HAVE_ED448_VERIFY #define HAVE_ED448_VERIFY + #ifdef WOLFSSL_ED448_STREAMING_VERIFY + #undef WOLFSSL_ED448_PERSISTENT_SHA + #define WOLFSSL_ED448_PERSISTENT_SHA + #endif #endif #ifndef NO_ED448_KEY_EXPORT #undef HAVE_ED448_KEY_EXPORT