diff --git a/tests/api.c b/tests/api.c index 32b90b9a07..3e59d42640 100644 --- a/tests/api.c +++ b/tests/api.c @@ -12610,12 +12610,7 @@ static int test_wolfSSL_tmp_dh(void) #endif static const unsigned char g[] = { 0x02 }; int gSz = (int)sizeof(g); -#if !defined(NO_DSA) - char file[] = "./certs/dsaparams.pem"; - DSA* dsa = NULL; -#else char file[] = "./certs/dh2048.pem"; -#endif XFILE f = XBADFILE; int bytes = 0; DH* dh = NULL; @@ -12657,14 +12652,7 @@ static int test_wolfSSL_tmp_dh(void) ExpectNotNull(bio = BIO_new_mem_buf((void*)buff, bytes)); -#if !defined(NO_DSA) - dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL); - ExpectNotNull(dsa); - - dh = wolfSSL_DSA_dup_DH(dsa); -#else dh = wolfSSL_PEM_read_bio_DHparams(bio, NULL, NULL, NULL); -#endif ExpectNotNull(dh); #if defined(WOLFSSL_DH_EXTRA) && \ (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) @@ -12750,9 +12738,6 @@ static int test_wolfSSL_tmp_dh(void) #endif BIO_free(bio); -#if !defined(NO_DSA) - DSA_free(dsa); -#endif DH_free(dh); dh = NULL; #ifndef NO_WOLFSSL_CLIENT @@ -20525,13 +20510,12 @@ static int test_wolfSSL_CTX_ctrl(void) char clientFile[] = "./certs/client-cert.pem"; SSL_CTX* ctx = NULL; X509* x509 = NULL; -#if !defined(NO_DH) && !defined(NO_DSA) && !defined(NO_BIO) +#if !defined(NO_DH) && !defined(NO_BIO) byte buf[6000]; - char file[] = "./certs/dsaparams.pem"; + char file[] = "./certs/dh2048.pem"; XFILE f = XBADFILE; int bytes = 0; BIO* bio = NULL; - DSA* dsa = NULL; DH* dh = NULL; #endif #ifdef HAVE_ECC @@ -20550,7 +20534,7 @@ static int test_wolfSSL_CTX_ctrl(void) ExpectNotNull(x509 = wolfSSL_X509_load_certificate_file(clientFile, WOLFSSL_FILETYPE_PEM)); -#if !defined(NO_DH) && !defined(NO_DSA) && !defined(NO_BIO) +#if !defined(NO_DH) && !defined(NO_BIO) /* Initialize DH */ ExpectTrue((f = XFOPEN(file, "rb")) != XBADFILE); ExpectIntGT(bytes = (int)XFREAD(buf, 1, sizeof(buf), f), 0); @@ -20559,9 +20543,7 @@ static int test_wolfSSL_CTX_ctrl(void) ExpectNotNull(bio = BIO_new_mem_buf((void*)buf, bytes)); - ExpectNotNull(dsa = wolfSSL_PEM_read_bio_DSAparams(bio, NULL, NULL, NULL)); - - ExpectNotNull(dh = wolfSSL_DSA_dup_DH(dsa)); + ExpectNotNull(dh = wolfSSL_PEM_read_bio_DHparams(bio, NULL, NULL, NULL)); #endif #ifdef HAVE_ECC /* Initialize WOLFSSL_EC_KEY */ @@ -20606,7 +20588,7 @@ static int test_wolfSSL_CTX_ctrl(void) /* Tests should fail with passed in NULL pointer */ ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); -#if !defined(NO_DH) && !defined(NO_DSA) +#if !defined(NO_DH) ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, NULL), WC_NO_ERR_TRACE(WOLFSSL_FAILURE)); #endif @@ -20634,7 +20616,7 @@ static int test_wolfSSL_CTX_ctrl(void) /* Test with SSL_CTRL_SET_TMP_DH * wolfSSL_CTX_ctrl should succesffuly call wolfSSL_SSL_CTX_set_tmp_dh */ -#if !defined(NO_DH) && !defined(NO_DSA) && !defined(NO_BIO) +#if !defined(NO_DH) && !defined(NO_BIO) ExpectIntEQ((int)wolfSSL_CTX_ctrl(ctx, SSL_CTRL_SET_TMP_DH, 0, dh), SSL_SUCCESS); #endif @@ -20674,14 +20656,11 @@ static int test_wolfSSL_CTX_ctrl(void) #endif #endif /* Cleanup and Pass */ -#if !defined(NO_DH) && !defined(NO_DSA) -#ifndef NO_BIO +#if !defined(NO_DH) && !defined(NO_BIO) BIO_free(bio); - DSA_free(dsa); DH_free(dh); dh = NULL; #endif -#endif #ifdef HAVE_ECC wolfSSL_EC_KEY_free(ecKey); #endif diff --git a/tests/api/test_dh.c b/tests/api/test_dh.c index 4b6c81c4a6..9a0b8a2988 100644 --- a/tests/api/test_dh.c +++ b/tests/api/test_dh.c @@ -84,7 +84,7 @@ int test_wc_DhAgree_subgroup_check(void) { EXPECT_DECLS; #if !defined(NO_DH) && !defined(WOLFSSL_SP_MATH) && !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || FIPS_VERSION3_GT(7,0,0)) + (!defined(HAVE_FIPS) || FIPS_VERSION3_GT(7,0,0)) && DH_MIN_SIZE <= 512 DhKey key; WC_RNG rng; byte agree[64]; diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 3e9abe3d86..86fa094493 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1259,6 +1259,12 @@ static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv, int ret = 0; word32 sz = 0; + /* reject primes below the minimum allowed size */ + if (mp_count_bits(&key->p) < DH_MIN_SIZE) { + WOLFSSL_MSG("DH prime smaller than DH_MIN_SIZE"); + return WC_KEY_SIZE_E; + } + if (mp_iseven(&key->p) == MP_YES) { ret = MP_VAL; } @@ -1344,6 +1350,12 @@ static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, return WC_KEY_SIZE_E; } + /* reject primes below the minimum allowed size */ + if (mp_count_bits(&key->p) < DH_MIN_SIZE) { + WOLFSSL_MSG("DH prime smaller than DH_MIN_SIZE"); + return WC_KEY_SIZE_E; + } + #ifdef WOLFSSL_HAVE_SP_DH #ifndef WOLFSSL_SP_NO_2048 if (mp_count_bits(&key->p) == 2048) @@ -2034,6 +2046,12 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, #endif #endif + /* reject primes below the minimum allowed size */ + if (mp_count_bits(&key->p) < DH_MIN_SIZE) { + WOLFSSL_MSG("DH prime smaller than DH_MIN_SIZE"); + return WC_KEY_SIZE_E; + } + if (mp_iseven(&key->p) == MP_YES) { return MP_VAL; } @@ -2362,6 +2380,10 @@ int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, #ifdef WOLFSSL_KCAPI_DH (void)priv; (void)privSz; + if (mp_count_bits(&key->p) < DH_MIN_SIZE) { + WOLFSSL_MSG("DH prime smaller than DH_MIN_SIZE"); + return WC_KEY_SIZE_E; + } ret = KcapiDh_SharedSecret(key, otherPub, pubSz, agree, agreeSz); #else #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 49deeaf0ce..4d4f92c697 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -29955,18 +29955,6 @@ static wc_test_ret_t dh_generate_test(WC_RNG *rng) #endif byte p[2] = { 1, 7 }; /* 263 in decimal */ byte g[2] = { 0, 2 }; -#if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_FFDHE) -#ifdef WOLFSSL_DH_CONST - /* the table for constant DH lookup will round to the lowest byte size 21 */ - byte priv[21]; - byte pub[21]; -#else - byte priv[2]; - byte pub[2]; -#endif - word32 privSz = sizeof(priv); - word32 pubSz = sizeof(pub); -#endif int smallKey_inited = 0; #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_NO_MALLOC) @@ -30009,20 +29997,12 @@ static wc_test_ret_t dh_generate_test(WC_RNG *rng) if (ret != 0) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_gen_test); -#if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_FFDHE) - /* Use API. */ - ret = wc_DhGenerateKeyPair(smallKey, rng, priv, &privSz, pub, &pubSz); -#if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_AsyncWait(ret, &smallKey->asyncDev, WC_ASYNC_FLAG_NONE); -#endif - if (ret != 0) { - ret = WC_TEST_RET_ENC_EC(ret); - } -#else + /* Generation with this sub-DH_MIN_SIZE prime is intentionally not + * exercised here; wc_DhGenerateKeyPair is covered with a valid group in + * dh_fips_generate_test. */ (void)rng; - #if defined(HAVE_FIPS) || !defined(WOLFSSL_NO_DH186) +#if defined(HAVE_FIPS) || !defined(WOLFSSL_NO_DH186) ret = 0; - #endif #endif #if !defined(HAVE_FIPS) && defined(WOLFSSL_NO_DH186) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 3cd37c739b..7508c5549a 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1231,10 +1231,8 @@ enum { #elif WOLFSSL_HARDEN_TLS >= 112 #define WOLFSSL_MIN_DHKEY_BITS 2048 #endif - #elif defined(WOLFSSL_MAX_STRENGTH) - #define WOLFSSL_MIN_DHKEY_BITS 2048 #else - #define WOLFSSL_MIN_DHKEY_BITS 1024 + #define WOLFSSL_MIN_DHKEY_BITS DH_MIN_SIZE #endif #endif #if defined(WOLFSSL_HARDEN_TLS) && WOLFSSL_MIN_DHKEY_BITS < 2048 && \ @@ -1252,6 +1250,12 @@ enum { #if (WOLFSSL_MIN_DHKEY_BITS > 16000) #error DH minimum bit size must not be greater than 16000 #endif +#if (WOLFSSL_MIN_DHKEY_BITS < DH_MIN_SIZE) + /* The TLS-layer minimum must not be looser than the wolfCrypt DH primitive + * minimum (DH_MIN_SIZE), otherwise a key size accepted during negotiation + * is later rejected by wc_DhAgree with WC_KEY_SIZE_E. */ + #error "WOLFSSL_MIN_DHKEY_BITS must be >= DH_MIN_SIZE" +#endif #define MIN_DHKEY_SZ (WOLFSSL_MIN_DHKEY_BITS / 8) /* set maximum DH key size allowed */ #ifndef WOLFSSL_MAX_DHKEY_BITS diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 9f69914584..f6c88e7b11 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -4626,6 +4626,20 @@ blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS." #endif #endif +/* Minimum allowed DH prime size in bits. SP 800-56A Rev3 / SP 800-131A + * disallow FFC below 2048 bits. Override to permit legacy sizes. */ +#ifndef DH_MIN_SIZE + #ifdef HAVE_FIPS + #define DH_MIN_SIZE 2048 + #elif defined(WOLFSSL_MIN_DHKEY_BITS) + /* For existing build settings that use WOLFSSL_MIN_DHKEY_BITS, map + * DH_MIN_SIZE to the user's desired minimum */ + #define DH_MIN_SIZE WOLFSSL_MIN_DHKEY_BITS + #else + #define DH_MIN_SIZE 1024 + #endif +#endif + /* wc_Sha512.devId isn't available before FIPS 5.1 */ #if defined(HAVE_FIPS) && FIPS_VERSION_LT(5,1) #define NO_SHA2_CRYPTO_CB