mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
* Added RSA non-blocking support enabled with WC_RSA_NONBLOCK
. Adds new wc_RsaSetNonBlock
function for enabling / non-block context. Added wolfCrypt test function rsa_nb_test
to validate. Result is: RSA non-block sign: 8200 times
and RSA non-block verify: 264 times
* Signature wrapper improvements to eliminate mallocs/frees unless small stack is used. If small stack is used only one allocation is done based on actual max (was previously was allocating too much and in the encoding case was reallocating a second buffer).
This commit is contained in:
@ -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;
|
||||
}
|
||||
|
||||
@ -3139,7 +3240,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)
|
||||
@ -3149,8 +3249,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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
@ -10671,6 +10751,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);
|
||||
@ -11444,7 +11530,7 @@ exit_rsa:
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif /* !NO_RSA */
|
||||
|
||||
|
||||
#ifndef NO_DH
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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" */
|
||||
|
Reference in New Issue
Block a user