From 8dbd8b0ad68cbb03ce366ea8216502fd89ca464b Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 15 Mar 2022 10:06:32 +1000 Subject: [PATCH] RSA: check for small difference between p and q --- wolfcrypt/src/rsa.c | 54 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index f46bc1766..9355465f9 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -59,15 +59,20 @@ RSA keys can be used to encrypt, decrypt, sign and verify data. /* Possible RSA enable options: - * NO_RSA: Overall control of RSA default: on (not defined) - * WC_RSA_BLINDING: Uses Blinding w/ Private Ops default: off - Note: slower by ~20% - * WOLFSSL_KEY_GEN: Allows Private Key Generation default: off - * RSA_LOW_MEM: NON CRT Private Operations, less memory default: off - * WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on (not defined) - * WC_RSA_NONBLOCK: Enables support for RSA non-blocking default: off - * WC_RSA_NONBLOCK_TIME:Enables support for time based blocking default: off - * time calculation. + * NO_RSA: Overall control of RSA default: on + * (not defined) + * WC_RSA_BLINDING: Uses Blinding w/ Private Ops default: off + Note: slower by ~20% + * WOLFSSL_KEY_GEN: Allows Private Key Generation default: off + * RSA_LOW_MEM: NON CRT Private Operations, less memory default: off + * WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on + * (not defined) + * WC_RSA_NONBLOCK: Enables support for RSA non-blocking default: off + * WC_RSA_NONBLOCK_TIME: Enables support for time based blocking default: off + * time calculation. + * WC_RSA_NO_FERMAT_CHECK:Don't check for small difference in default: off + * p and q (Fermat's factorization is (not defined) + * possible when small difference). */ /* @@ -731,6 +736,22 @@ int wc_CheckRsaKey(RsaKey* key) } } +#ifdef WC_RSA_NO_FERMAT_CHECK + /* Fermat's Factorization works when difference between p and q + * is less than (conservatively): + * n^(1/4) + 32 + * ~= 2^(bit count of n)^(1/4) + 32) = 2^((bit count of n)/4 + 32) + */ + if (ret == 0) { + ret = mp_sub(&key->p, &key->q, tmp); + } + if (ret == 0) { + if (mp_count_bits(tmp) <= (mp_count_bits(&key->n) / 4 + 32)) { + ret = MP_EXPTMOD_E; + } + } +#endif + /* Check dP, dQ and u if they exist */ if (ret == 0 && !mp_iszero(&key->dP)) { if (mp_sub_d(&key->p, 1, tmp) != MP_OKAY) { @@ -4526,6 +4547,21 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (err == MP_OKAY) err = _CheckProbablePrime(p, q, tmp3, size, &isPrime, rng); +#ifdef WC_RSA_NO_FERMAT_CHECK + if (err == MP_OKAY && isPrime) { + /* Fermat's Factorization works when difference between p and q + * is less than (conservatively): + * n^(1/4) + 32 + * ~= 2^(bit count of n)^(1/4) + 32) + * = 2^((bit count of n)/4 + 32) + */ + err = mp_sub(p, q, tmp1); + if (err == MP_OKAY && mp_count_bits(tmp1) <= (size / 4) + 32) { + isPrime = 0; + } + } +#endif + #ifdef HAVE_FIPS i++; #else