From 4afa7c7e22298c19218f8829c23b04ed9972f44c Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 17 Oct 2017 14:42:13 -0700 Subject: [PATCH 1/8] RSA Update Added mp wrappers for fp_abs() and fp_2expt(). --- wolfcrypt/src/tfm.c | 13 +++++++++++++ wolfssl/wolfcrypt/tfm.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 81edccd0b..5057b42ff 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -2455,6 +2455,12 @@ int mp_mul_2d(fp_int *a, int b, fp_int *c) return MP_OKAY; } +int mp_2expt(fp_int* a, int b) +{ + fp_2expt(a, b); + return MP_OKAY; +} + int mp_div(fp_int * a, fp_int * b, fp_int * c, fp_int * d) { return fp_div(a, b, c, d); @@ -3389,6 +3395,13 @@ void mp_dump(const char* desc, mp_int* a, byte verbose) #endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) */ +int mp_abs(mp_int* a, mp_int* b) +{ + fp_abs(a, b); + return FP_OKAY; +} + + int mp_lshd (mp_int * a, int b) { fp_lshd(a, b); diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index e0432311b..43d546307 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -672,6 +672,7 @@ MP_API int mp_mod(mp_int *a, mp_int *b, mp_int *c); MP_API int mp_invmod(mp_int *a, mp_int *b, mp_int *c); MP_API int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); MP_API int mp_mul_2d(mp_int *a, int b, mp_int *c); +MP_API int mp_2expt(mp_int* a, int b); MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); @@ -733,6 +734,7 @@ MP_API int mp_cnt_lsb(fp_int *a); MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); MP_API int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); MP_API int mp_lshd (mp_int * a, int b); +MP_API int mp_abs(mp_int* a, mp_int* b); WOLFSSL_API word32 CheckRunTimeFastMath(void); From 84f609306889c9710f11e82aa90a7248a832ca54 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 24 Oct 2017 11:51:22 -0700 Subject: [PATCH 2/8] RSA Update 1. Replaced MakeRsaKey() function wth a version that follows the NIST prescribed process closer. 2. Added an additional check to RSA key generation to ensure that |p-q| > 2^((nlen/2)-100) per NIST FIPS 186-4 sec B.3.1. 3. Added public API for checking a number being probably prime according to FIPS 186-4. 4. Added a large integer used to check the lower bound of a possible prime. --- wolfcrypt/src/error.c | 3 + wolfcrypt/src/rsa.c | 314 +++++++++++++++++++++++++++++--- wolfssl/wolfcrypt/error-crypt.h | 3 +- wolfssl/wolfcrypt/rsa.h | 4 + 4 files changed, 293 insertions(+), 31 deletions(-) diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 280f14d90..add4f6458 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -443,6 +443,9 @@ const char* wc_GetErrorString(int error) case PSS_SALTLEN_E: return "PSS - Length of salt is too big for hash algorithm"; + case PRIME_GEN_E: + return "Unable to find a prime for RSA key"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 178b41e95..6de416ce6 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -2096,16 +2096,221 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, } #ifdef WOLFSSL_KEY_GEN + +/* Check that |p-q| > 2^((size/2)-100) */ +static int wc_CompareDiffPQ(mp_int* p, mp_int* q, int size) +{ + mp_int c, d; + int ret; + + if (p == NULL || q == NULL) + return BAD_FUNC_ARG; + + ret = mp_init_multi(&c, &d, NULL, NULL, NULL, NULL); + + /* c = 2^((size/2)-100) */ + if (ret == 0) + ret = mp_2expt(&c, (size/2)-100); + + /* d = |p-q| */ + if (ret == 0) + ret = mp_sub(p, q, &d); + + if (ret == 0) + ret = mp_abs(&d, &d); + + /* compare */ + if (ret == 0) + ret = mp_cmp(&d, &c); + + if (ret == MP_GT) + ret = MP_OKAY; + + mp_clear(&d); + mp_clear(&c); + + return ret; +} + + +/* The lower_bound value is floor(2^(0.5) * 2^((nlen/2)-1)) where nlen is 4096. + * This number was calculated using a small test tool written with a common + * large number math library. Other values of nlen may be checked with a subset + * of lower_bound. */ +static const byte lower_bound[] = { + 0xB5, 0x04, 0xF3, 0x33, 0xF9, 0xDE, 0x64, 0x84, + 0x59, 0x7D, 0x89, 0xB3, 0x75, 0x4A, 0xBE, 0x9F, + 0x1D, 0x6F, 0x60, 0xBA, 0x89, 0x3B, 0xA8, 0x4C, + 0xED, 0x17, 0xAC, 0x85, 0x83, 0x33, 0x99, 0x15, +/* 512 */ + 0x4A, 0xFC, 0x83, 0x04, 0x3A, 0xB8, 0xA2, 0xC3, + 0xA8, 0xB1, 0xFE, 0x6F, 0xDC, 0x83, 0xDB, 0x39, + 0x0F, 0x74, 0xA8, 0x5E, 0x43, 0x9C, 0x7B, 0x4A, + 0x78, 0x04, 0x87, 0x36, 0x3D, 0xFA, 0x27, 0x68, +/* 1024 */ + 0xD2, 0x20, 0x2E, 0x87, 0x42, 0xAF, 0x1F, 0x4E, + 0x53, 0x05, 0x9C, 0x60, 0x11, 0xBC, 0x33, 0x7B, + 0xCA, 0xB1, 0xBC, 0x91, 0x16, 0x88, 0x45, 0x8A, + 0x46, 0x0A, 0xBC, 0x72, 0x2F, 0x7C, 0x4E, 0x33, + 0xC6, 0xD5, 0xA8, 0xA3, 0x8B, 0xB7, 0xE9, 0xDC, + 0xCB, 0x2A, 0x63, 0x43, 0x31, 0xF3, 0xC8, 0x4D, + 0xF5, 0x2F, 0x12, 0x0F, 0x83, 0x6E, 0x58, 0x2E, + 0xEA, 0xA4, 0xA0, 0x89, 0x90, 0x40, 0xCA, 0x4A, +/* 2048 */ + 0x81, 0x39, 0x4A, 0xB6, 0xD8, 0xFD, 0x0E, 0xFD, + 0xF4, 0xD3, 0xA0, 0x2C, 0xEB, 0xC9, 0x3E, 0x0C, + 0x42, 0x64, 0xDA, 0xBC, 0xD5, 0x28, 0xB6, 0x51, + 0xB8, 0xCF, 0x34, 0x1B, 0x6F, 0x82, 0x36, 0xC7, + 0x01, 0x04, 0xDC, 0x01, 0xFE, 0x32, 0x35, 0x2F, + 0x33, 0x2A, 0x5E, 0x9F, 0x7B, 0xDA, 0x1E, 0xBF, + 0xF6, 0xA1, 0xBE, 0x3F, 0xCA, 0x22, 0x13, 0x07, + 0xDE, 0xA0, 0x62, 0x41, 0xF7, 0xAA, 0x81, 0xC2, +/* 3072 */ + 0xC1, 0xFC, 0xBD, 0xDE, 0xA2, 0xF7, 0xDC, 0x33, + 0x18, 0x83, 0x8A, 0x2E, 0xAF, 0xF5, 0xF3, 0xB2, + 0xD2, 0x4F, 0x4A, 0x76, 0x3F, 0xAC, 0xB8, 0x82, + 0xFD, 0xFE, 0x17, 0x0F, 0xD3, 0xB1, 0xF7, 0x80, + 0xF9, 0xAC, 0xCE, 0x41, 0x79, 0x7F, 0x28, 0x05, + 0xC2, 0x46, 0x78, 0x5E, 0x92, 0x95, 0x70, 0x23, + 0x5F, 0xCF, 0x8F, 0x7B, 0xCA, 0x3E, 0xA3, 0x3B, + 0x4D, 0x7C, 0x60, 0xA5, 0xE6, 0x33, 0xE3, 0xE1 +/* 4096 */ +}; + + +static INLINE int RsaSizeCheck(int size) +{ + switch (size) { +#ifndef HAVE_FIPS + case 1024: +#endif + case 2048: + case 3072: + case 4096: + return 1; + } + return 0; +} + + +static int wc_CheckProbablePrime_ex(mp_int* p, mp_int* q, mp_int* e, int nlen, + int* isPrime) +{ + int ret; + mp_int tmp1, tmp2; + mp_int* prime; + + if (p == NULL || e == NULL || isPrime == NULL) + return BAD_FUNC_ARG; + + if (!RsaSizeCheck(nlen)) + return BAD_FUNC_ARG; + + *isPrime = MP_NO; + + if (q != NULL) { + /* 5.4 - check that |p-q| <= (2^(1/2))(2^((nlen/2)-1)) */ + ret = wc_CompareDiffPQ(p, q, nlen); + if (ret != MP_OKAY) goto notOkay; + prime = q; + } + else + prime = p; + + ret = mp_init_multi(&tmp1, &tmp2, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) goto notOkay; + + /* 4.4,5.5 - Check that prime >= (2^(1/2))(2^((nlen/2)-1)) + * This is a comparison against lowerBound */ + ret = mp_read_unsigned_bin(&tmp1, lower_bound, nlen/16); + if (ret != MP_OKAY) goto notOkay; + ret = mp_cmp(prime, &tmp1); + if (ret == MP_LT) goto exit; + + /* 4.5,5.6 - Check that GCD(p-1, e) == 1 */ + ret = mp_sub_d(prime, 1, &tmp1); /* tmp1 = prime-1 */ + if (ret != MP_OKAY) goto notOkay; + ret = mp_gcd(&tmp1, e, &tmp2); /* tmp2 = gcd(prime-1, e) */ + if (ret != MP_OKAY) goto notOkay; + 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. */ + if (ret != MP_OKAY) goto notOkay; + +exit: + ret = MP_OKAY; +notOkay: + mp_clear(&tmp1); + mp_clear(&tmp2); + return ret; +} + + + +int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, + const byte* qRaw, word32 qRawSz, + const byte* eRaw, word32 eRawSz, + int nlen, int* isPrime) +{ + mp_int p, q, e; + mp_int* Q = NULL; + int ret; + + if (pRaw == NULL || pRawSz == 0 || + eRaw == NULL || eRawSz == 0 || + isPrime == NULL) { + + return BAD_FUNC_ARG; + } + + if ((qRaw != NULL && qRawSz == 0) || (qRaw == NULL && qRawSz != 0)) + return BAD_FUNC_ARG; + + ret = mp_init_multi(&p, &q, &e, NULL, NULL, NULL); + + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(&p, pRaw, pRawSz); + + if (ret == MP_OKAY) { + if (qRaw != NULL) { + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(&q, qRaw, qRawSz); + if (ret == MP_OKAY) + Q = &q; + } + } + + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(&e, eRaw, eRawSz); + + if (ret == MP_OKAY) + ret = wc_CheckProbablePrime_ex(&p, Q, &e, nlen, isPrime); + + ret = (ret == MP_OKAY) ? 0 : PRIME_GEN_E; + + mp_clear(&p); + mp_clear(&q); + mp_clear(&e); + + return ret; +} + + /* 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) { mp_int p, q, tmp1, tmp2, tmp3; - int err; + int err, i, failCount, primeSz, isPrime; + byte* buf = NULL; if (key == NULL || rng == NULL) return BAD_FUNC_ARG; - if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) + if (!RsaSizeCheck(size)) return BAD_FUNC_ARG; if (e < 3 || (e & 1) == 0) @@ -2130,35 +2335,87 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) } #endif - if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) - return err; + err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL); - err = mp_set_int(&tmp3, e); + if (err == MP_OKAY) + err = mp_set_int(&tmp3, e); + + failCount = 5 * (size / 2); + primeSz = size / 16; /* size is the size of n in bits. + primeSz is in bytes. */ + + /* allocate buffer to work with */ + if (err == MP_OKAY) { + buf = (byte*)XMALLOC(primeSz, key->heap, DYNAMIC_TYPE_RSA); + if (buf == NULL) + err = MEMORY_E; + } /* make p */ if (err == MP_OKAY) { + isPrime = 0; + i = 0; do { - err = mp_rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */ +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, primeSz); + + if (err == 0) { + /* prime lower bound has the MSB set, set it in candidate */ + buf[0] |= 0x80; + /* make candidate odd */ + buf[primeSz-1] |= 0x01; + /* load value */ + err = mp_read_unsigned_bin(&p, buf, primeSz); + } if (err == MP_OKAY) - err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */ + err = wc_CheckProbablePrime_ex(&p, NULL, &tmp3, size, &isPrime); - if (err == MP_OKAY) - err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */ - } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divides p-1 */ + i++; + } while (err == MP_OKAY && !isPrime && i < failCount); } + if (err == MP_OKAY && !isPrime) + err = PRIME_GEN_E; + /* make q */ if (err == MP_OKAY) { + isPrime = 0; + i = 0; do { - err = mp_rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */ +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, primeSz); + + if (err == 0) { + /* prime lower bound has the MSB set, set it in candidate */ + buf[0] |= 0x80; + /* make candidate odd */ + buf[primeSz-1] |= 0x01; + /* load value */ + err = mp_read_unsigned_bin(&q, buf, primeSz); + } if (err == MP_OKAY) - err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */ + err = wc_CheckProbablePrime_ex(&p, &q, &tmp3, size, &isPrime); - if (err == MP_OKAY) - err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */ - } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divides q-1 */ + i++; + } while (err == MP_OKAY && !isPrime && i < failCount); + } + + if (err == MP_OKAY && !isPrime) + err = PRIME_GEN_E; + + if (buf) { + ForceZero(buf, primeSz); + XFREE(buf, key->heap, DYNAMIC_TYPE_RSA); } if (err == MP_OKAY) @@ -2168,35 +2425,32 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL); if (err == MP_OKAY) - err = mp_sub_d(&p, 1, &tmp2); /* tmp2 = p-1 */ + err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */ if (err == MP_OKAY) - err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */ + err = mp_sub_d(&q, 1, &tmp2); /* tmp2 = q-1 */ + + if (err == MP_OKAY) + err = mp_lcm(&tmp1, &tmp2, &tmp3); /* tmp3 = lcm(p-1, q-1),last loop */ /* make key */ if (err == MP_OKAY) err = mp_set_int(&key->e, (mp_digit)e); /* key->e = e */ if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */ - err = mp_invmod(&key->e, &tmp1, &key->d); + err = mp_invmod(&key->e, &tmp3, &key->d); if (err == MP_OKAY) err = mp_mul(&p, &q, &key->n); /* key->n = pq */ if (err == MP_OKAY) - err = mp_sub_d(&p, 1, &tmp1); + err = mp_mod(&key->d, &tmp1, &key->dP); /* key->dP = d mod(p-1) */ if (err == MP_OKAY) - err = mp_sub_d(&q, 1, &tmp2); + err = mp_mod(&key->d, &tmp2, &key->dQ); /* key->dQ = d mod(q-1) */ if (err == MP_OKAY) - err = mp_mod(&key->d, &tmp1, &key->dP); - - if (err == MP_OKAY) - err = mp_mod(&key->d, &tmp2, &key->dQ); - - if (err == MP_OKAY) - err = mp_invmod(&q, &p, &key->u); + err = mp_invmod(&q, &p, &key->u); /* key->u = 1/q mod p */ if (err == MP_OKAY) err = mp_copy(&p, &key->p); @@ -2207,11 +2461,11 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (err == MP_OKAY) key->type = RSA_PRIVATE; - mp_clear(&tmp3); - mp_clear(&tmp2); mp_clear(&tmp1); - mp_clear(&q); + mp_clear(&tmp2); + mp_clear(&tmp3); mp_clear(&p); + mp_clear(&q); if (err != MP_OKAY) { wc_FreeRsaKey(key); diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 4f6066272..9ca0c1a2b 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -195,8 +195,9 @@ enum { WC_HW_WAIT_E = -249, /* Hardware waiting on resource */ PSS_SALTLEN_E = -250, /* PSS length of salt is to long for hash */ + PRIME_GEN_E = -251, /* Failure finding a prime. */ - WC_LAST_E = -250, /* Update this to indicate last error */ + WC_LAST_E = -251, /* Update this to indicate last error */ MIN_CODE_E = -300 /* errors -101 - -299 */ /* add new companion error id strings for any new error codes diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index ee5a70366..d56a7d136 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -226,6 +226,10 @@ WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, #ifdef WOLFSSL_KEY_GEN WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); + WOLFSSL_API int wc_CheckProbablePrime(const byte* p, word32 pSz, + const byte* q, word32 qSz, + const byte* e, word32 eSz, + int nlen, int* isPrime); #endif #endif /* HAVE_USER_RSA */ From a784142edfbd707157771b076029a8f82f5c0936 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 31 Oct 2017 13:30:06 -0700 Subject: [PATCH 3/8] RSA Update 1. Added FIPS wrappers for MakeRsaKey(), CheckProbablePrime(), and RsaFlattenPublicKey(). 2. Update the API test so that it used appropriate key and message sizes for the RSA testing. 3. Add function to get all parts of a flattened RSA key. --- cyassl/ctaocrypt/rsa.h | 1 + wolfcrypt/src/rsa.c | 91 +++++++++++++++++++++++++++++++++++++---- wolfcrypt/test/test.c | 8 +++- wolfssl/wolfcrypt/rsa.h | 6 +++ 4 files changed, 97 insertions(+), 9 deletions(-) diff --git a/cyassl/ctaocrypt/rsa.h b/cyassl/ctaocrypt/rsa.h index 5ad6fe0a3..03b8f034f 100644 --- a/cyassl/ctaocrypt/rsa.h +++ b/cyassl/ctaocrypt/rsa.h @@ -45,6 +45,7 @@ #ifdef WOLFSSL_KEY_GEN #define MakeRsaKey wc_MakeRsaKey #define RsaKeyToDer wc_RsaKeyToDer + #define CheckProbablePrime wc_CheckProbablePrime #endif #ifdef WOLFSSL_ASYNC_CRYPT diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 6de416ce6..08991da0e 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -147,17 +147,47 @@ int wc_RsaEncryptSize(RsaKey* key) } -int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, - word32* bSz) -{ +#ifndef WOLFSSL_KEY_GEN + int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, + word32* bSz) + { + + /* not specified as fips so not needing _fips */ + return RsaFlattenPublicKey(key, a, aSz, b, bSz); + } +#else + int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, + word32* bSz) + { + + /* not specified as fips so not needing _fips */ + return RsaFlattenPublicKey_fips(key, a, aSz, b, bSz); + } + + int wc_RsaExportKey(RsaKey* key, + byte* e, word32* eSz, byte* n, word32* nSz, + byte* d, word32* dSz, byte* p, word32* pSz, + byte* q, word32* qSz) + { + + /* not specified as fips so not needing _fips */ + return RsaExportKey_fips(key, e, eSz, n, nSz, d, dSz, p, pSz, q, qSz); + } + + int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, + const byte* qRaw, word32 qRawSz, + const byte* eRaw, word32 eRawSz, + int nlen, int* isPrime) + { + return CheckProbablePrime_fips(pRaw, pRawSz, + qRaw, qRawSz, + eRaw, eRawSz, + nlen, isPrime); + } - /* not specified as fips so not needing _fips */ - return RsaFlattenPublicKey(key, a, aSz, b, bSz); -} -#ifdef WOLFSSL_KEY_GEN int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) { - return MakeRsaKey(key, size, e, rng); + return MakeRsaKey_fips(key, size, e, rng); } #endif @@ -2095,6 +2125,51 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, return 0; } + +static int RsaGetValue(mp_int* in, byte* out, word32* outSz) +{ + word32 sz; + int ret = 0; + + sz = (word32)mp_unsigned_bin_size(in); + if (sz > *outSz) + ret = RSA_BUFFER_E; + + if (ret == 0) + ret = mp_to_unsigned_bin(in, out); + + if (ret == MP_OKAY) + *outSz = sz; + + return ret; +} + + +int wc_RsaExportKey(RsaKey* key, + byte* e, word32* eSz, byte* n, word32* nSz, + byte* d, word32* dSz, byte* p, word32* pSz, + byte* q, word32* qSz) +{ + int ret = BAD_FUNC_ARG; + + if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) + ret = 0; + + if (ret == 0) + ret = RsaGetValue(&key->e, e, eSz); + if (ret == 0) + ret = RsaGetValue(&key->n, n, nSz); + if (ret == 0) + ret = RsaGetValue(&key->d, d, dSz); + if (ret == 0) + ret = RsaGetValue(&key->p, p, pSz); + if (ret == 0) + ret = RsaGetValue(&key->q, q, qSz); + + return ret; +} + + #ifdef WOLFSSL_KEY_GEN /* Check that |p-q| > 2^((size/2)-100) */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index c1eb272ab..1731a6726 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8394,11 +8394,17 @@ int rsa_test(void) #ifdef WOLFSSL_KEY_GEN { int derSz = 0; + int keySz = 1024; + + #ifdef HAVE_FIPS + keySz = 2048; + #endif /* HAVE_FIPS */ + ret = wc_InitRsaKey(&genKey, HEAP_HINT); if (ret != 0) { ERROR_OUT(-5550, exit_rsa); } - ret = wc_MakeRsaKey(&genKey, 1024, WC_RSA_EXPONENT, &rng); + ret = wc_MakeRsaKey(&genKey, keySz, WC_RSA_EXPONENT, &rng); if (ret != 0) { ERROR_OUT(-5551, exit_rsa); } diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index d56a7d136..8749a9c8f 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -222,6 +222,12 @@ WOLFSSL_API int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, #endif /* HAVE_FIPS*/ WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, word32*); +WOLFSSL_API int wc_RsaExportKey(RsaKey* key, + byte* e, word32* eSz, + byte* n, word32* nSz, + byte* d, word32* dSz, + byte* p, word32* pSz, + byte* q, word32* qSz); #ifdef WOLFSSL_KEY_GEN WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); From 274c6ca492767e829590bd2504efc2f3c60cafdf Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 2 Nov 2017 16:56:49 -0700 Subject: [PATCH 4/8] RSA Update 1. Fix issue with new key gen options and using old FIPS releases. 2. Modify the FIPS configure option to handle an option for the updated FIPS. --- configure.ac | 7 ++++++- wolfcrypt/src/rsa.c | 36 +++++++++++++++++++++--------------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 5099ec39c..8e17c1823 100644 --- a/configure.ac +++ b/configure.ac @@ -1903,8 +1903,10 @@ AC_ARG_ENABLE([fips], [ ENABLED_FIPS=no ] ) -if test "x$ENABLED_FIPS" = "xyes" +if test "x$ENABLED_FIPS" != "xno" then + FIPS_VERSION=$ENABLED_FIPS + ENABLED_FIPS=yes # requires thread local storage if test "$thread_ls_on" = "no" then @@ -1930,6 +1932,9 @@ then ENABLED_DES3="yes" fi AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" + # Add the FIPS flag. + AS_IF([test "x$FIPS_VERSION" = "xv2"], + [AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS_VERSION=2"]) else if test "x$ENABLED_FORTRESS" = "xyes" then diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 08991da0e..a333f4636 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -147,20 +147,12 @@ int wc_RsaEncryptSize(RsaKey* key) } -#ifndef WOLFSSL_KEY_GEN +/* New FIPS functions. */ +#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, word32* bSz) { - - /* not specified as fips so not needing _fips */ - return RsaFlattenPublicKey(key, a, aSz, b, bSz); - } -#else - int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, - word32* bSz) - { - - /* not specified as fips so not needing _fips */ return RsaFlattenPublicKey_fips(key, a, aSz, b, bSz); } @@ -169,8 +161,6 @@ int wc_RsaEncryptSize(RsaKey* key) byte* d, word32* dSz, byte* p, word32* pSz, byte* q, word32* qSz) { - - /* not specified as fips so not needing _fips */ return RsaExportKey_fips(key, e, eSz, n, nSz, d, dSz, p, pSz, q, qSz); } @@ -189,6 +179,24 @@ int wc_RsaEncryptSize(RsaKey* key) { return MakeRsaKey_fips(key, size, e, rng); } + +#else /* Use old version of FIPS functions. */ + + int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, + word32* bSz) + { + + /* not specified as fips so not needing _fips */ + return RsaFlattenPublicKey(key, a, aSz, b, bSz); + } + + #ifdef WOLFSSL_KEY_GEN + int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) + { + return MakeRsaKey(key, size, e, rng); + } + #endif + #endif @@ -2256,9 +2264,7 @@ static const byte lower_bound[] = { static INLINE int RsaSizeCheck(int size) { switch (size) { -#ifndef HAVE_FIPS case 1024: -#endif case 2048: case 3072: case 4096: From 6fdbe02291806f65ed9e20f787176c263dc1a194 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 1 Dec 2017 11:45:16 -0800 Subject: [PATCH 5/8] ECC FIPS Add the ECC API to the FIPS boundary. Included are ECDHE and ECDSA. --- .gitignore | 2 ++ autogen.sh | 2 ++ configure.ac | 3 ++- src/include.am | 7 +++++++ wolfcrypt/src/ecc.c | 15 +++++++++++++-- wolfssl/wolfcrypt/ecc.h | 11 ++++++++++- wolfssl/wolfcrypt/include.am | 1 + 7 files changed, 37 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 43c0d5115..3139a29e6 100644 --- a/.gitignore +++ b/.gitignore @@ -38,7 +38,9 @@ tags cyassl-config wolfssl-config cyassl.sublime* +fips.h fips.c +fipsv2.c fips_test.c fips src/async.c diff --git a/autogen.sh b/autogen.sh index e5ea530fa..861a90509 100755 --- a/autogen.sh +++ b/autogen.sh @@ -18,6 +18,8 @@ if test -e .git; then # touch fips files for non fips distribution touch ./ctaocrypt/src/fips.c touch ./ctaocrypt/src/fips_test.c + touch ./wolfcrypt/src/fipsv2.c + touch ./wolfssl/wolfcrypt/fips.h # touch async crypt files touch ./wolfcrypt/src/async.c diff --git a/configure.ac b/configure.ac index 8e17c1823..d45cc9111 100644 --- a/configure.ac +++ b/configure.ac @@ -1934,7 +1934,8 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS" # Add the FIPS flag. AS_IF([test "x$FIPS_VERSION" = "xv2"], - [AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS_VERSION=2"]) + [AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS_VERSION=2 -DWOLFSSL_KEY_GEN" + ENABLED_KEYGEN="yes"]) else if test "x$ENABLED_FORTRESS" = "xyes" then diff --git a/src/include.am b/src/include.am index 125f60cf2..81f9c9faa 100644 --- a/src/include.am +++ b/src/include.am @@ -36,6 +36,10 @@ if BUILD_RSA src_libwolfssl_la_SOURCES += ctaocrypt/src/rsa.c endif +if BUILD_ECC +src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c +endif + if BUILD_AES src_libwolfssl_la_SOURCES += ctaocrypt/src/aes.c endif @@ -53,6 +57,7 @@ src_libwolfssl_la_SOURCES += ctaocrypt/src/sha512.c endif src_libwolfssl_la_SOURCES += ctaocrypt/src/fips.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/fipsv2.c src_libwolfssl_la_SOURCES += ctaocrypt/src/fips_test.c # fips last file @@ -218,9 +223,11 @@ if BUILD_SLOWMATH src_libwolfssl_la_SOURCES += wolfcrypt/src/integer.c endif +if !BUILD_FIPS if BUILD_ECC src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c endif +endif if BUILD_CURVE25519 src_libwolfssl_la_SOURCES += wolfcrypt/src/curve25519.c diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 01224cddf..1daa330bc 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -93,6 +93,16 @@ ECC Curve Sizes: #endif +#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$e2") + #pragma const_seg(".fipsB$e2") + #endif +#endif + #include #include #include @@ -3786,10 +3796,10 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, Free an ECC key from memory key The key you wish to free */ -void wc_ecc_free(ecc_key* key) +int wc_ecc_free(ecc_key* key) { if (key == NULL) { - return; + return 0; } #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) @@ -3808,6 +3818,7 @@ void wc_ecc_free(ecc_key* key) mp_forcezero(&key->k); #endif /* WOLFSSL_ATECC508A */ + return 0; } #ifdef ECC_SHAMIR diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index b11ddecc6..93506c5d3 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -27,6 +27,10 @@ #ifdef HAVE_ECC +#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + #include #include @@ -172,6 +176,8 @@ typedef enum ecc_curve_id { #endif } ecc_curve_id; +#if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2) + #ifdef HAVE_OID_ENCODING typedef word16 ecc_oid_t; #else @@ -198,6 +204,7 @@ typedef struct ecc_set_type { int cofactor; } ecc_set_type; +#endif #ifdef ALT_ECC_SIZE @@ -258,6 +265,7 @@ typedef struct alt_fp_int { #endif /* ALT_ECC_SIZE */ +#if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2) /* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ typedef struct { @@ -315,6 +323,7 @@ struct ecc_key { typedef struct ecc_key ecc_key; #define WC_ECCKEY_TYPE_DEFINED #endif +#endif /* ECC predefined curve sets */ @@ -387,7 +396,7 @@ int wc_ecc_init(ecc_key* key); WOLFSSL_API int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); WOLFSSL_API -void wc_ecc_free(ecc_key* key); +int wc_ecc_free(ecc_key* key); WOLFSSL_API int wc_ecc_set_flags(ecc_key* key, word32 flags); WOLFSSL_API diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index b03a51618..956ed84a1 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -20,6 +20,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/fe_operations.h \ wolfssl/wolfcrypt/ge_operations.h \ wolfssl/wolfcrypt/error-crypt.h \ + wolfssl/wolfcrypt/fips.h \ wolfssl/wolfcrypt/fips_test.h \ wolfssl/wolfcrypt/hash.h \ wolfssl/wolfcrypt/hc128.h \ From 788cc39498311a37951ecb4abf006317cadbd31f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 7 Dec 2017 10:58:55 -0800 Subject: [PATCH 6/8] FIPS Update 1. Switch in different versions of rsa.c depending on FIPS v1 or v2. 2. Add the Windows pragmas to rsa.c if building for FIPS v2. 3. Leave out FIPS wrappers from rsa.c if not building for FIPS v1. --- configure.ac | 1 + src/include.am | 6 ++++ wolfcrypt/src/rsa.c | 79 +++++++++++++++++---------------------------- 3 files changed, 37 insertions(+), 49 deletions(-) diff --git a/configure.ac b/configure.ac index d45cc9111..828b52c40 100644 --- a/configure.ac +++ b/configure.ac @@ -1944,6 +1944,7 @@ else fi AM_CONDITIONAL([BUILD_FIPS], [test "x$ENABLED_FIPS" = "xyes"]) +AM_CONDITIONAL([BUILD_FIPS_V2], [test "x$FIPS_VERSION" = "xv2"]) # set sha224 default diff --git a/src/include.am b/src/include.am index 81f9c9faa..c0f132d43 100644 --- a/src/include.am +++ b/src/include.am @@ -33,8 +33,12 @@ src_libwolfssl_la_SOURCES += \ ctaocrypt/src/sha256.c if BUILD_RSA +if BUILD_FIPS_V2 +src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c +else src_libwolfssl_la_SOURCES += ctaocrypt/src/rsa.c endif +endif if BUILD_ECC src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c @@ -92,10 +96,12 @@ if BUILD_RSA if BUILD_FAST_RSA src_libwolfssl_la_SOURCES += wolfcrypt/user-crypto/src/rsa.c else +if !BUILD_FIPS_V2 src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c endif endif endif +endif if BUILD_SP src_libwolfssl_la_SOURCES += wolfcrypt/src/sp.c endif diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index a333f4636..a53a36863 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -29,6 +29,18 @@ #ifndef NO_RSA +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$e") + #pragma const_seg(".fipsB$e") + #endif +#endif + #include #ifdef WOLFSSL_HAVE_SP_RSA @@ -54,7 +66,10 @@ RSA Key Size Configuration: */ -#ifdef HAVE_FIPS +/* If building for old FIPS. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + int wc_InitRsaKey(RsaKey* key, void* ptr) { if (key == NULL) { @@ -64,6 +79,7 @@ int wc_InitRsaKey(RsaKey* key, void* ptr) return InitRsaKey_fips(key, ptr); } + int wc_InitRsaKey_ex(RsaKey* key, void* ptr, int devId) { (void)devId; @@ -73,6 +89,7 @@ int wc_InitRsaKey_ex(RsaKey* key, void* ptr, int devId) return InitRsaKey_fips(key, ptr); } + int wc_FreeRsaKey(RsaKey* key) { return FreeRsaKey_fips(key); @@ -102,7 +119,7 @@ int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { - if (in == NULL || out == NULL || key == NULL) { + if (in == NULL || out == NULL || key == NULL) { return BAD_FUNC_ARG; } return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key); @@ -147,56 +164,20 @@ int wc_RsaEncryptSize(RsaKey* key) } -/* New FIPS functions. */ -#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, + word32* bSz) +{ - int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, - word32* bSz) - { - return RsaFlattenPublicKey_fips(key, a, aSz, b, bSz); - } + /* not specified as fips so not needing _fips */ + return RsaFlattenPublicKey(key, a, aSz, b, bSz); +} - int wc_RsaExportKey(RsaKey* key, - byte* e, word32* eSz, byte* n, word32* nSz, - byte* d, word32* dSz, byte* p, word32* pSz, - byte* q, word32* qSz) - { - return RsaExportKey_fips(key, e, eSz, n, nSz, d, dSz, p, pSz, q, qSz); - } - - int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, - const byte* qRaw, word32 qRawSz, - const byte* eRaw, word32 eRawSz, - int nlen, int* isPrime) - { - return CheckProbablePrime_fips(pRaw, pRawSz, - qRaw, qRawSz, - eRaw, eRawSz, - nlen, isPrime); - } - - int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) - { - return MakeRsaKey_fips(key, size, e, rng); - } - -#else /* Use old version of FIPS functions. */ - - int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, - word32* bSz) - { - - /* not specified as fips so not needing _fips */ - return RsaFlattenPublicKey(key, a, aSz, b, bSz); - } - - #ifdef WOLFSSL_KEY_GEN - int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) - { - return MakeRsaKey(key, size, e, rng); - } - #endif +#ifdef WOLFSSL_KEY_GEN + int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) + { + return MakeRsaKey(key, size, e, rng); + } #endif From d01d25598515feeed356d6dd94d8e5142def76e5 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 10 Jan 2018 09:26:22 -0800 Subject: [PATCH 7/8] FIPS Update 1. When configuring FIPSv2, force enable RSA-PSS and ECC. 2. Add more checks for FIPSv2 around the code. --- configure.ac | 11 ++++++++++- wolfcrypt/src/rsa.c | 2 +- wolfcrypt/test/test.c | 6 ++++-- wolfssl/wolfcrypt/asn.h | 3 ++- wolfssl/wolfcrypt/ecc.h | 5 ----- wolfssl/wolfcrypt/rsa.h | 16 ++++++++++++---- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/configure.ac b/configure.ac index 828b52c40..2185d022a 100644 --- a/configure.ac +++ b/configure.ac @@ -1935,7 +1935,16 @@ then # Add the FIPS flag. AS_IF([test "x$FIPS_VERSION" = "xv2"], [AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS_VERSION=2 -DWOLFSSL_KEY_GEN" - ENABLED_KEYGEN="yes"]) + ENABLED_KEYGEN="yes" + AS_IF([test "x$ENABLED_RSAPSS" != "xyes"], + [ENABLED_RSAPSS="yes" + AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS"]) + AS_IF([test "x$ENABLED_ECC" != "xyes"], + [ENABLED_ECC="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + AS_IF([test "x$ENABLED_ECC_SHAMIR" = "xyes"], + [AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR"])]) + ]) else if test "x$ENABLED_FORTRESS" = "xyes" then diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index a53a36863..cf7f7d3e8 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -186,7 +186,7 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, * wc_RsaPublicKeyDecode */ -#else /* else build without fips */ +#else /* else build without fips, or for new fips */ #include #include diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 1731a6726..0fdf7f388 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -7248,7 +7248,8 @@ static int rsa_flatten_test(RsaKey* key) * -101 = USER_CRYPTO_ERROR */ if (ret == 0) -#elif defined(HAVE_FIPS) +#elif defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) if (ret != 0) #else if (ret != RSA_BUFFER_E) @@ -8048,7 +8049,8 @@ int rsa_test(void) #ifndef WC_NO_RSA_OAEP /* OAEP padding testing */ #if !defined(HAVE_FAST_RSA) && !defined(HAVE_USER_RSA) && \ - !defined(HAVE_FIPS) + (!defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) #ifndef NO_SHA XMEMSET(plain, 0, plainSz); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 7a88482be..798a152bf 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -30,7 +30,8 @@ #include /* fips declare of RsaPrivateKeyDecode @wc_fips */ -#if defined(HAVE_FIPS) && !defined(NO_RSA) +#if defined(HAVE_FIPS) && !defined(NO_RSA) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) #include #endif diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 93506c5d3..9185b9f05 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -176,8 +176,6 @@ typedef enum ecc_curve_id { #endif } ecc_curve_id; -#if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2) - #ifdef HAVE_OID_ENCODING typedef word16 ecc_oid_t; #else @@ -204,7 +202,6 @@ typedef struct ecc_set_type { int cofactor; } ecc_set_type; -#endif #ifdef ALT_ECC_SIZE @@ -265,7 +262,6 @@ typedef struct alt_fp_int { #endif /* ALT_ECC_SIZE */ -#if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2) /* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ typedef struct { @@ -323,7 +319,6 @@ struct ecc_key { typedef struct ecc_key ecc_key; #define WC_ECCKEY_TYPE_DEFINED #endif -#endif /* ECC predefined curve sets */ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 8749a9c8f..47d6dc5ae 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -39,7 +39,8 @@ #include "user_rsa.h" #else -#ifdef HAVE_FIPS +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) /* for fips @wc_fips */ #include #if defined(CYASSL_KEY_GEN) && !defined(WOLFSSL_KEY_GEN) @@ -48,7 +49,11 @@ #else #include #include -#endif /* HAVE_FIPS */ +#endif /* HAVE_FIPS && HAVE_FIPS_VERION 1 */ +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#include +#endif /* header file needed for OAEP padding */ #include @@ -62,7 +67,8 @@ #endif /* avoid redefinition of structs */ -#if !defined(HAVE_FIPS) +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) #ifdef WOLFSSL_ASYNC_CRYPT #include @@ -180,7 +186,9 @@ WOLFSSL_API int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inLen, WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); -#ifndef HAVE_FIPS /* to avoid asn duplicate symbols @wc_fips */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +/* to avoid asn duplicate symbols @wc_fips */ WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, word32); WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, From 862e59f47429243a053db2674a9d2032fd75f01d Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 12 Jan 2018 15:37:22 -0800 Subject: [PATCH 8/8] FIPS Update 1. White space changes. Converting tabs to spaces. 2. Add some comments explaining where a loop bound came from. 3. Added parameter checks to a function. --- wolfcrypt/src/rsa.c | 28 ++++++++++++++++------------ wolfcrypt/test/test.c | 10 +++++----- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index cf7f7d3e8..1cfb23439 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -30,7 +30,7 @@ #ifndef NO_RSA #if defined(HAVE_FIPS) && \ - defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ #define FIPS_NO_WRAPPERS @@ -68,7 +68,7 @@ RSA Key Size Configuration: /* If building for old FIPS. */ #if defined(HAVE_FIPS) && \ - (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) int wc_InitRsaKey(RsaKey* key, void* ptr) { @@ -119,7 +119,7 @@ int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, RsaKey* key) { - if (in == NULL || out == NULL || key == NULL) { + if (in == NULL || out == NULL || key == NULL) { return BAD_FUNC_ARG; } return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key); @@ -165,19 +165,19 @@ int wc_RsaEncryptSize(RsaKey* key) int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, - word32* bSz) + word32* bSz) { - /* not specified as fips so not needing _fips */ - return RsaFlattenPublicKey(key, a, aSz, b, bSz); + /* not specified as fips so not needing _fips */ + return RsaFlattenPublicKey(key, a, aSz, b, bSz); } #ifdef WOLFSSL_KEY_GEN - int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) - { - return MakeRsaKey(key, size, e, rng); - } + int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) + { + return MakeRsaKey(key, size, e, rng); + } #endif @@ -2120,6 +2120,9 @@ static int RsaGetValue(mp_int* in, byte* out, word32* outSz) word32 sz; int ret = 0; + if (in == NULL || out == NULL || outSz == NULL) + return BAD_FUNC_ARG; + sz = (word32)mp_unsigned_bin_size(in); if (sz > *outSz) ret = RSA_BUFFER_E; @@ -2339,8 +2342,7 @@ int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, if (ret == MP_OKAY) { if (qRaw != NULL) { - if (ret == MP_OKAY) - ret = mp_read_unsigned_bin(&q, qRaw, qRawSz); + ret = mp_read_unsigned_bin(&q, qRaw, qRawSz); if (ret == MP_OKAY) Q = &q; } @@ -2402,6 +2404,8 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (err == MP_OKAY) err = mp_set_int(&tmp3, e); + /* The failCount value comes from NIST FIPS 186-4, section B.3.3, + * process steps 4.7 and 5.8. */ failCount = 5 * (size / 2); primeSz = size / 16; /* size is the size of n in bits. primeSz is in bytes. */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 0fdf7f388..d2fa26954 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -7249,7 +7249,7 @@ static int rsa_flatten_test(RsaKey* key) */ if (ret == 0) #elif defined(HAVE_FIPS) && \ - (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) if (ret != 0) #else if (ret != RSA_BUFFER_E) @@ -8396,11 +8396,11 @@ int rsa_test(void) #ifdef WOLFSSL_KEY_GEN { int derSz = 0; - int keySz = 1024; + int keySz = 1024; - #ifdef HAVE_FIPS - keySz = 2048; - #endif /* HAVE_FIPS */ + #ifdef HAVE_FIPS + keySz = 2048; + #endif /* HAVE_FIPS */ ret = wc_InitRsaKey(&genKey, HEAP_HINT); if (ret != 0) {