From d235a5f0ccd087a0280647c854731309c68e7e58 Mon Sep 17 00:00:00 2001 From: toddouska Date: Mon, 18 Jul 2016 11:57:47 -0700 Subject: [PATCH] add WC_RSA_BLINDING, wc_RsaSetRNG() for RSA Private Decrypt which doesn't have an RNG --- src/internal.c | 5 ++ src/sniffer.c | 7 ++ wolfcrypt/benchmark/benchmark.c | 3 + wolfcrypt/src/pkcs7.c | 9 +- wolfcrypt/src/rsa.c | 150 ++++++++++++++++++++++++++++++-- wolfcrypt/src/tfm.c | 7 ++ wolfcrypt/test/test.c | 11 +++ wolfssl/test.h | 7 ++ wolfssl/wolfcrypt/rsa.h | 5 ++ wolfssl/wolfcrypt/tfm.h | 1 + 10 files changed, 195 insertions(+), 10 deletions(-) diff --git a/src/internal.c b/src/internal.c index e15755f33..d86ba3c3b 100755 --- a/src/internal.c +++ b/src/internal.c @@ -2827,6 +2827,11 @@ int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, else #endif /* HAVE_PK_CALLBACKS */ { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(key, ssl->rng); + if (ret != 0) + return ret; + #endif ret = wc_RsaPrivateDecryptInline(in, inSz, out, key); } diff --git a/src/sniffer.c b/src/sniffer.c index 3194183ae..577d59110 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -1366,6 +1366,13 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes, wc_FreeRsaKey(&key); return -1; } + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&key, session->sslServer->rng); + if (ret != 0) { + SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + #endif ret = wc_RsaPrivateDecrypt(input, length, session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key); diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index f2c39b177..a510d61d7 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -1443,6 +1443,9 @@ void bench_rsa(void) return; } +#ifdef WC_RSA_BLINDING + wc_RsaSetRNG(&rsaKey, &rng); +#endif start = current_time(1); for (i = 0; i < ntimes; i++) { diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index ce83ea2e0..cb7a00322 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1769,8 +1769,15 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, } /* decrypt encryptedKey */ - keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(key, ssl->rng); + #endif + if (ret == 0) { + keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, &decryptedKey, privKey); + } else { + keySz = ret; + } wc_FreeRsaKey(privKey); #ifdef WOLFSSL_SMALL_STACK diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 778c99efd..aa4e473e9 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -781,22 +781,117 @@ static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, #endif /* WC_NO_RSA_OAEP */ +#ifdef WC_RSA_BLINDING + +/* helper for either lib */ +static int get_digit_count(mp_int* a) +{ + if (a == NULL) + return 0; + + return a->used; +} + + +static int get_rand_digit(WC_RNG* rng, mp_digit* d) +{ + return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); +} + + +static int mp_rand(mp_int* a, int digits, WC_RNG* rng) +{ + int ret; + mp_digit d; + + if (a == NULL || rng == NULL) + return BAD_FUNC_ARG; + + mp_zero(a); + if (digits <= 0) { + return MP_OKAY; + } + + /* first place a random non-zero digit */ + do { + ret = get_rand_digit(rng, &d); + if (ret != 0) { + return ret; + } + } while (d == 0); + + if ((ret = mp_add_d(a, d, a)) != MP_OKAY) { + return ret; + } + + while (--digits > 0) { + if ((ret = mp_lshd(a, 1)) != MP_OKAY) { + return ret; + } + if ((ret = get_rand_digit(rng, &d)) != 0) { + return ret; + } + if ((ret = mp_add_d(a, d, a)) != MP_OKAY) { + return ret; + } + } + + return ret; +} + + +#endif /* WC_RSA_BLINGING */ + + static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, - word32* outLen, int type, RsaKey* key) + word32* outLen, int type, RsaKey* key, WC_RNG* rng) { #define ERROR_OUT(x) { ret = (x); goto done;} mp_int tmp; +#ifdef WC_RSA_BLINDING + mp_int rnd, rndi; +#endif int ret = 0; word32 keyLen, len; + (void)rng; + if (mp_init(&tmp) != MP_OKAY) return 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; + } + } +#endif + if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY) ERROR_OUT(MP_READ_E); if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + #ifdef WC_RSA_BLINDING + /* blind */ + ret = mp_rand(&rnd, get_digit_count(&key->n), rng); + if (ret != MP_OKAY) + ERROR_OUT(ret); + + /* rndi = 1/rnd mod n */ + if (mp_invmod(&rnd, &key->n, &rndi) != MP_OKAY) + ERROR_OUT(MP_INVMOD_E); + + /* rnd = rnd^e */ + if (mp_exptmod(&rnd, &key->e, &key->n, &rnd) != MP_OKAY) + ERROR_OUT(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_BLINGING */ + #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); @@ -844,6 +939,12 @@ static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, } #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 */ } else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) { if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY) @@ -872,6 +973,12 @@ static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, done: mp_clear(&tmp); +#ifdef WC_RSA_BLINDING + if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + mp_clear(&rndi); + mp_clear(&rnd); + } +#endif if (ret == MP_EXPTMOD_E) { WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); } @@ -905,7 +1012,7 @@ int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, return ret; if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PUBLIC_ENCRYPT, key)) < 0) + RSA_PUBLIC_ENCRYPT, key, NULL)) < 0) sz = ret; return sz; @@ -953,7 +1060,7 @@ int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, return ret; if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PUBLIC_ENCRYPT, key)) < 0) + RSA_PUBLIC_ENCRYPT, key, NULL)) < 0) sz = ret; return sz; @@ -964,6 +1071,7 @@ int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) { int ret; + WC_RNG* rng = NULL; #ifdef HAVE_CAVIUM if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { @@ -974,8 +1082,12 @@ int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) } #endif - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) - < 0) { +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + + if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key, + rng)) < 0) { return ret; } @@ -999,6 +1111,7 @@ int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, byte* label, word32 labelSz) { int ret; + WC_RNG* rng = NULL; /* sanity check on arguments */ if (in == NULL || key == NULL) { @@ -1019,7 +1132,12 @@ int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, } #endif - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + + if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key, + rng)) < 0) { return ret; } @@ -1139,8 +1257,8 @@ int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) } #endif - if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key)) - < 0) { + if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key, + NULL)) < 0) { return ret; } @@ -1211,7 +1329,7 @@ int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, return ret; if ((ret = wc_RsaFunction(out, sz, out, &outLen, - RSA_PRIVATE_ENCRYPT,key)) < 0) + RSA_PRIVATE_ENCRYPT, key, rng)) < 0) sz = ret; return sz; @@ -1366,6 +1484,20 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) #endif /* WOLFSSL_KEY_GEN */ +#ifdef WC_RSA_BLINDING + +int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + key->rng = rng; + + return 0; +} + +#endif /* WC_RSA_BLINDING */ + #ifdef HAVE_CAVIUM #include diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 7fe0c43dc..27745ec97 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -3133,4 +3133,11 @@ void mp_dump(const char* desc, mp_int* a, byte verbose) #endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) */ + +int mp_lshd (mp_int * a, int b) +{ + fp_lshd(a, b); + return FP_OKAY; +} + #endif /* USE_FAST_MATH */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 279383f83..847f9e524 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -4222,6 +4222,17 @@ int rsa_test(void) TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); return -43; } +#ifdef WC_RSA_BLINDING + { + int tmpret = ret; + ret = wc_RsaSetRNG(&key, &rng); + if (ret < 0) { + TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + return -843; + } + ret = tmpret; + } +#endif ret = wc_RsaPrivateDecrypt(out, ret, plain, sizeof(plain), &key); if (ret < 0) { TEST_XFREE(tmp, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfssl/test.h b/wolfssl/test.h index dc54872f6..c318a6e87 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1773,6 +1773,13 @@ static INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz, ret = wc_RsaPrivateKeyDecode(key, &idx, &myKey, keySz); if (ret == 0) { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&myKey, ssl->rng); + if (ret != 0) { + wc_FreeRsaKey(&myKey); + return ret; + } + #endif ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); } wc_FreeRsaKey(&myKey); diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index e3d8261ff..6e51e9fbe 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -65,6 +65,9 @@ typedef struct RsaKey { mp_int n, e, d, p, q, dP, dQ, u; int type; /* public or private */ void* heap; /* for user memory overrides */ +#ifdef WC_RSA_BLINDING + WC_RNG* rng; /* for PrivateDecrypt blinding */ +#endif #ifdef HAVE_CAVIUM int devId; /* nitrox device id */ word32 magic; /* using cavium magic */ @@ -110,6 +113,8 @@ 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); + /* 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 db0965d06..ef4732c11 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -689,6 +689,7 @@ int mp_exch(mp_int *a, mp_int *b); int mp_cnt_lsb(fp_int *a); int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); +int mp_lshd (mp_int * a, int b); WOLFSSL_API word32 CheckRunTimeFastMath(void);