From 41207f5d9bc2c7fb010c01a23770533fcfb5f03b Mon Sep 17 00:00:00 2001 From: Hayden Roche Date: Mon, 22 Aug 2022 22:19:24 -0700 Subject: [PATCH] Add support for non-blocking ECC key gen and shared secret gen for P-256/384/521. New functions: - sp_ecc_make_key_256_nb - sp_ecc_make_key_384_nb - sp_ecc_make_key_521_nb - sp_ecc_secret_gen_256_nb - sp_ecc_secret_gen_384_nb - sp_ecc_secret_gen_521_nb This commit also tweaks the testing for ECDSA testing in test.c. Instead of testing with one of P-256/384/521, we test with all that are available. --- wolfcrypt/src/ecc.c | 147 +- wolfcrypt/src/sp_arm32.c | 1714 ++++++++++++++--------- wolfcrypt/src/sp_arm64.c | 1714 ++++++++++++++--------- wolfcrypt/src/sp_armthumb.c | 1714 ++++++++++++++--------- wolfcrypt/src/sp_c32.c | 2578 ++++++++++++++++++++--------------- wolfcrypt/src/sp_c64.c | 2578 ++++++++++++++++++++--------------- wolfcrypt/src/sp_cortexm.c | 1714 ++++++++++++++--------- wolfcrypt/src/sp_x86_64.c | 1882 +++++++++++++++---------- wolfcrypt/test/test.c | 533 +++----- wolfssl/wolfcrypt/sp.h | 17 + 10 files changed, 8670 insertions(+), 5921 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index c6845f84e..4c3ed5eb0 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4324,6 +4324,11 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, mp_int k_lcl[1]; #endif #endif +#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WC_ECC_NONBLOCK) && \ + defined(WC_ECC_NONBLOCK_ONLY) + ecc_nb_ctx_t nb_ctx; + XMEMSET(&nb_ctx, 0, sizeof(nb_ctx)); +#endif /* WOLFSSL_HAVE_SP_ECC && WC_ECC_NONBLOCK && WC_ECC_NONBLOCK_ONLY */ #ifdef HAVE_ECC_CDH /* if cofactor flag has been set */ @@ -4349,27 +4354,85 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, #endif #ifdef WOLFSSL_HAVE_SP_ECC + #ifndef WOLFSSL_SP_NO_256 if (private_key->idx != ECC_CUSTOM_IDX && - ecc_sets[private_key->idx].id == ECC_SECP256R1) { + ecc_sets[private_key->idx].id == ECC_SECP256R1) { + #ifndef WC_ECC_NONBLOCK err = sp_ecc_secret_gen_256(k, point, out, outlen, private_key->heap); + #else + if (private_key->nb_ctx) { + err = sp_ecc_secret_gen_256_nb(&private_key->nb_ctx->sp_ctx, k, + point, out, outlen, + private_key->heap); + } + else { + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_secret_gen_256_nb(&nb_ctx.sp_ctx, k, point, out, + outlen, private_key->heap); + } while (err == FP_WOULDBLOCK); + #else + err = sp_ecc_secret_gen_256(k, point, out, outlen, + private_key->heap); + #endif /* WC_ECC_NONBLOCK_ONLY */ + } + #endif /* !WC_ECC_NONBLOCK */ } else -#endif +#endif /* ! WOLFSSL_SP_NO_256 */ #ifdef WOLFSSL_SP_384 if (private_key->idx != ECC_CUSTOM_IDX && - ecc_sets[private_key->idx].id == ECC_SECP384R1) { + ecc_sets[private_key->idx].id == ECC_SECP384R1) { + #ifndef WC_ECC_NONBLOCK err = sp_ecc_secret_gen_384(k, point, out, outlen, private_key->heap); + #else + if (private_key->nb_ctx) { + err = sp_ecc_secret_gen_384_nb(&private_key->nb_ctx->sp_ctx, k, + point, out, outlen, + private_key->heap); + } + else { + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_secret_gen_384_nb(&nb_ctx.sp_ctx, k, point, out, + outlen, private_key->heap); + } while (err == FP_WOULDBLOCK); + #else + err = sp_ecc_secret_gen_384(k, point, out, outlen, + private_key->heap); + #endif /* WC_ECC_NONBLOCK_ONLY */ + } + #endif /* !WC_ECC_NONBLOCK */ } else -#endif +#endif /* WOLFSSL_SP_384 */ #ifdef WOLFSSL_SP_521 if (private_key->idx != ECC_CUSTOM_IDX && ecc_sets[private_key->idx].id == ECC_SECP521R1) { + #ifndef WC_ECC_NONBLOCK err = sp_ecc_secret_gen_521(k, point, out, outlen, private_key->heap); + #else + if (private_key->nb_ctx) { + err = sp_ecc_secret_gen_521_nb(&private_key->nb_ctx->sp_ctx, k, + point, out, outlen, + private_key->heap); + } + else { + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_secret_gen_521_nb(&nb_ctx.sp_ctx, k, point, out, + outlen, private_key->heap); + } while (err == FP_WOULDBLOCK); + #else + err = sp_ecc_secret_gen_521(k, point, out, outlen, + private_key->heap); + #endif /* WC_ECC_NONBLOCK_ONLY */ + } + #endif /* !WC_ECC_NONBLOCK */ } else -#endif +#endif /* WOLFSSL_SP_521 */ #else (void)point; (void)out; @@ -5071,7 +5134,6 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, #if defined(HAVE_ECC_MAKE_PUB) && !defined(WOLFSSL_SP_MATH) DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); #endif - #if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) && \ !defined(WOLFSSL_ATECC608A) const CRYS_ECPKI_Domain_t* pDomain; @@ -5080,6 +5142,12 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, byte ucompressed_key[ECC_MAX_CRYPTO_HW_SIZE*2 + 1]; word32 raw_size = 0; #endif +#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WC_ECC_NONBLOCK) && \ + defined(WC_ECC_NONBLOCK_ONLY) + ecc_nb_ctx_t nb_ctx; + XMEMSET(&nb_ctx, 0, sizeof(nb_ctx)); +#endif /* WOLFSSL_HAVE_SP_ECC && WC_ECC_NONBLOCK && WC_ECC_NONBLOCK_ONLY */ + if (key == NULL || rng == NULL) { return BAD_FUNC_ARG; } @@ -5217,33 +5285,88 @@ static int _ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, #else #ifdef WOLFSSL_HAVE_SP_ECC + #ifndef WOLFSSL_SP_NO_256 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + #ifndef WC_ECC_NONBLOCK err = sp_ecc_make_key_256(rng, &key->k, &key->pubkey, key->heap); + #else + if (key->nb_ctx) { + err = sp_ecc_make_key_256_nb(&key->nb_ctx->sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } + else { + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_make_key_256_nb(&nb_ctx.sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } while (err == FP_WOULDBLOCK); + #else + err = sp_ecc_make_key_256(rng, &key->k, &key->pubkey, key->heap); + #endif /* WC_ECC_NONBLOCK_ONLY */ + } + #endif /* !WC_ECC_NONBLOCK */ + if (err == MP_OKAY) { key->type = ECC_PRIVATEKEY; } } else -#endif +#endif /* !WOLFSSL_SP_NO_256 */ #ifdef WOLFSSL_SP_384 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifndef WC_ECC_NONBLOCK err = sp_ecc_make_key_384(rng, &key->k, &key->pubkey, key->heap); + #else + if (key->nb_ctx) { + err = sp_ecc_make_key_384_nb(&key->nb_ctx->sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } + else { + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_make_key_384_nb(&nb_ctx.sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } while (err == FP_WOULDBLOCK); + #else + err = sp_ecc_make_key_384(rng, &key->k, &key->pubkey, key->heap); + #endif /* WC_ECC_NONBLOCK_ONLY */ + } + #endif /* !WC_ECC_NONBLOCK */ + if (err == MP_OKAY) { key->type = ECC_PRIVATEKEY; } } else -#endif +#endif /* WOLFSSL_SP_384 */ #ifdef WOLFSSL_SP_521 if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP521R1) { +#ifndef WC_ECC_NONBLOCK + err = sp_ecc_make_key_521(rng, &key->k, &key->pubkey, key->heap); +#else + if (key->nb_ctx) { + err = sp_ecc_make_key_521_nb(&key->nb_ctx->sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } + else { + #ifdef WC_ECC_NONBLOCK_ONLY + do { /* perform blocking call to non-blocking function */ + err = sp_ecc_make_key_521_nb(&nb_ctx.sp_ctx, rng, &key->k, + &key->pubkey, key->heap); + } while (err == FP_WOULDBLOCK); + #else err = sp_ecc_make_key_521(rng, &key->k, &key->pubkey, key->heap); - if (err == MP_OKAY) { - key->type = ECC_PRIVATEKEY; - } + #endif /* WC_ECC_NONBLOCK_ONLY */ + } +#endif /* !WC_ECC_NONBLOCK */ + + if (err == MP_OKAY) { + key->type = ECC_PRIVATEKEY; + } } else -#endif +#endif /* WOLFSSL_SP_521 */ #endif /* WOLFSSL_HAVE_SP_ECC */ { /* software key gen */ diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c index 62fd91186..ca421b239 100644 --- a/wolfcrypt/src/sp_arm32.c +++ b/wolfcrypt/src/sp_arm32.c @@ -73982,6 +73982,84 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_256_ctx { + int state; + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_digit k[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; +#else + sp_point_256 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_256_ctx; + +int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_256_ecc_gen_k_8(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_256_ecc_mulmod_base_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_order, 1, 1); + if (err == MP_OKAY) { + if (sp_256_iszero_8(ctx->point->x) || + sp_256_iszero_8(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_256_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 @@ -74064,6 +74142,56 @@ int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + }; + sp_digit k[8]; + sp_point_256 point; +} sp_ecc_sec_gen_256_ctx; + +int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_256_from_mp(ctx->k, 8, priv); + sp_256_point_from_ecc_point_8(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_256_to_bin_8(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -75096,6 +75224,124 @@ static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 8]; + sp_point_256 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 8; + k = e + 4 * 8; + r = e + 6 * 8; + tmp = e + 8 * 8; + s = e; + + if (hashLen > 32U) { + hashLen = 32U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, k); + } + else { + sp_256_from_mp(k, 8, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_256_norm_8(r); + + sp_256_from_mp(x, 8, priv); + sp_256_from_bin(e, 8, hash, (int)hashLen); + + err = sp_256_calc_s_8(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_256_ctx { int state; @@ -75123,8 +75369,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -75260,124 +75504,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_256* point = NULL; -#else - sp_digit e[7 * 2 * 8]; - sp_point_256 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 8; - k = e + 4 * 8; - r = e + 6 * 8; - tmp = e + 8 * 8; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_8(rng, k); - } - else { - sp_256_from_mp(k, 8, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); - sp_256_norm_8(r); - c = sp_256_cmp_8(r, p256_order); - sp_256_cond_sub_8(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_8(r); - - sp_256_from_mp(x, 8, priv); - sp_256_from_bin(e, 8, hash, (int)hashLen); - - err = sp_256_calc_s_8(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_256)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -76174,6 +76300,106 @@ static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[18 * 8]; + sp_point_256 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 8, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 8; + s = u1 + 4 * 8; + tmp = u1 + 6 * 8; + p2 = p1 + 1; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 8, hash, (int)hashLen); + sp_256_from_mp(u2, 8, rm); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, rm); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, rm); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + } + *res = (sp_256_cmp_8(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { int state; @@ -76323,106 +76549,6 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_256* p1 = NULL; -#else - sp_digit u1[18 * 8]; - sp_point_256 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 8, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 8; - s = u1 + 4 * 8; - tmp = u1 + 6 * 8; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 8, hash, (int)hashLen); - sp_256_from_mp(u2, 8, rm); - sp_256_from_mp(s, 8, sm); - sp_256_from_mp(p2->x, 8, pX); - sp_256_from_mp(p2->y, 8, pY); - sp_256_from_mp(p2->z, 8, pZ); - - err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 8, rm); - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 8, rm); - carry = sp_256_add_8(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_8(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_8(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_8(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -91179,6 +91305,84 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_384_ctx { + int state; + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_digit k[12]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; +#else + sp_point_384 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_384_ctx; + +int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_384_ecc_gen_k_12(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_384_ecc_mulmod_base_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p384_order, 1, 1); + if (err == MP_OKAY) { + if (sp_384_iszero_12(ctx->point->x) || + sp_384_iszero_12(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_384_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 @@ -91261,6 +91465,56 @@ int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + }; + sp_digit k[12]; + sp_point_384 point; +} sp_ecc_sec_gen_384_ctx; + +int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_384_from_mp(ctx->k, 12, priv); + sp_384_point_from_ecc_point_12(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_384_to_bin_12(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -92435,6 +92689,124 @@ static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 12]; + sp_point_384 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 12; + k = e + 4 * 12; + r = e + 6 * 12; + tmp = e + 8 * 12; + s = e; + + if (hashLen > 48U) { + hashLen = 48U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, k); + } + else { + sp_384_from_mp(k, 12, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); + sp_384_norm_12(r); + c = sp_384_cmp_12(r, p384_order); + sp_384_cond_sub_12(r, r, p384_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_384_norm_12(r); + + sp_384_from_mp(x, 12, priv); + sp_384_from_bin(e, 12, hash, (int)hashLen); + + err = sp_384_calc_s_12(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_384_ctx { int state; @@ -92462,8 +92834,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -92599,124 +92969,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_384* point = NULL; -#else - sp_digit e[7 * 2 * 12]; - sp_point_384 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 12; - k = e + 4 * 12; - r = e + 6 * 12; - tmp = e + 8 * 12; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_12(rng, k); - } - else { - sp_384_from_mp(k, 12, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); - sp_384_norm_12(r); - c = sp_384_cmp_12(r, p384_order); - sp_384_cond_sub_12(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_12(r); - - sp_384_from_mp(x, 12, priv); - sp_384_from_bin(e, 12, hash, (int)hashLen); - - err = sp_384_calc_s_12(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_384)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -93776,6 +94028,106 @@ static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[18 * 12]; + sp_point_384 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 12, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 12; + s = u1 + 4 * 12; + tmp = u1 + 6 * 12; + p2 = p1 + 1; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 12, hash, (int)hashLen); + sp_384_from_mp(u2, 12, rm); + sp_384_from_mp(s, 12, sm); + sp_384_from_mp(p2->x, 12, pX); + sp_384_from_mp(p2->y, 12, pY); + sp_384_from_mp(p2->z, 12, pZ); + + err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 12, rm); + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 12, rm); + carry = sp_384_add_12(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(u2, p384_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + } + *res = (sp_384_cmp_12(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { int state; @@ -93925,106 +94277,6 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_384* p1 = NULL; -#else - sp_digit u1[18 * 12]; - sp_point_384 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 12, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 12; - s = u1 + 4 * 12; - tmp = u1 + 6 * 12; - p2 = p1 + 1; - - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(u1, 12, hash, (int)hashLen); - sp_384_from_mp(u2, 12, rm); - sp_384_from_mp(s, 12, sm); - sp_384_from_mp(p2->x, 12, pX); - sp_384_from_mp(p2->y, 12, pY); - sp_384_from_mp(p2->z, 12, pZ); - - err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 12, rm); - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); - *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_384_from_mp(u2, 12, rm); - carry = sp_384_add_12(u2, u2, p384_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_384_norm_12(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_12(u2, p384_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); - } - *res = (sp_384_cmp_12(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -118378,6 +118630,84 @@ int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_521_ctx { + int state; + sp_521_ecc_mulmod_17_ctx mulmod_ctx; + sp_digit k[17]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521 point[2]; +#else + sp_point_521 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_521_ctx; + +int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_521_ecc_gen_k_17(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_521_ecc_mulmod_base_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p521_order, 1, 1); + if (err == MP_OKAY) { + if (sp_521_iszero_17(ctx->point->x) || + sp_521_iszero_17(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_521_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_521_point_to_ecc_point_17(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 66 @@ -118462,6 +118792,56 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_521_ctx { + int state; + union { + sp_521_ecc_mulmod_17_ctx mulmod_ctx; + }; + sp_digit k[17]; + sp_point_521 point; +} sp_ecc_sec_gen_521_ctx; + +int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_521_from_mp(ctx->k, 17, priv); + sp_521_point_from_ecc_point_17(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_521_to_bin_17(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -120301,6 +120681,128 @@ static int sp_521_calc_s_17(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_521* point = NULL; +#else + sp_digit e[7 * 2 * 17]; + sp_point_521 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 17, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 17; + k = e + 4 * 17; + r = e + 6 * 17; + tmp = e + 8 * 17; + s = e; + + if (hashLen > 66U) { + hashLen = 66U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_521_ecc_gen_k_17(rng, k); + } + else { + sp_521_from_mp(k, 17, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 17U); + sp_521_norm_17(r); + c = sp_521_cmp_17(r, p521_order); + sp_521_cond_sub_17(r, r, p521_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_521_norm_17(r); + + sp_521_from_mp(x, 17, priv); + sp_521_from_bin(e, 17, hash, (int)hashLen); + + if (hashLen == 66U) { + sp_521_rshift_17(e, e, 7); + } + + err = sp_521_calc_s_17(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_521_iszero_17(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_521_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_521_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_521)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_521_ctx { int state; @@ -120328,8 +120830,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -120468,128 +120968,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_521* point = NULL; -#else - sp_digit e[7 * 2 * 17]; - sp_point_521 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 17, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 17; - k = e + 4 * 17; - r = e + 6 * 17; - tmp = e + 8 * 17; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_17(rng, k); - } - else { - sp_521_from_mp(k, 17, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 17U); - sp_521_norm_17(r); - c = sp_521_cmp_17(r, p521_order); - sp_521_cond_sub_17(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_17(r); - - sp_521_from_mp(x, 17, priv); - sp_521_from_bin(e, 17, hash, (int)hashLen); - - if (hashLen == 66U) { - sp_521_rshift_17(e, e, 7); - } - - err = sp_521_calc_s_17(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_521_iszero_17(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 17); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_521)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -122079,6 +122457,110 @@ static int sp_521_calc_vfy_point_17(sp_point_521* p1, sp_point_521* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_521* p1 = NULL; +#else + sp_digit u1[18 * 17]; + sp_point_521 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_521* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 17, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 17; + s = u1 + 4 * 17; + tmp = u1 + 6 * 17; + p2 = p1 + 1; + + if (hashLen > 66U) { + hashLen = 66U; + } + + sp_521_from_bin(u1, 17, hash, (int)hashLen); + sp_521_from_mp(u2, 17, rm); + sp_521_from_mp(s, 17, sm); + sp_521_from_mp(p2->x, 17, pX); + sp_521_from_mp(p2->y, 17, pY); + sp_521_from_mp(p2->z, 17, pZ); + + if (hashLen == 66U) { + sp_521_rshift_17(u1, u1, 7); + } + + err = sp_521_calc_vfy_point_17(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_521_from_mp(u2, 17, rm); + err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_521_mont_sqr_17(p1->z, p1->z, p521_mod, p521_mp_mod); + sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); + *res = (int)(sp_521_cmp_17(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_521_from_mp(u2, 17, rm); + carry = sp_521_add_17(u2, u2, p521_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_521_norm_17(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_521_cmp_17(u2, p521_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); + } + *res = (sp_521_cmp_17(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_521_ctx { int state; @@ -122231,110 +122713,6 @@ int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_521* p1 = NULL; -#else - sp_digit u1[18 * 17]; - sp_point_521 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 17, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 17; - s = u1 + 4 * 17; - tmp = u1 + 6 * 17; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 17, hash, (int)hashLen); - sp_521_from_mp(u2, 17, rm); - sp_521_from_mp(s, 17, sm); - sp_521_from_mp(p2->x, 17, pX); - sp_521_from_mp(p2->y, 17, pY); - sp_521_from_mp(p2->z, 17, pZ); - - if (hashLen == 66U) { - sp_521_rshift_17(u1, u1, 7); - } - - err = sp_521_calc_vfy_point_17(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 17, rm); - err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_17(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_17(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 17, rm); - carry = sp_521_add_17(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_17(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_17(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_17(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY diff --git a/wolfcrypt/src/sp_arm64.c b/wolfcrypt/src/sp_arm64.c index fc52938a2..1526cae33 100644 --- a/wolfcrypt/src/sp_arm64.c +++ b/wolfcrypt/src/sp_arm64.c @@ -39648,6 +39648,84 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_256_ctx { + int state; + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_digit k[4]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; +#else + sp_point_256 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_256_ctx; + +int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_256_ecc_gen_k_4(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_256_ecc_mulmod_base_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_order, 1, 1); + if (err == MP_OKAY) { + if (sp_256_iszero_4(ctx->point->x) || + sp_256_iszero_4(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_256_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_4(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 @@ -39734,6 +39812,56 @@ int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + }; + sp_digit k[4]; + sp_point_256 point; +} sp_ecc_sec_gen_256_ctx; + +int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_256_from_mp(ctx->k, 4, priv); + sp_256_point_from_ecc_point_4(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_256_to_bin_4(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -40218,6 +40346,124 @@ static int sp_256_calc_s_4(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 4]; + sp_point_256 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 4; + k = e + 4 * 4; + r = e + 6 * 4; + tmp = e + 8 * 4; + s = e; + + if (hashLen > 32U) { + hashLen = 32U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, k); + } + else { + sp_256_from_mp(k, 4, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 4U); + sp_256_norm_4(r); + c = sp_256_cmp_4(r, p256_order); + sp_256_cond_sub_4(r, r, p256_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_256_norm_4(r); + + sp_256_from_mp(x, 4, priv); + sp_256_from_bin(e, 4, hash, (int)hashLen); + + err = sp_256_calc_s_4(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_4(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 4); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_256_ctx { int state; @@ -40245,8 +40491,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -40382,124 +40626,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_256* point = NULL; -#else - sp_digit e[7 * 2 * 4]; - sp_point_256 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 4; - k = e + 4 * 4; - r = e + 6 * 4; - tmp = e + 8 * 4; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_4(rng, k); - } - else { - sp_256_from_mp(k, 4, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 4U); - sp_256_norm_4(r); - c = sp_256_cmp_4(r, p256_order); - sp_256_cond_sub_4(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_4(r); - - sp_256_from_mp(x, 4, priv); - sp_256_from_bin(e, 4, hash, (int)hashLen); - - err = sp_256_calc_s_4(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_256_iszero_4(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 4); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_256)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -40873,6 +40999,106 @@ static int sp_256_calc_vfy_point_4(sp_point_256* p1, sp_point_256* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[18 * 4]; + sp_point_256 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 4; + s = u1 + 4 * 4; + tmp = u1 + 6 * 4; + p2 = p1 + 1; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 4, hash, (int)hashLen); + sp_256_from_mp(u2, 4, rm); + sp_256_from_mp(s, 4, sm); + sp_256_from_mp(p2->x, 4, pX); + sp_256_from_mp(p2->y, 4, pY); + sp_256_from_mp(p2->z, 4, pZ); + + err = sp_256_calc_vfy_point_4(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 4, rm); + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 4, rm); + carry = sp_256_add_4(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_4(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(u2, p256_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + } + *res = (sp_256_cmp_4(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { int state; @@ -41022,106 +41248,6 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_256* p1 = NULL; -#else - sp_digit u1[18 * 4]; - sp_point_256 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 4; - s = u1 + 4 * 4; - tmp = u1 + 6 * 4; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 4, hash, (int)hashLen); - sp_256_from_mp(u2, 4, rm); - sp_256_from_mp(s, 4, sm); - sp_256_from_mp(p2->x, 4, pX); - sp_256_from_mp(p2->y, 4, pY); - sp_256_from_mp(p2->z, 4, pZ); - - err = sp_256_calc_vfy_point_4(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 4, rm); - err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 4, rm); - carry = sp_256_add_4(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_4(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_4(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_4(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -65538,6 +65664,84 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_384_ctx { + int state; + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_digit k[6]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; +#else + sp_point_384 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_384_ctx; + +int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_384_ecc_gen_k_6(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_384_ecc_mulmod_base_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p384_order, 1, 1); + if (err == MP_OKAY) { + if (sp_384_iszero_6(ctx->point->x) || + sp_384_iszero_6(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_384_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 @@ -65624,6 +65828,56 @@ int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + }; + sp_digit k[6]; + sp_point_384 point; +} sp_ecc_sec_gen_384_ctx; + +int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_384_from_mp(ctx->k, 6, priv); + sp_384_point_from_ecc_point_6(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_384_to_bin_6(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -66144,6 +66398,124 @@ static int sp_384_calc_s_6(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 6]; + sp_point_384 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 6; + k = e + 4 * 6; + r = e + 6 * 6; + tmp = e + 8 * 6; + s = e; + + if (hashLen > 48U) { + hashLen = 48U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, k); + } + else { + sp_384_from_mp(k, 6, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 6U); + sp_384_norm_6(r); + c = sp_384_cmp_6(r, p384_order); + sp_384_cond_sub_6(r, r, p384_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_384_norm_6(r); + + sp_384_from_mp(x, 6, priv); + sp_384_from_bin(e, 6, hash, (int)hashLen); + + err = sp_384_calc_s_6(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_6(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_384_ctx { int state; @@ -66171,8 +66543,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -66308,124 +66678,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_384* point = NULL; -#else - sp_digit e[7 * 2 * 6]; - sp_point_384 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 6; - k = e + 4 * 6; - r = e + 6 * 6; - tmp = e + 8 * 6; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_6(rng, k); - } - else { - sp_384_from_mp(k, 6, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 6U); - sp_384_norm_6(r); - c = sp_384_cmp_6(r, p384_order); - sp_384_cond_sub_6(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_6(r); - - sp_384_from_mp(x, 6, priv); - sp_384_from_bin(e, 6, hash, (int)hashLen); - - err = sp_384_calc_s_6(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_384_iszero_6(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_384)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -66701,6 +66953,106 @@ static int sp_384_calc_vfy_point_6(sp_point_384* p1, sp_point_384* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[18 * 6]; + sp_point_384 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 6, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 6; + s = u1 + 4 * 6; + tmp = u1 + 6 * 6; + p2 = p1 + 1; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 6, hash, (int)hashLen); + sp_384_from_mp(u2, 6, rm); + sp_384_from_mp(s, 6, sm); + sp_384_from_mp(p2->x, 6, pX); + sp_384_from_mp(p2->y, 6, pY); + sp_384_from_mp(p2->z, 6, pZ); + + err = sp_384_calc_vfy_point_6(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 6, rm); + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_6(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 6, rm); + carry = sp_384_add_6(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(u2, p384_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); + } + *res = (sp_384_cmp_6(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { int state; @@ -66850,106 +67202,6 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_384* p1 = NULL; -#else - sp_digit u1[18 * 6]; - sp_point_384 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 6, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 6; - s = u1 + 4 * 6; - tmp = u1 + 6 * 6; - p2 = p1 + 1; - - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(u1, 6, hash, (int)hashLen); - sp_384_from_mp(u2, 6, rm); - sp_384_from_mp(s, 6, sm); - sp_384_from_mp(p2->x, 6, pX); - sp_384_from_mp(p2->y, 6, pY); - sp_384_from_mp(p2->z, 6, pZ); - - err = sp_384_calc_vfy_point_6(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 6, rm); - err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_6(p1->z, p1->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); - *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_384_from_mp(u2, 6, rm); - carry = sp_384_add_6(u2, u2, p384_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_384_norm_6(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_6(u2, p384_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); - } - *res = (sp_384_cmp_6(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -110416,6 +110668,84 @@ int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_521_ctx { + int state; + sp_521_ecc_mulmod_9_ctx mulmod_ctx; + sp_digit k[9]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521 point[2]; +#else + sp_point_521 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_521_ctx; + +int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_521_ecc_gen_k_9(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_521_ecc_mulmod_base_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p521_order, 1, 1); + if (err == MP_OKAY) { + if (sp_521_iszero_9(ctx->point->x) || + sp_521_iszero_9(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_521_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_521_point_to_ecc_point_9(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 66 @@ -110504,6 +110834,56 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_521_ctx { + int state; + union { + sp_521_ecc_mulmod_9_ctx mulmod_ctx; + }; + sp_digit k[9]; + sp_point_521 point; +} sp_ecc_sec_gen_521_ctx; + +int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_521_from_mp(ctx->k, 9, priv); + sp_521_point_from_ecc_point_9(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_521_to_bin_9(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -110768,6 +111148,128 @@ static int sp_521_calc_s_9(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_521* point = NULL; +#else + sp_digit e[7 * 2 * 9]; + sp_point_521 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 9; + k = e + 4 * 9; + r = e + 6 * 9; + tmp = e + 8 * 9; + s = e; + + if (hashLen > 66U) { + hashLen = 66U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_521_ecc_gen_k_9(rng, k); + } + else { + sp_521_from_mp(k, 9, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); + sp_521_norm_9(r); + c = sp_521_cmp_9(r, p521_order); + sp_521_cond_sub_9(r, r, p521_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_521_norm_9(r); + + sp_521_from_mp(x, 9, priv); + sp_521_from_bin(e, 9, hash, (int)hashLen); + + if (hashLen == 66U) { + sp_521_rshift_9(e, e, 7); + } + + err = sp_521_calc_s_9(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_521_iszero_9(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_521_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_521_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_521)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_521_ctx { int state; @@ -110795,8 +111297,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -110935,128 +111435,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_521* point = NULL; -#else - sp_digit e[7 * 2 * 9]; - sp_point_521 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 9; - k = e + 4 * 9; - r = e + 6 * 9; - tmp = e + 8 * 9; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_9(rng, k); - } - else { - sp_521_from_mp(k, 9, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); - sp_521_norm_9(r); - c = sp_521_cmp_9(r, p521_order); - sp_521_cond_sub_9(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_9(r); - - sp_521_from_mp(x, 9, priv); - sp_521_from_bin(e, 9, hash, (int)hashLen); - - if (hashLen == 66U) { - sp_521_rshift_9(e, e, 7); - } - - err = sp_521_calc_s_9(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_521_iszero_9(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_521)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -111350,6 +111728,110 @@ static int sp_521_calc_vfy_point_9(sp_point_521* p1, sp_point_521* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_521* p1 = NULL; +#else + sp_digit u1[18 * 9]; + sp_point_521 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_521* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 9; + s = u1 + 4 * 9; + tmp = u1 + 6 * 9; + p2 = p1 + 1; + + if (hashLen > 66U) { + hashLen = 66U; + } + + sp_521_from_bin(u1, 9, hash, (int)hashLen); + sp_521_from_mp(u2, 9, rm); + sp_521_from_mp(s, 9, sm); + sp_521_from_mp(p2->x, 9, pX); + sp_521_from_mp(p2->y, 9, pY); + sp_521_from_mp(p2->z, 9, pZ); + + if (hashLen == 66U) { + sp_521_rshift_9(u1, u1, 7); + } + + err = sp_521_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_521_from_mp(u2, 9, rm); + err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_521_mont_sqr_9(p1->z, p1->z, p521_mod, p521_mp_mod); + sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); + *res = (int)(sp_521_cmp_9(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_521_from_mp(u2, 9, rm); + carry = sp_521_add_9(u2, u2, p521_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_521_norm_9(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_521_cmp_9(u2, p521_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); + } + *res = (sp_521_cmp_9(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_521_ctx { int state; @@ -111502,110 +111984,6 @@ int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_521* p1 = NULL; -#else - sp_digit u1[18 * 9]; - sp_point_521 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 9; - s = u1 + 4 * 9; - tmp = u1 + 6 * 9; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 9, hash, (int)hashLen); - sp_521_from_mp(u2, 9, rm); - sp_521_from_mp(s, 9, sm); - sp_521_from_mp(p2->x, 9, pX); - sp_521_from_mp(p2->y, 9, pY); - sp_521_from_mp(p2->z, 9, pZ); - - if (hashLen == 66U) { - sp_521_rshift_9(u1, u1, 7); - } - - err = sp_521_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 9, rm); - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_9(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_9(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 9, rm); - carry = sp_521_add_9(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_9(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_9(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_9(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY diff --git a/wolfcrypt/src/sp_armthumb.c b/wolfcrypt/src/sp_armthumb.c index c551b09ae..5fea65bb6 100644 --- a/wolfcrypt/src/sp_armthumb.c +++ b/wolfcrypt/src/sp_armthumb.c @@ -104160,6 +104160,84 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_256_ctx { + int state; + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_digit k[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; +#else + sp_point_256 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_256_ctx; + +int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_256_ecc_gen_k_8(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_256_ecc_mulmod_base_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_order, 1, 1); + if (err == MP_OKAY) { + if (sp_256_iszero_8(ctx->point->x) || + sp_256_iszero_8(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_256_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 @@ -104242,6 +104320,56 @@ int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + }; + sp_digit k[8]; + sp_point_256 point; +} sp_ecc_sec_gen_256_ctx; + +int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_256_from_mp(ctx->k, 8, priv); + sp_256_point_from_ecc_point_8(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_256_to_bin_8(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -105574,6 +105702,124 @@ static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 8]; + sp_point_256 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 8; + k = e + 4 * 8; + r = e + 6 * 8; + tmp = e + 8 * 8; + s = e; + + if (hashLen > 32U) { + hashLen = 32U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, k); + } + else { + sp_256_from_mp(k, 8, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_256_norm_8(r); + + sp_256_from_mp(x, 8, priv); + sp_256_from_bin(e, 8, hash, (int)hashLen); + + err = sp_256_calc_s_8(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_256_ctx { int state; @@ -105601,8 +105847,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -105738,124 +105982,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_256* point = NULL; -#else - sp_digit e[7 * 2 * 8]; - sp_point_256 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 8; - k = e + 4 * 8; - r = e + 6 * 8; - tmp = e + 8 * 8; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_8(rng, k); - } - else { - sp_256_from_mp(k, 8, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); - sp_256_norm_8(r); - c = sp_256_cmp_8(r, p256_order); - sp_256_cond_sub_8(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_8(r); - - sp_256_from_mp(x, 8, priv); - sp_256_from_bin(e, 8, hash, (int)hashLen); - - err = sp_256_calc_s_8(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_256)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -107232,6 +107358,106 @@ static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[18 * 8]; + sp_point_256 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 8, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 8; + s = u1 + 4 * 8; + tmp = u1 + 6 * 8; + p2 = p1 + 1; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 8, hash, (int)hashLen); + sp_256_from_mp(u2, 8, rm); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, rm); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, rm); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + } + *res = (sp_256_cmp_8(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { int state; @@ -107381,106 +107607,6 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_256* p1 = NULL; -#else - sp_digit u1[18 * 8]; - sp_point_256 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 8, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 8; - s = u1 + 4 * 8; - tmp = u1 + 6 * 8; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 8, hash, (int)hashLen); - sp_256_from_mp(u2, 8, rm); - sp_256_from_mp(s, 8, sm); - sp_256_from_mp(p2->x, 8, pX); - sp_256_from_mp(p2->y, 8, pY); - sp_256_from_mp(p2->z, 8, pZ); - - err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 8, rm); - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 8, rm); - carry = sp_256_add_8(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_8(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_8(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_8(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -114760,6 +114886,84 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_384_ctx { + int state; + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_digit k[12]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; +#else + sp_point_384 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_384_ctx; + +int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_384_ecc_gen_k_12(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_384_ecc_mulmod_base_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p384_order, 1, 1); + if (err == MP_OKAY) { + if (sp_384_iszero_12(ctx->point->x) || + sp_384_iszero_12(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_384_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 @@ -114842,6 +115046,56 @@ int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + }; + sp_digit k[12]; + sp_point_384 point; +} sp_ecc_sec_gen_384_ctx; + +int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_384_from_mp(ctx->k, 12, priv); + sp_384_point_from_ecc_point_12(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_384_to_bin_12(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -116185,6 +116439,124 @@ static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 12]; + sp_point_384 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 12; + k = e + 4 * 12; + r = e + 6 * 12; + tmp = e + 8 * 12; + s = e; + + if (hashLen > 48U) { + hashLen = 48U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, k); + } + else { + sp_384_from_mp(k, 12, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); + sp_384_norm_12(r); + c = sp_384_cmp_12(r, p384_order); + sp_384_cond_sub_12(r, r, p384_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_384_norm_12(r); + + sp_384_from_mp(x, 12, priv); + sp_384_from_bin(e, 12, hash, (int)hashLen); + + err = sp_384_calc_s_12(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_384_ctx { int state; @@ -116212,8 +116584,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -116349,124 +116719,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_384* point = NULL; -#else - sp_digit e[7 * 2 * 12]; - sp_point_384 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 12; - k = e + 4 * 12; - r = e + 6 * 12; - tmp = e + 8 * 12; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_12(rng, k); - } - else { - sp_384_from_mp(k, 12, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); - sp_384_norm_12(r); - c = sp_384_cmp_12(r, p384_order); - sp_384_cond_sub_12(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_12(r); - - sp_384_from_mp(x, 12, priv); - sp_384_from_bin(e, 12, hash, (int)hashLen); - - err = sp_384_calc_s_12(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_384)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -118272,6 +118524,106 @@ static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[18 * 12]; + sp_point_384 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 12, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 12; + s = u1 + 4 * 12; + tmp = u1 + 6 * 12; + p2 = p1 + 1; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 12, hash, (int)hashLen); + sp_384_from_mp(u2, 12, rm); + sp_384_from_mp(s, 12, sm); + sp_384_from_mp(p2->x, 12, pX); + sp_384_from_mp(p2->y, 12, pY); + sp_384_from_mp(p2->z, 12, pZ); + + err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 12, rm); + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 12, rm); + carry = sp_384_add_12(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(u2, p384_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + } + *res = (sp_384_cmp_12(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { int state; @@ -118421,106 +118773,6 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_384* p1 = NULL; -#else - sp_digit u1[18 * 12]; - sp_point_384 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 12, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 12; - s = u1 + 4 * 12; - tmp = u1 + 6 * 12; - p2 = p1 + 1; - - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(u1, 12, hash, (int)hashLen); - sp_384_from_mp(u2, 12, rm); - sp_384_from_mp(s, 12, sm); - sp_384_from_mp(p2->x, 12, pX); - sp_384_from_mp(p2->y, 12, pY); - sp_384_from_mp(p2->z, 12, pZ); - - err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 12, rm); - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); - *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_384_from_mp(u2, 12, rm); - carry = sp_384_add_12(u2, u2, p384_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_384_norm_12(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_12(u2, p384_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); - } - *res = (sp_384_cmp_12(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -129095,6 +129347,84 @@ int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_521_ctx { + int state; + sp_521_ecc_mulmod_17_ctx mulmod_ctx; + sp_digit k[17]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521 point[2]; +#else + sp_point_521 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_521_ctx; + +int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_521_ecc_gen_k_17(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_521_ecc_mulmod_base_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p521_order, 1, 1); + if (err == MP_OKAY) { + if (sp_521_iszero_17(ctx->point->x) || + sp_521_iszero_17(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_521_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_521_point_to_ecc_point_17(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 66 @@ -129179,6 +129509,56 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_521_ctx { + int state; + union { + sp_521_ecc_mulmod_17_ctx mulmod_ctx; + }; + sp_digit k[17]; + sp_point_521 point; +} sp_ecc_sec_gen_521_ctx; + +int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_521_from_mp(ctx->k, 17, priv); + sp_521_point_from_ecc_point_17(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_521_to_bin_17(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -132226,6 +132606,128 @@ static int sp_521_calc_s_17(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_521* point = NULL; +#else + sp_digit e[7 * 2 * 17]; + sp_point_521 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 17, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 17; + k = e + 4 * 17; + r = e + 6 * 17; + tmp = e + 8 * 17; + s = e; + + if (hashLen > 66U) { + hashLen = 66U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_521_ecc_gen_k_17(rng, k); + } + else { + sp_521_from_mp(k, 17, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 17U); + sp_521_norm_17(r); + c = sp_521_cmp_17(r, p521_order); + sp_521_cond_sub_17(r, r, p521_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_521_norm_17(r); + + sp_521_from_mp(x, 17, priv); + sp_521_from_bin(e, 17, hash, (int)hashLen); + + if (hashLen == 66U) { + sp_521_rshift_17(e, e, 7); + } + + err = sp_521_calc_s_17(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_521_iszero_17(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_521_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_521_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_521)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_521_ctx { int state; @@ -132253,8 +132755,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -132393,128 +132893,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_521* point = NULL; -#else - sp_digit e[7 * 2 * 17]; - sp_point_521 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 17, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 17; - k = e + 4 * 17; - r = e + 6 * 17; - tmp = e + 8 * 17; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_17(rng, k); - } - else { - sp_521_from_mp(k, 17, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 17U); - sp_521_norm_17(r); - c = sp_521_cmp_17(r, p521_order); - sp_521_cond_sub_17(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_17(r); - - sp_521_from_mp(x, 17, priv); - sp_521_from_bin(e, 17, hash, (int)hashLen); - - if (hashLen == 66U) { - sp_521_rshift_17(e, e, 7); - } - - err = sp_521_calc_s_17(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_521_iszero_17(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 17); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_521)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -135050,6 +135428,110 @@ static int sp_521_calc_vfy_point_17(sp_point_521* p1, sp_point_521* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_521* p1 = NULL; +#else + sp_digit u1[18 * 17]; + sp_point_521 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_521* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 17, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 17; + s = u1 + 4 * 17; + tmp = u1 + 6 * 17; + p2 = p1 + 1; + + if (hashLen > 66U) { + hashLen = 66U; + } + + sp_521_from_bin(u1, 17, hash, (int)hashLen); + sp_521_from_mp(u2, 17, rm); + sp_521_from_mp(s, 17, sm); + sp_521_from_mp(p2->x, 17, pX); + sp_521_from_mp(p2->y, 17, pY); + sp_521_from_mp(p2->z, 17, pZ); + + if (hashLen == 66U) { + sp_521_rshift_17(u1, u1, 7); + } + + err = sp_521_calc_vfy_point_17(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_521_from_mp(u2, 17, rm); + err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_521_mont_sqr_17(p1->z, p1->z, p521_mod, p521_mp_mod); + sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); + *res = (int)(sp_521_cmp_17(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_521_from_mp(u2, 17, rm); + carry = sp_521_add_17(u2, u2, p521_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_521_norm_17(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_521_cmp_17(u2, p521_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); + } + *res = (sp_521_cmp_17(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_521_ctx { int state; @@ -135202,110 +135684,6 @@ int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_521* p1 = NULL; -#else - sp_digit u1[18 * 17]; - sp_point_521 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 17, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 17; - s = u1 + 4 * 17; - tmp = u1 + 6 * 17; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 17, hash, (int)hashLen); - sp_521_from_mp(u2, 17, rm); - sp_521_from_mp(s, 17, sm); - sp_521_from_mp(p2->x, 17, pX); - sp_521_from_mp(p2->y, 17, pY); - sp_521_from_mp(p2->z, 17, pZ); - - if (hashLen == 66U) { - sp_521_rshift_17(u1, u1, 7); - } - - err = sp_521_calc_vfy_point_17(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 17, rm); - err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_17(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_17(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 17, rm); - carry = sp_521_add_17(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_17(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_17(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_17(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c index 46611a491..8eb93d008 100644 --- a/wolfcrypt/src/sp_c32.c +++ b/wolfcrypt/src/sp_c32.c @@ -21885,6 +21885,108 @@ static int sp_256_mod_mul_norm_9(sp_digit* r, const sp_digit* a, const sp_digit* * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 t[3]; + sp_digit tmp[2 * 9 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_256) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_9(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 8; + c = 24; + n = k[i--] << (29 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 29; + } + + y = (n >> 28) & 1; + n <<= 1; + + sp_256_proj_point_add_9(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_256)); + sp_256_proj_point_dbl_9(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_256)); + } + + if (map != 0) { + sp_256_map_9(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_256)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 9 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_256) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_256_ecc_mulmod_9_ctx { @@ -22000,109 +22102,6 @@ static int sp_256_ecc_mulmod_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_256 t[3]; - sp_digit tmp[2 * 9 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_256) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_256_mod_mul_norm_9(t[1].x, g->x, p256_mod); - } - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod); - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod); - - if (err == MP_OKAY) { - i = 8; - c = 24; - n = k[i--] << (29 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 29; - } - - y = (n >> 28) & 1; - n <<= 1; - - sp_256_proj_point_add_9(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_256)); - sp_256_proj_point_dbl_9(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_256)); - } - - if (map != 0) { - sp_256_map_9(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_256)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 9 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_256) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_256 { @@ -23349,6 +23348,16 @@ static int sp_256_ecc_mulmod_base_9(sp_point_256* r, const sp_digit* k, return sp_256_ecc_mulmod_9(r, &p256_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_256_ecc_mulmod_base_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_9_nb(sp_ctx, r, &p256_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. @@ -24952,6 +24961,84 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_256_ctx { + int state; + sp_256_ecc_mulmod_9_ctx mulmod_ctx; + sp_digit k[9]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; +#else + sp_point_256 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_256_ctx; + +int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_256_ecc_gen_k_9(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_256_ecc_mulmod_base_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_order, 1, 1); + if (err == MP_OKAY) { + if (sp_256_iszero_9(ctx->point->x) || + sp_256_iszero_9(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_256_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_9(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 @@ -25059,6 +25146,56 @@ int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_256_ctx { + int state; + union { + sp_256_ecc_mulmod_9_ctx mulmod_ctx; + }; + sp_digit k[9]; + sp_point_256 point; +} sp_ecc_sec_gen_256_ctx; + +int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_256_from_mp(ctx->k, 9, priv); + sp_256_point_from_ecc_point_9(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_256_to_bin_9(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -25541,6 +25678,124 @@ static int sp_256_calc_s_9(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 9]; + sp_point_256 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 9; + k = e + 4 * 9; + r = e + 6 * 9; + tmp = e + 8 * 9; + s = e; + + if (hashLen > 32U) { + hashLen = 32U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_9(rng, k); + } + else { + sp_256_from_mp(k, 9, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); + sp_256_norm_9(r); + c = sp_256_cmp_9(r, p256_order); + sp_256_cond_sub_9(r, r, p256_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_256_norm_9(r); + + sp_256_from_mp(x, 9, priv); + sp_256_from_bin(e, 9, hash, (int)hashLen); + + err = sp_256_calc_s_9(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_9(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_256_ctx { int state; @@ -25568,8 +25823,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -25705,124 +25958,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_256* point = NULL; -#else - sp_digit e[7 * 2 * 9]; - sp_point_256 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 9; - k = e + 4 * 9; - r = e + 6 * 9; - tmp = e + 8 * 9; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_9(rng, k); - } - else { - sp_256_from_mp(k, 9, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); - sp_256_norm_9(r); - c = sp_256_cmp_9(r, p256_order); - sp_256_cond_sub_9(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_9(r); - - sp_256_from_mp(x, 9, priv); - sp_256_from_bin(e, 9, hash, (int)hashLen); - - err = sp_256_calc_s_9(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_256_iszero_9(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_256)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -26087,6 +26222,106 @@ static int sp_256_calc_vfy_point_9(sp_point_256* p1, sp_point_256* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[18 * 9]; + sp_point_256 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 9; + s = u1 + 4 * 9; + tmp = u1 + 6 * 9; + p2 = p1 + 1; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 9, hash, (int)hashLen); + sp_256_from_mp(u2, 9, rm); + sp_256_from_mp(s, 9, sm); + sp_256_from_mp(p2->x, 9, pX); + sp_256_from_mp(p2->y, 9, pY); + sp_256_from_mp(p2->z, 9, pZ); + + err = sp_256_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 9, rm); + err = sp_256_mod_mul_norm_9(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_9(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_9(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 9, rm); + carry = sp_256_add_9(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_9(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_9(u2, p256_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_9(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod); + } + *res = (sp_256_cmp_9(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { int state; @@ -26236,106 +26471,6 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_256* p1 = NULL; -#else - sp_digit u1[18 * 9]; - sp_point_256 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 9; - s = u1 + 4 * 9; - tmp = u1 + 6 * 9; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 9, hash, (int)hashLen); - sp_256_from_mp(u2, 9, rm); - sp_256_from_mp(s, 9, sm); - sp_256_from_mp(p2->x, 9, pX); - sp_256_from_mp(p2->y, 9, pY); - sp_256_from_mp(p2->z, 9, pZ); - - err = sp_256_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 9, rm); - err = sp_256_mod_mul_norm_9(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_9(p1->z, p1->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_9(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 9, rm); - carry = sp_256_add_9(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_9(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_9(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_9(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_9(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -29206,6 +29341,108 @@ static int sp_384_mod_mul_norm_15(sp_digit* r, const sp_digit* a, const sp_digit * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 t[3]; + sp_digit tmp[2 * 15 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod); + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod); + + if (err == MP_OKAY) { + i = 14; + c = 20; + n = k[i--] << (26 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 26; + } + + y = (n >> 25) & 1; + n <<= 1; + + sp_384_proj_point_add_15(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_384)); + sp_384_proj_point_dbl_15(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_384)); + } + + if (map != 0) { + sp_384_map_15(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_384)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 15 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_384) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_384_ecc_mulmod_15_ctx { @@ -29321,109 +29558,6 @@ static int sp_384_ecc_mulmod_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_384 t[3]; - sp_digit tmp[2 * 15 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_384) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod); - } - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod); - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod); - - if (err == MP_OKAY) { - i = 14; - c = 20; - n = k[i--] << (26 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 26; - } - - y = (n >> 25) & 1; - n <<= 1; - - sp_384_proj_point_add_15(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_384)); - sp_384_proj_point_dbl_15(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_384)); - } - - if (map != 0) { - sp_384_map_15(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_384)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 15 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_384) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_384 { @@ -30742,6 +30876,16 @@ static int sp_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k, return sp_384_ecc_mulmod_15(r, &p384_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_384_ecc_mulmod_base_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_384_ecc_mulmod_15_nb(sp_ctx, r, &p384_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. @@ -32857,6 +33001,84 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_384_ctx { + int state; + sp_384_ecc_mulmod_15_ctx mulmod_ctx; + sp_digit k[15]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; +#else + sp_point_384 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_384_ctx; + +int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_384_ecc_gen_k_15(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_384_ecc_mulmod_base_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p384_order, 1, 1); + if (err == MP_OKAY) { + if (sp_384_iszero_15(ctx->point->x) || + sp_384_iszero_15(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_384_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_15(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 @@ -32964,6 +33186,56 @@ int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_384_ctx { + int state; + union { + sp_384_ecc_mulmod_15_ctx mulmod_ctx; + }; + sp_digit k[15]; + sp_point_384 point; +} sp_ecc_sec_gen_384_ctx; + +int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_384_from_mp(ctx->k, 15, priv); + sp_384_point_from_ecc_point_15(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_384_to_bin_15(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -33459,6 +33731,124 @@ static int sp_384_calc_s_15(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 15]; + sp_point_384 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 15, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 15; + k = e + 4 * 15; + r = e + 6 * 15; + tmp = e + 8 * 15; + s = e; + + if (hashLen > 48U) { + hashLen = 48U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_15(rng, k); + } + else { + sp_384_from_mp(k, 15, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 15U); + sp_384_norm_15(r); + c = sp_384_cmp_15(r, p384_order); + sp_384_cond_sub_15(r, r, p384_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_384_norm_15(r); + + sp_384_from_mp(x, 15, priv); + sp_384_from_bin(e, 15, hash, (int)hashLen); + + err = sp_384_calc_s_15(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_15(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 15); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_384_ctx { int state; @@ -33486,8 +33876,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -33623,124 +34011,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_384* point = NULL; -#else - sp_digit e[7 * 2 * 15]; - sp_point_384 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 15, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 15; - k = e + 4 * 15; - r = e + 6 * 15; - tmp = e + 8 * 15; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_15(rng, k); - } - else { - sp_384_from_mp(k, 15, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 15U); - sp_384_norm_15(r); - c = sp_384_cmp_15(r, p384_order); - sp_384_cond_sub_15(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_15(r); - - sp_384_from_mp(x, 15, priv); - sp_384_from_bin(e, 15, hash, (int)hashLen); - - err = sp_384_calc_s_15(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_384_iszero_15(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 15); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_384)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -34011,6 +34281,106 @@ static int sp_384_calc_vfy_point_15(sp_point_384* p1, sp_point_384* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[18 * 15]; + sp_point_384 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 15, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 15; + s = u1 + 4 * 15; + tmp = u1 + 6 * 15; + p2 = p1 + 1; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 15, hash, (int)hashLen); + sp_384_from_mp(u2, 15, rm); + sp_384_from_mp(s, 15, sm); + sp_384_from_mp(p2->x, 15, pX); + sp_384_from_mp(p2->y, 15, pY); + sp_384_from_mp(p2->z, 15, pZ); + + err = sp_384_calc_vfy_point_15(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 15, rm); + err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_15(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_15(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 15, rm); + carry = sp_384_add_15(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_15(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_15(u2, p384_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod); + } + *res = (sp_384_cmp_15(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { int state; @@ -34160,106 +34530,6 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_384* p1 = NULL; -#else - sp_digit u1[18 * 15]; - sp_point_384 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 15, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 15; - s = u1 + 4 * 15; - tmp = u1 + 6 * 15; - p2 = p1 + 1; - - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(u1, 15, hash, (int)hashLen); - sp_384_from_mp(u2, 15, rm); - sp_384_from_mp(s, 15, sm); - sp_384_from_mp(p2->x, 15, pX); - sp_384_from_mp(p2->y, 15, pY); - sp_384_from_mp(p2->z, 15, pZ); - - err = sp_384_calc_vfy_point_15(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 15, rm); - err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_15(p1->z, p1->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod); - *res = (int)(sp_384_cmp_15(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_384_from_mp(u2, 15, rm); - carry = sp_384_add_15(u2, u2, p384_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_384_norm_15(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_15(u2, p384_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_15(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod); - } - *res = (sp_384_cmp_15(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -36588,6 +36858,108 @@ static int sp_521_mod_mul_norm_21(sp_digit* r, const sp_digit* a, const sp_digit * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_521* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_521 t[3]; + sp_digit tmp[2 * 21 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_521) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_521_mod_mul_norm_21(t[1].x, g->x, p521_mod); + } + if (err == MP_OKAY) + err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod); + if (err == MP_OKAY) + err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod); + + if (err == MP_OKAY) { + i = 20; + c = 21; + n = k[i--] << (25 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 25; + } + + y = (n >> 24) & 1; + n <<= 1; + + sp_521_proj_point_add_21(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_521)); + sp_521_proj_point_dbl_21(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_521)); + } + + if (map != 0) { + sp_521_map_21(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_521)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 21 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_521) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_521_ecc_mulmod_21_ctx { @@ -36703,109 +37075,6 @@ static int sp_521_ecc_mulmod_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_521* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_521 t[3]; - sp_digit tmp[2 * 21 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_521) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_521_mod_mul_norm_21(t[1].x, g->x, p521_mod); - } - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod); - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod); - - if (err == MP_OKAY) { - i = 20; - c = 21; - n = k[i--] << (25 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 25; - } - - y = (n >> 24) & 1; - n <<= 1; - - sp_521_proj_point_add_21(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_521)); - sp_521_proj_point_dbl_21(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_521)); - } - - if (map != 0) { - sp_521_map_21(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_521)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 21 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_521) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_521 { @@ -38196,6 +38465,16 @@ static int sp_521_ecc_mulmod_base_21(sp_point_521* r, const sp_digit* k, return sp_521_ecc_mulmod_21(r, &p521_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_521_ecc_mulmod_base_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_521_ecc_mulmod_21_nb(sp_ctx, r, &p521_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. @@ -40822,6 +41101,84 @@ int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_521_ctx { + int state; + sp_521_ecc_mulmod_21_ctx mulmod_ctx; + sp_digit k[21]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521 point[2]; +#else + sp_point_521 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_521_ctx; + +int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_521_ecc_gen_k_21(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_521_ecc_mulmod_base_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p521_order, 1, 1); + if (err == MP_OKAY) { + if (sp_521_iszero_21(ctx->point->x) || + sp_521_iszero_21(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_521_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_521_point_to_ecc_point_21(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 66 @@ -40929,6 +41286,56 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_521_ctx { + int state; + union { + sp_521_ecc_mulmod_21_ctx mulmod_ctx; + }; + sp_digit k[21]; + sp_point_521 point; +} sp_ecc_sec_gen_521_ctx; + +int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_521_from_mp(ctx->k, 21, priv); + sp_521_point_from_ecc_point_21(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_521_to_bin_21(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -41459,6 +41866,129 @@ static int sp_521_calc_s_21(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_521* point = NULL; +#else + sp_digit e[7 * 2 * 21]; + sp_point_521 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 21, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 21; + k = e + 4 * 21; + r = e + 6 * 21; + tmp = e + 8 * 21; + s = e; + + if (hashLen > 66U) { + hashLen = 66U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_521_ecc_gen_k_21(rng, k); + } + else { + sp_521_from_mp(k, 21, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 21U); + sp_521_norm_21(r); + c = sp_521_cmp_21(r, p521_order); + sp_521_cond_sub_21(r, r, p521_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_521_norm_21(r); + + sp_521_from_mp(x, 21, priv); + sp_521_from_bin(e, 21, hash, (int)hashLen); + + if (hashLen == 66U) { + sp_521_rshift_21(e, e, 7); + e[20] |= ((sp_digit)hash[0]) << 13; + } + + err = sp_521_calc_s_21(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_521_iszero_21(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_521_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_521_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 21); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_521)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_521_ctx { int state; @@ -41486,8 +42016,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -41627,129 +42155,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_521* point = NULL; -#else - sp_digit e[7 * 2 * 21]; - sp_point_521 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 21, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 21; - k = e + 4 * 21; - r = e + 6 * 21; - tmp = e + 8 * 21; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_21(rng, k); - } - else { - sp_521_from_mp(k, 21, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 21U); - sp_521_norm_21(r); - c = sp_521_cmp_21(r, p521_order); - sp_521_cond_sub_21(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_21(r); - - sp_521_from_mp(x, 21, priv); - sp_521_from_bin(e, 21, hash, (int)hashLen); - - if (hashLen == 66U) { - sp_521_rshift_21(e, e, 7); - e[20] |= ((sp_digit)hash[0]) << 13; - } - - err = sp_521_calc_s_21(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_521_iszero_21(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 21); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_521)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -42026,6 +42431,111 @@ static int sp_521_calc_vfy_point_21(sp_point_521* p1, sp_point_521* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_521* p1 = NULL; +#else + sp_digit u1[18 * 21]; + sp_point_521 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_521* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 21, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 21; + s = u1 + 4 * 21; + tmp = u1 + 6 * 21; + p2 = p1 + 1; + + if (hashLen > 66U) { + hashLen = 66U; + } + + sp_521_from_bin(u1, 21, hash, (int)hashLen); + sp_521_from_mp(u2, 21, rm); + sp_521_from_mp(s, 21, sm); + sp_521_from_mp(p2->x, 21, pX); + sp_521_from_mp(p2->y, 21, pY); + sp_521_from_mp(p2->z, 21, pZ); + + if (hashLen == 66U) { + sp_521_rshift_21(u1, u1, 7); + u1[20] |= ((sp_digit)hash[0]) << 13; + } + + err = sp_521_calc_vfy_point_21(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_521_from_mp(u2, 21, rm); + err = sp_521_mod_mul_norm_21(u2, u2, p521_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_521_mont_sqr_21(p1->z, p1->z, p521_mod, p521_mp_mod); + sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod); + *res = (int)(sp_521_cmp_21(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_521_from_mp(u2, 21, rm); + carry = sp_521_add_21(u2, u2, p521_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_521_norm_21(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_521_cmp_21(u2, p521_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_521_mod_mul_norm_21(u2, u2, p521_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod); + } + *res = (sp_521_cmp_21(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_521_ctx { int state; @@ -42179,111 +42689,6 @@ int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_521* p1 = NULL; -#else - sp_digit u1[18 * 21]; - sp_point_521 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 21, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 21; - s = u1 + 4 * 21; - tmp = u1 + 6 * 21; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 21, hash, (int)hashLen); - sp_521_from_mp(u2, 21, rm); - sp_521_from_mp(s, 21, sm); - sp_521_from_mp(p2->x, 21, pX); - sp_521_from_mp(p2->y, 21, pY); - sp_521_from_mp(p2->z, 21, pZ); - - if (hashLen == 66U) { - sp_521_rshift_21(u1, u1, 7); - u1[20] |= ((sp_digit)hash[0]) << 13; - } - - err = sp_521_calc_vfy_point_21(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 21, rm); - err = sp_521_mod_mul_norm_21(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_21(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_21(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 21, rm); - carry = sp_521_add_21(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_21(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_21(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_21(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_21(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -45223,6 +45628,108 @@ static void sp_1024_proj_point_add_42(sp_point_1024* r, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[3]; + sp_digit tmp[2 * 42 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_1024) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod); + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod); + + if (err == MP_OKAY) { + i = 40; + c = 24; + n = k[i--] << (25 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 25; + } + + y = (n >> 24) & 1; + n <<= 1; + + sp_1024_proj_point_add_42(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_1024)); + sp_1024_proj_point_dbl_42(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_1024)); + } + + if (map != 0) { + sp_1024_map_42(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 42 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_1024) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_1024_ecc_mulmod_42_ctx { @@ -45338,109 +45845,6 @@ static int sp_1024_ecc_mulmod_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_1024* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_1024 t[3]; - sp_digit tmp[2 * 42 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_1024) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod); - } - if (err == MP_OKAY) - err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod); - if (err == MP_OKAY) - err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod); - - if (err == MP_OKAY) { - i = 40; - c = 24; - n = k[i--] << (25 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 25; - } - - y = (n >> 24) & 1; - n <<= 1; - - sp_1024_proj_point_add_42(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_1024)); - sp_1024_proj_point_dbl_42(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_1024)); - } - - if (map != 0) { - sp_1024_map_42(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_1024)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 42 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_1024) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_1024 { @@ -46544,6 +46948,16 @@ static int sp_1024_ecc_mulmod_base_42(sp_point_1024* r, const sp_digit* k, return sp_1024_ecc_mulmod_42(r, &p1024_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_1024_ecc_mulmod_base_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_1024_ecc_mulmod_42_nb(sp_ctx, r, &p1024_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c index 0b86384d8..1e6e6a85e 100644 --- a/wolfcrypt/src/sp_c64.c +++ b/wolfcrypt/src/sp_c64.c @@ -22848,6 +22848,108 @@ static int sp_256_mod_mul_norm_5(sp_digit* r, const sp_digit* a, const sp_digit* * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_256* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_256 t[3]; + sp_digit tmp[2 * 5 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_256) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 4; + c = 48; + n = k[i--] << (52 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 52; + } + + y = (n >> 51) & 1; + n <<= 1; + + sp_256_proj_point_add_5(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_256)); + sp_256_proj_point_dbl_5(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_256)); + } + + if (map != 0) { + sp_256_map_5(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_256)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 5 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_256) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_256_ecc_mulmod_5_ctx { @@ -22963,109 +23065,6 @@ static int sp_256_ecc_mulmod_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_256_ecc_mulmod_5(sp_point_256* r, const sp_point_256* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_256* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_256 t[3]; - sp_digit tmp[2 * 5 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_256) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); - } - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); - if (err == MP_OKAY) - err = sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); - - if (err == MP_OKAY) { - i = 4; - c = 48; - n = k[i--] << (52 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 52; - } - - y = (n >> 51) & 1; - n <<= 1; - - sp_256_proj_point_add_5(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_256)); - sp_256_proj_point_dbl_5(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_256)); - } - - if (map != 0) { - sp_256_map_5(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_256)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 5 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_256) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_256 { @@ -24264,6 +24263,16 @@ static int sp_256_ecc_mulmod_base_5(sp_point_256* r, const sp_digit* k, return sp_256_ecc_mulmod_5(r, &p256_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_256_ecc_mulmod_base_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_5_nb(sp_ctx, r, &p256_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. @@ -25867,6 +25876,84 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_256_ctx { + int state; + sp_256_ecc_mulmod_5_ctx mulmod_ctx; + sp_digit k[5]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; +#else + sp_point_256 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_256_ctx; + +int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_256_ecc_gen_k_5(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_256_ecc_mulmod_base_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_order, 1, 1); + if (err == MP_OKAY) { + if (sp_256_iszero_5(ctx->point->x) || + sp_256_iszero_5(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_256_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_5(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 @@ -25974,6 +26061,56 @@ int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_256_ctx { + int state; + union { + sp_256_ecc_mulmod_5_ctx mulmod_ctx; + }; + sp_digit k[5]; + sp_point_256 point; +} sp_ecc_sec_gen_256_ctx; + +int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_256_from_mp(ctx->k, 5, priv); + sp_256_point_from_ecc_point_5(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_256_to_bin_5(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -26442,6 +26579,124 @@ static int sp_256_calc_s_5(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 5]; + sp_point_256 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 5; + k = e + 4 * 5; + r = e + 6 * 5; + tmp = e + 8 * 5; + s = e; + + if (hashLen > 32U) { + hashLen = 32U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_5(rng, k); + } + else { + sp_256_from_mp(k, 5, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_5(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 5U); + sp_256_norm_5(r); + c = sp_256_cmp_5(r, p256_order); + sp_256_cond_sub_5(r, r, p256_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_256_norm_5(r); + + sp_256_from_mp(x, 5, priv); + sp_256_from_bin(e, 5, hash, (int)hashLen); + + err = sp_256_calc_s_5(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_5(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 5); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_256_ctx { int state; @@ -26469,8 +26724,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -26606,124 +26859,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_256* point = NULL; -#else - sp_digit e[7 * 2 * 5]; - sp_point_256 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 5; - k = e + 4 * 5; - r = e + 6 * 5; - tmp = e + 8 * 5; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_5(rng, k); - } - else { - sp_256_from_mp(k, 5, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_5(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 5U); - sp_256_norm_5(r); - c = sp_256_cmp_5(r, p256_order); - sp_256_cond_sub_5(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_5(r); - - sp_256_from_mp(x, 5, priv); - sp_256_from_bin(e, 5, hash, (int)hashLen); - - err = sp_256_calc_s_5(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_256_iszero_5(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 5); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_256)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -26989,6 +27124,106 @@ static int sp_256_calc_vfy_point_5(sp_point_256* p1, sp_point_256* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[18 * 5]; + sp_point_256 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 5, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 5; + s = u1 + 4 * 5; + tmp = u1 + 6 * 5; + p2 = p1 + 1; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 5, hash, (int)hashLen); + sp_256_from_mp(u2, 5, rm); + sp_256_from_mp(s, 5, sm); + sp_256_from_mp(p2->x, 5, pX); + sp_256_from_mp(p2->y, 5, pY); + sp_256_from_mp(p2->z, 5, pZ); + + err = sp_256_calc_vfy_point_5(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 5, rm); + err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_5(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_5(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 5, rm); + carry = sp_256_add_5(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_5(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_5(u2, p256_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, p256_mp_mod); + } + *res = (sp_256_cmp_5(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { int state; @@ -27138,106 +27373,6 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_256* p1 = NULL; -#else - sp_digit u1[18 * 5]; - sp_point_256 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 5, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 5; - s = u1 + 4 * 5; - tmp = u1 + 6 * 5; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 5, hash, (int)hashLen); - sp_256_from_mp(u2, 5, rm); - sp_256_from_mp(s, 5, sm); - sp_256_from_mp(p2->x, 5, pX); - sp_256_from_mp(p2->y, 5, pY); - sp_256_from_mp(p2->z, 5, pZ); - - err = sp_256_calc_vfy_point_5(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 5, rm); - err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_5(p1->z, p1->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_5(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 5, rm); - carry = sp_256_add_5(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_5(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_5(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_5(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -29652,6 +29787,108 @@ static int sp_384_mod_mul_norm_7(sp_digit* r, const sp_digit* a, const sp_digit* * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_384* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_384 t[3]; + sp_digit tmp[2 * 7 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_384) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_7(t[1].x, g->x, p384_mod); + } + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_7(t[1].y, g->y, p384_mod); + if (err == MP_OKAY) + err = sp_384_mod_mul_norm_7(t[1].z, g->z, p384_mod); + + if (err == MP_OKAY) { + i = 6; + c = 54; + n = k[i--] << (55 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 55; + } + + y = (n >> 54) & 1; + n <<= 1; + + sp_384_proj_point_add_7(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_384)); + sp_384_proj_point_dbl_7(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_384)); + } + + if (map != 0) { + sp_384_map_7(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_384)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 7 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_384) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_384_ecc_mulmod_7_ctx { @@ -29767,109 +30004,6 @@ static int sp_384_ecc_mulmod_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_384_ecc_mulmod_7(sp_point_384* r, const sp_point_384* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_384* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_384 t[3]; - sp_digit tmp[2 * 7 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 7 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_384) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_384_mod_mul_norm_7(t[1].x, g->x, p384_mod); - } - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_7(t[1].y, g->y, p384_mod); - if (err == MP_OKAY) - err = sp_384_mod_mul_norm_7(t[1].z, g->z, p384_mod); - - if (err == MP_OKAY) { - i = 6; - c = 54; - n = k[i--] << (55 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 55; - } - - y = (n >> 54) & 1; - n <<= 1; - - sp_384_proj_point_add_7(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_384)); - sp_384_proj_point_dbl_7(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_384)); - } - - if (map != 0) { - sp_384_map_7(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_384)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 7 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_384) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_384 { @@ -31092,6 +31226,16 @@ static int sp_384_ecc_mulmod_base_7(sp_point_384* r, const sp_digit* k, return sp_384_ecc_mulmod_7(r, &p384_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_384_ecc_mulmod_base_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_384_ecc_mulmod_7_nb(sp_ctx, r, &p384_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. @@ -33205,6 +33349,84 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_384_ctx { + int state; + sp_384_ecc_mulmod_7_ctx mulmod_ctx; + sp_digit k[7]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; +#else + sp_point_384 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_384_ctx; + +int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_384_ecc_gen_k_7(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_384_ecc_mulmod_base_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p384_order, 1, 1); + if (err == MP_OKAY) { + if (sp_384_iszero_7(ctx->point->x) || + sp_384_iszero_7(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_384_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_7(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 @@ -33312,6 +33534,56 @@ int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_384_ctx { + int state; + union { + sp_384_ecc_mulmod_7_ctx mulmod_ctx; + }; + sp_digit k[7]; + sp_point_384 point; +} sp_ecc_sec_gen_384_ctx; + +int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_384_from_mp(ctx->k, 7, priv); + sp_384_point_from_ecc_point_7(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_384_to_bin_7(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -33759,6 +34031,124 @@ static int sp_384_calc_s_7(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 7]; + sp_point_384 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 7, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 7; + k = e + 4 * 7; + r = e + 6 * 7; + tmp = e + 8 * 7; + s = e; + + if (hashLen > 48U) { + hashLen = 48U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_7(rng, k); + } + else { + sp_384_from_mp(k, 7, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_7(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 7U); + sp_384_norm_7(r); + c = sp_384_cmp_7(r, p384_order); + sp_384_cond_sub_7(r, r, p384_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_384_norm_7(r); + + sp_384_from_mp(x, 7, priv); + sp_384_from_bin(e, 7, hash, (int)hashLen); + + err = sp_384_calc_s_7(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_7(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 7); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_384_ctx { int state; @@ -33786,8 +34176,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -33923,124 +34311,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_384* point = NULL; -#else - sp_digit e[7 * 2 * 7]; - sp_point_384 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 7, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 7; - k = e + 4 * 7; - r = e + 6 * 7; - tmp = e + 8 * 7; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_7(rng, k); - } - else { - sp_384_from_mp(k, 7, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_7(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 7U); - sp_384_norm_7(r); - c = sp_384_cmp_7(r, p384_order); - sp_384_cond_sub_7(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_7(r); - - sp_384_from_mp(x, 7, priv); - sp_384_from_bin(e, 7, hash, (int)hashLen); - - err = sp_384_calc_s_7(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_384_iszero_7(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 7); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_384)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -34308,6 +34578,106 @@ static int sp_384_calc_vfy_point_7(sp_point_384* p1, sp_point_384* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[18 * 7]; + sp_point_384 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 7, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 7; + s = u1 + 4 * 7; + tmp = u1 + 6 * 7; + p2 = p1 + 1; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 7, hash, (int)hashLen); + sp_384_from_mp(u2, 7, rm); + sp_384_from_mp(s, 7, sm); + sp_384_from_mp(p2->x, 7, pX); + sp_384_from_mp(p2->y, 7, pY); + sp_384_from_mp(p2->z, 7, pZ); + + err = sp_384_calc_vfy_point_7(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 7, rm); + err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_7(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_7(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 7, rm); + carry = sp_384_add_7(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_7(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_7(u2, p384_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, p384_mp_mod); + } + *res = (sp_384_cmp_7(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { int state; @@ -34457,106 +34827,6 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_384* p1 = NULL; -#else - sp_digit u1[18 * 7]; - sp_point_384 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 7, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 7; - s = u1 + 4 * 7; - tmp = u1 + 6 * 7; - p2 = p1 + 1; - - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(u1, 7, hash, (int)hashLen); - sp_384_from_mp(u2, 7, rm); - sp_384_from_mp(s, 7, sm); - sp_384_from_mp(p2->x, 7, pX); - sp_384_from_mp(p2->y, 7, pY); - sp_384_from_mp(p2->z, 7, pZ); - - err = sp_384_calc_vfy_point_7(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 7, rm); - err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_7(p1->z, p1->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, p384_mp_mod); - *res = (int)(sp_384_cmp_7(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_384_from_mp(u2, 7, rm); - carry = sp_384_add_7(u2, u2, p384_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_384_norm_7(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_7(u2, p384_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_7(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_384_mont_mul_7(u1, u2, p1->z, p384_mod, p384_mp_mod); - } - *res = (sp_384_cmp_7(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -36912,6 +37182,108 @@ static int sp_521_mod_mul_norm_9(sp_digit* r, const sp_digit* a, const sp_digit* * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_521_ecc_mulmod_9(sp_point_521* r, const sp_point_521* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_521* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_521 t[3]; + sp_digit tmp[2 * 9 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_521) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_521_mod_mul_norm_9(t[1].x, g->x, p521_mod); + } + if (err == MP_OKAY) + err = sp_521_mod_mul_norm_9(t[1].y, g->y, p521_mod); + if (err == MP_OKAY) + err = sp_521_mod_mul_norm_9(t[1].z, g->z, p521_mod); + + if (err == MP_OKAY) { + i = 8; + c = 57; + n = k[i--] << (58 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 58; + } + + y = (n >> 57) & 1; + n <<= 1; + + sp_521_proj_point_add_9(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_521)); + sp_521_proj_point_dbl_9(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_521)); + } + + if (map != 0) { + sp_521_map_9(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_521)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 9 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_521) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_521_ecc_mulmod_9_ctx { @@ -37027,109 +37399,6 @@ static int sp_521_ecc_mulmod_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_521_ecc_mulmod_9(sp_point_521* r, const sp_point_521* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_521* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_521 t[3]; - sp_digit tmp[2 * 9 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_521) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_521_mod_mul_norm_9(t[1].x, g->x, p521_mod); - } - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_9(t[1].y, g->y, p521_mod); - if (err == MP_OKAY) - err = sp_521_mod_mul_norm_9(t[1].z, g->z, p521_mod); - - if (err == MP_OKAY) { - i = 8; - c = 57; - n = k[i--] << (58 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 58; - } - - y = (n >> 57) & 1; - n <<= 1; - - sp_521_proj_point_add_9(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_521)); - sp_521_proj_point_dbl_9(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_521)); - } - - if (map != 0) { - sp_521_map_9(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_521)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 9 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_521) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_521 { @@ -38376,6 +38645,16 @@ static int sp_521_ecc_mulmod_base_9(sp_point_521* r, const sp_digit* k, return sp_521_ecc_mulmod_9(r, &p521_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_521_ecc_mulmod_base_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_521_ecc_mulmod_9_nb(sp_ctx, r, &p521_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. @@ -40490,6 +40769,84 @@ int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_521_ctx { + int state; + sp_521_ecc_mulmod_9_ctx mulmod_ctx; + sp_digit k[9]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521 point[2]; +#else + sp_point_521 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_521_ctx; + +int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_521_ecc_gen_k_9(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_521_ecc_mulmod_base_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p521_order, 1, 1); + if (err == MP_OKAY) { + if (sp_521_iszero_9(ctx->point->x) || + sp_521_iszero_9(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_521_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_521_point_to_ecc_point_9(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 66 @@ -40597,6 +40954,56 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_521_ctx { + int state; + union { + sp_521_ecc_mulmod_9_ctx mulmod_ctx; + }; + sp_digit k[9]; + sp_point_521 point; +} sp_ecc_sec_gen_521_ctx; + +int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_521_from_mp(ctx->k, 9, priv); + sp_521_point_from_ecc_point_9(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_521_to_bin_9(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -41065,6 +41472,129 @@ static int sp_521_calc_s_9(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_521* point = NULL; +#else + sp_digit e[7 * 2 * 9]; + sp_point_521 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 9; + k = e + 4 * 9; + r = e + 6 * 9; + tmp = e + 8 * 9; + s = e; + + if (hashLen > 66U) { + hashLen = 66U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_521_ecc_gen_k_9(rng, k); + } + else { + sp_521_from_mp(k, 9, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); + sp_521_norm_9(r); + c = sp_521_cmp_9(r, p521_order); + sp_521_cond_sub_9(r, r, p521_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_521_norm_9(r); + + sp_521_from_mp(x, 9, priv); + sp_521_from_bin(e, 9, hash, (int)hashLen); + + if (hashLen == 66U) { + sp_521_rshift_9(e, e, 7); + e[8] |= ((sp_digit)hash[0]) << 49; + } + + err = sp_521_calc_s_9(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_521_iszero_9(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_521_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_521_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_521)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_521_ctx { int state; @@ -41092,8 +41622,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -41233,129 +41761,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_521* point = NULL; -#else - sp_digit e[7 * 2 * 9]; - sp_point_521 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 9; - k = e + 4 * 9; - r = e + 6 * 9; - tmp = e + 8 * 9; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_9(rng, k); - } - else { - sp_521_from_mp(k, 9, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); - sp_521_norm_9(r); - c = sp_521_cmp_9(r, p521_order); - sp_521_cond_sub_9(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_9(r); - - sp_521_from_mp(x, 9, priv); - sp_521_from_bin(e, 9, hash, (int)hashLen); - - if (hashLen == 66U) { - sp_521_rshift_9(e, e, 7); - e[8] |= ((sp_digit)hash[0]) << 49; - } - - err = sp_521_calc_s_9(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_521_iszero_9(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_521)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -41625,6 +42030,111 @@ static int sp_521_calc_vfy_point_9(sp_point_521* p1, sp_point_521* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_521* p1 = NULL; +#else + sp_digit u1[18 * 9]; + sp_point_521 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_521* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 9; + s = u1 + 4 * 9; + tmp = u1 + 6 * 9; + p2 = p1 + 1; + + if (hashLen > 66U) { + hashLen = 66U; + } + + sp_521_from_bin(u1, 9, hash, (int)hashLen); + sp_521_from_mp(u2, 9, rm); + sp_521_from_mp(s, 9, sm); + sp_521_from_mp(p2->x, 9, pX); + sp_521_from_mp(p2->y, 9, pY); + sp_521_from_mp(p2->z, 9, pZ); + + if (hashLen == 66U) { + sp_521_rshift_9(u1, u1, 7); + u1[8] |= ((sp_digit)hash[0]) << 49; + } + + err = sp_521_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_521_from_mp(u2, 9, rm); + err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_521_mont_sqr_9(p1->z, p1->z, p521_mod, p521_mp_mod); + sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); + *res = (int)(sp_521_cmp_9(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_521_from_mp(u2, 9, rm); + carry = sp_521_add_9(u2, u2, p521_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_521_norm_9(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_521_cmp_9(u2, p521_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); + } + *res = (sp_521_cmp_9(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_521_ctx { int state; @@ -41778,111 +42288,6 @@ int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_521* p1 = NULL; -#else - sp_digit u1[18 * 9]; - sp_point_521 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 9; - s = u1 + 4 * 9; - tmp = u1 + 6 * 9; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 9, hash, (int)hashLen); - sp_521_from_mp(u2, 9, rm); - sp_521_from_mp(s, 9, sm); - sp_521_from_mp(p2->x, 9, pX); - sp_521_from_mp(p2->y, 9, pY); - sp_521_from_mp(p2->z, 9, pZ); - - if (hashLen == 66U) { - sp_521_rshift_9(u1, u1, 7); - u1[8] |= ((sp_digit)hash[0]) << 49; - } - - err = sp_521_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 9, rm); - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_9(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_9(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 9, rm); - carry = sp_521_add_9(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_9(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_9(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_9(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -44625,6 +45030,108 @@ static void sp_1024_proj_point_add_18(sp_point_1024* r, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +static int sp_1024_ecc_mulmod_18(sp_point_1024* r, const sp_point_1024* g, + const sp_digit* k, int map, int ct, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_point_1024* t = NULL; + sp_digit* tmp = NULL; +#else + sp_point_1024 t[3]; + sp_digit tmp[2 * 18 * 6]; +#endif + sp_digit n; + int i; + int c; + int y; + int err = MP_OKAY; + + /* Implementation is constant time. */ + (void)ct; + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 18 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + XMEMSET(t, 0, sizeof(sp_point_1024) * 3); + + /* t[0] = {0, 0, 1} * norm */ + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_1024_mod_mul_norm_18(t[1].x, g->x, p1024_mod); + } + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_18(t[1].y, g->y, p1024_mod); + if (err == MP_OKAY) + err = sp_1024_mod_mul_norm_18(t[1].z, g->z, p1024_mod); + + if (err == MP_OKAY) { + i = 17; + c = 55; + n = k[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_1024_proj_point_add_18(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), + sizeof(sp_point_1024)); + sp_1024_proj_point_dbl_18(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], + sizeof(sp_point_1024)); + } + + if (map != 0) { + sp_1024_map_18(r, &t[0], tmp); + } + else { + XMEMCPY(r, &t[0], sizeof(sp_point_1024)); + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (tmp != NULL) +#endif + { + ForceZero(tmp, sizeof(sp_digit) * 2 * 18 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (t != NULL) +#endif + { + ForceZero(t, sizeof(sp_point_1024) * 3); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_1024_ecc_mulmod_18_ctx { @@ -44740,109 +45247,6 @@ static int sp_1024_ecc_mulmod_18_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, #endif /* WOLFSSL_SP_NONBLOCK */ -static int sp_1024_ecc_mulmod_18(sp_point_1024* r, const sp_point_1024* g, - const sp_digit* k, int map, int ct, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_point_1024* t = NULL; - sp_digit* tmp = NULL; -#else - sp_point_1024 t[3]; - sp_digit tmp[2 * 18 * 6]; -#endif - sp_digit n; - int i; - int c; - int y; - int err = MP_OKAY; - - /* Implementation is constant time. */ - (void)ct; - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap, - DYNAMIC_TYPE_ECC); - if (t == NULL) - err = MEMORY_E; - if (err == MP_OKAY) { - tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 18 * 6, heap, - DYNAMIC_TYPE_ECC); - if (tmp == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - XMEMSET(t, 0, sizeof(sp_point_1024) * 3); - - /* t[0] = {0, 0, 1} * norm */ - t[0].infinity = 1; - /* t[1] = {g->x, g->y, g->z} * norm */ - err = sp_1024_mod_mul_norm_18(t[1].x, g->x, p1024_mod); - } - if (err == MP_OKAY) - err = sp_1024_mod_mul_norm_18(t[1].y, g->y, p1024_mod); - if (err == MP_OKAY) - err = sp_1024_mod_mul_norm_18(t[1].z, g->z, p1024_mod); - - if (err == MP_OKAY) { - i = 17; - c = 55; - n = k[i--] << (57 - c); - for (; ; c--) { - if (c == 0) { - if (i == -1) - break; - - n = k[i--]; - c = 57; - } - - y = (n >> 56) & 1; - n <<= 1; - - sp_1024_proj_point_add_18(&t[y^1], &t[0], &t[1], tmp); - - XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), - sizeof(sp_point_1024)); - sp_1024_proj_point_dbl_18(&t[2], &t[2], tmp); - XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + - ((size_t)&t[1] & addr_mask[y])), &t[2], - sizeof(sp_point_1024)); - } - - if (map != 0) { - sp_1024_map_18(r, &t[0], tmp); - } - else { - XMEMCPY(r, &t[0], sizeof(sp_point_1024)); - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (tmp != NULL) -#endif - { - ForceZero(tmp, sizeof(sp_digit) * 2 * 18 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(tmp, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (t != NULL) -#endif - { - ForceZero(t, sizeof(sp_point_1024) * 3); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(t, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} - #else /* A table entry for pre-computed points. */ typedef struct sp_table_entry_1024 { @@ -45898,6 +46302,16 @@ static int sp_1024_ecc_mulmod_base_18(sp_point_1024* r, const sp_digit* k, return sp_1024_ecc_mulmod_18(r, &p1024_base, k, map, ct, heap); } +#ifdef WOLFSSL_SP_NONBLOCK +static int sp_1024_ecc_mulmod_base_18_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, + const sp_digit* k, int map, int ct, void* heap) +{ + /* No pre-computed values. */ + return sp_1024_ecc_mulmod_18_nb(sp_ctx, r, &p1024_base, k, map, ct, heap); +} +#endif /* WOLFSSL_SP_NONBLOCK */ + + #else /* Striping precomputation table. * 8 points combined into a table of 256 points. diff --git a/wolfcrypt/src/sp_cortexm.c b/wolfcrypt/src/sp_cortexm.c index 33e85ead7..a738d9262 100644 --- a/wolfcrypt/src/sp_cortexm.c +++ b/wolfcrypt/src/sp_cortexm.c @@ -22834,6 +22834,84 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_256_ctx { + int state; + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_digit k[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; +#else + sp_point_256 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_256_ctx; + +int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_256_ecc_gen_k_8(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_256_ecc_mulmod_base_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_order, 1, 1); + if (err == MP_OKAY) { + if (sp_256_iszero_8(ctx->point->x) || + sp_256_iszero_8(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_256_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_8(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 32 @@ -22916,6 +22994,56 @@ int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + }; + sp_digit k[8]; + sp_point_256 point; +} sp_ecc_sec_gen_256_ctx; + +int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_256_from_mp(ctx->k, 8, priv); + sp_256_point_from_ecc_point_8(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_256_to_bin_8(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -23455,6 +23583,124 @@ static int sp_256_calc_s_8(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[7 * 2 * 8]; + sp_point_256 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 8; + k = e + 4 * 8; + r = e + 6 * 8; + tmp = e + 8 * 8; + s = e; + + if (hashLen > 32U) { + hashLen = 32U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, k); + } + else { + sp_256_from_mp(k, 8, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_256_norm_8(r); + + sp_256_from_mp(x, 8, priv); + sp_256_from_bin(e, 8, hash, (int)hashLen); + + err = sp_256_calc_s_8(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_256_ctx { int state; @@ -23482,8 +23728,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -23619,124 +23863,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_256* point = NULL; -#else - sp_digit e[7 * 2 * 8]; - sp_point_256 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 8; - k = e + 4 * 8; - r = e + 6 * 8; - tmp = e + 8 * 8; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_8(rng, k); - } - else { - sp_256_from_mp(k, 8, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_256_ecc_mulmod_base_8(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 8U); - sp_256_norm_8(r); - c = sp_256_cmp_8(r, p256_order); - sp_256_cond_sub_8(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_8(r); - - sp_256_from_mp(x, 8, priv); - sp_256_from_bin(e, 8, hash, (int)hashLen); - - err = sp_256_calc_s_8(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_256_iszero_8(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 8); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_256)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -24135,6 +24261,106 @@ static int sp_256_calc_vfy_point_8(sp_point_256* p1, sp_point_256* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[18 * 8]; + sp_point_256 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 8, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 8; + s = u1 + 4 * 8; + tmp = u1 + 6 * 8; + p2 = p1 + 1; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 8, hash, (int)hashLen); + sp_256_from_mp(u2, 8, rm); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, rm); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, rm); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + } + *res = (sp_256_cmp_8(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { int state; @@ -24284,106 +24510,6 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_256* p1 = NULL; -#else - sp_digit u1[18 * 8]; - sp_point_256 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 8, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 8; - s = u1 + 4 * 8; - tmp = u1 + 6 * 8; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 8, hash, (int)hashLen); - sp_256_from_mp(u2, 8, rm); - sp_256_from_mp(s, 8, sm); - sp_256_from_mp(p2->x, 8, pX); - sp_256_from_mp(p2->y, 8, pY); - sp_256_from_mp(p2->z, 8, pZ); - - err = sp_256_calc_vfy_point_8(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 8, rm); - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_8(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 8, rm); - carry = sp_256_add_8(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_8(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_8(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_8(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -30016,6 +30142,84 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_384_ctx { + int state; + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_digit k[12]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; +#else + sp_point_384 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_384_ctx; + +int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_384_ecc_gen_k_12(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_384_ecc_mulmod_base_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p384_order, 1, 1); + if (err == MP_OKAY) { + if (sp_384_iszero_12(ctx->point->x) || + sp_384_iszero_12(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_384_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_12(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 48 @@ -30098,6 +30302,56 @@ int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + }; + sp_digit k[12]; + sp_point_384 point; +} sp_ecc_sec_gen_384_ctx; + +int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_384_from_mp(ctx->k, 12, priv); + sp_384_point_from_ecc_point_12(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_384_to_bin_12(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -30622,6 +30876,124 @@ static int sp_384_calc_s_12(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 12]; + sp_point_384 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 12; + k = e + 4 * 12; + r = e + 6 * 12; + tmp = e + 8 * 12; + s = e; + + if (hashLen > 48U) { + hashLen = 48U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, k); + } + else { + sp_384_from_mp(k, 12, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); + sp_384_norm_12(r); + c = sp_384_cmp_12(r, p384_order); + sp_384_cond_sub_12(r, r, p384_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_384_norm_12(r); + + sp_384_from_mp(x, 12, priv); + sp_384_from_bin(e, 12, hash, (int)hashLen); + + err = sp_384_calc_s_12(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_384_ctx { int state; @@ -30649,8 +31021,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -30786,124 +31156,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_384* point = NULL; -#else - sp_digit e[7 * 2 * 12]; - sp_point_384 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 12, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 12; - k = e + 4 * 12; - r = e + 6 * 12; - tmp = e + 8 * 12; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_12(rng, k); - } - else { - sp_384_from_mp(k, 12, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_384_ecc_mulmod_base_12(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 12U); - sp_384_norm_12(r); - c = sp_384_cmp_12(r, p384_order); - sp_384_cond_sub_12(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_12(r); - - sp_384_from_mp(x, 12, priv); - sp_384_from_bin(e, 12, hash, (int)hashLen); - - err = sp_384_calc_s_12(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_384_iszero_12(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 12); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_384)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -31350,6 +31602,106 @@ static int sp_384_calc_vfy_point_12(sp_point_384* p1, sp_point_384* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[18 * 12]; + sp_point_384 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 12, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 12; + s = u1 + 4 * 12; + tmp = u1 + 6 * 12; + p2 = p1 + 1; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 12, hash, (int)hashLen); + sp_384_from_mp(u2, 12, rm); + sp_384_from_mp(s, 12, sm); + sp_384_from_mp(p2->x, 12, pX); + sp_384_from_mp(p2->y, 12, pY); + sp_384_from_mp(p2->z, 12, pZ); + + err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 12, rm); + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 12, rm); + carry = sp_384_add_12(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(u2, p384_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); + } + *res = (sp_384_cmp_12(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { int state; @@ -31499,106 +31851,6 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_384* p1 = NULL; -#else - sp_digit u1[18 * 12]; - sp_point_384 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 12, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 12; - s = u1 + 4 * 12; - tmp = u1 + 6 * 12; - p2 = p1 + 1; - - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(u1, 12, hash, (int)hashLen); - sp_384_from_mp(u2, 12, rm); - sp_384_from_mp(s, 12, sm); - sp_384_from_mp(p2->x, 12, pX); - sp_384_from_mp(p2->y, 12, pY); - sp_384_from_mp(p2->z, 12, pZ); - - err = sp_384_calc_vfy_point_12(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 12, rm); - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_384_mont_sqr_12(p1->z, p1->z, p384_mod, p384_mp_mod); - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); - *res = (int)(sp_384_cmp_12(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_384_from_mp(u2, 12, rm); - carry = sp_384_add_12(u2, u2, p384_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_384_norm_12(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_12(u2, p384_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_12(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_384_mont_mul_12(u1, u2, p1->z, p384_mod, p384_mp_mod); - } - *res = (sp_384_cmp_12(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -38352,6 +38604,84 @@ int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_521_ctx { + int state; + sp_521_ecc_mulmod_17_ctx mulmod_ctx; + sp_digit k[17]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521 point[2]; +#else + sp_point_521 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_521_ctx; + +int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_521_ecc_gen_k_17(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_521_ecc_mulmod_base_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p521_order, 1, 1); + if (err == MP_OKAY) { + if (sp_521_iszero_17(ctx->point->x) || + sp_521_iszero_17(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_521_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_521_point_to_ecc_point_17(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE /* Write r as big endian to byte array. * Fixed length number of bytes written: 66 @@ -38436,6 +38766,56 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_521_ctx { + int state; + union { + sp_521_ecc_mulmod_17_ctx mulmod_ctx; + }; + sp_digit k[17]; + sp_point_521 point; +} sp_ecc_sec_gen_521_ctx; + +int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_521_from_mp(ctx->k, 17, priv); + sp_521_point_from_ecc_point_17(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_521_ecc_mulmod_17_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_521_to_bin_17(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -39416,6 +39796,128 @@ static int sp_521_calc_s_17(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_521* point = NULL; +#else + sp_digit e[7 * 2 * 17]; + sp_point_521 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int32 c; + int err = MP_OKAY; + int i; + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 17, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 17; + k = e + 4 * 17; + r = e + 6 * 17; + tmp = e + 8 * 17; + s = e; + + if (hashLen > 66U) { + hashLen = 66U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_521_ecc_gen_k_17(rng, k); + } + else { + sp_521_from_mp(k, 17, km); + mp_zero(km); + } + if (err == MP_OKAY) { + err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 17U); + sp_521_norm_17(r); + c = sp_521_cmp_17(r, p521_order); + sp_521_cond_sub_17(r, r, p521_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_521_norm_17(r); + + sp_521_from_mp(x, 17, priv); + sp_521_from_bin(e, 17, hash, (int)hashLen); + + if (hashLen == 66U) { + sp_521_rshift_17(e, e, 7); + } + + err = sp_521_calc_s_17(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_521_iszero_17(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_521_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_521_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 17); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_521)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_521_ctx { int state; @@ -39443,8 +39945,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -39583,128 +40083,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_521* point = NULL; -#else - sp_digit e[7 * 2 * 17]; - sp_point_521 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int32 c; - int err = MP_OKAY; - int i; - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 17, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 17; - k = e + 4 * 17; - r = e + 6 * 17; - tmp = e + 8 * 17; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_17(rng, k); - } - else { - sp_521_from_mp(k, 17, km); - mp_zero(km); - } - if (err == MP_OKAY) { - err = sp_521_ecc_mulmod_base_17(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 17U); - sp_521_norm_17(r); - c = sp_521_cmp_17(r, p521_order); - sp_521_cond_sub_17(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_17(r); - - sp_521_from_mp(x, 17, priv); - sp_521_from_bin(e, 17, hash, (int)hashLen); - - if (hashLen == 66U) { - sp_521_rshift_17(e, e, 7); - } - - err = sp_521_calc_s_17(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_521_iszero_17(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 17); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_521)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -40244,6 +40622,110 @@ static int sp_521_calc_vfy_point_17(sp_point_521* p1, sp_point_521* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_521* p1 = NULL; +#else + sp_digit u1[18 * 17]; + sp_point_521 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_521* p2 = NULL; + sp_digit carry; + sp_int32 c = 0; + int err = MP_OKAY; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 17, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 17; + s = u1 + 4 * 17; + tmp = u1 + 6 * 17; + p2 = p1 + 1; + + if (hashLen > 66U) { + hashLen = 66U; + } + + sp_521_from_bin(u1, 17, hash, (int)hashLen); + sp_521_from_mp(u2, 17, rm); + sp_521_from_mp(s, 17, sm); + sp_521_from_mp(p2->x, 17, pX); + sp_521_from_mp(p2->y, 17, pY); + sp_521_from_mp(p2->z, 17, pZ); + + if (hashLen == 66U) { + sp_521_rshift_17(u1, u1, 7); + } + + err = sp_521_calc_vfy_point_17(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_521_from_mp(u2, 17, rm); + err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_521_mont_sqr_17(p1->z, p1->z, p521_mod, p521_mp_mod); + sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); + *res = (int)(sp_521_cmp_17(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_521_from_mp(u2, 17, rm); + carry = sp_521_add_17(u2, u2, p521_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_521_norm_17(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_521_cmp_17(u2, p521_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + { + sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); + } + *res = (sp_521_cmp_17(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_521_ctx { int state; @@ -40396,110 +40878,6 @@ int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_521* p1 = NULL; -#else - sp_digit u1[18 * 17]; - sp_point_521 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int32 c = 0; - int err = MP_OKAY; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 17, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 17; - s = u1 + 4 * 17; - tmp = u1 + 6 * 17; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 17, hash, (int)hashLen); - sp_521_from_mp(u2, 17, rm); - sp_521_from_mp(s, 17, sm); - sp_521_from_mp(p2->x, 17, pX); - sp_521_from_mp(p2->y, 17, pY); - sp_521_from_mp(p2->z, 17, pZ); - - if (hashLen == 66U) { - sp_521_rshift_17(u1, u1, 7); - } - - err = sp_521_calc_vfy_point_17(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 17, rm); - err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ - sp_521_mont_sqr_17(p1->z, p1->z, p521_mod, p521_mp_mod); - sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_17(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 17, rm); - carry = sp_521_add_17(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_17(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_17(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_17(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ - { - sp_521_mont_mul_17(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_17(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c index b0c5abd91..229fa2ce2 100644 --- a/wolfcrypt/src/sp_x86_64.c +++ b/wolfcrypt/src/sp_x86_64.c @@ -24627,6 +24627,84 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_256_ctx { + int state; + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_digit k[4]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256 point[2]; +#else + sp_point_256 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_256_ctx; + +int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_256* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_256_ecc_gen_k_4(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_256_ecc_mulmod_base_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p256_order, 1, 1); + if (err == MP_OKAY) { + if (sp_256_iszero_4(ctx->point->x) || + sp_256_iszero_4(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_256_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_256_point_to_ecc_point_4(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE #ifdef __cplusplus extern "C" { @@ -24733,6 +24811,56 @@ int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + }; + sp_digit k[4]; + sp_point_256 point; +} sp_ecc_sec_gen_256_ctx; + +int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_256_from_mp(ctx->k, 4, priv); + sp_256_point_from_ecc_point_4(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_256_to_bin_4(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -25477,6 +25605,132 @@ static int sp_256_calc_s_4(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_256* point = NULL; +#else + sp_digit e[8 * 2 * 4]; + sp_point_256 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 4; + k = e + 4 * 4; + r = e + 6 * 4; + tmp = e + 8 * 4; + s = e; + + if (hashLen > 32U) { + hashLen = 32U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, k); + } + else { + sp_256_from_mp(k, 4, km); + mp_zero(km); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 4U); + sp_256_norm_4(r); + c = sp_256_cmp_4(r, p256_order); + sp_256_cond_sub_4(r, r, p256_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_256_norm_4(r); + + sp_256_from_mp(x, 4, priv); + sp_256_from_bin(e, 4, hash, (int)hashLen); + + err = sp_256_calc_s_4(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_256_iszero_4(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_256_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_256_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 8 * 2 * 4); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_256)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_256_ctx { int state; @@ -25504,8 +25758,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -25641,132 +25893,6 @@ int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_256* point = NULL; -#else - sp_digit e[8 * 2 * 4]; - sp_point_256 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 2 * 4, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 4; - k = e + 4 * 4; - r = e + 6 * 4; - tmp = e + 8 * 4; - s = e; - - if (hashLen > 32U) { - hashLen = 32U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_256_ecc_gen_k_4(rng, k); - } - else { - sp_256_from_mp(k, 4, km); - mp_zero(km); - } - if (err == MP_OKAY) { -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, 1, heap); - else -#endif - err = sp_256_ecc_mulmod_base_4(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 4U); - sp_256_norm_4(r); - c = sp_256_cmp_4(r, p256_order); - sp_256_cond_sub_4(r, r, p256_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_256_norm_4(r); - - sp_256_from_mp(x, 4, priv); - sp_256_from_bin(e, 4, hash, (int)hashLen); - - err = sp_256_calc_s_4(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_256_iszero_4(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_256_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_256_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 8 * 2 * 4); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_256)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -25949,6 +26075,126 @@ static int sp_256_calc_vfy_point_4(sp_point_256* p1, sp_point_256* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_256* p1 = NULL; +#else + sp_digit u1[18 * 4]; + sp_point_256 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_256* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 4; + s = u1 + 4 * 4; + tmp = u1 + 6 * 4; + p2 = p1 + 1; + + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(u1, 4, hash, (int)hashLen); + sp_256_from_mp(u2, 4, rm); + sp_256_from_mp(s, 4, sm); + sp_256_from_mp(p2->x, 4, pX); + sp_256_from_mp(p2->y, 4, pY); + sp_256_from_mp(p2->z, 4, pZ); + + err = sp_256_calc_vfy_point_4(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 4, rm); + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_sqr_avx2_4(p1->z, p1->z, p256_mod, p256_mp_mod); + else +#endif + sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_mul_avx2_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + else +#endif + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 4, rm); + carry = sp_256_add_4(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_4(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(u2, p256_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_mul_avx2_4(u1, u2, p1->z, p256_mod, + p256_mp_mod); + } + else +#endif + { + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + } + *res = (sp_256_cmp_4(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_256_ctx { int state; @@ -26098,126 +26344,6 @@ int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_256* p1 = NULL; -#else - sp_digit u1[18 * 4]; - sp_point_256 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_256* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 4, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 4; - s = u1 + 4 * 4; - tmp = u1 + 6 * 4; - p2 = p1 + 1; - - if (hashLen > 32U) { - hashLen = 32U; - } - - sp_256_from_bin(u1, 4, hash, (int)hashLen); - sp_256_from_mp(u2, 4, rm); - sp_256_from_mp(s, 4, sm); - sp_256_from_mp(p2->x, 4, pX); - sp_256_from_mp(p2->y, 4, pY); - sp_256_from_mp(p2->z, 4, pZ); - - err = sp_256_calc_vfy_point_4(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_256_from_mp(u2, 4, rm); - err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_256_mont_sqr_avx2_4(p1->z, p1->z, p256_mod, p256_mp_mod); - else -#endif - sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod); -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_256_mont_mul_avx2_4(u1, u2, p1->z, p256_mod, p256_mp_mod); - else -#endif - sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); - *res = (int)(sp_256_cmp_4(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_256_from_mp(u2, 4, rm); - carry = sp_256_add_4(u2, u2, p256_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_256_norm_4(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_256_cmp_4(u2, p256_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_256_mont_mul_avx2_4(u1, u2, p1->z, p256_mod, - p256_mp_mod); - } - else -#endif - { - sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); - } - *res = (sp_256_cmp_4(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -49504,6 +49630,84 @@ int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_384_ctx { + int state; + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_digit k[6]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384 point[2]; +#else + sp_point_384 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_384_ctx; + +int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_384* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_384_ecc_gen_k_6(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_384_ecc_mulmod_base_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p384_order, 1, 1); + if (err == MP_OKAY) { + if (sp_384_iszero_6(ctx->point->x) || + sp_384_iszero_6(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_384_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_384_point_to_ecc_point_6(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE #ifdef __cplusplus extern "C" { @@ -49610,6 +49814,56 @@ int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + }; + sp_digit k[6]; + sp_point_384 point; +} sp_ecc_sec_gen_384_ctx; + +int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_384_from_mp(ctx->k, 6, priv); + sp_384_point_from_ecc_point_6(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_384_to_bin_6(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -50212,6 +50466,132 @@ static int sp_384_calc_s_6(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_384* point = NULL; +#else + sp_digit e[7 * 2 * 6]; + sp_point_384 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 6; + k = e + 4 * 6; + r = e + 6 * 6; + tmp = e + 8 * 6; + s = e; + + if (hashLen > 48U) { + hashLen = 48U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, k); + } + else { + sp_384_from_mp(k, 6, km); + mp_zero(km); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_384_ecc_mulmod_base_avx2_6(point, k, 1, 1, heap); + else +#endif + err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 6U); + sp_384_norm_6(r); + c = sp_384_cmp_6(r, p384_order); + sp_384_cond_sub_6(r, r, p384_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_384_norm_6(r); + + sp_384_from_mp(x, 6, priv); + sp_384_from_bin(e, 6, hash, (int)hashLen); + + err = sp_384_calc_s_6(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_384_iszero_6(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_384_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_384_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 6); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_384)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_384_ctx { int state; @@ -50239,8 +50619,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -50376,132 +50754,6 @@ int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_384* point = NULL; -#else - sp_digit e[7 * 2 * 6]; - sp_point_384 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 6, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 6; - k = e + 4 * 6; - r = e + 6 * 6; - tmp = e + 8 * 6; - s = e; - - if (hashLen > 48U) { - hashLen = 48U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_384_ecc_gen_k_6(rng, k); - } - else { - sp_384_from_mp(k, 6, km); - mp_zero(km); - } - if (err == MP_OKAY) { -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - err = sp_384_ecc_mulmod_base_avx2_6(point, k, 1, 1, heap); - else -#endif - err = sp_384_ecc_mulmod_base_6(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 6U); - sp_384_norm_6(r); - c = sp_384_cmp_6(r, p384_order); - sp_384_cond_sub_6(r, r, p384_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_384_norm_6(r); - - sp_384_from_mp(x, 6, priv); - sp_384_from_bin(e, 6, hash, (int)hashLen); - - err = sp_384_calc_s_6(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_384_iszero_6(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_384_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_384_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 6); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_384)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -50768,6 +51020,126 @@ static int sp_384_calc_vfy_point_6(sp_point_384* p1, sp_point_384* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_384* p1 = NULL; +#else + sp_digit u1[18 * 6]; + sp_point_384 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_384* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 6, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 6; + s = u1 + 4 * 6; + tmp = u1 + 6 * 6; + p2 = p1 + 1; + + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(u1, 6, hash, (int)hashLen); + sp_384_from_mp(u2, 6, rm); + sp_384_from_mp(s, 6, sm); + sp_384_from_mp(p2->x, 6, pX); + sp_384_from_mp(p2->y, 6, pY); + sp_384_from_mp(p2->z, 6, pZ); + + err = sp_384_calc_vfy_point_6(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(u2, 6, rm); + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mont_sqr_avx2_6(p1->z, p1->z, p384_mod, p384_mp_mod); + else +#endif + sp_384_mont_sqr_6(p1->z, p1->z, p384_mod, p384_mp_mod); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_384_mont_mul_avx2_6(u1, u2, p1->z, p384_mod, p384_mp_mod); + else +#endif + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); + *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_384_from_mp(u2, 6, rm); + carry = sp_384_add_6(u2, u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(u2, p384_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_384_mont_mul_avx2_6(u1, u2, p1->z, p384_mod, + p384_mp_mod); + } + else +#endif + { + sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); + } + *res = (sp_384_cmp_6(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_384_ctx { int state; @@ -50917,126 +51289,6 @@ int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_384* p1 = NULL; -#else - sp_digit u1[18 * 6]; - sp_point_384 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_384* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 6, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 6; - s = u1 + 4 * 6; - tmp = u1 + 6 * 6; - p2 = p1 + 1; - - if (hashLen > 48U) { - hashLen = 48U; - } - - sp_384_from_bin(u1, 6, hash, (int)hashLen); - sp_384_from_mp(u2, 6, rm); - sp_384_from_mp(s, 6, sm); - sp_384_from_mp(p2->x, 6, pX); - sp_384_from_mp(p2->y, 6, pY); - sp_384_from_mp(p2->z, 6, pZ); - - err = sp_384_calc_vfy_point_6(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_384_from_mp(u2, 6, rm); - err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_384_mont_sqr_avx2_6(p1->z, p1->z, p384_mod, p384_mp_mod); - else -#endif - sp_384_mont_sqr_6(p1->z, p1->z, p384_mod, p384_mp_mod); -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_384_mont_mul_avx2_6(u1, u2, p1->z, p384_mod, p384_mp_mod); - else -#endif - sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); - *res = (int)(sp_384_cmp_6(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_384_from_mp(u2, 6, rm); - carry = sp_384_add_6(u2, u2, p384_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_384_norm_6(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_384_cmp_6(u2, p384_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_384_mod_mul_norm_6(u2, u2, p384_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_384_mont_mul_avx2_6(u1, u2, p1->z, p384_mod, - p384_mp_mod); - } - else -#endif - { - sp_384_mont_mul_6(u1, u2, p1->z, p384_mod, p384_mp_mod); - } - *res = (sp_384_cmp_6(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY @@ -90423,6 +90675,84 @@ int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) return err; } +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_key_gen_521_ctx { + int state; + sp_521_ecc_mulmod_9_ctx mulmod_ctx; + sp_digit k[9]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521 point[2]; +#else + sp_point_521 point[1]; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ +} sp_ecc_key_gen_521_ctx; + +int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv, + ecc_point* pub, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point_521* infinity = ctx->point + 1; +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + + typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx) + >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + err = sp_521_ecc_gen_k_9(rng, ctx->k); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + ctx->state = 1; + } + break; + case 1: + err = sp_521_ecc_mulmod_base_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + err = FP_WOULDBLOCK; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + #else + ctx->state = 3; + #endif + } + break; + #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + case 2: + err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + infinity, ctx->point, p521_order, 1, 1); + if (err == MP_OKAY) { + if (sp_521_iszero_9(ctx->point->x) || + sp_521_iszero_9(ctx->point->y)) { + err = ECC_INF_E; + } + else { + err = FP_WOULDBLOCK; + ctx->state = 3; + } + } + break; + #endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */ + case 3: + err = sp_521_to_mp(ctx->k, priv); + if (err == MP_OKAY) { + err = sp_521_point_to_ecc_point_9(ctx->point, pub); + } + break; + } + + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + #ifdef HAVE_ECC_DHE #ifdef __cplusplus extern "C" { @@ -90529,6 +90859,56 @@ int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out, return err; } + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sec_gen_521_ctx { + int state; + union { + sp_521_ecc_mulmod_9_ctx mulmod_ctx; + }; + sp_digit k[9]; + sp_point_521 point; +} sp_ecc_sec_gen_521_ctx; + +int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv, + const ecc_point* pub, byte* out, word32* outLen, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + if (*outLen < 32U) { + err = BUFFER_E; + } + + switch (ctx->state) { + case 0: + sp_521_from_mp(ctx->k, 9, priv); + sp_521_point_from_ecc_point_9(&ctx->point, pub); + ctx->state = 1; + break; + case 1: + err = sp_521_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &ctx->point, ctx->k, 1, 1, heap); + if (err == MP_OKAY) { + sp_521_to_bin_9(ctx->point.x, out); + *outLen = 32; + } + break; + } + + if (err == MP_OKAY && ctx->state != 1) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx)); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ #endif /* HAVE_ECC_DHE */ #if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) @@ -91186,6 +91566,136 @@ static int sp_521_calc_s_9(sp_digit* s, const sp_digit* r, sp_digit* k, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, + const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* e = NULL; + sp_point_521* point = NULL; +#else + sp_digit e[7 * 2 * 9]; + sp_point_521 point[1]; +#endif + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_digit* s = NULL; + sp_int64 c; + int err = MP_OKAY; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, + DYNAMIC_TYPE_ECC); + if (point == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, + DYNAMIC_TYPE_ECC); + if (e == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + x = e + 2 * 9; + k = e + 4 * 9; + r = e + 6 * 9; + tmp = e + 8 * 9; + s = e; + + if (hashLen > 66U) { + hashLen = 66U; + } + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_521_ecc_gen_k_9(rng, k); + } + else { + sp_521_from_mp(k, 9, km); + mp_zero(km); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_521_ecc_mulmod_base_avx2_9(point, k, 1, 1, heap); + else +#endif + err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, heap); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); + sp_521_norm_9(r); + c = sp_521_cmp_9(r, p521_order); + sp_521_cond_sub_9(r, r, p521_order, + (sp_digit)0 - (sp_digit)(c >= 0)); + sp_521_norm_9(r); + + sp_521_from_mp(x, 9, priv); + sp_521_from_bin(e, 9, hash, (int)hashLen); + + if (hashLen == 66U) { + sp_521_rshift_9(e, e, 7); + } + + err = sp_521_calc_s_9(s, r, k, x, e, tmp); + } + + /* Check that signature is usable. */ + if ((err == MP_OKAY) && (sp_521_iszero_9(s) == 0)) { + break; + } +#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP + i = 1; +#endif + } + + if (i == 0) { + err = RNG_FAILURE_E; + } + + if (err == MP_OKAY) { + err = sp_521_to_mp(r, rm); + } + if (err == MP_OKAY) { + err = sp_521_to_mp(s, sm); + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (e != NULL) +#endif + { + ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(e, heap, DYNAMIC_TYPE_ECC); + #endif + } +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (point != NULL) +#endif + { + ForceZero(point, sizeof(sp_point_521)); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + XFREE(point, heap, DYNAMIC_TYPE_ECC); + #endif + } + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_sign_521_ctx { int state; @@ -91213,8 +91723,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; (void)sizeof(ctx_size_test); - (void)heap; - switch (ctx->state) { case 0: /* INIT */ ctx->s = ctx->e; @@ -91353,136 +91861,6 @@ int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, W return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng, - const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* e = NULL; - sp_point_521* point = NULL; -#else - sp_digit e[7 * 2 * 9]; - sp_point_521 point[1]; -#endif - sp_digit* x = NULL; - sp_digit* k = NULL; - sp_digit* r = NULL; - sp_digit* tmp = NULL; - sp_digit* s = NULL; - sp_int64 c; - int err = MP_OKAY; - int i; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif - - (void)heap; - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, - DYNAMIC_TYPE_ECC); - if (point == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap, - DYNAMIC_TYPE_ECC); - if (e == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - x = e + 2 * 9; - k = e + 4 * 9; - r = e + 6 * 9; - tmp = e + 8 * 9; - s = e; - - if (hashLen > 66U) { - hashLen = 66U; - } - } - - for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { - /* New random point. */ - if (km == NULL || mp_iszero(km)) { - err = sp_521_ecc_gen_k_9(rng, k); - } - else { - sp_521_from_mp(k, 9, km); - mp_zero(km); - } - if (err == MP_OKAY) { -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - err = sp_521_ecc_mulmod_base_avx2_9(point, k, 1, 1, heap); - else -#endif - err = sp_521_ecc_mulmod_base_9(point, k, 1, 1, heap); - } - - if (err == MP_OKAY) { - /* r = point->x mod order */ - XMEMCPY(r, point->x, sizeof(sp_digit) * 9U); - sp_521_norm_9(r); - c = sp_521_cmp_9(r, p521_order); - sp_521_cond_sub_9(r, r, p521_order, - (sp_digit)0 - (sp_digit)(c >= 0)); - sp_521_norm_9(r); - - sp_521_from_mp(x, 9, priv); - sp_521_from_bin(e, 9, hash, (int)hashLen); - - if (hashLen == 66U) { - sp_521_rshift_9(e, e, 7); - } - - err = sp_521_calc_s_9(s, r, k, x, e, tmp); - } - - /* Check that signature is usable. */ - if ((err == MP_OKAY) && (sp_521_iszero_9(s) == 0)) { - break; - } -#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP - i = 1; -#endif - } - - if (i == 0) { - err = RNG_FAILURE_E; - } - - if (err == MP_OKAY) { - err = sp_521_to_mp(r, rm); - } - if (err == MP_OKAY) { - err = sp_521_to_mp(s, sm); - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (e != NULL) -#endif - { - ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(e, heap, DYNAMIC_TYPE_ECC); - #endif - } -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (point != NULL) -#endif - { - ForceZero(point, sizeof(sp_point_521)); - #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - XFREE(point, heap, DYNAMIC_TYPE_ECC); - #endif - } - - return err; -} #endif /* HAVE_ECC_SIGN */ #ifndef WOLFSSL_SP_SMALL @@ -91752,6 +92130,130 @@ static int sp_521_calc_vfy_point_9(sp_point_521* p1, sp_point_521* p2, * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ +int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, + const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, + int* res, void* heap) +{ +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + sp_digit* u1 = NULL; + sp_point_521* p1 = NULL; +#else + sp_digit u1[18 * 9]; + sp_point_521 p1[2]; +#endif + sp_digit* u2 = NULL; + sp_digit* s = NULL; + sp_digit* tmp = NULL; + sp_point_521* p2 = NULL; + sp_digit carry; + sp_int64 c = 0; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (err == MP_OKAY) { + p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, + DYNAMIC_TYPE_ECC); + if (p1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, + DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } +#endif + + if (err == MP_OKAY) { + u2 = u1 + 2 * 9; + s = u1 + 4 * 9; + tmp = u1 + 6 * 9; + p2 = p1 + 1; + + if (hashLen > 66U) { + hashLen = 66U; + } + + sp_521_from_bin(u1, 9, hash, (int)hashLen); + sp_521_from_mp(u2, 9, rm); + sp_521_from_mp(s, 9, sm); + sp_521_from_mp(p2->x, 9, pX); + sp_521_from_mp(p2->y, 9, pY); + sp_521_from_mp(p2->z, 9, pZ); + + if (hashLen == 66U) { + sp_521_rshift_9(u1, u1, 7); + } + + err = sp_521_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); + } + if (err == MP_OKAY) { + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_521_from_mp(u2, 9, rm); + err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_521_mont_sqr_avx2_9(p1->z, p1->z, p521_mod, p521_mp_mod); + else +#endif + sp_521_mont_sqr_9(p1->z, p1->z, p521_mod, p521_mp_mod); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_521_mont_mul_avx2_9(u1, u2, p1->z, p521_mod, p521_mp_mod); + else +#endif + sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); + *res = (int)(sp_521_cmp_9(p1->x, u1) == 0); + if (*res == 0) { + /* Reload r and add order. */ + sp_521_from_mp(u2, 9, rm); + carry = sp_521_add_9(u2, u2, p521_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_521_norm_9(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_521_cmp_9(u2, p521_mod); + } + } + if ((*res == 0) && (c < 0)) { + /* Convert to Montogomery form */ + err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_521_mont_mul_avx2_9(u1, u2, p1->z, p521_mod, + p521_mp_mod); + } + else +#endif + { + sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); + } + *res = (sp_521_cmp_9(p1->x, u1) == 0); + } + } + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) + if (u1 != NULL) + XFREE(u1, heap, DYNAMIC_TYPE_ECC); + if (p1 != NULL) + XFREE(p1, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + #ifdef WOLFSSL_SP_NONBLOCK typedef struct sp_ecc_verify_521_ctx { int state; @@ -91904,130 +92406,6 @@ int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, return err; } #endif /* WOLFSSL_SP_NONBLOCK */ - -int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX, - const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm, - int* res, void* heap) -{ -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - sp_digit* u1 = NULL; - sp_point_521* p1 = NULL; -#else - sp_digit u1[18 * 9]; - sp_point_521 p1[2]; -#endif - sp_digit* u2 = NULL; - sp_digit* s = NULL; - sp_digit* tmp = NULL; - sp_point_521* p2 = NULL; - sp_digit carry; - sp_int64 c = 0; - int err = MP_OKAY; -#ifdef HAVE_INTEL_AVX2 - word32 cpuid_flags = cpuid_get_flags(); -#endif - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (err == MP_OKAY) { - p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, - DYNAMIC_TYPE_ECC); - if (p1 == NULL) - err = MEMORY_E; - } - if (err == MP_OKAY) { - u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap, - DYNAMIC_TYPE_ECC); - if (u1 == NULL) - err = MEMORY_E; - } -#endif - - if (err == MP_OKAY) { - u2 = u1 + 2 * 9; - s = u1 + 4 * 9; - tmp = u1 + 6 * 9; - p2 = p1 + 1; - - if (hashLen > 66U) { - hashLen = 66U; - } - - sp_521_from_bin(u1, 9, hash, (int)hashLen); - sp_521_from_mp(u2, 9, rm); - sp_521_from_mp(s, 9, sm); - sp_521_from_mp(p2->x, 9, pX); - sp_521_from_mp(p2->y, 9, pY); - sp_521_from_mp(p2->z, 9, pZ); - - if (hashLen == 66U) { - sp_521_rshift_9(u1, u1, 7); - } - - err = sp_521_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap); - } - if (err == MP_OKAY) { - /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ - /* Reload r and convert to Montgomery form. */ - sp_521_from_mp(u2, 9, rm); - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - } - - if (err == MP_OKAY) { - /* u1 = r.z'.z' mod prime */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_521_mont_sqr_avx2_9(p1->z, p1->z, p521_mod, p521_mp_mod); - else -#endif - sp_521_mont_sqr_9(p1->z, p1->z, p521_mod, p521_mp_mod); -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) - sp_521_mont_mul_avx2_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - else -#endif - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - *res = (int)(sp_521_cmp_9(p1->x, u1) == 0); - if (*res == 0) { - /* Reload r and add order. */ - sp_521_from_mp(u2, 9, rm); - carry = sp_521_add_9(u2, u2, p521_order); - /* Carry means result is greater than mod and is not valid. */ - if (carry == 0) { - sp_521_norm_9(u2); - - /* Compare with mod and if greater or equal then not valid. */ - c = sp_521_cmp_9(u2, p521_mod); - } - } - if ((*res == 0) && (c < 0)) { - /* Convert to Montogomery form */ - err = sp_521_mod_mul_norm_9(u2, u2, p521_mod); - if (err == MP_OKAY) { - /* u1 = (r + 1*order).z'.z' mod prime */ -#ifdef HAVE_INTEL_AVX2 - if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { - sp_521_mont_mul_avx2_9(u1, u2, p1->z, p521_mod, - p521_mp_mod); - } - else -#endif - { - sp_521_mont_mul_9(u1, u2, p1->z, p521_mod, p521_mp_mod); - } - *res = (sp_521_cmp_9(p1->x, u1) == 0); - } - } - } - -#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC) - if (u1 != NULL) - XFREE(u1, heap, DYNAMIC_TYPE_ECC); - if (p1 != NULL) - XFREE(p1, heap, DYNAMIC_TYPE_ECC); -#endif - - return err; -} #endif /* HAVE_ECC_VERIFY */ #ifdef HAVE_ECC_CHECK_KEY diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 20bbd5f19..0f66cb6db 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -24766,24 +24766,31 @@ exit: /* ECC Non-blocking tests for Sign and Verify */ /* Requires SP math and supports P384 or P256 */ /* ./configure --enable-ecc=nonblock --enable-sp=yes,nonblock CFLAGS="-DWOLFSSL_PUBLIC_MP" */ -#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_PUBLIC_MP) && \ - defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) && \ - defined(WOLFSSL_HAVE_SP_ECC) -/* Test Data - Random */ -static const uint8_t kMsg[] = { - 0x69, 0xbc, 0x9f, 0xce, 0x68, 0x17, 0xc2, 0x10, 0xea, 0xfc, 0x10, 0x65, 0x67, 0x52, 0xed, 0x78, - 0x6e, 0xb8, 0x83, 0x9c, 0x9a, 0xb4, 0x56, 0x0d, 0xc1, 0x0d, 0x1f, 0x78, 0x6e, 0x75, 0xd7, 0xbe, - 0x92, 0x6b, 0x12, 0xf6, 0x76, 0x60, 0x8e, 0xb1, 0xf4, 0x19, 0x0c, 0x81, 0xe7, 0x54, 0x5e, 0xbc, - 0xe0, 0xae, 0xc2, 0x7d, 0x1b, 0xc4, 0x6e, 0xec, 0xb1, 0x99, 0x6c, 0xbf, 0x0e, 0x38, 0xa8, 0x01, - 0xa6, 0x9a, 0x48, 0x12, 0xe4, 0xc9, 0x3b, 0xf0, 0x63, 0x46, 0x15, 0xb4, 0x61, 0xa8, 0x1a, 0x60, - 0x71, 0x87, 0x98, 0xd7, 0x6f, 0x98, 0x7b, 0x2d, 0xb9, 0x19, 0x1b, 0x21, 0x9c, 0x70, 0x58, 0xe8, - 0x0d, 0x0f, 0xe9, 0x2d, 0x9a, 0x9a, 0xf1, 0x55, 0xa0, 0x4c, 0xd3, 0x07, 0xbd, 0x97, 0x48, 0xec, - 0x88, 0x0a, 0xaf, 0xb3, 0x80, 0x78, 0xa4, 0x59, 0x43, 0x57, 0xd3, 0xa7, 0x01, 0x66, 0x0e, 0xfc -}; - +#if defined(WC_ECC_NONBLOCK) && defined(WOLFSSL_HAVE_SP_ECC) && \ + defined(WOLFSSL_PUBLIC_MP) /* ECC Private Key "d" */ -static const uint8_t kPrivKey[] = { +static const byte p256PrivKey[] = { + /* SECP256R1 */ + /* d */ + 0x1e, 0xe7, 0x70, 0x07, 0xd3, 0x30, 0x94, 0x39, + 0x28, 0x90, 0xdf, 0x23, 0x88, 0x2c, 0x4a, 0x34, + 0x15, 0xdb, 0x4c, 0x43, 0xcd, 0xfa, 0xe5, 0x1f, + 0x3d, 0x4c, 0x37, 0xfe, 0x59, 0x3b, 0x96, 0xd8 +}; +#ifdef HAVE_ECC384 +static const byte p384PrivKey[] = { + /* SECP384R1 */ + /* d */ + 0xa4, 0xe5, 0x06, 0xe8, 0x06, 0x16, 0x3e, 0xab, + 0x89, 0xf8, 0x60, 0x43, 0xc0, 0x60, 0x25, 0xdb, + 0xba, 0x7b, 0xfe, 0x19, 0x35, 0x08, 0x55, 0x65, + 0x76, 0xe2, 0xdc, 0xe0, 0x01, 0x8b, 0x6b, 0x68, + 0xdf, 0xcf, 0x6f, 0x80, 0x12, 0xce, 0x79, 0x37, + 0xeb, 0x2b, 0x9c, 0x7b, 0xc4, 0x68, 0x1c, 0x74 +}; +#endif /* HAVE_ECC384 */ #ifdef HAVE_ECC521 +static const byte p521PrivKey[] = { /* SECP521R1 */ /* d */ 0x01, 0x68, 0x91, 0x33, 0x53, 0xe2, 0x90, 0x68, @@ -24795,28 +24802,44 @@ static const uint8_t kPrivKey[] = { 0x02, 0x32, 0xee, 0x26, 0x87, 0xcc, 0xed, 0x63, 0x3f, 0x39, 0x27, 0xf0, 0xd7, 0x17, 0x77, 0xa1, 0xa4, 0x36 -#elif defined(HAVE_ECC384) - /* SECP384R1 */ - /* d */ - 0xa4, 0xe5, 0x06, 0xe8, 0x06, 0x16, 0x3e, 0xab, - 0x89, 0xf8, 0x60, 0x43, 0xc0, 0x60, 0x25, 0xdb, - 0xba, 0x7b, 0xfe, 0x19, 0x35, 0x08, 0x55, 0x65, - 0x76, 0xe2, 0xdc, 0xe0, 0x01, 0x8b, 0x6b, 0x68, - 0xdf, 0xcf, 0x6f, 0x80, 0x12, 0xce, 0x79, 0x37, - 0xeb, 0x2b, 0x9c, 0x7b, 0xc4, 0x68, 0x1c, 0x74 -#else - /* SECP256R1 */ - /* d */ - 0x1e, 0xe7, 0x70, 0x07, 0xd3, 0x30, 0x94, 0x39, - 0x28, 0x90, 0xdf, 0x23, 0x88, 0x2c, 0x4a, 0x34, - 0x15, 0xdb, 0x4c, 0x43, 0xcd, 0xfa, 0xe5, 0x1f, - 0x3d, 0x4c, 0x37, 0xfe, 0x59, 0x3b, 0x96, 0xd8 -#endif }; +#endif /* HAVE_ECC521 */ /* ECC public key Qx/Qy */ -static const uint8_t kPubKey[] = { +static const byte p256PubKey[] = { + /* SECP256R1 */ + /* Qx */ + 0x96, 0x93, 0x1c, 0x53, 0x0b, 0x43, 0x6c, 0x42, + 0x0c, 0x52, 0x90, 0xe4, 0xa7, 0xec, 0x98, 0xb1, + 0xaf, 0xd4, 0x14, 0x49, 0xd8, 0xc1, 0x42, 0x82, + 0x04, 0x78, 0xd1, 0x90, 0xae, 0xa0, 0x6c, 0x07, + /* Qy */ + 0xf2, 0x3a, 0xb5, 0x10, 0x32, 0x8d, 0xce, 0x9e, + 0x76, 0xa0, 0xd2, 0x8c, 0xf3, 0xfc, 0xa9, 0x94, + 0x43, 0x24, 0xe6, 0x82, 0x00, 0x40, 0xc6, 0xdb, + 0x1c, 0x2f, 0xcd, 0x38, 0x4b, 0x60, 0xdd, 0x61 +}; +#ifdef HAVE_ECC384 +static const byte p384PubKey[] = { + /* SECP384R1 */ + /* Qx */ + 0xea, 0xcf, 0x93, 0x4f, 0x2c, 0x09, 0xbb, 0x39, + 0x14, 0x0f, 0x56, 0x64, 0xc3, 0x40, 0xb4, 0xdf, + 0x0e, 0x63, 0xae, 0xe5, 0x71, 0x4b, 0x00, 0xcc, + 0x04, 0x97, 0xff, 0xe1, 0xe9, 0x38, 0x96, 0xbb, + 0x5f, 0x91, 0xb2, 0x6a, 0xcc, 0xb5, 0x39, 0x5f, + 0x8f, 0x70, 0x59, 0xf1, 0x01, 0xf6, 0x5a, 0x2b, + /* Qy */ + 0x01, 0x6c, 0x68, 0x0b, 0xcf, 0x55, 0x25, 0xaf, + 0x6d, 0x98, 0x48, 0x0a, 0xa8, 0x74, 0xc9, 0xa9, + 0x17, 0xa0, 0x0c, 0xc3, 0xfb, 0xd3, 0x23, 0x68, + 0xfe, 0x04, 0x3c, 0x63, 0x50, 0x88, 0x3b, 0xb9, + 0x4f, 0x7c, 0x67, 0x34, 0xf7, 0x3b, 0xa9, 0x73, + 0xe7, 0x1b, 0xc3, 0x51, 0x5e, 0x22, 0x18, 0xec +}; +#endif #ifdef HAVE_ECC521 +static const byte p521PubKey[] = { /* SECP521R1 */ /* Qx */ 0x01, 0x62, 0x6e, 0xf1, 0x00, 0xec, 0xd8, 0x99, @@ -24838,269 +24861,8 @@ static const uint8_t kPubKey[] = { 0x37, 0x24, 0xd8, 0xbf, 0x03, 0x0d, 0x8b, 0xb5, 0x40, 0x5c, 0x4f, 0xd6, 0x13, 0x73, 0x42, 0xbc, 0x91, 0xd9 -#elif defined(HAVE_ECC384) - /* SECP384R1 */ - /* Qx */ - 0xea, 0xcf, 0x93, 0x4f, 0x2c, 0x09, 0xbb, 0x39, - 0x14, 0x0f, 0x56, 0x64, 0xc3, 0x40, 0xb4, 0xdf, - 0x0e, 0x63, 0xae, 0xe5, 0x71, 0x4b, 0x00, 0xcc, - 0x04, 0x97, 0xff, 0xe1, 0xe9, 0x38, 0x96, 0xbb, - 0x5f, 0x91, 0xb2, 0x6a, 0xcc, 0xb5, 0x39, 0x5f, - 0x8f, 0x70, 0x59, 0xf1, 0x01, 0xf6, 0x5a, 0x2b, - /* Qy */ - 0x01, 0x6c, 0x68, 0x0b, 0xcf, 0x55, 0x25, 0xaf, - 0x6d, 0x98, 0x48, 0x0a, 0xa8, 0x74, 0xc9, 0xa9, - 0x17, 0xa0, 0x0c, 0xc3, 0xfb, 0xd3, 0x23, 0x68, - 0xfe, 0x04, 0x3c, 0x63, 0x50, 0x88, 0x3b, 0xb9, - 0x4f, 0x7c, 0x67, 0x34, 0xf7, 0x3b, 0xa9, 0x73, - 0xe7, 0x1b, 0xc3, 0x51, 0x5e, 0x22, 0x18, 0xec -#else - /* SECP256R1 */ - /* Qx */ - 0x96, 0x93, 0x1c, 0x53, 0x0b, 0x43, 0x6c, 0x42, - 0x0c, 0x52, 0x90, 0xe4, 0xa7, 0xec, 0x98, 0xb1, - 0xaf, 0xd4, 0x14, 0x49, 0xd8, 0xc1, 0x42, 0x82, - 0x04, 0x78, 0xd1, 0x90, 0xae, 0xa0, 0x6c, 0x07, - /* Qy */ - 0xf2, 0x3a, 0xb5, 0x10, 0x32, 0x8d, 0xce, 0x9e, - 0x76, 0xa0, 0xd2, 0x8c, 0xf3, 0xfc, 0xa9, 0x94, - 0x43, 0x24, 0xe6, 0x82, 0x00, 0x40, 0xc6, 0xdb, - 0x1c, 0x2f, 0xcd, 0x38, 0x4b, 0x60, 0xdd, 0x61 -#endif }; -/* ECC Curve */ -#ifdef HAVE_ECC521 - /* SECP521R1 */ - #define ECC_CURVE_SZ 66 - #define ECC_CURVE_ID ECC_SECP521R1 -#elif defined(HAVE_ECC384) - /* SECP384R1 */ - #define ECC_CURVE_SZ 48 - #define ECC_CURVE_ID ECC_SECP384R1 -#else - /* SECP256R1 */ - #define ECC_CURVE_SZ 32 - #define ECC_CURVE_ID ECC_SECP256R1 -#endif - -/* Hash Algorithm */ -#if defined(HAVE_ECC521) && defined(WOLFSSL_SHA3) - #define HASH_DIGEST_SZ WC_SHA3_512_DIGEST_SIZE - #define HASH_SHA_VER 3 - #define CRYPTO_HASH_FN crypto_sha3_512 -#elif defined(HAVE_ECC521) && defined(WOLFSSL_SHA512) - #define HASH_DIGEST_SZ WC_SHA512_DIGEST_SIZE - #define HASH_SHA_VER 2 - #define CRYPTO_HASH_FN crypto_sha2_512 -#elif defined(HAVE_ECC384) && defined(WOLFSSL_SHA3) - #define HASH_DIGEST_SZ WC_SHA3_384_DIGEST_SIZE - #define HASH_SHA_VER 3 - #define CRYPTO_HASH_FN crypto_sha3_384 -#elif defined(HAVE_ECC384) && defined(WOLFSSL_SHA384) - #define HASH_DIGEST_SZ WC_SHA384_DIGEST_SIZE - #define HASH_SHA_VER 2 - #define CRYPTO_HASH_FN crypto_sha2_384 -#elif !defined(NO_SHA256) - #define HASH_DIGEST_SZ WC_SHA256_DIGEST_SIZE - #define HASH_SHA_VER 2 - #define CRYPTO_HASH_FN crypto_sha2_256 -#else - #error test configuration not supported -#endif - -#if defined(HAVE_ECC521) && defined(WOLFSSL_SHA3) -/* helper to perform hashing block by block */ -static int crypto_sha3_512(const uint8_t *buf, uint32_t len, uint8_t *hash, - uint32_t hashSz, uint32_t blkSz) -{ - int ret; - uint32_t i = 0, chunk; - wc_Sha3 sha3; - - /* validate arguments */ - if ((buf == NULL && len > 0) || hash == NULL || - hashSz < WC_SHA3_512_DIGEST_SIZE || blkSz == 0) - { - return BAD_FUNC_ARG; - } - - /* Init Sha3_512 structure */ - ret = wc_InitSha3_512(&sha3, NULL, INVALID_DEVID); - if (ret != 0) { - return ret; - } - while (i < len) { - chunk = blkSz; - if ((chunk + i) > len) - chunk = len - i; - /* Perform chunked update */ - ret = wc_Sha3_512_Update(&sha3, (buf + i), chunk); - if (ret != 0) { - break; - } - i += chunk; - } - if (ret == 0) { - /* Get final digest result */ - ret = wc_Sha3_512_Final(&sha3, hash); - } - return ret; -} -#elif defined(HAVE_ECC521) && defined(WOLFSSL_SHA512) -/* helper to perform hashing block by block */ -static int crypto_sha2_512(const uint8_t *buf, uint32_t len, uint8_t *hash, - uint32_t hashSz, uint32_t blkSz) -{ - int ret; - uint32_t i = 0, chunk; - wc_Sha512 sha512; - - /* validate arguments */ - if ((buf == NULL && len > 0) || hash == NULL || - hashSz < WC_SHA512_DIGEST_SIZE || blkSz == 0) - { - return BAD_FUNC_ARG; - } - - /* Init Sha512 structure */ - ret = wc_InitSha512(&sha512); - if (ret != 0) { - return ret; - } - while (i < len) { - chunk = blkSz; - if ((chunk + i) > len) - chunk = len - i; - /* Perform chunked update */ - ret = wc_Sha512Update(&sha512, (buf + i), chunk); - if (ret != 0) { - break; - } - i += chunk; - } - if (ret == 0) { - /* Get final digest result */ - ret = wc_Sha512Final(&sha512, hash); - } - return ret; -} -#elif defined(HAVE_ECC384) && defined(WOLFSSL_SHA3) -/* helper to perform hashing block by block */ -static int crypto_sha3_384(const uint8_t *buf, uint32_t len, uint8_t *hash, - uint32_t hashSz, uint32_t blkSz) -{ - int ret; - uint32_t i = 0, chunk; - wc_Sha3 sha3; - - /* validate arguments */ - if ((buf == NULL && len > 0) || hash == NULL || - hashSz < WC_SHA3_384_DIGEST_SIZE || blkSz == 0) - { - return BAD_FUNC_ARG; - } - - /* Init Sha3_384 structure */ - ret = wc_InitSha3_384(&sha3, NULL, INVALID_DEVID); - if (ret != 0) { - return ret; - } - while (i < len) { - chunk = blkSz; - if ((chunk + i) > len) - chunk = len - i; - /* Perform chunked update */ - ret = wc_Sha3_384_Update(&sha3, (buf + i), chunk); - if (ret != 0) { - break; - } - i += chunk; - } - if (ret == 0) { - /* Get final digest result */ - ret = wc_Sha3_384_Final(&sha3, hash); - } - return ret; -} -#elif defined(HAVE_ECC384) && defined(WOLFSSL_SHA384) -/* helper to perform hashing block by block */ -static int crypto_sha2_384(const uint8_t *buf, uint32_t len, uint8_t *hash, - uint32_t hashSz, uint32_t blkSz) -{ - int ret; - uint32_t i = 0, chunk; - wc_Sha384 sha384; - - /* validate arguments */ - if ((buf == NULL && len > 0) || hash == NULL || - hashSz < WC_SHA384_DIGEST_SIZE || blkSz == 0) - { - return BAD_FUNC_ARG; - } - - /* Init Sha384 structure */ - ret = wc_InitSha384(&sha384); - if (ret != 0) { - return ret; - } - while (i < len) { - chunk = blkSz; - if ((chunk + i) > len) - chunk = len - i; - /* Perform chunked update */ - ret = wc_Sha384Update(&sha384, (buf + i), chunk); - if (ret != 0) { - break; - } - i += chunk; - } - if (ret == 0) { - /* Get final digest result */ - ret = wc_Sha384Final(&sha384, hash); - } - return ret; -} -#elif !defined(NO_SHA256) -/* helper to perform hashing block by block */ -static int crypto_sha2_256(const uint8_t *buf, uint32_t len, uint8_t *hash, - uint32_t hashSz, uint32_t blkSz) -{ - int ret; - uint32_t i = 0, chunk; - wc_Sha256 sha256; - - /* validate arguments */ - if ((buf == NULL && len > 0) || hash == NULL || - hashSz < WC_SHA256_DIGEST_SIZE || blkSz == 0) - { - return BAD_FUNC_ARG; - } - - /* Init Sha256 structure */ - ret = wc_InitSha256(&sha256); - if (ret != 0) { - return ret; - } - while (i < len) { - chunk = blkSz; - if ((chunk + i) > len) - chunk = len - i; - /* Perform chunked update */ - ret = wc_Sha256Update(&sha256, (buf + i), chunk); - if (ret != 0) { - break; - } - i += chunk; - } - if (ret == 0) { - /* Get final digest result */ - ret = wc_Sha256Final(&sha256, hash); - } - return ret; -} -#endif - /* perform verify of signature and hash using public key */ /* key is public Qx + public Qy */ /* sig is r + s */ @@ -25283,48 +25045,177 @@ static int crypto_ecc_sign(const uint8_t *key, uint32_t keySz, return ret; } +#endif /* HAVE_ECC_SIGN && HAVE_ECC_VERIFY */ -static int ecc_test_nonblock(WC_RNG* rng) +/* + * This test doesn't work with WOLFSSL_VALIDATE_ECC_KEYGEN defined because we + * don't have non-blocking versions of the key checking functions, yet. + */ +#if defined(HAVE_ECC_DHE) && !defined(WOLFSSL_VALIDATE_ECC_KEYGEN) +static int ecc_test_nonblock_dhe(int curveId, word32 curveSz, + const byte* privKey, const byte* pubKey, WC_RNG* rng) { int ret; - uint8_t hash[HASH_DIGEST_SZ]; - uint8_t sig[ECC_CURVE_SZ*2]; - uint32_t sigSz = sizeof(sig); + ecc_key keyA; + ecc_key keyB; + ecc_nb_ctx_t nbCtxA; + ecc_nb_ctx_t nbCtxB; + byte secretA[ECC_SHARED_SIZE]; + byte secretB[ECC_SHARED_SIZE]; + word32 secretSzA = ECC_SHARED_SIZE; + word32 secretSzB = ECC_SHARED_SIZE; + int count = 0; - ret = CRYPTO_HASH_FN( - kMsg, sizeof(kMsg), /* input message */ - hash, sizeof(hash), /* hash digest result */ - 32 /* configurable block / chunk size */ - ); + ret = wc_ecc_init(&keyA); + if (ret == 0) { + ret = wc_ecc_init(&keyB); + } + if (ret == 0) { + ret = wc_ecc_set_nonblock(&keyA, &nbCtxA); + } + if (ret == 0) { + ret = wc_ecc_set_nonblock(&keyB, &nbCtxB); + } + if (ret == 0) { + do { + ret = wc_ecc_make_key_ex(rng, curveSz, &keyA, curveId); + count++; + } while (ret == FP_WOULDBLOCK); + } +#ifdef DEBUG_WOLFSSL + fprintf(stderr, "ECC non-block key gen: %d times\n", count); +#endif + if (ret == 0) { + ret = wc_ecc_check_key(&keyA); + } + if (ret == 0) { + ret = wc_ecc_import_unsigned(&keyB, pubKey, pubKey + curveSz, + privKey, curveId); + } + count = 0; + if (ret == 0) { + do { + ret = wc_ecc_shared_secret(&keyA, &keyB, secretA, &secretSzA); + count++; + } while (ret == FP_WOULDBLOCK); + } +#ifdef DEBUG_WOLFSSL + fprintf(stderr, "ECC non-block shared secret: %d times\n", count); +#endif + if (ret == 0) { + do { + ret = wc_ecc_shared_secret(&keyB, &keyA, secretB, &secretSzB); + } while (ret == FP_WOULDBLOCK); + } + if (ret == 0) { + if (secretSzA != secretSzB || + XMEMCMP(secretA, secretB, secretSzA) != 0) { + ret = -1; + } + } + + wc_ecc_free(&keyA); + wc_ecc_free(&keyB); + + return ret; +} +#endif /* HAVE_ECC_DHE && !WOLFSSL_VALIDATE_ECC_KEYGEN */ + +#if defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) +static int ecc_test_nonblock_ecdsa(int curveId, word32 curveSz, + const byte* privKey, word32 privKeySz, const byte* pubKey, word32 pubKeySz, + WC_RNG* rng) +{ + int ret = 0; + byte* sig = NULL; + word32 sigSz = curveSz * 2; + static const byte hash[] = { + 0x8d, 0x28, 0xa3, 0x8b, 0x0b, 0xa9, 0xfe, 0xd4, 0x0e, 0x54, 0xc4, 0x17, + 0x3d, 0x54, 0x66, 0x34, 0xbf, 0x5d, 0x6f, 0x46, 0xc2, 0x20, 0xcb, 0xc3, + 0x22, 0xe9, 0xb0, 0xdf, 0xe7, 0x64, 0x3f, 0xd9 + }; + + sig = (byte*)XMALLOC(sigSz, HEAP_HINT, DYNAMIC_TYPE_SIGNATURE); + if (sig == NULL) { + ret = -1; + } if (ret == 0) { /* Sign hash using private key */ /* Note: result of an ECC sign varies for each call even with same private key and hash. This is because a new random public key is used for each operation. */ - ret = crypto_ecc_sign( - kPrivKey, sizeof(kPrivKey), /* private key */ - hash, sizeof(hash), /* computed hash digest */ - sig, &sigSz, /* signature r/s */ - ECC_CURVE_SZ, /* curve size in bytes */ - ECC_CURVE_ID, /* curve id */ - rng - ); + ret = crypto_ecc_sign(privKey, privKeySz, hash, sizeof(hash), sig, + &sigSz, curveSz, curveId, rng); } - if (ret == 0) { /* Verify generated signature is valid */ - ret = crypto_ecc_verify( - kPubKey, sizeof(kPubKey), /* public key point x/y */ - hash, sizeof(hash), /* computed hash digest */ - sig, sigSz, /* signature r/s */ - ECC_CURVE_SZ, /* curve size in bytes */ - ECC_CURVE_ID /* curve id */ - ); + ret = crypto_ecc_verify(pubKey, pubKeySz, hash, sizeof(hash), sig, + sigSz, curveSz, curveId); + } + + if (sig != NULL) { + XFREE(sig, HEAP_HINT, DYNAMIC_TYPE_SIGNATURE); } return ret; } -#endif /* WC_ECC_NONBLOCK && WOLFSSL_PUBLIC_MP && HAVE_ECC_SIGN && HAVE_ECC_VERIFY */ +#endif /* HAVE_ECC_SIGN && HAVE_ECC_VERIFY */ + +static int ecc_test_nonblock(WC_RNG* rng) +{ + int ret = 0; + word32 i; + int curveIds[3] = {0, 0, 0}; + word32 curveSzs[3] = {0, 0, 0}; + const byte* privKeys[3] = {NULL, NULL, NULL}; + word32 privKeySzs[3] = {0, 0, 0}; + const byte* pubKeys[3] = {NULL, NULL, NULL}; + word32 pubKeySzs[3] = {0, 0, 0}; + + curveIds[0] = ECC_SECP256R1; + curveSzs[0] = 32; + privKeys[0] = p256PrivKey; + privKeySzs[0] = sizeof(p256PrivKey); + pubKeys[0] = p256PubKey; + pubKeySzs[0] = sizeof(p256PubKey); +#ifdef HAVE_ECC384 + curveIds[1] = ECC_SECP384R1; + curveSzs[1] = 48; + privKeys[1] = p384PrivKey; + privKeySzs[1] = sizeof(p384PrivKey); + pubKeys[1] = p384PubKey; + pubKeySzs[1] = sizeof(p384PubKey); +#endif +#ifdef HAVE_ECC521 + curveIds[2] = ECC_SECP521R1; + curveSzs[2] = 66; + privKeys[2] = p521PrivKey; + privKeySzs[2] = sizeof(p521PrivKey); + pubKeys[2] = p521PubKey; + pubKeySzs[2] = sizeof(p521PubKey); +#endif + + for (i = 0; ret == 0 && i < sizeof(curveIds) / sizeof(curveIds[0]); ++i) { + if (curveIds[i] == 0) { + continue; + } + + #if defined(HAVE_ECC_SIGN) && defined(HAVE_ECC_VERIFY) + ret = ecc_test_nonblock_ecdsa(curveIds[i], curveSzs[i], privKeys[i], + privKeySzs[i], pubKeys[i], pubKeySzs[i], rng); + #endif /* HAVE_ECC_SIGN && HAVE_ECC_VERIFY */ + + #if defined(HAVE_ECC_DHE) && !defined(WOLFSSL_VALIDATE_ECC_KEYGEN) + if (ret == 0) { + ret = ecc_test_nonblock_dhe(curveIds[i], curveSzs[i], privKeys[i], + pubKeys[i], rng); + } + #endif /* HAVE_ECC_DHE && !WOLFSSL_VALIDATE_ECC_KEYGEN */ + } + + return ret; +} +#endif /* WC_ECC_NONBLOCK && WOLFSSL_HAVE_SP_ECC && WOLFSSL_PUBLIC_MP */ WOLFSSL_TEST_SUBROUTINE int ecc_test(void) { diff --git a/wolfssl/wolfcrypt/sp.h b/wolfssl/wolfcrypt/sp.h index 528ab0b55..c046b41fa 100644 --- a/wolfssl/wolfcrypt/sp.h +++ b/wolfssl/wolfcrypt/sp.h @@ -329,18 +329,35 @@ WOLFSSL_LOCAL int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY, #endif /* HAVE_FIPS_VERSION && HAVE_FIPS_VERSION == 2 && !WOLFSSL_SP_ARM[32|64]_ASM */ #ifdef WOLFSSL_SP_NONBLOCK +WOLFSSL_LOCAL int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, + mp_int* priv, ecc_point* pub, void* heap); +WOLFSSL_LOCAL int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, + const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, + void* heap); WOLFSSL_LOCAL int sp_ecc_sign_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap); WOLFSSL_LOCAL int sp_ecc_verify_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm, int* res, void* heap); + +WOLFSSL_LOCAL int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, + mp_int* priv, ecc_point* pub, void* heap); +WOLFSSL_LOCAL int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, + const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, + void* heap); WOLFSSL_LOCAL int sp_ecc_sign_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap); WOLFSSL_LOCAL int sp_ecc_verify_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ, const mp_int* r, const mp_int* sm, int* res, void* heap); + +WOLFSSL_LOCAL int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, + mp_int* priv, ecc_point* pub, void* heap); +WOLFSSL_LOCAL int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, + const mp_int* priv, const ecc_point* pub, byte* out, word32* outLen, + void* heap); WOLFSSL_LOCAL int sp_ecc_sign_521_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap);