diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 84290c64f..48a4edfa6 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4529,7 +4529,9 @@ int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) } /* test */ - if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) { + /* Running Miller-Rabin up to 40 times gives us a 2^{-80} chance + * of a candidate being a false positive. */ + if ((err = mp_prime_is_prime_ex(N, 40, &res, rng)) != MP_OKAY) { XFREE(buf, heap, DYNAMIC_TYPE_RSA); return err; } @@ -4602,6 +4604,74 @@ LBL_B:mp_clear (&b); } +/* + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) +{ + mp_int b; + int ix, err, res; + byte scratch[16]; + + /* default to no */ + *result = MP_NO; + + /* valid value of t? */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { + *result = MP_YES; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + + /* now do a miller rabin with up to t random numbers, this should + * give a (1/4)^t chance of a false prime. */ + for (ix = 0; ix < t; ix++) { + /* Set a test candidate. */ + if ((err = wc_RNG_GenerateBlock(rng, scratch, sizeof(scratch))) != 0) { + goto LBL_B; + } + + if ((err = mp_read_unsigned_bin(&b, scratch, sizeof(scratch))) != MP_OKAY) { + goto LBL_B; + } + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + + if (res == MP_NO) { + goto LBL_B; + } + } + + /* passed the test */ + *result = MP_YES; +LBL_B:mp_clear (&b); + return err; +} + + /* computes least common multiple as |a*b|/(a, b) */ int mp_lcm (mp_int * a, mp_int * b, mp_int * c) { diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index f223f35c0..31e9e7208 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -2945,10 +2945,60 @@ int fp_isprime(fp_int *a) return fp_isprime_ex(a, 8); } + +int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) +{ + int ret = FP_YES; + + if (a == NULL || result == NULL || rng == NULL) + return FP_VAL; + + /* do trial division */ + if (ret == FP_YES) { + fp_digit d; + int r; + + for (r = 0; r < FP_PRIME_SIZE; r++) { + if (fp_mod_d(a, primes[r], &d) == MP_OKAY) { + if (d == 0) + ret = FP_NO; + } + else + return FP_VAL; + } + } + + /* now do a miller rabin with up to t random numbers, this should + * give a (1/4)^t chance of a false prime. */ + if (ret == FP_YES) { + byte scratch[16]; + fp_int b; + + fp_init(&b); + while (t > 0) { + wc_RNG_GenerateBlock(rng, scratch, sizeof(scratch)); + fp_read_unsigned_bin(&b, scratch, sizeof(scratch)); + fp_prime_miller_rabin(a, &b, &ret); + if (ret == FP_NO) + break; + fp_zero(&b); + t--; + } + fp_clear(&b); + } + + *result = ret; + return FP_OKAY; +} + + int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) { static const int USE_BBS = 1; int err, type; + int isPrime = FP_YES; + /* Assume the candidate is probably prime and then test until + * it is proven composite. */ byte* buf; /* get type */ @@ -2991,7 +3041,10 @@ int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) fp_read_unsigned_bin(N, buf, len); /* test */ - } while (fp_isprime(N) == FP_NO); + /* Running Miller-Rabin up to 40 times gives us a 2^{-80} chance + * of a candidate being a false positive. */ + mp_prime_is_prime_ex(N, 40, &isPrime, rng); + } while (isPrime == FP_NO); XMEMSET(buf, 0, len); XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 14767b9ab..646437adb 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -372,6 +372,7 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size); #ifdef WOLFSSL_KEY_GEN MP_API int mp_prime_is_prime (mp_int * a, int t, int *result); + MP_API int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG*); MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c); MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c); MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 43217f584..104df8b75 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -732,6 +732,7 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size); MP_API int mp_gcd(fp_int *a, fp_int *b, fp_int *c); MP_API int mp_lcm(fp_int *a, fp_int *b, fp_int *c); MP_API int mp_prime_is_prime(mp_int* a, int t, int* result); +MP_API int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng); MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); MP_API int mp_exch(mp_int *a, mp_int *b); #endif /* WOLFSSL_KEY_GEN */