diff --git a/src/ssl.c b/src/ssl.c index b09c64c47..21df183db 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -23605,6 +23605,7 @@ static int SetRsaExternal(WOLFSSL_RSA* rsa) return WOLFSSL_FATAL_ERROR; } + #ifndef RSA_LOW_MEM if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa dP key error"); return WOLFSSL_FATAL_ERROR; @@ -23619,6 +23620,7 @@ static int SetRsaExternal(WOLFSSL_RSA* rsa) WOLFSSL_MSG("rsa u key error"); return WOLFSSL_FATAL_ERROR; } + #endif /* !RSA_LOW_MEM */ } rsa->exSet = 1; @@ -23677,6 +23679,7 @@ static int SetRsaInternal(WOLFSSL_RSA* rsa) return WOLFSSL_FATAL_ERROR; } +#ifndef RSA_LOW_MEM if (rsa->dmp1 != NULL && SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("rsa dP key error"); @@ -23694,6 +23697,7 @@ static int SetRsaInternal(WOLFSSL_RSA* rsa) WOLFSSL_MSG("rsa u key error"); return WOLFSSL_FATAL_ERROR; } +#endif /* !RSA_LOW_MEM */ rsa->inSet = 1; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index bbacacb25..f10991efe 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -746,6 +746,25 @@ int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) return 0; } +#ifdef RSA_LOW_MEM +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) +static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + int ret; + int length; + + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + + *inOutIdx = idx + length; + + return 0; +} +#endif +#endif + static int CheckBitString(const byte* input, word32* inOutIdx, int* len, word32 maxIdx, int zeroBits, byte* unusedBits) { @@ -2092,10 +2111,16 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, GetInt(&key->e, input, inOutIdx, inSz) < 0 || GetInt(&key->d, input, inOutIdx, inSz) < 0 || GetInt(&key->p, input, inOutIdx, inSz) < 0 || - GetInt(&key->q, input, inOutIdx, inSz) < 0 || - GetInt(&key->dP, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0) return ASN_RSA_KEY_E; +#ifndef RSA_LOW_MEM + if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 || GetInt(&key->dQ, input, inOutIdx, inSz) < 0 || GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; +#else + if (SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; +#endif #ifdef WOLFSSL_XILINX_CRYPT if (wc_InitRsaHw(key) != 0) { @@ -2310,20 +2335,45 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #if !defined(NO_RSA) /* test if RSA key */ if (der->keyOID == RSAk) { - RsaKey a, b; + #ifdef WOLFSSL_SMALL_STACK + RsaKey* a = NULL; + RsaKey* b = NULL; + #else + RsaKey a[1], b[1]; + #endif word32 keyIdx = 0; - if ((ret = wc_InitRsaKey(&a, NULL)) < 0) - return ret; - if ((ret = wc_InitRsaKey(&b, NULL)) < 0) { - wc_FreeRsaKey(&a); + #ifdef WOLFSSL_SMALL_STACK + a = XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (a == NULL) + return MEMORY_E; + b = XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (b == NULL) { + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + return MEMORY_E; + } + #endif + + if ((ret = wc_InitRsaKey(a, NULL)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif return ret; } - if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz)) == 0) { + if ((ret = wc_InitRsaKey(b, NULL)) < 0) { + wc_FreeRsaKey(a); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + return ret; + } + if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 0) { WOLFSSL_MSG("Checking RSA key pair"); keyIdx = 0; /* reset to 0 for parsing public key */ - if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, &b, + if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, b, der->pubKeySize)) == 0) { /* limit for user RSA crypto because of RsaKey * dereference. */ @@ -2333,8 +2383,8 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #else /* both keys extracted successfully now check n and e * values are the same. This is dereferencing RsaKey */ - if (mp_cmp(&(a.n), &(b.n)) != MP_EQ || - mp_cmp(&(a.e), &(b.e)) != MP_EQ) { + if (mp_cmp(&(a->n), &(b->n)) != MP_EQ || + mp_cmp(&(a->e), &(b->e)) != MP_EQ) { ret = MP_CMP_E; } else @@ -2342,73 +2392,119 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) #endif } } - wc_FreeRsaKey(&b); - wc_FreeRsaKey(&a); + wc_FreeRsaKey(b); + wc_FreeRsaKey(a); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif } else #endif /* NO_RSA */ #ifdef HAVE_ECC if (der->keyOID == ECDSAk) { - ecc_key key_pair; - byte privDer[MAX_ECC_BYTES]; - word32 privSz = MAX_ECC_BYTES; - word32 keyIdx = 0; + #ifdef WOLFSSL_SMALL_STACK + ecc_key* key_pair = NULL; + byte* privDer; + #else + ecc_key key_pair[1]; + byte privDer[MAX_ECC_BYTES]; + #endif + word32 privSz = MAX_ECC_BYTES; + word32 keyIdx = 0; - if ((ret = wc_ecc_init(&key_pair)) < 0) + #ifdef WOLFSSL_SMALL_STACK + key_pair = XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (key_pair == NULL) + return MEMORY_E; + privDer = XMALLOC(MAX_ECC_BYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privDer == NULL) { + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + + if ((ret = wc_ecc_init(key_pair)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + #endif return ret; + } - if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, + if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair, keySz)) == 0) { WOLFSSL_MSG("Checking ECC key pair"); - if ((ret = wc_ecc_export_private_only(&key_pair, privDer, &privSz)) + if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz)) == 0) { - wc_ecc_free(&key_pair); - ret = wc_ecc_init(&key_pair); + wc_ecc_free(key_pair); + ret = wc_ecc_init(key_pair); if (ret == 0) { ret = wc_ecc_import_private_key((const byte*)privDer, privSz, (const byte*)der->publicKey, - der->pubKeySize, &key_pair); + der->pubKeySize, key_pair); } /* public and private extracted successfuly now check if is * a pair and also do sanity checks on key. wc_ecc_check_key * checks that private * base generator equals pubkey */ if (ret == 0) { - if ((ret = wc_ecc_check_key(&key_pair)) == 0) { + if ((ret = wc_ecc_check_key(key_pair)) == 0) { ret = 1; } } ForceZero(privDer, privSz); } } - wc_ecc_free(&key_pair); + wc_ecc_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + #endif } else #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 if (der->keyOID == ED25519k) { - word32 keyIdx = 0; - ed25519_key key_pair; + #ifdef WOLFSSL_SMALL_STACK + ed25519_key* key_pair = NULL; + #else + ed25519_key key_pair[1]; + #endif + word32 keyIdx = 0; - if ((ret = wc_ed25519_init(&key_pair)) < 0) + #ifdef WOLFSSL_SMALL_STACK + key_pair = XMALLOC(sizeof(ed25519_key), NULL, DYNAMIC_TYPE_ED25519); + if (key_pair == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_ed25519_init(key_pair)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519); + #endif return ret; - if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, &key_pair, + } + if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair, keySz)) == 0) { WOLFSSL_MSG("Checking ED25519 key pair"); keyIdx = 0; if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize, - &key_pair)) == 0) { + key_pair)) == 0) { /* public and private extracted successfuly no check if is * a pair and also do sanity checks on key. wc_ecc_check_key * checks that private * base generator equals pubkey */ - if ((ret = wc_ed25519_check_key(&key_pair)) == 0) + if ((ret = wc_ed25519_check_key(key_pair)) == 0) ret = 1; } } - wc_ed25519_free(&key_pair); + wc_ed25519_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519); + #endif } else #endif diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 7ef917f5c..e8d945a88 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -276,7 +276,11 @@ int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) if (ret != MP_OKAY) return ret; +#ifdef RSA_LOW_MEM + ret = mp_init_multi(&key->d, &key->p, &key->q, NULL, NULL, NULL); +#else ret = mp_init_multi(&key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u); +#endif if (ret != MP_OKAY) { mp_clear(&key->n); mp_clear(&key->e); @@ -387,17 +391,21 @@ int wc_FreeRsaKey(RsaKey* key) #endif if (key->type == RSA_PRIVATE) { +#ifndef RSA_LOW_MEM mp_forcezero(&key->u); mp_forcezero(&key->dQ); mp_forcezero(&key->dP); +#endif mp_forcezero(&key->q); mp_forcezero(&key->p); mp_forcezero(&key->d); } /* private part */ +#ifndef RSA_LOW_MEM mp_clear(&key->u); mp_clear(&key->dQ); mp_clear(&key->dP); +#endif mp_clear(&key->q); mp_clear(&key->p); mp_clear(&key->d); @@ -420,10 +428,21 @@ int wc_FreeRsaKey(RsaKey* key) * Verify that k = (k^e)^d, for some k: 1 < k < n-1. */ int wc_CheckRsaKey(RsaKey* key) { - mp_int k, tmp; +#ifdef WOLFSSL_SMALL_STACK + mp_int *k = NULL, *tmp = NULL; +#else + mp_int k[1], tmp[1]; +#endif int ret = 0; - if (mp_init_multi(&k, &tmp, NULL, NULL, NULL, NULL) != MP_OKAY) +#ifdef WOLFSSL_SMALL_STACK + k = (mp_int*)XMALLOC(sizeof(mp_int) * 2, NULL, DYNAMIC_TYPE_RSA); + if (k == NULL) + return MEMORY_E; + tmp = k + 1; +#endif + + if (mp_init_multi(k, tmp, NULL, NULL, NULL, NULL) != MP_OKAY) ret = MP_INIT_E; if (ret == 0) { @@ -432,28 +451,64 @@ int wc_CheckRsaKey(RsaKey* key) } if (ret == 0) { - if (mp_set_int(&k, 0x2342) != MP_OKAY) + if (mp_set_int(k, 0x2342) != MP_OKAY) ret = MP_READ_E; } - if (ret == 0) { - if (mp_exptmod(&k, &key->e, &key->n, &tmp) != MP_OKAY) +#ifdef WOLFSSL_SP_RSA +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->n) == 2048) { + ret = sp_ModExp_2048(k, &key->e, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + ret = sp_ModExp_2048(tmp, &key->d, &key->n, tmp); + if (ret != 0) ret = MP_EXPTMOD_E; } - - if (ret == 0) { - if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->n) == 3072) { + ret = sp_ModExp_3072(k, &key->e, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + ret = sp_ModExp_3072(tmp, &key->d, &key->n, tmp); + if (ret != 0) ret = MP_EXPTMOD_E; } + else +#endif +#endif +#ifdef WOLFSSL_SP_MATH + { + ret = WC_KEY_SIZE_E; + } +#else + { + if (ret == 0) { + if (mp_exptmod(k, &key->e, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + + if (ret == 0) { + if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + } +#endif if (ret == 0) { - if (mp_cmp(&k, &tmp) != MP_EQ) + if (mp_cmp(k, tmp) != MP_EQ) ret = RSA_KEY_PAIR_E; } - mp_forcezero(&tmp); - mp_clear(&tmp); - mp_clear(&k); + mp_forcezero(tmp); + mp_clear(tmp); + mp_clear(k); +#ifdef WOLFSSL_SMALL_STACK + XFREE(k, NULL, DYNAMIC_TYPE_RSA); +#endif + return ret; } @@ -1296,9 +1351,17 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, word32* outLen, int type, RsaKey* key, WC_RNG* rng) { #ifndef WOLFSSL_SP_MATH - mp_int tmp; +#ifdef WOLFSSL_SMALL_STACK + mp_int* tmp = NULL; #ifdef WC_RSA_BLINDING - mp_int rnd, rndi; + mp_int* rnd = NULL; + mp_int* rndi = NULL; +#endif +#else + mp_int tmp[1]; +#ifdef WC_RSA_BLINDING + mp_int rnd[1], rndi[1]; +#endif #endif int ret = 0; word32 keyLen, len; @@ -1314,9 +1377,14 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, if (rng == NULL) return MISSING_RNG_E; #endif + #ifndef RSA_LOW_MEM return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u, &key->n, out, outLen); + #else + return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q, + NULL, NULL, NULL, &key->n, out, outLen); + #endif case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: return sp_RsaPublic_2048(in, inLen, &key->e, &key->n, out, outLen); @@ -1332,9 +1400,14 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, if (rng == NULL) return MISSING_RNG_E; #endif + #ifndef RSA_LOW_MEM return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u, &key->n, out, outLen); + #else + return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q, + NULL, NULL, NULL, &key->n, out, outLen); + #endif case RSA_PUBLIC_ENCRYPT: case RSA_PUBLIC_DECRYPT: return sp_RsaPublic_3072(in, inLen, &key->e, &key->n, out, outLen); @@ -1348,152 +1421,193 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, #else (void)rng; - if (mp_init(&tmp) != MP_OKAY) - return MP_INIT_E; +#ifdef WOLFSSL_SMALL_STACK + tmp = XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); + if (tmp == NULL) + return MEMORY_E; +#ifdef WC_RSA_BLINDING + rnd = XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA); + if (rnd == NULL) { + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + return MEMORY_E; + } + rndi = rnd + 1; +#endif /* WC_RSA_BLINDING */ +#endif /* WOLFSSL_SMALL_STACK */ + + if (mp_init(tmp) != MP_OKAY) + ret = MP_INIT_E; #ifdef WC_RSA_BLINDING - if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - if (mp_init_multi(&rnd, &rndi, NULL, NULL, NULL, NULL) != MP_OKAY) { - mp_clear(&tmp); - return MP_INIT_E; + if (ret == 0) { + if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + if (mp_init_multi(rnd, rndi, NULL, NULL, NULL, NULL) != MP_OKAY) { + mp_clear(tmp); + ret = MP_INIT_E; + } } } #endif - if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY) - ERROR_OUT(MP_READ_E); + if (ret == 0 && mp_read_unsigned_bin(tmp, (byte*)in, inLen) != MP_OKAY) + ret = MP_READ_E; - switch(type) { - case RSA_PRIVATE_DECRYPT: - case RSA_PRIVATE_ENCRYPT: - { - #ifdef WC_RSA_BLINDING - /* blind */ - ret = mp_rand(&rnd, get_digit_count(&key->n), rng); - if (ret != MP_OKAY) - goto done; + if (ret == 0) { + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + { + #ifdef WC_RSA_BLINDING + /* blind */ + ret = mp_rand(rnd, get_digit_count(&key->n), rng); - /* rndi = 1/rnd mod n */ - if (mp_invmod(&rnd, &key->n, &rndi) != MP_OKAY) - ERROR_OUT(MP_INVMOD_E); + /* rndi = 1/rnd mod n */ + if (ret == 0 && mp_invmod(rnd, &key->n, rndi) != MP_OKAY) + ret = MP_INVMOD_E; - /* rnd = rnd^e */ - if (mp_exptmod(&rnd, &key->e, &key->n, &rnd) != MP_OKAY) - ERROR_OUT(MP_EXPTMOD_E); + /* rnd = rnd^e */ + if (ret == 0 && mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY) + ret = MP_EXPTMOD_E; - /* tmp = tmp*rnd mod n */ - if (mp_mulmod(&tmp, &rnd, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_MULMOD_E); - #endif /* WC_RSA_BLINDING */ + /* tmp = tmp*rnd mod n */ + if (ret == 0 && mp_mulmod(tmp, rnd, &key->n, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + #endif /* WC_RSA_BLINDING */ - #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ - if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_EXPTMOD_E); - #else - /* Return 0 when cond is false and n when cond is true. */ - #define COND_N(cond, n) ((0 - (cond)) & (n)) - /* If ret has an error value return it otherwise if r is OK then return - * 0 otherwise return e. - */ - #define RET_ERR(ret, r, e) \ - ((ret) | (COND_N((ret) == 0, COND_N((r) != MP_OKAY, (e))))) + #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ + if (ret == 0 && mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + #else + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* tmpa = NULL; + mp_int* tmpb = NULL; + #else + mp_int tmpa[1], tmpb[1]; + #endif + int cleara = 0, clearb = 0; - { /* tmpa/b scope */ - mp_int tmpa, tmpb; - int r; + #ifdef WOLFSSL_SMALL_STACK + tmpa = XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA); + if (tmpa != NULL) + tmpb = tmpa + 1; + else + ret = MEMORY_E; + #endif - if (mp_init(&tmpa) != MP_OKAY) - ERROR_OUT(MP_INIT_E); + if (ret == 0) { + if (mp_init(tmpa) != MP_OKAY) + ret = MP_INIT_E; + else + cleara = 1; + } - if (mp_init(&tmpb) != MP_OKAY) { - mp_clear(&tmpa); - ERROR_OUT(MP_INIT_E); + if (ret == 0) { + if (mp_init(tmpb) != MP_OKAY) + ret = MP_INIT_E; + else + clearb = 1; + } + + /* tmpa = tmp^dP mod p */ + if (ret == 0 && mp_exptmod(tmp, &key->dP, &key->p, + tmpa) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmpb = tmp^dQ mod q */ + if (ret == 0 && mp_exptmod(tmp, &key->dQ, &key->q, + tmpb) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY) + ret = MP_SUB_E; + + if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p, + tmp) != MP_OKAY) + ret = MP_MULMOD_E; + + /* tmp = tmpb + q * tmp */ + if (ret == 0 && mp_mul(tmp, &key->q, tmp) != MP_OKAY) + ret = MP_MUL_E; + + if (ret == 0 && mp_add(tmp, tmpb, tmp) != MP_OKAY) + ret = MP_ADD_E; + + #ifdef WOLFSSL_SMALL_STACK + if (tmpa != NULL) + #endif + { + if (cleara) + mp_clear(tmpa); + if (clearb) + mp_clear(tmpb); + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmpa, key->heap, DYNAMIC_TYPE_RSA); + #endif + } + } /* tmpa/b scope */ + #endif /* RSA_LOW_MEM */ + + #ifdef WC_RSA_BLINDING + /* unblind */ + if (ret == 0 && mp_mulmod(tmp, rndi, &key->n, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + #endif /* WC_RSA_BLINDING */ + + break; + } + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + #ifdef WOLFSSL_XILINX_CRYPT + ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng); + #else + if (mp_exptmod(tmp, &key->e, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + #endif + 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(tmp); + + /* pad front w/ zeros to match key length */ + while (len < keyLen) { + *out++ = 0x00; + len++; } - /* tmpa = tmp^dP mod p */ - r = mp_exptmod(&tmp, &key->dP, &key->p, &tmpa); - ret = RET_ERR(ret, r, MP_EXPTMOD_E); + *outLen = keyLen; - /* tmpb = tmp^dQ mod q */ - r = mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb); - ret = RET_ERR(ret, r, MP_EXPTMOD_E); - - /* tmp = (tmpa - tmpb) * qInv (mod p) */ - r = mp_sub(&tmpa, &tmpb, &tmp); - ret = RET_ERR(ret, r, MP_SUB_E); - - r = mp_mulmod(&tmp, &key->u, &key->p, &tmp); - ret = RET_ERR(ret, r, MP_MULMOD_E); - - /* tmp = tmpb + q * tmp */ - r = mp_mul(&tmp, &key->q, &tmp); - ret = RET_ERR(ret, r, MP_MUL_E); - - r = mp_add(&tmp, &tmpb, &tmp); - ret = RET_ERR(ret, r, MP_ADD_E); - - mp_clear(&tmpa); - mp_clear(&tmpb); - - if (ret != 0) { - goto done; - } - #undef RET_ERR - #undef COND_N - } /* tmpa/b scope */ - #endif /* RSA_LOW_MEM */ - - #ifdef WC_RSA_BLINDING - /* unblind */ - if (mp_mulmod(&tmp, &rndi, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_MULMOD_E); - #endif /* WC_RSA_BLINDING */ - - break; - } - case RSA_PUBLIC_ENCRYPT: - case RSA_PUBLIC_DECRYPT: - #ifdef WOLFSSL_XILINX_CRYPT - ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng); - goto done; - #else - if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY) - ERROR_OUT(MP_EXPTMOD_E); - break; - #endif - default: - ERROR_OUT(RSA_WRONG_TYPE_E); + /* convert */ + if (mp_to_unsigned_bin(tmp, out) != MP_OKAY) + ret = MP_TO_E; } - keyLen = wc_RsaEncryptSize(key); - if (keyLen > *outLen) { - ERROR_OUT(RSA_BUFFER_E); - } - - len = mp_unsigned_bin_size(&tmp); - - /* pad front w/ zeros to match key length */ - while (len < keyLen) { - *out++ = 0x00; - len++; - } - - *outLen = keyLen; - - /* convert */ - if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY) - ERROR_OUT(MP_TO_E); - -done: - mp_clear(&tmp); + mp_clear(tmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); +#endif #ifdef WC_RSA_BLINDING if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - mp_clear(&rndi); - mp_clear(&rnd); + mp_clear(rndi); + mp_clear(rnd); } +#ifdef WOLFSSL_SMALL_STACK + XFREE(rnd, key->heap, DYNAMIC_TYPE_RSA); #endif +#endif /* WC_RSA_BLINDING */ return ret; -#endif +#endif /* WOLFSSL_SP_MATH */ } #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) @@ -1690,30 +1804,44 @@ int wc_RsaFunction(const byte* in, word32 inLen, byte* out, key->state == RSA_STATE_DECRYPT_EXPTMOD) { /* Check that 1 < in < n-1. (Requirement of 800-56B.) */ - mp_int c; +#ifdef WOLFSSL_SMALL_STACK + mp_int* c = NULL; +#else + mp_int c[1]; +#endif - if (mp_init(&c) != MP_OKAY) +#ifdef WOLFSSL_SMALL_STACK + c = XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); + if (c == NULL) + ret = MEMORY_E; +#endif + + if (mp_init(c) != MP_OKAY) ret = MEMORY_E; if (ret == 0) { - if (mp_read_unsigned_bin(&c, in, inLen) != 0) + if (mp_read_unsigned_bin(c, in, inLen) != 0) ret = MP_READ_E; } if (ret == 0) { /* check c > 1 */ - if (mp_cmp_d(&c, 1) != MP_GT) + if (mp_cmp_d(c, 1) != MP_GT) ret = RSA_OUT_OF_RANGE_E; } if (ret == 0) { /* add c+1 */ - if (mp_add_d(&c, 1, &c) != MP_OKAY) + if (mp_add_d(c, 1, c) != MP_OKAY) ret = MP_ADD_E; } if (ret == 0) { /* check c+1 < n */ - if (mp_cmp(&c, &key->n) != MP_LT) + if (mp_cmp(c, &key->n) != MP_LT) ret = RSA_OUT_OF_RANGE_E; } - mp_clear(&c); + mp_clear(c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, key->heap, DYNAMIC_TYPE_RSA); +#endif if (ret != 0) return ret; diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c index 2a195ff91..f6322d0fe 100644 --- a/wolfcrypt/src/sp_c32.c +++ b/wolfcrypt/src/sp_c32.c @@ -3054,7 +3054,8 @@ static int sp_2048_mod_exp_90(sp_digit* r, sp_digit* a, sp_digit* e, int bits, } #endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) /* AND m into each word of a and store in r. * * r A single precision integer. @@ -3311,7 +3312,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, byte* out, word32* outLen) { -#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) sp_digit* a; sp_digit* d = NULL; @@ -3521,7 +3522,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, return err; #endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ -#endif /* SP_RSA_PRIVATE_EXP_D */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } #endif /* WOLFSSL_HAVE_SP_RSA */ @@ -6424,7 +6425,8 @@ static int sp_3072_mod_exp_136(sp_digit* r, sp_digit* a, sp_digit* e, int bits, } #endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) /* AND m into each word of a and store in r. * * r A single precision integer. @@ -6680,7 +6682,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, byte* out, word32* outLen) { -#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) sp_digit* a; sp_digit* d = NULL; @@ -6890,7 +6892,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, return err; #endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ -#endif /* SP_RSA_PRIVATE_EXP_D */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } #endif /* WOLFSSL_HAVE_SP_RSA */ diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c index 079c12163..3f54833d5 100644 --- a/wolfcrypt/src/sp_c64.c +++ b/wolfcrypt/src/sp_c64.c @@ -2480,7 +2480,8 @@ static int sp_2048_mod_exp_36(sp_digit* r, sp_digit* a, sp_digit* e, int bits, } #endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) /* AND m into each word of a and store in r. * * r A single precision integer. @@ -2734,7 +2735,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, byte* out, word32* outLen) { -#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) sp_digit* a; sp_digit* d = NULL; @@ -2944,7 +2945,7 @@ int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, return err; #endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ -#endif /* SP_RSA_PRIVATE_EXP_D */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } #endif /* WOLFSSL_HAVE_SP_RSA */ @@ -5861,7 +5862,8 @@ static int sp_3072_mod_exp_54(sp_digit* r, sp_digit* a, sp_digit* e, int bits, } #endif /* SP_RSA_PRIVATE_EXP_D || WOLFSSL_HAVE_SP_DH */ -#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) /* AND m into each word of a and store in r. * * r A single precision integer. @@ -6116,7 +6118,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, byte* out, word32* outLen) { -#ifdef SP_RSA_PRIVATE_EXP_D +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) #if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) sp_digit* a; sp_digit* d = NULL; @@ -6326,7 +6328,7 @@ int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, return err; #endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ -#endif /* SP_RSA_PRIVATE_EXP_D */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ } #endif /* WOLFSSL_HAVE_SP_RSA */ diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 74a37b6be..83cff49ba 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -633,6 +633,22 @@ int sp_add(sp_int* a, sp_int* b, sp_int* r) } #endif +#ifndef NO_RSA +/* Set a number into the big number. + * + * a SP integer. + * b Value to set. + * returns MP_OKAY always. + */ +int sp_set_int(sp_int* a, unsigned long b) +{ + a->used = 1; + a->dp[0] = b; + + return MP_OKAY; +} +#endif + #if !defined(USE_FAST_MATH) /* Returns the run time settings. * diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 6c1f988bf..3e2423e65 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -113,7 +113,10 @@ enum { /* RSA */ struct RsaKey { - mp_int n, e, d, p, q, dP, dQ, u; + mp_int n, e, d, p, q; +#if defined(WOLFSSL_KEY_GEN) || !defined(RSA_LOW_MEM) + mp_int dP, dQ, u; +#endif void* heap; /* for user memory overrides */ byte* data; /* temp buffer for async RSA */ int type; /* public or private */ diff --git a/wolfssl/wolfcrypt/sp_int.h b/wolfssl/wolfcrypt/sp_int.h index 51b9e2fb8..d11357949 100644 --- a/wolfssl/wolfcrypt/sp_int.h +++ b/wolfssl/wolfcrypt/sp_int.h @@ -133,6 +133,7 @@ MP_API void sp_zero(sp_int* a); MP_API int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r); MP_API int sp_lshd(sp_int* a, int s); MP_API int sp_add(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_set_int(sp_int* a, unsigned long b); typedef sp_int mp_int; typedef sp_digit mp_digit; @@ -180,6 +181,7 @@ typedef sp_digit mp_digit; #define mp_lshd sp_lshd #define mp_add sp_add #define mp_isodd sp_isodd +#define mp_set_int sp_set_int #define MP_INT_DEFINED