Fix to not do prime test on DH key the server loaded. Now it will only do the prime test on the peer's provided public DH key using 8 miller rabbins. Refactored the fast math miller rabin function to reuse mp_int's, which improved peformance for mp_prime_is_prime_ex from 100ms to 80ms. Normal math mp_prime_is_prime_ex is ~40ms (as-is). Added test for wc_DhSetCheckKey.

This commit is contained in:
David Garske
2018-10-30 11:20:07 -07:00
parent ba90674357
commit f4b0261ca7
3 changed files with 77 additions and 47 deletions

View File

@@ -21429,21 +21429,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_sske; goto exit_sske;
} }
#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ /* this is the loaded server side DH key (trusted) */
!defined(WOLFSSL_OLD_PRIME_CHECK)
ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key,
ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length,
NULL, 0, 0, ssl->rng);
#else
ret = wc_DhSetKey(ssl->buffers.serverDH_Key, ret = wc_DhSetKey(ssl->buffers.serverDH_Key,
ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length, ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer, ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length); ssl->buffers.serverDH_G.length);
#endif
if (ret != 0) { if (ret != 0) {
goto exit_sske; goto exit_sske;
} }

View File

@@ -3193,13 +3193,9 @@ int mp_prime_is_prime(mp_int* a, int t, int* result)
* Randomly the chance of error is no more than 1/4 and often * Randomly the chance of error is no more than 1/4 and often
* very much lower. * very much lower.
*/ */
static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result) static int fp_prime_miller_rabin_ex(fp_int * a, fp_int * b, int *result,
fp_int *n1, fp_int *y, fp_int *r)
{ {
#ifndef WOLFSSL_SMALL_STACK
fp_int n1[1], y[1], r[1];
#else
fp_int *n1, *y, *r;
#endif
int s, j; int s, j;
int err; int err;
@@ -3211,26 +3207,15 @@ static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
return FP_OKAY; return FP_OKAY;
} }
#ifdef WOLFSSL_SMALL_STACK
n1 = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (n1 == NULL) {
return FP_MEM;
}
y = &n1[1]; r = &n1[2];
#endif
/* get n1 = a - 1 */ /* get n1 = a - 1 */
fp_init_copy(n1, a); fp_copy(a, n1);
err = fp_sub_d(n1, 1, n1); err = fp_sub_d(n1, 1, n1);
if (err != FP_OKAY) { if (err != FP_OKAY) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return err; return err;
} }
/* set 2**s * r = n1 */ /* set 2**s * r = n1 */
fp_init_copy(r, n1); fp_copy(n1, r);
/* count the number of least significant bits /* count the number of least significant bits
* which are zero * which are zero
@@ -3241,7 +3226,7 @@ static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
fp_div_2d (r, s, r, NULL); fp_div_2d (r, s, r, NULL);
/* compute y = b**r mod a */ /* compute y = b**r mod a */
fp_init(y); fp_zero(y);
fp_exptmod(b, r, a, y); fp_exptmod(b, r, a, y);
/* if y != 1 and y != n1 do */ /* if y != 1 and y != n1 do */
@@ -3253,9 +3238,6 @@ static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
/* if y == 1 then composite */ /* if y == 1 then composite */
if (fp_cmp_d (y, 1) == FP_EQ) { if (fp_cmp_d (y, 1) == FP_EQ) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return FP_OKAY; return FP_OKAY;
} }
++j; ++j;
@@ -3263,9 +3245,6 @@ static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
/* if y != n1 then composite */ /* if y != n1 then composite */
if (fp_cmp (y, n1) != FP_EQ) { if (fp_cmp (y, n1) != FP_EQ) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return FP_OKAY; return FP_OKAY;
} }
} }
@@ -3273,10 +3252,41 @@ static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
/* probably prime now */ /* probably prime now */
*result = FP_YES; *result = FP_YES;
return FP_OKAY;
}
static int fp_prime_miller_rabin(fp_int * a, fp_int * b, int *result)
{
int err;
#ifndef WOLFSSL_SMALL_STACK
fp_int n1[1], y[1], r[1];
#else
fp_int *n1, *y, *r;
#endif
#ifdef WOLFSSL_SMALL_STACK
n1 = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (n1 == NULL) {
return FP_MEM;
}
y = &n1[1]; r = &n1[2];
#endif
fp_init(n1);
fp_init(y);
fp_init(r);
err = fp_prime_miller_rabin_ex(a, b, result, n1, y, r);
fp_clear(n1);
fp_clear(y);
fp_clear(r);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif #endif
return FP_OKAY;
return err;
} }
@@ -3333,6 +3343,7 @@ int fp_isprime_ex(fp_int *a, int t, int* result)
return FP_NO; return FP_NO;
} }
/* check against primes table */
for (r = 0; r < FP_PRIME_SIZE; r++) { for (r = 0; r < FP_PRIME_SIZE; r++) {
if (fp_cmp_d(a, primes[r]) == FP_EQ) { if (fp_cmp_d(a, primes[r]) == FP_EQ) {
*result = FP_YES; *result = FP_YES;
@@ -3382,11 +3393,11 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
if (a == NULL || result == NULL || rng == NULL) if (a == NULL || result == NULL || rng == NULL)
return FP_VAL; return FP_VAL;
/* do trial division */
if (ret == FP_YES) { if (ret == FP_YES) {
fp_digit d; fp_digit d;
int r; int r;
/* check against primes table */
for (r = 0; r < FP_PRIME_SIZE; r++) { for (r = 0; r < FP_PRIME_SIZE; r++) {
if (fp_cmp_d(a, primes[r]) == FP_EQ) { if (fp_cmp_d(a, primes[r]) == FP_EQ) {
*result = FP_YES; *result = FP_YES;
@@ -3394,6 +3405,7 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
} }
} }
/* do trial division */
for (r = 0; r < FP_PRIME_SIZE; r++) { for (r = 0; r < FP_PRIME_SIZE; r++) {
if (fp_mod_d(a, primes[r], &d) == MP_OKAY) { if (fp_mod_d(a, primes[r], &d) == MP_OKAY) {
if (d == 0) if (d == 0)
@@ -3409,10 +3421,10 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
* give a (1/4)^t chance of a false prime. */ * give a (1/4)^t chance of a false prime. */
if (ret == FP_YES) { if (ret == FP_YES) {
#ifndef WOLFSSL_SMALL_STACK #ifndef WOLFSSL_SMALL_STACK
fp_int b[1], c[1]; fp_int b[1], c[1], n1[1], y[1], r[1];
byte base[FP_MAX_PRIME_SIZE]; byte base[FP_MAX_PRIME_SIZE];
#else #else
fp_int *b, *c; fp_int *b, *c, *n1, *y, *r;
byte* base; byte* base;
#endif #endif
word32 baseSz; word32 baseSz;
@@ -3431,15 +3443,19 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
if (base == NULL) if (base == NULL)
return FP_MEM; return FP_MEM;
b = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); b = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (b == NULL) { if (b == NULL) {
return FP_MEM; return FP_MEM;
} }
c = &b[1]; c = &b[1]; n1 = &b[2]; y= &b[3]; r = &b[4];
#endif #endif
fp_init(b); fp_init(b);
fp_init(c); fp_init(c);
fp_init(n1);
fp_init(y);
fp_init(r);
err = fp_sub_d(a, 2, c); err = fp_sub_d(a, 2, c);
if (err != FP_OKAY) { if (err != FP_OKAY) {
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
@@ -3449,16 +3465,29 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng)
return err; return err;
} }
while (t > 0) { while (t > 0) {
wc_RNG_GenerateBlock(rng, base, baseSz); if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return err;
}
fp_read_unsigned_bin(b, base, baseSz); fp_read_unsigned_bin(b, base, baseSz);
if (fp_cmp_d(b, 2) != FP_GT || fp_cmp(b, c) != FP_LT) if (fp_cmp_d(b, 2) != FP_GT || fp_cmp(b, c) != FP_LT) {
continue; continue;
fp_prime_miller_rabin(a, b, &ret); }
fp_prime_miller_rabin_ex(a, b, &ret, n1, y, r);
if (ret == FP_NO) if (ret == FP_NO)
break; break;
fp_zero(b); fp_zero(b);
t--; t--;
} }
fp_clear(n1);
fp_clear(y);
fp_clear(r);
fp_clear(b); fp_clear(b);
fp_clear(c); fp_clear(c);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK

View File

@@ -11858,6 +11858,16 @@ int dh_test(void)
if (ret == 0) if (ret == 0)
ret = dh_fips_generate_test(&rng); ret = dh_fips_generate_test(&rng);
#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
!defined(WOLFSSL_OLD_PRIME_CHECK)
if (ret == 0) {
/* Test Check Key */
ret = wc_DhSetCheckKey(&key, dh_p, sizeof(dh_p), dh_g, sizeof(dh_g),
NULL, 0, 0, &rng);
}
#endif
done: done:
wc_FreeDhKey(&key); wc_FreeDhKey(&key);