1. When enabling FIPSv5 in configure, enable WOLFSSL_WOLFSSH.
2. Appropriate size selection of DH private keys.
This commit is contained in:
John Safranek
2021-04-14 11:55:02 -07:00
parent 962c64a78d
commit 78ed928c8b
5 changed files with 54 additions and 64 deletions

View File

@ -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

View File

@ -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 =

View File

@ -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;

View File

@ -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 */

View File

@ -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);