diff --git a/.github/workflows/async.yml b/.github/workflows/async.yml index 8a572c328f5..74c073fe1c3 100644 --- a/.github/workflows/async.yml +++ b/.github/workflows/async.yml @@ -18,6 +18,10 @@ jobs: matrix: config: [ # Add new configs here + '--enable-asynccrypt --enable-all --enable-dtls13 --disable-mlkem CFLAGS="-pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFCRYPT_TEST_LINT"', + '--enable-asynccrypt-sw --enable-ocspstapling --enable-ocspstapling2 --disable-mlkem CFLAGS="-pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', + '--enable-asynccrypt --enable-all --enable-dtls13 --disable-pqc-hybrids --enable-tls-mlkem-standalone CFLAGS="-pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFCRYPT_TEST_LINT"', + '--enable-asynccrypt-sw --enable-ocspstapling --enable-ocspstapling2 --disable-pqc-hybrids --enable-tls-mlkem-standalone CFLAGS="-pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', '--enable-asynccrypt --enable-all --enable-dtls13 CFLAGS="-pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFCRYPT_TEST_LINT"', '--enable-asynccrypt-sw --enable-ocspstapling --enable-ocspstapling2 CFLAGS="-pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', '--enable-ocsp CFLAGS="-DTEST_NONBLOCK_CERTS -pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 092c8f7d651..8570fb5cac6 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -73,6 +73,7 @@ jobs: -DWOLFSSL_X963KDF:BOOL=yes -DWOLFSSL_DILITHIUM:BOOL=yes -DWOLFSSL_PKCS11:BOOL=yes \ -DWOLFSSL_ECCSI:BOOL=yes -DWOLFSSL_SAKKE:BOOL=yes -DWOLFSSL_SIPHASH:BOOL=yes \ -DWOLFSSL_WC_RSA_DIRECT:BOOL=yes -DWOLFSSL_PUBLIC_MP:BOOL=yes \ + -DWOLFSSL_EXTRA_PQC_HYBRIDS:BOOL=yes -DWOLFSSL_TLS_NO_MLKEM_STANDALONE:BOOL=no \ .. cmake --build . ctest -j $(nproc) diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 461c0b0df9c..a91657a9c62 100644 --- a/.github/workflows/os-check.yml +++ b/.github/workflows/os-check.yml @@ -38,6 +38,12 @@ jobs: '--enable-experimental --enable-kyber --enable-dtls --enable-dtls13 --enable-dtls-frag-ch', '--enable-all --enable-dtls13 --enable-dtls-frag-ch', + '--enable-all --enable-dtls13 --enable-dtls-frag-ch --disable-mlkem', + '--enable-all --enable-dtls13 --enable-dtls-frag-ch + --enable-tls-mlkem-standalone', + '--enable-all --enable-dtls13 --enable-dtls-frag-ch + --enable-tls-mlkem-standalone --enable-experimental + --enable-extra-pqc-hybrids', '--enable-dtls --enable-dtls13 --enable-dtls-frag-ch --enable-dtls-mtu', '--enable-dtls --enable-dtlscid --enable-dtls13 --enable-secure-renegotiation diff --git a/.github/workflows/pq-all.yml b/.github/workflows/pq-all.yml index cabd5f367c4..b4ba3a22ec7 100644 --- a/.github/workflows/pq-all.yml +++ b/.github/workflows/pq-all.yml @@ -27,9 +27,13 @@ jobs: '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-acert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-quic --with-sys-crypto-policy --enable-experimental --enable-mlkem=yes,kyber,ml-kem --enable-lms --enable-xmss --enable-slhdsa --enable-dilithium --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ"', '--disable-intelasm --enable-all --enable-testcert --enable-acert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-quic --with-sys-crypto-policy --enable-experimental --enable-mlkem=yes,kyber,ml-kem,small --enable-lms=yes,small --enable-xmss=yes,small --enable-slhdsa=yes,small --enable-dilithium=yes,small --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFSSL_MLKEM_MAKEKEY_SMALL_MEM -DWOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM -DWOLFSSL_MLKEM_NO_LARGE_CODE -DWOLFSSL_DILITHIUM_SIGN_SMALL_MEM -DWOLFSSL_DILITHIUM_VERIFY_SMALL_MEM -DWOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM -DWOLFSSL_DILITHIUM_NO_LARGE_CODE"', '--disable-intelasm --enable-smallstack --enable-smallstackcache --enable-all --enable-testcert --enable-acert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-quic --with-sys-crypto-policy --enable-experimental --enable-mlkem=yes,kyber,ml-kem,small --enable-lms=yes,small --enable-xmss=yes,small --enable-slhdsa=yes,small --enable-dilithium=yes,small --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFSSL_MLKEM_MAKEKEY_SMALL_MEM -DWOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM -DWOLFSSL_MLKEM_NO_LARGE_CODE -DWOLFSSL_DILITHIUM_SIGN_SMALL_MEM -DWOLFSSL_DILITHIUM_VERIFY_SMALL_MEM -DWOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM -DWOLFSSL_DILITHIUM_NO_LARGE_CODE"', - '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,512 --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', + '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,512 --enable-tls-mlkem-standalone --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,768 --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', + '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,768 --enable-tls-mlkem-standalone --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', + '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,768 --enable-tls-mlkem-standalone --disable-pqc-hybrids --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,1024 --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', + '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,1024 --enable-tls-mlkem-standalone --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', + '--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,1024 --enable-tls-mlkem-standalone --disable-pqc-hybrids --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', ] name: make check if: github.repository_owner == 'wolfssl' diff --git a/.github/workflows/psk.yml b/.github/workflows/psk.yml index 4b1373579af..f1cd0c64df3 100644 --- a/.github/workflows/psk.yml +++ b/.github/workflows/psk.yml @@ -18,10 +18,10 @@ jobs: matrix: config: [ # Add new configs here - '--enable-psk C_EXTRA_FLAGS="-DWOLFSSL_STATIC_PSK -DWOLFSSL_OLDTLS_SHA2_CIPHERSUITES"', - '--enable-psk C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --disable-rsa --disable-ecc --disable-dh', - '--disable-oldtls --disable-tls13 --enable-psk -disable-rsa --disable-dh -disable-ecc --disable-asn C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --enable-lowresource --enable-singlethreaded --disable-asm --disable-errorstrings --disable-pkcs12 --disable-sha3 --disable-sha224 --disable-sha384 --disable-sha512 --disable-sha --disable-md5 -disable-aescbc --disable-chacha --disable-poly1305 --disable-coding --disable-sp-math-all', - '--disable-oldtls --disable-tlsv12 --enable-tls13 --enable-psk -disable-rsa --disable-dh -disable-ecc --disable-asn C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --enable-lowresource --enable-singlethreaded --disable-asm --disable-errorstrings --disable-pkcs12 --disable-sha3 --disable-sha224 --disable-sha384 --disable-sha512 --disable-sha --disable-md5 -disable-aescbc --disable-chacha --disable-poly1305 --disable-coding --disable-sp-math-all' + '--enable-psk --disable-mlkem C_EXTRA_FLAGS="-DWOLFSSL_STATIC_PSK -DWOLFSSL_OLDTLS_SHA2_CIPHERSUITES"', + '--enable-psk --disable-mlkem C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --disable-rsa --disable-ecc --disable-dh', + '--disable-oldtls --disable-tls13 --enable-psk -disable-rsa --disable-dh -disable-ecc --disable-asn C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --enable-lowresource --enable-singlethreaded --disable-asm --disable-errorstrings --disable-pkcs12 --disable-sha3 --disable-sha224 --disable-sha384 --disable-sha512 --disable-sha --disable-md5 -disable-aescbc --disable-chacha --disable-poly1305 --disable-coding --disable-sp-math-all --disable-mlkem', + '--disable-oldtls --disable-tlsv12 --enable-tls13 --enable-psk -disable-rsa --disable-dh -disable-ecc --disable-asn C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --enable-lowresource --enable-singlethreaded --disable-asm --disable-errorstrings --disable-pkcs12 --disable-sha3 --disable-sha224 --disable-sha384 --disable-sha512 --disable-sha --disable-md5 -disable-aescbc --disable-chacha --disable-poly1305 --disable-coding --disable-sp-math-all --disable-mlkem' ] name: make check if: github.repository_owner == 'wolfssl' diff --git a/.github/workflows/rust-wrapper.yml b/.github/workflows/rust-wrapper.yml index 8a27b8fb131..667960d944b 100644 --- a/.github/workflows/rust-wrapper.yml +++ b/.github/workflows/rust-wrapper.yml @@ -41,36 +41,36 @@ jobs: '--enable-all --enable-dilithium', '--enable-all --enable-mlkem', '--enable-cryptonly --disable-examples', - '--enable-cryptonly --disable-examples --disable-aes --disable-aesgcm', - '--enable-cryptonly --disable-examples --disable-aescbc', - '--enable-cryptonly --disable-examples --disable-aeseax', - '--enable-cryptonly --disable-examples --disable-aesecb', - '--enable-cryptonly --disable-examples --disable-aesccm', - '--enable-cryptonly --disable-examples --disable-aescfb', - '--enable-cryptonly --disable-examples --disable-aesctr', - '--enable-cryptonly --disable-examples --disable-aescts', - '--enable-cryptonly --disable-examples --disable-aesgcm', - '--enable-cryptonly --disable-examples --disable-aesgcm-stream', - '--enable-cryptonly --disable-examples --disable-aesofb', - '--enable-cryptonly --disable-examples --disable-aesxts', - '--enable-cryptonly --disable-examples --disable-cmac', - '--enable-cryptonly --disable-examples --disable-dh', - '--enable-cryptonly --disable-examples --disable-ecc', - '--enable-cryptonly --disable-examples --disable-ed25519', - '--enable-cryptonly --disable-examples --disable-ed25519-stream', - '--enable-cryptonly --disable-examples --disable-ed448', - '--enable-cryptonly --disable-examples --disable-ed448-stream', - '--enable-cryptonly --disable-examples --disable-hkdf', - '--enable-cryptonly --disable-examples --disable-hmac', - '--enable-cryptonly --disable-examples --disable-rng', - '--enable-cryptonly --disable-examples --disable-rsa', - '--enable-cryptonly --disable-examples --disable-rsapss', - '--enable-cryptonly --disable-examples --disable-sha224', - '--enable-cryptonly --disable-examples --disable-sha3', - '--enable-cryptonly --disable-examples --disable-sha384', - '--enable-cryptonly --disable-examples --disable-sha512', - '--enable-cryptonly --disable-examples --disable-shake128', - '--enable-cryptonly --disable-examples --disable-shake256', - '--enable-cryptonly --disable-examples --disable-srtp-kdf', - '--enable-cryptonly --disable-examples --disable-x963kdf', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aes --disable-aesgcm', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aescbc', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aeseax', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aesecb', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aesccm', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aescfb', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aesctr', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aescts', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aesgcm', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aesgcm-stream', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aesofb', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-aesxts', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-cmac', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-dh', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-ecc', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-ed25519', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-ed25519-stream', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-ed448', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-ed448-stream', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-hkdf', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-hmac', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-rng', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-rsa', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-rsapss', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-sha224', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-sha3', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-sha384', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-sha512', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-shake128', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-shake256', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-srtp-kdf', + '--enable-cryptonly --disable-examples --disable-mlkem --disable-x963kdf', ] diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index df1b2e1cddb..922dce92c67 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -28,7 +28,7 @@ jobs: if: github.repository_owner == 'wolfssl' runs-on: ubuntu-22.04 # This should be a safe limit for the tests to run. - timeout-minutes: 25 + timeout-minutes: 45 steps: - name: Install dependencies run: | diff --git a/.wolfssl_known_macro_extras b/.wolfssl_known_macro_extras index e147b902c69..931d8da31ca 100644 --- a/.wolfssl_known_macro_extras +++ b/.wolfssl_known_macro_extras @@ -174,6 +174,7 @@ CONFIG_WOLFSSL_EXAMPLE_NAME_WOLFSSH_ECHOSERVER CONFIG_WOLFSSL_EXAMPLE_NAME_WOLFSSH_TEMPLATE CONFIG_WOLFSSL_HKDF CONFIG_WOLFSSL_MAX_FRAGMENT_LEN +CONFIG_WOLFSSL_MLKEM CONFIG_WOLFSSL_NO_ASN_STRICT CONFIG_WOLFSSL_PSK CONFIG_WOLFSSL_RSA_PSS diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f2f9923136..75275d857b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,7 +610,7 @@ add_option(WOLFSSL_OQS # ML-KEM/Kyber add_option(WOLFSSL_MLKEM "Enable the wolfSSL PQ ML-KEM library (default: disabled)" - "no" "yes;no") + "yes" "yes;no") if (WOLFSSL_MLKEM) list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_HAVE_MLKEM") @@ -626,6 +626,32 @@ if (WOLFSSL_MLKEM) set_wolfssl_definitions("WOLFSSL_SHAKE256" RESULT) endif() +# When MLKEM and DTLS 1.3 are both enabled, DTLS ClientHello fragmenting is +# required (PQC keys in ClientHello can exceed MTU), so enable it automatically. +if(WOLFSSL_MLKEM AND WOLFSSL_DTLS13 AND NOT WOLFSSL_DTLS_CH_FRAG) + message(STATUS "MLKEM and DTLS 1.3 are enabled; enabling DTLS ClientHello fragmenting") + override_cache(WOLFSSL_DTLS_CH_FRAG "yes") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_DTLS_CH_FRAG") +endif() + +# Disable ML-KEM as standalone TLS key exchange (non-hybrid); when enabled (default), standalone is disabled +add_option(WOLFSSL_TLS_NO_MLKEM_STANDALONE + "Disable ML-KEM as standalone TLS key exchange (non-hybrid) (default: enabled, i.e. standalone disabled)" + "yes" "yes;no") + +if (WOLFSSL_TLS_NO_MLKEM_STANDALONE) + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_TLS_NO_MLKEM_STANDALONE") +endif() + +# PQ/T hybrid combinations +add_option(WOLFSSL_PQC_HYBRIDS + "Enable PQ/T hybrid combinations (default: enabled)" + "yes" "yes;no") + +if (WOLFSSL_PQC_HYBRIDS) + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_PQC_HYBRIDS") +endif() + # Dilithium add_option(WOLFSSL_DILITHIUM "Enable the wolfSSL PQ Dilithium (ML-DSA) implementation (default: disabled)" @@ -675,6 +701,10 @@ add_option(WOLFSSL_EXPERIMENTAL "Enable experimental features (default: disabled)" "no" "yes;no") +add_option(WOLFSSL_EXTRA_PQC_HYBRIDS + "Enable extra PQ/T hybrid combinations (default: disabled)" + "no" "yes;no") + message(STATUS "Looking for WOLFSSL_EXPERIMENTAL") if (WOLFSSL_EXPERIMENTAL) message(STATUS "Looking for WOLFSSL_EXPERIMENTAL - found") @@ -710,6 +740,16 @@ if (WOLFSSL_EXPERIMENTAL) message(STATUS "Looking for WOLFSSL_OQS - not found") endif() + # Checking for experimental feature: extra PQ/T hybrid combinations + message(STATUS "Looking for WOLFSSL_EXTRA_PQC_HYBRIDS") + if (WOLFSSL_EXTRA_PQC_HYBRIDS) + set(WOLFSSL_FOUND_EXPERIMENTAL_FEATURE 1) + message(STATUS "Looking for WOLFSSL_EXTRA_PQC_HYBRIDS - found") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_EXTRA_PQC_HYBRIDS") + else() + message(STATUS "Looking for WOLFSSL_EXTRA_PQC_HYBRIDS - not found") + endif() + # Other experimental feature detection can be added here... # Were any experimental features found? Display a message. diff --git a/IDE/WIN10/wolfssl-fips.vcxproj b/IDE/WIN10/wolfssl-fips.vcxproj index 42d574220fd..eac076eb3ae 100644 --- a/IDE/WIN10/wolfssl-fips.vcxproj +++ b/IDE/WIN10/wolfssl-fips.vcxproj @@ -292,6 +292,8 @@ + + diff --git a/cmake/options.h.in b/cmake/options.h.in index 31df488e1e8..985b54241d6 100644 --- a/cmake/options.h.in +++ b/cmake/options.h.in @@ -380,6 +380,8 @@ extern "C" { #cmakedefine WOLFSSL_HAVE_MLKEM #undef WOLFSSL_WC_MLKEM #cmakedefine WOLFSSL_WC_MLKEM +#undef WOLFSSL_TLS_NO_MLKEM_STANDALONE +#cmakedefine WOLFSSL_TLS_NO_MLKEM_STANDALONE #undef WOLFSSL_WC_DILITHIUM #cmakedefine WOLFSSL_WC_DILITHIUM #undef NO_WOLFSSL_STUB @@ -414,6 +416,10 @@ extern "C" { #cmakedefine WOLFSSL_HAVE_SLHDSA #undef WOLFSSL_WC_SLHDSA #cmakedefine WOLFSSL_WC_SLHDSA +#undef WOLFSSL_PQC_HYBRIDS +#cmakedefine WOLFSSL_PQC_HYBRIDS +#undef WOLFSSL_EXTRA_PQC_HYBRIDS +#cmakedefine WOLFSSL_EXTRA_PQC_HYBRIDS #ifdef __cplusplus } diff --git a/configure.ac b/configure.ac index dc5ca6715d1..6e7ed2cc552 100644 --- a/configure.ac +++ b/configure.ac @@ -1711,9 +1711,9 @@ AC_ARG_WITH([liboqs], # Used: # - SHA3, Shake128 and Shake256 AC_ARG_ENABLE([mlkem], - [AS_HELP_STRING([--enable-mlkem],[Enable ML-KEM/Kyber (default: disabled)])], + [AS_HELP_STRING([--enable-mlkem],[Enable ML-KEM/Kyber (default: enabled)])], [ ENABLED_MLKEM=$enableval ], - [ ENABLED_MLKEM=no ] + [ ENABLED_MLKEM=yes ] ) # note, inherits default from "mlkem" clause above. AC_ARG_ENABLE([kyber], @@ -1721,6 +1721,13 @@ AC_ARG_ENABLE([kyber], [ ENABLED_MLKEM=$enableval ] ) +# FIPS traditionally does not support SHAKE 128 and SHAKE 256 (v6 does), so disable +# ML-KEM if FIPS is enabled and version is less than 6 +AS_IF([test "x$ENABLED_FIPS" = "xyes" && test $HAVE_FIPS_VERSION -lt 6],[ + AC_MSG_NOTICE([Disabling MLKEM because FIPS < 6 does not support required SHAKE]) + ENABLED_MLKEM="no" +]) + ENABLED_WC_MLKEM=no ENABLED_ML_KEM=unset ENABLED_MLKEM_MAKE_KEY=no @@ -1847,8 +1854,61 @@ then fi fi +AC_ARG_ENABLE([tls-mlkem-standalone], + [AS_HELP_STRING([--enable-tls-mlkem-standalone],[Enable ML-KEM as standalone TLS key exchange (non-hybrid) (default: disabled)])], + [ ENABLED_MLKEM_STANDALONE=$enableval ], + [ ENABLED_MLKEM_STANDALONE=no ] + ) + +AS_IF([ test "$ENABLED_MLKEM_STANDALONE" = "yes" && test "$ENABLED_ML_KEM" = "no" ],[AC_MSG_ERROR([ML-KEM as standalone TLS key exchange (non-hybrid) requires ML-KEM.])]) +if test "$ENABLED_MLKEM_STANDALONE" != "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_TLS_NO_MLKEM_STANDALONE" +fi + +AC_ARG_ENABLE([pqc-hybrids], + [AS_HELP_STRING([--enable-pqc-hybrids],[Enable PQ/T hybrid combinations (default: enabled)])], + [ ENABLED_PQC_HYBRIDS=$enableval ], + [ ENABLED_PQC_HYBRIDS=yes ] + ) + +if test "$ENABLED_PQC_HYBRIDS" = "yes" +then + if test "$ENABLED_ML_KEM" = "no" || test "$ENABLED_MLKEM" = "no" + then + ENABLED_PQC_HYBRIDS=no + elif test "$ENABLED_MLKEM768" = "" && test "$ENABLED_MLKEM1024" = ""; then + AC_MSG_NOTICE([PQC hybrid combinations require either ML-KEM 768 or ML-KEM 1024, but both disabled.]) + ENABLED_PQC_HYBRIDS=no + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PQC_HYBRIDS" + fi +fi + +if test "$ENABLED_ML_KEM" != "no" && test "$ENABLED_MLKEM" != "no" +then + if test "$ENABLED_PQC_HYBRIDS" = "no" && test "$ENABLED_MLKEM_STANDALONE" = "no" && test "$ENABLED_CRYPTONLY" = "no" + then + AC_MSG_ERROR([Both hybrid PQ/T and standalone ML-KEM are disabled, so no PQC hybrid combinations will be available.]) + fi +fi + +# Extra PQ/T Hybrid combinations +AC_ARG_ENABLE([extra-pqc-hybrids], + [AS_HELP_STRING([--enable-extra-pqc-hybrids],[Enable extra PQ/T hybrid combinations (default: disabled)])], + [ ENABLED_EXTRA_PQC_HYBRIDS=$enableval ], + [ ENABLED_EXTRA_PQC_HYBRIDS=no ] + ) + +if test "$ENABLED_EXTRA_PQC_HYBRIDS" = "yes" +then + AS_IF([ test "$ENABLED_EXPERIMENTAL" != "yes" ],[ AC_MSG_ERROR([extra-pqc-hybrids requires --enable-experimental.]) ]) + AS_IF([ test "$ENABLED_ML_KEM" = "no" ],[ AC_MSG_ERROR([extra-pqc-hybrids requires ML-KEM.]) ]) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_EXTRA_PQC_HYBRIDS" +fi + # Dilithium -# - SHA3, Shake128, Shake256 and AES-CTR +# - SHA3, Shake128 and Shake256 AC_ARG_ENABLE([mldsa], [AS_HELP_STRING([--enable-mldsa],[Enable ML-DSA/Dilithium (default: disabled)])], [ ENABLED_DILITHIUM=$enableval ], @@ -4628,6 +4688,17 @@ then AM_CFLAGS="$AM_CFLAGS -DWC_SHA3_NO_ASM" fi +# MLKEM requires SHA-3. Force-enable SHA-3 when MLKEM is enabled. +if test "$ENABLED_MLKEM" != "no" +then + if test "$ENABLED_SHA3" = "no" + then + AC_MSG_NOTICE([MLKEM enabled (not explicitly disabled); overriding --disable-sha3 to enable SHA-3]) + ENABLED_SHA3=yes + enable_sha3=yes + fi +fi + # SHAKE128 AC_ARG_ENABLE([shake128], [AS_HELP_STRING([--enable-shake128],[Enable wolfSSL SHAKE128 support (default: disabled)])], @@ -4635,6 +4706,17 @@ AC_ARG_ENABLE([shake128], [ ENABLED_SHAKE128=no ] ) +# MLKEM requires SHAKE128. Force-enable when MLKEM is enabled. +if test "$ENABLED_MLKEM" != "no" +then + if test "$ENABLED_SHAKE128" = "no" + then + AC_MSG_WARN([MLKEM enabled (not explicitly disabled); overriding --disable-shake128 to enable SHAKE128]) + ENABLED_SHAKE128=yes + enable_shake128=yes + fi +fi + # SHAKE256 AC_ARG_ENABLE([shake256], [AS_HELP_STRING([--enable-shake256],[Enable wolfSSL SHAKE256 support (default: disabled)])], @@ -4642,6 +4724,17 @@ AC_ARG_ENABLE([shake256], [ ENABLED_SHAKE256=no ] ) +# MLKEM requires SHAKE256. Force-enable when MLKEM is enabled. +if test "$ENABLED_MLKEM" != "no" +then + if test "$ENABLED_SHAKE256" = "no" + then + AC_MSG_WARN([MLKEM enabled (not explicitly disabled); overriding --disable-shake256 to enable SHAKE256]) + ENABLED_SHAKE256=yes + enable_shake256=yes + fi +fi + # SHA512 AC_ARG_ENABLE([sha512], [AS_HELP_STRING([--enable-sha512],[Enable wolfSSL SHA-512 support (default: enabled)])], @@ -5828,6 +5921,15 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DTLS_CH_FRAG" fi +# When MLKEM and DTLS 1.3 are both enabled, DTLS ClientHello fragmenting is +# required (PQC keys in ClientHello can exceed MTU), so enable it automatically. +if test "x$ENABLED_MLKEM" != "xno" && test "x$ENABLED_DTLS13" = "xyes" && test "x$ENABLED_DTLS_CH_FRAG" != "xyes" +then + AC_MSG_NOTICE([MLKEM and DTLS 1.3 are enabled; enabling DTLS ClientHello fragmenting]) + ENABLED_DTLS_CH_FRAG=yes + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DTLS_CH_FRAG" +fi + # CODING AC_ARG_ENABLE([coding], [AS_HELP_STRING([--enable-coding],[Enable Coding base 16/64 (default: enabled)])], @@ -7964,6 +8066,11 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SEND_HRR_COOKIE" ENABLED_SEND_HRR_COOKIE="yes" fi + if test "x$ENABLED_MLKEM" != "xno" && test "x$ENABLED_DTLS_CH_FRAG" != "xyes" + then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_DTLS_CH_FRAG" + ENABLED_DTLS_CH_FRAG="yes" + fi if test "x$ENABLED_AES" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_AES_DIRECT" @@ -12073,6 +12180,9 @@ echo " * ERR Queues per Thread: $ENABLED_ERRORQUEUEPERTHREAD" echo " * rwlock: $ENABLED_RWLOCK" echo " * keylog export: $ENABLED_KEYLOG_EXPORT" echo " * AutoSAR : $ENABLED_AUTOSAR" +echo " * ML-KEM standalone: $ENABLED_MLKEM_STANDALONE" +echo " * PQ/T hybrids: $ENABLED_PQC_HYBRIDS" +echo " * Extra PQ/T hybrids: $ENABLED_EXTRA_PQC_HYBRIDS" echo "" echo "---" diff --git a/examples/benchmark/tls_bench.c b/examples/benchmark/tls_bench.c index 25355943683..85645224fdb 100644 --- a/examples/benchmark/tls_bench.c +++ b/examples/benchmark/tls_bench.c @@ -296,17 +296,23 @@ static struct group_info groups[] = { { WOLFSSL_FFDHE_8192, "FFDHE_8192" }, #ifdef HAVE_PQC #ifndef WOLFSSL_NO_ML_KEM + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE { WOLFSSL_ML_KEM_512, "ML_KEM_512" }, { WOLFSSL_ML_KEM_768, "ML_KEM_768" }, { WOLFSSL_ML_KEM_1024, "ML_KEM_1024" }, + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_PQC_HYBRIDS + { WOLFSSL_SECP256R1MLKEM768, "SecP256r1MLKEM768" }, + { WOLFSSL_SECP384R1MLKEM1024, "SecP384r1MLKEM1024" }, + { WOLFSSL_X25519MLKEM768, "X25519MLKEM768" }, + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS { WOLFSSL_SECP256R1MLKEM512, "SecP256r1MLKEM512" }, { WOLFSSL_SECP384R1MLKEM768, "SecP384r1MLKEM768" }, - { WOLFSSL_SECP256R1MLKEM768, "SecP256r1MLKEM768" }, { WOLFSSL_SECP521R1MLKEM1024, "SecP521r1MLKEM1024" }, - { WOLFSSL_SECP384R1MLKEM1024, "SecP384r1MLKEM1024" }, { WOLFSSL_X25519MLKEM512, "X25519MLKEM512" }, { WOLFSSL_X448MLKEM768, "X448MLKEM768" }, - { WOLFSSL_X25519MLKEM768, "X25519MLKEM768" }, + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ #endif #ifdef WOLFSSL_MLKEM_KYBER { WOLFSSL_KYBER_LEVEL1, "KYBER_LEVEL1" }, diff --git a/examples/client/client.c b/examples/client/client.c index c3f8d67d535..8e925f41173 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -426,61 +426,78 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, int group = 0; #ifndef WOLFSSL_NO_ML_KEM - #ifndef WOLFSSL_NO_ML_KEM_512 + #if !defined(WOLFSSL_NO_ML_KEM_512) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) if (XSTRCMP(pqcAlg, "ML_KEM_512") == 0) { group = WOLFSSL_ML_KEM_512; } else #endif - #ifndef WOLFSSL_NO_ML_KEM_768 + #if !defined(WOLFSSL_NO_ML_KEM_768) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) if (XSTRCMP(pqcAlg, "ML_KEM_768") == 0) { group = WOLFSSL_ML_KEM_768; } else #endif - #ifndef WOLFSSL_NO_ML_KEM_1024 + #if !defined(WOLFSSL_NO_ML_KEM_1024) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) if (XSTRCMP(pqcAlg, "ML_KEM_1024") == 0) { group = WOLFSSL_ML_KEM_1024; } else #endif - #ifndef WOLFSSL_NO_ML_KEM_512 + #if !defined(WOLFSSL_NO_ML_KEM_512) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "SecP256r1MLKEM512") == 0) { group = WOLFSSL_SECP256R1MLKEM512; } else #endif #ifndef WOLFSSL_NO_ML_KEM_768 + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS if (XSTRCMP(pqcAlg, "SecP384r1MLKEM768") == 0) { group = WOLFSSL_SECP384R1MLKEM768; } - else if (XSTRCMP(pqcAlg, "SecP256r1MLKEM768") == 0) { + else + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #ifdef WOLFSSL_PQC_HYBRIDS + if (XSTRCMP(pqcAlg, "SecP256r1MLKEM768") == 0) { group = WOLFSSL_SECP256R1MLKEM768; } else + #endif /* WOLFSSL_PQC_HYBRIDS */ #endif #ifndef WOLFSSL_NO_ML_KEM_1024 + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS if (XSTRCMP(pqcAlg, "SecP521r1MLKEM1024") == 0) { group = WOLFSSL_SECP521R1MLKEM1024; } - else if (XSTRCMP(pqcAlg, "SecP384r1MLKEM1024") == 0) { + else + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #ifdef WOLFSSL_PQC_HYBRIDS + if (XSTRCMP(pqcAlg, "SecP384r1MLKEM1024") == 0) { group = WOLFSSL_SECP384R1MLKEM1024; } else + #endif /* WOLFSSL_PQC_HYBRIDS */ #endif - #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) + #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "X25519MLKEM512") == 0) { group = WOLFSSL_X25519MLKEM512; } else #endif - #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) && \ + defined(WOLFSSL_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "X25519MLKEM768") == 0) { group = WOLFSSL_X25519MLKEM768; } else #endif - #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "X448MLKEM768") == 0) { group = WOLFSSL_X448MLKEM768; } @@ -551,12 +568,17 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, } printf("Using Post-Quantum KEM: %s\n", pqcAlg); - if (wolfSSL_UseKeyShare(ssl, group) == WOLFSSL_SUCCESS) { - groups[count++] = group; - } - else { - err_sys("unable to use post-quantum KEM"); - } + do { + ret = wolfSSL_UseKeyShare(ssl, group); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = group; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use post-quantum KEM"); + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); #ifdef WOLFSSL_DTLS13 if (wolfSSL_dtls(ssl)) { diff --git a/examples/server/server.c b/examples/server/server.c index e642b695092..e52d611fbb6 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -717,61 +717,78 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, #ifdef HAVE_PQC groups[count] = 0; #ifndef WOLFSSL_NO_ML_KEM - #ifndef WOLFSSL_NO_ML_KEM_512 + #if !defined(WOLFSSL_NO_ML_KEM_512) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) if (XSTRCMP(pqcAlg, "ML_KEM_512") == 0) { groups[count] = WOLFSSL_ML_KEM_512; } else #endif - #ifndef WOLFSSL_NO_ML_KEM_768 + #if !defined(WOLFSSL_NO_ML_KEM_768) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) if (XSTRCMP(pqcAlg, "ML_KEM_768") == 0) { groups[count] = WOLFSSL_ML_KEM_768; } else #endif - #ifndef WOLFSSL_NO_ML_KEM_1024 + #if !defined(WOLFSSL_NO_ML_KEM_1024) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) if (XSTRCMP(pqcAlg, "ML_KEM_1024") == 0) { groups[count] = WOLFSSL_ML_KEM_1024; } else #endif - #ifndef WOLFSSL_NO_ML_KEM_512 + #if !defined(WOLFSSL_NO_ML_KEM_512) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "SecP256r1MLKEM512") == 0) { groups[count] = WOLFSSL_SECP256R1MLKEM512; } else #endif #ifndef WOLFSSL_NO_ML_KEM_768 + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS if (XSTRCMP(pqcAlg, "SecP384r1MLKEM768") == 0) { groups[count] = WOLFSSL_SECP384R1MLKEM768; } - else if (XSTRCMP(pqcAlg, "SecP256r1MLKEM768") == 0) { + else + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #ifdef WOLFSSL_PQC_HYBRIDS + if (XSTRCMP(pqcAlg, "SecP256r1MLKEM768") == 0) { groups[count] = WOLFSSL_SECP256R1MLKEM768; } else + #endif /* WOLFSSL_PQC_HYBRIDS */ #endif #ifndef WOLFSSL_NO_ML_KEM_1024 + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS if (XSTRCMP(pqcAlg, "SecP521r1MLKEM1024") == 0) { groups[count] = WOLFSSL_SECP521R1MLKEM1024; } - else if (XSTRCMP(pqcAlg, "SecP384r1MLKEM1024") == 0) { + else + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #ifdef WOLFSSL_PQC_HYBRIDS + if (XSTRCMP(pqcAlg, "SecP384r1MLKEM1024") == 0) { groups[count] = WOLFSSL_SECP384R1MLKEM1024; } else + #endif /* WOLFSSL_PQC_HYBRIDS */ #endif - #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) + #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "X25519MLKEM512") == 0) { groups[count] = WOLFSSL_X25519MLKEM512; } else #endif - #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) && \ + defined(WOLFSSL_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "X25519MLKEM768") == 0) { groups[count] = WOLFSSL_X25519MLKEM768; } else #endif - #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) if (XSTRCMP(pqcAlg, "X448MLKEM768") == 0) { groups[count] = WOLFSSL_X448MLKEM768; } @@ -845,14 +862,21 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, err_sys("invalid post-quantum KEM specified"); } else { - if (wolfSSL_UseKeyShare(ssl, groups[count]) == WOLFSSL_SUCCESS) { - printf("Using Post-Quantum KEM: %s\n", pqcAlg); - count++; - } - else { - groups[count] = 0; - err_sys("unable to use post-quantum algorithm"); - } + do { + ret = wolfSSL_UseKeyShare(ssl, groups[count]); + if (ret == WOLFSSL_SUCCESS) { + printf("Using Post-Quantum KEM: %s\n", pqcAlg); + count++; + } + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else { + groups[count] = 0; + err_sys("unable to use post-quantum algorithm"); + } + } while (ret == WC_NO_ERR_TRACE(WC_PENDING_E)); } #endif } diff --git a/src/internal.c b/src/internal.c index 0ffe6c51f06..0b201c5b5de 100644 --- a/src/internal.c +++ b/src/internal.c @@ -35172,21 +35172,28 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Returns 1 when the given group is a PQC hybrid group, 0 otherwise. */ int NamedGroupIsPqcHybrid(int group) { + #if defined(WOLFSSL_PQC_HYBRIDS) || defined(WOLFSSL_EXTRA_PQC_HYBRIDS) || \ + defined(WOLFSSL_MLKEM_KYBER) + switch (group) { #ifndef WOLFSSL_NO_ML_KEM + #ifdef WOLFSSL_PQC_HYBRIDS case WOLFSSL_SECP256R1MLKEM768: case WOLFSSL_X25519MLKEM768: case WOLFSSL_SECP384R1MLKEM1024: + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS case WOLFSSL_SECP256R1MLKEM512: case WOLFSSL_SECP384R1MLKEM768: case WOLFSSL_SECP521R1MLKEM1024: case WOLFSSL_X25519MLKEM512: case WOLFSSL_X448MLKEM768: -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS + #ifdef WOLFSSL_ML_KEM_USE_OLD_IDS case WOLFSSL_P256_ML_KEM_512_OLD: case WOLFSSL_P384_ML_KEM_768_OLD: case WOLFSSL_P521_ML_KEM_1024_OLD: -#endif + #endif + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ #endif #ifdef WOLFSSL_MLKEM_KYBER case WOLFSSL_P256_KYBER_LEVEL3: @@ -35201,6 +35208,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, default: return 0; } + #else + (void)group; + return 0; + #endif } #endif /* WOLFSSL_HAVE_MLKEM */ diff --git a/src/ssl.c b/src/ssl.c index 9772b85e4ef..b21558da1c8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2967,18 +2967,24 @@ static int isValidCurveGroup(word16 name) #ifdef WOLFSSL_HAVE_MLKEM #ifndef WOLFSSL_NO_ML_KEM + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE case WOLFSSL_ML_KEM_512: case WOLFSSL_ML_KEM_768: case WOLFSSL_ML_KEM_1024: + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ #if defined(WOLFSSL_WC_MLKEM) || defined(HAVE_LIBOQS) + #ifdef WOLFSSL_PQC_HYBRIDS + case WOLFSSL_SECP384R1MLKEM1024: + case WOLFSSL_X25519MLKEM768: + case WOLFSSL_SECP256R1MLKEM768: + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS case WOLFSSL_SECP256R1MLKEM512: case WOLFSSL_SECP384R1MLKEM768: case WOLFSSL_SECP521R1MLKEM1024: - case WOLFSSL_SECP384R1MLKEM1024: case WOLFSSL_X25519MLKEM512: case WOLFSSL_X448MLKEM768: - case WOLFSSL_X25519MLKEM768: - case WOLFSSL_SECP256R1MLKEM768: + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ #endif #endif /* !WOLFSSL_NO_ML_KEM */ #ifdef WOLFSSL_MLKEM_KYBER @@ -10610,49 +10616,59 @@ const char* wolfSSL_get_curve_name(WOLFSSL* ssl) #ifndef WOLFSSL_NO_ML_KEM_512 case WOLFSSL_ML_KEM_512: return "ML_KEM_512"; - case WOLFSSL_SECP256R1MLKEM512: - return "SecP256r1MLKEM512"; -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + #ifdef WOLFSSL_ML_KEM_USE_OLD_IDS case WOLFSSL_P256_ML_KEM_512_OLD: return "P256_ML_KEM_512_OLD"; -#endif + #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS */ + case WOLFSSL_SECP256R1MLKEM512: + return "SecP256r1MLKEM512"; #ifdef HAVE_CURVE25519 case WOLFSSL_X25519MLKEM512: return "X25519MLKEM512"; - #endif - #endif + #endif /* HAVE_CURVE25519 */ + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #endif /* WOLFSSL_NO_ML_KEM_512 */ #ifndef WOLFSSL_NO_ML_KEM_768 case WOLFSSL_ML_KEM_768: return "ML_KEM_768"; - case WOLFSSL_SECP384R1MLKEM768: - return "SecP384r1MLKEM768"; -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS - case WOLFSSL_P384_ML_KEM_768_OLD: - return "P384_ML_KEM_768_OLD"; -#endif + #ifdef WOLFSSL_PQC_HYBRIDS case WOLFSSL_SECP256R1MLKEM768: return "SecP256r1MLKEM768"; #ifdef HAVE_CURVE25519 case WOLFSSL_X25519MLKEM768: return "X25519MLKEM768"; #endif + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + #ifdef WOLFSSL_ML_KEM_USE_OLD_IDS + case WOLFSSL_P384_ML_KEM_768_OLD: + return "P384_ML_KEM_768_OLD"; + #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS */ + case WOLFSSL_SECP384R1MLKEM768: + return "SecP384r1MLKEM768"; #ifdef HAVE_CURVE448 case WOLFSSL_X448MLKEM768: return "X448MLKEM768"; - #endif - #endif + #endif /* HAVE_CURVE448 */ + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #endif /* WOLFSSL_NO_ML_KEM_768 */ #ifndef WOLFSSL_NO_ML_KEM_1024 case WOLFSSL_ML_KEM_1024: return "ML_KEM_1024"; - case WOLFSSL_SECP521R1MLKEM1024: - return "SecP521r1MLKEM1024"; -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS - case WOLFSSL_P521_ML_KEM_1024_OLD: - return "P521_ML_KEM_1024_OLD"; -#endif + #ifdef WOLFSSL_PQC_HYBRIDS case WOLFSSL_SECP384R1MLKEM1024: return "SecP384r1MLKEM1024"; - #endif + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + #ifdef WOLFSSL_ML_KEM_USE_OLD_IDS + case WOLFSSL_P521_ML_KEM_1024_OLD: + return "P521_ML_KEM_1024_OLD"; + #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS */ + case WOLFSSL_SECP521R1MLKEM1024: + return "SecP521r1MLKEM1024"; + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #endif /* WOLFSSL_NO_ML_KEM_1024 */ #elif defined(HAVE_LIBOQS) case WOLFSSL_ML_KEM_512: return "ML_KEM_512"; @@ -16847,22 +16863,26 @@ const WOLF_EC_NIST_NAME kNistCurves[] = { {CURVE_NAME("ML_KEM_768"), WOLFSSL_ML_KEM_768, WOLFSSL_ML_KEM_768}, {CURVE_NAME("ML_KEM_1024"), WOLFSSL_ML_KEM_1024, WOLFSSL_ML_KEM_1024}, #if (defined(WOLFSSL_WC_MLKEM) || defined(HAVE_LIBOQS)) && defined(HAVE_ECC) + #ifdef WOLFSSL_PQC_HYBRIDS + {CURVE_NAME("SecP256r1MLKEM768"), WOLFSSL_SECP256R1MLKEM768, + WOLFSSL_SECP256R1MLKEM768}, + {CURVE_NAME("SecP384r1MLKEM1024"), WOLFSSL_SECP384R1MLKEM1024, + WOLFSSL_SECP384R1MLKEM1024}, + {CURVE_NAME("X25519MLKEM768"), WOLFSSL_X25519MLKEM768, + WOLFSSL_X25519MLKEM768}, + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS {CURVE_NAME("SecP256r1MLKEM512"), WOLFSSL_SECP256R1MLKEM512, WOLFSSL_SECP256R1MLKEM512}, {CURVE_NAME("SecP384r1MLKEM768"), WOLFSSL_SECP384R1MLKEM768, WOLFSSL_SECP384R1MLKEM768}, - {CURVE_NAME("SecP256r1MLKEM768"), WOLFSSL_SECP256R1MLKEM768, - WOLFSSL_SECP256R1MLKEM768}, {CURVE_NAME("SecP521r1MLKEM1024"), WOLFSSL_SECP521R1MLKEM1024, WOLFSSL_SECP521R1MLKEM1024}, - {CURVE_NAME("SecP384r1MLKEM1024"), WOLFSSL_SECP384R1MLKEM1024, - WOLFSSL_SECP384R1MLKEM1024}, {CURVE_NAME("X25519MLKEM512"), WOLFSSL_X25519MLKEM512, WOLFSSL_X25519MLKEM512}, {CURVE_NAME("X448MLKEM768"), WOLFSSL_X448MLKEM768, WOLFSSL_X448MLKEM768}, - {CURVE_NAME("X25519MLKEM768"), WOLFSSL_X25519MLKEM768, - WOLFSSL_X25519MLKEM768}, + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ #endif #endif /* !WOLFSSL_NO_ML_KEM */ #ifdef WOLFSSL_MLKEM_KYBER diff --git a/src/tls.c b/src/tls.c index a4dc98e592b..26ebcf713e4 100644 --- a/src/tls.c +++ b/src/tls.c @@ -4465,7 +4465,7 @@ static void findEccPqc(int *ecc, int *pqc, int *pqc_first, int group); * namedGroup The named group to check. * returns 1 when supported or 0 otherwise. */ -static int TLSX_IsGroupSupported(int namedGroup) +int TLSX_IsGroupSupported(int namedGroup) { switch (namedGroup) { #ifdef HAVE_FFDHE_2048 @@ -4577,37 +4577,55 @@ static int TLSX_IsGroupSupported(int namedGroup) #ifndef WOLFSSL_NO_ML_KEM #ifdef WOLFSSL_WC_MLKEM #ifndef WOLFSSL_NO_ML_KEM_512 + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE case WOLFSSL_ML_KEM_512: + break; + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS case WOLFSSL_SECP256R1MLKEM512: - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 case WOLFSSL_X25519MLKEM512: - #endif - break; - #endif + #endif /* HAVE_CURVE25519 */ + break; + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #endif /* WOLFSSL_NO_ML_KEM_512 */ #ifndef WOLFSSL_NO_ML_KEM_768 + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE case WOLFSSL_ML_KEM_768: - case WOLFSSL_SECP384R1MLKEM768: + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_PQC_HYBRIDS case WOLFSSL_SECP256R1MLKEM768: - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 case WOLFSSL_X25519MLKEM768: - #endif - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + #endif /* HAVE_CURVE25519 */ + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + case WOLFSSL_SECP384R1MLKEM768: + #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 case WOLFSSL_X448MLKEM768: - #endif - break; - #endif + #endif /* HAVE_CURVE448 */ + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + break; + #endif /* WOLFSSL_NO_ML_KEM_768 */ #ifndef WOLFSSL_NO_ML_KEM_1024 + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE case WOLFSSL_ML_KEM_1024: - case WOLFSSL_SECP521R1MLKEM1024: + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_PQC_HYBRIDS case WOLFSSL_SECP384R1MLKEM1024: + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + case WOLFSSL_SECP521R1MLKEM1024: + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ break; #endif -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS + #if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \ + defined (WOLFSSL_EXTRA_PQC_HYBRIDS) case WOLFSSL_P256_ML_KEM_512_OLD: case WOLFSSL_P384_ML_KEM_768_OLD: case WOLFSSL_P521_ML_KEM_1024_OLD: break; -#endif + #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS && WOLFSSL_EXTRA_PQC_HYBRIDS */ #elif defined(HAVE_LIBOQS) case WOLFSSL_ML_KEM_512: case WOLFSSL_ML_KEM_768: @@ -5914,7 +5932,8 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) heap); if (ret != 0) return ret; -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS + #if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \ + defined (WOLFSSL_EXTRA_PQC_HYBRIDS) if (name == WOLFSSL_SECP256R1MLKEM512) { ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data, WOLFSSL_P256_ML_KEM_512_OLD, heap); @@ -5930,7 +5949,7 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) if (ret != 0) { return ret; } -#endif + #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS && WOLFSSL_EXTRA_PQC_HYBRIDS */ } return WOLFSSL_SUCCESS; @@ -8292,26 +8311,22 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) word16 curveId = (word16) ECC_CURVE_INVALID; ecc_key* eccKey = (ecc_key*)kse->key; - /* TODO: [TLS13] Get key sizes using wc_ecc_get_curve_size_from_id. */ /* Translate named group to a curve id. */ switch (kse->group) { #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP256R1: curveId = ECC_SECP256R1; - keySize = 32; break; #endif /* !NO_ECC_SECP */ #ifdef WOLFSSL_SM2 case WOLFSSL_ECC_SM2P256V1: curveId = ECC_SM2P256V1; - keySize = 32; break; #endif /* !WOLFSSL_SM2 */ #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP256R1TLS13: curveId = ECC_BRAINPOOLP256R1; - keySize = 32; break; #endif /* HAVE_ECC_BRAINPOOL */ #endif @@ -8319,13 +8334,11 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP384R1: curveId = ECC_SECP384R1; - keySize = 48; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP384R1TLS13: curveId = ECC_BRAINPOOLP384R1; - keySize = 48; break; #endif /* HAVE_ECC_BRAINPOOL */ #endif @@ -8333,7 +8346,6 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) #ifdef HAVE_ECC_BRAINPOOL case WOLFSSL_ECC_BRAINPOOLP512R1TLS13: curveId = ECC_BRAINPOOLP512R1; - keySize = 64; break; #endif /* HAVE_ECC_BRAINPOOL */ #endif @@ -8341,7 +8353,6 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP521R1: curveId = ECC_SECP521R1; - keySize = 66; break; #endif /* !NO_ECC_SECP */ #endif @@ -8350,6 +8361,15 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) return BAD_FUNC_ARG; } + { + int size = wc_ecc_get_curve_size_from_id(curveId); + if (size < 0) { + WOLFSSL_ERROR_VERBOSE(size); + return size; + } + keySize = (word32)size; + } + if (kse->key == NULL) { /* Allocate an ECC key to hold private key. */ kse->key = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_ECC); @@ -8543,6 +8563,11 @@ static int mlkem_id2type(int id, int *type) } #endif +#if defined(WOLFSSL_NO_ML_KEM_768) && defined(WOLFSSL_NO_ML_KEM_1024) && \ + defined(WOLFSSL_PQC_HYBRIDS) + #error "PQC hybrid combinations require either ML-KEM 768 or ML-KEM 1024" +#endif + /* Structures and objects needed for hybrid key exchanges using both classic * ECDHE and PQC KEM key material. */ typedef struct PqcHybridMapping { @@ -8554,23 +8579,33 @@ typedef struct PqcHybridMapping { static const PqcHybridMapping pqc_hybrid_mapping[] = { #ifndef WOLFSSL_NO_ML_KEM +#ifdef WOLFSSL_PQC_HYBRIDS + {WOLFSSL_SECP256R1MLKEM768, WOLFSSL_ECC_SECP256R1, WOLFSSL_ML_KEM_768, 0}, + {WOLFSSL_SECP384R1MLKEM1024, WOLFSSL_ECC_SECP384R1, WOLFSSL_ML_KEM_1024, 0}, +#endif /* WOLFSSL_PQC_HYBRIDS */ +#ifdef WOLFSSL_EXTRA_PQC_HYBRIDS {WOLFSSL_SECP256R1MLKEM512, WOLFSSL_ECC_SECP256R1, WOLFSSL_ML_KEM_512, 0}, {WOLFSSL_SECP384R1MLKEM768, WOLFSSL_ECC_SECP384R1, WOLFSSL_ML_KEM_768, 0}, - {WOLFSSL_SECP256R1MLKEM768, WOLFSSL_ECC_SECP256R1, WOLFSSL_ML_KEM_768, 0}, {WOLFSSL_SECP521R1MLKEM1024, WOLFSSL_ECC_SECP521R1, WOLFSSL_ML_KEM_1024, 0}, - {WOLFSSL_SECP384R1MLKEM1024, WOLFSSL_ECC_SECP384R1, WOLFSSL_ML_KEM_1024, 0}, #ifdef WOLFSSL_ML_KEM_USE_OLD_IDS {WOLFSSL_P256_ML_KEM_512_OLD, WOLFSSL_ECC_SECP256R1, WOLFSSL_ML_KEM_512, 0}, {WOLFSSL_P384_ML_KEM_768_OLD, WOLFSSL_ECC_SECP384R1, WOLFSSL_ML_KEM_768, 0}, {WOLFSSL_P521_ML_KEM_1024_OLD, WOLFSSL_ECC_SECP521R1, WOLFSSL_ML_KEM_1024, 0}, -#endif +#endif /* WOLFSSL_ML_KEM_USE_OLD_IDS */ +#endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ #ifdef HAVE_CURVE25519 - {WOLFSSL_X25519MLKEM512, WOLFSSL_ECC_X25519, WOLFSSL_ML_KEM_512, 1}, +#ifdef WOLFSSL_PQC_HYBRIDS {WOLFSSL_X25519MLKEM768, WOLFSSL_ECC_X25519, WOLFSSL_ML_KEM_768, 1}, -#endif +#endif /* WOLFSSL_PQC_HYBRIDS */ +#ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + {WOLFSSL_X25519MLKEM512, WOLFSSL_ECC_X25519, WOLFSSL_ML_KEM_512, 1}, +#endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ +#endif /* HAVE_CURVE25519 */ #ifdef HAVE_CURVE448 +#ifdef WOLFSSL_EXTRA_PQC_HYBRIDS {WOLFSSL_X448MLKEM768, WOLFSSL_ECC_X448, WOLFSSL_ML_KEM_768, 1}, -#endif +#endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ +#endif /* HAVE_CURVE448 */ #endif /* WOLFSSL_NO_ML_KEM */ #ifdef WOLFSSL_MLKEM_KYBER {WOLFSSL_P256_KYBER_LEVEL1, WOLFSSL_ECC_SECP256R1, WOLFSSL_KYBER_LEVEL1, 0}, @@ -8823,6 +8858,21 @@ static int TLSX_KeyShare_GenPqcHybridKeyClient(WOLFSSL *ssl, KeyShareEntry* kse) /* Generate ECC key share part */ if (ret == 0) { ecc_kse->group = ecc_group; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Check if the provided kse already contains an ECC key and the + * last error was WC_PENDING_E. In this case, we already tried to + * generate an ECC key. Hence, we have to restore it. */ + if (kse->key != NULL && kse->keyLen > 0 && + kse->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) { + ecc_kse->key = kse->key; + ecc_kse->keyLen = kse->keyLen; + ecc_kse->pubKeyLen = kse->pubKeyLen; + ecc_kse->lastRet = kse->lastRet; + kse->key = NULL; + } + #endif + #ifdef HAVE_CURVE25519 if (ecc_group == WOLFSSL_ECC_X25519) { ret = TLSX_KeyShare_GenX25519Key(ssl, ecc_kse); @@ -8838,7 +8888,17 @@ static int TLSX_KeyShare_GenPqcHybridKeyClient(WOLFSSL *ssl, KeyShareEntry* kse) { ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse); } - /* No error message, TLSX_KeyShare_Gen*Key will do it. */ + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { + /* Store the generated ECC key in the provided kse to later + * restore it.*/ + kse->key = ecc_kse->key; + kse->keyLen = ecc_kse->keyLen; + kse->pubKeyLen = ecc_kse->pubKeyLen; + ecc_kse->key = NULL; + } + #endif } /* Generate PQC key share part */ @@ -9835,7 +9895,6 @@ static int TLSX_KeyShare_ProcessPqcHybridClient(WOLFSSL* ssl, KeyShareEntry *ecc_kse = NULL; word32 ctSz = 0; word32 ssSzPqc = 0; - word32 ssSzEcc = 0; if (ssl->options.side == WOLFSSL_SERVER_END) { /* I am the server, the shared secret has already been generated and @@ -9970,6 +10029,9 @@ static int TLSX_KeyShare_ProcessPqcHybridClient(WOLFSSL* ssl, XMEMCPY(ecc_kse->ke, keyShareEntry->ke + offset, ecc_kse->keLen); } + #ifdef WOLFSSL_ASYNC_CRYPT + ecc_kse->lastRet = keyShareEntry->lastRet; + #endif } /* Process ECDH key share part. The generated shared secret is directly @@ -9979,36 +10041,46 @@ static int TLSX_KeyShare_ProcessPqcHybridClient(WOLFSSL* ssl, if (ret == 0) { int offset = 0; - /* Set the ECC size variable to the initial buffer size */ - ssSzEcc = ssl->arrays->preMasterSz; - if (pqc_first) offset = ssSzPqc; #ifdef HAVE_CURVE25519 if (ecc_group == WOLFSSL_ECC_X25519) { ret = TLSX_KeyShare_ProcessX25519_ex(ssl, ecc_kse, - ssl->arrays->preMasterSecret + offset, &ssSzEcc); + ssl->arrays->preMasterSecret + offset, + &ssl->arrays->preMasterSz); } else #endif #ifdef HAVE_CURVE448 if (ecc_group == WOLFSSL_ECC_X448) { ret = TLSX_KeyShare_ProcessX448_ex(ssl, ecc_kse, - ssl->arrays->preMasterSecret + offset, &ssSzEcc); + ssl->arrays->preMasterSecret + offset, + &ssl->arrays->preMasterSz); } else #endif { ret = TLSX_KeyShare_ProcessEcc_ex(ssl, ecc_kse, - ssl->arrays->preMasterSecret + offset, &ssSzEcc); + ssl->arrays->preMasterSecret + offset, + &ssl->arrays->preMasterSz); } + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { + keyShareEntry->lastRet = WC_PENDING_E; + /* Prevent freeing of the ECC and ML-KEM private keys */ + ecc_kse->key = NULL; + pqc_kse->privKey = NULL; + } + #endif } if (ret == 0) { keyShareEntry->key = ecc_kse->key; - if ((ret == 0) && ((ssSzEcc + ssSzPqc) > ENCRYPT_LEN)) { + if ((ret == 0) && + ((ssl->arrays->preMasterSz + ssSzPqc) > ENCRYPT_LEN)) { WOLFSSL_MSG("shared secret is too long."); ret = LENGTH_ERROR; } @@ -10017,7 +10089,7 @@ static int TLSX_KeyShare_ProcessPqcHybridClient(WOLFSSL* ssl, /* Process PQC KEM key share part. Depending on the pqc_first flag, the * KEM shared secret part goes before or after the ECDH part. */ if (ret == 0) { - int offset = ssSzEcc; + int offset = ssl->arrays->preMasterSz; if (pqc_first) offset = 0; @@ -10029,7 +10101,7 @@ static int TLSX_KeyShare_ProcessPqcHybridClient(WOLFSSL* ssl, if (ret == 0) { keyShareEntry->privKey = (byte*)pqc_kse->key; - ssl->arrays->preMasterSz = ssSzEcc + ssSzPqc; + ssl->arrays->preMasterSz += ssSzPqc; } else #ifdef WOLFSSL_ASYNC_CRYPT @@ -10146,10 +10218,12 @@ static int TLSX_KeyShareEntry_Parse(const WOLFSSL* ssl, const byte* input, *seenGroupsCnt = i + 1; } -#ifdef WOLFSSL_HAVE_MLKEM - if ((WOLFSSL_NAMED_GROUP_IS_PQC(group) || - WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(group)) && - ssl->options.side == WOLFSSL_SERVER_END) { +#if defined(WOLFSSL_HAVE_MLKEM) + if ((WOLFSSL_NAMED_GROUP_IS_PQC(group) + #if !defined(WOLFSSL_ASYNC_CRYPT) + || WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(group) + #endif + ) && ssl->options.side == WOLFSSL_SERVER_END) { /* When handling a key share containing a KEM public key on the server * end, we have to perform the encapsulation immediately in order to * send the resulting ciphertext back to the client in the ServerHello @@ -10157,7 +10231,12 @@ static int TLSX_KeyShareEntry_Parse(const WOLFSSL* ssl, const byte* input, * don't have to create a copy of it. * In case of a hybrid key exchange, the ECDH part is also performed * immediately (to not split the generation of the master secret). - * Hence, we also don't have to store this public key either. */ + * Hence, we also don't have to store this public key either. + * + * When WOLFSSL_ASYNC_CRYPT is enabled, this handling is not possible + * for the hybrid case, as the ECC part is performed asynchronously, + * requiring the key share data to be stored. + */ ke = (byte *)&input[offset]; } else #endif @@ -10552,7 +10631,7 @@ static int TLSX_KeyShare_HandlePqcKeyServer(WOLFSSL* ssl, return ret; } -static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, +int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, KeyShareEntry* keyShareEntry, byte* data, word16 len) { /* I am the server. The data parameter is the concatenation of the client's @@ -10572,7 +10651,6 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, word32 pubSz = 0; word32 ctSz = 0; word32 ssSzPqc = 0; - word32 ssSzEcc = 0; if (data == NULL) { WOLFSSL_MSG("No hybrid key share data from the client."); @@ -10596,14 +10674,17 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, ret = MEMORY_ERROR; } } + if (ret == 0) { + XMEMSET(ecc_kse, 0, sizeof(*ecc_kse)); + ecc_kse->group = ecc_group; + XMEMSET(pqc_kse, 0, sizeof(*pqc_kse)); + pqc_kse->group = pqc_group; + } /* The ciphertext and shared secret sizes of a KEM are fixed. Hence, we * decode these sizes to properly concatenate the KEM ciphertext with the * ECDH public key. */ if (ret == 0) { - XMEMSET(pqc_kse, 0, sizeof(*pqc_kse)); - pqc_kse->group = pqc_group; - /* Allocate a Kyber key to hold private key. */ pqc_kse->key = (KyberKey*) XMALLOC(sizeof(KyberKey), ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); @@ -10639,10 +10720,26 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, } } +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == 0) { + /* Check if the provided kse already contains ECC data and the + * last error was WC_PENDING_E. In this case, we already tried to + * process ECC kse data. Hence, we have to restore it. */ + if (keyShareEntry->key != NULL && keyShareEntry->keyLen > 0 && + keyShareEntry->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) { + ecc_kse->key = keyShareEntry->key; + ecc_kse->keyLen = keyShareEntry->keyLen; + ecc_kse->pubKey = keyShareEntry->pubKey; + ecc_kse->pubKeyLen = keyShareEntry->pubKeyLen; + ecc_kse->lastRet = keyShareEntry->lastRet; + keyShareEntry->key = NULL; + keyShareEntry->pubKey = NULL; + } + } +#endif + /* Generate the ECDH key share part to be sent to the client */ - if (ret == 0 && ecc_group != 0) { - XMEMSET(ecc_kse, 0, sizeof(*ecc_kse)); - ecc_kse->group = ecc_group; + if (ret == 0 && ecc_group != 0 && ecc_kse->pubKey == NULL) { #ifdef HAVE_CURVE25519 if (ecc_group == WOLFSSL_ECC_X25519) { ret = TLSX_KeyShare_GenX25519Key(ssl, ecc_kse); @@ -10658,7 +10755,22 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, { ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse); } - /* No error message, TLSX_KeyShare_GenKey will do it. */ + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { + /* Store the generated ECC key in the provided kse to later + * restore it.*/ + keyShareEntry->key = ecc_kse->key; + keyShareEntry->keyLen = ecc_kse->keyLen; + keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen; + keyShareEntry->lastRet = WC_PENDING_E; + ecc_kse->key = NULL; + } + else if (ret == 0 && + keyShareEntry->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) { + keyShareEntry->lastRet = 0; + ecc_kse->lastRet = 0; + } + #endif } if (ret == 0 && len != pubSz + ecc_kse->pubKeyLen) { @@ -10694,9 +10806,6 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, int pubOffset = 0; int ssOffset = 0; - /* Set the ECC size variable to the initial buffer size */ - ssSzEcc = ssl->arrays->preMasterSz; - if (pqc_first) { pubOffset = pubSz; ssOffset = ssSzPqc; @@ -10707,31 +10816,44 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, #ifdef HAVE_CURVE25519 if (ecc_group == WOLFSSL_ECC_X25519) { ret = TLSX_KeyShare_ProcessX25519_ex(ssl, ecc_kse, - ssl->arrays->preMasterSecret + ssOffset, &ssSzEcc); + ssl->arrays->preMasterSecret + ssOffset, + &ssl->arrays->preMasterSz); } else #endif #ifdef HAVE_CURVE448 if (ecc_group == WOLFSSL_ECC_X448) { ret = TLSX_KeyShare_ProcessX448_ex(ssl, ecc_kse, - ssl->arrays->preMasterSecret + ssOffset, &ssSzEcc); + ssl->arrays->preMasterSecret + ssOffset, + &ssl->arrays->preMasterSz); } else #endif { ret = TLSX_KeyShare_ProcessEcc_ex(ssl, ecc_kse, - ssl->arrays->preMasterSecret + ssOffset, &ssSzEcc); + ssl->arrays->preMasterSecret + ssOffset, + &ssl->arrays->preMasterSz); } } if (ret == 0) { - if (ssSzEcc != ecc_kse->keyLen) { + if (ssl->arrays->preMasterSz != ecc_kse->keyLen) { WOLFSSL_MSG("Data length mismatch."); ret = BAD_FUNC_ARG; } } + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_NO_ERR_TRACE(WC_PENDING_E)) { + keyShareEntry->lastRet = WC_PENDING_E; + keyShareEntry->key = ecc_kse->key; + keyShareEntry->pubKey = ecc_kse->pubKey; + keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen; + ecc_kse->key = NULL; + ecc_kse->pubKey = NULL; + } + #endif } - if (ret == 0 && ssSzEcc + ssSzPqc > ENCRYPT_LEN) { + if (ret == 0 && ssl->arrays->preMasterSz + ssSzPqc > ENCRYPT_LEN) { WOLFSSL_MSG("shared secret is too long."); ret = LENGTH_ERROR; } @@ -10740,7 +10862,7 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, * KEM shared secret part goes before or after the ECDH part. */ if (ret == 0) { int input_offset = ecc_kse->keLen; - int output_offset = ssSzEcc; + int output_offset = ssl->arrays->preMasterSz; if (pqc_first) { input_offset = 0; @@ -10755,7 +10877,7 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, if (ret == 0) { XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - ssl->arrays->preMasterSz = ssSzEcc + ssSzPqc; + ssl->arrays->preMasterSz += ssSzPqc; keyShareEntry->ke = NULL; keyShareEntry->keLen = 0; @@ -10832,7 +10954,8 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data, /* Try to find the key share entry with this group. */ keyShareEntry = (KeyShareEntry*)extension->data; while (keyShareEntry != NULL) { -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS + #if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \ + defined (WOLFSSL_EXTRA_PQC_HYBRIDS) if ((group == WOLFSSL_P256_ML_KEM_512_OLD && keyShareEntry->group == WOLFSSL_SECP256R1MLKEM512) || (group == WOLFSSL_P384_ML_KEM_768_OLD && @@ -10843,7 +10966,7 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data, break; } else -#endif + #endif /* WOLFSSL_ML_KEM_USE_OLD_IDS && WOLFSSL_EXTRA_PQC_HYBRIDS */ if (keyShareEntry->group == group) break; keyShareEntry = keyShareEntry->next; @@ -10876,7 +10999,9 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data, keyShareEntry->keLen = 0; } } - else if (ssl->options.side == WOLFSSL_SERVER_END && + else +#if !defined(WOLFSSL_ASYNC_CRYPT) + if (ssl->options.side == WOLFSSL_SERVER_END && WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(group)) { if (TLSX_IsGroupSupported(group)) { ret = TLSX_KeyShare_HandlePqcHybridKeyServer((WOLFSSL*)ssl, @@ -10892,6 +11017,7 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data, } } else +#endif #endif if (data != NULL) { XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); @@ -10939,21 +11065,39 @@ int TLSX_KeyShare_Empty(WOLFSSL* ssl) } static const word16 preferredGroup[] = { -#if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ - defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 256 - WOLFSSL_ECC_SECP256R1, -#if !defined(HAVE_FIPS) && defined(WOLFSSL_SM2) - WOLFSSL_ECC_SM2P256V1, -#endif -#if defined(HAVE_ECC_BRAINPOOL) - WOLFSSL_ECC_BRAINPOOLP256R1TLS13, + /* Sort by strength, but prefer non-experimental PQ/T hybrid groups */ +#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \ + defined(WOLFSSL_PQC_HYBRIDS) + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) && \ + ECC_MIN_KEY_SZ <= 256 + WOLFSSL_X25519MLKEM768, + #endif + #if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) && \ + (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 384 + WOLFSSL_SECP384R1MLKEM1024, + #endif + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \ + (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 256 + WOLFSSL_SECP256R1MLKEM768, + #endif +#endif /* WOLFSSL_HAVE_MLKEM && !WOLFSSL_NO_ML_KEM && WOLFSSL_PQC_HYBRIDS */ +#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \ + !defined(WOLFSSL_NO_ML_KEM_1024) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + WOLFSSL_ML_KEM_1024, #endif +#if defined(HAVE_ECC) && (!defined(NO_ECC521) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 521 + WOLFSSL_ECC_SECP521R1, #endif -#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - WOLFSSL_ECC_X25519, +#if defined(HAVE_ECC) && defined(HAVE_ECC512) && \ + defined(HAVE_ECC_BRAINPOOL) && ECC_MIN_KEY_SZ <= 512 + WOLFSSL_ECC_BRAINPOOLP512R1TLS13, #endif -#if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - WOLFSSL_ECC_X448, +#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \ + !defined(WOLFSSL_NO_ML_KEM_768) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + WOLFSSL_ML_KEM_768, #endif #if defined(HAVE_ECC) && (!defined(NO_ECC384) || \ defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 384 @@ -10962,81 +11106,65 @@ static const word16 preferredGroup[] = { WOLFSSL_ECC_BRAINPOOLP384R1TLS13, #endif #endif -#if defined(HAVE_ECC) && (!defined(NO_ECC521) || \ - defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 521 - WOLFSSL_ECC_SECP521R1, +#if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + WOLFSSL_ECC_X448, #endif -#if defined(HAVE_ECC) && defined(HAVE_ECC512) && \ - defined(HAVE_ECC_BRAINPOOL) && ECC_MIN_KEY_SZ <= 512 - WOLFSSL_ECC_BRAINPOOLP512R1TLS13, +#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \ + !defined(WOLFSSL_NO_ML_KEM_512) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + WOLFSSL_ML_KEM_512, #endif -#if defined(HAVE_FFDHE_2048) - WOLFSSL_FFDHE_2048, +#if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) && ECC_MIN_KEY_SZ <= 256 + WOLFSSL_ECC_SECP256R1, +#if !defined(HAVE_FIPS) && defined(WOLFSSL_SM2) + WOLFSSL_ECC_SM2P256V1, #endif -#if defined(HAVE_FFDHE_3072) - WOLFSSL_FFDHE_3072, +#if defined(HAVE_ECC_BRAINPOOL) + WOLFSSL_ECC_BRAINPOOLP256R1TLS13, #endif -#if defined(HAVE_FFDHE_4096) - WOLFSSL_FFDHE_4096, #endif -#if defined(HAVE_FFDHE_6144) - WOLFSSL_FFDHE_6144, +#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + WOLFSSL_ECC_X25519, #endif #if defined(HAVE_FFDHE_8192) WOLFSSL_FFDHE_8192, #endif +#if defined(HAVE_FFDHE_6144) + WOLFSSL_FFDHE_6144, +#endif +#if defined(HAVE_FFDHE_4096) + WOLFSSL_FFDHE_4096, +#endif +#if defined(HAVE_FFDHE_3072) + WOLFSSL_FFDHE_3072, +#endif +#if defined(HAVE_FFDHE_2048) + WOLFSSL_FFDHE_2048, +#endif #ifndef WOLFSSL_NO_ML_KEM -#ifdef WOLFSSL_WC_MLKEM - #ifndef WOLFSSL_NO_ML_KEM_512 - WOLFSSL_ML_KEM_512, - WOLFSSL_SECP256R1MLKEM512, - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - WOLFSSL_X25519MLKEM512, - #endif + #if !defined(WOLFSSL_NO_ML_KEM_1024) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) + WOLFSSL_SECP521R1MLKEM1024, #endif - #ifndef WOLFSSL_NO_ML_KEM_768 - WOLFSSL_ML_KEM_768, + #if !defined(WOLFSSL_NO_ML_KEM_768) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) WOLFSSL_SECP384R1MLKEM768, - WOLFSSL_SECP256R1MLKEM768, - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - WOLFSSL_X25519MLKEM768, - #endif #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 WOLFSSL_X448MLKEM768, + #endif /* HAVE_CURVE448 */ #endif - #endif - #ifndef WOLFSSL_NO_ML_KEM_1024 - WOLFSSL_ML_KEM_1024, - WOLFSSL_SECP521R1MLKEM1024, - WOLFSSL_SECP384R1MLKEM1024, - #endif -#elif defined(HAVE_LIBOQS) - /* These require a runtime call to TLSX_IsGroupSupported to use */ - WOLFSSL_ML_KEM_512, - WOLFSSL_ML_KEM_768, - WOLFSSL_ML_KEM_1024, + #if !defined(WOLFSSL_NO_ML_KEM_512) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) WOLFSSL_SECP256R1MLKEM512, - WOLFSSL_SECP384R1MLKEM768, - WOLFSSL_SECP256R1MLKEM768, - WOLFSSL_SECP521R1MLKEM1024, - WOLFSSL_SECP384R1MLKEM1024, #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 WOLFSSL_X25519MLKEM512, - WOLFSSL_X25519MLKEM768, - #endif - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - WOLFSSL_X448MLKEM768, + #endif /* HAVE_CURVE25519 */ #endif -#endif #endif /* !WOLFSSL_NO_ML_KEM */ #ifdef WOLFSSL_MLKEM_KYBER -#ifdef WOLFSSL_WC_MLKEM - #ifdef WOLFSSL_KYBER512 - WOLFSSL_KYBER_LEVEL1, - WOLFSSL_P256_KYBER_LEVEL1, - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - WOLFSSL_X25519_KYBER_LEVEL1, - #endif + #ifdef WOLFSSL_KYBER1024 + WOLFSSL_KYBER_LEVEL5, + WOLFSSL_P521_KYBER_LEVEL5, #endif #ifdef WOLFSSL_KYBER768 WOLFSSL_KYBER_LEVEL3, @@ -11049,27 +11177,13 @@ static const word16 preferredGroup[] = { WOLFSSL_X448_KYBER_LEVEL3, #endif #endif - #ifdef WOLFSSL_KYBER1024 - WOLFSSL_KYBER_LEVEL5, - WOLFSSL_P521_KYBER_LEVEL5, - #endif -#elif defined(HAVE_LIBOQS) - /* These require a runtime call to TLSX_IsGroupSupported to use */ + #ifdef WOLFSSL_KYBER512 WOLFSSL_KYBER_LEVEL1, - WOLFSSL_KYBER_LEVEL3, - WOLFSSL_KYBER_LEVEL5, WOLFSSL_P256_KYBER_LEVEL1, - WOLFSSL_P384_KYBER_LEVEL3, - WOLFSSL_P256_KYBER_LEVEL3, - WOLFSSL_P521_KYBER_LEVEL5, #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 WOLFSSL_X25519_KYBER_LEVEL1, - WOLFSSL_X25519_KYBER_LEVEL3, #endif - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - WOLFSSL_X448_KYBER_LEVEL3, #endif -#endif #endif /* WOLFSSL_MLKEM_KYBER */ WOLFSSL_NAMED_GROUP_INVALID }; @@ -11106,7 +11220,8 @@ static int TLSX_KeyShare_GroupRank(const WOLFSSL* ssl, int group) #endif for (i = 0; i < numGroups; i++) { -#ifdef WOLFSSL_ML_KEM_USE_OLD_IDS +#if defined(WOLFSSL_ML_KEM_USE_OLD_IDS) && \ + defined (WOLFSSL_EXTRA_PQC_HYBRIDS) if ((group == WOLFSSL_P256_ML_KEM_512_OLD && groups[i] == WOLFSSL_SECP256R1MLKEM512) || (group == WOLFSSL_P384_ML_KEM_768_OLD && @@ -11486,8 +11601,11 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) if (clientKSE->key == NULL) { #ifdef WOLFSSL_HAVE_MLKEM - if (WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group) || - WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(clientKSE->group)) { + if (WOLFSSL_NAMED_GROUP_IS_PQC(clientKSE->group) + #if !defined(WOLFSSL_ASYNC_CRYPT) + || WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(clientKSE->group) + #endif + ) { /* Going to need the public key (AKA ciphertext). */ serverKSE->pubKey = clientKSE->pubKey; clientKSE->pubKey = NULL; @@ -11495,6 +11613,13 @@ int TLSX_KeyShare_Setup(WOLFSSL *ssl, KeyShareEntry* clientKSE) clientKSE->pubKeyLen = 0; } else + #if defined(WOLFSSL_ASYNC_CRYPT) + if (WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(clientKSE->group)) { + ret = TLSX_KeyShare_HandlePqcHybridKeyServer(ssl, serverKSE, + clientKSE->ke, clientKSE->keLen); + } + else + #endif #endif { ret = TLSX_KeyShare_GenKey(ssl, serverKSE); @@ -15012,144 +15137,204 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) } #endif /* WOLFSSL_TLS13 */ +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_NO_ML_KEM) && defined(WOLFSSL_PQC_HYBRIDS) + /* Prefer non-experimental PQ/T hybrid groups (only for TLS 1.3) */ + if (IsAtLeastTLSv1_3(ssl->version)) { + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) && \ + ECC_MIN_KEY_SZ <= 256 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519MLKEM768, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) && \ + (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 384 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM1024, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \ + (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 256 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM768, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + } +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_1024) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + if (IsAtLeastTLSv1_3(ssl->version)) { + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_1024, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + } +#endif + #if defined(HAVE_ECC) - /* list in order by strength, since not all servers choose by strength */ - #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521 - #ifndef NO_ECC_SECP + /* list in order by strength, since not all servers choose by strength */ + #if (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521 + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP521R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512 + #ifdef HAVE_ECC_BRAINPOOL + if (IsAtLeastTLSv1_3(ssl->version)) { + /* TLS 1.3 BrainpoolP512 curve */ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP512R1TLS13, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + + /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */ + if (ssl->options.downgrade && + (ssl->options.minDowngrade <= TLSv1_2_MINOR || + ssl->options.minDowngrade <= DTLSv1_2_MINOR)) { ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP521R1, ssl->heap); + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); if (ret != WOLFSSL_SUCCESS) return ret; - #endif + } + } + else { + /* TLS 1.2 only */ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + } #endif - #if (defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 512 - #ifdef HAVE_ECC_BRAINPOOL - if (IsAtLeastTLSv1_3(ssl->version)) { - /* TLS 1.3 BrainpoolP512 curve */ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP512R1TLS13, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - - /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */ - if (ssl->options.downgrade && - (ssl->options.minDowngrade <= TLSv1_2_MINOR || - ssl->options.minDowngrade <= DTLSv1_2_MINOR)) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - } - } - else { - /* TLS 1.2 only */ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - } - #endif + #endif +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_768) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + if (IsAtLeastTLSv1_3(ssl->version)) { + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_768, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + } +#endif + +#if defined(HAVE_ECC) + #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384 + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif - #if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384 - #ifndef NO_ECC_SECP + #ifdef HAVE_ECC_BRAINPOOL + if (IsAtLeastTLSv1_3(ssl->version)) { + /* TLS 1.3 BrainpoolP384 curve */ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP384R1TLS13, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + + /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */ + if (ssl->options.downgrade && + (ssl->options.minDowngrade <= TLSv1_2_MINOR || + ssl->options.minDowngrade <= DTLSv1_2_MINOR)) { ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP384R1, ssl->heap); + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_BRAINPOOL - if (IsAtLeastTLSv1_3(ssl->version)) { - /* TLS 1.3 BrainpoolP384 curve */ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP384R1TLS13, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - - /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */ - if (ssl->options.downgrade && - (ssl->options.minDowngrade <= TLSv1_2_MINOR || - ssl->options.minDowngrade <= DTLSv1_2_MINOR)) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - } - } - else { - /* TLS 1.2 only */ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - } - #endif + } + } + else { + /* TLS 1.2 only */ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + } #endif + #endif #endif /* HAVE_ECC */ - #ifndef HAVE_FIPS - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_X448, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif /* HAVE_FIPS */ +#ifndef HAVE_FIPS + #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X448, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif +#endif /* HAVE_FIPS */ + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_512) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + if (IsAtLeastTLSv1_3(ssl->version)) { + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_512, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + } +#endif #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP256R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP256K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_BRAINPOOL - if (IsAtLeastTLSv1_3(ssl->version)) { - /* TLS 1.3 BrainpoolP256 curve */ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP256R1TLS13, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - - /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */ - if (ssl->options.downgrade && - (ssl->options.minDowngrade <= TLSv1_2_MINOR || - ssl->options.minDowngrade <= DTLSv1_2_MINOR)) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - } - } - else { - /* TLS 1.2 only */ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - } - #endif - #ifdef WOLFSSL_SM2 + #if (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + if (IsAtLeastTLSv1_3(ssl->version)) { + /* TLS 1.3 BrainpoolP256 curve */ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP256R1TLS13, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + + /* If TLS 1.2 is allowed, also add the TLS 1.2 curve */ + if (ssl->options.downgrade && + (ssl->options.minDowngrade <= TLSv1_2_MINOR || + ssl->options.minDowngrade <= DTLSv1_2_MINOR)) { ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SM2P256V1, ssl->heap); + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); if (ret != WOLFSSL_SUCCESS) return ret; - #endif + } + } + else { + /* TLS 1.2 only */ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + } + #endif + #ifdef WOLFSSL_SM2 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SM2P256V1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif + #endif #endif /* HAVE_ECC */ - #ifndef HAVE_FIPS - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_X25519, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif /* HAVE_FIPS */ +#ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif +#endif /* HAVE_FIPS */ #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224 - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP224R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP224K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif + #if (defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224 + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif + #endif #ifndef HAVE_FIPS #if (defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 192 @@ -15185,220 +15370,149 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) #endif /* HAVE_ECC */ #ifndef NO_DH - /* Add FFDHE supported groups. */ - #ifdef HAVE_FFDHE_8192 - if (8192/8 >= ssl->options.minDhKeySz && - 8192/8 <= ssl->options.maxDhKeySz) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_8192, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - } - #endif - #ifdef HAVE_FFDHE_6144 - if (6144/8 >= ssl->options.minDhKeySz && - 6144/8 <= ssl->options.maxDhKeySz) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_6144, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - } - #endif - #ifdef HAVE_FFDHE_4096 - if (4096/8 >= ssl->options.minDhKeySz && - 4096/8 <= ssl->options.maxDhKeySz) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_4096, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - } - #endif - #ifdef HAVE_FFDHE_3072 - if (3072/8 >= ssl->options.minDhKeySz && - 3072/8 <= ssl->options.maxDhKeySz) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_3072, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - } - #endif - #ifdef HAVE_FFDHE_2048 - if (2048/8 >= ssl->options.minDhKeySz && - 2048/8 <= ssl->options.maxDhKeySz) { - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_2048, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - } - #endif -#endif - -#ifdef WOLFSSL_HAVE_MLKEM -#ifndef WOLFSSL_NO_ML_KEM -#ifdef WOLFSSL_WC_MLKEM -#ifndef WOLFSSL_NO_ML_KEM_512 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_512, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM512, - ssl->heap); - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519MLKEM512, - ssl->heap); + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_8192 + if (8192/8 >= ssl->options.minDhKeySz && + 8192/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } #endif -#endif -#ifndef WOLFSSL_NO_ML_KEM_768 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_768, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM768, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM768, - ssl->heap); - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519MLKEM768, - ssl->heap); + #ifdef HAVE_FFDHE_6144 + if (6144/8 >= ssl->options.minDhKeySz && + 6144/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } #endif - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448MLKEM768, - ssl->heap); + #ifdef HAVE_FFDHE_4096 + if (4096/8 >= ssl->options.minDhKeySz && + 4096/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_3072 + if (3072/8 >= ssl->options.minDhKeySz && + 3072/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_2048 + if (2048/8 >= ssl->options.minDhKeySz && + 2048/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } #endif #endif -#ifndef WOLFSSL_NO_ML_KEM_1024 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_1024, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_NO_ML_KEM) && defined(WOLFSSL_EXTRA_PQC_HYBRIDS) + if (IsAtLeastTLSv1_3(ssl->version)) { +#if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) && \ + (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 521 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP521R1MLKEM1024, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM1024, - ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; #endif -#elif defined(HAVE_LIBOQS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_512, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_768, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_1024, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM512, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) +#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) && \ + (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 384 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM768, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM768, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP521R1MLKEM1024, + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) && \ + ECC_MIN_KEY_SZ <= 448 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448MLKEM768, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM1024, + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_ECC) && \ + (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 256 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM512, ssl->heap); - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - if (ret == WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) && \ + ECC_MIN_KEY_SZ <= 256 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519MLKEM512, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519MLKEM768, - ssl->heap); - #endif - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448MLKEM768, - ssl->heap); - #endif -#endif /* HAVE_LIBOQS */ -#endif /* !WOLFSSL_NO_ML_KEM */ -#ifdef WOLFSSL_MLKEM_KYBER -#ifdef WOLFSSL_WC_MLKEM -#ifdef WOLFSSL_KYBER512 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL1, + if (ret != WOLFSSL_SUCCESS) return ret; +#endif + } +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_HAVE_MLKEM) && \ + defined(WOLFSSL_MLKEM_KYBER) + if (IsAtLeastTLSv1_3(ssl->version)) { +#ifdef WOLFSSL_KYBER1024 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5, ssl->heap); - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL1, + if (ret != WOLFSSL_SUCCESS) return ret; +#if defined(HAVE_ECC) && (defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 521 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5, ssl->heap); - #endif + if (ret != WOLFSSL_SUCCESS) return ret; +#endif #endif #ifdef WOLFSSL_KYBER768 - if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL3, ssl->heap); - if (ret == WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; +#if defined(HAVE_ECC) && (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 384 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL3, ssl->heap); - if (ret == WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#if defined(HAVE_ECC) && (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 256 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL3, ssl->heap); - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - if (ret == WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL3, ssl->heap); - #endif - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - if (ret == WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448_KYBER_LEVEL3, ssl->heap); - #endif + if (ret != WOLFSSL_SUCCESS) return ret; #endif -#ifdef WOLFSSL_KYBER1024 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5, - ssl->heap); #endif -#elif defined(HAVE_LIBOQS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL3, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5, +#ifdef WOLFSSL_KYBER512 + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap); - if (ret == WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; +#if defined(HAVE_ECC) && (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 256 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL1, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P384_KYBER_LEVEL3, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL3, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5, - ssl->heap); - #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 - if (ret == WOLFSSL_SUCCESS) + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL1, ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X25519_KYBER_LEVEL3, - ssl->heap); - #endif - #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448_KYBER_LEVEL3, - ssl->heap); - #endif -#endif /* HAVE_LIBOQS */ -#endif /* WOLFSSL_MLKEM_KYBER */ -#endif /* WOLFSSL_HAVE_MLKEM */ + if (ret != WOLFSSL_SUCCESS) return ret; +#endif +#endif + } +#endif (void)ssl; (void)extensions; diff --git a/src/tls13.c b/src/tls13.c index 27d1ec0c3fa..c01604c1030 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -7371,7 +7371,16 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, KeyShareEntry* serverKSE = (KeyShareEntry*)extension->data; if (serverKSE != NULL && serverKSE->lastRet == WC_NO_ERR_TRACE(WC_PENDING_E)) { - ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + #if defined(WOLFSSL_HAVE_MLKEM) + if (WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(serverKSE->group)) { + ret = TLSX_KeyShare_HandlePqcHybridKeyServer(ssl, serverKSE, + serverKSE->ke, serverKSE->keLen); + } + else + #endif + { + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + } if (ret != 0) goto exit_dch; } @@ -14038,6 +14047,12 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) (void)ret; (void)group; #else + /* Check if the group is supported. */ + if (!TLSX_IsGroupSupported(group)) { + WOLFSSL_MSG("Group not supported."); + return BAD_FUNC_ARG; + } + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL, &ssl->extensions); if (ret != 0) return ret; diff --git a/tests/api.c b/tests/api.c index fd16b4d5b22..5add85836a3 100644 --- a/tests/api.c +++ b/tests/api.c @@ -30437,6 +30437,10 @@ static int test_dtls13_bad_epoch_ch(void) WOLFSSL *ssl_s = NULL; struct test_memio_ctx test_ctx; const int EPOCH_OFF = 3; + int groups[] = { + WOLFSSL_ECC_SECP256R1, + WOLFSSL_ECC_SECP384R1, + }; XMEMSET(&test_ctx, 0, sizeof(test_ctx)); ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, @@ -30446,6 +30450,9 @@ static int test_dtls13_bad_epoch_ch(void) * with just one message */ ExpectIntEQ(wolfSSL_disable_hrr_cookie(ssl_s), WOLFSSL_SUCCESS); + /* Set client groups to traditional only to avoid CH fragmentation */ + ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 2), WOLFSSL_SUCCESS); + ExpectIntNE(wolfSSL_connect(ssl_c), WOLFSSL_SUCCESS); ExpectIntEQ(wolfSSL_get_error(ssl_c, WC_NO_ERR_TRACE(WOLFSSL_FATAL_ERROR)), WOLFSSL_ERROR_WANT_READ); @@ -31060,6 +31067,10 @@ static int test_TLSX_CA_NAMES_bad_extension(void) 0x0d, 0x00, 0x00, 0x11, 0x00, 0x00, 0x0d, 0x00, 0x2f, 0x00, 0x06, 0x00, 0x04, 0x00, 0x03, 0x30, 0x00, 0x13, 0x94, 0x00, 0x06, 0x00, 0x04, 0x02 }; + int groups[2] = { + WOLFSSL_ECC_SECP256R1, + WOLFSSL_ECC_SECP521R1, + }; int i = 0; for (i = 0; i < 2; i++) { @@ -31082,6 +31093,9 @@ static int test_TLSX_CA_NAMES_bad_extension(void) break; } + /* Ensure the correct groups are used for the test */ + ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 2), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_connect(ssl_c), -1); #ifndef WOLFSSL_DISABLE_EARLY_SANITY_CHECKS ExpectIntEQ(wolfSSL_get_error(ssl_c, -1), WC_NO_ERR_TRACE(EXT_MISSING)); @@ -32035,7 +32049,7 @@ static int test_dtls13_frag_ch_pq(void) int group = WOLFSSL_KYBER_LEVEL1; const char *group_name = "KYBER_LEVEL1"; #endif -#else +#elif !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) #if !defined(WOLFSSL_NO_ML_KEM_1024) int group = WOLFSSL_ML_KEM_1024; const char *group_name = "ML_KEM_1024"; @@ -32046,6 +32060,17 @@ static int test_dtls13_frag_ch_pq(void) int group = WOLFSSL_ML_KEM_512; const char *group_name = "ML_KEM_512"; #endif +#elif defined(WOLFSSL_PQC_HYBRIDS) + #if defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) + int group = WOLFSSL_X25519MLKEM768; + const char *group_name = "X25519MLKEM768"; + #elif !defined(WOLFSSL_NO_ML_KEM_768) + int group = WOLFSSL_SECP256R1MLKEM768; + const char *group_name = "SecP256r1MLKEM768"; + #else + int group = WOLFSSL_SECP384R1MLKEM1024; + const char *group_name = "SecP384r1MLKEM1024"; + #endif #endif XMEMSET(&test_ctx, 0, sizeof(test_ctx)); diff --git a/tests/api/test_dtls.c b/tests/api/test_dtls.c index 39c14e8bd3d..bc277066dcf 100644 --- a/tests/api/test_dtls.c +++ b/tests/api/test_dtls.c @@ -1614,6 +1614,43 @@ int test_dtls_rtx_across_epoch_change(void) WOLFSSL_CTX *ctx_c = NULL, *ctx_s = NULL; WOLFSSL *ssl_c = NULL, *ssl_s = NULL; struct test_memio_ctx test_ctx; +#if defined(WOLFSSL_HAVE_MLKEM) + /* When ML-KEM is used in the key share, the hello messages are fragmented + *into two messages */ + int helloMsgCount = 2; + int groups[2] = { + #if defined(HAVE_CURVE25519) && defined(WOLFSSL_PQC_HYBRIDS) && \ + !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_768) + WOLFSSL_X25519MLKEM768, + #elif defined(HAVE_ECC) && defined(WOLFSSL_PQC_HYBRIDS) && \ + !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_768) + WOLFSSL_SECP256R1MLKEM768, + #elif defined(HAVE_ECC) && defined(WOLFSSL_PQC_HYBRIDS) && \ + !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_NO_ML_KEM_1024) + WOLFSSL_SECP384R1MLKEM1024, + #elif !defined(WOLFSSL_NO_ML_KEM_1024) && !defined(WOLFSSL_NO_ML_KEM) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + WOLFSSL_ML_KEM_1024, + #elif !defined(WOLFSSL_NO_ML_KEM_768) && !defined(WOLFSSL_NO_ML_KEM) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + WOLFSSL_ML_KEM_768, + #elif !defined(WOLFSSL_NO_ML_KEM_512) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + WOLFSSL_ML_KEM_512, + #elif defined(WOLFSSL_MLKEM_KYBER) && !defined(WOLFSSL_NO_KYBER1024) + WOLFSSL_KYBER_LEVEL5, + #elif defined(WOLFSSL_MLKEM_KYBER) && !defined(WOLFSSL_NO_KYBER768) + WOLFSSL_KYBER_LEVEL3, + #elif defined(WOLFSSL_MLKEM_KYBER) && !defined(WOLFSSL_NO_KYBER512) + WOLFSSL_KYBER_LEVEL1, + #endif + WOLFSSL_ECC_SECP256R1, + }; +#else + /* When ECC is used in the key share, the hello messages are not + * fragmented */ + int helloMsgCount = 1; +#endif XMEMSET(&test_ctx, 0, sizeof(test_ctx)); @@ -1622,6 +1659,11 @@ int test_dtls_rtx_across_epoch_change(void) wolfDTLSv1_3_client_method, wolfDTLSv1_3_server_method), 0); +#if defined(WOLFSSL_HAVE_MLKEM) + ExpectIntEQ(wolfSSL_set_groups(ssl_c, groups, 2), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_set_groups(ssl_s, groups, 2), WOLFSSL_SUCCESS); +#endif + /* CH0 */ wolfSSL_SetLoggingPrefix("client:"); ExpectIntEQ(wolfSSL_connect(ssl_c), -1); @@ -1646,7 +1688,7 @@ int test_dtls_rtx_across_epoch_change(void) ExpectIntGE(test_ctx.c_msg_count, 2); /* drop everything but the SH */ - while (test_ctx.c_msg_count > 1 && EXPECT_SUCCESS()) { + while (test_ctx.c_msg_count > helloMsgCount && EXPECT_SUCCESS()) { ExpectIntEQ(test_memio_drop_message(&test_ctx, 1, test_ctx.c_msg_count - 1), 0); } diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index 6e5b1930e5d..4650fa0946d 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -102,7 +102,7 @@ int test_tls13_apis(void) #else WOLFSSL_KYBER_LEVEL5 #endif -#else +#elif !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) #ifndef WOLFSSL_NO_ML_KEM_512 WOLFSSL_ML_KEM_512 #elif !defined(WOLFSSL_NO_ML_KEM_768) @@ -110,6 +110,12 @@ int test_tls13_apis(void) #else WOLFSSL_ML_KEM_1024 #endif +#else + #ifndef WOLFSSL_NO_ML_KEM_768 + WOLFSSL_SECP256R1MLKEM768 + #else + WOLFSSL_ECC_SECP256R1 + #endif #endif #else WOLFSSL_ECC_SECP256R1 @@ -153,12 +159,18 @@ int test_tls13_apis(void) ":P256_KYBER_LEVEL5" #endif #else - #ifndef WOLFSSL_NO_ML_KEM_512 + #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(WOLFSSL_EXTRA_PQC_HYBRIDS) ":SecP256r1MLKEM512" - #elif !defined(WOLFSSL_NO_ML_KEM_768) - ":SecP384r1MLKEM768" - #elif !defined(WOLFSSL_NO_ML_KEM_1024) - ":SecP521r1MLKEM1024" + #elif !defined(WOLFSSL_NO_ML_KEM_768) && defined(WOLFSSL_PQC_HYBRIDS) + ":SecP256r1MLKEM768" + #elif !defined(WOLFSSL_NO_ML_KEM_1024) && defined(WOLFSSL_PQC_HYBRIDS) + ":SecP384r1MLKEM1024" + #elif !defined(WOLFSSL_NO_ML_KEM_1024) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + ":ML_KEM_1024" + #elif !defined(WOLFSSL_NO_ML_KEM_768) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + ":ML_KEM_768" #endif #endif #endif @@ -176,8 +188,8 @@ int test_tls13_apis(void) #elif !defined(WOLFSSL_NO_KYBER1024) ":KYBER_LEVEL5" #endif -#else - #ifndef WOLFSSL_NO_ML_KEM_512 +#elif !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + #if !defined(WOLFSSL_NO_ML_KEM_512) ":ML_KEM_512" #elif !defined(WOLFSSL_NO_ML_KEM_768) ":ML_KEM_768" @@ -191,7 +203,11 @@ int test_tls13_apis(void) #if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MALLOC) && \ !defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \ !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \ - !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) + !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \ + defined(HAVE_SUPPORTED_CURVES) && \ + (!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \ + (defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \ + (defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768))) int mlkemLevel; #endif @@ -354,8 +370,12 @@ int test_tls13_apis(void) #if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_MALLOC) && \ !defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \ !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \ - !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) + !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \ + (!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \ + (defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \ + (defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768))) #ifndef WOLFSSL_NO_ML_KEM +#ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE #ifndef WOLFSSL_NO_ML_KEM_768 mlkemLevel = WOLFSSL_ML_KEM_768; #elif !defined(WOLFSSL_NO_ML_KEM_1024) @@ -364,6 +384,13 @@ int test_tls13_apis(void) mlkemLevel = WOLFSSL_ML_KEM_512; #endif #else +#if defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) + mlkemLevel = WOLFSSL_X25519MLKEM768; +#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768) + mlkemLevel = WOLFSSL_SECP256R1MLKEM768; +#endif +#endif +#else #ifndef WOLFSSL_NO_KYBER768 mlkemLevel = WOLFSSL_KYBER_LEVEL3; #elif !defined(WOLFSSL_NO_KYBER1024) @@ -1933,27 +1960,34 @@ int test_tls13_rpk_handshake(void) #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \ defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \ !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \ - !defined(WOLFSSL_MLKEM_NO_MAKE_KEY) + !defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \ + (!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \ + (defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \ + (defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768))) static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx) { -#ifndef WOLFSSL_NO_ML_KEM_1024 #ifdef WOLFSSL_MLKEM_KYBER + #if !defined(WOLFSSL_NO_KYBER1024) int group = WOLFSSL_KYBER_LEVEL5; -#else - int group = WOLFSSL_ML_KEM_1024; -#endif /* WOLFSSL_MLKEM_KYBER */ -#elif !defined(WOLFSSL_NO_ML_KEM_768) -#ifdef WOLFSSL_MLKEM_KYBER + #elif !defined(WOLFSSL_NO_KYBER768) int group = WOLFSSL_KYBER_LEVEL3; -#else - int group = WOLFSSL_ML_KEM_768; -#endif /* WOLFSSL_MLKEM_KYBER */ -#else -#ifdef WOLFSSL_MLKEM_KYBER + #else int group = WOLFSSL_KYBER_LEVEL1; -#else + #endif +#elif !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + #if !defined(WOLFSSL_NO_ML_KEM_1024) + int group = WOLFSSL_ML_KEM_1024; + #elif !defined(WOLFSSL_NO_ML_KEM_768) + int group = WOLFSSL_ML_KEM_768; + #else int group = WOLFSSL_ML_KEM_512; -#endif /* WOLFSSL_MLKEM_KYBER */ + #endif +#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768) && \ + defined(WOLFSSL_PQC_HYBRIDS) + int group = WOLFSSL_SECP256R1MLKEM768; +#elif defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) && \ + defined(WOLFSSL_PQC_HYBRIDS) + int group = WOLFSSL_X25519MLKEM768; #endif AssertIntEQ(wolfSSL_CTX_set_groups(ctx, &group, 1), WOLFSSL_SUCCESS); @@ -1961,24 +1995,28 @@ static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx) static void test_tls13_pq_groups_on_result(WOLFSSL* ssl) { -#ifndef WOLFSSL_NO_ML_KEM_1024 #ifdef WOLFSSL_MLKEM_KYBER + #if !defined(WOLFSSL_NO_KYBER1024) AssertStrEQ(wolfSSL_get_curve_name(ssl), "KYBER_LEVEL5"); -#else - AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_1024"); -#endif /* WOLFSSL_MLKEM_KYBER */ -#elif !defined(WOLFSSL_NO_ML_KEM_768) -#ifdef WOLFSSL_MLKEM_KYBER + #elif !defined(WOLFSSL_NO_KYBER768) AssertStrEQ(wolfSSL_get_curve_name(ssl), "KYBER_LEVEL3"); -#else - AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_768"); -#endif /* WOLFSSL_MLKEM_KYBER */ -#else -#ifdef WOLFSSL_MLKEM_KYBER + #else AssertStrEQ(wolfSSL_get_curve_name(ssl), "KYBER_LEVEL1"); -#else + #endif +#elif !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + #if !defined(WOLFSSL_NO_ML_KEM_1024) + AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_1024"); + #elif !defined(WOLFSSL_NO_ML_KEM_768) + AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_768"); + #else AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_512"); -#endif /* WOLFSSL_MLKEM_KYBER */ + #endif +#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768) && \ + defined(WOLFSSL_PQC_HYBRIDS) + AssertStrEQ(wolfSSL_get_curve_name(ssl), "SecP256r1MLKEM768"); +#elif defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) && \ + defined(WOLFSSL_PQC_HYBRIDS) + AssertStrEQ(wolfSSL_get_curve_name(ssl), "X25519MLKEM768"); #endif } #endif @@ -1989,7 +2027,10 @@ int test_tls13_pq_groups(void) #if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_TLS13) && \ defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) && \ !defined(WOLFSSL_MLKEM_NO_DECAPSULATE) && \ - !defined(WOLFSSL_MLKEM_NO_MAKE_KEY) + !defined(WOLFSSL_MLKEM_NO_MAKE_KEY) && \ + (!defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) || \ + (defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768)) || \ + (defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768))) callback_functions func_cb_client; callback_functions func_cb_server; @@ -2174,6 +2215,25 @@ int test_tls13_early_data(void) ExpectIntEQ(test_memio_setup(&test_ctx, &ctx_c, &ctx_s, &ssl_c, &ssl_s, params[i].client_meth, params[i].server_meth), 0); + if (params[i].isUdp) { + /* Early data is incompatible with HRR usage. Hence, we have to make + * sure a group is negotiated that does not cause a fragemented CH. + */ + int group[1] = { + #ifdef HAVE_ECC + WOLFSSL_ECC_SECP256R1, + #elif defined(HAVE_CURVE25519) + WOLFSSL_ECC_X25519, + #elif defined(HAVE_CURVE448) + WOLFSSL_ECC_X448, + #elif defined(HAVE_FFDHE_2048) + WOLFSSL_FFDHE_2048, + #endif + }; + ExpectIntEQ(wolfSSL_set_groups(ssl_c, group, 1), WOLFSSL_SUCCESS); + ExpectIntEQ(wolfSSL_set_groups(ssl_s, group, 1), WOLFSSL_SUCCESS); + } + /* Get a ticket so that we can do 0-RTT on the next connection */ ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); /* Make sure we read the ticket */ diff --git a/tests/include.am b/tests/include.am index 7b4e6f17e78..fc1359d3d52 100644 --- a/tests/include.am +++ b/tests/include.am @@ -33,12 +33,14 @@ EXTRA_DIST += tests/unit.h \ tests/test-tls13-down.conf \ tests/test-tls13-ecc.conf \ tests/test-tls13-psk.conf \ - tests/test-tls13-pq.conf \ + tests/test-tls13-pq-standalone.conf \ tests/test-tls13-pq-hybrid.conf \ - tests/test-dtls13-pq.conf \ - tests/test-dtls13-pq-frag.conf \ - tests/test-dtls13-pq-hybrid.conf \ + tests/test-tls13-pq-hybrid-extra.conf \ + tests/test-dtls13-pq-standalone.conf \ + tests/test-dtls13-pq-standalone-frag.conf \ tests/test-dtls13-pq-hybrid-frag.conf \ + tests/test-dtls13-pq-hybrid-extra.conf \ + tests/test-dtls13-pq-hybrid-extra-frag.conf \ tests/test-psk.conf \ tests/test-psk-no-id.conf \ tests/test-psk-no-id-sha2.conf \ diff --git a/tests/suites.c b/tests/suites.c index 3b461b77691..67bc85fb21f 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -196,6 +196,7 @@ static int IsKyberLevelAvailable(const char* line) if (begin != NULL && len > 0) { #ifndef WOLFSSL_NO_ML_KEM + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE #ifndef WOLFSSL_NO_ML_KEM_512 if (MATCH_PQC(begin, "ML_KEM_512", len)) { available = 1; @@ -211,7 +212,25 @@ static int IsKyberLevelAvailable(const char* line) available = 1; } #endif - + #endif /* WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_PQC_HYBRIDS + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) + if (MATCH_PQC(begin, "SecP256r1MLKEM768", len)) { + available = 1; + } + #endif + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) + if (MATCH_PQC(begin, "X25519MLKEM768", len)) { + available = 1; + } + #endif + #if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC) + if (MATCH_PQC(begin, "SecP384r1MLKEM1024", len)) { + available = 1; + } + #endif + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_ECC) if (MATCH_PQC(begin, "SecP256r1MLKEM512", len)) { available = 1; @@ -222,11 +241,13 @@ static int IsKyberLevelAvailable(const char* line) } #endif #endif - #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) - if (MATCH_PQC(begin, "SecP384r1MLKEM768", len)) { + #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) + if (MATCH_PQC(begin, "X25519MLKEM512", len)) { available = 1; } - if (MATCH_PQC(begin, "SecP256r1MLKEM768", len)) { + #endif + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) + if (MATCH_PQC(begin, "SecP384r1MLKEM768", len)) { available = 1; } #ifdef WOLFSSL_ML_KEM_USE_OLD_IDS @@ -235,8 +256,8 @@ static int IsKyberLevelAvailable(const char* line) } #endif #endif - #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) - if (MATCH_PQC(begin, "X25519MLKEM768", len)) { + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) + if (MATCH_PQC(begin, "X448MLKEM768", len)) { available = 1; } #endif @@ -244,26 +265,15 @@ static int IsKyberLevelAvailable(const char* line) if (MATCH_PQC(begin, "SecP521r1MLKEM1024", len)) { available = 1; } - if (MATCH_PQC(begin, "SecP384r1MLKEM1024", len)) { - available = 1; - } #ifdef WOLFSSL_ML_KEM_USE_OLD_IDS if (MATCH_PQC(begin, "P521_ML_KEM_1024_OLD", len)) { available = 1; } #endif #endif - #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) - if (MATCH_PQC(begin, "X25519MLKEM512", len)) { - available = 1; - } - #endif - #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) - if (MATCH_PQC(begin, "X448MLKEM768", len)) { - available = 1; - } - #endif + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ #endif /* !WOLFSSL_NO_ML_KEM */ + #ifdef WOLFSSL_MLKEM_KYBER #ifndef WOLFSSL_NO_KYBER512 if (MATCH_PQC(begin, "KYBER_LEVEL1", len)) { @@ -1118,8 +1128,9 @@ int SuiteTest(int argc, char** argv) } #endif #ifdef HAVE_PQC - /* add TLSv13 pq tests */ - XSTRLCPY(argv0[1], "tests/test-tls13-pq.conf", sizeof(argv0[1])); + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE + /* add TLSv13 pq standalone tests */ + XSTRLCPY(argv0[1], "tests/test-tls13-pq-standalone.conf", sizeof(argv0[1])); printf("starting TLSv13 post-quantum groups tests\n"); test_harness(&args); if (args.return_code != 0) { @@ -1127,6 +1138,8 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_PQC_HYBRIDS /* add TLSv13 pq hybrid tests */ XSTRLCPY(argv0[1], "tests/test-tls13-pq-hybrid.conf", sizeof(argv0[1])); printf("starting TLSv13 post-quantum groups tests\n"); @@ -1136,10 +1149,23 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + /* add TLSv13 pq extra hybrid tests */ + XSTRLCPY(argv0[1], "tests/test-tls13-pq-hybrid-extra.conf", sizeof(argv0[1])); + printf("starting TLSv13 post-quantum groups tests\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + #endif #endif #if defined(HAVE_PQC) && defined(WOLFSSL_DTLS13) - /* add DTLSv13 pq tests */ - XSTRLCPY(argv0[1], "tests/test-dtls13-pq.conf", sizeof(argv0[1])); + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE + /* add DTLSv13 pq standalone tests */ + XSTRLCPY(argv0[1], "tests/test-dtls13-pq-standalone.conf", sizeof(argv0[1])); printf("starting DTLSv13 post-quantum groups tests\n"); test_harness(&args); if (args.return_code != 0) { @@ -1147,8 +1173,10 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } - /* add DTLSv13 pq hybrid tests */ - XSTRLCPY(argv0[1], "tests/test-dtls13-pq-hybrid.conf", sizeof(argv0[1])); + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + /* add DTLSv13 pq extra hybrid tests */ + XSTRLCPY(argv0[1], "tests/test-dtls13-pq-hybrid-extra.conf", sizeof(argv0[1])); printf("starting DTLSv13 post-quantum 2 groups tests\n"); test_harness(&args); if (args.return_code != 0) { @@ -1156,9 +1184,11 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } + #endif #ifdef WOLFSSL_DTLS_CH_FRAG - /* add DTLSv13 pq frag tests */ - XSTRLCPY(argv0[1], "tests/test-dtls13-pq-frag.conf", sizeof(argv0[1])); + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE + /* add DTLSv13 pq standalone frag tests */ + XSTRLCPY(argv0[1], "tests/test-dtls13-pq-standalone-frag.conf", sizeof(argv0[1])); printf("starting DTLSv13 post-quantum groups tests with fragmentation\n"); test_harness(&args); if (args.return_code != 0) { @@ -1166,6 +1196,8 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + #ifdef WOLFSSL_PQC_HYBRIDS /* add DTLSv13 pq hybrid frag tests */ XSTRLCPY(argv0[1], "tests/test-dtls13-pq-hybrid-frag.conf", sizeof(argv0[1])); printf("starting DTLSv13 post-quantum 2 groups tests with fragmentation\n"); @@ -1175,6 +1207,18 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } + #endif /* WOLFSSL_PQC_HYBRIDS */ + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + /* add DTLSv13 pq extra hybrid frag tests */ + XSTRLCPY(argv0[1], "tests/test-dtls13-pq-hybrid-extra-frag.conf", sizeof(argv0[1])); + printf("starting DTLSv13 post-quantum 2 groups tests with fragmentation\n"); + test_harness(&args); + if (args.return_code != 0) { + printf("error from script %d\n", args.return_code); + args.return_code = EXIT_FAILURE; + goto exit; + } + #endif #endif #endif #endif diff --git a/tests/test-dtls13-pq-hybrid-extra-frag.conf b/tests/test-dtls13-pq-hybrid-extra-frag.conf new file mode 100644 index 00000000000..3048d53ded0 --- /dev/null +++ b/tests/test-dtls13-pq-hybrid-extra-frag.conf @@ -0,0 +1,95 @@ +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP384r1MLKEM768 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP384r1MLKEM768 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP521r1MLKEM1024 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP521r1MLKEM1024 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448MLKEM768 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448MLKEM768 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# server DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 + +# client DTLSv1.3 with post-quantum hybrid group +-u +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 diff --git a/tests/test-dtls13-pq-hybrid.conf b/tests/test-dtls13-pq-hybrid-extra.conf similarity index 100% rename from tests/test-dtls13-pq-hybrid.conf rename to tests/test-dtls13-pq-hybrid-extra.conf diff --git a/tests/test-dtls13-pq-hybrid-frag.conf b/tests/test-dtls13-pq-hybrid-frag.conf index 267468887ef..19aebb0e1a2 100644 --- a/tests/test-dtls13-pq-hybrid-frag.conf +++ b/tests/test-dtls13-pq-hybrid-frag.conf @@ -1,15 +1,3 @@ -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP384r1MLKEM768 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP384r1MLKEM768 - # server DTLSv1.3 with post-quantum hybrid group -u -v 4 @@ -22,18 +10,6 @@ -l TLS13-AES256-GCM-SHA384 --pqc SecP256r1MLKEM768 -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP521r1MLKEM1024 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP521r1MLKEM1024 - # server DTLSv1.3 with post-quantum hybrid group -u -v 4 @@ -57,75 +33,3 @@ -v 4 -l TLS13-AES256-GCM-SHA384 --pqc X25519MLKEM768 - -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448MLKEM768 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448MLKEM768 - -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL3 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL3 - -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 - -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519_KYBER_LEVEL3 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519_KYBER_LEVEL3 - -# server DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448_KYBER_LEVEL3 - -# client DTLSv1.3 with post-quantum hybrid group --u --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448_KYBER_LEVEL3 diff --git a/tests/test-dtls13-pq-frag.conf b/tests/test-dtls13-pq-standalone-frag.conf similarity index 100% rename from tests/test-dtls13-pq-frag.conf rename to tests/test-dtls13-pq-standalone-frag.conf diff --git a/tests/test-dtls13-pq.conf b/tests/test-dtls13-pq-standalone.conf similarity index 100% rename from tests/test-dtls13-pq.conf rename to tests/test-dtls13-pq-standalone.conf diff --git a/tests/test-tls13-pq-hybrid-extra.conf b/tests/test-tls13-pq-hybrid-extra.conf new file mode 100644 index 00000000000..2d0e601ce91 --- /dev/null +++ b/tests/test-tls13-pq-hybrid-extra.conf @@ -0,0 +1,119 @@ +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP256r1MLKEM512 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP256r1MLKEM512 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP384r1MLKEM768 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP384r1MLKEM768 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP521r1MLKEM1024 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc SecP521r1MLKEM1024 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519MLKEM512 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519MLKEM512 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448MLKEM768 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448MLKEM768 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL1 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL1 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P384_KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P256_KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc P521_KYBER_LEVEL5 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL1 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL1 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X25519_KYBER_LEVEL3 + +# server TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 + +# client TLSv1.3 with post-quantum hybrid group +-v 4 +-l TLS13-AES256-GCM-SHA384 +--pqc X448_KYBER_LEVEL3 diff --git a/tests/test-tls13-pq-hybrid.conf b/tests/test-tls13-pq-hybrid.conf index 76c8e57696f..0c4f4303a8f 100644 --- a/tests/test-tls13-pq-hybrid.conf +++ b/tests/test-tls13-pq-hybrid.conf @@ -1,23 +1,3 @@ -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP256r1MLKEM512 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP256r1MLKEM512 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP384r1MLKEM768 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP384r1MLKEM768 - # server TLSv1.3 with post-quantum hybrid group -v 4 -l TLS13-AES256-GCM-SHA384 @@ -28,16 +8,6 @@ -l TLS13-AES256-GCM-SHA384 --pqc SecP256r1MLKEM768 -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP521r1MLKEM1024 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc SecP521r1MLKEM1024 - # server TLSv1.3 with post-quantum hybrid group -v 4 -l TLS13-AES256-GCM-SHA384 @@ -48,16 +18,6 @@ -l TLS13-AES256-GCM-SHA384 --pqc SecP384r1MLKEM1024 -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519MLKEM512 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519MLKEM512 - # server TLSv1.3 with post-quantum hybrid group -v 4 -l TLS13-AES256-GCM-SHA384 @@ -67,83 +27,3 @@ -v 4 -l TLS13-AES256-GCM-SHA384 --pqc X25519MLKEM768 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448MLKEM768 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448MLKEM768 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL1 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL1 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P384_KYBER_LEVEL3 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL3 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P256_KYBER_LEVEL3 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc P521_KYBER_LEVEL5 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519_KYBER_LEVEL1 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519_KYBER_LEVEL1 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519_KYBER_LEVEL3 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X25519_KYBER_LEVEL3 - -# server TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448_KYBER_LEVEL3 - -# client TLSv1.3 with post-quantum hybrid group --v 4 --l TLS13-AES256-GCM-SHA384 ---pqc X448_KYBER_LEVEL3 diff --git a/tests/test-tls13-pq.conf b/tests/test-tls13-pq-standalone.conf similarity index 100% rename from tests/test-tls13-pq.conf rename to tests/test-tls13-pq-standalone.conf diff --git a/wolfssl/internal.h b/wolfssl/internal.h index e40ded4e7d8..4e91e95e186 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3425,6 +3425,7 @@ WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point, void* heap); +WOLFSSL_LOCAL int TLSX_IsGroupSupported(int namedGroup); #ifndef NO_WOLFSSL_SERVER WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(const WOLFSSL* ssl, byte first, @@ -3675,6 +3676,8 @@ WOLFSSL_LOCAL int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, byte msgType); WOLFSSL_LOCAL int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl, const byte* input, word16 length, TLSX** extensions); +WOLFSSL_LOCAL int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, + KeyShareEntry* keyShareEntry, byte* data, word16 len); #ifdef WOLFSSL_DUAL_ALG_CERTS WOLFSSL_LOCAL int TLSX_CKS_Parse(WOLFSSL* ssl, byte* input, word16 length, TLSX** extensions); diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index be31fa63abb..dd66a3d7e22 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -4558,6 +4558,13 @@ extern void uITRON4_free(void *p) ; #error "WOLFSSL_DTLS_CH_FRAG only works with DTLS 1.3" #endif +#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_NO_ML_KEM) && !defined(WOLFSSL_PQC_HYBRIDS) && \ + defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) && !defined(WOLFCRYPT_ONLY) +#error "Neither PQ/T hybrid combinations nor ML-KEM as standalone TLS key " \ + "exchange are enabled" +#endif + /* SRTP requires DTLS */ #if defined(WOLFSSL_SRTP) && !defined(WOLFSSL_DTLS) #error The SRTP extension requires DTLS diff --git a/zephyr/Kconfig b/zephyr/Kconfig index 0de97943cb9..ff05e74d23b 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -85,6 +85,11 @@ config WOLFSSL_PSK help Enable PSK support +config WOLFSSL_MLKEM + bool "wolfSSL PQC ML-KEM support" + help + Enable PQC ML-KEM support for Key Exchange + config WOLFSSL_MAX_FRAGMENT_LEN int default 3 diff --git a/zephyr/samples/wolfssl_tls_sock/prj.conf b/zephyr/samples/wolfssl_tls_sock/prj.conf index a51becba375..e48f28362ca 100644 --- a/zephyr/samples/wolfssl_tls_sock/prj.conf +++ b/zephyr/samples/wolfssl_tls_sock/prj.conf @@ -45,3 +45,4 @@ CONFIG_WOLFSSL_KEY_EXCHANGE_ALL_ENABLED=y CONFIG_WOLFSSL_CIPHER_ALL_ENABLED=y CONFIG_WOLFSSL_MAC_ALL_ENABLED=y CONFIG_WOLFSSL_HMAC_DRBG_ENABLED=y +CONFIG_WOLFSSL_MLKEM=y diff --git a/zephyr/samples/wolfssl_tls_thread/prj.conf b/zephyr/samples/wolfssl_tls_thread/prj.conf index 6fb19d3aa9f..b2b48c98c15 100644 --- a/zephyr/samples/wolfssl_tls_thread/prj.conf +++ b/zephyr/samples/wolfssl_tls_thread/prj.conf @@ -35,3 +35,4 @@ CONFIG_WOLFSSL_KEY_EXCHANGE_ALL_ENABLED=y CONFIG_WOLFSSL_CIPHER_ALL_ENABLED=y CONFIG_WOLFSSL_MAC_ALL_ENABLED=y CONFIG_WOLFSSL_HMAC_DRBG_ENABLED=y +CONFIG_WOLFSSL_MLKEM=y diff --git a/zephyr/user_settings.h b/zephyr/user_settings.h index 6f2606bdbf3..cc333bdaaa7 100644 --- a/zephyr/user_settings.h +++ b/zephyr/user_settings.h @@ -333,9 +333,21 @@ extern "C" { #define NO_MD4 #define NO_MD5 //#define NO_DES3 /* Necessary for pkcs12 tests */ -#define WOLFSSL_NO_SHAKE128 -#define WOLFSSL_NO_SHAKE256 +/* PQC ML-KEM */ +#if defined(CONFIG_WOLFSSL_MLKEM) + #define WOLFSSL_HAVE_MLKEM + #define WOLFSSL_WC_MLKEM + #define WOLFSSL_MLKEM_NO_LARGE_CODE + #define WOLFSSL_MLKEM_SMALL + #define WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM + #define WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM + #define WOLFSSL_SHAKE128 + #define WOLFSSL_SHAKE256 +#else + #define WOLFSSL_NO_SHAKE128 + #define WOLFSSL_NO_SHAKE256 +#endif /* ------------------------------------------------------------------------- */