Merge pull request #1903 from dgarske/dhkeycheck

Speed improvements for DH public key prime checking
This commit is contained in:
toddouska 2018-11-06 16:35:27 -08:00 committed by GitHub
commit 5d8f4351ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 129 additions and 67 deletions

View File

@ -21429,21 +21429,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_sske;
}
#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
!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,
ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
#endif
if (ret != 0) {
goto exit_sske;
}
@ -24970,21 +24960,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_dcke;
}
#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
!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,
ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
#endif
/* set the max agree result size */
ssl->arrays->preMasterSz = ENCRYPT_LEN;
@ -25036,21 +25016,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
goto exit_dcke;
}
#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \
!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,
ssl->buffers.serverDH_P.buffer,
ssl->buffers.serverDH_P.length,
ssl->buffers.serverDH_G.buffer,
ssl->buffers.serverDH_G.length);
#endif
break;
}

View File

@ -1477,6 +1477,25 @@ int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz,
if (ssl->options.side == WOLFSSL_CLIENT_END)
return SIDE_ERROR;
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
{
DhKey checkKey;
int error, freeKey = 0;
error = wc_InitDhKey(&checkKey);
if (!error) {
freeKey = 1;
error = wc_DhSetCheckKey(&checkKey,
p, pSz, g, gSz, NULL, 0, 0, ssl->rng);
}
if (freeKey)
wc_FreeDhKey(&checkKey);
if (error)
return error;
}
#endif
if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) {
XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
ssl->buffers.serverDH_P.buffer = NULL;
@ -1545,6 +1564,29 @@ int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz,
if (pSz > ctx->maxDhKeySz)
return DH_KEY_SIZE_E;
#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
{
DhKey checkKey;
WC_RNG rng;
int error, freeKey = 0;
error = wc_InitRng(&rng);
if (!error)
error = wc_InitDhKey(&checkKey);
if (!error) {
freeKey = 1;
error = wc_DhSetCheckKey(&checkKey,
p, pSz, g, gSz, NULL, 0, 0, &rng);
}
if (freeKey)
wc_FreeDhKey(&checkKey);
wc_FreeRng(&rng);
if (error)
return error;
}
#endif
XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);
ctx->serverDH_P.buffer = NULL;
XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY);

View File

@ -56,6 +56,17 @@
#endif
/*
Possible DH enable options:
* NO_RSA: Overall control of DH default: on (not defined)
* WOLFSSL_OLD_PRIME_CHECK: Disables the new prime number check. It does not
directly effect this file, but it does speed up DH
removing the testing. It is not recommended to
disable the prime checking. default: off
*/
#if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST)
#include <math.h>
#define XPOW(x,y) pow((x),(y))

View File

@ -3193,15 +3193,11 @@ 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
* 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 err;
int s, j;
int err;
/* default */
*result = FP_NO;
@ -3211,26 +3207,15 @@ static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
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 */
fp_init_copy(n1, a);
fp_copy(a, n1);
err = fp_sub_d(n1, 1, n1);
if (err != FP_OKAY) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return err;
}
/* set 2**s * r = n1 */
fp_init_copy(r, n1);
fp_copy(n1, r);
/* count the number of least significant bits
* 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);
/* compute y = b**r mod a */
fp_init(y);
fp_zero(y);
fp_exptmod(b, r, a, y);
/* 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 (fp_cmp_d (y, 1) == FP_EQ) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return FP_OKAY;
}
++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 (fp_cmp (y, n1) != FP_EQ) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return FP_OKAY;
}
}
@ -3273,10 +3252,41 @@ static int fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result)
/* probably prime now */
*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
XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return FP_OKAY;
return err;
}
@ -3333,6 +3343,7 @@ int fp_isprime_ex(fp_int *a, int t, int* result)
return FP_NO;
}
/* check against primes table */
for (r = 0; r < FP_PRIME_SIZE; r++) {
if (fp_cmp_d(a, primes[r]) == FP_EQ) {
*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)
return FP_VAL;
/* do trial division */
if (ret == FP_YES) {
fp_digit d;
int r;
/* check against primes table */
for (r = 0; r < FP_PRIME_SIZE; r++) {
if (fp_cmp_d(a, primes[r]) == FP_EQ) {
*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++) {
if (fp_mod_d(a, primes[r], &d) == MP_OKAY) {
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. */
if (ret == FP_YES) {
#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];
#else
fp_int *b, *c;
fp_int *b, *c, *n1, *y, *r;
byte* base;
#endif
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)
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) {
return FP_MEM;
}
c = &b[1];
c = &b[1]; n1 = &b[2]; y= &b[3]; r = &b[4];
#endif
fp_init(b);
fp_init(c);
fp_init(n1);
fp_init(y);
fp_init(r);
err = fp_sub_d(a, 2, c);
if (err != FP_OKAY) {
#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;
}
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);
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;
fp_prime_miller_rabin(a, b, &ret);
}
fp_prime_miller_rabin_ex(a, b, &ret, n1, y, r);
if (ret == FP_NO)
break;
fp_zero(b);
t--;
}
fp_clear(n1);
fp_clear(y);
fp_clear(r);
fp_clear(b);
fp_clear(c);
#ifdef WOLFSSL_SMALL_STACK

View File

@ -11859,6 +11859,16 @@ int dh_test(void)
if (ret == 0)
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:
wc_FreeDhKey(&key);