From 9e0e11fa7de95256f1a9fff79636dddb663c5b49 Mon Sep 17 00:00:00 2001 From: kaleb-himes Date: Fri, 27 Feb 2026 12:17:14 -0700 Subject: [PATCH] Phase 2: PQ in boundary and SHA512 DRBG Add rules to preserve module boundary in include.am Add HAVE_SELFTEST and rng_bank SHA512 awareness Fixed ML_KEM, SMALL_STACK tests, and avoidable internal SHA256-use for NSA 2.0 Fix windows ready and multi-test items Fix the --disable-rng build Fix RDSEED build failure Multi-test report fixes Updates after performance review Used asym_finish reporting for RNG's but we lose access when PSK only Continued updates to new benchmarks SHA512-DRBG default ENTROPY_SCALE_FACTOR on par with SHA256-DRBG one more benchmark item --- .wolfssl_known_macro_extras | 1 + IDE/WIN10/wolfssl-fips.vcxproj | 7 + configure.ac | 577 ++++++++--- doc/dox_comments/header_files/random.h | 238 +++++ src/include.am | 385 +++++++- tests/api.c | 2 - tests/api/test_mldsa.c | 24 + tests/api/test_mlkem.c | 8 + tests/api/test_random.c | 143 +++ tests/api/test_random.h | 4 +- wolfcrypt/benchmark/benchmark.c | 358 ++++++- wolfcrypt/benchmark/benchmark.h | 7 + wolfcrypt/src/dilithium.c | 32 + wolfcrypt/src/error.c | 21 + wolfcrypt/src/ext_mlkem.c | 6 + wolfcrypt/src/random.c | 1234 ++++++++++++++++++++++-- wolfcrypt/src/rng_bank.c | 38 +- wolfcrypt/src/wc_lms.c | 5 + wolfcrypt/src/wc_mlkem.c | 37 + wolfcrypt/src/wc_xmss.c | 5 + wolfcrypt/test/test.c | 198 +++- wolfssl/wolfcrypt/error-crypt.h | 15 +- wolfssl/wolfcrypt/fips_test.h | 7 +- wolfssl/wolfcrypt/random.h | 134 ++- 24 files changed, 3224 insertions(+), 262 deletions(-) diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index ea4c8eaaa93..c8c0139cad6 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -730,6 +730,7 @@ WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC WOLFSSL_DILITHIUM_SIGN_SMALL_MEM_PRECALC_A WOLFSSL_DILITHIUM_SMALL_MEM_POLY64 WOLFSSL_DISABLE_EARLY_SANITY_CHECKS +WOLFSSL_DRBG_SHA256 WOLFSSL_DTLS_DISALLOW_FUTURE WOLFSSL_DTLS_RECORDS_CAN_SPAN_DATAGRAMS WOLFSSL_DTLS_RESEND_ONLY_TIMEOUT diff --git a/IDE/WIN10/wolfssl-fips.vcxproj b/IDE/WIN10/wolfssl-fips.vcxproj index 42d574220fd..7f6afe63f3e 100644 --- a/IDE/WIN10/wolfssl-fips.vcxproj +++ b/IDE/WIN10/wolfssl-fips.vcxproj @@ -316,6 +316,13 @@ + + + + + + + diff --git a/configure.ac b/configure.ac index c3cbbb5be69..6ce9ca01d55 100644 --- a/configure.ac +++ b/configure.ac @@ -624,21 +624,31 @@ AS_CASE([$ENABLED_FIPS], DEF_SP_MATH="yes" DEF_FAST_MATH="no" ], + [v7],[ + FIPS_VERSION="v7" + HAVE_FIPS_VERSION=7 + HAVE_FIPS_VERSION_MAJOR=7 + HAVE_FIPS_VERSION_MINOR=0 + HAVE_FIPS_VERSION_PATCH=0 + ENABLED_FIPS="yes" + DEF_SP_MATH="yes" + DEF_FAST_MATH="no" + ], # Should always remain one ahead of the latest so as not to be confused with # the latest - [ready|v6-ready],[ + [ready|v7-ready],[ FIPS_VERSION="ready" - HAVE_FIPS_VERSION=7 - HAVE_FIPS_VERSION_MAJOR=7 + HAVE_FIPS_VERSION=8 + HAVE_FIPS_VERSION_MAJOR=8 HAVE_FIPS_VERSION_MINOR=0 HAVE_FIPS_VERSION_PATCH=0 ENABLED_FIPS="yes" DEF_SP_MATH="yes" DEF_FAST_MATH="no" ], - [dev|v6-dev],[ + [dev|v7-dev],[ FIPS_VERSION="dev" - HAVE_FIPS_VERSION_MAJOR=7 + HAVE_FIPS_VERSION_MAJOR=8 HAVE_FIPS_VERSION_MINOR=0 HAVE_FIPS_VERSION_PATCH=0 ENABLED_FIPS="yes" @@ -646,14 +656,14 @@ AS_CASE([$ENABLED_FIPS], ], [lean-aesgcm|lean-aesgcm-ready|lean-aesgcm-dev],[ FIPS_VERSION="$ENABLED_FIPS" - HAVE_FIPS_VERSION_MAJOR=7 + HAVE_FIPS_VERSION_MAJOR=8 HAVE_FIPS_VERSION_MINOR=0 HAVE_FIPS_VERSION_PATCH=0 ENABLED_FIPS="yes" ], [ AS_IF([test "$ENABLED_FIPS" = "yes"],[ENABLED_FIPS="(unset)"],[ENABLED_FIPS=\"$ENABLED_FIPS\"]) - AC_MSG_ERROR([Invalid value for --enable-fips $ENABLED_FIPS (main options: v1, v2, v5, v6, ready, dev, rand, lean-aesgcm, no, disabled)]) + AC_MSG_ERROR([Invalid value for --enable-fips $ENABLED_FIPS (main options: v1, v2, v5, v6, v7, ready, dev, rand, lean-aesgcm, no, disabled)]) ]) if test -z "$HAVE_FIPS_VERSION_MAJOR" @@ -1775,65 +1785,6 @@ do esac done -if test "$ENABLED_MLKEM" != "no" -then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_MLKEM" - # Use liboqs if specified. - if test "$ENABLED_LIBOQS" = "no"; then - ENABLED_WC_MLKEM=yes - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_MLKEM" - AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_WC_MLKEM" - fi - - if test "$ENABLED_ORIGINAL" = "yes"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_KYBER" - if test "$ENABLED_MLKEM512" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_KYBER512" - fi - if test "$ENABLED_MLKEM768" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_KYBER768" - fi - if test "$ENABLED_MLKEM1024" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_KYBER1024" - fi - if test "$ENABLED_ML_KEM" = "unset"; then - ENABLED_ML_KEM=no - fi - fi - if test "$ENABLED_ML_KEM" = "unset"; then - ENABLED_ML_KEM=yes - fi - if test "$ENABLED_ML_KEM" = "yes"; then - if test "$ENABLED_MLKEM512" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM_512" - fi - if test "$ENABLED_MLKEM768" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM_768" - fi - if test "$ENABLED_MLKEM1024" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM_1024" - fi - else - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM" - fi - if test "$ENABLED_MLKEM_MAKE_KEY" = "no"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_NO_MAKE_KEY" - fi - if test "$ENABLED_MLKEM_ENCAPSULATE" = "no"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_NO_ENCAPSULATE" - fi - if test "$ENABLED_MLKEM_DECAPSULATE" = "no"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_NO_DECAPSULATE" - fi - - if test "$ENABLED_WC_MLKEM" = "yes" - then - test "$enable_sha3" = "" && enable_sha3=yes - test "$enable_shake128" = "" && enable_shake128=yes - test "$enable_shake256" = "" && enable_shake256=yes - fi -fi - # Dilithium # - SHA3, Shake128, Shake256 and AES-CTR AC_ARG_ENABLE([mldsa], @@ -1905,39 +1856,6 @@ do esac done -if test "$ENABLED_DILITHIUM" != "no" -then - AM_CFLAGS="$AM_CFLAGS -DHAVE_DILITHIUM" - - if test "$ENABLED_MLDSA44" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_DSA_44" - fi - if test "$ENABLED_MLDSA65" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_DSA_65" - fi - if test "$ENABLED_MLDSA87" = ""; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_DSA_87" - fi - if test "$ENABLED_DILITHIUM_MAKE_KEY" = "no"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DILITHIUM_NO_MAKE_KEY" - fi - if test "$ENABLED_DILITHIUM_SIGN" = "no"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DILITHIUM_NO_SIGN" - fi - if test "$ENABLED_DILITHIUM_VERIFY" = "no"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DILITHIUM_NO_VERIFY" - fi - - if test "$ENABLED_LIBOQS" = "no"; then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_DILITHIUM" - AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_WC_DILITHIUM" - test "$enable_sha3" = "" && enable_sha3=yes - test "$enable_shake128" = "" && enable_shake128=yes - test "$enable_shake256" = "" && enable_shake256=yes - fi - ENABLED_CERTS=yes -fi - # XMSS ENABLED_WC_XMSS=no AC_ARG_ENABLE([xmss], @@ -2017,19 +1935,6 @@ AC_ARG_WITH([libxmss], [XMSS_ROOT=""] ) -if test "$ENABLED_XMSS" != "no" -then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_XMSS" - - # Use hash-sigs XMSS lib if enabled. - if test "$ENABLED_LIBXMSS" = "yes"; then - ENABLED_WC_XMSS=no - else - ENABLED_WC_XMSS=yes - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_XMSS" - fi -fi - # LMS ENABLED_WC_LMS=no AC_ARG_ENABLE([lms], @@ -2131,19 +2036,6 @@ AC_ARG_WITH([liblms], ] ) -if test "$ENABLED_LMS" != "no" -then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_LMS" - - # Use hash-sigs LMS lib if enabled. - if test "$ENABLED_LIBLMS" = "yes"; then - ENABLED_WC_LMS=no - else - ENABLED_WC_LMS=yes - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS" - fi -fi - # SINGLE THREADED AC_ARG_ENABLE([singlethreaded], [AS_HELP_STRING([--enable-singlethreaded],[Enable wolfSSL single threaded (default: disabled)])], @@ -4547,6 +4439,25 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512" fi +# SHA-256 Hash DRBG (SP 800-90A) -- sub-option of hashdrbg +AC_ARG_ENABLE([sha256-drbg], + [AS_HELP_STRING([--enable-sha256-drbg],[Enable SHA-256 Hash DRBG (default: enabled)])], + [ ENABLED_SHA256_DRBG=$enableval ], + [ ENABLED_SHA256_DRBG=yes ] + ) + +# SHA-512 Hash DRBG (SP 800-90A) -- sub-option of hashdrbg +AC_ARG_ENABLE([sha512-drbg], + [AS_HELP_STRING([--enable-sha512-drbg],[Enable SHA-512 Hash DRBG (default: enabled)])], + [ ENABLED_SHA512_DRBG=$enableval ], + [ ENABLED_SHA512_DRBG=yes ] + ) + +# SHA-512 DRBG requires SHA-512 +if test "$ENABLED_SHA512" != "yes" +then + ENABLED_SHA512_DRBG=no +fi # SHA384 AC_ARG_ENABLE([sha384], @@ -6031,11 +5942,11 @@ AC_ARG_ENABLE([aeskeywrap], # FIPS feature and macro setup AS_CASE([$FIPS_VERSION], - [v6|ready|dev],[ # FIPS 140-3 SRTP-KDF + [v7|ready|dev],[ # FIPS 140-3 PQ-FS AS_IF([test "$FIPS_VERSION" = "dev"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_FIPS_DEV"]) - AS_IF([test "$FIPS_VERSION" = "ready"], + AS_IF([test "$FIPS_VERSION" = "ready" || test "$FIPS_VERSION" = "v7"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_FIPS_READY"]) AM_CFLAGS="$AM_CFLAGS \ @@ -6212,6 +6123,228 @@ AS_CASE([$FIPS_VERSION], (test "$FIPS_VERSION" != "dev" || test "$enable_aeskeywrap" != "no")], [ENABLED_AESKEYWRAP="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP"]) +# Post-Quantum section + AS_IF([test "$ENABLED_MLKEM" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_mlkem" != "no")], + [ENABLED_MLKEM="yes" + ENABLED_MLKEM512="yes" + ENABLED_MLKEM768="yes" + ENABLED_MLKEM1024="yes" + ENABLED_MLKEM_MAKE_KEY="yes" + ENABLED_MLKEM_ENCAPSULATE="yes" + ENABLED_MLKEM_DECAPSULATE="yes"]) + + AS_IF([test "$ENABLED_DILITHIUM" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_dilithium" != "no")], + [ENABLED_DILITHIUM="yes" + ENABLED_MLDSA44="yes" + ENABLED_MLDSA65="yes" + ENABLED_MLDSA87="yes" + ENABLED_DILITHIUM_MAKE_KEY="yes" + ENABLED_DILITHIUM_SIGN="yes" + ENABLED_DILITHIUM_VERIFY="yes"]) + + AS_IF([test "$ENABLED_XMSS" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_xmss" != "no")], + [ENABLED_XMSS="yes"]) + + AS_IF([test "$ENABLED_LMS" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_lms" != "no")], + [ENABLED_LMS="yes"]) + +# SHA-256 DRBG -- cannot be disabled at build time in FIPS mode + AS_IF([test "$enable_sha256_drbg" = "no"], + [AC_MSG_WARN([Can not disable SHA256-DRBG at build time in FIPS mode, disable at run-time with wc_Sha256Drbg_Disable() or wc_Sha256Drbg_Disable_fips()])]) + ENABLED_SHA256_DRBG="yes" + +# SHA-512 DRBG -- cannot be disabled at build time in FIPS mode + AS_IF([test "$enable_sha512_drbg" = "no"], + [AC_MSG_WARN([Can not disable SHA512-DRBG at build time in FIPS mode, disable it at run-time with wc_Sha512Drbg_Disable() or wc_Sha512Drbg_Disable_fips()])]) + ENABLED_SHA512_DRBG="yes" + +# Old TLS requires MD5 + HMAC, which is not allowed under FIPS 140-3 + AS_IF([test "$ENABLED_OLD_TLS" != "no"], + [AC_MSG_WARN([Forcing off oldtls for FIPS ${FIPS_VERSION}.]) + ENABLED_OLD_TLS="no"; AM_CFLAGS="$AM_CFLAGS -DNO_OLD_TLS"]) + + ], + + [v6],[ # FIPS 140-3 SRTP-KDF (frozen) + + AM_CFLAGS="$AM_CFLAGS \ + -DHAVE_FIPS \ + -DHAVE_FIPS_VERSION=$HAVE_FIPS_VERSION \ + -DHAVE_FIPS_VERSION_MAJOR=$HAVE_FIPS_VERSION_MAJOR \ + -DHAVE_FIPS_VERSION_MINOR=$HAVE_FIPS_VERSION_MINOR \ + -DHAVE_FIPS_VERSION_PATCH=$HAVE_FIPS_VERSION_PATCH \ + -DHAVE_ECC_CDH \ + -DWC_RSA_NO_PADDING \ + -DECC_USER_CURVES \ + -DHAVE_ECC384 \ + -DHAVE_ECC521 \ + -DWOLFSSL_VALIDATE_FFC_IMPORT \ + -DHAVE_FFDHE_Q \ + -DHAVE_FFDHE_3072 \ + -DHAVE_FFDHE_4096 \ + -DHAVE_FFDHE_6144 \ + -DHAVE_FFDHE_8192" + + # KCAPI API does not support custom k for sign, don't force enable ECC key sizes and don't use seed callback + AS_IF([test "x$ENABLED_KCAPI_ECC" = "xno"], + [AM_CFLAGS="$AM_CFLAGS \ + -DWC_RNG_SEED_CB \ + -DWOLFSSL_ECDSA_SET_K \ + -DWOLFSSL_VALIDATE_ECC_IMPORT \ + -DWOLFSSL_VALIDATE_ECC_KEYGEN \ + -DHAVE_ECC192 \ + -DHAVE_ECC224 \ + -DHAVE_ECC256"]) + + DEFAULT_MAX_CLASSIC_ASYM_KEY_BITS=8192 +# optimizations section + +# protocol section + AS_IF([test "$ENABLED_WOLFSSH" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_ssh" != "no")], + [enable_ssh="yes"]) + + AS_IF([test "$ENABLED_HKDF" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_hkdf" != "no")], + [ENABLED_HKDF="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF"]) + + AS_IF([test "x$ENABLED_PWDBASED" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_pwdbased" != "no")], + [ENABLED_PWDBASED="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_PBKDF2 -DHAVE_AESGCM"]) + + AS_IF([test "x$ENABLED_SRTP" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_srtp" != "no")], + [ENABLED_SRTP="yes"]) + AS_IF([test "x$ENABLED_SRTP_KDF" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_srtp_kdf" != "no")], + [ENABLED_SRTP_KDF="yes"]) + +# public key section + AS_IF([test "$ENABLED_KEYGEN" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_keygen" != "no")], + [ENABLED_KEYGEN="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KEY_GEN"]) + +# AS_IF([test "$ENABLED_COMPKEY" != "yes" && +# (test "$FIPS_VERSION" != "dev" || test "$enable_compkey" != "yes")], +# [ENABLED_COMPKEY="yes"]) + + AS_IF([test "$ENABLED_RSAPSS" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_rsapss" != "no")], + [ENABLED_RSAPSS="yes"; AM_CFLAGS="$AM_CFLAGS -DWC_RSA_PSS"]) + + AS_IF([test "$ENABLED_ECC" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_ecc" != "no")], + [ENABLED_ECC="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ECC -DTFM_ECC256" + AS_IF([test "$ENABLED_ECC_SHAMIR" = "yes"], + [AM_CFLAGS="$AM_CFLAGS -DECC_SHAMIR"])]) + + AS_IF([test "$ENABLED_ED25519" = "no" && + (test "$FIPS_VERSION" != "dev" || test "$enable_ed25519" != "no")], + [ENABLED_ED25519="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ED25519 -DHAVE_ED25519_KEY_IMPORT"]) + + AS_IF([test "$ENABLED_CURVE25519" != "no" && + (test "$FIPS_VERSION" != "dev" || test "$enable_curve25519" = "")], + [ENABLED_CURVE25519="no"; AM_CFLAGS="$AM_CFLAGS"]) + + AS_IF([test "x$ENABLED_ED448" != "xyes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_ed448" != "no")], + [ENABLED_ED448="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_ED448 -DHAVE_ED448_KEY_IMPORT"]) + + AS_IF([test "$ENABLED_CURVE448" != "no" && + (test "$FIPS_VERSION" != "dev" || test "$enable_curve448" = "")], + [ENABLED_CURVE448="no"; AM_CFLAGS="$AM_CFLAGS"]) + + AS_IF([test "x$ENABLED_ED25519_STREAM" != "xyes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_ed25519_stream" != "no")], + [ENABLED_ED25519_STREAM="yes"]) + AS_IF([test "x$ENABLED_ED448_STREAM" != "xyes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_ed448_stream" != "no")], + [ENABLED_ED448_STREAM="yes"]) + + AS_IF([test "x$ENABLED_ECCCUSTCURVES" != "xno" && + test "$FIPS_VERSION" != "dev"], + [AC_MSG_WARN([Forcing off ecccustcurves for FIPS ${FIPS_VERSION}.]) + ENABLED_ECCCUSTCURVES="no"]) + +# Hashing section + AS_IF([test "x$ENABLED_SHA3" != "xyes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_sha3" != "no")], + [ENABLED_SHA3="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA3"]) + + AS_IF([test "$ENABLED_SHA224" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_sha224" != "no")], + [ENABLED_SHA224="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA224"]) + + AS_IF([test "$ENABLED_SHA512" = "no" && + (test "$FIPS_VERSION" != "dev" || test "$enable_sha512" != "no")], + [ENABLED_SHA512="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SHA512 -DWOLFSSL_SHA384"]) + + # SHA512-224 and SHA512-256 are SHA-2 algorithms not in our FIPS algorithm list + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NOSHA512_224 -DWOLFSSL_NOSHA512_256" + + # Shake128 because we're testing SHAKE256 + AS_IF([test "x$ENABLED_SHAKE128" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_shake128" != "no")], + [ENABLED_SHAKE128="yes"]) + + # Shake256 mandated for ED448 + AS_IF([test "x$ENABLED_SHAKE256" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_shake256" != "no")], + [ENABLED_SHAKE256="yes"]) + +# Aes section + AS_IF([test "$ENABLED_AESCCM" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aesccm" != "no")], + [ENABLED_AESCCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESCCM"]) + + AS_IF([test "$ENABLED_AESCTR" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aesctr" != "no")], + [ENABLED_AESCTR="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_COUNTER"]) + + AS_IF([test "$ENABLED_CMAC" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_cmac" != "no")], + [ENABLED_CMAC="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CMAC"]) + + AS_IF([test "$ENABLED_AESGCM" = "no" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aesgcm" != "no")], + [ENABLED_AESGCM="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AESGCM"; AM_CCASFLAGS="$AM_CCASFLAGS -DHAVE_AESGCM"]) + + AS_IF([test "$ENABLED_AESGCM_STREAM" != "yes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aesgcm_stream" != "no")], + [ENABLED_AESGCM_STREAM="yes"]) + + AS_IF([test "x$ENABLED_AESOFB" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aesofb" != "no")], + [ENABLED_AESOFB="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_OFB"]) + + AS_IF([test "x$ENABLED_AESCFB" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aescfb" != "no")], + [ENABLED_AESCFB="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_CFB"]) + + AS_IF([test "x$ENABLED_AESXTS" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aesxts" != "no")], + [ENABLED_AESXTS="yes"; AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_XTS"]) + AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_AESNI" = "xyes"], + [AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_AES_XTS"]) + + AS_IF([test "x$ENABLED_AESXTS_STREAM" = "xno" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aesxts_stream" != "no")], + [ENABLED_AESXTS_STREAM="yes"]) + + AS_IF([(test "$ENABLED_AESCCM" != "no" && test "$HAVE_AESCCM_PORT" != "yes") || + (test "$ENABLED_AESCTR" != "no" && test "$HAVE_AESCTR_PORT" != "yes") || + (test "$ENABLED_AESGCM" != "no" && test "$HAVE_AESGCM_PORT" != "yes") || + (test "$ENABLED_AESOFB" != "no" && test "$HAVE_AESOFB_PORT" != "yes")], + [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT -DHAVE_AES_ECB"]) + + AS_IF([test "x$ENABLED_AESKEYWRAP" != "xyes" && + (test "$FIPS_VERSION" != "dev" || test "$enable_aeskeywrap" != "no")], + [ENABLED_AESKEYWRAP="yes"; AM_CFLAGS="$AM_CFLAGS -DHAVE_AES_KEYWRAP"]) + # Old TLS requires MD5 + HMAC, which is not allowed under FIPS 140-3 AS_IF([test "$ENABLED_OLD_TLS" != "no"], [AC_MSG_WARN([Forcing off oldtls for FIPS ${FIPS_VERSION}.]) @@ -6696,6 +6829,11 @@ AS_CASE([$SELFTEST_VERSION], AM_CFLAGS="$AM_CFLAGS -DHAVE_SELFTEST -DHAVE_PUBLIC_FFDHE" ]) +# Selftest uses its own random.c which doesn't support SHA-512 DRBG +# or runtime DRBG disable/enable APIs +AS_IF([test "x$ENABLED_SELFTEST" = "xyes"], + [ENABLED_SHA512_DRBG=no]) + AS_IF([test "x$ENABLED_AESXTS" = "xyes"], [AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_XTS -DWOLFSSL_AES_DIRECT"]) AS_IF([test "x$ENABLED_AESXTS" = "xyes" && test "x$ENABLED_INTELASM" = "xyes"], @@ -6801,6 +6939,21 @@ then AM_CFLAGS="$AM_CFLAGS -DWC_SRTP_KDF -DHAVE_AES_ECB -DWOLFSSL_AES_DIRECT" fi +# ML-KEM and Dilithium require SHA-3 and SHAKE -- force them on before flag +# processing so that the correct -D flags are emitted. +if test "$ENABLED_MLKEM" != "no" && test "$ENABLED_LIBOQS" = "no" +then + ENABLED_SHA3=yes + ENABLED_SHAKE128=yes + ENABLED_SHAKE256=yes +fi +if test "$ENABLED_DILITHIUM" != "no" && test "$ENABLED_LIBOQS" = "no" +then + ENABLED_SHA3=yes + ENABLED_SHAKE128=yes + ENABLED_SHAKE256=yes +fi + # Set SHA-3 flags if test "$ENABLED_SHA3" != "no" then @@ -6839,6 +6992,128 @@ else AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHAKE256" fi +# MLKEM CFLAG processing (after FIPS section for sandwich pattern) +if test "$ENABLED_MLKEM" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_MLKEM" + # Use liboqs if specified. + if test "$ENABLED_LIBOQS" = "no"; then + ENABLED_WC_MLKEM=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_MLKEM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_WC_MLKEM" + fi + + if test "$ENABLED_ORIGINAL" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_KYBER" + if test "$ENABLED_MLKEM512" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_KYBER512" + fi + if test "$ENABLED_MLKEM768" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_KYBER768" + fi + if test "$ENABLED_MLKEM1024" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_KYBER1024" + fi + if test "$ENABLED_ML_KEM" = "unset"; then + ENABLED_ML_KEM=no + fi + fi + if test "$ENABLED_ML_KEM" = "unset"; then + ENABLED_ML_KEM=yes + fi + if test "$ENABLED_ML_KEM" = "yes"; then + if test "$ENABLED_MLKEM512" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM_512" + fi + if test "$ENABLED_MLKEM768" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM_768" + fi + if test "$ENABLED_MLKEM1024" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM_1024" + fi + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM" + fi + if test "$ENABLED_MLKEM_MAKE_KEY" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_NO_MAKE_KEY" + fi + if test "$ENABLED_MLKEM_ENCAPSULATE" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_NO_ENCAPSULATE" + fi + if test "$ENABLED_MLKEM_DECAPSULATE" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_NO_DECAPSULATE" + fi + + if test "$ENABLED_WC_MLKEM" = "yes" + then + test "$enable_sha3" = "" && enable_sha3=yes + test "$enable_shake128" = "" && enable_shake128=yes + test "$enable_shake256" = "" && enable_shake256=yes + fi +fi + +# Dilithium CFLAG processing (after FIPS section for sandwich pattern) +if test "$ENABLED_DILITHIUM" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_DILITHIUM" + + if test "$ENABLED_MLDSA44" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_DSA_44" + fi + if test "$ENABLED_MLDSA65" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_DSA_65" + fi + if test "$ENABLED_MLDSA87" = ""; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_DSA_87" + fi + if test "$ENABLED_DILITHIUM_MAKE_KEY" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DILITHIUM_NO_MAKE_KEY" + fi + if test "$ENABLED_DILITHIUM_SIGN" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DILITHIUM_NO_SIGN" + fi + if test "$ENABLED_DILITHIUM_VERIFY" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DILITHIUM_NO_VERIFY" + fi + + if test "$ENABLED_LIBOQS" = "no"; then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_DILITHIUM" + AM_CCASFLAGS="$AM_CCASFLAGS -DWOLFSSL_WC_DILITHIUM" + test "$enable_sha3" = "" && enable_sha3=yes + test "$enable_shake128" = "" && enable_shake128=yes + test "$enable_shake256" = "" && enable_shake256=yes + fi + ENABLED_CERTS=yes +fi + +# XMSS CFLAG processing (after FIPS section for sandwich pattern) +if test "$ENABLED_XMSS" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_XMSS" + + # Use hash-sigs XMSS lib if enabled. + if test "$ENABLED_LIBXMSS" = "yes"; then + ENABLED_WC_XMSS=no + else + ENABLED_WC_XMSS=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_XMSS" + fi +fi + +# LMS CFLAG processing (after FIPS section for sandwich pattern) +if test "$ENABLED_LMS" != "no" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_HAVE_LMS" + + # Use hash-sigs LMS lib if enabled. + if test "$ENABLED_LIBLMS" = "yes"; then + ENABLED_WC_LMS=no + else + ENABLED_WC_LMS=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_LMS" + fi +fi + # set POLY1305 default POLY1305_DEFAULT=yes @@ -6927,27 +7202,55 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_ASCON" fi -# Hash DRBG +# Hash DRBG (master switch for all Hash DRBGs) AC_ARG_ENABLE([hashdrbg], [AS_HELP_STRING([--enable-hashdrbg],[Enable Hash DRBG support (default: enabled)])], [ ENABLED_HASHDRBG=$enableval ], [ ENABLED_HASHDRBG=yes ] ) +# If hashdrbg is explicitly disabled, force both sub-options off +if test "x$ENABLED_HASHDRBG" = "xno" +then + ENABLED_SHA256_DRBG=no + ENABLED_SHA512_DRBG=no +fi + +# If both sub-options are off, treat hashdrbg as off +if test "x$ENABLED_SHA256_DRBG" != "xyes" && test "x$ENABLED_SHA512_DRBG" != "xyes" +then + ENABLED_HASHDRBG=no +fi + +# FIPS override: Hash DRBG is mandatory +if test "x$ENABLED_HASHDRBG" != "xyes" && test "x$ENABLED_FIPS" = "xyes" && test "x$ENABLED_KCAPI" = "xno" +then + if test "$enable_hashdrbg" = "no" + then + AC_MSG_WARN([SHA256-DRBG and SHA512-DRBG required in FIPS build, may be disabled at run-time with wc_Sha256Drbg_Disable_fips() or wc_Sha512Drbg_Disable_fips()]) + fi + ENABLED_HASHDRBG=yes + ENABLED_SHA256_DRBG=yes + ENABLED_SHA512_DRBG=yes +fi + +# Set Hash DRBG compiler flags if test "x$ENABLED_HASHDRBG" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" -else - # turn on Hash DRBG if FIPS is on (don't force on for KCAPI) - if test "x$ENABLED_FIPS" = "xyes" && test "x$ENABLED_KCAPI" = "xno" + if test "x$ENABLED_SHA256_DRBG" != "xyes" then - AM_CFLAGS="$AM_CFLAGS -DHAVE_HASHDRBG" - ENABLED_HASHDRBG=yes - else - AM_CFLAGS="$AM_CFLAGS -DWC_NO_HASHDRBG" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_SHA256_DRBG" fi + if test "x$ENABLED_SHA512_DRBG" = "xyes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DRBG_SHA512" + fi +else + AM_CFLAGS="$AM_CFLAGS -DWC_NO_HASHDRBG" fi + # MemUse Entropy (AKA wolfEntropy) if test "x$ENABLED_ENTROPY_MEMUSE" != "xno" then @@ -11250,6 +11553,8 @@ AM_CONDITIONAL([BUILD_FIPS_V5],[test "$HAVE_FIPS_VERSION" = 5]) AM_CONDITIONAL([BUILD_FIPS_V5_PLUS],[test "$HAVE_FIPS_VERSION" -ge 5]) AM_CONDITIONAL([BUILD_FIPS_V6],[test $HAVE_FIPS_VERSION = 6]) AM_CONDITIONAL([BUILD_FIPS_V6_PLUS],[test $HAVE_FIPS_VERSION -ge 6]) +AM_CONDITIONAL([BUILD_FIPS_V7],[test $HAVE_FIPS_VERSION = 7]) +AM_CONDITIONAL([BUILD_FIPS_V7_PLUS],[test $HAVE_FIPS_VERSION -ge 7]) AM_CONDITIONAL([BUILD_SIPHASH],[test "x$ENABLED_SIPHASH" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_CMAC],[test "x$ENABLED_CMAC" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"]) AM_CONDITIONAL([BUILD_SELFTEST],[test "x$ENABLED_SELFTEST" = "xyes"]) @@ -11736,6 +12041,8 @@ echo " * certgencache: $ENABLED_certgencache" echo " * CHACHA: $ENABLED_CHACHA" echo " * XCHACHA: $ENABLED_XCHACHA" echo " * Hash DRBG: $ENABLED_HASHDRBG" +echo " * SHA-256 Hash DRBG: $ENABLED_SHA256_DRBG" +echo " * SHA-512 Hash DRBG: $ENABLED_SHA512_DRBG" echo " * MmemUse Entropy:" echo " * (AKA: wolfEntropy): $ENABLED_ENTROPY_MEMUSE" echo " * PWDBASED: $ENABLED_PWDBASED" diff --git a/doc/dox_comments/header_files/random.h b/doc/dox_comments/header_files/random.h index ead9011d468..f6961b99427 100644 --- a/doc/dox_comments/header_files/random.h +++ b/doc/dox_comments/header_files/random.h @@ -583,3 +583,241 @@ int wc_Entropy_Get(int bits, unsigned char* entropy, word32 len); \sa wc_Entropy_Get */ int wc_Entropy_OnDemandTest(void); + +/*! + \ingroup Random + + \brief Runs the SHA-512 Hash_DRBG Known Answer Test (KAT) per + SP 800-90A. Instantiates a SHA-512 DRBG with seedA, optionally + reseeds with seedB, generates output, and compares against known + test vectors. Available when WOLFSSL_DRBG_SHA512 is defined. + + \return 0 On success + \return BAD_FUNC_ARG If seedA or output is NULL, or if reseed is + set and seedB is NULL + \return -1 Test failed + + \param reseed Non-zero to test reseeding + \param seedA Initial entropy seed + \param seedASz Size of seedA in bytes + \param seedB Reseed entropy (required if reseed is set) + \param seedBSz Size of seedB in bytes + \param output Buffer to receive generated output + \param outputSz Size of output in bytes + + _Example_ + \code + byte output[WC_SHA512_DIGEST_SIZE * 4]; + const byte seedA[] = { ... }; + const byte seedB[] = { ... }; + + ret = wc_RNG_HealthTest_SHA512(0, seedA, sizeof(seedA), NULL, 0, + output, sizeof(output)); + if (ret != 0) + return -1; + + ret = wc_RNG_HealthTest_SHA512(1, seedA, sizeof(seedA), + seedB, sizeof(seedB), + output, sizeof(output)); + if (ret != 0) + return -1; + \endcode + + \sa wc_RNG_HealthTest + \sa wc_RNG_HealthTest_SHA512_ex +*/ +int wc_RNG_HealthTest_SHA512(int reseed, const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz); + +/*! + \ingroup Random + + \brief Extended SHA-512 Hash_DRBG health test with nonce, + personalization string, and additional input support. Suitable + for full ACVP / CAVP test vector validation. Available when + WOLFSSL_DRBG_SHA512 is defined. + + \return 0 On success + \return BAD_FUNC_ARG If required params are NULL + \return -1 Test failed + + \param reseed Non-zero to test reseeding + \param nonce Nonce buffer (can be NULL) + \param nonceSz Nonce size + \param persoString Personalization string (can be NULL) + \param persoStringSz Personalization string size + \param seedA Initial entropy seed + \param seedASz Initial seed size + \param seedB Reseed entropy (required if reseed is set) + \param seedBSz Reseed size + \param additionalA Additional input for first generate (can be NULL) + \param additionalASz Additional input A size + \param additionalB Additional input for second generate (can be NULL) + \param additionalBSz Additional input B size + \param output Output buffer + \param outputSz Output size + \param heap Heap hint (can be NULL) + \param devId Device ID (INVALID_DEVID for software) + + _Example_ + \code + byte output[WC_SHA512_DIGEST_SIZE * 4]; + const byte seedA[] = { ... }; + const byte nonce[] = { ... }; + + int ret = wc_RNG_HealthTest_SHA512_ex(0, nonce, sizeof(nonce), + NULL, 0, + seedA, sizeof(seedA), + NULL, 0, + NULL, 0, NULL, 0, + output, sizeof(output), + NULL, INVALID_DEVID); + \endcode + + \sa wc_RNG_HealthTest_SHA512 + \sa wc_RNG_HealthTest_ex +*/ +int wc_RNG_HealthTest_SHA512_ex(int reseed, const byte* nonce, word32 nonceSz, + const byte* persoString, word32 persoStringSz, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + const byte* additionalA, word32 additionalASz, + const byte* additionalB, word32 additionalBSz, + byte* output, word32 outputSz, + void* heap, int devId); + +/*! + \ingroup Random + + \brief Disables the SHA-256 Hash_DRBG at runtime. When disabled, + newly initialized WC_RNG instances will not use the SHA-256 DRBG. + If the SHA-512 DRBG is enabled (WOLFSSL_DRBG_SHA512), new RNG + instances will use SHA-512 instead. Requires HAVE_HASHDRBG. + + \return 0 On success + + _Example_ + \code + wc_Sha256Drbg_Disable(); + // New WC_RNG instances will now use SHA-512 DRBG if available + WC_RNG rng; + wc_InitRng(&rng); + \endcode + + \sa wc_Sha256Drbg_Enable + \sa wc_Sha256Drbg_GetStatus + \sa wc_Sha512Drbg_Disable +*/ +int wc_Sha256Drbg_Disable(void); + +/*! + \ingroup Random + + \brief Re-enables the SHA-256 Hash_DRBG at runtime after a prior + call to wc_Sha256Drbg_Disable(). Requires HAVE_HASHDRBG. + + \return 0 On success + + _Example_ + \code + wc_Sha256Drbg_Disable(); + // ... use SHA-512 DRBG only ... + wc_Sha256Drbg_Enable(); + // New WC_RNG instances can use SHA-256 DRBG again + \endcode + + \sa wc_Sha256Drbg_Disable + \sa wc_Sha256Drbg_GetStatus +*/ +int wc_Sha256Drbg_Enable(void); + +/*! + \ingroup Random + + \brief Returns the current status of the SHA-256 Hash_DRBG + (disabled or enabled). Requires HAVE_HASHDRBG. + + \return 1 SHA-256 DRBG is disabled + \return 0 SHA-256 DRBG is enabled + + _Example_ + \code + if (wc_Sha256Drbg_GetStatus()) { + printf("SHA-256 DRBG is off\n"); + } + \endcode + + \sa wc_Sha256Drbg_Disable + \sa wc_Sha256Drbg_Enable +*/ +int wc_Sha256Drbg_GetStatus(void); + +/*! + \ingroup Random + + \brief Disables the SHA-512 Hash_DRBG at runtime. When disabled, + newly initialized WC_RNG instances will not use the SHA-512 DRBG. + If the SHA-256 DRBG is still enabled, new RNG instances will fall + back to SHA-256. Available when WOLFSSL_DRBG_SHA512 is defined. + Requires HAVE_HASHDRBG. + + \return 0 On success + + _Example_ + \code + wc_Sha512Drbg_Disable(); + // New WC_RNG instances will now use SHA-256 DRBG + WC_RNG rng; + wc_InitRng(&rng); + \endcode + + \sa wc_Sha512Drbg_Enable + \sa wc_Sha512Drbg_GetStatus + \sa wc_Sha256Drbg_Disable +*/ +int wc_Sha512Drbg_Disable(void); + +/*! + \ingroup Random + + \brief Re-enables the SHA-512 Hash_DRBG at runtime after a prior + call to wc_Sha512Drbg_Disable(). Available when WOLFSSL_DRBG_SHA512 + is defined. Requires HAVE_HASHDRBG. + + \return 0 On success + + _Example_ + \code + wc_Sha512Drbg_Disable(); + // ... use SHA-256 DRBG only ... + wc_Sha512Drbg_Enable(); + // New WC_RNG instances can use SHA-512 DRBG again + \endcode + + \sa wc_Sha512Drbg_Disable + \sa wc_Sha512Drbg_GetStatus +*/ +int wc_Sha512Drbg_Enable(void); + +/*! + \ingroup Random + + \brief Returns the current status of the SHA-512 Hash_DRBG + (disabled or enabled). Available when WOLFSSL_DRBG_SHA512 is + defined. Requires HAVE_HASHDRBG. + + \return 1 SHA-512 DRBG is disabled + \return 0 SHA-512 DRBG is enabled + + _Example_ + \code + if (wc_Sha512Drbg_GetStatus()) { + printf("SHA-512 DRBG is off\n"); + } + \endcode + + \sa wc_Sha512Drbg_Disable + \sa wc_Sha512Drbg_Enable +*/ +int wc_Sha512Drbg_GetStatus(void); diff --git a/src/include.am b/src/include.am index 943522b4e8e..4f7ed1db281 100644 --- a/src/include.am +++ b/src/include.am @@ -431,7 +431,7 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fips.c \ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfcrypt_last.c endif BUILD_FIPS_V5 -if BUILD_FIPS_V6_PLUS +if BUILD_FIPS_V6 # FIPS 140-3 SRTP-KDF first file src_libwolfssl@LIBSUFFIX@_la_SOURCES += \ wolfcrypt/src/wolfcrypt_first.c @@ -756,7 +756,386 @@ src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fips.c \ # fips last file src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfcrypt_last.c -endif BUILD_FIPS_V6_PLUS +endif BUILD_FIPS_V6 + +if BUILD_FIPS_V7_PLUS +# FIPS 140-3 v7.0.0+ first file +src_libwolfssl@LIBSUFFIX@_la_SOURCES += \ + wolfcrypt/src/wolfcrypt_first.c + +src_libwolfssl@LIBSUFFIX@_la_SOURCES += \ + wolfcrypt/src/hmac.c \ + wolfcrypt/src/random.c + +if BUILD_MEMUSE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfentropy.c +endif + +if BUILD_RNG_BANK +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rng_bank.c +endif + +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/kdf.c + +if BUILD_RSA +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/rsa.c +endif + +if BUILD_ECC +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ecc.c +endif + +if BUILD_AES +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes.c + +if BUILD_ARMASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(LEGACY_ARMASM_AES_C) +endif BUILD_ARMASM + +if BUILD_ARMASM_NEON +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(NEW_ARMASM_AES_ASM_C) +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(NEW_ARMASM_AES_ASM_S) +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM +if BUILD_ARMASM_INLINE +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm_c.c +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-aes-asm_c.c +endif +else +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-aes-asm.S +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-aes-asm.S +endif +endif !BUILD_ARMASM_INLINE +endif BUILD_ARMASM +endif !BUILD_ARMASM_NEON +endif BUILD_AES + +if BUILD_AESNI +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_asm.S +if BUILD_X86_ASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_gcm_x86_asm.S +else +if BUILD_AESGCM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_gcm_asm.S +endif +if BUILD_AESXTS +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/aes_xts_asm.S +endif +endif +endif + +if BUILD_SHA +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha.c +endif + +if BUILD_ARMASM_NEON +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(ARMASM_SHA256_C) +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(LEGACY_ARMASM_SHA256_C) +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(NEW_ARMASM_SHA256_ASM_C) +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(NEW_ARMASM_SHA256_ASM_S) +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(ARMASM_SHA256_C) +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(LEGACY_ARMASM_SHA256_C) +if BUILD_ARMASM_INLINE +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm_c.c +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha256-asm_c.c +endif +else +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha256-asm.S +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha256-asm.S +endif +endif !BUILD_ARMASM_INLINE +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha256.c +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha256_asm.S +endif BUILD_INTELASM +endif !BUILD_ARMASM +endif !BUILD_ARMASM_NEON + +if BUILD_RISCV_ASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/riscv/riscv-64-sha256.c +endif BUILD_RISCV_ASM + +if BUILD_PPC32_ASM +if BUILD_PPC32_ASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/ppc32/ppc32-sha256-asm_c.c +else +if BUILD_PPC32_ASM_INLINE_REG +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/ppc32/ppc32-sha256-asm_cr.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/ppc32/ppc32-sha256-asm.S +endif !BUILD_PPC32_ASM_INLINE_REG +endif !BUILD_PPC32_ASM_INLINE +endif BUILD_PPC32_ASM + +if BUILD_SHA512 +if BUILD_RISCV_ASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/riscv/riscv-64-sha512.c +else + +if !BUILD_FIPS_V5 +if !BUILD_FIPS_V6 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha512.c +endif !BUILD_FIPS_V6 +endif !BUILD_FIPS_V5 + +if BUILD_ARMASM_NEON +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(LEGACY_ARMASM_SHA512_C) +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512-asm_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512-asm.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += $(LEGACY_ARMASM_SHA512_C) +if BUILD_ARMASM_INLINE +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm_c.c +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha512-asm_c.c +endif +else +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha512-asm.S +endif +endif !BUILD_ARMASM_INLINE +else + +if BUILD_FIPS_V5 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha512.c +else +if BUILD_FIPS_V6 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha512.c +endif BUILD_FIPS_V6 +endif !BUILD_FIPS_V5 + +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha512_asm.S +endif BUILD_INTELASM +endif !BUILD_ARMASM +endif !BUILD_ARMASM_NEON +endif !BUILD_RISCV_ASM +endif BUILD_SHA512 + +if BUILD_SHA3 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha3.c +if BUILD_ARMASM_NEON +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha3-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha3-asm.S +endif !BUILD_ARMASM_INLINE +endif BUILD_ARMASM_NEON +if BUILD_ARMASM +if BUILD_ARMASM_INLINE +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha3-asm_c.c +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha3-asm_c.c +endif +else +if BUILD_ARM_NONTHUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha3-asm.S +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-sha3-asm.S +endif +endif !BUILD_ARMASM_INLINE +endif BUILD_ARMASM +if BUILD_RISCV_ASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/riscv/riscv-64-sha3.c +endif BUILD_RISCV_ASM +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sha3_asm.S +endif +endif + +if BUILD_DH +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/dh.c +endif + +if BUILD_CMAC +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/cmac.c +endif + +if BUILD_CURVE448 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/curve448.c +endif + +if BUILD_ED448 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ed448.c +endif + +if BUILD_CURVE25519 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/curve25519.c +endif + +if BUILD_ED25519 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/ed25519.c +endif + +if BUILD_ARMASM +if BUILD_ARMASM_NEON +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519_c.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519.S +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM_INLINE +if BUILD_ARM_NONTHUMB +if BUILD_ARM_32 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519_c.c +endif +if BUILD_ARM_64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519_c.c +endif +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-curve25519_c.c +endif +else +if BUILD_ARM_NONTHUMB +if BUILD_ARM_32 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519.S +endif +if BUILD_ARM_64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +endif +endif +if BUILD_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-curve25519.S +endif +endif !BUILD_ARMASM_INLINE +endif !BUILD_ARMASM_NEON +endif BUILD_ARMASM + +if BUILD_PWDBASED +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/pwdbased.c +endif BUILD_PWDBASED + +if BUILD_SP +if BUILD_SP_C32 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_c32.c +endif +if BUILD_SP_C64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_c64.c +endif + +if BUILD_SP_X86_64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_x86_64.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_x86_64_asm.S +endif +if !BUILD_FIPS_V2 +if BUILD_SP_ARM32 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_arm32.c +endif +endif +if BUILD_SP_ARM_THUMB +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_armthumb.c +endif +if !BUILD_FIPS_V2 +if BUILD_SP_ARM64 +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_arm64.c +endif +endif +if BUILD_SP_ARM_CORTEX +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sp_cortexm.c +endif +endif BUILD_SP + +# PQ Algorithms (FIPS v7.0.0+) +if BUILD_WC_MLKEM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_mlkem.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_mlkem_poly.c +if BUILD_ARMASM +if BUILD_ARM_THUMB +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-mlkem-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/thumb2-mlkem-asm.S +endif !BUILD_ARMASM_INLINE +else +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-mlkem-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-mlkem-asm.S +endif !BUILD_ARMASM_INLINE +endif !BUILD_ARM_THUMB +endif BUILD_ARMASM +if !BUILD_X86_ASM +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_mlkem_asm.S +endif +endif +if BUILD_ARMASM_NEON +if BUILD_ARMASM_INLINE +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-mlkem-asm_c.c +else +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/port/arm/armv8-mlkem-asm.S +endif !BUILD_ARMASM_INLINE +endif BUILD_ARMASM_NEON +endif + +if BUILD_DILITHIUM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/dilithium.c +if !BUILD_X86_ASM +if BUILD_INTELASM +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_mldsa_asm.S +endif BUILD_INTELASM +endif !BUILD_X86_ASM +endif + +if BUILD_WC_LMS +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms_impl.c +endif + +if BUILD_WC_XMSS +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_xmss.c +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_xmss_impl.c +endif + +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/fips.c \ + wolfcrypt/src/fips_test.c + +# fips last file +src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wolfcrypt_last.c +endif BUILD_FIPS_V7_PLUS endif BUILD_FIPS @@ -1367,6 +1746,7 @@ if BUILD_SAKKE src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/sakke.c endif +if !BUILD_FIPS_V7_PLUS if BUILD_WC_MLKEM src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_mlkem.c src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_mlkem_poly.c @@ -1417,6 +1797,7 @@ if BUILD_WC_XMSS src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_xmss.c src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_xmss_impl.c endif +endif !BUILD_FIPS_V7_PLUS if !BUILD_FIPS_V6_PLUS if BUILD_CURVE25519 diff --git a/tests/api.c b/tests/api.c index 0cda4e114af..5d85fdeacd0 100644 --- a/tests/api.c +++ b/tests/api.c @@ -26098,8 +26098,6 @@ static int error_test(void) {27, 26 }, #endif { -9, WC_SPAN1_FIRST_E + 1 }, - { -124, -124 }, - { -167, -169 }, { -300, -300 }, { -335, -336 }, { -346, -349 }, diff --git a/tests/api/test_mldsa.c b/tests/api/test_mldsa.c index 2aa788e8615..19c24a73e60 100644 --- a/tests/api/test_mldsa.c +++ b/tests/api/test_mldsa.c @@ -553,6 +553,8 @@ int test_wc_dilithium(void) ExpectIntEQ(wc_InitRng(&rng), 0); #endif + PRIVATE_KEY_UNLOCK(); + ExpectIntEQ(wc_dilithium_init(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_dilithium_init_ex(NULL, NULL, INVALID_DEVID), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); wc_dilithium_free(NULL); @@ -673,6 +675,8 @@ int test_wc_dilithium(void) WC_NO_ERR_TRACE(BAD_FUNC_ARG)); #endif + PRIVATE_KEY_LOCK(); + wc_dilithium_free(key); #if !defined(WOLFSSL_DILITHIUM_NO_MAKE_KEY) || \ !defined(WOLFSSL_DILITHIUM_NO_SIGN) @@ -765,6 +769,8 @@ int test_wc_dilithium_sign(void) ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_dilithium_init(key), 0); + PRIVATE_KEY_UNLOCK(); + #ifndef WOLFSSL_NO_ML_DSA_44 ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_44), 0); #elif !defined(WOLFSSL_NO_ML_DSA_65) @@ -878,6 +884,8 @@ int test_wc_dilithium_sign(void) #endif wc_dilithium_free(importKey); + PRIVATE_KEY_LOCK(); + wc_dilithium_free(key); wc_FreeRng(&rng); @@ -1251,6 +1259,8 @@ int test_wc_dilithium_check_key(void) ExpectIntEQ(wc_InitRng(&rng), 0); + PRIVATE_KEY_UNLOCK(); + ExpectIntEQ(wc_dilithium_check_key(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_dilithium_init(checkKey), 0); @@ -1337,6 +1347,8 @@ int test_wc_dilithium_check_key(void) pubCheckKey[48] ^= 0x80; } + PRIVATE_KEY_LOCK(); + wc_dilithium_free(checkKey); wc_FreeRng(&rng); @@ -2940,6 +2952,8 @@ int test_wc_dilithium_der(void) ExpectIntEQ(wc_InitRng(&rng), 0); ExpectIntEQ(wc_dilithium_init(key), 0); + PRIVATE_KEY_UNLOCK(); + ExpectIntEQ(wc_Dilithium_PublicKeyToDer(key, der, DILITHIUM_MAX_DER_SIZE, 0), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); ExpectIntEQ(wc_Dilithium_PublicKeyToDer(key, der, DILITHIUM_MAX_DER_SIZE, @@ -3091,6 +3105,7 @@ int test_wc_dilithium_der(void) idx = 0; ExpectIntEQ(wc_Dilithium_PrivateKeyDecode(der, &idx, key, len), 0); + PRIVATE_KEY_LOCK(); wc_dilithium_free(key); wc_FreeRng(&rng); @@ -12346,6 +12361,9 @@ int test_wc_dilithium_sig_kats(void) } ExpectIntEQ(wc_dilithium_init_ex(key, NULL, INVALID_DEVID), 0); + + PRIVATE_KEY_UNLOCK(); + #ifndef WOLFSSL_NO_ML_DSA_44 ExpectIntEQ(wc_dilithium_set_level(key, WC_ML_DSA_44), 0); ExpectIntEQ(wc_dilithium_import_private(sk_44, (word32)sizeof(sk_44), key), @@ -12377,6 +12395,8 @@ int test_wc_dilithium_sig_kats(void) ExpectIntEQ(XMEMCMP(sig, sig_87, sizeof(sig_87)), 0); #endif + PRIVATE_KEY_LOCK(); + wc_dilithium_free(key); XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif @@ -16745,6 +16765,8 @@ int test_wc_Dilithium_PrivateKeyDecode_OpenSSL_form(void) ExpectNotNull(der = (byte*) XMALLOC(derMaxSz, NULL, DYNAMIC_TYPE_TMP_BUFFER)); + PRIVATE_KEY_UNLOCK(); + for (size_t i = 0; i < sizeof(ossl_form) / sizeof(ossl_form[0]); ++i) { ExpectNotNull(fp = XFOPEN(ossl_form[i].fileName, "rb")); ExpectIntGT(derSz = XFREAD(der, 1, derMaxSz, fp), 0); @@ -16811,6 +16833,8 @@ int test_wc_Dilithium_PrivateKeyDecode_OpenSSL_form(void) wc_dilithium_free(&key); } + PRIVATE_KEY_LOCK(); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); diff --git a/tests/api/test_mlkem.c b/tests/api/test_mlkem.c index c727194fbe1..c42ab186a49 100644 --- a/tests/api/test_mlkem.c +++ b/tests/api/test_mlkem.c @@ -1451,6 +1451,8 @@ int test_wc_mlkem_make_key_kats(void) XMEMSET(key, 0, sizeof(MlKemKey)); } + PRIVATE_KEY_UNLOCK(); + #ifndef WOLFSSL_NO_ML_KEM_512 ExpectIntEQ(wc_MlKemKey_Init(key, WC_ML_KEM_512, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_MlKemKey_MakeKeyWithRandom(key, seed_512, sizeof(seed_512)), @@ -1488,6 +1490,8 @@ int test_wc_mlkem_make_key_kats(void) wc_MlKemKey_Free(key); #endif + PRIVATE_KEY_LOCK(); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); @@ -3845,6 +3849,8 @@ int test_wc_mlkem_decapsulate_kats(void) XMEMSET(key, 0, sizeof(MlKemKey)); } + PRIVATE_KEY_UNLOCK(); + #ifndef WOLFSSL_NO_ML_KEM_512 ExpectIntEQ(wc_MlKemKey_Init(key, WC_ML_KEM_512, NULL, INVALID_DEVID), 0); ExpectIntEQ(wc_MlKemKey_DecodePrivateKey(key, dk_512, sizeof(dk_512)), 0); @@ -3867,6 +3873,8 @@ int test_wc_mlkem_decapsulate_kats(void) wc_MlKemKey_Free(key); #endif + PRIVATE_KEY_LOCK(); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return EXPECT_RESULT(); diff --git a/tests/api/test_random.c b/tests/api/test_random.c index fe8aaf0ee15..79f8c27b5ee 100644 --- a/tests/api/test_random.c +++ b/tests/api/test_random.c @@ -530,3 +530,146 @@ int test_wc_RNG_HealthTest(void) return EXPECT_RESULT(); } +/* + * Testing wc_RNG_HealthTest_SHA512() + * Test vectors from NIST CAVP drbgtestvectors.zip, Hash_DRBG.rsp, [SHA-512]. + * Source: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm- + * Validation-Program/documents/drbg/drbgtestvectors.zip + */ +int test_wc_RNG_HealthTest_SHA512(void) +{ + EXPECT_DECLS; +#if defined(HAVE_HASHDRBG) && defined(WOLFSSL_DRBG_SHA512) && \ + !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + + /* No-reseed test: drbgvectors_no_reseed/Hash_DRBG.rsp, [SHA-512], + * COUNT=0 */ + const byte test1Seed[] = + { + /* EntropyInput (32 bytes) */ + 0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a, + 0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22, + 0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b, + 0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c, + /* Nonce (16 bytes) */ + 0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa, + 0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25 + }; + const byte test1Output[] = + { + 0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57, + 0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6, + 0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d, + 0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf, + 0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26, + 0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64, + 0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55, + 0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a, + 0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78, + 0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e, + 0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb, + 0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30, + 0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19, + 0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f, + 0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d, + 0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a, + 0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2, + 0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd, + 0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd, + 0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2, + 0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b, + 0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1, + 0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99, + 0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e, + 0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3, + 0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67, + 0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3, + 0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d, + 0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b, + 0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13, + 0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c, + 0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 + }; + + /* Reseed test: drbgvectors_pr_false/Hash_DRBG.rsp, [SHA-512], COUNT=0 */ + const byte test2SeedA[] = + { + /* EntropyInput (32 bytes) */ + 0x31, 0x44, 0xe1, 0x7a, 0x10, 0xc8, 0x56, 0x12, + 0x97, 0x64, 0xf5, 0x8f, 0xd8, 0xe4, 0x23, 0x10, + 0x20, 0x54, 0x69, 0x96, 0xc0, 0xbf, 0x6c, 0xff, + 0x8e, 0x91, 0xc2, 0x4e, 0xe0, 0x9b, 0xe3, 0x33, + /* Nonce (16 bytes) */ + 0xb1, 0x6f, 0xcb, 0x1c, 0xf0, 0xc0, 0x10, 0xf3, + 0x1f, 0xea, 0xb7, 0x33, 0x58, 0x8b, 0x8e, 0x04 + }; + const byte test2SeedB[] = + { + /* EntropyInputReseed (32 bytes) */ + 0xa0, 0xb3, 0x58, 0x4c, 0x2c, 0x84, 0x12, 0xf6, + 0x18, 0x40, 0x68, 0x34, 0x40, 0x4d, 0x1e, 0xb0, + 0xce, 0x99, 0x9b, 0xa2, 0x89, 0x66, 0x05, 0x4d, + 0x7e, 0x49, 0x7e, 0x0d, 0xb6, 0x08, 0xb9, 0x67 + }; + const byte test2Output[] = + { + 0xef, 0xa3, 0x5d, 0xd0, 0x36, 0x2a, 0xdb, 0x76, + 0x26, 0x45, 0x6b, 0x36, 0xfa, 0xc7, 0x4d, 0x3c, + 0x28, 0xd0, 0x1d, 0x92, 0x64, 0x20, 0x27, 0x5a, + 0x28, 0xbe, 0xa9, 0xc9, 0xdd, 0x75, 0x47, 0xc1, + 0x5e, 0x79, 0x31, 0x85, 0x2a, 0xc1, 0x27, 0x70, + 0x76, 0x56, 0x75, 0x35, 0x23, 0x9c, 0x1f, 0x42, + 0x9c, 0x7f, 0x75, 0xcf, 0x74, 0xc2, 0x26, 0x7d, + 0xeb, 0x6a, 0x3e, 0x59, 0x6c, 0xf3, 0x26, 0x15, + 0x6c, 0x79, 0x69, 0x41, 0x28, 0x3b, 0x8d, 0x58, + 0x3f, 0x17, 0x1c, 0x2f, 0x6e, 0x33, 0x23, 0xf7, + 0x55, 0x5e, 0x1b, 0x18, 0x1f, 0xfd, 0xa3, 0x05, + 0x07, 0x21, 0x0c, 0xb1, 0xf5, 0x89, 0xb2, 0x3c, + 0xd7, 0x18, 0x80, 0xfd, 0x44, 0x37, 0x0c, 0xac, + 0xf4, 0x33, 0x75, 0xb0, 0xdb, 0x7e, 0x33, 0x6f, + 0x12, 0xb3, 0x09, 0xbf, 0xd4, 0xf6, 0x10, 0xbb, + 0x8f, 0x20, 0xe1, 0xa1, 0x5e, 0x25, 0x3a, 0x4f, + 0xe5, 0x11, 0xa0, 0x27, 0x96, 0x8d, 0xf0, 0xb1, + 0x05, 0xa1, 0xd7, 0x3a, 0xff, 0x7c, 0x7a, 0x82, + 0x6d, 0x39, 0xf6, 0x40, 0xdf, 0xb8, 0xf5, 0x22, + 0x25, 0x9e, 0xd4, 0x02, 0x28, 0x2e, 0x2c, 0x2e, + 0x9d, 0x3a, 0x49, 0x8f, 0x51, 0x72, 0x5f, 0xe4, + 0x14, 0x1b, 0x06, 0xda, 0x55, 0x98, 0xa4, 0x2a, + 0xc1, 0xe0, 0x49, 0x4e, 0x99, 0x7d, 0x56, 0x6a, + 0x1a, 0x39, 0xb6, 0x76, 0xb9, 0x6a, 0x60, 0x03, + 0xa4, 0xc5, 0xdb, 0x84, 0xf2, 0x46, 0x58, 0x4e, + 0xe6, 0x5a, 0xf7, 0x0f, 0xf2, 0x16, 0x02, 0x78, + 0x16, 0x6d, 0xa1, 0x6d, 0x91, 0xc9, 0xb8, 0xf2, + 0xde, 0xb0, 0x27, 0x51, 0xa1, 0x08, 0x8a, 0xd6, + 0xbe, 0x4e, 0x80, 0xef, 0x96, 0x6e, 0xb7, 0x3e, + 0x66, 0xbc, 0x87, 0xca, 0xd8, 0x7c, 0x77, 0xc0, + 0xb3, 0x4a, 0x21, 0xba, 0x1d, 0xa0, 0xba, 0x6d, + 0x16, 0xca, 0x50, 0x46, 0xdc, 0x4a, 0xbd, 0xa0 + }; + + byte output[WC_SHA512_DIGEST_SIZE * 4]; /* 256 bytes */ + + /* Bad parameter tests */ + ExpectIntNE(wc_RNG_HealthTest_SHA512(0, NULL, sizeof(test1Seed), + NULL, 0, output, sizeof(output)), 0); + ExpectIntNE(wc_RNG_HealthTest_SHA512(0, test1Seed, sizeof(test1Seed), + NULL, 0, NULL, sizeof(output)), 0); + ExpectIntNE(wc_RNG_HealthTest_SHA512(0, test1Seed, sizeof(test1Seed), + NULL, 0, output, 42), 0); /* wrong output size */ + + /* Good parameter tests */ + /* No-reseed */ + ExpectIntEQ(wc_RNG_HealthTest_SHA512(0, test1Seed, sizeof(test1Seed), + NULL, 0, output, sizeof(output)), 0); + ExpectBufEQ(test1Output, output, sizeof(output)); + + /* With reseed */ + ExpectIntEQ(wc_RNG_HealthTest_SHA512(1, test2SeedA, sizeof(test2SeedA), + test2SeedB, sizeof(test2SeedB), output, sizeof(output)), 0); + ExpectBufEQ(test2Output, output, sizeof(output)); + +#endif /* HAVE_HASHDRBG && WOLFSSL_DRBG_SHA512 && !HAVE_SELFTEST && FIPS v7+ */ + return EXPECT_RESULT(); +} + diff --git a/tests/api/test_random.h b/tests/api/test_random.h index a6478b38df9..0454e14c703 100644 --- a/tests/api/test_random.h +++ b/tests/api/test_random.h @@ -35,6 +35,7 @@ int test_wc_rng_new(void); int test_wc_RNG_DRBG_Reseed(void); int test_wc_RNG_TestSeed(void); int test_wc_RNG_HealthTest(void); +int test_wc_RNG_HealthTest_SHA512(void); #define TEST_RANDOM_DECLS \ TEST_DECL_GROUP("random", test_wc_InitRng), \ @@ -47,6 +48,7 @@ int test_wc_RNG_HealthTest(void); TEST_DECL_GROUP("random", test_wc_rng_new), \ TEST_DECL_GROUP("random", test_wc_RNG_DRBG_Reseed), \ TEST_DECL_GROUP("random", test_wc_RNG_TestSeed), \ - TEST_DECL_GROUP("random", test_wc_RNG_HealthTest) + TEST_DECL_GROUP("random", test_wc_RNG_HealthTest), \ + TEST_DECL_GROUP("random", test_wc_RNG_HealthTest_SHA512) #endif /* WOLFCRYPT_TEST_RANDOM_H */ diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index fea45db55e8..74e2c027666 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -969,6 +969,15 @@ static WC_INLINE void bench_append_memory_info(char* buffer, size_t size, /* Other */ #define BENCH_RNG 0x00000001 #define BENCH_SCRYPT 0x00000002 +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + #define BENCH_RNG_SHA512 0x00000004 +#endif +#define BENCH_RNG_INIT 0x00000008 +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + #define BENCH_RNG_SHA512_INIT 0x00000010 +#endif #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) || \ (defined(HAVE_CHACHA) && defined(HAVE_POLY1305)) @@ -1275,6 +1284,17 @@ static const bench_alg bench_other_opt[] = { #ifndef WC_NO_RNG { "-rng", BENCH_RNG }, #endif +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + { "-rng-sha512", BENCH_RNG_SHA512 }, +#endif +#ifndef WC_NO_RNG + { "-rng-init", BENCH_RNG_INIT }, +#endif +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + { "-rng-sha512-init", BENCH_RNG_SHA512_INIT }, +#endif #ifdef HAVE_SCRYPT { "-scrypt", BENCH_SCRYPT }, #endif @@ -2030,12 +2050,7 @@ static const char* bench_result_words3[][5] = { #define BENCH_ASYM #endif -#if defined(BENCH_ASYM) -#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DH) || \ - defined(HAVE_CURVE25519) || defined(HAVE_ED25519) || \ - defined(HAVE_CURVE448) || defined(HAVE_ED448) || \ - defined(WOLFSSL_HAVE_MLKEM) || defined(HAVE_DILITHIUM) || \ - defined(WOLFSSL_HAVE_LMS) +#if defined(BENCH_ASYM) || !defined(WC_NO_RNG) static const char* bench_result_words2[][6] = { #ifdef BENCH_MICROSECOND { "ops took", "μsec" , "avg" , "ops/μsec", "cycles/op", @@ -2049,8 +2064,7 @@ static const char* bench_result_words2[][6] = { NULL }, /* 1 Japanese */ #endif }; -#endif -#endif +#endif /* BENCH_ASYM || !WC_NO_RNG */ #ifdef WOLFSSL_CAAM #include @@ -3171,6 +3185,102 @@ static void bench_stats_sym_finish(const char* desc, int useDeviceID, TEST_SLEEP(); } /* bench_stats_sym_finish */ +#ifndef WC_NO_RNG +/* Report ops/sec in the same format as bench_stats_asym_finish, but without + * requiring BENCH_ASYM to be defined. Used for benchmarks like RNG init/free + * that measure operation counts rather than byte throughput. */ +static void bench_stats_ops_finish(const char* algo, int strength, + const char* desc, int count, double start, int ret) +{ + double total, each = 0, opsSec, milliEach; + const char **word = bench_result_words2[lng_index]; + char msg[256]; +#ifdef BENCH_MICROSECOND + const int digits = 5; +#else + const int digits = 3; +#endif + + XMEMSET(msg, 0, sizeof(msg)); + + total = current_time(0) - start; + +#ifdef WOLFSSL_ESPIDF + END_ESP_CYCLES +#else + END_CYCLES +#endif + + if (count > 0) + each = total / count; + if (total > 0) + opsSec = count / total; + else + opsSec = 0; + +#ifdef BENCH_MICROSECOND + milliEach = each / 1000; +#else + milliEach = each * 1000; +#endif + + SLEEP_ON_ERROR(ret); + + if (csv_format == 1) { + (void)XSNPRINTF(msg, sizeof(msg), "%s,%d,%s," FLT_FMT_PREC "," + FLT_FMT_PREC "," STATS_CLAUSE_SEPARATOR, + algo, strength, desc, + FLT_FMT_PREC_ARGS(3, milliEach), + FLT_FMT_PREC_ARGS(digits, opsSec)); + } + else { +#ifdef HAVE_GET_CYCLES + (void)XSNPRINTF(msg, sizeof(msg), + "%-6s %5d %8s %6d %s " FLT_FMT_PREC2 " %s, %s " + FLT_FMT_PREC2 " ms, " FLT_FMT_PREC2 " %s, %lu cycles", + algo, strength, desc, + count, word[0], + FLT_FMT_PREC2_ARGS(5, 3, total), word[1], word[2], + FLT_FMT_PREC2_ARGS(5, 3, milliEach), + FLT_FMT_PREC2_ARGS(digits + 6, digits, opsSec), + word[3], (unsigned long)total_cycles); +#else + (void)XSNPRINTF(msg, sizeof(msg), + "%-6s %5d %8s %6d %s " FLT_FMT_PREC2 " %s, %s " + FLT_FMT_PREC2 " ms, " FLT_FMT_PREC2 " %s", + algo, strength, desc, + count, word[0], + FLT_FMT_PREC2_ARGS(5, 3, total), word[1], word[2], + FLT_FMT_PREC2_ARGS(5, 3, milliEach), + FLT_FMT_PREC2_ARGS(digits + 6, digits, opsSec), + word[3]); +#endif + +#ifdef WOLFSSL_ESPIDF + SHOW_ESP_CYCLES_OPS(msg, sizeof(msg)); +#else + SHOW_CYCLES_OPS(msg, sizeof(msg)); +#endif + } + + printf("%s", msg); + + if (ret < 0) { + printf("%sBenchmark %s %s %d failed: %d\n", + err_prefix, algo, desc, strength, ret); + } + +#ifndef WOLFSSL_SGX + XFFLUSH(stdout); +#endif + + (void)ret; + + bench_stats_prepare(); + TEST_SLEEP(); +} /* bench_stats_ops_finish */ +#endif /* !WC_NO_RNG */ + #ifdef BENCH_ASYM #if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DH) || \ defined(HAVE_CURVE25519) || defined(HAVE_ED25519) || \ @@ -3809,6 +3919,12 @@ static void* benchmarks_do(void* args) if (bench_all || (bench_other_algs & BENCH_RNG)) bench_rng(); #endif /* WC_NO_RNG */ +#if defined(WOLFSSL_DRBG_SHA512) && !defined(WC_NO_RNG) && \ + !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + if (bench_all || (bench_other_algs & BENCH_RNG_SHA512)) + bench_rng_sha512(); +#endif #ifndef NO_AES #ifdef HAVE_AES_CBC if (bench_all || (bench_cipher_algs & BENCH_AES_CBC)) { @@ -4532,6 +4648,16 @@ static void* benchmarks_do(void* args) bench_sphincsKeySign(5, SMALL_VARIANT); #endif +#ifndef WC_NO_RNG + if (bench_all || (bench_other_algs & BENCH_RNG_INIT)) + bench_rng_init(); +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + if (bench_all || (bench_other_algs & BENCH_RNG_SHA512_INIT)) + bench_rng_sha512_init(); +#endif +#endif + exit: /* free benchmark buffers */ XFREE(bench_plain, HEAP_HINT, DYNAMIC_TYPE_WOLF_BIGINT); @@ -4878,6 +5004,21 @@ void bench_rng(void) WC_RNG myrng; DECLARE_MULTI_VALUE_STATS_VARS() + /* Force SHA-256 DRBG by temporarily disabling SHA-512 DRBG */ +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + #if !defined(NO_SHA256) + ret = wc_Sha512Drbg_Disable(); + if (ret != 0) { + printf("wc_Sha512Drbg_Disable failed %d\n", ret); + return; + } + #else + printf("RNG SHA-256 DRBG (Skipped: Disabled)\n"); + return; + #endif +#endif + bench_stats_prepare(); #ifndef HAVE_FIPS @@ -4886,7 +5027,11 @@ void bench_rng(void) ret = wc_InitRng(&myrng); #endif if (ret < 0) { - printf("InitRNG failed %d\n", ret); + printf("InitRNG (SHA-256) failed %d\n", ret); +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + wc_Sha512Drbg_Enable(); +#endif return; } @@ -4917,15 +5062,204 @@ void bench_rng(void) #endif ); exit_rng: - bench_stats_sym_finish("RNG", 0, count, bench_size, start, ret); + bench_stats_sym_finish("RNG SHA-256 DRBG", 0, count, bench_size, start, + ret); #ifdef MULTI_VALUE_STATISTICS bench_multi_value_stats(max, min, sum, squareSum, runs); #endif wc_FreeRng(&myrng); + + /* Restore SHA-512 DRBG */ +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + wc_Sha512Drbg_Enable(); +#endif } #endif /* WC_NO_RNG */ +#if defined(WOLFSSL_DRBG_SHA512) && !defined(WC_NO_RNG) && \ + !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) +void bench_rng_sha512(void) +{ + int ret, i, count; + double start; + long pos, len, remain; + WC_RNG myrng; + DECLARE_MULTI_VALUE_STATS_VARS() + + /* Force SHA-512 DRBG by temporarily disabling SHA-256 DRBG */ +#ifndef NO_SHA256 + ret = wc_Sha256Drbg_Disable(); + if (ret != 0) { + printf("wc_Sha256Drbg_Disable failed %d\n", ret); + return; + } +#endif + + bench_stats_prepare(); + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&myrng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&myrng); +#endif + if (ret < 0) { + printf("InitRNG (SHA-512) failed %d\n", ret); +#ifndef NO_SHA256 + wc_Sha256Drbg_Enable(); +#endif + return; + } + + bench_stats_start(&count, &start); + do { + for (i = 0; i < numBlocks; i++) { + /* Split request to handle large RNG request */ + pos = 0; + remain = (int)bench_size; + while (remain > 0) { + len = remain; + if (len > RNG_MAX_BLOCK_LEN) + len = RNG_MAX_BLOCK_LEN; + ret = wc_RNG_GenerateBlock(&myrng, &bench_plain[pos], + (word32)len); + if (ret < 0) + goto exit_rng_sha512; + + remain -= len; + pos += len; + } + RECORD_MULTI_VALUE_STATS(); + } + count += i; + } while (bench_stats_check(start) +#ifdef MULTI_VALUE_STATISTICS + || runs < minimum_runs +#endif + ); +exit_rng_sha512: + bench_stats_sym_finish("RNG SHA-512 DRBG", 0, count, bench_size, start, + ret); +#ifdef MULTI_VALUE_STATISTICS + bench_multi_value_stats(max, min, sum, squareSum, runs); +#endif + + wc_FreeRng(&myrng); + + /* Restore SHA-256 DRBG */ +#ifndef NO_SHA256 + wc_Sha256Drbg_Enable(); +#endif +} +#endif /* WOLFSSL_DRBG_SHA512 && !WC_NO_RNG && !HAVE_SELFTEST && FIPS v7+ */ + +#ifndef WC_NO_RNG +void bench_rng_init(void) +{ + int ret, count; + double start; + WC_RNG myrng; + DECLARE_MULTI_VALUE_STATS_VARS() + + /* Force SHA-256 DRBG by temporarily disabling SHA-512 DRBG */ +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + #if !defined(NO_SHA256) + ret = wc_Sha512Drbg_Disable(); + if (ret != 0) { + printf("wc_Sha512Drbg_Disable failed %d\n", ret); + return; + } + #else + printf("RNG SHA-256 Init/Free (Skipped: Disabled)\n"); + return; + #endif +#endif + + bench_stats_start(&count, &start); + do { + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&myrng, HEAP_HINT, devId); + #else + ret = wc_InitRng(&myrng); + #endif + if (ret < 0) { + printf("InitRNG (SHA-256 init bench) failed %d\n", ret); + goto exit_rng_init; + } + wc_FreeRng(&myrng); + count++; + RECORD_MULTI_VALUE_STATS(); + } while (bench_stats_check(start) +#ifdef MULTI_VALUE_STATISTICS + || runs < minimum_runs +#endif + ); +exit_rng_init: + bench_stats_ops_finish("RNG", 256, "SHA256 Init/Free", count, start, ret); +#ifdef MULTI_VALUE_STATISTICS + bench_multi_value_stats(max, min, sum, squareSum, runs); +#endif + + /* Restore SHA-512 DRBG */ +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + wc_Sha512Drbg_Enable(); +#endif +} + +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) +void bench_rng_sha512_init(void) +{ + int ret, count; + double start; + WC_RNG myrng; + DECLARE_MULTI_VALUE_STATS_VARS() + + /* Force SHA-512 DRBG by temporarily disabling SHA-256 DRBG */ +#ifndef NO_SHA256 + ret = wc_Sha256Drbg_Disable(); + if (ret != 0) { + printf("wc_Sha256Drbg_Disable failed %d\n", ret); + return; + } +#endif + + bench_stats_start(&count, &start); + do { + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&myrng, HEAP_HINT, devId); + #else + ret = wc_InitRng(&myrng); + #endif + if (ret < 0) { + printf("InitRNG (SHA-512 init bench) failed %d\n", ret); + goto exit_rng_sha512_init; + } + wc_FreeRng(&myrng); + count++; + RECORD_MULTI_VALUE_STATS(); + } while (bench_stats_check(start) +#ifdef MULTI_VALUE_STATISTICS + || runs < minimum_runs +#endif + ); +exit_rng_sha512_init: + bench_stats_ops_finish("RNG", 512, "SHA512 Init/Free", count, start, ret); +#ifdef MULTI_VALUE_STATISTICS + bench_multi_value_stats(max, min, sum, squareSum, runs); +#endif + + /* Restore SHA-256 DRBG */ +#ifndef NO_SHA256 + wc_Sha256Drbg_Enable(); +#endif +} +#endif /* WOLFSSL_DRBG_SHA512 && !HAVE_SELFTEST && FIPS v7+ */ +#endif /* !WC_NO_RNG */ #ifndef NO_AES @@ -10640,6 +10974,7 @@ static void bench_mlkem_encap(int type, const char* name, int keySize, RESET_MULTI_VALUE_STATS_VARS(); /* MLKEM Decapsulate */ + PRIVATE_KEY_UNLOCK(); bench_stats_start(&count, &start); do { /* while free pending slots in queue, submit ops */ @@ -10657,6 +10992,7 @@ static void bench_mlkem_encap(int type, const char* name, int keySize, ); exit_decap: + PRIVATE_KEY_LOCK(); bench_stats_asym_finish(name, keySize, desc[13], 0, count, start, ret); #ifdef MULTI_VALUE_STATISTICS bench_multi_value_stats(max, min, sum, squareSum, runs); @@ -15328,6 +15664,7 @@ void bench_dilithiumKeySign(byte level) #elif !defined WOLFSSL_DILITHIUM_NO_SIGN + PRIVATE_KEY_UNLOCK(); #ifndef WOLFSSL_NO_ML_DSA_44 if (level == 2) { ret = wc_dilithium_import_private(bench_dilithium_level2_key, @@ -15346,6 +15683,7 @@ void bench_dilithiumKeySign(byte level) sizeof_bench_dilithium_level5_key, key); } #endif + PRIVATE_KEY_LOCK(); if (ret != 0) { printf("Failed to load private key\n"); goto out; diff --git a/wolfcrypt/benchmark/benchmark.h b/wolfcrypt/benchmark/benchmark.h index 5ba8bae24bf..e97fa35d4eb 100644 --- a/wolfcrypt/benchmark/benchmark.h +++ b/wolfcrypt/benchmark/benchmark.h @@ -127,6 +127,13 @@ void bench_sakkeRskGen(void); void bench_sakkeValidate(void); void bench_sakke(void); void bench_rng(void); +void bench_rng_init(void); +#if defined(WOLFSSL_DRBG_SHA512) && !defined(WC_NO_RNG) && \ + !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) +void bench_rng_sha512(void); +void bench_rng_sha512_init(void); +#endif void bench_blake2b(void); void bench_blake2s(void); void bench_ascon_hash(void); diff --git a/wolfcrypt/src/dilithium.c b/wolfcrypt/src/dilithium.c index dfd9ac4f6c0..b2657d89fda 100644 --- a/wolfcrypt/src/dilithium.c +++ b/wolfcrypt/src/dilithium.c @@ -132,6 +132,11 @@ #include +#if FIPS_VERSION3_GE(2,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif + #ifndef WOLFSSL_DILITHIUM_NO_ASN1 #include #endif @@ -10075,6 +10080,30 @@ int wc_dilithium_make_key(dilithium_key* key, WC_RNG* rng) #endif } +#ifdef HAVE_FIPS + /* Pairwise Consistency Test (PCT) per FIPS 140-3 / ISO 19790:2012 + * Section 7.10.3.3 (TE10.35.02): sign with new sk, verify with pk. + * Runs on every key generation. */ + if (ret == 0) { + static const byte pct_msg[] = "wolfSSL ML-DSA PCT"; + byte pct_sig[DILITHIUM_MAX_SIG_SIZE]; + word32 pct_sigSz = DILITHIUM_MAX_SIG_SIZE; + int pct_res = 0; + + ret = wc_dilithium_sign_msg(pct_msg, sizeof(pct_msg), + pct_sig, &pct_sigSz, key, rng); + + if (ret == 0) + ret = wc_dilithium_verify_msg(pct_sig, pct_sigSz, + pct_msg, sizeof(pct_msg), &pct_res, key); + + if (ret == 0 && pct_res != 1) + ret = ML_DSA_PCT_E; + + ForceZero(pct_sig, sizeof(pct_sig)); + } +#endif /* HAVE_FIPS */ + return ret; } @@ -10103,6 +10132,9 @@ int wc_dilithium_make_key_from_seed(dilithium_key* key, const byte* seed) #endif } + /* Note: PCT is performed in wc_dilithium_make_key() which calls this + * function and has the RNG parameter needed for signing. */ + return ret; } #endif diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 431a3c996c0..2134758f4a6 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -665,6 +665,27 @@ const char* wc_GetErrorString(int error) case ALREADY_E: return "Operation was redundant or preempted"; + case ML_KEM_KAT_FIPS_E: + return "wolfCrypt FIPS ML-KEM Known Answer Test Failure"; + + case ML_DSA_KAT_FIPS_E: + return "wolfCrypt FIPS ML-DSA Known Answer Test Failure"; + + case LMS_KAT_FIPS_E: + return "wolfCrypt FIPS LMS Known Answer Test Failure"; + + case XMSS_KAT_FIPS_E: + return "wolfCrypt FIPS XMSS Known Answer Test Failure"; + + case ML_KEM_PCT_E: + return "wolfcrypt ML-KEM Pairwise Consistency Test Failure"; + + case ML_DSA_PCT_E: + return "wolfcrypt ML-DSA Pairwise Consistency Test Failure"; + + case DRBG_SHA512_KAT_FIPS_E: + return "SHA-512 DRBG Known Answer Test check FIPS error"; + case SEQ_OVERFLOW_E: return "Sequence counter would overflow"; diff --git a/wolfcrypt/src/ext_mlkem.c b/wolfcrypt/src/ext_mlkem.c index 91634f494f2..90ffbb1662d 100644 --- a/wolfcrypt/src/ext_mlkem.c +++ b/wolfcrypt/src/ext_mlkem.c @@ -22,6 +22,12 @@ #include #if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_WC_MLKEM) + +#if FIPS_VERSION3_GE(2,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif + #include #ifdef NO_INLINE diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 5c8cc3edf8b..893df554508 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -75,7 +75,12 @@ This library contains implementation for the random number generator. #ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ -#include +#ifndef NO_SHA256 + #include +#endif +#ifdef WOLFSSL_DRBG_SHA512 + #include +#endif #ifdef WOLF_CRYPTO_CB #include @@ -274,11 +279,48 @@ enum { drbgInitV = 4 }; +#ifndef NO_SHA256 typedef struct DRBG_internal DRBG_internal; +#endif + +#ifdef WOLFSSL_DRBG_SHA512 +typedef struct DRBG_SHA512_internal DRBG_SHA512_internal; + +static int Hash512_DRBG_Reseed(DRBG_SHA512_internal* drbg, const byte* seed, + word32 seedSz); +static int Hash512_DRBG_Generate(DRBG_SHA512_internal* drbg, byte* out, + word32 outSz); +static int Hash512_DRBG_Instantiate(DRBG_SHA512_internal* drbg, + const byte* seed, word32 seedSz, + const byte* nonce, word32 nonceSz, + void* heap, int devId); +static int Hash512_DRBG_Uninstantiate(DRBG_SHA512_internal* drbg); +#endif + +/* Runtime DRBG disable state */ +#ifndef NO_SHA256 +#ifdef WOLFSSL_NO_SHA256_DRBG +static int sha256DrbgDisabled = 1; +#else +static int sha256DrbgDisabled = 0; +#endif +#endif +#ifdef WOLFSSL_DRBG_SHA512 +static int sha512DrbgDisabled = 0; +#endif static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap, int devId); +#ifdef WOLFSSL_DRBG_SHA512 +static int wc_RNG_HealthTest_SHA512_ex_internal(DRBG_SHA512_internal* drbg, + int reseed, const byte* nonce, word32 nonceSz, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz, + void* heap, int devId); +#endif + /* Hash Derivation Function */ /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, @@ -432,17 +474,30 @@ int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) return BAD_FUNC_ARG; } - if (rng->drbg == NULL) { - #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) - if (IS_INTEL_RDRAND(intel_flags)) { - /* using RDRAND not DRBG, so return success */ - return 0; - } - return BAD_FUNC_ARG; - #endif +#ifdef HAVE_INTEL_RDRAND + if (IS_INTEL_RDRAND(intel_flags)) { + /* using RDRAND not DRBG, so return success */ + return 0; } +#endif + +#ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) { + if (rng->drbg == NULL) + return BAD_FUNC_ARG; + return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz); + } +#endif +#ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbgType == WC_DRBG_SHA512) { + if (rng->drbg512 == NULL) + return BAD_FUNC_ARG; + return Hash512_DRBG_Reseed((DRBG_SHA512_internal *)rng->drbg512, + seed, seedSz); + } +#endif - return Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, seed, seedSz); + return BAD_FUNC_ARG; } static WC_INLINE void array_add_one(byte* data, word32 dataSz) @@ -745,6 +800,399 @@ static int Hash_DRBG_Uninstantiate(DRBG_internal* drbg) return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } +/* ====================================================================== */ +/* SHA-512 Hash_DRBG (SP 800-90A Rev 1, Table 2) */ +/* */ +/* Internal state (V, C): seedlen = 888 bits = 111 bytes each */ +/* Output block length: 512 bits = 64 bytes (WC_SHA512_DIGEST_SIZE) */ +/* Security strength: 256 bits */ +/* */ +/* NOTE: The raw entropy seed gathered at instantiation / reseed is */ +/* WC_DRBG_SEED_SZ (1024 bits in FIPS builds), NOT seedlen. We overseed */ +/* to tolerate weak entropy sources. Hash_df then compresses the seed */ +/* material down to the 888-bit V and derives C from V. See random.h. */ +/* ====================================================================== */ +#ifdef WOLFSSL_DRBG_SHA512 + +#define OUTPUT_BLOCK_LEN_SHA512 (WC_SHA512_DIGEST_SIZE) /* 64 bytes */ + +/* Hash Derivation Function using SHA-512 */ +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash512_df(DRBG_SHA512_internal* drbg, byte* out, word32 outSz, + byte type, + const byte* inA, word32 inASz, + const byte* inB, word32 inBSz) +{ + int ret = DRBG_FAILURE; + byte ctr; + word32 i; + word32 len; + word32 bits = (outSz * 8); +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha512* sha = &drbg->sha512; +#else + wc_Sha512 sha[1]; +#endif +#if defined(WOLFSSL_SMALL_STACK_CACHE) + byte* digest = drbg->digest_scratch; +#elif defined(WOLFSSL_SMALL_STACK) + byte* digest; +#else + byte digest[WC_SHA512_DIGEST_SIZE]; +#endif + + if (drbg == NULL) { + return DRBG_FAILURE; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap, + DYNAMIC_TYPE_DIGEST); + if (digest == NULL) + return DRBG_FAILURE; +#endif + +#ifdef LITTLE_ENDIAN_ORDER + bits = ByteReverseWord32(bits); +#endif + len = (outSz / OUTPUT_BLOCK_LEN_SHA512) + + ((outSz % OUTPUT_BLOCK_LEN_SHA512) ? 1 : 0); + + ctr = 1; + for (i = 0; i < len; i++) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha512(sha); + #endif + if (ret != 0) + break; +#endif + ret = wc_Sha512Update(sha, &ctr, sizeof(ctr)); + if (ret == 0) { + ctr++; + ret = wc_Sha512Update(sha, (byte*)&bits, sizeof(bits)); + } + + if (ret == 0) { + /* churning V is the only string that doesn't have the type added */ + if (type != drbgInitV) + ret = wc_Sha512Update(sha, &type, sizeof(type)); + } + if (ret == 0) + ret = wc_Sha512Update(sha, inA, inASz); + if (ret == 0) { + if (inB != NULL && inBSz > 0) + ret = wc_Sha512Update(sha, inB, inBSz); + } + if (ret == 0) + ret = wc_Sha512Final(sha, digest); + +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha512Free(sha); +#endif + if (ret == 0) { + if (outSz > OUTPUT_BLOCK_LEN_SHA512) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN_SHA512); + outSz -= OUTPUT_BLOCK_LEN_SHA512; + out += OUTPUT_BLOCK_LEN_SHA512; + } + else { + XMEMCPY(out, digest, outSz); + } + } + } + + ForceZero(digest, WC_SHA512_DIGEST_SIZE); + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); +#endif + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash512_DRBG_Reseed(DRBG_SHA512_internal* drbg, const byte* seed, + word32 seedSz) +{ + int ret; + WC_DECLARE_VAR(newV, byte, DRBG_SHA512_SEED_LEN, 0); + + if (drbg == NULL) { + return DRBG_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK_CACHE + newV = drbg->seed_scratch; +#else + WC_ALLOC_VAR_EX(newV, byte, DRBG_SHA512_SEED_LEN, drbg->heap, + DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E); +#endif + XMEMSET(newV, 0, DRBG_SHA512_SEED_LEN); + + ret = Hash512_df(drbg, newV, DRBG_SHA512_SEED_LEN, drbgReseed, + drbg->V, sizeof(drbg->V), seed, seedSz); + if (ret == DRBG_SUCCESS) { + XMEMCPY(drbg->V, newV, sizeof(drbg->V)); + ForceZero(newV, DRBG_SHA512_SEED_LEN); + + ret = Hash512_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, + sizeof(drbg->V), NULL, 0); + } + if (ret == DRBG_SUCCESS) { + drbg->reseedCtr = 1; + } + +#ifndef WOLFSSL_SMALL_STACK_CACHE + WC_FREE_VAR_EX(newV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash512_gen(DRBG_SHA512_internal* drbg, byte* out, word32 outSz, + const byte* V) +{ + int ret = DRBG_FAILURE; + word32 i; + word32 len; +#if defined(WOLFSSL_SMALL_STACK_CACHE) + wc_Sha512* sha = &drbg->sha512; + byte* data = drbg->seed_scratch; + byte* digest = drbg->digest_scratch; +#elif defined(WOLFSSL_SMALL_STACK) + wc_Sha512 sha[1]; + byte* data = NULL; + byte* digest = NULL; +#else + wc_Sha512 sha[1]; + byte data[DRBG_SHA512_SEED_LEN]; + byte digest[WC_SHA512_DIGEST_SIZE]; +#endif + + if (drbg == NULL) { + return DRBG_FAILURE; + } + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + data = (byte*)XMALLOC(DRBG_SHA512_SEED_LEN, drbg->heap, + DYNAMIC_TYPE_TMP_BUFFER); + digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap, + DYNAMIC_TYPE_DIGEST); + if (data == NULL || digest == NULL) { + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); + XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); + return DRBG_FAILURE; + } +#endif + + /* Special case: outSz is 0 and out is NULL. Generate a block to save for + * the continuous test. */ + if (outSz == 0) { + outSz = 1; + } + + len = (outSz / OUTPUT_BLOCK_LEN_SHA512) + + ((outSz % OUTPUT_BLOCK_LEN_SHA512) ? 1 : 0); + + XMEMCPY(data, V, DRBG_SHA512_SEED_LEN); + for (i = 0; i < len; i++) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha512(sha); + #endif + if (ret == 0) +#endif + ret = wc_Sha512Update(sha, data, DRBG_SHA512_SEED_LEN); + if (ret == 0) + ret = wc_Sha512Final(sha, digest); +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha512Free(sha); +#endif + + if (ret == 0) { + if (out != NULL && outSz != 0) { + if (outSz >= OUTPUT_BLOCK_LEN_SHA512) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN_SHA512); + outSz -= OUTPUT_BLOCK_LEN_SHA512; + out += OUTPUT_BLOCK_LEN_SHA512; + array_add_one(data, DRBG_SHA512_SEED_LEN); + } + else { + XMEMCPY(out, digest, outSz); + outSz = 0; + } + } + } + else { + break; + } + } + ForceZero(data, DRBG_SHA512_SEED_LEN); + +#ifndef WOLFSSL_SMALL_STACK_CACHE + WC_FREE_VAR_EX(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); + WC_FREE_VAR_EX(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */ +static int Hash512_DRBG_Generate(DRBG_SHA512_internal* drbg, byte* out, + word32 outSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha512* sha = &drbg->sha512; +#else + wc_Sha512 sha[1]; +#endif + byte type; + word64 reseedCtr; + + if (drbg == NULL) { + return DRBG_FAILURE; + } + + if (drbg->reseedCtr >= WC_RESEED_INTERVAL) { + return DRBG_NEED_RESEED; + } + else { + #if defined(WOLFSSL_SMALL_STACK_CACHE) + byte* digest = drbg->digest_scratch; + #elif defined(WOLFSSL_SMALL_STACK) + byte* digest = (byte*)XMALLOC(WC_SHA512_DIGEST_SIZE, drbg->heap, + DYNAMIC_TYPE_DIGEST); + if (digest == NULL) + return DRBG_FAILURE; + #else + byte digest[WC_SHA512_DIGEST_SIZE]; + #endif + + type = drbgGenerateH; + reseedCtr = drbg->reseedCtr; + + ret = Hash512_gen(drbg, out, outSz, drbg->V); + if (ret == DRBG_SUCCESS) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha512_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha512(sha); + #endif + if (ret == 0) +#endif + ret = wc_Sha512Update(sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha512Update(sha, drbg->V, sizeof(drbg->V)); + if (ret == 0) + ret = wc_Sha512Final(sha, digest); + +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha512Free(sha); +#endif + + if (ret == 0) { + array_add(drbg->V, sizeof(drbg->V), digest, + WC_SHA512_DIGEST_SIZE); + array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C)); + #ifdef LITTLE_ENDIAN_ORDER + reseedCtr = ByteReverseWord64(reseedCtr); + #endif + array_add(drbg->V, sizeof(drbg->V), + (byte*)&reseedCtr, sizeof(reseedCtr)); + ret = DRBG_SUCCESS; + } + drbg->reseedCtr++; + } + ForceZero(digest, WC_SHA512_DIGEST_SIZE); + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash512_DRBG_Init(DRBG_SHA512_internal* drbg, const byte* seed, + word32 seedSz, const byte* nonce, word32 nonceSz) +{ + if (seed == NULL) + return DRBG_FAILURE; + + if (Hash512_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz, + nonce, nonceSz) == DRBG_SUCCESS && + Hash512_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, + sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) { + + drbg->reseedCtr = 1; + return DRBG_SUCCESS; + } + else { + return DRBG_FAILURE; + } +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash512_DRBG_Instantiate(DRBG_SHA512_internal* drbg, + const byte* seed, word32 seedSz, + const byte* nonce, word32 nonceSz, + void* heap, int devId) +{ + int ret = DRBG_FAILURE; + + XMEMSET(drbg, 0, sizeof(DRBG_SHA512_internal)); + drbg->heap = heap; +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + drbg->devId = devId; +#else + (void)devId; +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha512_ex(&drbg->sha512, drbg->heap, drbg->devId); + #else + ret = wc_InitSha512(&drbg->sha512); + #endif + if (ret != 0) + return ret; +#endif + + if (seed != NULL) + ret = Hash512_DRBG_Init(drbg, seed, seedSz, nonce, nonceSz); + return ret; +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash512_DRBG_Uninstantiate(DRBG_SHA512_internal* drbg) +{ + word32 i; + int compareSum = 0; + byte* compareDrbg = (byte*)drbg; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha512Free(&drbg->sha512); +#endif + + ForceZero(drbg, sizeof(DRBG_SHA512_internal)); + + for (i = 0; i < sizeof(DRBG_SHA512_internal); i++) { + compareSum |= compareDrbg[i] ^ 0; + } + + return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +#endif /* WOLFSSL_DRBG_SHA512 */ + /* FIPS 140-3 IG 10.3.A / SP800-90B Health Tests for Seed Data * @@ -875,6 +1323,64 @@ int wc_RNG_TestSeed(const byte* seed, word32 seedSz) return ret; } +/* Runtime DRBG disable/enable API -- only available in non-selftest and + * FIPS v7+ builds (older FIPS/selftest random.c doesn't have these) */ +#if !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) +#ifndef NO_SHA256 +int wc_Sha256Drbg_Disable(void) +{ +#ifdef WOLFSSL_DRBG_SHA512 + if (sha512DrbgDisabled) + return BAD_STATE_E; /* can't disable both */ + sha256DrbgDisabled = 1; + return 0; +#else + return NOT_COMPILED_IN; +#endif +} + +int wc_Sha256Drbg_Enable(void) +{ + sha256DrbgDisabled = 0; + return 0; +} + +int wc_Sha256Drbg_GetStatus(void) +{ + return sha256DrbgDisabled; +} +#else +/* When SHA-256 is not compiled in, these are stubs */ +int wc_Sha256Drbg_Disable(void) { return NOT_COMPILED_IN; } +int wc_Sha256Drbg_Enable(void) { return 0; } +int wc_Sha256Drbg_GetStatus(void) { return 1; } /* always disabled */ +#endif /* !NO_SHA256 */ +#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */ + +#ifdef WOLFSSL_DRBG_SHA512 +int wc_Sha512Drbg_Disable(void) +{ +#ifndef NO_SHA256 + if (sha256DrbgDisabled) + return BAD_STATE_E; /* can't disable both */ +#endif + sha512DrbgDisabled = 1; + return 0; +} + +int wc_Sha512Drbg_Enable(void) +{ + sha512DrbgDisabled = 0; + return 0; +} + +int wc_Sha512Drbg_GetStatus(void) +{ + return sha512DrbgDisabled; +} +#endif /* WOLFSSL_DRBG_SHA512 */ + #endif /* HAVE_HASHDRBG */ /* End NIST DRBG Code */ @@ -925,11 +1431,41 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, #ifdef HAVE_HASHDRBG /* init the DBRG to known values */ +#ifndef NO_SHA256 rng->drbg = NULL; #ifdef WOLFSSL_SMALL_STACK_CACHE rng->drbg_scratch = NULL; #endif +#endif +#ifdef WOLFSSL_DRBG_SHA512 + rng->drbg512 = NULL; + #ifdef WOLFSSL_SMALL_STACK_CACHE + rng->drbg512_scratch = NULL; + rng->health_check_scratch_512 = NULL; + #endif +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + rng->newSeed_buf = NULL; +#ifndef NO_SHA256 + rng->health_check_scratch = NULL; +#endif +#endif rng->status = DRBG_NOT_INIT; + + /* Select DRBG type: prefer SHA-512 unless disabled or not compiled */ +#ifdef WOLFSSL_DRBG_SHA512 + if (!wc_Sha512Drbg_GetStatus()) + rng->drbgType = WC_DRBG_SHA512; + else +#endif +#ifndef NO_SHA256 + if (!wc_Sha256Drbg_GetStatus()) + rng->drbgType = WC_DRBG_SHA256; + else +#endif + { + return BAD_STATE_E; /* no DRBG available */ + } #endif #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) || \ @@ -985,54 +1521,110 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, seedSz = MAX_SEED_SZ; } -#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) - rng->drbg = - (struct DRBG*)XMALLOC(sizeof(DRBG_internal), rng->heap, - DYNAMIC_TYPE_RNG); - if (rng->drbg == NULL) { - #if defined(DEBUG_WOLFSSL) - WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes", - sizeof(DRBG_internal)); - #endif - ret = MEMORY_E; - rng->status = DRBG_FAILED; - } -#else - rng->drbg = (struct DRBG*)&rng->drbg_data; -#endif /* WOLFSSL_NO_MALLOC or WOLFSSL_STATIC_MEMORY */ - -#ifdef WOLFSSL_SMALL_STACK_CACHE - if (ret == 0) { - rng->drbg_scratch = - (DRBG_internal *)XMALLOC(sizeof(DRBG_internal), rng->heap, - DYNAMIC_TYPE_RNG); - if (rng->drbg_scratch == NULL) { -#if defined(DEBUG_WOLFSSL) +#ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) { + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + rng->drbg = + (struct DRBG*)XMALLOC(sizeof(DRBG_internal), rng->heap, + DYNAMIC_TYPE_RNG); + if (rng->drbg == NULL) { + #if defined(DEBUG_WOLFSSL) WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes", sizeof(DRBG_internal)); -#endif + #endif ret = MEMORY_E; rng->status = DRBG_FAILED; } - } + #else + rng->drbg = (struct DRBG*)&rng->drbg_data; + #endif /* WOLFSSL_NO_MALLOC or WOLFSSL_STATIC_MEMORY */ - if (ret == 0) { - ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg_scratch, - NULL /* seed */, 0, NULL /* nonce */, 0, rng->heap, devId); - if (ret == 0) - drbg_scratch_instantiated = 1; - } + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (ret == 0) { + rng->drbg_scratch = + (DRBG_internal *)XMALLOC(sizeof(DRBG_internal), rng->heap, + DYNAMIC_TYPE_RNG); + if (rng->drbg_scratch == NULL) { + #if defined(DEBUG_WOLFSSL) + WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes", + sizeof(DRBG_internal)); + #endif + ret = MEMORY_E; + rng->status = DRBG_FAILED; + } + } - if (ret == 0) { - rng->health_check_scratch = - (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, rng->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (rng->health_check_scratch == NULL) { + if (ret == 0) { + ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg_scratch, + NULL, 0, NULL, 0, rng->heap, devId); + if (ret == 0) + drbg_scratch_instantiated = 1; + } + + if (ret == 0) { + rng->health_check_scratch = + (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, rng->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (rng->health_check_scratch == NULL) { + ret = MEMORY_E; + rng->status = DRBG_FAILED; + } + } + #endif /* WOLFSSL_SMALL_STACK_CACHE */ + } /* WC_DRBG_SHA256 */ +#endif /* !NO_SHA256 */ + +#ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbgType == WC_DRBG_SHA512) { + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + rng->drbg512 = + (struct DRBG_SHA512*)XMALLOC(sizeof(DRBG_SHA512_internal), + rng->heap, DYNAMIC_TYPE_RNG); + if (rng->drbg512 == NULL) { + #if defined(DEBUG_WOLFSSL) + WOLFSSL_MSG_EX("_InitRng XMALLOC failed to allocate %d bytes", + sizeof(DRBG_SHA512_internal)); + #endif ret = MEMORY_E; rng->status = DRBG_FAILED; } - } + #else + rng->drbg512 = (struct DRBG_SHA512*)&rng->drbg512_data; + #endif + + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (ret == 0) { + rng->drbg512_scratch = + (DRBG_SHA512_internal *)XMALLOC(sizeof(DRBG_SHA512_internal), + rng->heap, DYNAMIC_TYPE_RNG); + if (rng->drbg512_scratch == NULL) { + ret = MEMORY_E; + rng->status = DRBG_FAILED; + } + } + + if (ret == 0) { + ret = Hash512_DRBG_Instantiate(rng->drbg512_scratch, + NULL, 0, NULL, 0, rng->heap, devId); + if (ret == 0) + drbg_scratch_instantiated = 1; + } + + if (ret == 0) { + rng->health_check_scratch_512 = + (byte *)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE_SHA512, rng->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (rng->health_check_scratch_512 == NULL) { + ret = MEMORY_E; + rng->status = DRBG_FAILED; + } + } + #endif /* WOLFSSL_SMALL_STACK_CACHE */ + } /* WC_DRBG_SHA512 */ +#endif /* WOLFSSL_DRBG_SHA512 */ + /* newSeed_buf shared by both DRBG types for PollAndReSeed */ +#ifdef WOLFSSL_SMALL_STACK_CACHE if (ret == 0) { rng->newSeed_buf = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap, DYNAMIC_TYPE_SEED); @@ -1113,14 +1705,29 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, } #endif - if (ret == DRBG_SUCCESS) - ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg, - #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED) - seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ, - #else - seed, seedSz, - #endif - nonce, nonceSz, rng->heap, devId); + if (ret == DRBG_SUCCESS) { +#ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) + ret = Hash_DRBG_Instantiate((DRBG_internal *)rng->drbg, + #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED) + seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ, + #else + seed, seedSz, + #endif + nonce, nonceSz, rng->heap, devId); +#endif +#ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbgType == WC_DRBG_SHA512) + ret = Hash512_DRBG_Instantiate( + (DRBG_SHA512_internal *)rng->drbg512, + #if defined(HAVE_FIPS) || !defined(WOLFSSL_RNG_USE_FULL_SEED) + seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ, + #else + seed, seedSz, + #endif + nonce, nonceSz, rng->heap, devId); +#endif + } } /* ret == 0 */ #ifdef WOLFSSL_SMALL_STACK @@ -1132,29 +1739,56 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, WC_FREE_VAR_EX(seed, rng->heap, DYNAMIC_TYPE_SEED); if (ret != DRBG_SUCCESS) { - #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) - XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + #ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) { + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + #endif + rng->drbg = NULL; + #ifdef WOLFSSL_SMALL_STACK_CACHE + XFREE(rng->health_check_scratch, rng->heap, + DYNAMIC_TYPE_TMP_BUFFER); + rng->health_check_scratch = NULL; + if (drbg_scratch_instantiated) + (void)Hash_DRBG_Uninstantiate( + (DRBG_internal *)rng->drbg_scratch); + XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG); + rng->drbg_scratch = NULL; + #endif + } + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbgType == WC_DRBG_SHA512) { + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(rng->drbg512, rng->heap, DYNAMIC_TYPE_RNG); + #endif + rng->drbg512 = NULL; + #ifdef WOLFSSL_SMALL_STACK_CACHE + XFREE(rng->health_check_scratch_512, rng->heap, + DYNAMIC_TYPE_TMP_BUFFER); + rng->health_check_scratch_512 = NULL; + if (drbg_scratch_instantiated) + (void)Hash512_DRBG_Uninstantiate(rng->drbg512_scratch); + XFREE(rng->drbg512_scratch, rng->heap, DYNAMIC_TYPE_RNG); + rng->drbg512_scratch = NULL; + #endif + } #endif - rng->drbg = NULL; #ifdef WOLFSSL_SMALL_STACK_CACHE - XFREE(rng->health_check_scratch, rng->heap, DYNAMIC_TYPE_TMP_BUFFER); - rng->health_check_scratch = NULL; - XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_SEED); rng->newSeed_buf = NULL; - if (drbg_scratch_instantiated) - (void)Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg_scratch); - XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG); - rng->drbg_scratch = NULL; #endif } /* else wc_RNG_HealthTestLocal was successful */ if (ret == DRBG_SUCCESS) { #ifdef WOLFSSL_CHECK_MEM_ZERO - #ifdef HAVE_HASHDRBG - struct DRBG_internal* drbg = (struct DRBG_internal*)rng->drbg; - wc_MemZero_Add("DRBG V", &drbg->V, sizeof(drbg->V)); - wc_MemZero_Add("DRBG C", &drbg->C, sizeof(drbg->C)); + #ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) { + struct DRBG_internal* drbg = (struct DRBG_internal*)rng->drbg; + wc_MemZero_Add("DRBG V", &drbg->V, sizeof(drbg->V)); + wc_MemZero_Add("DRBG C", &drbg->C, sizeof(drbg->C)); + } #endif #endif @@ -1315,9 +1949,19 @@ static int PollAndReSeed(WC_RNG* rng) "err %d.", ret); #endif } - if (ret == DRBG_SUCCESS) - ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, - newSeed + SEED_BLOCK_SZ, SEED_SZ); + if (ret == DRBG_SUCCESS) { +#ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) + ret = Hash_DRBG_Reseed((DRBG_internal *)rng->drbg, + newSeed + SEED_BLOCK_SZ, SEED_SZ); +#endif +#ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbgType == WC_DRBG_SHA512) + ret = Hash512_DRBG_Reseed( + (DRBG_SHA512_internal *)rng->drbg512, + newSeed + SEED_BLOCK_SZ, SEED_SZ); +#endif + } #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) if (newSeed != NULL) { ForceZero(newSeed, SEED_SZ + SEED_BLOCK_SZ); @@ -1413,11 +2057,33 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) } #endif - ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); - if (ret == DRBG_NEED_RESEED) { - ret = PollAndReSeed(rng); - if (ret == DRBG_SUCCESS) - ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); +#ifndef NO_SHA256 + if (rng->drbgType == WC_DRBG_SHA256) { + ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); + if (ret == DRBG_NEED_RESEED) { + ret = PollAndReSeed(rng); + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, + sz); + } + } + else +#endif +#ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbgType == WC_DRBG_SHA512) { + ret = Hash512_DRBG_Generate((DRBG_SHA512_internal *)rng->drbg512, + output, sz); + if (ret == DRBG_NEED_RESEED) { + ret = PollAndReSeed(rng); + if (ret == DRBG_SUCCESS) + ret = Hash512_DRBG_Generate( + (DRBG_SHA512_internal *)rng->drbg512, output, sz); + } + } + else +#endif + { + ret = DRBG_FAILURE; } if (ret == DRBG_SUCCESS) { @@ -1502,6 +2168,7 @@ int wc_FreeRng(WC_RNG* rng) #endif #ifdef HAVE_HASHDRBG +#ifndef NO_SHA256 if (rng->drbg != NULL) { if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg) != DRBG_SUCCESS) ret = RNG_FAILURE_E; @@ -1512,20 +2179,51 @@ int wc_FreeRng(WC_RNG* rng) wc_MemZero_Check(rng->drbg, sizeof(DRBG_internal)); #endif rng->drbg = NULL; - } #ifdef WOLFSSL_SMALL_STACK_CACHE - if (rng->drbg_scratch != NULL) { - if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg_scratch) != DRBG_SUCCESS) + if (rng->drbg_scratch != NULL) { + if (Hash_DRBG_Uninstantiate((DRBG_internal *)rng->drbg_scratch) + != DRBG_SUCCESS) + ret = RNG_FAILURE_E; + XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG); + rng->drbg_scratch = NULL; + } + XFREE(rng->health_check_scratch, rng->heap, DYNAMIC_TYPE_TMP_BUFFER); + rng->health_check_scratch = NULL; + #endif + } +#endif /* !NO_SHA256 */ + +#ifdef WOLFSSL_DRBG_SHA512 + if (rng->drbg512 != NULL) { + if (Hash512_DRBG_Uninstantiate( + (DRBG_SHA512_internal *)rng->drbg512) != DRBG_SUCCESS) ret = RNG_FAILURE_E; - XFREE(rng->drbg_scratch, rng->heap, DYNAMIC_TYPE_RNG); - rng->drbg_scratch = NULL; + + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(rng->drbg512, rng->heap, DYNAMIC_TYPE_RNG); + #endif + rng->drbg512 = NULL; + + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (rng->drbg512_scratch != NULL) { + if (Hash512_DRBG_Uninstantiate(rng->drbg512_scratch) + != DRBG_SUCCESS) + ret = RNG_FAILURE_E; + XFREE(rng->drbg512_scratch, rng->heap, DYNAMIC_TYPE_RNG); + rng->drbg512_scratch = NULL; + } + XFREE(rng->health_check_scratch_512, rng->heap, + DYNAMIC_TYPE_TMP_BUFFER); + rng->health_check_scratch_512 = NULL; + #endif } - XFREE(rng->health_check_scratch, rng->heap, DYNAMIC_TYPE_RNG); - rng->health_check_scratch = NULL; - XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_RNG); +#endif /* WOLFSSL_DRBG_SHA512 */ + +#ifdef WOLFSSL_SMALL_STACK_CACHE + XFREE(rng->newSeed_buf, rng->heap, DYNAMIC_TYPE_SEED); rng->newSeed_buf = NULL; - #endif +#endif rng->status = DRBG_NOT_INIT; #endif /* HAVE_HASHDRBG */ @@ -1720,10 +2418,180 @@ const FLASH_QUALIFIER byte outputB_data[] = { }; +/* SHA-512 DRBG KAT vectors for local health test. + * Source: NIST CAVP Hash_DRBG.rsp, [SHA-512], PredictionResistance=False, + * EntropyInputLen=256, NonceLen=128, PersonalizationStringLen=0, + * AdditionalInputLen=0, ReturnedBitsLen=2048. */ +#ifdef WOLFSSL_DRBG_SHA512 + +/* Reseed test vectors (COUNT=0 from reseed section) */ +static const byte sha512_seedA_data[] = { + /* EntropyInput (32 bytes) || Nonce (16 bytes) */ + 0x31, 0x44, 0xe1, 0x7a, 0x10, 0xc8, 0x56, 0x12, + 0x97, 0x64, 0xf5, 0x8f, 0xd8, 0xe4, 0x23, 0x10, + 0x20, 0x54, 0x69, 0x96, 0xc0, 0xbf, 0x6c, 0xff, + 0x8e, 0x91, 0xc2, 0x4e, 0xe0, 0x9b, 0xe3, 0x33, + 0xb1, 0x6f, 0xcb, 0x1c, 0xf0, 0xc0, 0x10, 0xf3, + 0x1f, 0xea, 0xb7, 0x33, 0x58, 0x8b, 0x8e, 0x04 +}; +static const byte sha512_reseedSeedA_data[] = { + /* EntropyInputReseed (32 bytes) */ + 0xa0, 0xb3, 0x58, 0x4c, 0x2c, 0x84, 0x12, 0xf6, + 0x18, 0x40, 0x68, 0x34, 0x40, 0x4d, 0x1e, 0xb0, + 0xce, 0x99, 0x9b, 0xa2, 0x89, 0x66, 0x05, 0x4d, + 0x7e, 0x49, 0x7e, 0x0d, 0xb6, 0x08, 0xb9, 0x67 +}; +static const byte sha512_outputA_data[] = { + 0xef, 0xa3, 0x5d, 0xd0, 0x36, 0x2a, 0xdb, 0x76, + 0x26, 0x45, 0x6b, 0x36, 0xfa, 0xc7, 0x4d, 0x3c, + 0x28, 0xd0, 0x1d, 0x92, 0x64, 0x20, 0x27, 0x5a, + 0x28, 0xbe, 0xa9, 0xc9, 0xdd, 0x75, 0x47, 0xc1, + 0x5e, 0x79, 0x31, 0x85, 0x2a, 0xc1, 0x27, 0x70, + 0x76, 0x56, 0x75, 0x35, 0x23, 0x9c, 0x1f, 0x42, + 0x9c, 0x7f, 0x75, 0xcf, 0x74, 0xc2, 0x26, 0x7d, + 0xeb, 0x6a, 0x3e, 0x59, 0x6c, 0xf3, 0x26, 0x15, + 0x6c, 0x79, 0x69, 0x41, 0x28, 0x3b, 0x8d, 0x58, + 0x3f, 0x17, 0x1c, 0x2f, 0x6e, 0x33, 0x23, 0xf7, + 0x55, 0x5e, 0x1b, 0x18, 0x1f, 0xfd, 0xa3, 0x05, + 0x07, 0x21, 0x0c, 0xb1, 0xf5, 0x89, 0xb2, 0x3c, + 0xd7, 0x18, 0x80, 0xfd, 0x44, 0x37, 0x0c, 0xac, + 0xf4, 0x33, 0x75, 0xb0, 0xdb, 0x7e, 0x33, 0x6f, + 0x12, 0xb3, 0x09, 0xbf, 0xd4, 0xf6, 0x10, 0xbb, + 0x8f, 0x20, 0xe1, 0xa1, 0x5e, 0x25, 0x3a, 0x4f, + 0xe5, 0x11, 0xa0, 0x27, 0x96, 0x8d, 0xf0, 0xb1, + 0x05, 0xa1, 0xd7, 0x3a, 0xff, 0x7c, 0x7a, 0x82, + 0x6d, 0x39, 0xf6, 0x40, 0xdf, 0xb8, 0xf5, 0x22, + 0x25, 0x9e, 0xd4, 0x02, 0x28, 0x2e, 0x2c, 0x2e, + 0x9d, 0x3a, 0x49, 0x8f, 0x51, 0x72, 0x5f, 0xe4, + 0x14, 0x1b, 0x06, 0xda, 0x55, 0x98, 0xa4, 0x2a, + 0xc1, 0xe0, 0x49, 0x4e, 0x99, 0x7d, 0x56, 0x6a, + 0x1a, 0x39, 0xb6, 0x76, 0xb9, 0x6a, 0x60, 0x03, + 0xa4, 0xc5, 0xdb, 0x84, 0xf2, 0x46, 0x58, 0x4e, + 0xe6, 0x5a, 0xf7, 0x0f, 0xf2, 0x16, 0x02, 0x78, + 0x16, 0x6d, 0xa1, 0x6d, 0x91, 0xc9, 0xb8, 0xf2, + 0xde, 0xb0, 0x27, 0x51, 0xa1, 0x08, 0x8a, 0xd6, + 0xbe, 0x4e, 0x80, 0xef, 0x96, 0x6e, 0xb7, 0x3e, + 0x66, 0xbc, 0x87, 0xca, 0xd8, 0x7c, 0x77, 0xc0, + 0xb3, 0x4a, 0x21, 0xba, 0x1d, 0xa0, 0xba, 0x6d, + 0x16, 0xca, 0x50, 0x46, 0xdc, 0x4a, 0xbd, 0xa0 +}; + +/* No-reseed test vectors (COUNT=0 from no-reseed section) */ +static const byte sha512_seedB_data[] = { + /* EntropyInput (32 bytes) || Nonce (16 bytes) */ + 0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a, + 0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22, + 0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b, + 0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c, + 0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa, + 0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25 +}; +static const byte sha512_outputB_data[] = { + 0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57, + 0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6, + 0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d, + 0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf, + 0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26, + 0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64, + 0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55, + 0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a, + 0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78, + 0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e, + 0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb, + 0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30, + 0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19, + 0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f, + 0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d, + 0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a, + 0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2, + 0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd, + 0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd, + 0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2, + 0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b, + 0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1, + 0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99, + 0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e, + 0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3, + 0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67, + 0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3, + 0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d, + 0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b, + 0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13, + 0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c, + 0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 +}; +#endif /* WOLFSSL_DRBG_SHA512 */ + + static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap, int devId) { int ret = 0; + +#ifdef WOLFSSL_DRBG_SHA512 + /* SHA-512 DRBG health test path */ + if (rng->drbgType == WC_DRBG_SHA512) { + #ifdef WOLFSSL_SMALL_STACK_CACHE + byte *check512 = rng->health_check_scratch_512; + DRBG_SHA512_internal* drbg512 = rng->drbg512_scratch; + #else + WC_DECLARE_VAR(check512, byte, RNG_HEALTH_TEST_CHECK_SIZE_SHA512, 0); + WC_DECLARE_VAR(drbg512, DRBG_SHA512_internal, 1, 0); + + WC_ALLOC_VAR_EX(check512, byte, RNG_HEALTH_TEST_CHECK_SIZE_SHA512, + heap, DYNAMIC_TYPE_TMP_BUFFER, return MEMORY_E); + WC_ALLOC_VAR_EX(drbg512, DRBG_SHA512_internal, + sizeof(DRBG_SHA512_internal), heap, DYNAMIC_TYPE_TMP_BUFFER, + WC_DO_NOTHING); + #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC + if (drbg512 == NULL) { + WC_FREE_VAR_EX(check512, heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + #endif + + if (reseed) { + /* Reseed test with NIST CAVP SHA-512 vectors */ + ret = wc_RNG_HealthTest_SHA512_ex_internal( + drbg512, 1, NULL, 0, + sha512_seedA_data, sizeof(sha512_seedA_data), + sha512_reseedSeedA_data, + sizeof(sha512_reseedSeedA_data), + check512, RNG_HEALTH_TEST_CHECK_SIZE_SHA512, + heap, devId); + if (ret == 0) { + if (ConstantCompare(check512, sha512_outputA_data, + RNG_HEALTH_TEST_CHECK_SIZE_SHA512) != 0) + ret = -1; + } + } + else { + /* No-reseed test with NIST CAVP SHA-512 vectors */ + ret = wc_RNG_HealthTest_SHA512_ex_internal( + drbg512, 0, NULL, 0, + sha512_seedB_data, sizeof(sha512_seedB_data), + NULL, 0, + check512, RNG_HEALTH_TEST_CHECK_SIZE_SHA512, + heap, devId); + if (ret == 0) { + if (ConstantCompare(check512, sha512_outputB_data, + RNG_HEALTH_TEST_CHECK_SIZE_SHA512) != 0) + ret = -1; + } + } + + #ifndef WOLFSSL_SMALL_STACK_CACHE + WC_FREE_VAR_EX(check512, heap, DYNAMIC_TYPE_TMP_BUFFER); + WC_FREE_VAR_EX(drbg512, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } +#endif /* WOLFSSL_DRBG_SHA512 */ + + /* SHA-256 DRBG health test path (original) */ +#ifndef NO_SHA256 + { #ifdef WOLFSSL_SMALL_STACK_CACHE byte *check = rng->health_check_scratch; DRBG_internal* drbg = (DRBG_internal *)rng->drbg_scratch; @@ -1861,10 +2729,204 @@ static int wc_RNG_HealthTestLocal(WC_RNG* rng, int reseed, void* heap, WC_FREE_VAR_EX(check, heap, DYNAMIC_TYPE_TMP_BUFFER); WC_FREE_VAR_EX(drbg, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + } /* SHA-256 path */ +#endif /* !NO_SHA256 */ + + return ret; +} + +/* ====================================================================== */ +/* SHA-512 Health Test API */ +/* ====================================================================== */ +#ifdef WOLFSSL_DRBG_SHA512 + +static int wc_RNG_HealthTest_SHA512_ex_internal(DRBG_SHA512_internal* drbg, + int reseed, const byte* nonce, word32 nonceSz, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz, + void* heap, int devId) +{ + int ret = -1; + + if (seedA == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + if (reseed != 0 && seedB == NULL) { + return BAD_FUNC_ARG; + } + + if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE_SHA512) { + return ret; + } + +#ifdef WOLFSSL_SMALL_STACK_CACHE + (void)heap; + (void)devId; + + if (Hash512_DRBG_Init(drbg, seedA, seedASz, nonce, nonceSz) != 0) { + goto exit_rng_ht512; + } +#else + if (Hash512_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz, + heap, devId) != 0) { + goto exit_rng_ht512; + } +#endif + + if (reseed) { + if (Hash512_DRBG_Reseed(drbg, seedB, seedBSz) != 0) { + goto exit_rng_ht512; + } + } + + /* First generate: output discarded per NIST DRBGVS procedure */ + if (Hash512_DRBG_Generate(drbg, output, outputSz) != 0) { + goto exit_rng_ht512; + } + + /* Second generate: this is the actual test output */ + if (Hash512_DRBG_Generate(drbg, output, outputSz) != 0) { + goto exit_rng_ht512; + } + + ret = 0; + +exit_rng_ht512: + +#ifndef WOLFSSL_SMALL_STACK_CACHE + if (Hash512_DRBG_Uninstantiate(drbg) != 0) { + ret = -1; + } +#endif + + return ret; +} + + +/* Extended API with personalization string and additional input + * for ACVP testing */ +int wc_RNG_HealthTest_SHA512_ex(int reseed, + const byte* nonce, word32 nonceSz, + const byte* persoString, word32 persoStringSz, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + const byte* additionalA, word32 additionalASz, + const byte* additionalB, word32 additionalBSz, + byte* output, word32 outputSz, + void* heap, int devId) +{ + int ret = -1; + DRBG_SHA512_internal* drbg; +#ifndef WOLFSSL_SMALL_STACK + DRBG_SHA512_internal drbg_var; +#endif + + /* Suppress unused parameter warnings for future use */ + (void)persoString; + (void)persoStringSz; + (void)additionalA; + (void)additionalASz; + (void)additionalB; + (void)additionalBSz; + + if (seedA == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE_SHA512) { + return ret; + } + +#ifdef WOLFSSL_SMALL_STACK + drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), heap, + DYNAMIC_TYPE_RNG); + if (drbg == NULL) { + return MEMORY_E; + } +#else + drbg = &drbg_var; +#endif + + /* For the extended API, personalization string is concatenated + * with entropy during instantiation per SP 800-90A Sec 10.1.1.2. + * For now we use the simple path (persoString not yet wired into + * Hash512_df). This can be extended for full ACVP support. */ + ret = Hash512_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz, + heap, devId); + if (ret != 0) { + goto exit_sha512_ex; + } + + if (reseed) { + if (seedB != NULL && seedBSz > 0) { + ret = Hash512_DRBG_Reseed(drbg, seedB, seedBSz); + if (ret != 0) goto exit_sha512_ex; + } + } + + /* First generate (output discarded per NIST procedure) */ + ret = Hash512_DRBG_Generate(drbg, output, outputSz); + if (ret != 0) goto exit_sha512_ex; + + /* Second generate (this is the actual output) */ + ret = Hash512_DRBG_Generate(drbg, output, outputSz); + +exit_sha512_ex: + (void)Hash512_DRBG_Uninstantiate(drbg); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(drbg, heap, DYNAMIC_TYPE_RNG); +#endif + + return (ret == DRBG_SUCCESS) ? 0 : -1; +} + + +/* Simple API matching wc_RNG_HealthTest() pattern - entropy+nonce only */ +int wc_RNG_HealthTest_SHA512(int reseed, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz) +{ + int ret = -1; + DRBG_SHA512_internal* drbg; +#ifndef WOLFSSL_SMALL_STACK + DRBG_SHA512_internal drbg_var; +#endif + +#ifdef WOLFSSL_SMALL_STACK + drbg = (DRBG_SHA512_internal*)XMALLOC(sizeof(DRBG_SHA512_internal), NULL, + DYNAMIC_TYPE_RNG); + if (drbg == NULL) { + return MEMORY_E; + } +#else + drbg = &drbg_var; +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + ret = Hash512_DRBG_Instantiate(drbg, + NULL /* seed */, 0, NULL /* nonce */, 0, NULL, INVALID_DEVID); + if (ret == 0) +#endif + { + ret = wc_RNG_HealthTest_SHA512_ex_internal( + drbg, reseed, NULL, 0, + seedA, seedASz, seedB, seedBSz, + output, outputSz, NULL, INVALID_DEVID); +#ifdef WOLFSSL_SMALL_STACK_CACHE + Hash512_DRBG_Uninstantiate(drbg); +#endif + } + WC_FREE_VAR_EX(drbg, NULL, DYNAMIC_TYPE_RNG); return ret; } +#endif /* WOLFSSL_DRBG_SHA512 */ + #endif /* HAVE_HASHDRBG */ diff --git a/wolfcrypt/src/rng_bank.c b/wolfcrypt/src/rng_bank.c index 5bb5d9d35af..62fa408d16e 100644 --- a/wolfcrypt/src/rng_bank.c +++ b/wolfcrypt/src/rng_bank.c @@ -26,6 +26,33 @@ #include #include +/* Helper to get reseedCtr from the active DRBG, regardless of SHA-256/SHA-512 */ +#ifdef WOLFSSL_DRBG_SHA512 + #define WC_RNG_BANK_RESEED_CTR(rng_ptr) \ + (((rng_ptr)->drbgType == WC_DRBG_SHA512) \ + ? ((struct DRBG_SHA512_internal *)(rng_ptr)->drbg512)->reseedCtr \ + : ((struct DRBG_internal *)(rng_ptr)->drbg)->reseedCtr) + #define WC_RNG_BANK_SET_RESEED_CTR(rng_ptr, val) \ + do { \ + if ((rng_ptr)->drbgType == WC_DRBG_SHA512) \ + ((struct DRBG_SHA512_internal *)(rng_ptr)->drbg512)->reseedCtr \ + = (val); \ + else \ + ((struct DRBG_internal *)(rng_ptr)->drbg)->reseedCtr = (val); \ + } while (0) + #define WC_RNG_BANK_DRBG_NULL(rng_ptr) \ + ((rng_ptr)->drbg == NULL && (rng_ptr)->drbg512 == NULL) +#else + #define WC_RNG_BANK_RESEED_CTR(rng_ptr) \ + (((struct DRBG_internal *)(rng_ptr)->drbg)->reseedCtr) + #define WC_RNG_BANK_SET_RESEED_CTR(rng_ptr, val) \ + do { \ + ((struct DRBG_internal *)(rng_ptr)->drbg)->reseedCtr = (val); \ + } while (0) + #define WC_RNG_BANK_DRBG_NULL(rng_ptr) \ + ((rng_ptr)->drbg == NULL) +#endif + WOLFSSL_API int wc_rng_bank_init( struct wc_rng_bank *ctx, int n_rngs, @@ -343,7 +370,7 @@ WOLFSSL_API int wc_rng_bank_checkout( *rng_inst = &bank->rngs[preferred_inst_offset]; if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) && - (((struct DRBG_internal *)(*rng_inst)->rng.drbg)->reseedCtr >= + (WC_RNG_BANK_RESEED_CTR(&(*rng_inst)->rng) >= WC_RESEED_INTERVAL) && (flags & WC_RNG_BANK_FLAG_CAN_FAIL_OVER_INST) && (n_rngs_tried < bank->n_rngs)) @@ -353,7 +380,7 @@ WOLFSSL_API int wc_rng_bank_checkout( else { #ifdef WC_VERBOSE_RNG if ((! (flags & WC_RNG_BANK_FLAG_CAN_WAIT)) && - (((struct DRBG_internal *)(*rng_inst)->rng.drbg)->reseedCtr >= + (WC_RNG_BANK_RESEED_CTR(&(*rng_inst)->rng) >= WC_RESEED_INTERVAL)) { WOLFSSL_DEBUG_PRINTF( @@ -484,7 +511,7 @@ WOLFSSL_API int wc_rng_bank_inst_reinit( int devId; if ((rng_inst == NULL) || - (rng_inst->rng.drbg == NULL)) + WC_RNG_BANK_DRBG_NULL(&rng_inst->rng)) { return BAD_FUNC_ARG; } @@ -561,7 +588,7 @@ WOLFSSL_API int wc_rng_bank_seed(struct wc_rng_bank *bank, #endif break; } - else if (drbg->rng.drbg == NULL) { + else if (WC_RNG_BANK_DRBG_NULL(&drbg->rng)) { #ifdef WC_VERBOSE_RNG WOLFSSL_DEBUG_PRINTF( "WARNING: wc_rng_bank_seed(): inst#%d has null .drbg.\n", n); @@ -612,8 +639,7 @@ WOLFSSL_API int wc_rng_bank_reseed(struct wc_rng_bank *bank, if (ret != 0) return ret; - ((struct DRBG_internal *)drbg->rng.drbg)->reseedCtr = - WC_RESEED_INTERVAL; + WC_RNG_BANK_SET_RESEED_CTR(&drbg->rng, WC_RESEED_INTERVAL); if (flags & WC_RNG_BANK_FLAG_CAN_WAIT) { byte scratch[4]; diff --git a/wolfcrypt/src/wc_lms.c b/wolfcrypt/src/wc_lms.c index 7035060621c..1250cea5aed 100644 --- a/wolfcrypt/src/wc_lms.c +++ b/wolfcrypt/src/wc_lms.c @@ -22,6 +22,11 @@ #include #if defined(WOLFSSL_HAVE_LMS) && defined(WOLFSSL_WC_LMS) + +#if FIPS_VERSION3_GE(2,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif #include #ifdef NO_INLINE diff --git a/wolfcrypt/src/wc_mlkem.c b/wolfcrypt/src/wc_mlkem.c index 2c43bbabecb..8010571cd60 100644 --- a/wolfcrypt/src/wc_mlkem.c +++ b/wolfcrypt/src/wc_mlkem.c @@ -71,6 +71,11 @@ #undef WOLFSSL_RISCV_ASM #endif +#if FIPS_VERSION3_GE(2,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif + #include #include #include @@ -392,6 +397,35 @@ int wc_MlKemKey_MakeKey(MlKemKey* key, WC_RNG* rng) ret = wc_KyberKey_MakeKeyWithRandom(key, rand, sizeof(rand)); } +#ifdef HAVE_FIPS + /* Pairwise Consistency Test (PCT) per FIPS 140-3 / ISO 19790:2012 + * Section 7.10.3.3: encapsulate with ek, decapsulate with dk, + * verify shared secrets match. */ + if (ret == 0) { + byte pct_ct[WC_ML_KEM_MAX_CIPHER_TEXT_SIZE]; + byte pct_ss1[WC_ML_KEM_SS_SZ]; + byte pct_ss2[WC_ML_KEM_SS_SZ]; + word32 ctSz = 0; + + ret = wc_MlKemKey_CipherTextSize(key, &ctSz); + + if (ret == 0) + ret = wc_MlKemKey_Encapsulate(key, pct_ct, pct_ss1, rng); + + if (ret == 0) + ret = wc_MlKemKey_Decapsulate(key, pct_ss2, pct_ct, ctSz); + + if (ret == 0) { + if (XMEMCMP(pct_ss1, pct_ss2, WC_ML_KEM_SS_SZ) != 0) + ret = ML_KEM_PCT_E; + } + + ForceZero(pct_ss1, sizeof(pct_ss1)); + ForceZero(pct_ss2, sizeof(pct_ss2)); + ForceZero(pct_ct, sizeof(pct_ct)); + } +#endif /* HAVE_FIPS */ + /* Ensure seeds are zeroized. */ ForceZero((void*)rand, (word32)sizeof(rand)); @@ -625,6 +659,9 @@ int wc_MlKemKey_MakeKeyWithRandom(MlKemKey* key, const unsigned char* rand, } #endif + /* Note: PCT is performed in wc_MlKemKey_MakeKey() which calls this + * function and has the RNG parameter needed for encapsulation. */ + return ret; } #endif /* !WOLFSSL_MLKEM_NO_MAKE_KEY */ diff --git a/wolfcrypt/src/wc_xmss.c b/wolfcrypt/src/wc_xmss.c index ef7248d209e..dfc6375e4e3 100644 --- a/wolfcrypt/src/wc_xmss.c +++ b/wolfcrypt/src/wc_xmss.c @@ -22,6 +22,11 @@ #include #ifdef WOLFSSL_HAVE_XMSS + +#if FIPS_VERSION3_GE(2,0,0) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS +#endif #include #ifdef NO_INLINE diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 6a8ca6798f8..4f195c79be7 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -2767,17 +2767,21 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\ #endif #ifdef WOLFSSL_HAVE_MLKEM + PRIVATE_KEY_UNLOCK(); if ( (ret = mlkem_test()) != 0) TEST_FAIL("MLKEM test failed!\n", ret); else TEST_PASS("MLKEM test passed!\n"); + PRIVATE_KEY_LOCK(); #endif #ifdef HAVE_DILITHIUM + PRIVATE_KEY_UNLOCK(); if ( (ret = dilithium_test()) != 0) TEST_FAIL("DILITHIUM test failed!\n", ret); else TEST_PASS("DILITHIUM test passed!\n"); + PRIVATE_KEY_LOCK(); #endif #if defined(WOLFSSL_HAVE_XMSS) @@ -3665,8 +3669,6 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void) int first; int last; } missing[] = { - { -124, -124 }, - { -167, -169 }, { WC_SPAN1_LAST_E - 1, WC_SPAN2_FIRST_E + 1 }, { WC_SPAN2_LAST_E - 1, WC_SPAN2_MIN_CODE_E } }; @@ -20141,14 +20143,37 @@ static wc_test_ret_t _rng_test(WC_RNG* rng) WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { #endif - ((struct DRBG_internal *)rng->drbg)->reseedCtr = WC_RESEED_INTERVAL; + #if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + if (rng->drbgType == WC_DRBG_SHA512) { + ((struct DRBG_SHA512_internal *)rng->drbg512)->reseedCtr = + WC_RESEED_INTERVAL; + } + else + #endif + { + ((struct DRBG_internal *)rng->drbg)->reseedCtr = + WC_RESEED_INTERVAL; + } ret = wc_RNG_GenerateBlock(rng, block, sizeof(block)); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); - if (((struct DRBG_internal *)rng->drbg)->reseedCtr == WC_RESEED_INTERVAL) - return WC_TEST_RET_ENC_NC; + #if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + if (rng->drbgType == WC_DRBG_SHA512) { + if (((struct DRBG_SHA512_internal *)rng->drbg512)->reseedCtr == + WC_RESEED_INTERVAL) + return WC_TEST_RET_ENC_NC; + } + else + #endif + { + if (((struct DRBG_internal *)rng->drbg)->reseedCtr == + WC_RESEED_INTERVAL) + return WC_TEST_RET_ENC_NC; + } #ifdef WOLF_CRYPTO_CB } #endif @@ -20469,6 +20494,150 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_test(void) if (XMEMCMP(test2Output, output, sizeof(output)) != 0) return WC_TEST_RET_ENC_NC; +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + /* SHA-512 DRBG Health Tests using NIST CAVP test vectors. + * Source: NIST CAVP drbgtestvectors.zip, Hash_DRBG.rsp, [SHA-512], + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm- + * Validation-Program/documents/drbg/drbgtestvectors.zip */ + { + /* No-reseed test: drbgvectors_no_reseed/Hash_DRBG.rsp, [SHA-512], + * PredictionResistance=False, EntropyInputLen=256, NonceLen=128, + * PersonalizationStringLen=0, AdditionalInputLen=0, + * ReturnedBitsLen=2048, COUNT=0. + * EntropyInput || Nonce concatenated as seedA. */ + WOLFSSL_SMALL_STACK_STATIC const byte sha512test1Entropy[] = + { + /* EntropyInput (32 bytes) */ + 0x6b, 0x50, 0xa7, 0xd8, 0xf8, 0xa5, 0x5d, 0x7a, + 0x3d, 0xf8, 0xbb, 0x40, 0xbc, 0xc3, 0xb7, 0x22, + 0xd8, 0x70, 0x8d, 0xe6, 0x7f, 0xda, 0x01, 0x0b, + 0x03, 0xc4, 0xc8, 0x4d, 0x72, 0x09, 0x6f, 0x8c, + /* Nonce (16 bytes) */ + 0x3e, 0xc6, 0x49, 0xcc, 0x62, 0x56, 0xd9, 0xfa, + 0x31, 0xdb, 0x7a, 0x29, 0x04, 0xaa, 0xf0, 0x25 + }; + WOLFSSL_SMALL_STACK_STATIC const byte sha512test1Output[] = + { + 0x95, 0xb7, 0xf1, 0x7e, 0x98, 0x02, 0xd3, 0x57, + 0x73, 0x92, 0xc6, 0xa9, 0xc0, 0x80, 0x83, 0xb6, + 0x7d, 0xd1, 0x29, 0x22, 0x65, 0xb5, 0xf4, 0x2d, + 0x23, 0x7f, 0x1c, 0x55, 0xbb, 0x9b, 0x10, 0xbf, + 0xcf, 0xd8, 0x2c, 0x77, 0xa3, 0x78, 0xb8, 0x26, + 0x6a, 0x00, 0x99, 0x14, 0x3b, 0x3c, 0x2d, 0x64, + 0x61, 0x1e, 0xee, 0xb6, 0x9a, 0xcd, 0xc0, 0x55, + 0x95, 0x7c, 0x13, 0x9e, 0x8b, 0x19, 0x0c, 0x7a, + 0x06, 0x95, 0x5f, 0x2c, 0x79, 0x7c, 0x27, 0x78, + 0xde, 0x94, 0x03, 0x96, 0xa5, 0x01, 0xf4, 0x0e, + 0x91, 0x39, 0x6a, 0xcf, 0x8d, 0x7e, 0x45, 0xeb, + 0xdb, 0xb5, 0x3b, 0xbf, 0x8c, 0x97, 0x52, 0x30, + 0xd2, 0xf0, 0xff, 0x91, 0x06, 0xc7, 0x61, 0x19, + 0xae, 0x49, 0x8e, 0x7f, 0xbc, 0x03, 0xd9, 0x0f, + 0x8e, 0x4c, 0x51, 0x62, 0x7a, 0xed, 0x5c, 0x8d, + 0x42, 0x63, 0xd5, 0xd2, 0xb9, 0x78, 0x87, 0x3a, + 0x0d, 0xe5, 0x96, 0xee, 0x6d, 0xc7, 0xf7, 0xc2, + 0x9e, 0x37, 0xee, 0xe8, 0xb3, 0x4c, 0x90, 0xdd, + 0x1c, 0xf6, 0xa9, 0xdd, 0xb2, 0x2b, 0x4c, 0xbd, + 0x08, 0x6b, 0x14, 0xb3, 0x5d, 0xe9, 0x3d, 0xa2, + 0xd5, 0xcb, 0x18, 0x06, 0x69, 0x8c, 0xbd, 0x7b, + 0xbb, 0x67, 0xbf, 0xe3, 0xd3, 0x1f, 0xd2, 0xd1, + 0xdb, 0xd2, 0xa1, 0xe0, 0x58, 0xa3, 0xeb, 0x99, + 0xd7, 0xe5, 0x1f, 0x1a, 0x93, 0x8e, 0xed, 0x5e, + 0x1c, 0x1d, 0xe2, 0x3a, 0x6b, 0x43, 0x45, 0xd3, + 0x19, 0x14, 0x09, 0xf9, 0x2f, 0x39, 0xb3, 0x67, + 0x0d, 0x8d, 0xbf, 0xb6, 0x35, 0xd8, 0xe6, 0xa3, + 0x69, 0x32, 0xd8, 0x10, 0x33, 0xd1, 0x44, 0x8d, + 0x63, 0xb4, 0x03, 0xdd, 0xf8, 0x8e, 0x12, 0x1b, + 0x6e, 0x81, 0x9a, 0xc3, 0x81, 0x22, 0x6c, 0x13, + 0x21, 0xe4, 0xb0, 0x86, 0x44, 0xf6, 0x72, 0x7c, + 0x36, 0x8c, 0x5a, 0x9f, 0x7a, 0x4b, 0x3e, 0xe2 + }; + + /* Reseed test: drbgvectors_pr_false/Hash_DRBG.rsp, [SHA-512], + * PredictionResistance=False, EntropyInputLen=256, NonceLen=128, + * PersonalizationStringLen=0, AdditionalInputLen=0, + * ReturnedBitsLen=2048, COUNT=0. */ + WOLFSSL_SMALL_STACK_STATIC const byte sha512test2EntropyA[] = + { + /* EntropyInput (32 bytes) */ + 0x31, 0x44, 0xe1, 0x7a, 0x10, 0xc8, 0x56, 0x12, + 0x97, 0x64, 0xf5, 0x8f, 0xd8, 0xe4, 0x23, 0x10, + 0x20, 0x54, 0x69, 0x96, 0xc0, 0xbf, 0x6c, 0xff, + 0x8e, 0x91, 0xc2, 0x4e, 0xe0, 0x9b, 0xe3, 0x33, + /* Nonce (16 bytes) */ + 0xb1, 0x6f, 0xcb, 0x1c, 0xf0, 0xc0, 0x10, 0xf3, + 0x1f, 0xea, 0xb7, 0x33, 0x58, 0x8b, 0x8e, 0x04 + }; + WOLFSSL_SMALL_STACK_STATIC const byte sha512test2EntropyB[] = + { + /* EntropyInputReseed (32 bytes) */ + 0xa0, 0xb3, 0x58, 0x4c, 0x2c, 0x84, 0x12, 0xf6, + 0x18, 0x40, 0x68, 0x34, 0x40, 0x4d, 0x1e, 0xb0, + 0xce, 0x99, 0x9b, 0xa2, 0x89, 0x66, 0x05, 0x4d, + 0x7e, 0x49, 0x7e, 0x0d, 0xb6, 0x08, 0xb9, 0x67 + }; + WOLFSSL_SMALL_STACK_STATIC const byte sha512test2Output[] = + { + 0xef, 0xa3, 0x5d, 0xd0, 0x36, 0x2a, 0xdb, 0x76, + 0x26, 0x45, 0x6b, 0x36, 0xfa, 0xc7, 0x4d, 0x3c, + 0x28, 0xd0, 0x1d, 0x92, 0x64, 0x20, 0x27, 0x5a, + 0x28, 0xbe, 0xa9, 0xc9, 0xdd, 0x75, 0x47, 0xc1, + 0x5e, 0x79, 0x31, 0x85, 0x2a, 0xc1, 0x27, 0x70, + 0x76, 0x56, 0x75, 0x35, 0x23, 0x9c, 0x1f, 0x42, + 0x9c, 0x7f, 0x75, 0xcf, 0x74, 0xc2, 0x26, 0x7d, + 0xeb, 0x6a, 0x3e, 0x59, 0x6c, 0xf3, 0x26, 0x15, + 0x6c, 0x79, 0x69, 0x41, 0x28, 0x3b, 0x8d, 0x58, + 0x3f, 0x17, 0x1c, 0x2f, 0x6e, 0x33, 0x23, 0xf7, + 0x55, 0x5e, 0x1b, 0x18, 0x1f, 0xfd, 0xa3, 0x05, + 0x07, 0x21, 0x0c, 0xb1, 0xf5, 0x89, 0xb2, 0x3c, + 0xd7, 0x18, 0x80, 0xfd, 0x44, 0x37, 0x0c, 0xac, + 0xf4, 0x33, 0x75, 0xb0, 0xdb, 0x7e, 0x33, 0x6f, + 0x12, 0xb3, 0x09, 0xbf, 0xd4, 0xf6, 0x10, 0xbb, + 0x8f, 0x20, 0xe1, 0xa1, 0x5e, 0x25, 0x3a, 0x4f, + 0xe5, 0x11, 0xa0, 0x27, 0x96, 0x8d, 0xf0, 0xb1, + 0x05, 0xa1, 0xd7, 0x3a, 0xff, 0x7c, 0x7a, 0x82, + 0x6d, 0x39, 0xf6, 0x40, 0xdf, 0xb8, 0xf5, 0x22, + 0x25, 0x9e, 0xd4, 0x02, 0x28, 0x2e, 0x2c, 0x2e, + 0x9d, 0x3a, 0x49, 0x8f, 0x51, 0x72, 0x5f, 0xe4, + 0x14, 0x1b, 0x06, 0xda, 0x55, 0x98, 0xa4, 0x2a, + 0xc1, 0xe0, 0x49, 0x4e, 0x99, 0x7d, 0x56, 0x6a, + 0x1a, 0x39, 0xb6, 0x76, 0xb9, 0x6a, 0x60, 0x03, + 0xa4, 0xc5, 0xdb, 0x84, 0xf2, 0x46, 0x58, 0x4e, + 0xe6, 0x5a, 0xf7, 0x0f, 0xf2, 0x16, 0x02, 0x78, + 0x16, 0x6d, 0xa1, 0x6d, 0x91, 0xc9, 0xb8, 0xf2, + 0xde, 0xb0, 0x27, 0x51, 0xa1, 0x08, 0x8a, 0xd6, + 0xbe, 0x4e, 0x80, 0xef, 0x96, 0x6e, 0xb7, 0x3e, + 0x66, 0xbc, 0x87, 0xca, 0xd8, 0x7c, 0x77, 0xc0, + 0xb3, 0x4a, 0x21, 0xba, 0x1d, 0xa0, 0xba, 0x6d, + 0x16, 0xca, 0x50, 0x46, 0xdc, 0x4a, 0xbd, 0xa0 + }; + + byte output512[WC_SHA512_DIGEST_SIZE * 4]; /* 256 bytes */ + + /* Test 1: SHA-512 DRBG no-reseed */ + ret = wc_RNG_HealthTest_SHA512(0, + sha512test1Entropy, sizeof(sha512test1Entropy), + NULL, 0, + output512, sizeof(output512)); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + + if (XMEMCMP(sha512test1Output, output512, sizeof(output512)) != 0) + return WC_TEST_RET_ENC_NC; + + /* Test 2: SHA-512 DRBG with reseed */ + ret = wc_RNG_HealthTest_SHA512(1, + sha512test2EntropyA, sizeof(sha512test2EntropyA), + sha512test2EntropyB, sizeof(sha512test2EntropyB), + output512, sizeof(output512)); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + + if (XMEMCMP(sha512test2Output, output512, sizeof(output512)) != 0) + return WC_TEST_RET_ENC_NC; + } +#endif /* WOLFSSL_DRBG_SHA512 && !HAVE_SELFTEST && FIPS v7+ */ + /* Basic RNG generate block test */ if ((ret = random_rng_test()) != 0) return ret; @@ -20689,8 +20858,20 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t random_bank_test(void) ERROR_OUT(WC_TEST_RET_ENC_EC(ret), out); for (i = 0; i < bank->n_rngs; ++i) { + #if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + word64 bankReseedCtr; + if (bank->rngs[i].rng.drbgType == WC_DRBG_SHA512) + bankReseedCtr = ((struct DRBG_SHA512_internal *) + bank->rngs[i].rng.drbg512)->reseedCtr; + else + bankReseedCtr = ((struct DRBG_internal *) + bank->rngs[i].rng.drbg)->reseedCtr; + if (bankReseedCtr != WC_RESEED_INTERVAL) + #else if (((struct DRBG_internal *)bank->rngs[i].rng.drbg) ->reseedCtr != WC_RESEED_INTERVAL) + #endif { ERROR_OUT(WC_TEST_RET_ENC_I(i), out); } @@ -62789,7 +62970,7 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx) len = (word32)sizeof(seed); if (info->seed.sz < len) len = info->seed.sz; - XMEMCPY(info->seed.seed, seed, sizeof(seed)); + XMEMCPY(info->seed.seed, seed, len); info->seed.seed += len; info->seed.sz -= len; (*seedWord32)++; @@ -64694,7 +64875,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t aes_siv_test(void) #else printf("Test Profile: Default (Aggressive multi-threaded)\n"); #endif - printf("Expected statistical false positive rate: ~%.2f failures\n", + printf("Current expected statistical false positive rate with ADP/RCT" + ": NONE\n"); + printf("Historical expected statistical false positive rate with " + "continuous test: ~%.2f failures\n", (double)total_iterations * 32.0 / 4294967296.0); for (i = 0; i < NUM_THREADS; i++) { diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index f879aabc3bb..9e0f09f5a3e 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -88,7 +88,7 @@ enum wolfCrypt_ErrorCodes { AES_EAX_AUTH_E = -122, /* AES-EAX Authentication check failure */ KEY_EXHAUSTED_E = -123, /* No longer usable for operation. */ - /* -124 unused. */ + ML_KEM_KAT_FIPS_E = -124, /* ML-KEM KAT failure */ MEMORY_E = -125, /* out of memory error */ VAR_STATE_CHANGE_E = -126, /* var state modified by different thread */ @@ -136,7 +136,9 @@ enum wolfCrypt_ErrorCodes { ED448_KAT_FIPS_E = -164, /* Ed448 Known answer test failure */ PBKDF2_KAT_FIPS_E = -165, /* PBKDF2 Known answer test failure */ WC_KEY_MISMATCH_E = -166, /* Error for private/public key mismatch */ - /* -167..-169 unused. */ + ML_DSA_KAT_FIPS_E = -167, /* ML-DSA KAT failure */ + LMS_KAT_FIPS_E = -168, /* LMS KAT failure */ + XMSS_KAT_FIPS_E = -169, /* XMSS KAT failure */ ECC_BAD_ARG_E = -170, /* ECC input argument of wrong type */ ASN_ECC_KEY_E = -171, /* ASN ECC bad input */ @@ -311,10 +313,13 @@ enum wolfCrypt_ErrorCodes { * not match stored hash*/ BUSY_E = -1006, /* Object is busy */ ALREADY_E = -1007, /* Operation was redundant or preempted */ + ML_KEM_PCT_E = -1008, /* ML-KEM Pairwise Consistency Test failure */ + ML_DSA_PCT_E = -1009, /* ML-DSA Pairwise Consistency Test failure */ + DRBG_SHA512_KAT_FIPS_E = -1010, /* SHA-512 DRBG KAT failure */ - SEQ_OVERFLOW_E = -1008, /* Sequence counter would overflow */ - WC_SPAN2_LAST_E = -1008, /* Update to indicate last used error code */ - WC_LAST_E = -1008, /* the last code used either here or in + SEQ_OVERFLOW_E = -1011, /* Sequence counter would overflow */ + WC_SPAN2_LAST_E = -1011, /* Update to indicate last used error code */ + WC_LAST_E = -1011, /* the last code used either here or in * error-ssl.h */ WC_SPAN2_MIN_CODE_E = -1999, /* Last usable code in span 2 */ diff --git a/wolfssl/wolfcrypt/fips_test.h b/wolfssl/wolfcrypt/fips_test.h index e4e8bf84d23..b75803f6133 100644 --- a/wolfssl/wolfcrypt/fips_test.h +++ b/wolfssl/wolfcrypt/fips_test.h @@ -74,7 +74,12 @@ enum FipsCastId { FIPS_CAST_PBKDF2 = 18, /* v7.0.0 + */ FIPS_CAST_AES_ECB = 19, - FIPS_CAST_COUNT = 20 + FIPS_CAST_ML_KEM = 20, + FIPS_CAST_ML_DSA = 21, + FIPS_CAST_LMS = 22, + FIPS_CAST_XMSS = 23, + FIPS_CAST_DRBG_SHA512 = 24, + FIPS_CAST_COUNT = 25 }; enum FipsCastStateId { diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index db7d58a97ef..f6177d745de 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -52,11 +52,15 @@ #endif #endif -/* Size of the BRBG seed */ +/* Size of the DRBG seed (SHA-256) */ #ifndef DRBG_SEED_LEN #define DRBG_SEED_LEN (440/8) #endif +#ifdef WOLFSSL_DRBG_SHA512 + #define DRBG_SHA512_SEED_LEN (888/8) /* 111 bytes per SP 800-90A Table 2 */ +#endif + #if !defined(CUSTOM_RAND_TYPE) /* To maintain compatibility the default is byte */ @@ -104,9 +108,16 @@ #endif #elif defined(HAVE_HASHDRBG) #ifdef NO_SHA256 - #error "Hash DRBG requires SHA-256." + #ifndef WOLFSSL_DRBG_SHA512 + #error "Hash DRBG requires SHA-256 or SHA-512." + #endif #endif /* NO_SHA256 */ - #include + #ifndef NO_SHA256 + #include + #endif + #ifdef WOLFSSL_DRBG_SHA512 + #include + #endif #elif defined(HAVE_WNR) /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ #elif defined(HAVE_INTEL_RDRAND) @@ -239,7 +250,33 @@ struct OS_Seed { #define WC_DRBG_SEED_BLOCK_SZ SEED_BLOCK_SZ -#define WC_DRBG_SEED_SZ (RNG_SECURITY_STRENGTH*ENTROPY_SCALE_FACTOR/8) +/* WC_DRBG_SEED_SZ is the number of bytes of raw entropy gathered from the + * NDRNG at instantiation and reseed. We deliberately "overseed" beyond the + * NIST minimum (security_strength bits) to account for entropy sources that + * may deliver fewer than 1 bit of real entropy per bit of output. With the + * default FIPS ENTROPY_SCALE_FACTOR of 4 this yields 256*4/8 = 128 bytes = + * 1024 bits of raw seed material, guaranteeing at least 256 bits of real + * entropy even if the source provides only 1 good bit per 4. + * + * Hash_df then compresses this seed material into the internal V and C state + * vectors (seedlen = 440 bits for SHA-256, 888 bits for SHA-512 per + * SP 800-90A Table 2). + * + * In FIPS mode (ENTROPY_SCALE_FACTOR >= 4) the base is already >= 128 bytes + * which exceeds DRBG_SHA512_SEED_LEN (111), so both DRBGs use the same + * seed size. In non-FIPS mode we use the base for both DRBGs so that + * enabling SHA-512 DRBG does not inflate the per-init entropy cost. + * SP 800-90A requires only security_strength bits (256 = 32 bytes) of + * entropy regardless of hash size; hash_df compresses the seed material + * into the internal V/C state vectors. */ +#define WC_DRBG_SEED_SZ_BASE (RNG_SECURITY_STRENGTH*ENTROPY_SCALE_FACTOR/8) + +#if defined(HAVE_FIPS) && defined(WOLFSSL_DRBG_SHA512) && \ + (WC_DRBG_SEED_SZ_BASE < DRBG_SHA512_SEED_LEN) + #define WC_DRBG_SEED_SZ DRBG_SHA512_SEED_LEN +#else + #define WC_DRBG_SEED_SZ WC_DRBG_SEED_SZ_BASE +#endif /* The maximum seed size will be the seed size plus a seed block for the * test, and an additional half of the seed size. This additional half @@ -248,8 +285,14 @@ struct OS_Seed { #define WC_DRBG_MAX_SEED_SZ (WC_DRBG_SEED_SZ + WC_DRBG_SEED_SZ/2 + \ SEED_BLOCK_SZ) -#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4) +#ifndef NO_SHA256 + #define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4) +#endif +#ifdef WOLFSSL_DRBG_SHA512 + #define RNG_HEALTH_TEST_CHECK_SIZE_SHA512 (WC_SHA512_DIGEST_SIZE * 4) +#endif +#ifndef NO_SHA256 struct DRBG_internal { #ifdef WORD64_AVAILABLE word64 reseedCtr; @@ -268,8 +311,34 @@ struct DRBG_internal { byte digest_scratch[WC_SHA256_DIGEST_SIZE]; #endif }; +#endif /* !NO_SHA256 */ + +#ifdef WOLFSSL_DRBG_SHA512 +struct DRBG_SHA512_internal { + word64 reseedCtr; + byte V[DRBG_SHA512_SEED_LEN]; + byte C[DRBG_SHA512_SEED_LEN]; + void* heap; +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + int devId; +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha512 sha512; + byte seed_scratch[DRBG_SHA512_SEED_LEN]; + byte digest_scratch[WC_SHA512_DIGEST_SIZE]; +#endif +}; +#endif /* WOLFSSL_DRBG_SHA512 */ #endif /* HAVE_HASHDRBG */ +/* DRBG type enum */ +#ifdef HAVE_HASHDRBG +enum wc_DrbgType { + WC_DRBG_SHA256 = 0, + WC_DRBG_SHA512 = 1, +}; +#endif + /* RNG health states */ #define WC_DRBG_NOT_INIT 0 #define WC_DRBG_OK 1 @@ -301,17 +370,35 @@ struct WC_RNG { #ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES struct { #endif - /* Hash-based Deterministic Random Bit Generator */ + #ifndef NO_SHA256 + /* SHA-256 Hash-based Deterministic Random Bit Generator */ struct DRBG* drbg; #if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) struct DRBG_internal drbg_data; #endif #ifdef WOLFSSL_SMALL_STACK_CACHE - /* Scratch buffers -- all preallocated by _InitRng(). */ + /* SHA-256 scratch buffers -- preallocated by _InitRng(). */ struct DRBG_internal *drbg_scratch; byte *health_check_scratch; + #endif + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SMALL_STACK_CACHE + /* Seed buffer for PollAndReSeed -- shared by both DRBG types */ byte *newSeed_buf; #endif + #ifdef WOLFSSL_DRBG_SHA512 + /* SHA-512 Hash-based Deterministic Random Bit Generator */ + struct DRBG_SHA512* drbg512; + #if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) + struct DRBG_SHA512_internal drbg512_data; + #endif + #ifdef WOLFSSL_SMALL_STACK_CACHE + /* SHA-512 scratch buffers -- preallocated by _InitRng(). */ + struct DRBG_SHA512_internal *drbg512_scratch; + byte *health_check_scratch_512; + #endif + #endif /* WOLFSSL_DRBG_SHA512 */ + byte drbgType; /* WC_DRBG_SHA256 or WC_DRBG_SHA512 */ #ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES }; #endif @@ -407,6 +494,39 @@ WOLFSSL_API int wc_FreeRng(WC_RNG* rng); const byte* seedB, word32 seedBSz, byte* output, word32 outputSz, void* heap, int devId); +#if defined(WOLFSSL_DRBG_SHA512) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + WOLFSSL_API int wc_RNG_HealthTest_SHA512(int reseed, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz); + WOLFSSL_API int wc_RNG_HealthTest_SHA512_ex(int reseed, + const byte* nonce, word32 nonceSz, + const byte* persoString, + word32 persoStringSz, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + const byte* additionalA, + word32 additionalASz, + const byte* additionalB, + word32 additionalBSz, + byte* output, word32 outputSz, + void* heap, int devId); +#endif /* WOLFSSL_DRBG_SHA512 && !HAVE_SELFTEST && FIPS v7+ */ + + /* Runtime DRBG disable/enable API */ +#if !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0)) + WOLFSSL_API int wc_Sha256Drbg_Disable(void); + WOLFSSL_API int wc_Sha256Drbg_Enable(void); + WOLFSSL_API int wc_Sha256Drbg_GetStatus(void); +#ifdef WOLFSSL_DRBG_SHA512 + WOLFSSL_API int wc_Sha512Drbg_Disable(void); + WOLFSSL_API int wc_Sha512Drbg_Enable(void); + WOLFSSL_API int wc_Sha512Drbg_GetStatus(void); +#endif +#endif /* !HAVE_SELFTEST && (!HAVE_FIPS || FIPS v7+) */ + #endif /* HAVE_HASHDRBG */ #ifdef __cplusplus