From f1c3098bdca9b6fd10a532fe3ae1da4b4cc212e7 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 5 Jul 2018 17:23:01 -0700 Subject: [PATCH 01/11] Prime Number Testing Made modifications to the primality testing so that the Miller-Rabin tests check against up to 40 random numbers rather than a fixed list of small primes. --- wolfcrypt/src/integer.c | 72 ++++++++++++++++++++++++++++++++++++- wolfcrypt/src/tfm.c | 55 +++++++++++++++++++++++++++- wolfssl/wolfcrypt/integer.h | 1 + wolfssl/wolfcrypt/tfm.h | 1 + 4 files changed, 127 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 84290c64f0..48a4edfa69 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 f223f35c00..31e9e72083 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 14767b9ab8..646437adb1 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 43217f584a..104df8b75d 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 */ From 0e06f6413d67cea4d691a325f7df2188ee22a486 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 10 Jul 2018 14:24:05 -0700 Subject: [PATCH 02/11] Prime Number Testing 1. Update the function wolfSSL_BN_is_prime_ex to use mp_prime_is_prime_ex. 2. Modified fast and normal mp_prime_is_prime_ex() to use random numbers that are in the range 2 < a < n-2. --- src/ssl.c | 43 +++++++++++++++++++++++++++++++++++++---- wolfcrypt/src/integer.c | 31 +++++++++++++++++++++++++---- wolfcrypt/src/tfm.c | 40 +++++++++++++++++++++++++++++++------- 3 files changed, 99 insertions(+), 15 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index bb5a99ea66..2370b5537f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -22526,7 +22526,14 @@ int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb) { - int res; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + int initTmpRng = 0; + int res = MP_NO; (void)ctx; (void)cb; @@ -22538,10 +22545,38 @@ int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, return WOLFSSL_FATAL_ERROR; } - if (mp_prime_is_prime((mp_int*)bn->internal, nbchecks, &res) != MP_OKAY) { - WOLFSSL_MSG("mp_prime_is_prime error"); - return WOLFSSL_FATAL_ERROR; +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) { + WOLFSSL_MSG("Global RNG no Init"); + } + else + rng = &globalRNG; + } + + if (rng) { + if (mp_prime_is_prime_ex((mp_int*)bn->internal, + nbchecks, &res, rng) != MP_OKAY) { + WOLFSSL_MSG("mp_prime_is_prime error"); + res = MP_NO; + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif if (res != MP_YES) { WOLFSSL_MSG("mp_prime_is_prime not prime"); diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 48a4edfa69..6b01ee3916 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4609,9 +4609,10 @@ LBL_B:mp_clear (&b); */ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) { - mp_int b; + mp_int b, c; int ix, err, res; - byte scratch[16]; + byte* base = NULL; + word32 baseSz = 0; /* default to no */ *result = MP_NO; @@ -4643,19 +4644,39 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) if ((err = mp_init (&b)) != MP_OKAY) { return err; } + if ((err = mp_init (&c)) != MP_OKAY) { + mp_clear(&b); + return err; + } + + baseSz = mp_count_bits(a); + baseSz = (baseSz / 8) + (baseSz % 8) ? 1 : 0; + + base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (base == NULL) { + err = MP_MEM; + goto LBL_B; + } + + if ((err = mp_copy(a, 2, &c)) != MP_OKAY) { + goto LBL_B; + } /* 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) { + if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) { goto LBL_B; } - if ((err = mp_read_unsigned_bin(&b, scratch, sizeof(scratch))) != MP_OKAY) { + if ((err = mp_read_unsigned_bin(&b, base, baseSz)) != MP_OKAY) { goto LBL_B; } + if (mp_cmp_d(&b, 2) != MP_GT || mp_cmp(&b, &c) != MP_LT) + continue; + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { goto LBL_B; } @@ -4668,6 +4689,8 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) /* passed the test */ *result = MP_YES; LBL_B:mp_clear (&b); + mp_clear (&c); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); return err; } diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 31e9e72083..a1775f976e 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -2760,7 +2760,7 @@ int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c) static void fp_gcd(fp_int *a, fp_int *b, fp_int *c); static void fp_lcm(fp_int *a, fp_int *b, fp_int *c); static int fp_isprime_ex(fp_int *a, int t); -static int fp_isprime(fp_int *a); +/* static int fp_isprime(fp_int *a); */ static int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap); int mp_gcd(fp_int *a, fp_int *b, fp_int *c) @@ -2780,7 +2780,7 @@ int mp_lcm(fp_int *a, fp_int *b, fp_int *c) int mp_prime_is_prime(mp_int* a, int t, int* result) { (void)t; - *result = fp_isprime(a); + *result = fp_isprime_ex(a, t); return MP_OKAY; } @@ -2940,11 +2940,13 @@ int fp_isprime_ex(fp_int *a, int t) return FP_YES; } +#if 0 +/* Removed in favor of fp_isprime_ex(). */ int fp_isprime(fp_int *a) { return fp_isprime_ex(a, 8); } - +#endif int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) { @@ -2971,13 +2973,33 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) /* 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_int b, c; + /* FP_MAX_BITS is 2 times the modulus size. The modulus size is + * 2 times the prime size. */ + word32 baseSz; + #ifndef WOLFSSL_SMALL_STACK + byte base[FP_MAX_BITS/32]; + #else + byte* base; + #endif + + baseSz = fp_count_bits(a); + baseSz = (baseSz / 8) + (baseSz % 8) ? 1 : 0; + + #ifdef WOLFSSL_SMALL_STACK + base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (base == NULL) + return FP_MEM; + #endif fp_init(&b); + fp_init(&c); + fp_sub_d(a, 2, &c); while (t > 0) { - wc_RNG_GenerateBlock(rng, scratch, sizeof(scratch)); - fp_read_unsigned_bin(&b, scratch, sizeof(scratch)); + wc_RNG_GenerateBlock(rng, base, baseSz); + fp_read_unsigned_bin(&b, base, baseSz); + if (fp_cmp_d(&b, 2) != FP_GT || fp_cmp(&b, &c) != FP_LT) + continue; fp_prime_miller_rabin(a, &b, &ret); if (ret == FP_NO) break; @@ -2985,6 +3007,10 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) t--; } fp_clear(&b); + fp_clear(&c); + #ifdef WOLFSSL_SMALL_STACK + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif } *result = ret; From 5908230d20edabfbb65b317d5d4628322c99af7e Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 11 Jul 2018 16:24:41 -0700 Subject: [PATCH 03/11] Prime Number Testing 1. Fixed variable name typo in DH for the FFDHE 8192-bit q value. 2. Updated some error strings in wolfSSL_BN_is_prime_ex(). 3. Changed the calls to mp_prime_is_prime_ex() in fp_randprime() and mp_randprime() so they go back to the 8 rounds of MR, which is more than adequate in this situation. --- src/ssl.c | 4 ++-- wolfcrypt/src/dh.c | 2 +- wolfcrypt/src/integer.c | 8 +++++--- wolfcrypt/src/tfm.c | 8 +++++--- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 2370b5537f..c32858c47c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -22566,7 +22566,7 @@ int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, if (rng) { if (mp_prime_is_prime_ex((mp_int*)bn->internal, nbchecks, &res, rng) != MP_OKAY) { - WOLFSSL_MSG("mp_prime_is_prime error"); + WOLFSSL_MSG("mp_prime_is_prime_ex error"); res = MP_NO; } } @@ -22579,7 +22579,7 @@ int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, #endif if (res != MP_YES) { - WOLFSSL_MSG("mp_prime_is_prime not prime"); + WOLFSSL_MSG("mp_prime_is_prime_ex not prime"); return WOLFSSL_FAILURE; } diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 5ce1c24429..50680e4fcd 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -765,7 +765,7 @@ static const byte dh_ffdhe8192_p[] = { }; static const byte dh_ffdhe8192_g[] = { 0x02 }; #ifdef HAVE_FFDHE_Q -static const byte dh_ffdhe8192_g[] = { +static const byte dh_ffdhe8192_q[] = { 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 6b01ee3916..d5a6bebb9e 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4529,9 +4529,11 @@ int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) } /* test */ - /* 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) { + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8. */ + if ((err = mp_prime_is_prime_ex(N, 8, &res, rng)) != MP_OKAY) { XFREE(buf, heap, DYNAMIC_TYPE_RSA); return err; } diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index a1775f976e..6ead9d792a 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -3067,9 +3067,11 @@ int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) fp_read_unsigned_bin(N, buf, len); /* test */ - /* 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); + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8 */ + mp_prime_is_prime_ex(N, 8, &isPrime, rng); } while (isPrime == FP_NO); XMEMSET(buf, 0, len); From d486df50aa996318e971e4332ebf64c2d2da2520 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 12 Jul 2018 11:03:41 -0700 Subject: [PATCH 04/11] fix an error where mp_copy was used instead of mp_sub_d --- wolfcrypt/src/integer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index d5a6bebb9e..de3160e512 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4660,7 +4660,7 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) goto LBL_B; } - if ((err = mp_copy(a, 2, &c)) != MP_OKAY) { + if ((err = mp_sub_d(a, 2, &c)) != MP_OKAY) { goto LBL_B; } From 997a3773103c22f5b626ba9ee20faefc30b6aad8 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 12 Jul 2018 14:58:19 -0700 Subject: [PATCH 05/11] Prime Number Testing 1. In wc_DhGenerateParams(), changed the call to mp_prime_is_prime() to mp_prime_is_prime_ex(). 2. In wc_MakeDsaParameters(), changed the call to mp_prime_is_prime() to mp_prime_is_prime_ex(). 3. Added wc_CheckProbablePrime_ex in RSA that also takes an RNG to call mp_prime_is_prime_ex(). If RNG is NULL, call mp_prime_is_prime(). 4. Rewrite wc_CheckProbablePrime() in terms of wc_CheckProbablePrime_ex(). --- wolfcrypt/src/dh.c | 2 +- wolfcrypt/src/dsa.c | 2 +- wolfcrypt/src/rsa.c | 40 ++++++++++++++++++++++++++++------------ wolfssl/wolfcrypt/rsa.h | 4 ++++ 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 50680e4fcd..d541b6862a 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1900,7 +1900,7 @@ int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh) /* loop until p is prime */ if (ret == 0) { do { - if (mp_prime_is_prime(&dh->p, 8, &primeCheck) != MP_OKAY) + if (mp_prime_is_prime_ex(&dh->p, 8, &primeCheck, rng) != MP_OKAY) ret = PRIME_GEN_E; if (primeCheck != MP_YES) { diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index 86d6015603..18970489a0 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -337,7 +337,7 @@ int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) /* loop until p is prime */ while (check_prime == MP_NO) { - err = mp_prime_is_prime(&dsa->p, 8, &check_prime); + err = mp_prime_is_prime_ex(&dsa->p, 8, &check_prime, rng); if (err != MP_OKAY) { mp_clear(&dsa->q); mp_clear(&dsa->p); diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 7ef917f5ce..9eaf1fe6a1 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -2641,8 +2641,8 @@ static WC_INLINE int RsaSizeCheck(int size) } -static int wc_CheckProbablePrime_ex(mp_int* p, mp_int* q, mp_int* e, int nlen, - int* isPrime) +static int _CheckProbablePrime(mp_int* p, mp_int* q, mp_int* e, int nlen, + int* isPrime, WC_RNG* rng) { int ret; mp_int tmp1, tmp2; @@ -2683,10 +2683,17 @@ static int wc_CheckProbablePrime_ex(mp_int* p, mp_int* q, mp_int* e, int nlen, ret = mp_cmp_d(&tmp2, 1); if (ret != MP_EQ) goto exit; /* e divides p-1 */ - /* 4.5.1,5.6.1 - Check primality of p with 8 iterations */ - ret = mp_prime_is_prime(prime, 8, isPrime); - /* Performs some divides by a table of primes, and then does M-R, - * it sets isPrime as a side-effect. */ + /* 4.5.1,5.6.1 - Check primality of p with 8 rounds of M-R. + * mp_prime_is_prime_ex() performs test divisons against the first 256 + * prime numbers. After that it performs 8 rounds of M-R using random + * bases between 2 and n-2. + * mp_prime_is_prime() performs the same test divisions and then does + * M-R with the first 8 primes. Both functions set isPrime as a + * side-effect. */ + if (rng != NULL) + ret = mp_prime_is_prime_ex(prime, 8, isPrime, rng); + else + ret = mp_prime_is_prime(prime, 8, isPrime); if (ret != MP_OKAY) goto notOkay; exit: @@ -2698,11 +2705,10 @@ notOkay: } - -int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, +int wc_CheckProbablePrime_ex(const byte* pRaw, word32 pRawSz, const byte* qRaw, word32 qRawSz, const byte* eRaw, word32 eRawSz, - int nlen, int* isPrime) + int nlen, int* isPrime, WC_RNG* rng) { mp_int p, q, e; mp_int* Q = NULL; @@ -2735,7 +2741,7 @@ int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, ret = mp_read_unsigned_bin(&e, eRaw, eRawSz); if (ret == MP_OKAY) - ret = wc_CheckProbablePrime_ex(&p, Q, &e, nlen, isPrime); + ret = _CheckProbablePrime(&p, Q, &e, nlen, isPrime, rng); ret = (ret == MP_OKAY) ? 0 : PRIME_GEN_E; @@ -2747,6 +2753,16 @@ int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, } +int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, + const byte* qRaw, word32 qRawSz, + const byte* eRaw, word32 eRawSz, + int nlen, int* isPrime) +{ + return wc_CheckProbablePrime_ex(pRaw, pRawSz, qRaw, qRawSz, + eRaw, eRawSz, nlen, isPrime, NULL); +} + + /* Make an RSA key for size bits, with e specified, 65537 is a good e */ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) { @@ -2822,7 +2838,7 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) } if (err == MP_OKAY) - err = wc_CheckProbablePrime_ex(&p, NULL, &tmp3, size, &isPrime); + err = _CheckProbablePrime(&p, NULL, &tmp3, size, &isPrime, rng); #ifdef WOLFSSL_FIPS i++; @@ -2858,7 +2874,7 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) } if (err == MP_OKAY) - err = wc_CheckProbablePrime_ex(&p, &q, &tmp3, size, &isPrime); + err = _CheckProbablePrime(&p, &q, &tmp3, size, &isPrime, rng); #ifdef WOLFSSL_FIPS i++; diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 6c1f988bff..cb05919c36 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -269,6 +269,10 @@ WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); #ifdef WOLFSSL_KEY_GEN WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); + WOLFSSL_API int wc_CheckProbablePrime_ex(const byte* p, word32 pSz, + const byte* q, word32 qSz, + const byte* e, word32 eSz, + int nlen, int* isPrime, WC_RNG* rng); WOLFSSL_API int wc_CheckProbablePrime(const byte* p, word32 pSz, const byte* q, word32 qSz, const byte* e, word32 eSz, From 771e3499257e728c6566f9697dfce631d476af8d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 12 Jul 2018 17:22:44 -0700 Subject: [PATCH 06/11] Prime Number Testing 1. Moved a few functions around in tfm.c and integer.c. 2. Added some new ifdef clauses to tfc and integer so that the prime checking is available when using RSA, DSA, or DH. 3. Added an internal version of function wc_DhSetKey and wc_DsaImportParamsRaw that always checks to see if the prime value is prime. Modified the original function to be a wrapper. --- wolfcrypt/src/dh.c | 34 ++++++++- wolfcrypt/src/dsa.c | 72 ++++++++++++++---- wolfcrypt/src/integer.c | 144 ++++++++++++++++++------------------ wolfcrypt/src/tfm.c | 103 ++++++++++++++++---------- wolfssl/wolfcrypt/dh.h | 3 + wolfssl/wolfcrypt/dsa.h | 3 + wolfssl/wolfcrypt/integer.h | 4 +- wolfssl/wolfcrypt/tfm.h | 6 +- 8 files changed, 238 insertions(+), 131 deletions(-) diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index d541b6862a..b1bd516c12 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1728,8 +1728,9 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, } -int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, - word32 gSz, const byte* q, word32 qSz) +static int _DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz, int trusted, + WC_RNG* rng) { int ret = 0; mp_int* keyP = NULL; @@ -1766,6 +1767,18 @@ int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, else keyP = &key->p; } + + if (ret == 0 && !trusted) { + int isPrime = 0; + if (rng != NULL) + ret = mp_prime_is_prime_ex(keyP, 8, &isPrime, rng); + else + ret = mp_prime_is_prime(keyP, 8, &isPrime); + + if (ret == 0 && isPrime == 0) + ret = DH_CHECK_PUB_E; + } + if (ret == 0 && mp_init(&key->g) != MP_OKAY) ret = MP_INIT_E; if (ret == 0) { @@ -1799,11 +1812,26 @@ int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, } +int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz, int trusted, + WC_RNG* rng) +{ + return _DhSetKey(key, p, pSz, g, gSz, q, qSz, trusted, rng); +} + + +int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz) +{ + return _DhSetKey(key, p, pSz, g, gSz, q, qSz, 1, NULL); +} + + /* not in asn anymore since no actual asn types used */ int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz) { - return wc_DhSetKey_ex(key, p, pSz, g, gSz, NULL, 0); + return _DhSetKey(key, p, pSz, g, gSz, NULL, 0, 1, NULL); } diff --git a/wolfcrypt/src/dsa.c b/wolfcrypt/src/dsa.c index 18970489a0..b7911555a9 100644 --- a/wolfcrypt/src/dsa.c +++ b/wolfcrypt/src/dsa.c @@ -426,21 +426,8 @@ int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) #endif /* WOLFSSL_KEY_GEN */ -/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), - * input parameters (p,q,g) should be represented as ASCII hex values. - * - * dsa - pointer to initialized DsaKey structure - * p - DSA (p) parameter, ASCII hex string - * pSz - length of p - * q - DSA (q) parameter, ASCII hex string - * qSz - length of q - * g - DSA (g) parameter, ASCII hex string - * gSz - length of g - * - * returns 0 on success, negative upon failure - */ -int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, - const char* g) +static int _DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, + const char* g, int trusted, WC_RNG* rng) { int err; word32 pSz, qSz; @@ -450,6 +437,18 @@ int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, /* read p */ err = mp_read_radix(&dsa->p, p, MP_RADIX_HEX); + if (err == MP_OKAY && !trusted) { + int isPrime = 1; + if (rng == NULL) + err = mp_prime_is_prime(&dsa->p, 8, &isPrime); + else + err = mp_prime_is_prime_ex(&dsa->p, 8, &isPrime, rng); + + if (err == MP_OKAY) { + if (!isPrime) + err = DH_CHECK_PUB_E; + } + } /* read q */ if (err == MP_OKAY) @@ -478,6 +477,49 @@ int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, } +/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), + * input parameters (p,q,g) should be represented as ASCII hex values. + * + * dsa - pointer to initialized DsaKey structure + * p - DSA (p) parameter, ASCII hex string + * pSz - length of p + * q - DSA (q) parameter, ASCII hex string + * qSz - length of q + * g - DSA (g) parameter, ASCII hex string + * gSz - length of g + * + * returns 0 on success, negative upon failure + */ +int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, + const char* g) +{ + return _DsaImportParamsRaw(dsa, p, q, g, 1, NULL); +} + + +/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), + * input parameters (p,q,g) should be represented as ASCII hex values. Check + * that the p value is probably prime. + * + * dsa - pointer to initialized DsaKey structure + * p - DSA (p) parameter, ASCII hex string + * pSz - length of p + * q - DSA (q) parameter, ASCII hex string + * qSz - length of q + * g - DSA (g) parameter, ASCII hex string + * gSz - length of g + * trusted - trust that p is OK + * rng - random number generator for the prime test + * + * returns 0 on success, negative upon failure + */ +int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p, const char* q, + const char* g, int trusted, WC_RNG* rng) +{ + return _DsaImportParamsRaw(dsa, p, q, g, trusted, rng); +} + + /* Export raw DSA parameters from DsaKey structure * * dsa - pointer to initialized DsaKey structure diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index de3160e512..b7d9788485 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4320,7 +4320,7 @@ int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) #endif /* WOLFSSL_KEY_GEN || HAVE_COMP_KEY || HAVE_ECC || DEBUG_WOLFSSL */ -#ifdef WOLFSSL_KEY_GEN +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) const mp_digit ltm_prime_tab[PRIME_SIZE] = { 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, @@ -4476,75 +4476,6 @@ static int mp_prime_is_divisible (mp_int * a, int *result) return MP_OKAY; } -static const int USE_BBS = 1; - -int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) -{ - int err, res, type; - byte* buf; - - if (N == NULL || rng == NULL) - return MP_VAL; - - /* get type */ - if (len < 0) { - type = USE_BBS; - len = -len; - } else { - type = 0; - } - - /* allow sizes between 2 and 512 bytes for a prime size */ - if (len < 2 || len > 512) { - return MP_VAL; - } - - /* allocate buffer to work with */ - buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA); - if (buf == NULL) { - return MP_MEM; - } - XMEMSET(buf, 0, len); - - do { -#ifdef SHOW_GEN - printf("."); - fflush(stdout); -#endif - /* generate value */ - err = wc_RNG_GenerateBlock(rng, buf, len); - if (err != 0) { - XFREE(buf, heap, DYNAMIC_TYPE_RSA); - return err; - } - - /* munge bits */ - buf[0] |= 0x80 | 0x40; - buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); - - /* load value */ - if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) { - XFREE(buf, heap, DYNAMIC_TYPE_RSA); - return err; - } - - /* test */ - /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance - * of a 1024-bit candidate being a false positive, when it is our - * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) - * Using 8 because we've always used 8. */ - if ((err = mp_prime_is_prime_ex(N, 8, &res, rng)) != MP_OKAY) { - XFREE(buf, heap, DYNAMIC_TYPE_RSA); - return err; - } - } while (res == MP_NO); - - XMEMSET(buf, 0, len); - XFREE(buf, heap, DYNAMIC_TYPE_RSA); - - return MP_OKAY; -} - /* * Sets result to 1 if probably prime, 0 otherwise */ @@ -4696,6 +4627,79 @@ LBL_B:mp_clear (&b); return err; } +#endif /* WOLFSSL_KEY_GEN NO_DH NO_DSA NO_RSA */ + +#ifdef WOLFSSL_KEY_GEN + +static const int USE_BBS = 1; + +int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) +{ + int err, res, type; + byte* buf; + + if (N == NULL || rng == NULL) + return MP_VAL; + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } else { + type = 0; + } + + /* allow sizes between 2 and 512 bytes for a prime size */ + if (len < 2 || len > 512) { + return MP_VAL; + } + + /* allocate buffer to work with */ + buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA); + if (buf == NULL) { + return MP_MEM; + } + XMEMSET(buf, 0, len); + + do { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, len); + if (err != 0) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + + /* munge bits */ + buf[0] |= 0x80 | 0x40; + buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* load value */ + if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + + /* test */ + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8. */ + if ((err = mp_prime_is_prime_ex(N, 8, &res, rng)) != MP_OKAY) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + } while (res == MP_NO); + + XMEMSET(buf, 0, len); + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + + return MP_OKAY; +} + /* 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 6ead9d792a..db102d9a78 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -2607,7 +2607,8 @@ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b) #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \ - defined(WOLFSSL_PUBLIC_MP) + defined(WOLFSSL_PUBLIC_MP) || !defined(NO_DH) || !defined(NO_DSA) || \ + !defined(NO_RSA) #ifdef WOLFSSL_KEY_GEN /* swap the elements of two integers, for cases where you can't simply swap the @@ -2755,26 +2756,11 @@ int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c) #endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) */ -#ifdef WOLFSSL_KEY_GEN -static void fp_gcd(fp_int *a, fp_int *b, fp_int *c); -static void fp_lcm(fp_int *a, fp_int *b, fp_int *c); +#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN) + static int fp_isprime_ex(fp_int *a, int t); /* static int fp_isprime(fp_int *a); */ -static int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap); - -int mp_gcd(fp_int *a, fp_int *b, fp_int *c) -{ - fp_gcd(a, b, c); - return MP_OKAY; -} - - -int mp_lcm(fp_int *a, fp_int *b, fp_int *c) -{ - fp_lcm(a, b, c); - return MP_OKAY; -} int mp_prime_is_prime(mp_int* a, int t, int* result) @@ -2784,28 +2770,6 @@ int mp_prime_is_prime(mp_int* a, int t, int* result) return MP_OKAY; } -int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) -{ - int err; - - err = fp_randprime(N, len, rng, heap); - switch(err) { - case FP_VAL: - return MP_VAL; - case FP_MEM: - return MP_MEM; - default: - break; - } - - return MP_OKAY; -} - -int mp_exch (mp_int * a, mp_int * b) -{ - fp_exch(a, b); - return MP_OKAY; -} /* Miller-Rabin test of "a" to the base of "b" as described in * HAC pp. 139 Algorithm 4.24 @@ -2920,6 +2884,12 @@ int fp_isprime_ex(fp_int *a, int t) return FP_NO; } + for (r = 0; r < FP_PRIME_SIZE; r++) { + if (fp_cmp_d(a, primes[r]) == FP_EQ) { + return FP_YES; + } + } + /* do trial division */ for (r = 0; r < FP_PRIME_SIZE; r++) { res = fp_mod_d(a, primes[r], &d); @@ -2960,6 +2930,13 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) fp_digit d; int r; + for (r = 0; r < FP_PRIME_SIZE; r++) { + if (fp_cmp_d(a, primes[r]) == FP_EQ) { + *result = FP_YES; + return FP_OKAY; + } + } + for (r = 0; r < FP_PRIME_SIZE; r++) { if (fp_mod_d(a, primes[r], &d) == MP_OKAY) { if (d == 0) @@ -3017,6 +2994,52 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) return FP_OKAY; } +#endif /* NO_RSA NO_DSA NO_DH WOLFSSL_KEY_GEN */ + + +#ifdef WOLFSSL_KEY_GEN + +static void fp_gcd(fp_int *a, fp_int *b, fp_int *c); +static void fp_lcm(fp_int *a, fp_int *b, fp_int *c); +static int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap); + +int mp_gcd(fp_int *a, fp_int *b, fp_int *c) +{ + fp_gcd(a, b, c); + return MP_OKAY; +} + + +int mp_lcm(fp_int *a, fp_int *b, fp_int *c) +{ + fp_lcm(a, b, c); + return MP_OKAY; +} + +int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) +{ + int err; + + err = fp_randprime(N, len, rng, heap); + switch(err) { + case FP_VAL: + return MP_VAL; + case FP_MEM: + return MP_MEM; + default: + break; + } + + return MP_OKAY; +} + +int mp_exch (mp_int * a, mp_int * b) +{ + fp_exch(a, b); + return MP_OKAY; +} + + int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) { diff --git a/wolfssl/wolfcrypt/dh.h b/wolfssl/wolfcrypt/dh.h index f30a19f3c3..edb59d0ccb 100644 --- a/wolfssl/wolfcrypt/dh.h +++ b/wolfssl/wolfcrypt/dh.h @@ -98,6 +98,9 @@ WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g word32 gSz); WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz, const byte* q, word32 qSz); +WOLFSSL_API int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, + const byte* g, word32 gSz, const byte* q, word32 qSz, + int trusted, WC_RNG* rng); WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, byte* g, word32* gInOutSz); WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz); diff --git a/wolfssl/wolfcrypt/dsa.h b/wolfssl/wolfcrypt/dsa.h index 752cf41865..3a0c0f3d01 100644 --- a/wolfssl/wolfcrypt/dsa.h +++ b/wolfssl/wolfcrypt/dsa.h @@ -80,6 +80,9 @@ WOLFSSL_API int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) /* raw export functions */ WOLFSSL_API int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, const char* g); +WOLFSSL_API int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p, + const char* q, const char* g, + int trusted, WC_RNG* rng); WOLFSSL_API int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz, byte* q, word32* qSz, byte* g, word32* gSz); diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 646437adb1..d7da22004f 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -370,9 +370,11 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size); MP_API int mp_read_radix(mp_int* a, const char* str, int radix); #endif -#ifdef WOLFSSL_KEY_GEN +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || !defined(NO_DSA) || !defined(NO_DH) 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*); +#endif /* WOLFSSL_KEY_GEN NO_RSA NO_DSA NO_DH */ +#ifdef WOLFSSL_KEY_GEN 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 104df8b75d..980fa69c4a 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -728,11 +728,13 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size); MP_API int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); #endif +#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || defined(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* rng); +#endif /* NO_DH NO_DSA NO_RSA WOLFSSL_KEY_GEN */ #ifdef WOLFSSL_KEY_GEN 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 */ From 00fd7ff8def70bf09d320cd99763e320cc1aa9fe Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 13 Jul 2018 17:42:35 -0700 Subject: [PATCH 07/11] Prime Number Testing 1. Added some new ifdef clauses to tfc and integer so that the prime checking is available when using RSA, DSA, or DH. A couple functions used were dependent on ECC being enabled. --- wolfcrypt/src/integer.c | 6 ++++-- wolfcrypt/src/tfm.c | 3 ++- wolfssl/wolfcrypt/integer.h | 3 ++- wolfssl/wolfcrypt/tfm.h | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index b7d9788485..819c4789f8 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -3978,7 +3978,8 @@ int mp_set_int (mp_int * a, unsigned long b) } -#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) || !defined(NO_RSA) || \ + !defined(NO_DSA) | !defined(NO_DH) /* c = a * a (mod b) */ int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) @@ -4172,7 +4173,8 @@ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c) #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(HAVE_ECC) || \ - defined(DEBUG_WOLFSSL) + defined(DEBUG_WOLFSSL) || !defined(NO_RSA) || !defined(NO_DSA) || \ + !defined(NO_DH) static const int lnz[16] = { 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index db102d9a78..aef6cf2b93 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -2564,7 +2564,8 @@ int mp_set_bit(mp_int *a, mp_digit b) return fp_set_bit(a, b); } -#if defined(WOLFSSL_KEY_GEN) || defined (HAVE_ECC) +#if defined(WOLFSSL_KEY_GEN) || defined (HAVE_ECC) || !defined(NO_DH) || \ + !defined(NO_DSA) || !defined(NO_RSA) /* c = a * a (mod b) */ int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c) diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index d7da22004f..8bb37e0d36 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -363,7 +363,8 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size); #define mp_dump(desc, a, verbose) #endif -#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || \ + !defined(NO_DSA) || !defined(NO_DH) MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); #endif #if !defined(NO_DSA) || defined(HAVE_ECC) diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 980fa69c4a..8aebfd2e03 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -723,7 +723,8 @@ MP_API int mp_radix_size (mp_int * a, int radix, int *size); MP_API int mp_set(fp_int *a, fp_digit b); #endif -#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || \ + !defined(NO_DSA) || !defined(NO_DH) MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); MP_API int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); #endif From 4b2a591a93061acca25ef45fd63414eacb745e3b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 26 Jul 2018 14:43:04 -0700 Subject: [PATCH 08/11] Prime Number Testing 1. Added calls to wc_DhSetCheckKey() on the client side of TLS. 2. Added an API test to the wolfCrypt test. 3. Fixed a bug in the prime test found with the API test. Misuse of tertiary operator. --- src/internal.c | 25 +++--- wolfcrypt/src/integer.c | 2 +- wolfcrypt/src/tfm.c | 2 +- wolfcrypt/test/test.c | 193 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 210 insertions(+), 12 deletions(-) diff --git a/src/internal.c b/src/internal.c index 8b78071524..787d10b7f5 100644 --- a/src/internal.c +++ b/src/internal.c @@ -19108,11 +19108,12 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } - ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + 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); + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); if (ret != 0) { goto exit_scke; } @@ -19203,11 +19204,12 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } - ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + 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); + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); if (ret != 0) { goto exit_scke; } @@ -20917,11 +20919,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_sske; } - ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + 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); + ssl->buffers.serverDH_G.length, + NULL, 0, 1, ssl->rng); if (ret != 0) { goto exit_sske; } @@ -24447,11 +24450,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } - ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + 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); + ssl->buffers.serverDH_G.length, + NULL, 0, 1, ssl->rng); /* set the max agree result size */ ssl->arrays->preMasterSz = ENCRYPT_LEN; @@ -24503,11 +24507,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } - ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + 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); + ssl->buffers.serverDH_G.length, + NULL, 0, 1, ssl->rng); break; } diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 819c4789f8..13a1ab5c1b 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4585,7 +4585,7 @@ int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) } baseSz = mp_count_bits(a); - baseSz = (baseSz / 8) + (baseSz % 8) ? 1 : 0; + baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (base == NULL) { diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index aef6cf2b93..3e4a8e8d04 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -2962,7 +2962,7 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) #endif baseSz = fp_count_bits(a); - baseSz = (baseSz / 8) + (baseSz % 8) ? 1 : 0; + baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); #ifdef WOLFSSL_SMALL_STACK base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 65c1410224..eef29de761 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -331,6 +331,9 @@ int memory_test(void); #ifdef HAVE_VALGRIND int mp_test(void); #endif +#ifdef WOLFSSL_PUBLIC_MP +int prime_test(void); +#endif #ifdef ASN_BER_TO_DER int berder_test(void); #endif @@ -928,6 +931,13 @@ initDefaultName(); printf( "mp test passed!\n"); #endif +#ifdef WOLFSSL_PUBLIC_MP + if ( (ret = prime_test()) != 0) + return err_sys("prime test failed!\n", ret); + else + printf( "prime test passed!\n"); +#endif + #if defined(ASN_BER_TO_DER) && \ (defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ defined(OPENSSL_EXTRA_X509_SMALL)) @@ -19131,6 +19141,189 @@ done: } #endif + +#ifdef WOLFSSL_PUBLIC_MP + +typedef struct pairs_t { + const unsigned char* coeff; + int coeffSz; + int exp; +} pairs_t; + + +/* +n =p1p2p3, where pi = ki(p1−1)+1 with (k2,k3) = (173,293) +p1 = 2^192 * 0x000000000000e24fd4f6d6363200bf2323ec46285cac1d3a + + 2^0 * 0x0b2488b0c29d96c5e67f8bec15b54b189ae5636efe89b45b +*/ + +const unsigned char c192a[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x4f, + 0xd4, 0xf6, 0xd6, 0x36, 0x32, 0x00, 0xbf, 0x23, + 0x23, 0xec, 0x46, 0x28, 0x5c, 0xac, 0x1d, 0x3a +}; +const unsigned char c0a[] = +{ + 0x0b, 0x24, 0x88, 0xb0, 0xc2, 0x9d, 0x96, 0xc5, + 0xe6, 0x7f, 0x8b, 0xec, 0x15, 0xb5, 0x4b, 0x18, + 0x9a, 0xe5, 0x63, 0x6e, 0xfe, 0x89, 0xb4, 0x5b +}; + +const pairs_t ecPairsA[] = +{ + {c192a, sizeof(c192a), 192}, + {c0a, sizeof(c0a), 0} +}; + +const int kA[] = {173, 293}; + +const unsigned char controlPrime[] = { + 0xe1, 0x76, 0x45, 0x80, 0x59, 0xb6, 0xd3, 0x49, + 0xdf, 0x0a, 0xef, 0x12, 0xd6, 0x0f, 0xf0, 0xb7, + 0xcb, 0x2a, 0x37, 0xbf, 0xa7, 0xf8, 0xb5, 0x4d, + 0xf5, 0x31, 0x35, 0xad, 0xe4, 0xa3, 0x94, 0xa1, + 0xdb, 0xf1, 0x96, 0xad, 0xb5, 0x05, 0x64, 0x85, + 0x83, 0xfc, 0x1b, 0x5b, 0x29, 0xaa, 0xbe, 0xf8, + 0x26, 0x3f, 0x76, 0x7e, 0xad, 0x1c, 0xf0, 0xcb, + 0xd7, 0x26, 0xb4, 0x1b, 0x05, 0x8e, 0x56, 0x86, + 0x7e, 0x08, 0x62, 0x21, 0xc1, 0x86, 0xd6, 0x47, + 0x79, 0x3e, 0xb7, 0x5d, 0xa4, 0xc6, 0x3a, 0xd7, + 0xb1, 0x74, 0x20, 0xf6, 0x50, 0x97, 0x41, 0x04, + 0x53, 0xed, 0x3f, 0x26, 0xd6, 0x6f, 0x91, 0xfa, + 0x68, 0x26, 0xec, 0x2a, 0xdc, 0x9a, 0xf1, 0xe7, + 0xdc, 0xfb, 0x73, 0xf0, 0x79, 0x43, 0x1b, 0x21, + 0xa3, 0x59, 0x04, 0x63, 0x52, 0x07, 0xc9, 0xd7, + 0xe6, 0xd1, 0x1b, 0x5d, 0x5e, 0x96, 0xfa, 0x53 +}; + + +static int GenerateNextP(mp_int* p1, mp_int* p2, int k) +{ + int ret; + + ret = mp_sub_d(p1, 1, p2); + if (ret == 0) + ret = mp_mul_d(p2, k, p2); + if (ret == 0) + ret = mp_add_d(p2, 1, p2); + + return ret; +} + + +static int GenerateP(mp_int* p1, mp_int* p2, mp_int* p3, + const pairs_t* ecPairs, int ecPairsSz, + const int* k) +{ + mp_int x,y; + int ret, i; + + ret = mp_init(&x); + if (ret == 0) { + ret = mp_init(&y); + if (ret != 0) { + mp_clear(&x); + return MP_MEM; + } + } + for (i = 0; ret == 0 && i < ecPairsSz; i++) { + ret = mp_read_unsigned_bin(&x, ecPairs[i].coeff, ecPairs[i].coeffSz); + /* p1 = 2^exp */ + if (ret == 0) + ret = mp_2expt(&y, ecPairs[i].exp); + /* p1 = p1 * m */ + if (ret == 0) + ret = mp_mul(&x, &y, &x); + /* p1 += */ + if (ret == 0) + ret = mp_add(p1, &x, p1); + mp_zero(&x); + mp_zero(&y); + } + mp_clear(&x); + mp_clear(&y); + + if (ret == 0) + ret = GenerateNextP(p1, p2, k[0]); + if (ret == 0) + ret = GenerateNextP(p1, p3, k[1]); + + return ret; +} + +int prime_test(void) +{ + mp_int n, p1, p2, p3; + int ret, isPrime = 0; + WC_RNG rng; + + ret = wc_InitRng(&rng); + if (ret == 0) + ret = mp_init_multi(&n, &p1, &p2, &p3, NULL, NULL); + if (ret == 0) + ret = GenerateP(&p1, &p2, &p3, + ecPairsA, sizeof(ecPairsA) / sizeof(ecPairsA[0]), kA); + if (ret == 0) + ret = mp_mul(&p1, &p2, &n); + if (ret == 0) + ret = mp_mul(&n, &p3, &n); + if (ret != 0) + return -9650; + + /* Check the old prime test using the number that false positives. + * This test result should indicate as not prime. */ + ret = mp_prime_is_prime(&n, 40, &isPrime); + if (ret != 0) + return -9651; + if (isPrime) + return -9652; + + /* This test result should fail. It should indicate the value as prime. */ + ret = mp_prime_is_prime(&n, 8, &isPrime); + if (ret != 0) + return -9653; + if (!isPrime) + return -9654; + + /* This test result should indicate the value as not prime. */ + ret = mp_prime_is_prime_ex(&n, 8, &isPrime, &rng); + if (ret != 0) + return -9655; + if (isPrime) + return -9656; + + ret = mp_read_unsigned_bin(&n, controlPrime, sizeof(controlPrime)); + if (ret != 0) + return -9657; + + /* This test result should indicate the value as prime. */ + ret = mp_prime_is_prime_ex(&n, 8, &isPrime, &rng); + if (ret != 0) + return -9658; + if (!isPrime) + return -9659; + + /* This test result should indicate the value as prime. */ + isPrime = -1; + ret = mp_prime_is_prime(&n, 8, &isPrime); + if (ret != 0) + return -9660; + if (!isPrime) + return -9661; + + mp_clear(&p3); + mp_clear(&p2); + mp_clear(&p1); + mp_clear(&n); + wc_FreeRng(&rng); + + return 0; +} + +#endif /* WOLFSSL_PUBLIC_MP */ + + #if defined(ASN_BER_TO_DER) && \ (defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ defined(OPENSSL_EXTRA_X509_SMALL)) From 31f1692cbf91448be1a0e0276e1a6e048ed098bd Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 26 Jul 2018 16:01:08 -0700 Subject: [PATCH 09/11] Prime Number Testing 1. Disable the new prime test from TLS while using FIPS or setting the flag WOLFSSL_OLD_PRIME_CHECK. --- src/internal.c | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/internal.c b/src/internal.c index 787d10b7f5..c42f00f0b9 100644 --- a/src/internal.c +++ b/src/internal.c @@ -19108,12 +19108,20 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } +#if !defined(HAVE_FIPS) && !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_scke; } @@ -19204,12 +19212,20 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } +#if !defined(HAVE_FIPS) && !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_scke; } @@ -20919,12 +20935,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_sske; } +#if !defined(HAVE_FIPS) && !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, 1, ssl->rng); + 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; } @@ -24450,12 +24474,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } +#if !defined(HAVE_FIPS) && !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, 1, ssl->rng); + 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; @@ -24507,12 +24539,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } +#if !defined(HAVE_FIPS) && !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, 1, ssl->rng); + 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; } From 4b8507813eb515d86f2ecb87c9b9278d69e6b4a2 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 27 Jul 2018 13:34:38 -0700 Subject: [PATCH 10/11] Prime Number Testing 1. Also disable the new prime test from TLS while using SELFTEST. --- src/internal.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/internal.c b/src/internal.c index c42f00f0b9..4be19df416 100644 --- a/src/internal.c +++ b/src/internal.c @@ -19108,7 +19108,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } -#if !defined(HAVE_FIPS) && !defined(WOLFSSL_OLD_PRIME_CHECK) +#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, @@ -19212,7 +19213,8 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } -#if !defined(HAVE_FIPS) && !defined(WOLFSSL_OLD_PRIME_CHECK) +#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, @@ -20935,7 +20937,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_sske; } -#if !defined(HAVE_FIPS) && !defined(WOLFSSL_OLD_PRIME_CHECK) +#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, @@ -24474,7 +24477,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } -#if !defined(HAVE_FIPS) && !defined(WOLFSSL_OLD_PRIME_CHECK) +#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, @@ -24539,7 +24543,8 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto exit_dcke; } -#if !defined(HAVE_FIPS) && !defined(WOLFSSL_OLD_PRIME_CHECK) +#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, From 7647d52d77ca7c0a520b4e787ce8eb365dde5114 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 1 Aug 2018 14:49:06 -0700 Subject: [PATCH 11/11] Prime Number Testing 1. Remove a copy-paste error when clearing up the RNG used to test a prime. 2. Tag a some const test values as static in the wolfCrypt test. --- src/ssl.c | 1 - wolfcrypt/test/test.c | 10 +++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index c32858c47c..01b321bec0 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -22574,7 +22574,6 @@ int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, if (initTmpRng) wc_FreeRng(tmpRNG); #ifdef WOLFSSL_SMALL_STACK - tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); #endif diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index eef29de761..cdd6068abd 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19157,28 +19157,28 @@ p1 = 2^192 * 0x000000000000e24fd4f6d6363200bf2323ec46285cac1d3a + 2^0 * 0x0b2488b0c29d96c5e67f8bec15b54b189ae5636efe89b45b */ -const unsigned char c192a[] = +static const unsigned char c192a[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe2, 0x4f, 0xd4, 0xf6, 0xd6, 0x36, 0x32, 0x00, 0xbf, 0x23, 0x23, 0xec, 0x46, 0x28, 0x5c, 0xac, 0x1d, 0x3a }; -const unsigned char c0a[] = +static const unsigned char c0a[] = { 0x0b, 0x24, 0x88, 0xb0, 0xc2, 0x9d, 0x96, 0xc5, 0xe6, 0x7f, 0x8b, 0xec, 0x15, 0xb5, 0x4b, 0x18, 0x9a, 0xe5, 0x63, 0x6e, 0xfe, 0x89, 0xb4, 0x5b }; -const pairs_t ecPairsA[] = +static const pairs_t ecPairsA[] = { {c192a, sizeof(c192a), 192}, {c0a, sizeof(c0a), 0} }; -const int kA[] = {173, 293}; +static const int kA[] = {173, 293}; -const unsigned char controlPrime[] = { +static const unsigned char controlPrime[] = { 0xe1, 0x76, 0x45, 0x80, 0x59, 0xb6, 0xd3, 0x49, 0xdf, 0x0a, 0xef, 0x12, 0xd6, 0x0f, 0xf0, 0xb7, 0xcb, 0x2a, 0x37, 0xbf, 0xa7, 0xf8, 0xb5, 0x4d,