diff --git a/configure.ac b/configure.ac index 6e1dce91c4..7315827a7b 100644 --- a/configure.ac +++ b/configure.ac @@ -1545,13 +1545,18 @@ then ENABLED_ECC="yes" fi -if test "$ENABLED_ECC" = "yes" +if test "$ENABLED_ECC" != "no" then AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" if test "$ENABLED_ECC_SHAMIR" = "yes" && test "$ENABLED_LOWRESOURCE" = "no" then AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR" fi + + if test "$ENABLED_ECC" = "nonblock" + then + AM_CFLAGS="$AM_CFLAGS -DWC_ECC_NONBLOCK" + fi fi @@ -3206,7 +3211,7 @@ then ENABLED_ENCRYPT_THEN_MAC=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC -DHAVE_ALPN -DHAVE_TRUSTED_CA" # Check the ECC supported curves prereq - AS_IF([test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_TLS13" = "xyes"], + AS_IF([test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_CURVE25519" = "xyes" || test "x$ENABLED_TLS13" = "xyes"], [ENABLED_SUPPORTED_CURVES=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi @@ -3762,7 +3767,7 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SNI -DHAVE_MAX_FRAGMENT -DHAVE_TRUNCATED_HMAC" # Check the ECC supported curves prereq - AS_IF([test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_CURVE25519" = "xyes"], + AS_IF([test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_CURVE25519" = "xyes"], [ENABLED_SUPPORTED_CURVES=yes AM_CFLAGS="$AM_CFLAGS -DHAVE_SUPPORTED_CURVES"]) fi @@ -3905,7 +3910,7 @@ then AC_MSG_ERROR([please enable psk if disabling asn.]) fi - if test "x$ENABLED_ECC" = "xyes" && test "x$ENABLED_ASN" = "xno" + if test "x$ENABLED_ECC" != "xno" && test "x$ENABLED_ASN" = "xno" then AC_MSG_ERROR([please disable ecc if disabling asn.]) fi @@ -4251,6 +4256,7 @@ ENABLED_SP_ECC=no ENABLED_SP_EC_256=no ENABLED_SP_EC_384=no ENABLED_SP_NO_MALLOC=no +ENABLED_SP_NONBLOCK=no for v in `echo $ENABLED_SP | tr "," " "` do case $v in @@ -4267,6 +4273,7 @@ do ENABLED_SP_EC_384=yes fi ;; + yes) ENABLED_SP_RSA=yes ENABLED_SP_DH=yes @@ -4279,6 +4286,7 @@ do ENABLED_SP_EC_384=yes fi ;; + no) ;; @@ -4312,7 +4320,6 @@ do ENABLED_SP_DH=yes ENABLED_SP_FF_2048=yes ;; - smallrsa2048) ENABLED_SP_SMALL=yes ENABLED_SP_RSA=yes @@ -4334,7 +4341,6 @@ do ENABLED_SP_DH=yes ENABLED_SP_FF_3072=yes ;; - smallrsa3072) ENABLED_SP_SMALL=yes ENABLED_SP_RSA=yes @@ -4351,19 +4357,16 @@ do ENABLED_SP_DH=yes ENABLED_SP_FF_4096=yes ;; - 4096 | +4096) ENABLED_SP_RSA=yes ENABLED_SP_DH=yes ENABLED_SP_FF_4096=yes ;; - smallrsa4096) ENABLED_SP_SMALL=yes ENABLED_SP_RSA=yes ENABLED_SP_FF_4096=yes ;; - rsa4096) ENABLED_SP_RSA=yes ENABLED_SP_FF_4096=yes @@ -4373,6 +4376,13 @@ do ENABLED_SP_NO_MALLOC=yes ;; + nonblock) + # Requires small and no malloc + ENABLED_SP_NONBLOCK=yes + ENABLED_SP_NO_MALLOC=yes + ENABLED_SP_SMALL=yes + ;; + *) AC_MSG_ERROR([Invalid choice of Single Precision length in bits [256, 2048, 3072]: $ENABLED_SP.]) break;; @@ -4404,7 +4414,7 @@ if test "$ENABLED_SP_RSA" = "yes" || test "$ENABLED_SP_DH" = "yes"; then AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_4096" fi fi -if test "$ENABLED_ECC" = "yes" && test "$ENABLED_SP_ECC" = "yes"; then +if test "$ENABLED_ECC" != "no" && test "$ENABLED_SP_ECC" = "yes"; then ENABLED_SP=yes AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_SP_ECC" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_HAVE_SP_ECC" @@ -4425,6 +4435,10 @@ if test "$ENABLED_SP_NO_MALLOC" = "yes"; then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NO_MALLOC" AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NO_MALLOC" fi +if test "$ENABLED_SP_NONBLOCK" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SP_NONBLOCK" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_SP_NONBLOCK" +fi AC_ARG_ENABLE([sp-asm], @@ -4908,7 +4922,7 @@ AS_CASE(["$CFLAGS $CPPFLAGS"],[*'WOLFSSL_TRUST_PEER_CERT'*],[ENABLED_TRUSTED_PEE # dertermine if we have key validation mechanism -if test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_RSA" = "xyes" +if test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_RSA" = "xyes" then if test "x$ENABLED_ASN" = "xyes" then @@ -5046,7 +5060,7 @@ then ENABLED_AESKEYWRAP="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP -DWOLFSSL_AES_DIRECT" fi - if test "x$ENABLED_X963KDF" = "xno" && test "$ENABLED_ECC" = "yes" + if test "x$ENABLED_X963KDF" = "xno" && test "$ENABLED_ECC" != "no" then ENABLED_X963KDF="yes" AM_CFLAGS="$AM_CFLAGS -DHAVE_X963_KDF" @@ -5218,7 +5232,7 @@ AM_CONDITIONAL([BUILD_BLAKE2],[test "x$ENABLED_BLAKE2" = "xyes" || test "x$ENABL AM_CONDITIONAL([BUILD_BLAKE2S],[test "x$ENABLED_BLAKE2S" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_SHA512],[test "x$ENABLED_SHA512" = "xyes" || test "x$ENABLED_SHA384" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_DSA],[test "x$ENABLED_DSA" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) -AM_CONDITIONAL([BUILD_ECC],[test "x$ENABLED_ECC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) +AM_CONDITIONAL([BUILD_ECC],[test "x$ENABLED_ECC" != "xno" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_ED25519],[test "x$ENABLED_ED25519" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_ED25519_SMALL],[test "x$ENABLED_ED25519_SMALL" = "xyes"]) AM_CONDITIONAL([BUILD_FEMATH], [test "x$ENABLED_FEMATH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index f3f21c258a..58d57fb562 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -48,7 +48,7 @@ Possible ECC enable options: * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves. default: off * Includes the curve "a" variable in calculation * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off - * ECC_CACHE_CURVE: Enables cache of curve info to improve perofrmance + * ECC_CACHE_CURVE: Enables cache of curve info to improve performance default: off * FP_ECC: ECC Fixed Point Cache default: off * USE_ECC_B_PARAM: Enable ECC curve B param default: off @@ -56,6 +56,10 @@ Possible ECC enable options: * WOLFSSL_ECC_CURVE_STATIC: default off (on for windows) For the ECC curve paramaters `ecc_set_type` use fixed array for hex string + * WC_ECC_NONBLOCK: Enable non-blocking support for sign/verify. + Requires SP with WOLFSSL_SP_NONBLOCK + * WC_ECC_NONBLOCK_ONLY Enable the non-blocking function only, no fall-back to + normal blocking API's */ /* @@ -4891,60 +4895,54 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #ifdef WOLFSSL_SP_MATH -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, key->heap); - #else - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif + if (key->idx == ECC_CUSTOM_IDX || + (ecc_sets[key->idx].id != ECC_SECP256R1 && + ecc_sets[key->idx].id != ECC_SECP384R1)) { + return WC_KEY_SIZE_E; } #endif -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL, key->heap); - #else - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif - } -#endif - return WC_KEY_SIZE_E; -#else -#ifdef WOLFSSL_HAVE_SP_ECC - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) - #endif - { -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP256R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, - key->heap); - #else - return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif - } -#endif -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP384R1) { - #ifndef WOLFSSL_ECDSA_SET_K - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, NULL, - key->heap); - #else - return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, key->sign_k, - key->heap); - #endif - } -#endif - } -#endif /* WOLFSSL_HAVE_SP_ECC */ +#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_HAVE_SP_ECC) + if (key->idx != ECC_CUSTOM_IDX + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + && key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC + #endif + ) { + #ifdef WOLFSSL_ECDSA_SET_K + mp_int* sign_k = key->sign_k; + #else + mp_int* sign_k = NULL; + #endif + #ifndef WOLFSSL_SP_NO_256 + if (ecc_sets[key->idx].id == ECC_SECP256R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_sign_256_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, &key->k, r, s, sign_k, key->heap); + } + #endif + #ifndef WC_ECC_NONBLOCK_ONLY + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, sign_k, key->heap); + #else + return NOT_COMPILED_IN; + #endif + } + #endif + #ifdef WOLFSSL_SP_384 + if (ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_sign_384_nb(&key->nb_ctx->sp_ctx, in, inlen, rng, &key->k, r, s, sign_k, key->heap); + } + #endif + #ifndef WC_ECC_NONBLOCK_ONLY + return sp_ecc_sign_384(in, inlen, rng, &key->k, r, s, sign_k, key->heap); + #else + return NOT_COMPILED_IN; + #endif + } + #endif + } +#endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ defined(WOLFSSL_ASYNC_CRYPT_TEST) @@ -4962,6 +4960,9 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #endif + +#ifndef WOLFSSL_SP_MATH + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) err = wc_ecc_alloc_mpint(key, &key->e); if (err != 0) { @@ -5288,7 +5289,7 @@ int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key) #endif /* WOLFSSL_ECDSA_SET_K */ #endif /* WOLFSSL_ATECC508A && WOLFSSL_CRYPTOCELL*/ -#endif /* HAVE_ECC_SIGN */ +#endif /* !HAVE_ECC_SIGN */ #ifdef WOLFSSL_CUSTOM_CURVES void wc_ecc_free_curve(const ecc_set_type* curve, void* heap) @@ -5992,44 +5993,57 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, key->pubkey.z, r, s, res, key->heap); } #endif + #if defined(WOLFSSL_SP_MATH) && !defined(FREESCALE_LTC_ECC) -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { - return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, - key->pubkey.z, r, s, res, key->heap); - } -#endif -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP384R1) { - return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, key->pubkey.y, - key->pubkey.z, r, s, res, key->heap); - } -#endif - return WC_KEY_SIZE_E; -#else -#if defined WOLFSSL_HAVE_SP_ECC && !defined(FREESCALE_LTC_ECC) - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) - if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) - #endif - { -#ifndef WOLFSSL_SP_NO_256 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP256R1) { - return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z,r, s, res, - key->heap); - } -#endif /* WOLFSSL_SP_NO_256 */ -#ifdef WOLFSSL_SP_384 - if (key->idx != ECC_CUSTOM_IDX && - ecc_sets[key->idx].id == ECC_SECP384R1) { - return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, - key->pubkey.y, key->pubkey.z,r, s, res, - key->heap); - } -#endif /* WOLFSSL_SP_384 */ + if (key->idx == ECC_CUSTOM_IDX || + (ecc_sets[key->idx].id != ECC_SECP256R1 && + ecc_sets[key->idx].id != ECC_SECP384R1)) { + return WC_KEY_SIZE_E; } -#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif + +#if (defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_HAVE_SP_ECC)) && !defined(FREESCALE_LTC_ECC) + if (key->idx != ECC_CUSTOM_IDX + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + && key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC + #endif + ) { + #ifndef WOLFSSL_SP_NO_256 + if (ecc_sets[key->idx].id == ECC_SECP256R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_verify_256_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + } + #endif + #ifndef WC_ECC_NONBLOCK_ONLY + return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + #else + return NOT_COMPILED_IN; + #endif + } + #endif + #ifdef WOLFSSL_SP_384 + if (ecc_sets[key->idx].id == ECC_SECP384R1) { + #ifdef WC_ECC_NONBLOCK + if (key->nb_ctx) { + return sp_ecc_verify_384_nb(&key->nb_ctx->sp_ctx, hash, hashlen, + key->pubkey.x, key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + } + #endif + #ifndef WC_ECC_NONBLOCK_ONLY + return sp_ecc_verify_384(hash, hashlen, key->pubkey.x, + key->pubkey.y, key->pubkey.z, r, s, res, key->heap); + #else + return NOT_COMPILED_IN; + #endif + } + #endif + } +#endif + +#if !defined(WOLFSSL_SP_MATH) || defined(FREESCALE_LTC_ECC) ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); @@ -6287,7 +6301,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, wc_ecc_curve_free(curve); FREE_CURVE_SPECS(); -#endif /* WOLFSSL_SP_MATH */ +#endif /* !WOLFSSL_SP_MATH || FREESCALE_LTC_ECC */ #endif /* WOLFSSL_ATECC508A */ (void)keySz; @@ -10816,4 +10830,18 @@ int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, } #endif /* HAVE_X963_KDF */ +#ifdef WC_ECC_NONBLOCK +/* Enable ECC support for non-blocking operations */ +int wc_ecc_set_nonblock(ecc_key *key, ecc_nb_ctx_t* ctx) +{ + if (key) { + if (ctx) { + XMEMSET(ctx, 0, sizeof(ecc_nb_ctx_t)); + } + key->nb_ctx = ctx; + } + return 0; +} +#endif /* WC_ECC_NONBLOCK */ + #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c index c0743d619a..2ba17cbd1d 100644 --- a/wolfcrypt/src/sp_arm32.c +++ b/wolfcrypt/src/sp_arm32.c @@ -31332,6 +31332,141 @@ static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_8_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_8_ctx; + +static int sp_256_proj_point_dbl_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_8_ctx* ctx = (sp_256_proj_point_dbl_8_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_8(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_8(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_8(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_8(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_8(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_8(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_8(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_8(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_8(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_8(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_8(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_8(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -31504,6 +31639,209 @@ static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_8_ctx { + int state; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_8_ctx; + +static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_8_ctx* ctx = (sp_256_proj_point_add_8_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->t3 = t + 4*8; + ctx->t4 = t + 6*8; + ctx->t5 = t + 8*8; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_8(ctx->t1, p256_mod, q->y); + sp_256_norm_8(ctx->t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<8; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_8(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_8(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_8(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_8(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_8(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_8(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_8(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_8(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_8(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_8(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -35706,6 +36044,46 @@ static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_8_ctx { + int state; + int i; +} sp_256_mont_inv_order_8_ctx; +static int sp_256_mont_inv_order_8_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_8_ctx* ctx = (sp_256_mont_inv_order_8_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 8); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 8U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -35821,6 +36199,165 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + }; + sp_digit e[2*8]; + sp_digit x[2*8]; + sp_digit k[2*8]; + sp_digit r[2*8]; + sp_digit tmp[3 * 2*8]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 8, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 8, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 8U); + sp_256_norm_8(ctx->r); + c = sp_256_cmp_8(ctx->r, p256_order); + sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_8(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_8(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_8(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_8(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_8(ctx->x); + carry = sp_256_add_8(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_8(ctx->s); + c = sp_256_cmp_8(ctx->s, p256_order); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_8(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -35992,6 +36529,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + sp_256_proj_point_add_8_ctx add_ctx; + }; + sp_digit u1[2*8]; + sp_digit u2[2*8]; + sp_digit s[2*8]; + sp_digit tmp[2*8 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->s, 8, sm); + sp_256_from_mp(ctx->p2.x, 8, pX); + sp_256_from_mp(ctx->p2.y, 8, pY); + sp_256_from_mp(ctx->p2.z, 8, pZ); + sp_256_mul_8(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_8(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_8(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_8(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_8(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_8_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_8(ctx->p1.z)) { + if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<8; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 8, r); + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 8, r); + carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -40102,6 +40802,141 @@ static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_12_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_12_ctx; + +static int sp_384_proj_point_dbl_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_12_ctx* ctx = (sp_384_proj_point_dbl_12_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_12(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_12(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_12(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_12(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_12(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_12(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_12(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_12(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_12(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_12(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_12(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_12(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -40177,6 +41012,209 @@ static int sp_384_cmp_equal_12(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_12_ctx { + int state; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_12_ctx; + +static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_12_ctx* ctx = (sp_384_proj_point_add_12_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->t3 = t + 4*12; + ctx->t4 = t + 6*12; + ctx->t5 = t + 8*12; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_12(ctx->t1, p384_mod, q->y); + sp_384_norm_12(ctx->t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<12; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_12(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_12(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_12(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_12(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_12(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_12(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_12(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_12(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_12(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_12(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -43458,6 +44496,46 @@ static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_12_ctx { + int state; + int i; +} sp_384_mont_inv_order_12_ctx; +static int sp_384_mont_inv_order_12_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_12_ctx* ctx = (sp_384_mont_inv_order_12_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 12); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 12U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -43544,6 +44622,165 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + }; + sp_digit e[2*12]; + sp_digit x[2*12]; + sp_digit k[2*12]; + sp_digit r[2*12]; + sp_digit tmp[3 * 2*12]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 12, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 12, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 12U); + sp_384_norm_12(ctx->r); + c = sp_384_cmp_12(ctx->r, p384_order); + sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_12(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_12(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_12(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_12(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_12(ctx->x); + carry = sp_384_add_12(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_12(ctx->s); + c = sp_384_cmp_12(ctx->s, p384_order); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_12(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -43715,6 +44952,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + sp_384_proj_point_add_12_ctx add_ctx; + }; + sp_digit u1[2*12]; + sp_digit u2[2*12]; + sp_digit s[2*12]; + sp_digit tmp[2*12 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->s, 12, sm); + sp_384_from_mp(ctx->p2.x, 12, pX); + sp_384_from_mp(ctx->p2.y, 12, pY); + sp_384_from_mp(ctx->p2.z, 12, pZ); + sp_384_mul_12(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_12(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_12(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_12(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_12(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_12_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_12(ctx->p1.z)) { + if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<12; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 12, r); + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 12, r); + carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_arm64.c b/wolfcrypt/src/sp_arm64.c index 3ea3c4ec10..378ffbf652 100644 --- a/wolfcrypt/src/sp_arm64.c +++ b/wolfcrypt/src/sp_arm64.c @@ -20053,6 +20053,141 @@ static void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_4_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_4_ctx; + +static int sp_256_proj_point_dbl_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_4_ctx* ctx = (sp_256_proj_point_dbl_4_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_4(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_4(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_4(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_4(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_4(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_4(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_4(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_4(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_4(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_4(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_4(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_4(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_4(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -20303,6 +20438,209 @@ static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_4_ctx { + int state; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_4_ctx; + +static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_4_ctx* ctx = (sp_256_proj_point_add_4_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->t3 = t + 4*4; + ctx->t4 = t + 6*4; + ctx->t5 = t + 8*4; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_4(ctx->t1, p256_mod, q->y); + sp_256_norm_4(ctx->t1); + if ((sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<4; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<4; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<4; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_4(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_4(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_4(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_4(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_4(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_4(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_4(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_4(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_4(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_4(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_4(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -35477,6 +35815,46 @@ static void sp_256_mont_sqr_n_order_4(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_4_ctx { + int state; + int i; +} sp_256_mont_inv_order_4_ctx; +static int sp_256_mont_inv_order_4_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_4_ctx* ctx = (sp_256_mont_inv_order_4_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 4); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_4(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_4(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 4U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -35592,6 +35970,165 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + }; + sp_digit e[2*4]; + sp_digit x[2*4]; + sp_digit k[2*4]; + sp_digit r[2*4]; + sp_digit tmp[3 * 2*4]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 4, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 4, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 4U); + sp_256_norm_4(ctx->r); + c = sp_256_cmp_4(ctx->r, p256_order); + sp_256_cond_sub_4(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_4(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_4(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_4(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_4(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_4(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_256_norm_4(ctx->x); + carry = sp_256_add_4(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_4(ctx->s); + c = sp_256_cmp_4(ctx->s, p256_order); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_4(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_4(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_4(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -35763,6 +36300,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + sp_256_proj_point_add_4_ctx add_ctx; + }; + sp_digit u1[2*4]; + sp_digit u2[2*4]; + sp_digit s[2*4]; + sp_digit tmp[2*4 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 4, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->s, 4, sm); + sp_256_from_mp(ctx->p2.x, 4, pX); + sp_256_from_mp(ctx->p2.y, 4, pY); + sp_256_from_mp(ctx->p2.z, 4, pZ); + sp_256_mul_4(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_4(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_4(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_4(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_4(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_4_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_4(ctx->p1.z)) { + if (sp_256_iszero_4(ctx->p1.x) && sp_256_iszero_4(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<4; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 4, r); + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 4, r); + carry = sp_256_add_4(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_4(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -38098,6 +38798,141 @@ static void sp_384_div2_6(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_6_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_6_ctx; + +static int sp_384_proj_point_dbl_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_6_ctx* ctx = (sp_384_proj_point_dbl_6_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_6(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_6(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_6(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_6(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_6(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_6(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_6(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_6(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_6(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_6(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_6(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_6(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_6(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -38260,6 +39095,209 @@ static int sp_384_cmp_equal_6(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_6_ctx { + int state; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_6_ctx; + +static int sp_384_proj_point_add_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_6_ctx* ctx = (sp_384_proj_point_add_6_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->t3 = t + 4*6; + ctx->t4 = t + 6*6; + ctx->t5 = t + 8*6; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_6(ctx->t1, p384_mod, q->y); + sp_384_norm_6(ctx->t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<6; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_6(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_6(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_6(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_6(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_6(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_6(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_6(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_6(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_6(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_6(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_6(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_6(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_6(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -41099,6 +42137,46 @@ static void sp_384_mont_sqr_n_order_6(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_6_ctx { + int state; + int i; +} sp_384_mont_inv_order_6_ctx; +static int sp_384_mont_inv_order_6_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_6_ctx* ctx = (sp_384_mont_inv_order_6_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 6); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_6(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_6(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 6U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -41185,6 +42263,165 @@ static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + }; + sp_digit e[2*6]; + sp_digit x[2*6]; + sp_digit k[2*6]; + sp_digit r[2*6]; + sp_digit tmp[3 * 2*6]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 6, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 6, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 6U); + sp_384_norm_6(ctx->r); + c = sp_384_cmp_6(ctx->r, p384_order); + sp_384_cond_sub_6(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_6(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_6(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_6(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_6(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_6(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_384_norm_6(ctx->x); + carry = sp_384_add_6(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_6(ctx->s); + c = sp_384_cmp_6(ctx->s, p384_order); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_6(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_6(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_6(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -41356,6 +42593,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + sp_384_proj_point_add_6_ctx add_ctx; + }; + sp_digit u1[2*6]; + sp_digit u2[2*6]; + sp_digit s[2*6]; + sp_digit tmp[2*6 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 6, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->s, 6, sm); + sp_384_from_mp(ctx->p2.x, 6, pX); + sp_384_from_mp(ctx->p2.y, 6, pY); + sp_384_from_mp(ctx->p2.z, 6, pZ); + sp_384_mul_6(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_6(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_6(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_6(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_6(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_6_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_6(ctx->p1.z)) { + if (sp_384_iszero_6(ctx->p1.x) && sp_384_iszero_6(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<6; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 6, r); + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_6(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 6, r); + carry = sp_384_add_6(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_armthumb.c b/wolfcrypt/src/sp_armthumb.c index b1c23b8d2f..0463607980 100644 --- a/wolfcrypt/src/sp_armthumb.c +++ b/wolfcrypt/src/sp_armthumb.c @@ -17060,6 +17060,141 @@ SP_NOINLINE static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_d * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_8_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_8_ctx; + +static int sp_256_proj_point_dbl_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_8_ctx* ctx = (sp_256_proj_point_dbl_8_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_8(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_8(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_8(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_8(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_8(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_8(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_8(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_8(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_8(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_8(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_8(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_8(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -17225,6 +17360,209 @@ static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_8_ctx { + int state; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_8_ctx; + +static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_8_ctx* ctx = (sp_256_proj_point_add_8_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->t3 = t + 4*8; + ctx->t4 = t + 6*8; + ctx->t5 = t + 8*8; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_8(ctx->t1, p256_mod, q->y); + sp_256_norm_8(ctx->t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<8; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_8(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_8(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_8(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_8(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_8(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_8(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_8(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_8(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_8(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_8(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -20479,6 +20817,46 @@ static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_8_ctx { + int state; + int i; +} sp_256_mont_inv_order_8_ctx; +static int sp_256_mont_inv_order_8_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_8_ctx* ctx = (sp_256_mont_inv_order_8_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 8); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 8U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -20594,6 +20972,165 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + }; + sp_digit e[2*8]; + sp_digit x[2*8]; + sp_digit k[2*8]; + sp_digit r[2*8]; + sp_digit tmp[3 * 2*8]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 8, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 8, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 8U); + sp_256_norm_8(ctx->r); + c = sp_256_cmp_8(ctx->r, p256_order); + sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_8(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_8(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_8(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_8(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_8(ctx->x); + carry = sp_256_add_8(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_8(ctx->s); + c = sp_256_cmp_8(ctx->s, p256_order); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_8(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -20765,6 +21302,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + sp_256_proj_point_add_8_ctx add_ctx; + }; + sp_digit u1[2*8]; + sp_digit u2[2*8]; + sp_digit s[2*8]; + sp_digit tmp[2*8 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->s, 8, sm); + sp_256_from_mp(ctx->p2.x, 8, pX); + sp_256_from_mp(ctx->p2.y, 8, pY); + sp_256_from_mp(ctx->p2.z, 8, pZ); + sp_256_mul_8(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_8(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_8(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_8(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_8(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_8_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_8(ctx->p1.z)) { + if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<8; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 8, r); + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 8, r); + carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -22937,6 +23637,141 @@ SP_NOINLINE static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_ * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_12_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_12_ctx; + +static int sp_384_proj_point_dbl_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_12_ctx* ctx = (sp_384_proj_point_dbl_12_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_12(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_12(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_12(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_12(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_12(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_12(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_12(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_12(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_12(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_12(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_12(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_12(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -23012,6 +23847,209 @@ static int sp_384_cmp_equal_12(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_12_ctx { + int state; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_12_ctx; + +static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_12_ctx* ctx = (sp_384_proj_point_add_12_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->t3 = t + 4*12; + ctx->t4 = t + 6*12; + ctx->t5 = t + 8*12; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_12(ctx->t1, p384_mod, q->y); + sp_384_norm_12(ctx->t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<12; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_12(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_12(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_12(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_12(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_12(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_12(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_12(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_12(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_12(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_12(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -26300,6 +27338,46 @@ static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_12_ctx { + int state; + int i; +} sp_384_mont_inv_order_12_ctx; +static int sp_384_mont_inv_order_12_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_12_ctx* ctx = (sp_384_mont_inv_order_12_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 12); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 12U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -26386,6 +27464,165 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + }; + sp_digit e[2*12]; + sp_digit x[2*12]; + sp_digit k[2*12]; + sp_digit r[2*12]; + sp_digit tmp[3 * 2*12]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 12, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 12, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 12U); + sp_384_norm_12(ctx->r); + c = sp_384_cmp_12(ctx->r, p384_order); + sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_12(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_12(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_12(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_12(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_12(ctx->x); + carry = sp_384_add_12(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_12(ctx->s); + c = sp_384_cmp_12(ctx->s, p384_order); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_12(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -26557,6 +27794,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + sp_384_proj_point_add_12_ctx add_ctx; + }; + sp_digit u1[2*12]; + sp_digit u2[2*12]; + sp_digit s[2*12]; + sp_digit tmp[2*12 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->s, 12, sm); + sp_384_from_mp(ctx->p2.x, 12, pX); + sp_384_from_mp(ctx->p2.y, 12, pY); + sp_384_from_mp(ctx->p2.z, 12, pZ); + sp_384_mul_12(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_12(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_12(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_12(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_12(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_12_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_12(ctx->p1.z)) { + if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<12; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 12, r); + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 12, r); + carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c index 3662ceae2e..714729f4fb 100644 --- a/wolfcrypt/src/sp_c32.c +++ b/wolfcrypt/src/sp_c32.c @@ -57,6 +57,10 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 }; #endif +#if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || !defined(WOLFSSL_SP_SMALL)) + #error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC) +#endif + #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) #ifndef WOLFSSL_SP_NO_2048 /* Read big endian unsigned byte array into r. @@ -13847,6 +13851,141 @@ static void sp_256_div2_10(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_10_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_10_ctx; + +static int sp_256_proj_point_dbl_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_10_ctx* ctx = (sp_256_proj_point_dbl_10_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*10; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_10(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_10(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_10(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_10(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_10(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_10(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_10(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_10(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_10(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_10(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_10(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_10(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_10(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_10(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_10(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -13922,6 +14061,209 @@ static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_10_ctx { + int state; + sp_256_proj_point_dbl_10_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_10_ctx; + +static int sp_256_proj_point_add_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_10_ctx* ctx = (sp_256_proj_point_add_10_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*10; + ctx->t3 = t + 4*10; + ctx->t4 = t + 6*10; + ctx->t5 = t + 8*10; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_10(ctx->t1, p256_mod, q->y); + sp_256_norm_10(ctx->t1); + if ((sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) & + (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_10_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<10; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<10; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<10; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_10(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_10(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_10(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_10(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_10(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_10(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_10(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_10(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_10(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_10(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_10(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_10(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_10(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_10(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_10(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_10(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_10(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_10(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_10(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_10(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_10(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -14020,6 +14362,118 @@ static void sp_256_proj_point_add_10(sp_point_256* r, const sp_point_256* p, con * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_ecc_mulmod_10_ctx { + int state; + union { + sp_256_proj_point_dbl_10_ctx dbl_ctx; + sp_256_proj_point_add_10_ctx add_ctx; + }; + sp_point_256 t[3]; + sp_digit tmp[2 * 10 * 5]; + sp_digit n; + int i; + int c; + int y; +} sp_256_ecc_mulmod_10_ctx; + +static int sp_256_ecc_mulmod_10_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_256_ecc_mulmod_10_ctx* ctx = (sp_256_ecc_mulmod_10_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_256) * 3); + ctx->i = 9; + ctx->c = 22; + ctx->n = k[ctx->i--] << (26 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_10(ctx->t[1].x, g->x, p256_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_256_mod_mul_norm_10(ctx->t[1].y, g->y, p256_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_256_mod_mul_norm_10(ctx->t[1].z, g->z, p256_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 26; + } + ctx->y = (ctx->n >> 25) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_256_proj_point_add_10_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_256)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_256_proj_point_dbl_10_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_256)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_256_map_10(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#endif /* WOLFSSL_SP_NONBLOCK */ + static int sp_256_ecc_mulmod_10(sp_point_256* r, const sp_point_256* g, const sp_digit* k, int map, void* heap) { @@ -16826,6 +17280,46 @@ static void sp_256_mont_sqr_n_order_10(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_10_ctx { + int state; + int i; +} sp_256_mont_inv_order_10_ctx; +static int sp_256_mont_inv_order_10_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_10_ctx* ctx = (sp_256_mont_inv_order_10_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_10_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 10); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_10(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_10(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 10U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -16941,6 +17435,165 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_10_ctx mulmod_ctx; + sp_256_mont_inv_order_10_ctx mont_inv_order_ctx; + }; + sp_digit e[2*10]; + sp_digit x[2*10]; + sp_digit k[2*10]; + sp_digit r[2*10]; + sp_digit tmp[3 * 2*10]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 10, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 10, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_10(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 10, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_10_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 10U); + sp_256_norm_10(ctx->r); + c = sp_256_cmp_10(ctx->r, p256_order); + sp_256_cond_sub_10(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_10(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_10(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_10(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_10(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_10_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_10(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_10(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_10(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_10(ctx->x); + carry = sp_256_add_10(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_10(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_10(ctx->s); + c = sp_256_cmp_10(ctx->s, p256_order); + sp_256_cond_sub_10(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_10(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_10(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_10(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_10(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 10U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 10U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -17112,6 +17765,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_10_ctx mulmod_ctx; + sp_256_mont_inv_order_10_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_10_ctx dbl_ctx; + sp_256_proj_point_add_10_ctx add_ctx; + }; + sp_digit u1[2*10]; + sp_digit u2[2*10]; + sp_digit s[2*10]; + sp_digit tmp[2*10 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 10, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 10, r); + sp_256_from_mp(ctx->s, 10, sm); + sp_256_from_mp(ctx->p2.x, 10, pX); + sp_256_from_mp(ctx->p2.y, 10, pY); + sp_256_from_mp(ctx->p2.z, 10, pZ); + sp_256_mul_10(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_10(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_10(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_10_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_10(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_10(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_10_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_10_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_10_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_10(ctx->p1.z)) { + if (sp_256_iszero_10(ctx->p1.x) && sp_256_iszero_10(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<10; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_10_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 10, r); + err = sp_256_mod_mul_norm_10(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_10(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_10(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_10(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 10, r); + carry = sp_256_add_10(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_10(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_10(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_10(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_10(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_10(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -19472,6 +20288,141 @@ static void sp_384_div2_15(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_15_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_15_ctx; + +static int sp_384_proj_point_dbl_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_15_ctx* ctx = (sp_384_proj_point_dbl_15_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*15; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_15(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_15(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_15(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_15(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_15(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_15(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_15(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_15(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_15(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_15(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_15(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_15(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_15(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_15(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -19548,6 +20499,209 @@ static int sp_384_cmp_equal_15(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_15_ctx { + int state; + sp_384_proj_point_dbl_15_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_15_ctx; + +static int sp_384_proj_point_add_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_15_ctx* ctx = (sp_384_proj_point_add_15_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*15; + ctx->t3 = t + 4*15; + ctx->t4 = t + 6*15; + ctx->t5 = t + 8*15; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_15(ctx->t1, p384_mod, q->y); + sp_384_norm_15(ctx->t1); + if ((sp_384_cmp_equal_15(p->x, q->x) & sp_384_cmp_equal_15(p->z, q->z) & + (sp_384_cmp_equal_15(p->y, q->y) | sp_384_cmp_equal_15(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<15; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<15; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<15; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_15(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_15(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_15(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_15(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_15(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_15(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_15(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_15(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_15(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_15(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_15(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_15(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_15(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_15(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_15(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_15(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_15(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -19646,6 +20800,118 @@ static void sp_384_proj_point_add_15(sp_point_384* r, const sp_point_384* p, con * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_ecc_mulmod_15_ctx { + int state; + union { + sp_384_proj_point_dbl_15_ctx dbl_ctx; + sp_384_proj_point_add_15_ctx add_ctx; + }; + sp_point_384 t[3]; + sp_digit tmp[2 * 15 * 6]; + sp_digit n; + int i; + int c; + int y; +} sp_384_ecc_mulmod_15_ctx; + +static int sp_384_ecc_mulmod_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_384_ecc_mulmod_15_ctx* ctx = (sp_384_ecc_mulmod_15_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_384) * 3); + ctx->i = 14; + ctx->c = 20; + ctx->n = k[ctx->i--] << (26 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_15(ctx->t[1].x, g->x, p384_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_384_mod_mul_norm_15(ctx->t[1].y, g->y, p384_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_384_mod_mul_norm_15(ctx->t[1].z, g->z, p384_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 26; + } + ctx->y = (ctx->n >> 25) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_384)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_384)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_384_map_15(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#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, void* heap) { @@ -22973,6 +24239,46 @@ static void sp_384_mont_sqr_n_order_15(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_15_ctx { + int state; + int i; +} sp_384_mont_inv_order_15_ctx; +static int sp_384_mont_inv_order_15_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_15_ctx* ctx = (sp_384_mont_inv_order_15_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 15); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_15(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_15(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 15U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -23059,6 +24365,165 @@ static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_15_ctx mulmod_ctx; + sp_384_mont_inv_order_15_ctx mont_inv_order_ctx; + }; + sp_digit e[2*15]; + sp_digit x[2*15]; + sp_digit k[2*15]; + sp_digit r[2*15]; + sp_digit tmp[3 * 2*15]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 15, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 15, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_15(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 15, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 15U); + sp_384_norm_15(ctx->r); + c = sp_384_cmp_15(ctx->r, p384_order); + sp_384_cond_sub_15(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_15(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_15(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_15(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_15(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_15(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_15(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_15(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_15(ctx->x); + carry = sp_384_add_15(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_15(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_15(ctx->s); + c = sp_384_cmp_15(ctx->s, p384_order); + sp_384_cond_sub_15(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_15(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_15(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_15(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_15(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 15U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 15U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -23230,6 +24695,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_15_ctx mulmod_ctx; + sp_384_mont_inv_order_15_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_15_ctx dbl_ctx; + sp_384_proj_point_add_15_ctx add_ctx; + }; + sp_digit u1[2*15]; + sp_digit u2[2*15]; + sp_digit s[2*15]; + sp_digit tmp[2*15 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 15, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 15, r); + sp_384_from_mp(ctx->s, 15, sm); + sp_384_from_mp(ctx->p2.x, 15, pX); + sp_384_from_mp(ctx->p2.y, 15, pY); + sp_384_from_mp(ctx->p2.z, 15, pZ); + sp_384_mul_15(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_15(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_15(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_15(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_15(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_15(ctx->p1.z)) { + if (sp_384_iszero_15(ctx->p1.x) && sp_384_iszero_15(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<15; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 15, r); + err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_15(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 15, r); + carry = sp_384_add_15(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_15(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_15(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c index 74e54f2268..4d4d3b645c 100644 --- a/wolfcrypt/src/sp_c64.c +++ b/wolfcrypt/src/sp_c64.c @@ -57,6 +57,10 @@ static const size_t addr_mask[2] = { 0, (size_t)-1 }; #endif +#if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || !defined(WOLFSSL_SP_SMALL)) + #error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC) +#endif + #if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) #ifndef WOLFSSL_SP_NO_2048 /* Read big endian unsigned byte array into r. @@ -13668,6 +13672,141 @@ static void sp_256_div2_5(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_5_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_5_ctx; + +static int sp_256_proj_point_dbl_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_5_ctx* ctx = (sp_256_proj_point_dbl_5_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*5; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_5(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_5(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_5(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_5(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_5(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_5(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_5(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_5(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_5(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_5(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_5(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_5(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_5(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_5(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_5(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -13742,6 +13881,209 @@ static int sp_256_cmp_equal_5(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_5_ctx { + int state; + sp_256_proj_point_dbl_5_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_5_ctx; + +static int sp_256_proj_point_add_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_5_ctx* ctx = (sp_256_proj_point_add_5_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*5; + ctx->t3 = t + 4*5; + ctx->t4 = t + 6*5; + ctx->t5 = t + 8*5; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_5(ctx->t1, p256_mod, q->y); + sp_256_norm_5(ctx->t1); + if ((sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) & + (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_5_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<5; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<5; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<5; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_5(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_5(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_5(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_5(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_5(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_5(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_5(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_5(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_5(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_5(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_5(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_5(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_5(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_5(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_5(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_5(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_5(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_5(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_5(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_5(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_5(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -13840,6 +14182,118 @@ static void sp_256_proj_point_add_5(sp_point_256* r, const sp_point_256* p, cons * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_ecc_mulmod_5_ctx { + int state; + union { + sp_256_proj_point_dbl_5_ctx dbl_ctx; + sp_256_proj_point_add_5_ctx add_ctx; + }; + sp_point_256 t[3]; + sp_digit tmp[2 * 5 * 5]; + sp_digit n; + int i; + int c; + int y; +} sp_256_ecc_mulmod_5_ctx; + +static int sp_256_ecc_mulmod_5_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_256_ecc_mulmod_5_ctx* ctx = (sp_256_ecc_mulmod_5_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_256) * 3); + ctx->i = 4; + ctx->c = 48; + ctx->n = k[ctx->i--] << (52 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_5(ctx->t[1].x, g->x, p256_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_256_mod_mul_norm_5(ctx->t[1].y, g->y, p256_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_256_mod_mul_norm_5(ctx->t[1].z, g->z, p256_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 52; + } + ctx->y = (ctx->n >> 51) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_256_proj_point_add_5_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_256)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_256_proj_point_dbl_5_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_256)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_256_map_5(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#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, void* heap) { @@ -16627,6 +17081,46 @@ static void sp_256_mont_sqr_n_order_5(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_5_ctx { + int state; + int i; +} sp_256_mont_inv_order_5_ctx; +static int sp_256_mont_inv_order_5_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_5_ctx* ctx = (sp_256_mont_inv_order_5_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_5_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 5); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_5(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_5(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 5U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -16742,6 +17236,165 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_5_ctx mulmod_ctx; + sp_256_mont_inv_order_5_ctx mont_inv_order_ctx; + }; + sp_digit e[2*5]; + sp_digit x[2*5]; + sp_digit k[2*5]; + sp_digit r[2*5]; + sp_digit tmp[3 * 2*5]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 5, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 5, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_5(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 5, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 5U); + sp_256_norm_5(ctx->r); + c = sp_256_cmp_5(ctx->r, p256_order); + sp_256_cond_sub_5(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_5(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_5(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_5(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_5(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_5_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_5(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_5(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_5(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_256_norm_5(ctx->x); + carry = sp_256_add_5(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_5(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_5(ctx->s); + c = sp_256_cmp_5(ctx->s, p256_order); + sp_256_cond_sub_5(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_5(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_5(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_5(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_5(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 5U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 5U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -16913,6 +17566,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_5_ctx mulmod_ctx; + sp_256_mont_inv_order_5_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_5_ctx dbl_ctx; + sp_256_proj_point_add_5_ctx add_ctx; + }; + sp_digit u1[2*5]; + sp_digit u2[2*5]; + sp_digit s[2*5]; + sp_digit tmp[2*5 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 5, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 5, r); + sp_256_from_mp(ctx->s, 5, sm); + sp_256_from_mp(ctx->p2.x, 5, pX); + sp_256_from_mp(ctx->p2.y, 5, pY); + sp_256_from_mp(ctx->p2.z, 5, pZ); + sp_256_mul_5(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_5(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_5(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_5_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_5(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_5(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_5_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_5_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_5(ctx->p1.z)) { + if (sp_256_iszero_5(ctx->p1.x) && sp_256_iszero_5(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<5; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_5_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 5, r); + err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_5(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_5(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 5, r); + carry = sp_256_add_5(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_5(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_5(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_5(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_5(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_5(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -18854,6 +19670,141 @@ static void sp_384_div2_7(sp_digit* r, const sp_digit* a, const sp_digit* m) * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_7_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_7_ctx; + +static int sp_384_proj_point_dbl_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_7_ctx* ctx = (sp_384_proj_point_dbl_7_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*7; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_7(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_7(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_7(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_7(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_7(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_7(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_7(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_7(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_7(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_7(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_7(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_7(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_7(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_7(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_7(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -18928,6 +19879,209 @@ static int sp_384_cmp_equal_7(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_7_ctx { + int state; + sp_384_proj_point_dbl_7_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_7_ctx; + +static int sp_384_proj_point_add_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_7_ctx* ctx = (sp_384_proj_point_add_7_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*7; + ctx->t3 = t + 4*7; + ctx->t4 = t + 6*7; + ctx->t5 = t + 8*7; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_7(ctx->t1, p384_mod, q->y); + sp_384_norm_7(ctx->t1); + if ((sp_384_cmp_equal_7(p->x, q->x) & sp_384_cmp_equal_7(p->z, q->z) & + (sp_384_cmp_equal_7(p->y, q->y) | sp_384_cmp_equal_7(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_7_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<7; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<7; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<7; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_7(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_7(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_7(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_7(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_7(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_7(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_7(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_7(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_7(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_7(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_7(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_7(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_7(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_7(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_7(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_7(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_7(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_7(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_7(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_7(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_7(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_7(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -19026,6 +20180,118 @@ static void sp_384_proj_point_add_7(sp_point_384* r, const sp_point_384* p, cons * heap Heap to use for allocation. * returns MEMORY_E when memory allocation fails and MP_OKAY on success. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_ecc_mulmod_7_ctx { + int state; + union { + sp_384_proj_point_dbl_7_ctx dbl_ctx; + sp_384_proj_point_add_7_ctx add_ctx; + }; + sp_point_384 t[3]; + sp_digit tmp[2 * 7 * 6]; + sp_digit n; + int i; + int c; + int y; +} sp_384_ecc_mulmod_7_ctx; + +static int sp_384_ecc_mulmod_7_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* g, const sp_digit* k, int map, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_384_ecc_mulmod_7_ctx* ctx = (sp_384_ecc_mulmod_7_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + XMEMSET(ctx->t, 0, sizeof(sp_point_384) * 3); + ctx->i = 6; + ctx->c = 54; + ctx->n = k[ctx->i--] << (55 - ctx->c); + + /* t[0] = {0, 0, 1} * norm */ + ctx->t[0].infinity = 1; + ctx->state = 1; + break; + case 1: /* T1X */ + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_384_mod_mul_norm_7(ctx->t[1].x, g->x, p384_mod); + ctx->state = 2; + break; + case 2: /* T1Y */ + err = sp_384_mod_mul_norm_7(ctx->t[1].y, g->y, p384_mod); + ctx->state = 3; + break; + case 3: /* T1Z */ + err = sp_384_mod_mul_norm_7(ctx->t[1].z, g->z, p384_mod); + ctx->state = 4; + break; + case 4: /* ADDPREP */ + if (ctx->c == 0) { + if (ctx->i == -1) { + ctx->state = 7; + break; + } + + ctx->n = k[ctx->i--]; + ctx->c = 55; + } + ctx->y = (ctx->n >> 54) & 1; + ctx->n <<= 1; + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 5; + break; + case 5: /* ADD */ + err = sp_384_proj_point_add_7_nb((sp_ecc_ctx_t*)&ctx->add_ctx, + &ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), + sizeof(sp_point_384)); + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 6; + } + break; + case 6: /* DBL */ + err = sp_384_proj_point_dbl_7_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2], + &ctx->t[2], ctx->tmp); + if (err == MP_OKAY) { + XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) + + ((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2], + sizeof(sp_point_384)); + ctx->state = 4; + ctx->c--; + } + break; + case 7: /* MAP */ + if (map != 0) { + sp_384_map_7(r, &ctx->t[0], ctx->tmp); + } + else { + XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384)); + } + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 7) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + ForceZero(ctx->tmp, sizeof(ctx->tmp)); + ForceZero(ctx->t, sizeof(ctx->t)); + } + + (void)heap; + + return err; +} + +#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, void* heap) { @@ -22344,6 +23610,46 @@ static void sp_384_mont_sqr_n_order_7(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_7_ctx { + int state; + int i; +} sp_384_mont_inv_order_7_ctx; +static int sp_384_mont_inv_order_7_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_7_ctx* ctx = (sp_384_mont_inv_order_7_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_7_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 7); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_7(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_7(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 7U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_7(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -22430,6 +23736,165 @@ static void sp_384_mont_inv_order_7(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_7_ctx mulmod_ctx; + sp_384_mont_inv_order_7_ctx mont_inv_order_ctx; + }; + sp_digit e[2*7]; + sp_digit x[2*7]; + sp_digit k[2*7]; + sp_digit r[2*7]; + sp_digit tmp[3 * 2*7]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 7, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 7, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_7(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 7, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 7U); + sp_384_norm_7(ctx->r); + c = sp_384_cmp_7(ctx->r, p384_order); + sp_384_cond_sub_7(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_7(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_7(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_7(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_7(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_7_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_7(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_7(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_7(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_384_norm_7(ctx->x); + carry = sp_384_add_7(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_7(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_7(ctx->s); + c = sp_384_cmp_7(ctx->s, p384_order); + sp_384_cond_sub_7(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_7(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_7(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_7(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_7(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 7U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 7U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -22601,6 +24066,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_7_ctx mulmod_ctx; + sp_384_mont_inv_order_7_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_7_ctx dbl_ctx; + sp_384_proj_point_add_7_ctx add_ctx; + }; + sp_digit u1[2*7]; + sp_digit u2[2*7]; + sp_digit s[2*7]; + sp_digit tmp[2*7 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 7, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 7, r); + sp_384_from_mp(ctx->s, 7, sm); + sp_384_from_mp(ctx->p2.x, 7, pX); + sp_384_from_mp(ctx->p2.y, 7, pY); + sp_384_from_mp(ctx->p2.z, 7, pZ); + sp_384_mul_7(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_7(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_7(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_7_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_7(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_7(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_7_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_7_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_7(ctx->p1.z)) { + if (sp_384_iszero_7(ctx->p1.x) && sp_384_iszero_7(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<7; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_7_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 7, r); + err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_7(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_7(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 7, r); + carry = sp_384_add_7(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_7(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_7(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_7(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_7(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_7(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_cortexm.c b/wolfcrypt/src/sp_cortexm.c index be01f9757c..5f54b56d66 100644 --- a/wolfcrypt/src/sp_cortexm.c +++ b/wolfcrypt/src/sp_cortexm.c @@ -15902,6 +15902,141 @@ SP_NOINLINE static void sp_256_div2_8(sp_digit* r, const sp_digit* a, const sp_d * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_8_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_8_ctx; + +static int sp_256_proj_point_dbl_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_8_ctx* ctx = (sp_256_proj_point_dbl_8_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_8(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_8(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_8(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_8(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_8(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_8(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_8(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_8(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_8(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_8(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_8(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_8(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_8(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -16067,6 +16202,209 @@ static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_8_ctx { + int state; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_8_ctx; + +static int sp_256_proj_point_add_8_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_8_ctx* ctx = (sp_256_proj_point_add_8_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*8; + ctx->t3 = t + 4*8; + ctx->t4 = t + 6*8; + ctx->t5 = t + 8*8; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_8(ctx->t1, p256_mod, q->y); + sp_256_norm_8(ctx->t1); + if ((sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<8; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<8; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<8; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_8(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_8(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_8(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_8(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_8(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_8(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_8(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_8(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_8(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_8(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_8(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_8(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_8(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_8(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_8(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -20047,6 +20385,46 @@ static void sp_256_mont_sqr_n_order_8(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_8_ctx { + int state; + int i; +} sp_256_mont_inv_order_8_ctx; +static int sp_256_mont_inv_order_8_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_8_ctx* ctx = (sp_256_mont_inv_order_8_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_8_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 8); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_8(t, t); + if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_256_mont_mul_order_8(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 8U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -20162,6 +20540,165 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + }; + sp_digit e[2*8]; + sp_digit x[2*8]; + sp_digit k[2*8]; + sp_digit r[2*8]; + sp_digit tmp[3 * 2*8]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 8, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 8, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_8(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 8, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 8U); + sp_256_norm_8(ctx->r); + c = sp_256_cmp_8(ctx->r, p256_order); + sp_256_cond_sub_8(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_8(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_8(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_8(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_8(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_8(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_256_norm_8(ctx->x); + carry = sp_256_add_8(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_8(ctx->s); + c = sp_256_cmp_8(ctx->s, p256_order); + sp_256_cond_sub_8(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_8(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_8(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_8(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 8U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 8U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -20333,6 +20870,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_8_ctx mulmod_ctx; + sp_256_mont_inv_order_8_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_8_ctx dbl_ctx; + sp_256_proj_point_add_8_ctx add_ctx; + }; + sp_digit u1[2*8]; + sp_digit u2[2*8]; + sp_digit s[2*8]; + sp_digit tmp[2*8 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 8, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 8, r); + sp_256_from_mp(ctx->s, 8, sm); + sp_256_from_mp(ctx->p2.x, 8, pX); + sp_256_from_mp(ctx->p2.y, 8, pY); + sp_256_from_mp(ctx->p2.z, 8, pZ); + sp_256_mul_8(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_8(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_8(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_8_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_8(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_8(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_8_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_8_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_8(ctx->p1.z)) { + if (sp_256_iszero_8(ctx->p1.x) && sp_256_iszero_8(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<8; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_8_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 8, r); + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 8, r); + carry = sp_256_add_8(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_8(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_8(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -22356,6 +23056,141 @@ SP_NOINLINE static void sp_384_div2_12(sp_digit* r, const sp_digit* a, const sp_ * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_12_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_12_ctx; + +static int sp_384_proj_point_dbl_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_12_ctx* ctx = (sp_384_proj_point_dbl_12_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_12(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_12(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_12(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_12(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_12(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_12(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_12(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_12(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_12(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_12(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_12(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_12(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_12(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_12(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -22431,6 +23266,209 @@ static int sp_384_cmp_equal_12(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_12_ctx { + int state; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_12_ctx; + +static int sp_384_proj_point_add_12_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_12_ctx* ctx = (sp_384_proj_point_add_12_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*12; + ctx->t3 = t + 4*12; + ctx->t4 = t + 6*12; + ctx->t5 = t + 8*12; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_12(ctx->t1, p384_mod, q->y); + sp_384_norm_12(ctx->t1); + if ((sp_384_cmp_equal_12(p->x, q->x) & sp_384_cmp_equal_12(p->z, q->z) & + (sp_384_cmp_equal_12(p->y, q->y) | sp_384_cmp_equal_12(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<12; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<12; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<12; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_12(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_12(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_12(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_12(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_12(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_12(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_12(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_12(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_12(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_12(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_12(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_12(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_12(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_12(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_12(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_12(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_12(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_12(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_12(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_12(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_12(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -25581,6 +26619,46 @@ static void sp_384_mont_sqr_n_order_12(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_12_ctx { + int state; + int i; +} sp_384_mont_inv_order_12_ctx; +static int sp_384_mont_inv_order_12_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_12_ctx* ctx = (sp_384_mont_inv_order_12_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_12_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 12); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_12(t, t); + if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) { + sp_384_mont_mul_order_12(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 12U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -25667,6 +26745,165 @@ static void sp_384_mont_inv_order_12(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + }; + sp_digit e[2*12]; + sp_digit x[2*12]; + sp_digit k[2*12]; + sp_digit r[2*12]; + sp_digit tmp[3 * 2*12]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 12, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 12, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_12(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 12, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int32_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 12U); + sp_384_norm_12(ctx->r); + c = sp_384_cmp_12(ctx->r, p384_order); + sp_384_cond_sub_12(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_12(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_12(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_12(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_12(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_12(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_12(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int32_t c; + sp_384_norm_12(ctx->x); + carry = sp_384_add_12(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_12(ctx->s); + c = sp_384_cmp_12(ctx->s, p384_order); + sp_384_cond_sub_12(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_12(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_12(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_12(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_12(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 12U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 12U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -25838,6 +27075,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_12_ctx mulmod_ctx; + sp_384_mont_inv_order_12_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_12_ctx dbl_ctx; + sp_384_proj_point_add_12_ctx add_ctx; + }; + sp_digit u1[2*12]; + sp_digit u2[2*12]; + sp_digit s[2*12]; + sp_digit tmp[2*12 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 12, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 12, r); + sp_384_from_mp(ctx->s, 12, sm); + sp_384_from_mp(ctx->p2.x, 12, pX); + sp_384_from_mp(ctx->p2.y, 12, pY); + sp_384_from_mp(ctx->p2.z, 12, pZ); + sp_384_mul_12(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_12(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_12(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_12_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_12(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_12(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_12_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_12_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_12(ctx->p1.z)) { + if (sp_384_iszero_12(ctx->p1.x) && sp_384_iszero_12(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<12; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_12_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 12, r); + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_12(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int32_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 12, r); + carry = sp_384_add_12(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_12(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_12(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_12(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_12(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_12(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index e21f4888fe..1f9c8cf88f 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -38,8 +38,10 @@ * WOLFSSL_HAVE_SP_RSA: Enable SP RSA support * WOLFSSL_HAVE_SP_DH: Enable SP DH support * WOLFSSL_HAVE_SP_ECC: Enable SP ECC support - * WOLFSSL_SP_MATH: Use only single precision math and algorithms it supports (no fastmath tfm.c or normal integer.c) - * WOLFSSL_SP_SMALL: Use smaller version of code and avoid large stack variables + * WOLFSSL_SP_MATH: Use only single precision math and algorithms + * it supports (no fastmath tfm.c or normal integer.c) + * WOLFSSL_SP_SMALL: Use smaller version of code and avoid large + * stack variables * WOLFSSL_SP_NO_MALLOC: Always use stack, no heap XMALLOC/XFREE allowed * WOLFSSL_SP_NO_2048: Disable RSA/DH 2048-bit support * WOLFSSL_SP_NO_3072: Disable RSA/DH 3072-bit support @@ -52,8 +54,12 @@ * WOLFSSL_SP_ARM32_ASM Enable Aarch32 assembly speedups * WOLFSSL_SP_ARM64_ASM Enable Aarch64 assembly speedups * WOLFSSL_SP_ARM_CORTEX_M_ASM Enable Cortex-M assembly speedups - * WOLFSSL_SP_ARM_THUMB_ASM Enable ARM Thumb assembly speedups (used with -mthumb) + * WOLFSSL_SP_ARM_THUMB_ASM Enable ARM Thumb assembly speedups + * (used with -mthumb) * SP_WORD_SIZE Force 32 or 64 bit mode + * WOLFSSL_SP_NONBLOCK Enables "non blocking" mode for SP math, which + * will return FP_WOULDBLOCK for long operations and function must be + * called again until complete. */ #ifdef WOLFSSL_SP_MATH diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c index 435aa22344..67eadecffb 100644 --- a/wolfcrypt/src/sp_x86_64.c +++ b/wolfcrypt/src/sp_x86_64.c @@ -6562,6 +6562,141 @@ extern void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m); * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_4_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_4_ctx; + +static int sp_256_proj_point_dbl_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_4_ctx* ctx = (sp_256_proj_point_dbl_4_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_4(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_4(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_4(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_4(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_4(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_4(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_4(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_4(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_4(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_4(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_4(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_4(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_4(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -6723,6 +6858,209 @@ static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_4_ctx { + int state; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_4_ctx; + +static int sp_256_proj_point_add_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_4_ctx* ctx = (sp_256_proj_point_add_4_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->t3 = t + 4*4; + ctx->t4 = t + 6*4; + ctx->t5 = t + 8*4; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_4(ctx->t1, p256_mod, q->y); + sp_256_norm_4(ctx->t1); + if ((sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<4; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<4; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<4; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_4(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_4(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_4(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_4(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_4(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_4(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_4(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_4(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_4(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_4(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_4(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_4(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_4(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_4(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_4(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -7286,6 +7624,141 @@ static void sp_256_map_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_dbl_avx2_4_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_dbl_avx2_4_ctx; + +static int sp_256_proj_point_dbl_avx2_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_dbl_avx2_4_ctx* ctx = (sp_256_proj_point_dbl_avx2_4_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_avx2_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_256_mont_sqr_avx2_4(ctx->t1, p->z, p256_mod, p256_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_256_mont_mul_avx2_4(ctx->z, p->y, p->z, p256_mod, p256_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_256_mont_dbl_avx2_4(ctx->z, ctx->z, p256_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_256_mont_sub_avx2_4(ctx->t2, p->x, ctx->t1, p256_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_256_mont_add_avx2_4(ctx->t1, p->x, ctx->t1, p256_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_256_mont_mul_avx2_4(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_256_mont_tpl_avx2_4(ctx->t1, ctx->t2, p256_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_256_mont_dbl_avx2_4(ctx->y, p->y, p256_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_256_mont_sqr_avx2_4(ctx->y, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_256_mont_sqr_avx2_4(ctx->t2, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_256_div2_avx2_4(ctx->t2, ctx->t2, p256_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_256_mont_mul_avx2_4(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_256_mont_sqr_avx2_4(ctx->x, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->y, p256_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_256_mont_mul_avx2_4(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->t2, p256_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_dbl_avx2_4(sp_point_256* r, const sp_point_256* p, sp_digit* t) { sp_digit* t1 = t; @@ -7435,6 +7908,209 @@ static void sp_256_proj_point_dbl_n_avx2_4(sp_point_256* p, int n, sp_digit* t) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_proj_point_add_avx2_4_ctx { + int state; + sp_256_proj_point_dbl_avx2_4_ctx dbl_ctx; + const sp_point_256* ap[2]; + sp_point_256* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_256_proj_point_add_avx2_4_ctx; + +static int sp_256_proj_point_add_avx2_4_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, + const sp_point_256* p, const sp_point_256* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_proj_point_add_avx2_4_ctx* ctx = (sp_256_proj_point_add_avx2_4_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_256* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_256_proj_point_add_avx2_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*4; + ctx->t3 = t + 4*4; + ctx->t4 = t + 6*4; + ctx->t5 = t + 8*4; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_256_sub_avx2_4(ctx->t1, p256_mod, q->y); + sp_256_norm_avx2_4(ctx->t1); + if ((sp_256_cmp_equal_avx2_4(p->x, q->x) & sp_256_cmp_equal_avx2_4(p->z, q->z) & + (sp_256_cmp_equal_avx2_4(p->y, q->y) | sp_256_cmp_equal_avx2_4(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_256_proj_point_dbl_avx2_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_256*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_256)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<4; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<4; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<4; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_avx2_4(ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 5; + break; + case 5: + sp_256_mont_mul_avx2_4(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod); + ctx->state = 6; + break; + case 6: + sp_256_mont_mul_avx2_4(ctx->t1, ctx->t1, ctx->x, p256_mod, p256_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 8; + break; + case 8: + sp_256_mont_mul_avx2_4(ctx->t4, ctx->t2, ctx->z, p256_mod, p256_mp_mod); + ctx->state = 9; + break; + case 9: + sp_256_mont_mul_avx2_4(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_avx2_4(ctx->t3, ctx->t3, ctx->y, p256_mod, p256_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_256_mont_sub_avx2_4(ctx->t2, ctx->t2, ctx->t1, p256_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_256_mont_sub_avx2_4(ctx->t4, ctx->t4, ctx->t3, p256_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_avx2_4(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod); + ctx->state = 15; + break; + case 15: + sp_256_mont_mul_avx2_4(ctx->z, ctx->z, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_avx2_4(ctx->x, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 17; + break; + case 17: + sp_256_mont_sqr_avx2_4(ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 18; + break; + case 18: + sp_256_mont_mul_avx2_4(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod); + ctx->state = 19; + break; + case 19: + sp_256_mont_mul_avx2_4(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod); + ctx->state = 20; + break; + case 20: + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->t5, p256_mod); + ctx->state = 21; + break; + case 21: + sp_256_mont_dbl_avx2_4(ctx->t1, ctx->y, p256_mod); + ctx->state = 22; + break; + case 22: + sp_256_mont_sub_avx2_4(ctx->x, ctx->x, ctx->t1, p256_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->x, p256_mod); + ctx->state = 24; + break; + case 24: + sp_256_mont_mul_avx2_4(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod); + ctx->state = 25; + break; + case 25: + sp_256_mont_mul_avx2_4(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod); + ctx->state = 26; + break; + case 26: + sp_256_mont_sub_avx2_4(ctx->y, ctx->y, ctx->t5, p256_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_proj_point_add_avx2_4(sp_point_256* r, const sp_point_256* p, const sp_point_256* q, sp_digit* t) { @@ -22626,6 +23302,46 @@ static void sp_256_mont_sqr_n_order_4(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_4_ctx { + int state; + int i; +} sp_256_mont_inv_order_4_ctx; +static int sp_256_mont_inv_order_4_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_4_ctx* ctx = (sp_256_mont_inv_order_4_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 4); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_4(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_4(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 4U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -22772,6 +23488,46 @@ static void sp_256_mont_sqr_n_order_avx2_4(sp_digit* r, const sp_digit* a, int n * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_256_mont_inv_order_avx2_4_ctx { + int state; + int i; +} sp_256_mont_inv_order_avx2_4_ctx; +static int sp_256_mont_inv_order_avx2_4_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_256_mont_inv_order_avx2_4_ctx* ctx = (sp_256_mont_inv_order_avx2_4_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_avx2_4_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 4); + ctx->i = 254; + ctx->state = 1; + break; + case 1: + sp_256_mont_sqr_order_avx2_4(t, t); + if ((p256_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_256_mont_mul_order_avx2_4(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 4U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_256_mont_inv_order_avx2_4(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -22888,6 +23644,165 @@ static void sp_256_mont_inv_order_avx2_4(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + }; + sp_digit e[2*4]; + sp_digit x[2*4]; + sp_digit k[2*4]; + sp_digit r[2*4]; + sp_digit tmp[3 * 2*4]; + sp_point_256 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_256_ctx; + +int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->e, 4, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_256_from_mp(ctx->x, 4, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_256_ecc_gen_k_4(rng, ctx->k); + } + else { + sp_256_from_mp(ctx->k, 4, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p256_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 4U); + sp_256_norm_4(ctx->r); + c = sp_256_cmp_4(ctx->r, p256_order); + sp_256_cond_sub_4(ctx->r, ctx->r, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_4(ctx->k, ctx->k, p256_norm_order); + err = sp_256_mod_4(ctx->k, ctx->k, p256_order); + if (err == MP_OKAY) { + sp_256_norm_4(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_256_norm_4(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_256_mul_4(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_256_mod_4(ctx->x, ctx->x, p256_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_256_norm_4(ctx->x); + carry = sp_256_add_4(ctx->s, ctx->e, ctx->x); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0 - carry); + sp_256_norm_4(ctx->s); + c = sp_256_cmp_4(ctx->s, p256_order); + sp_256_cond_sub_4(ctx->s, ctx->s, p256_order, 0L - (sp_digit)(c >= 0)); + sp_256_norm_4(ctx->s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_4(ctx->s, ctx->s, ctx->kInv); + sp_256_norm_4(ctx->s); + + /* Check that signature is usable. */ + if (sp_256_iszero_4(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_256_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_256_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 4U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 4U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -23087,6 +24002,169 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_256_ctx { + int state; + union { + sp_256_ecc_mulmod_4_ctx mulmod_ctx; + sp_256_mont_inv_order_4_ctx mont_inv_order_ctx; + sp_256_proj_point_dbl_4_ctx dbl_ctx; + sp_256_proj_point_add_4_ctx add_ctx; + }; + sp_digit u1[2*4]; + sp_digit u2[2*4]; + sp_digit s[2*4]; + sp_digit tmp[2*4 * 5]; + sp_point_256 p1; + sp_point_256 p2; +} sp_ecc_verify_256_ctx; + +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 32U) { + hashLen = 32U; + } + + sp_256_from_bin(ctx->u1, 4, hash, (int)hashLen); + sp_256_from_mp(ctx->u2, 4, r); + sp_256_from_mp(ctx->s, 4, sm); + sp_256_from_mp(ctx->p2.x, 4, pX); + sp_256_from_mp(ctx->p2.y, 4, pY); + sp_256_from_mp(ctx->p2.z, 4, pZ); + sp_256_mul_4(ctx->s, ctx->s, p256_norm_order); + err = sp_256_mod_4(ctx->s, ctx->s, p256_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_256_norm_4(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_256_mont_inv_order_4_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_256_mont_mul_order_4(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_256_mont_mul_order_4(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_256_ecc_mulmod_4_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_256_proj_point_add_4_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_256_iszero_4(ctx->p1.z)) { + if (sp_256_iszero_4(ctx->p1.x) && sp_256_iszero_4(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<4; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p256_norm_mod, sizeof(p256_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_256_proj_point_dbl_4_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(ctx->u2, 4, r); + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_256_from_mp(ctx->u2, 4, r); + carry = sp_256_add_4(ctx->u2, ctx->u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_256_norm_4(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(ctx->u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(ctx->u2, ctx->u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, + p256_mp_mod); + *res = (int)(sp_256_cmp_4(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { @@ -24596,6 +25674,141 @@ extern void sp_384_div2_6(sp_digit* r, const sp_digit* a, const sp_digit* m); * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_6_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_6_ctx; + +static int sp_384_proj_point_dbl_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_6_ctx* ctx = (sp_384_proj_point_dbl_6_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_6(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_6(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_6(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_6(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_6(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_6(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_6(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_6(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_6(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_6(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_6(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_6(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_6(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -24758,6 +25971,209 @@ static int sp_384_cmp_equal_6(const sp_digit* a, const sp_digit* b) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_6_ctx { + int state; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_6_ctx; + +static int sp_384_proj_point_add_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_6_ctx* ctx = (sp_384_proj_point_add_6_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->t3 = t + 4*6; + ctx->t4 = t + 6*6; + ctx->t5 = t + 8*6; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_6(ctx->t1, p384_mod, q->y); + sp_384_norm_6(ctx->t1); + if ((sp_384_cmp_equal_6(p->x, q->x) & sp_384_cmp_equal_6(p->z, q->z) & + (sp_384_cmp_equal_6(p->y, q->y) | sp_384_cmp_equal_6(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<6; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_6(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_6(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_6(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_6(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_6(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_6(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_6(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_6(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_6(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_6(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_6(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_6(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_6(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_6(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_6(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_6(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_6(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_6(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_6(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_6(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -25373,6 +26789,141 @@ static void sp_384_map_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* * p Point to double. * t Temporary ordinate data. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_dbl_avx2_6_ctx { + int state; + sp_digit* t1; + sp_digit* t2; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_dbl_avx2_6_ctx; + +static int sp_384_proj_point_dbl_avx2_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_dbl_avx2_6_ctx* ctx = (sp_384_proj_point_dbl_avx2_6_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_avx2_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->x = r->x; + ctx->y = r->y; + ctx->z = r->z; + + /* Put infinity into result. */ + if (r != p) { + r->infinity = p->infinity; + } + ctx->state = 1; + break; + case 1: + /* T1 = Z * Z */ + sp_384_mont_sqr_avx2_6(ctx->t1, p->z, p384_mod, p384_mp_mod); + ctx->state = 2; + break; + case 2: + /* Z = Y * Z */ + sp_384_mont_mul_avx2_6(ctx->z, p->y, p->z, p384_mod, p384_mp_mod); + ctx->state = 3; + break; + case 3: + /* Z = 2Z */ + sp_384_mont_dbl_avx2_6(ctx->z, ctx->z, p384_mod); + ctx->state = 4; + break; + case 4: + /* T2 = X - T1 */ + sp_384_mont_sub_avx2_6(ctx->t2, p->x, ctx->t1, p384_mod); + ctx->state = 5; + break; + case 5: + /* T1 = X + T1 */ + sp_384_mont_add_avx2_6(ctx->t1, p->x, ctx->t1, p384_mod); + ctx->state = 6; + break; + case 6: + /* T2 = T1 * T2 */ + sp_384_mont_mul_avx2_6(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* T1 = 3T2 */ + sp_384_mont_tpl_avx2_6(ctx->t1, ctx->t2, p384_mod); + ctx->state = 8; + break; + case 8: + /* Y = 2Y */ + sp_384_mont_dbl_avx2_6(ctx->y, p->y, p384_mod); + ctx->state = 9; + break; + case 9: + /* Y = Y * Y */ + sp_384_mont_sqr_avx2_6(ctx->y, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* T2 = Y * Y */ + sp_384_mont_sqr_avx2_6(ctx->t2, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* T2 = T2/2 */ + sp_384_div2_avx2_6(ctx->t2, ctx->t2, p384_mod); + ctx->state = 12; + break; + case 12: + /* Y = Y * X */ + sp_384_mont_mul_avx2_6(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: + /* X = T1 * T1 */ + sp_384_mont_sqr_avx2_6(ctx->x, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 14; + break; + case 14: + /* X = X - Y */ + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 15; + break; + case 15: + /* X = X - Y */ + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->y, p384_mod); + ctx->state = 16; + break; + case 16: + /* Y = Y - X */ + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 17; + break; + case 17: + /* Y = Y * T1 */ + sp_384_mont_mul_avx2_6(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + /* Y = Y - T2 */ + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->t2, p384_mod); + ctx->state = 19; + /* fall-through */ + case 19: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 19) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_dbl_avx2_6(sp_point_384* r, const sp_point_384* p, sp_digit* t) { sp_digit* t1 = t; @@ -25522,6 +27073,209 @@ static void sp_384_proj_point_dbl_n_avx2_6(sp_point_384* p, int n, sp_digit* t) * q Second point to add. * t Temporary ordinate data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_proj_point_add_avx2_6_ctx { + int state; + sp_384_proj_point_dbl_avx2_6_ctx dbl_ctx; + const sp_point_384* ap[2]; + sp_point_384* rp[2]; + sp_digit* t1; + sp_digit* t2; + sp_digit* t3; + sp_digit* t4; + sp_digit* t5; + sp_digit* x; + sp_digit* y; + sp_digit* z; +} sp_384_proj_point_add_avx2_6_ctx; + +static int sp_384_proj_point_add_avx2_6_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, + const sp_point_384* p, const sp_point_384* q, sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_proj_point_add_avx2_6_ctx* ctx = (sp_384_proj_point_add_avx2_6_ctx*)sp_ctx->data; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + const sp_point_384* a = p; + p = q; + q = a; + } + + typedef char ctx_size_test[sizeof(sp_384_proj_point_add_avx2_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + ctx->t1 = t; + ctx->t2 = t + 2*6; + ctx->t3 = t + 4*6; + ctx->t4 = t + 6*6; + ctx->t5 = t + 8*6; + + ctx->state = 1; + break; + case 1: + /* Check double */ + (void)sp_384_sub_avx2_6(ctx->t1, p384_mod, q->y); + sp_384_norm_avx2_6(ctx->t1); + if ((sp_384_cmp_equal_avx2_6(p->x, q->x) & sp_384_cmp_equal_avx2_6(p->z, q->z) & + (sp_384_cmp_equal_avx2_6(p->y, q->y) | sp_384_cmp_equal_avx2_6(p->y, ctx->t1))) != 0) + { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 2; + } + else { + ctx->state = 3; + } + break; + case 2: + err = sp_384_proj_point_dbl_avx2_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, r, p, t); + if (err == MP_OKAY) + ctx->state = 27; /* done */ + break; + case 3: + { + int i; + ctx->rp[0] = r; + + /*lint allow cast to different type of pointer*/ + ctx->rp[1] = (sp_point_384*)t; /*lint !e9087 !e740*/ + XMEMSET(ctx->rp[1], 0, sizeof(sp_point_384)); + ctx->x = ctx->rp[p->infinity | q->infinity]->x; + ctx->y = ctx->rp[p->infinity | q->infinity]->y; + ctx->z = ctx->rp[p->infinity | q->infinity]->z; + + ctx->ap[0] = p; + ctx->ap[1] = q; + for (i=0; i<6; i++) { + r->x[i] = ctx->ap[p->infinity]->x[i]; + } + for (i=0; i<6; i++) { + r->y[i] = ctx->ap[p->infinity]->y[i]; + } + for (i=0; i<6; i++) { + r->z[i] = ctx->ap[p->infinity]->z[i]; + } + r->infinity = ctx->ap[p->infinity]->infinity; + + ctx->state = 4; + break; + } + case 4: + /* U1 = X1*Z2^2 */ + sp_384_mont_sqr_avx2_6(ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 5; + break; + case 5: + sp_384_mont_mul_avx2_6(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod); + ctx->state = 6; + break; + case 6: + sp_384_mont_mul_avx2_6(ctx->t1, ctx->t1, ctx->x, p384_mod, p384_mp_mod); + ctx->state = 7; + break; + case 7: + /* U2 = X2*Z1^2 */ + sp_384_mont_sqr_avx2_6(ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 8; + break; + case 8: + sp_384_mont_mul_avx2_6(ctx->t4, ctx->t2, ctx->z, p384_mod, p384_mp_mod); + ctx->state = 9; + break; + case 9: + sp_384_mont_mul_avx2_6(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod); + ctx->state = 10; + break; + case 10: + /* S1 = Y1*Z2^3 */ + sp_384_mont_mul_avx2_6(ctx->t3, ctx->t3, ctx->y, p384_mod, p384_mp_mod); + ctx->state = 11; + break; + case 11: + /* S2 = Y2*Z1^3 */ + sp_384_mont_mul_avx2_6(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: + /* H = U2 - U1 */ + sp_384_mont_sub_avx2_6(ctx->t2, ctx->t2, ctx->t1, p384_mod); + ctx->state = 13; + break; + case 13: + /* R = S2 - S1 */ + sp_384_mont_sub_avx2_6(ctx->t4, ctx->t4, ctx->t3, p384_mod); + ctx->state = 14; + break; + case 14: + /* Z3 = H*Z1*Z2 */ + sp_384_mont_mul_avx2_6(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod); + ctx->state = 15; + break; + case 15: + sp_384_mont_mul_avx2_6(ctx->z, ctx->z, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 16; + break; + case 16: + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_384_mont_sqr_avx2_6(ctx->x, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 17; + break; + case 17: + sp_384_mont_sqr_avx2_6(ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 18; + break; + case 18: + sp_384_mont_mul_avx2_6(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod); + ctx->state = 19; + break; + case 19: + sp_384_mont_mul_avx2_6(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod); + ctx->state = 20; + break; + case 20: + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->t5, p384_mod); + ctx->state = 21; + break; + case 21: + sp_384_mont_dbl_avx2_6(ctx->t1, ctx->y, p384_mod); + ctx->state = 22; + break; + case 22: + sp_384_mont_sub_avx2_6(ctx->x, ctx->x, ctx->t1, p384_mod); + ctx->state = 23; + break; + case 23: + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->x, p384_mod); + ctx->state = 24; + break; + case 24: + sp_384_mont_mul_avx2_6(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod); + ctx->state = 25; + break; + case 25: + sp_384_mont_mul_avx2_6(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod); + ctx->state = 26; + break; + case 26: + sp_384_mont_sub_avx2_6(ctx->y, ctx->y, ctx->t5, p384_mod); + ctx->state = 27; + /* fall-through */ + case 27: + err = MP_OKAY; + break; + } + + if (err == MP_OKAY && ctx->state != 27) { + err = FP_WOULDBLOCK; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_proj_point_add_avx2_6(sp_point_384* r, const sp_point_384* p, const sp_point_384* q, sp_digit* t) { @@ -28483,6 +30237,46 @@ static void sp_384_mont_sqr_n_order_6(sp_digit* r, const sp_digit* a, int n) * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_6_ctx { + int state; + int i; +} sp_384_mont_inv_order_6_ctx; +static int sp_384_mont_inv_order_6_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_6_ctx* ctx = (sp_384_mont_inv_order_6_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 6); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_6(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_6(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 6U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_6(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -28596,6 +30390,46 @@ static void sp_384_mont_sqr_n_order_avx2_6(sp_digit* r, const sp_digit* a, int n * a Number to invert. * td Temporary data. */ + +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_384_mont_inv_order_avx2_6_ctx { + int state; + int i; +} sp_384_mont_inv_order_avx2_6_ctx; +static int sp_384_mont_inv_order_avx2_6_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a, + sp_digit* t) +{ + int err = FP_WOULDBLOCK; + sp_384_mont_inv_order_avx2_6_ctx* ctx = (sp_384_mont_inv_order_avx2_6_ctx*)sp_ctx; + + typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_avx2_6_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: + XMEMCPY(t, a, sizeof(sp_digit) * 6); + ctx->i = 382; + ctx->state = 1; + break; + case 1: + sp_384_mont_sqr_order_avx2_6(t, t); + if ((p384_order_minus_2[ctx->i / 64] & ((sp_int_digit)1 << (ctx->i % 64))) != 0) { + sp_384_mont_mul_order_avx2_6(t, t, a); + } + ctx->i--; + if (ctx->i == 0) { + ctx->state = 2; + } + break; + case 2: + XMEMCPY(r, t, sizeof(sp_digit) * 6U); + err = MP_OKAY; + break; + } + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + static void sp_384_mont_inv_order_avx2_6(sp_digit* r, const sp_digit* a, sp_digit* td) { @@ -28683,6 +30517,165 @@ static void sp_384_mont_inv_order_avx2_6(sp_digit* r, const sp_digit* a, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_sign_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + }; + sp_digit e[2*6]; + sp_digit x[2*6]; + sp_digit k[2*6]; + sp_digit r[2*6]; + sp_digit tmp[3 * 2*6]; + sp_point_384 point; + sp_digit* s; + sp_digit* kInv; + int i; +} sp_ecc_sign_384_ctx; + +int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, mp_int* km, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data; + + 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; + ctx->kInv = ctx->k; + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->e, 6, hash, (int)hashLen); + + ctx->i = SP_ECC_MAX_SIG_GEN; + ctx->state = 1; + break; + case 1: /* GEN */ + sp_384_from_mp(ctx->x, 6, priv); + /* New random point. */ + if (km == NULL || mp_iszero(km)) { + err = sp_384_ecc_gen_k_6(rng, ctx->k); + } + else { + sp_384_from_mp(ctx->k, 6, km); + mp_zero(km); + } + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 2; + break; + case 2: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, + &ctx->point, &p384_base, ctx->k, 1, heap); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* MODORDER */ + { + int64_t c; + /* r = point->x mod order */ + XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 6U); + sp_384_norm_6(ctx->r); + c = sp_384_cmp_6(ctx->r, p384_order); + sp_384_cond_sub_6(ctx->r, ctx->r, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->r); + ctx->state = 4; + break; + } + case 4: /* KMODORDER */ + /* Conv k to Montgomery form (mod order) */ + sp_384_mul_6(ctx->k, ctx->k, p384_norm_order); + err = sp_384_mod_6(ctx->k, ctx->k, p384_order); + if (err == MP_OKAY) { + sp_384_norm_6(ctx->k); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 5; + } + break; + case 5: /* KINV */ + /* kInv = 1/k mod order */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp); + if (err == MP_OKAY) { + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 6; + } + break; + case 6: /* KINVNORM */ + sp_384_norm_6(ctx->kInv); + ctx->state = 7; + break; + case 7: /* R */ + /* s = r * x + e */ + sp_384_mul_6(ctx->x, ctx->x, ctx->r); + ctx->state = 8; + break; + case 8: /* S1 */ + err = sp_384_mod_6(ctx->x, ctx->x, p384_order); + if (err == MP_OKAY) + ctx->state = 9; + break; + case 9: /* S2 */ + { + sp_digit carry; + int64_t c; + sp_384_norm_6(ctx->x); + carry = sp_384_add_6(ctx->s, ctx->e, ctx->x); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0 - carry); + sp_384_norm_6(ctx->s); + c = sp_384_cmp_6(ctx->s, p384_order); + sp_384_cond_sub_6(ctx->s, ctx->s, p384_order, 0L - (sp_digit)(c >= 0)); + sp_384_norm_6(ctx->s); + + /* s = s * k^-1 mod order */ + sp_384_mont_mul_order_6(ctx->s, ctx->s, ctx->kInv); + sp_384_norm_6(ctx->s); + + /* Check that signature is usable. */ + if (sp_384_iszero_6(ctx->s) == 0) { + ctx->state = 10; + break; + } + + /* not usable gen, try again */ + ctx->i--; + if (ctx->i == 0) { + err = RNG_FAILURE_E; + } + ctx->state = 1; + break; + } + case 10: /* RES */ + err = sp_384_to_mp(ctx->r, rm); + if (err == MP_OKAY) { + err = sp_384_to_mp(ctx->s, sm); + } + break; + } + + if (err == MP_OKAY && ctx->state != 10) { + err = FP_WOULDBLOCK; + } + if (err != FP_WOULDBLOCK) { + XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 6U); + XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 6U); + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap) { @@ -28882,6 +30875,169 @@ int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, * returns RNG failures, MEMORY_E when memory allocation fails and * MP_OKAY on success. */ +#ifdef WOLFSSL_SP_NONBLOCK +typedef struct sp_ecc_verify_384_ctx { + int state; + union { + sp_384_ecc_mulmod_6_ctx mulmod_ctx; + sp_384_mont_inv_order_6_ctx mont_inv_order_ctx; + sp_384_proj_point_dbl_6_ctx dbl_ctx; + sp_384_proj_point_add_6_ctx add_ctx; + }; + sp_digit u1[2*6]; + sp_digit u2[2*6]; + sp_digit s[2*6]; + sp_digit tmp[2*6 * 5]; + sp_point_384 p1; + sp_point_384 p2; +} sp_ecc_verify_384_ctx; + +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ + int err = FP_WOULDBLOCK; + sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data; + + typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1]; + (void)sizeof(ctx_size_test); + + switch (ctx->state) { + case 0: /* INIT */ + if (hashLen > 48U) { + hashLen = 48U; + } + + sp_384_from_bin(ctx->u1, 6, hash, (int)hashLen); + sp_384_from_mp(ctx->u2, 6, r); + sp_384_from_mp(ctx->s, 6, sm); + sp_384_from_mp(ctx->p2.x, 6, pX); + sp_384_from_mp(ctx->p2.y, 6, pY); + sp_384_from_mp(ctx->p2.z, 6, pZ); + sp_384_mul_6(ctx->s, ctx->s, p384_norm_order); + err = sp_384_mod_6(ctx->s, ctx->s, p384_order); + if (err == MP_OKAY) + ctx->state = 1; + break; + case 1: /* NORMS1 */ + sp_384_norm_6(ctx->s); + XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx)); + ctx->state = 2; + break; + case 2: /* NORMS2 */ + err = sp_384_mont_inv_order_6_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 3; + } + break; + case 3: /* NORMS3 */ + sp_384_mont_mul_order_6(ctx->u1, ctx->u1, ctx->s); + ctx->state = 4; + break; + case 4: /* NORMS4 */ + sp_384_mont_mul_order_6(ctx->u2, ctx->u2, ctx->s); + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 5; + break; + case 5: /* MULBASE */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx)); + ctx->state = 6; + } + break; + case 6: /* MULMOD */ + err = sp_384_ecc_mulmod_6_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, heap); + if (err == MP_OKAY) { + XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx)); + ctx->state = 7; + } + break; + case 7: /* ADD */ + err = sp_384_proj_point_add_6_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp); + if (err == MP_OKAY) + ctx->state = 8; + break; + case 8: /* DBLPREP */ + if (sp_384_iszero_6(ctx->p1.z)) { + if (sp_384_iszero_6(ctx->p1.x) && sp_384_iszero_6(ctx->p1.y)) { + XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx)); + ctx->state = 9; + break; + } + else { + /* Y ordinate is not used from here - don't set. */ + int i; + for (i=0; i<6; i++) { + ctx->p1.x[i] = 0; + } + XMEMCPY(ctx->p1.z, p384_norm_mod, sizeof(p384_norm_mod)); + } + } + ctx->state = 10; + break; + case 9: /* DBL */ + err = sp_384_proj_point_dbl_6_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->p1, + &ctx->p2, ctx->tmp); + if (err == MP_OKAY) { + ctx->state = 10; + } + break; + case 10: /* MONT */ + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_384_from_mp(ctx->u2, 6, r); + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) + ctx->state = 11; + break; + case 11: /* SQR */ + /* u1 = r.z'.z' mod prime */ + sp_384_mont_sqr_6(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 12; + break; + case 12: /* MUL */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod); + ctx->state = 13; + break; + case 13: /* RES */ + err = MP_OKAY; /* math okay, now check result */ + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + if (*res == 0) { + sp_digit carry; + int64_t c; + + /* Reload r and add order. */ + sp_384_from_mp(ctx->u2, 6, r); + carry = sp_384_add_6(ctx->u2, ctx->u2, p384_order); + /* Carry means result is greater than mod and is not valid. */ + if (carry == 0) { + sp_384_norm_6(ctx->u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_384_cmp_6(ctx->u2, p384_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_384_mod_mul_norm_6(ctx->u2, ctx->u2, p384_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_384_mont_mul_6(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, + p384_mp_mod); + *res = (int)(sp_384_cmp_6(ctx->p1.x, ctx->u1) == 0); + } + } + } + } + break; + } + + if (err == MP_OKAY && ctx->state != 13) { + err = FP_WOULDBLOCK; + } + + return err; +} +#endif /* WOLFSSL_SP_NONBLOCK */ + int sp_ecc_verify_384(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) { diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 3dc0f32532..930b96199e 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -58,6 +58,11 @@ #include #endif +#ifdef WOLFSSL_HAVE_SP_ECC + #include +#endif + + #ifdef __cplusplus extern "C" { #endif @@ -353,6 +358,19 @@ enum { #endif }; +/* ECC non-blocking */ +#ifdef WC_ECC_NONBLOCK + typedef struct ecc_nb_ctx { + #if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_NONBLOCK) + sp_ecc_ctx_t sp_ctx; + #else + /* build configuration not supported */ + #error ECC non-blocking only supports SP (--enable-sp=nonblock) + #endif + } ecc_nb_ctx_t; +#endif /* WC_ECC_NONBLOCK */ + + /* An ECC Key */ struct ecc_key { int type; /* Public or Private */ @@ -413,6 +431,9 @@ struct ecc_key { #ifdef WOLFSSL_DSP remote_handle64 handle; #endif +#ifdef WC_ECC_NONBLOCK + ecc_nb_ctx_t* nb_ctx; +#endif }; @@ -757,6 +778,10 @@ int sp_dsp_ecc_verify_256(remote_handle64 handle, const byte* hash, word32 hashL mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); #endif +#ifdef WC_ECC_NONBLOCK + WOLFSSL_API int wc_ecc_set_nonblock(ecc_key *key, ecc_nb_ctx_t* ctx); +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/sp.h b/wolfssl/wolfcrypt/sp.h index e468a06fa4..5e01b82a82 100644 --- a/wolfssl/wolfcrypt/sp.h +++ b/wolfssl/wolfcrypt/sp.h @@ -141,7 +141,18 @@ int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ, int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ); int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym); -#endif /*ifdef WOLFSSL_HAVE_SP_ECC */ +#ifdef WOLFSSL_SP_NONBLOCK +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); +int sp_ecc_verify_256_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, + mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +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); +int sp_ecc_verify_384_nb(sp_ecc_ctx_t* ctx, const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, + mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +#endif /* WOLFSSL_SP_NONBLOCK */ + +#endif /* WOLFSSL_HAVE_SP_ECC */ #ifdef __cplusplus diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index e3cc191bec..ef0ebbb0a3 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -109,6 +109,17 @@ #define SP_MASK (sp_digit)(-1) + +#if defined(WOLFSSL_HAVE_SP_ECC) && defined(WOLFSSL_SP_NONBLOCK) +typedef struct sp_ecc_ctx { + #ifdef WOLFSSL_SP_384 + byte data[48*80]; /* stack data */ + #else + byte data[32*80]; /* stack data */ + #endif +} sp_ecc_ctx_t; +#endif + #ifdef WOLFSSL_SP_MATH #include @@ -216,7 +227,6 @@ MP_API void sp_rshb(sp_int* a, int n, sp_int* r); MP_API int sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r); -#define MP_OKAY 0 #define MP_NO 0 #define MP_YES 1 @@ -226,8 +236,10 @@ MP_API int sp_mul_d(sp_int* a, sp_int_digit n, sp_int* r); #define MP_EQ 0 #define MP_LT -1 +#define MP_OKAY 0 #define MP_MEM -2 #define MP_VAL -3 +#define FP_WOULDBLOCK -4 #define DIGIT_BIT SP_WORD_SIZE #define MP_MASK SP_MASK