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 22ef42453..78ce2de23 100644 --- a/configure.ac +++ b/configure.ac @@ -1917,8 +1917,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 @@ -1944,6 +1946,19 @@ 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 -DWOLFSSL_KEY_GEN" + 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 @@ -1952,6 +1967,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/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/src/include.am b/src/include.am index 125f60cf2..c0f132d43 100644 --- a/src/include.am +++ b/src/include.am @@ -33,8 +33,16 @@ 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 +endif if BUILD_AES src_libwolfssl_la_SOURCES += ctaocrypt/src/aes.c @@ -53,6 +61,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 @@ -87,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 @@ -218,9 +229,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/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 ebfec7b93..ab0860b89 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); @@ -154,6 +171,8 @@ int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, /* 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) { @@ -167,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 @@ -2099,17 +2118,267 @@ 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; + + 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; + + 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) */ +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) { + case 1024: + 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) { + 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) @@ -2134,35 +2403,89 @@ 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); + + /* 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. */ + + /* 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) @@ -2172,35 +2495,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); @@ -2211,11 +2531,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/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 98ec9b13f..b190fcf33 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); @@ -3394,6 +3400,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/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 173036857..7690fb88f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -7558,7 +7558,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) @@ -8358,7 +8359,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); @@ -8704,11 +8706,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/asn.h b/wolfssl/wolfcrypt/asn.h index 09a1d6e82..6101221ee 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 b11ddecc6..9185b9f05 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 @@ -387,7 +391,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/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/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 \ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index ee5a70366..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, @@ -222,10 +230,20 @@ 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); 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 */ diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index 205302050..5b165cbe8 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); @@ -736,6 +737,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);