forked from wolfSSL/wolfssl
Merge pull request #1901 from dgarske/rsa_nonblock
Added RSA non-blocking support
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;
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
@ -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)
|
||||
{
|
||||
@ -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
|
||||
|
@ -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