diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index af1cc5b05..a7623c946 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -1379,6 +1379,84 @@ static int wc_RsaFunctionXil(const byte* in, word32 inLen, byte* out, } #endif /* WOLFSSL_XILINX_CRYPT */ +#ifdef WC_RSA_NONBLOCK +static int wc_RsaFunctionNonBlock(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key) +{ + int ret = 0; + word32 keyLen, len; + + if (key == NULL || key->nb == NULL) { + return BAD_FUNC_ARG; + } + + if (key->nb->exptmod.state == TFM_EXPTMOD_NB_INIT) { + if (mp_init(&key->nb->tmp) != MP_OKAY) { + ret = MP_INIT_E; + } + + if (ret == 0) { + if (mp_read_unsigned_bin(&key->nb->tmp, (byte*)in, inLen) != MP_OKAY) { + ret = MP_READ_E; + } + } + } + + if (ret == 0) { + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->d, + &key->n, &key->nb->tmp); + if (ret == FP_WOULDBLOCK) + return ret; + if (ret != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->e, + &key->n, &key->nb->tmp); + if (ret == FP_WOULDBLOCK) + return ret; + if (ret != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + default: + ret = RSA_WRONG_TYPE_E; + break; + } + } + + if (ret == 0) { + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) + ret = RSA_BUFFER_E; + } + if (ret == 0) { + len = mp_unsigned_bin_size(&key->nb->tmp); + + /* pad front w/ zeros to match key length */ + while (len < keyLen) { + *out++ = 0x00; + len++; + } + + *outLen = keyLen; + + /* convert */ + if (mp_to_unsigned_bin(&key->nb->tmp, out) != MP_OKAY) { + ret = MP_TO_E; + } + } + + mp_clear(&key->nb->tmp); + + return ret; +} +#endif /* WC_RSA_NONBLOCK */ + static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { @@ -1800,7 +1878,11 @@ int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, } /* if async pending then skip cleanup*/ - if (ret == WC_PENDING_E) { + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { return ret; } @@ -1886,13 +1968,23 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng); } else +#endif +#ifdef WC_RSA_NONBLOCK + if (key->nb) { + ret = wc_RsaFunctionNonBlock(in, inLen, out, outLen, type, key); + } + else #endif { ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); } /* handle error */ - if (ret < 0 && ret != WC_PENDING_E) { + if (ret < 0 && ret != WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + && ret != FP_WOULDBLOCK + #endif + ) { if (ret == MP_EXPTMOD_E) { /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */ WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); @@ -1959,8 +2051,6 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, switch (key->state) { case RSA_STATE_NONE: case RSA_STATE_ENCRYPT_PAD: - key->state = RSA_STATE_ENCRYPT_PAD; - #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ defined(HAVE_CAVIUM) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && @@ -1981,6 +2071,7 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, } #endif + key->state = RSA_STATE_ENCRYPT_PAD; ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, pad_type, hash, mgf, label, labelSz, saltLen, mp_count_bits(&key->n), key->heap); @@ -1989,7 +2080,6 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, } key->state = RSA_STATE_ENCRYPT_EXPTMOD; - FALL_THROUGH; case RSA_STATE_ENCRYPT_EXPTMOD: @@ -2016,7 +2106,11 @@ static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, } /* if async pending then return and skip done cleanup below */ - if (ret == WC_PENDING_E) { + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { return ret; } @@ -2059,8 +2153,6 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, switch (key->state) { case RSA_STATE_NONE: - case RSA_STATE_DECRYPT_EXPTMOD: - key->state = RSA_STATE_DECRYPT_EXPTMOD; key->dataLen = inLen; #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ @@ -2103,8 +2195,13 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, else { key->data = out; } - ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, rsa_type, - key, rng); + + key->state = RSA_STATE_DECRYPT_EXPTMOD; + FALL_THROUGH; + + case RSA_STATE_DECRYPT_EXPTMOD: + ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, + rsa_type, key, rng); if (ret >= 0 || ret == WC_PENDING_E) { key->state = RSA_STATE_DECRYPT_UNPAD; @@ -2162,7 +2259,11 @@ static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, } /* if async pending then return and skip done cleanup below */ - if (ret == WC_PENDING_E) { + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { return ret; } @@ -3158,7 +3259,6 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) #ifdef WC_RSA_BLINDING - int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) { if (key == NULL) @@ -3168,8 +3268,23 @@ int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) return 0; } - #endif /* WC_RSA_BLINDING */ +#ifdef WC_RSA_NONBLOCK +int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + if (nb) { + XMEMSET(nb, 0, sizeof(RsaNb)); + } + + /* Allow nb == NULL to clear non-block mode */ + key->nb = nb; + + return 0; +} +#endif /* WC_RSA_NONBLOCK */ #endif /* NO_RSA */ diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c index 6d8ef5224..7c9013b1a 100644 --- a/wolfcrypt/src/signature.c +++ b/wolfcrypt/src/signature.c @@ -49,35 +49,23 @@ #ifndef NO_SIG_WRAPPER #if !defined(NO_RSA) && !defined(NO_ASN) -static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte** hash_data, - word32* hash_len) +static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte* hash_data, + word32 hash_len, word32* hash_enc_len) { - int ret = wc_HashGetOID(hash_type); - if (ret > 0) { - int oid = ret; + int ret, oid; - /* Allocate buffer for hash and max DER encoded */ - word32 digest_len = *hash_len + MAX_DER_DIGEST_SZ; - byte *digest_buf = (byte*)XMALLOC(digest_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digest_buf) { - ret = wc_EncodeSignature(digest_buf, *hash_data, *hash_len, oid); - if (ret > 0) { - digest_len = ret; - ret = 0; - - /* Replace hash with digest (DER encoding + hash) */ - XFREE(*hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); - *hash_data = digest_buf; - *hash_len = digest_len; - } - else { - XFREE(digest_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } - } - else { - ret = MEMORY_E; - } + ret = wc_HashGetOID(hash_type); + if (ret < 0) { + return ret; } + oid = ret; + + ret = wc_EncodeSignature(hash_data, hash_data, hash_len, oid); + if (ret > 0) { + *hash_enc_len = ret; + ret = 0; + } + return ret; } #endif /* !NO_RSA && !NO_ASN */ @@ -244,8 +232,12 @@ int wc_SignatureVerify( const void* key, word32 key_len) { int ret; - word32 hash_len; - byte *hash_data = NULL; + word32 hash_len, hash_enc_len; +#ifdef WOLFSSL_SMALL_STACK + byte *hash_data; +#else + byte hash_data[MAX_DER_DIGEST_SZ]; +#endif /* Check arguments */ if (data == NULL || data_len <= 0 || @@ -266,13 +258,22 @@ int wc_SignatureVerify( WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); return ret; } - hash_len = ret; + hash_enc_len = hash_len = ret; +#ifndef NO_RSA + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + /* For RSA with ASN.1 encoding include room */ + hash_enc_len += MAX_DER_DIGEST_ASN_SZ; + } +#endif + +#ifdef WOLFSSL_SMALL_STACK /* Allocate temporary buffer for hash data */ - hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + hash_data = (byte*)XMALLOC(hash_enc_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (hash_data == NULL) { return MEMORY_E; } +#endif /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); @@ -282,20 +283,21 @@ int wc_SignatureVerify( #if defined(NO_RSA) || defined(NO_ASN) ret = SIG_TYPE_E; #else - ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len); + ret = wc_SignatureDerEncode(hash_type, hash_data, hash_len, + &hash_enc_len); #endif } if (ret == 0) { /* Verify signature using hash */ ret = wc_SignatureVerifyHash(hash_type, sig_type, - hash_data, hash_len, sig, sig_len, key, key_len); + hash_data, hash_enc_len, sig, sig_len, key, key_len); } } - if (hash_data) { - XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif return ret; } @@ -390,8 +392,12 @@ int wc_SignatureGenerate( const void* key, word32 key_len, WC_RNG* rng) { int ret; - word32 hash_len; - byte *hash_data = NULL; + word32 hash_len, hash_enc_len; +#ifdef WOLFSSL_SMALL_STACK + byte *hash_data; +#else + byte hash_data[MAX_DER_DIGEST_SZ]; +#endif /* Check arguments */ if (data == NULL || data_len <= 0 || @@ -412,13 +418,22 @@ int wc_SignatureGenerate( WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); return ret; } - hash_len = ret; + hash_enc_len = hash_len = ret; +#ifndef NO_RSA + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + /* For RSA with ASN.1 encoding include room */ + hash_enc_len += MAX_DER_DIGEST_ASN_SZ; + } +#endif + +#ifdef WOLFSSL_SMALL_STACK /* Allocate temporary buffer for hash data */ - hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + hash_data = (byte*)XMALLOC(hash_enc_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (hash_data == NULL) { return MEMORY_E; } +#endif /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); @@ -428,20 +443,21 @@ int wc_SignatureGenerate( #if defined(NO_RSA) || defined(NO_ASN) ret = SIG_TYPE_E; #else - ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len); + ret = wc_SignatureDerEncode(hash_type, hash_data, hash_len, + &hash_enc_len); #endif } if (ret == 0) { /* Generate signature using hash */ ret = wc_SignatureGenerateHash(hash_type, sig_type, - hash_data, hash_len, sig, sig_len, key, key_len, rng); + hash_data, hash_enc_len, sig, sig_len, key, key_len, rng); } } - if (hash_data) { - XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif return ret; } diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index b55daca11..716fbc92b 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -1194,6 +1194,159 @@ int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) #ifdef TFM_TIMING_RESISTANT +#ifdef WC_RSA_NONBLOCK + +/* non-blocking version of timing resistant fp_exptmod function */ +/* supports cache resistance */ +int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y) +{ + int err; + + if (nb == NULL) + return FP_VAL; + + switch (nb->state) { + case TFM_EXPTMOD_NB_INIT: + /* now setup montgomery */ + if ((err = fp_montgomery_setup(P, &nb->mp)) != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + /* init ints */ + fp_init(&nb->R[0]); + fp_init(&nb->R[1]); + #ifndef WC_NO_CACHE_RESISTANT + fp_init(&nb->R[2]); + #endif + nb->state = TFM_EXPTMOD_NB_MONT; + break; + + case TFM_EXPTMOD_NB_MONT: + /* mod m -> R[0] */ + fp_montgomery_calc_normalization (&nb->R[0], P); + + nb->state = TFM_EXPTMOD_NB_MONT_RED; + break; + + case TFM_EXPTMOD_NB_MONT_RED: + /* reduce G -> R[1] */ + if (fp_cmp_mag(P, G) != FP_GT) { + /* G > P so we reduce it first */ + fp_mod(G, P, &nb->R[1]); + } else { + fp_copy(G, &nb->R[1]); + } + + nb->state = TFM_EXPTMOD_NB_MONT_MUL; + break; + + case TFM_EXPTMOD_NB_MONT_MUL: + /* G (R[1]) * m (R[0]) */ + err = fp_mul(&nb->R[1], &nb->R[0], &nb->R[1]); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + nb->state = TFM_EXPTMOD_NB_MONT_MOD; + break; + + case TFM_EXPTMOD_NB_MONT_MOD: + /* mod m */ + err = fp_div(&nb->R[1], P, NULL, &nb->R[1]); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + nb->state = TFM_EXPTMOD_NB_MONT_MODCHK; + break; + + case TFM_EXPTMOD_NB_MONT_MODCHK: + /* m matches sign of (G * R mod m) */ + if (nb->R[1].sign != P->sign) { + fp_add(&nb->R[1], P, &nb->R[1]); + } + + /* set initial mode and bit cnt */ + nb->bitcnt = 1; + nb->buf = 0; + nb->digidx = X->used - 1; + + nb->state = TFM_EXPTMOD_NB_NEXT; + break; + + case TFM_EXPTMOD_NB_NEXT: + /* grab next digit as required */ + if (--nb->bitcnt == 0) { + /* if nb->digidx == -1 we are out of digits so break */ + if (nb->digidx == -1) { + nb->state = TFM_EXPTMOD_NB_RED; + break; + } + /* read next digit and reset nb->bitcnt */ + nb->buf = X->dp[nb->digidx--]; + nb->bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + nb->y = (int)(nb->buf >> (DIGIT_BIT - 1)) & 1; + nb->buf <<= (fp_digit)1; + nb->state = TFM_EXPTMOD_NB_MUL; + FALL_THROUGH; + + case TFM_EXPTMOD_NB_MUL: + fp_mul(&nb->R[0], &nb->R[1], &nb->R[nb->y^1]); + nb->state = TFM_EXPTMOD_NB_MUL_RED; + break; + + case TFM_EXPTMOD_NB_MUL_RED: + fp_montgomery_reduce(&nb->R[nb->y^1], P, nb->mp); + nb->state = TFM_EXPTMOD_NB_SQR; + break; + + case TFM_EXPTMOD_NB_SQR: + #ifdef WC_NO_CACHE_RESISTANT + fp_sqr(&nb->R[nb->y], &nb->R[nb->y]); + #else + fp_copy((fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) + + ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ), + &nb->R[2]); + fp_sqr(&nb->R[2], &nb->R[2]); + #endif /* WC_NO_CACHE_RESISTANT */ + + nb->state = TFM_EXPTMOD_NB_SQR_RED; + break; + + case TFM_EXPTMOD_NB_SQR_RED: + #ifdef WC_NO_CACHE_RESISTANT + fp_montgomery_reduce(&nb->R[nb->y], P, nb->mp); + #else + fp_montgomery_reduce(&nb->R[2], P, nb->mp); + fp_copy(&nb->R[2], + (fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) + + ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ) ); + #endif /* WC_NO_CACHE_RESISTANT */ + + nb->state = TFM_EXPTMOD_NB_NEXT; + break; + + case TFM_EXPTMOD_NB_RED: + /* final reduce */ + fp_montgomery_reduce(&nb->R[0], P, nb->mp); + fp_copy(&nb->R[0], Y); + + nb->state = TFM_EXPTMOD_NB_INIT; + return FP_OKAY; + } /* switch */ + + return FP_WOULDBLOCK; +} + +#endif /* WC_RSA_NONBLOCK */ + + /* timing resistant montgomery ladder based exptmod Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", Cryptographic Hardware and Embedded Systems, CHES 2002 diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index f87edd323..879e6e848 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -9260,6 +9260,86 @@ static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng) } #endif /* !NO_SIG_WRAPPER */ +#ifdef WC_RSA_NONBLOCK +static int rsa_nb_test(RsaKey* key, const byte* in, word32 inLen, byte* out, + word32 outSz, byte* plain, word32 plainSz, WC_RNG* rng) +{ + int ret = 0, count; + int signSz = 0; + RsaNb nb; + byte* inlinePlain = NULL; + + /* Enable non-blocking RSA mode - provide context */ + ret = wc_RsaSetNonBlock(key, &nb); + if (ret != 0) + return ret; + + count = 0; + do { + ret = wc_RsaSSL_Sign(in, inLen, out, outSz, key, rng); + count++; /* track number of would blocks */ + if (ret == FP_WOULDBLOCK) { + /* do "other" work here */ + } + } while (ret == FP_WOULDBLOCK); + if (ret < 0) { + return ret; + } +#ifdef DEBUG_WOLFSSL + printf("RSA non-block sign: %d times\n", count); +#endif + signSz = ret; + + /* Test non-blocking verify */ + XMEMSET(plain, 0, plainSz); + count = 0; + do { + ret = wc_RsaSSL_Verify(out, (word32)signSz, plain, plainSz, key); + count++; /* track number of would blocks */ + if (ret == FP_WOULDBLOCK) { + /* do "other" work here */ + } + } while (ret == FP_WOULDBLOCK); + if (ret < 0) { + return ret; + } +#ifdef DEBUG_WOLFSSL + printf("RSA non-block verify: %d times\n", count); +#endif + + if (signSz == ret && XMEMCMP(plain, in, (size_t)ret)) { + return SIG_VERIFY_E; + } + + /* Test inline non-blocking verify */ + count = 0; + do { + ret = wc_RsaSSL_VerifyInline(out, (word32)signSz, &inlinePlain, key); + count++; /* track number of would blocks */ + if (ret == FP_WOULDBLOCK) { + /* do "other" work here */ + } + } while (ret == FP_WOULDBLOCK); + if (ret < 0) { + return ret; + } +#ifdef DEBUG_WOLFSSL + printf("RSA non-block inline verify: %d times\n", count); +#endif + + if (signSz == ret && XMEMCMP(inlinePlain, in, (size_t)ret)) { + return SIG_VERIFY_E; + } + + /* Disabling non-block RSA mode */ + ret = wc_RsaSetNonBlock(key, NULL); + + (void)count; + + return 0; +} +#endif + #ifndef HAVE_USER_RSA static int rsa_decode_test(RsaKey* keyPub) { @@ -10672,6 +10752,12 @@ int rsa_test(void) goto exit_rsa; #endif +#ifdef WC_RSA_NONBLOCK + ret = rsa_nb_test(&key, in, inLen, out, outSz, plain, plainSz, &rng); + if (ret != 0) + goto exit_rsa; +#endif + do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -11445,7 +11531,7 @@ exit_rsa: } } -#endif +#endif /* !NO_RSA */ #ifndef NO_DH diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 31ff20069..382698d75 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -250,7 +250,8 @@ enum Misc_ASN { MAX_EXP_SZ = 5, /* enum(contextspec|con|exp) + length(4) */ MAX_PRSTR_SZ = 5, /* enum(prstr) + length(4) */ MAX_VERSION_SZ = 5, /* enum + id + version(byte) + (header(2))*/ - MAX_ENCODED_DIG_SZ = 73, /* sha512 + enum(bit or octet) + length(4) */ + MAX_ENCODED_DIG_ASN_SZ= 9, /* enum(bit or octet) + length(4) */ + MAX_ENCODED_DIG_SZ = 64 + MAX_ENCODED_DIG_ASN_SZ, /* asn header + sha512 */ MAX_RSA_INT_SZ = 517, /* RSA raw sz 4096 for bits + tag + len(4) */ MAX_NTRU_KEY_SZ = 610, /* NTRU 112 bit public key */ MAX_NTRU_ENC_SZ = 628, /* NTRU 112 bit DER public encoding */ @@ -258,7 +259,10 @@ enum Misc_ASN { MAX_RSA_E_SZ = 16, /* Max RSA public e size */ MAX_CA_SZ = 32, /* Max encoded CA basic constraint length */ MAX_SN_SZ = 35, /* Max encoded serial number (INT) length */ - MAX_DER_DIGEST_SZ = MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, /* Maximum DER digest size */ + MAX_DER_DIGEST_SZ = MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, + /* Maximum DER digest size */ + MAX_DER_DIGEST_ASN_SZ = MAX_ENCODED_DIG_ASN_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, + /* Maximum DER digest ASN header size */ #ifdef WOLFSSL_CERT_GEN #ifdef WOLFSSL_CERT_REQ /* Max encoded cert req attributes length */ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index b85e6d1e6..ae3af7ec2 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -37,6 +37,17 @@ #define WC_RSA_EXPONENT 65537L #endif +#if defined(WC_RSA_NONBLOCK) + /* enable support for fast math based non-blocking exptmod */ + /* this splits the RSA function into many smaller operations */ + #ifndef USE_FAST_MATH + #error RSA non-blocking mode only supported using fast math + #endif + + /* RSA bounds check is not supported with RSA non-blocking mode */ + #undef NO_RSA_BOUNDS_CHECK + #define NO_RSA_BOUNDS_CHECK +#endif /* allow for user to plug in own crypto */ #if !defined(HAVE_FIPS) && (defined(HAVE_USER_RSA) || defined(HAVE_FAST_RSA)) @@ -117,6 +128,13 @@ enum { #endif }; +#ifdef WC_RSA_NONBLOCK +typedef struct RsaNb { + exptModNb_t exptmod; /* non-block expt_mod */ + mp_int tmp; +} RsaNb; +#endif + /* RSA */ struct RsaKey { mp_int n, e, d, p, q; @@ -150,6 +168,9 @@ struct RsaKey { int idLen; #endif byte dataIsAlloc; +#ifdef WC_RSA_NONBLOCK + RsaNb* nb; +#endif }; #ifndef WC_RSAKEY_TYPE_DEFINED @@ -237,7 +258,12 @@ WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); #endif -WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); +#ifdef WC_RSA_BLINDING + WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); +#endif +#ifdef WC_RSA_NONBLOCK + WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb); +#endif /* choice of padding added after fips, so not available when using fips RSA diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 689214fd4..49f95f791 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -294,6 +294,7 @@ #define FP_VAL -1 #define FP_MEM -2 #define FP_NOT_INF -3 +#define FP_WOULDBLOCK -4 /* equalities */ #define FP_LT -1 /* less than */ @@ -538,6 +539,42 @@ int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); /* d = a**b (mod c) */ int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); +#ifdef WC_RSA_NONBLOCK + +enum tfmExptModNbState { + TFM_EXPTMOD_NB_INIT = 0, + TFM_EXPTMOD_NB_MONT, + TFM_EXPTMOD_NB_MONT_RED, + TFM_EXPTMOD_NB_MONT_MUL, + TFM_EXPTMOD_NB_MONT_MOD, + TFM_EXPTMOD_NB_MONT_MODCHK, + TFM_EXPTMOD_NB_NEXT, + TFM_EXPTMOD_NB_MUL, + TFM_EXPTMOD_NB_MUL_RED, + TFM_EXPTMOD_NB_SQR, + TFM_EXPTMOD_NB_SQR_RED, + TFM_EXPTMOD_NB_RED, +}; + +typedef struct { +#ifndef WC_NO_CACHE_RESISTANT + fp_int R[3]; +#else + fp_int R[2]; +#endif + fp_digit buf, mp; + int bitcnt; + int digidx; + int y; + int state; /* tfmExptModNbState */ +} exptModNb_t; + +/* non-blocking version of timing resistant fp_exptmod function */ +/* supports cache resistance */ +int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y); + +#endif /* WC_RSA_NONBLOCK */ + /* primality stuff */ /* perform a Miller-Rabin test of a to the base b and store result in "result" */