mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 20:24:39 +02:00
Merge pull request #1311 from ejohnstown/rsakeygen
RSA Key Generation (FIPS 186-4)
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -38,7 +38,9 @@ tags
|
||||
cyassl-config
|
||||
wolfssl-config
|
||||
cyassl.sublime*
|
||||
fips.h
|
||||
fips.c
|
||||
fipsv2.c
|
||||
fips_test.c
|
||||
fips
|
||||
src/async.c
|
||||
|
@@ -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
|
||||
|
18
configure.ac
18
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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 <wolfssl/wolfcrypt/ecc.h>
|
||||
#include <wolfssl/wolfcrypt/asn.h>
|
||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
||||
@@ -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
|
||||
|
@@ -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";
|
||||
|
||||
|
@@ -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 <wolfssl/wolfcrypt/rsa.h>
|
||||
|
||||
#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 <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/logging.h>
|
||||
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -30,7 +30,8 @@
|
||||
#include <wolfssl/wolfcrypt/integer.h>
|
||||
|
||||
/* 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 <cyassl/ctaocrypt/rsa.h>
|
||||
#endif
|
||||
|
||||
|
@@ -27,6 +27,10 @@
|
||||
|
||||
#ifdef HAVE_ECC
|
||||
|
||||
#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
|
||||
#include <wolfssl/wolfcrypt/fips.h>
|
||||
#endif /* HAVE_FIPS_VERSION >= 2 */
|
||||
|
||||
#include <wolfssl/wolfcrypt/integer.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
|
||||
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 \
|
||||
|
@@ -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 <cyassl/ctaocrypt/rsa.h>
|
||||
#if defined(CYASSL_KEY_GEN) && !defined(WOLFSSL_KEY_GEN)
|
||||
@@ -48,7 +49,11 @@
|
||||
#else
|
||||
#include <wolfssl/wolfcrypt/integer.h>
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#endif /* HAVE_FIPS */
|
||||
#endif /* HAVE_FIPS && HAVE_FIPS_VERION 1 */
|
||||
#if defined(HAVE_FIPS) && \
|
||||
defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
|
||||
#include <wolfssl/wolfcrypt/fips.h>
|
||||
#endif
|
||||
|
||||
/* header file needed for OAEP padding */
|
||||
#include <wolfssl/wolfcrypt/hash.h>
|
||||
@@ -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 <wolfssl/wolfcrypt/async.h>
|
||||
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user