diff --git a/configure.ac b/configure.ac index 40edfa38a..31365d647 100644 --- a/configure.ac +++ b/configure.ac @@ -3046,7 +3046,7 @@ fi AS_CASE([$FIPS_VERSION], ["v5"], [ # FIPS 140-3 AM_CFLAGS="$AM_CFLAGS -DHAVE_FIPS -DHAVE_FIPS_VERSION=5 -DWOLFSSL_KEY_GEN -DWOLFSSL_SHA224 -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB -DHAVE_ECC_CDH -DWC_RSA_NO_PADDING" - ENABLED_KEYGEN="yes"; ENABLED_SHA224="yes"; ENABLED_DES3="no"; ENABLED=WOLFSSH="yes" + ENABLED_KEYGEN="yes"; ENABLED_SHA224="yes"; ENABLED_DES3="no" # Shake256 is a SHA-3 algorithm not in our FIPS algorithm list AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHAKE256" AS_IF([test "x$ENABLED_AESCCM" != "xyes"], @@ -6114,6 +6114,9 @@ AS_IF([test "x$ENABLED_NULL_CIPHER" = "xno" && \ [AM_CFLAGS="-DHAVE_NULL_CIPHER $AM_CFLAGS" ENABLED_NULL_CIPHER=yes]) +# FIPSv5 requires the wolfSSH option. +AS_IF([test "x$FIPS_VERSION" = "xv5"],[ENABLED_WOLFSSH="yes"]) + # wolfSSH and WPA Supplicant both need Public MP, only enable once. # This will let you know if you enabled wolfSSH but have any of the prereqs # disabled. Some of these options, disabling them adds things to the FLAGS and diff --git a/src/internal.c b/src/internal.c index 33b26b5bb..ffda943c2 100644 --- a/src/internal.c +++ b/src/internal.c @@ -22281,8 +22281,8 @@ static int GetDhPublicKey(WOLFSSL* ssl, const byte* input, word32 size, if (!wc_DhCmpNamedKey(group, 1, ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length, - NULL, 0, - ssl->buffers.serverDH_G.buffer, ssl->buffers.serverDH_G.length)) { + ssl->buffers.serverDH_G.buffer, ssl->buffers.serverDH_G.length, + NULL, 0)) { WOLFSSL_MSG("Server not using FFDHE parameters"); #ifdef WOLFSSL_REQUIRE_FFDHE SendAlert(ssl, alert_fatal, handshake_failure); @@ -24069,6 +24069,18 @@ int SendClientKeyExchange(WOLFSSL* ssl) goto exit_scke; } +#ifdef HAVE_FFDHE + if (ssl->namedGroup) { + ret = wc_DhSetNamedKey(ssl->buffers.serverDH_Key, + ssl->namedGroup); + if (ret != 0) { + goto exit_scke; + } + ssl->buffers.sig.length = + wc_DhGetNamedKeyMinSize(ssl->namedGroup); + } + else +#endif #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ !defined(WOLFSSL_OLD_PRIME_CHECK) if (ssl->options.dhDoKeyTest && @@ -24214,8 +24226,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) /* for DH, encSecret is Yc, agree is pre-master */ ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, - ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, - args->output + OPAQUE16_LEN, &args->length); + ssl->buffers.sig.buffer, + (word32*)&ssl->buffers.sig.length, + args->output + OPAQUE16_LEN, &args->length); break; } #endif /* !NO_DH && !NO_PSK */ @@ -26115,29 +26128,27 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Free'd in SSL_ResourceFree and * FreeHandshakeResources */ ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( - pSz + OPAQUE16_LEN, - ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_Pub.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - ssl->buffers.serverDH_Pub.length = - pSz + OPAQUE16_LEN; + ssl->buffers.serverDH_Pub.length = pSz; } + ssl->options.dhKeySz =(word16)pSz; + + pSz = wc_DhGetNamedKeyMinSize(ssl->namedGroup); + if (ssl->buffers.serverDH_Priv.buffer == NULL) { /* Free'd in SSL_ResourceFree and * FreeHandshakeResources */ ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( - pSz + OPAQUE16_LEN, - ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + pSz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); if (ssl->buffers.serverDH_Priv.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } - ssl->buffers.serverDH_Priv.length = - pSz + OPAQUE16_LEN; + ssl->buffers.serverDH_Priv.length = pSz; } - ssl->options.dhKeySz =(word16)pSz; - ret = AllocKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key); if (ret != 0) { @@ -26173,25 +26184,25 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->buffers.serverDH_Pub.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->buffers.serverDH_P.length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); if (ssl->buffers.serverDH_Pub.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } ssl->buffers.serverDH_Pub.length = - ssl->buffers.serverDH_P.length + OPAQUE16_LEN; + ssl->buffers.serverDH_P.length; } if (ssl->buffers.serverDH_Priv.buffer == NULL) { /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( - ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->buffers.serverDH_P.length, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); if (ssl->buffers.serverDH_Priv.buffer == NULL) { ERROR_OUT(MEMORY_E, exit_sske); } ssl->buffers.serverDH_Priv.length = - ssl->buffers.serverDH_P.length + OPAQUE16_LEN; + ssl->buffers.serverDH_P.length; } ssl->options.dhKeySz = diff --git a/src/tls.c b/src/tls.c index 4b3fb66e4..dc9f76974 100644 --- a/src/tls.c +++ b/src/tls.c @@ -6695,6 +6695,11 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) goto end; } /* Allocate space for the private key */ + keySz = wc_DhGetNamedKeyMinSize(kse->group); + if (keySz == 0) { + ret = WC_KEY_SIZE_E; + goto end; + } key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); if (key == NULL) { ret = MEMORY_E; diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 4644b4754..ca53e949d 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -939,6 +939,7 @@ int wc_InitDhKey_ex(DhKey* key, void* heap, int devId) return BAD_FUNC_ARG; key->heap = heap; /* for XMALLOC/XFREE in future */ + key->trustedGroup = 0; #ifdef WOLFSSL_DH_EXTRA if (mp_init_multi(&key->p, &key->g, &key->q, &key->pub, &key->priv, NULL) != MP_OKAY) @@ -1051,8 +1052,8 @@ static int CheckDhLN(int modLen, int divLen) /* Create DH private key * - * Based on NIST FIPS 186-4, - * "B.1.1 Key Pair Generation Using Extra Random Bits" + * Based on NIST SP 800-56Ar3 + * "5.6.1.1.3 Key Pair Generation Using Extra Random Bits" * * dh - pointer to initialized DhKey structure, needs to have dh->q * rng - pointer to initialized WC_RNG structure @@ -1091,7 +1092,7 @@ static int GeneratePrivateDh186(DhKey* key, WC_RNG* rng, byte* priv, } /* generate extra 64 bits so that bias from mod function is negligible */ - cSz = qSz + (64 / WOLFSSL_BIT_SIZE); + cSz = *privSz + (64 / WOLFSSL_BIT_SIZE); cBuf = (byte*)XMALLOC(cSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER); if (cBuf == NULL) { return MEMORY_E; @@ -1143,18 +1144,18 @@ static int GeneratePrivateDh186(DhKey* key, WC_RNG* rng, byte* priv, ForceZero(cBuf, cSz); XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - /* tmpQ = q - 1 */ + /* tmpQ: M = 2^N - 1 */ if (err == MP_OKAY) - err = mp_copy(&key->q, tmpQ); + err = mp_2expt(tmpQ, *privSz * 8); if (err == MP_OKAY) err = mp_sub_d(tmpQ, 1, tmpQ); - /* x = c mod (q-1), tmpX holds c */ + /* x = c mod (M), tmpX holds c */ if (err == MP_OKAY) err = mp_mod(tmpX, tmpQ, tmpX); - /* x = c mod (q-1) + 1 */ + /* x = c mod (M) + 1 */ if (err == MP_OKAY) err = mp_add_d(tmpX, 1, tmpX); @@ -1192,7 +1193,7 @@ static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv, #ifndef WOLFSSL_NO_DH186 if (mp_iszero(&key->q) == MP_NO) { - /* q param available, use NIST FIPS 186-4, "B.1.1 Key Pair + /* q param available, use NIST SP 800-56Ar3, "5.6.1.1.3 Key Pair * Generation Using Extra Random Bits" */ ret = GeneratePrivateDh186(key, rng, priv, privSz); @@ -1894,10 +1895,6 @@ int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); } - if (ret == 0) { - ret = wc_DhCheckKeyPair(key, pub, *pubSz, priv, *privSz); - } - return ret; } @@ -2368,7 +2365,7 @@ int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, const byte* g, 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); + return _DhSetKey(key, p, pSz, g, gSz, q, qSz, 0, NULL); } @@ -2376,6 +2373,7 @@ int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, word32 gSz) { + /* This should not have trusted set. */ return _DhSetKey(key, p, pSz, g, gSz, NULL, 0, 1, NULL); } @@ -2454,9 +2452,6 @@ int wc_DhSetNamedKey(DhKey* key, int name) return _DhSetKey(key, p, pSz, g, gSz, q, qSz, 1, NULL); } -#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 5) - #define HAVE_FIPS_V5 -#endif word32 wc_DhGetNamedKeyMinSize(int name) { @@ -2465,47 +2460,27 @@ word32 wc_DhGetNamedKeyMinSize(int name) switch (name) { #ifdef HAVE_FFDHE_2048 case WC_FFDHE_2048: - #ifndef HAVE_FIPS_V5 size = 29; - #else - size = 256; - #endif break; #endif /* HAVE_FFDHE_2048 */ #ifdef HAVE_FFDHE_3072 case WC_FFDHE_3072: - #ifndef HAVE_FIPS_V5 size = 34; - #else - size = 384; - #endif break; #endif /* HAVE_FFDHE_3072 */ #ifdef HAVE_FFDHE_4096 case WC_FFDHE_4096: - #ifndef HAVE_FIPS_V5 size = 39; - #else - size = 512; - #endif break; #endif /* HAVE_FFDHE_4096 */ #ifdef HAVE_FFDHE_6144 case WC_FFDHE_6144: - #ifndef HAVE_FIPS_V5 - size = 768; - #else - size = 256; - #endif + size = 46; break; #endif /* HAVE_FFDHE_6144 */ #ifdef HAVE_FFDHE_8192 case WC_FFDHE_8192: - #ifndef HAVE_FIPS_V5 size = 52; - #else - size = 1024; - #endif break; #endif /* HAVE_FFDHE_8192 */ default: @@ -2515,10 +2490,6 @@ word32 wc_DhGetNamedKeyMinSize(int name) return size; } -#ifdef HAVE_FIPS_V5 - #undef HAVE_FIPS_V5 -#endif - /* Returns 1: params match * 0: params differ */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index d2df02d5e..1d6e8acab 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -16048,8 +16048,8 @@ static int dh_fips_generate_test(WC_RNG *rng) 0xec, 0x24, 0x5d, 0x78, 0x59, 0xe7, 0x8d, 0xb5, 0x40, 0x52, 0xed, 0x41 }; - byte priv[256]; - byte pub[256]; + byte priv[sizeof q]; + byte pub[sizeof p]; word32 privSz = sizeof(priv); word32 pubSz = sizeof(pub); @@ -16368,8 +16368,8 @@ static int dh_ffdhe_test(WC_RNG *rng, int name) pubSz = FFDHE_KEY_SIZE; pubSz2 = FFDHE_KEY_SIZE; - privSz = FFDHE_KEY_SIZE; - privSz2 = FFDHE_KEY_SIZE; + privSz = wc_DhGetNamedKeyMinSize(name); + privSz2 = privSz; XMEMSET(key, 0, sizeof *key); XMEMSET(key2, 0, sizeof *key2);