From ee5d7a3d324f6b3fb601503dbb1e12536d30c02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Mon, 2 Feb 2026 17:02:59 +0100 Subject: [PATCH 1/2] Enable and use ML-KEM by default * Enable ML-KEM by default * Only allow three to-be-standardized hybrid PQ/T combinatations by default * Use X25519MLKEM768 as the default KeyShare in the ClientHello (if user does not override that) * Disable standalone ML-KEM in supported groups by default (enable with --enable-tls-mlkem-standalone) * Disable extra OQS-based hybrid PQ/T curves by default and gate behind --enable-experimental (enable with --enable-extra-pqc-hybrids) * Reorder the SupportedGroups extension to reflect the preferences * Reorder the preferredGroup array to also reflect the same preferences * Enable DTLS1.3 ClientHello fragmentation by default when both DTLS1.3 and ML-KEM are enabled * Fix memory leak in TLS server PQC handling in case of ECH * Ensure PQ/T hybrids are properly tested in unit tests --- .github/workflows/async.yml | 6 +- .github/workflows/cmake.yml | 6 +- .github/workflows/os-check.yml | 6 + .github/workflows/psk.yml | 6 +- .github/workflows/rust-wrapper.yml | 64 +- .github/workflows/zephyr.yml | 2 +- CMakeLists.txt | 155 ++-- cmake/options.h.in | 6 + configure.ac | 112 ++- examples/benchmark/tls_bench.c | 12 +- examples/client/client.c | 47 +- examples/server/server.c | 35 +- src/dtls.c | 15 + src/internal.c | 24 +- src/ssl.c | 80 +- src/tls.c | 802 +++++++++--------- src/tls13.c | 6 + tests/api.c | 10 + tests/api/test_dtls.c | 29 +- tests/api/test_tls13.c | 84 +- tests/include.am | 10 +- tests/suites.c | 123 ++- tests/test-dtls13-pq-hybrid-extra-frag.conf | 95 +++ ....conf => test-dtls13-pq-hybrid-extra.conf} | 0 tests/test-dtls13-pq-hybrid-frag.conf | 96 --- ...nf => test-dtls13-pq-standalone-frag.conf} | 0 ...pq.conf => test-dtls13-pq-standalone.conf} | 0 tests/test-tls13-pq-hybrid-extra.conf | 119 +++ tests/test-tls13-pq-hybrid.conf | 120 --- ...-pq.conf => test-tls13-pq-standalone.conf} | 0 wolfssl/internal.h | 1 + wolfssl/ssl.h | 11 +- wolfssl/wolfcrypt/settings.h | 13 +- zephyr/Kconfig | 5 + zephyr/samples/wolfssl_tls_sock/prj.conf | 1 + zephyr/samples/wolfssl_tls_thread/prj.conf | 1 + zephyr/user_settings.h | 16 +- 37 files changed, 1299 insertions(+), 819 deletions(-) create mode 100644 tests/test-dtls13-pq-hybrid-extra-frag.conf rename tests/{test-dtls13-pq-hybrid.conf => test-dtls13-pq-hybrid-extra.conf} (100%) rename tests/{test-dtls13-pq-frag.conf => test-dtls13-pq-standalone-frag.conf} (100%) rename tests/{test-dtls13-pq.conf => test-dtls13-pq-standalone.conf} (100%) create mode 100644 tests/test-tls13-pq-hybrid-extra.conf rename tests/{test-tls13-pq.conf => test-tls13-pq-standalone.conf} (100%) diff --git a/.github/workflows/async.yml b/.github/workflows/async.yml index 8a572c328f5..4ab1c41084c 100644 --- a/.github/workflows/async.yml +++ b/.github/workflows/async.yml @@ -18,8 +18,10 @@ jobs: matrix: config: [ # Add new configs here - '--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-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-ocsp CFLAGS="-DTEST_NONBLOCK_CERTS -pedantic -Wdeclaration-after-statement -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"', ] name: make check diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9639a7a6e91..55b50b53872 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -69,9 +69,9 @@ jobs: -DWOLFSSL_TICKET_NONCE_MALLOC:BOOL=yes -DWOLFSSL_TLS13:BOOL=yes -DWOLFSSL_TLSV12:BOOL=yes \ -DWOLFSSL_TLSX:BOOL=yes -DWOLFSSL_TPM:BOOL=yes -DWOLFSSL_CLU:BOOL=yes -DWOLFSSL_USER_SETTINGS:BOOL=no \ -DWOLFSSL_USER_SETTINGS_ASM:BOOL=no -DWOLFSSL_WOLFSSH:BOOL=ON -DWOLFSSL_X86_64_BUILD_ASM:BOOL=yes \ - -DWOLFSSL_MLKEM=1 -DWOLFSSL_LMS=1 -DWOLFSSL_LMSSHA256192=1 -DWOLFSSL_EXPERIMENTAL=1 \ - -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_MLKEM:BOOL=yes -DWOLFSSL_EXTRA_PQC_HYBRIDS:BOOL=yes -DWOLFSSL_LMS:BOOL=yes \ + -DWOLFSSL_LMSSHA256192:BOOL=yes -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 \ .. cmake --build . diff --git a/.github/workflows/os-check.yml b/.github/workflows/os-check.yml index 2e6c32d04f2..7eae06589b9 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/psk.yml b/.github/workflows/psk.yml index 5026c4bdfc0..097403c4673 100644 --- a/.github/workflows/psk.yml +++ b/.github/workflows/psk.yml @@ -18,9 +18,9 @@ jobs: matrix: config: [ # Add new configs here - '--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 C_EXTRA_FLAGS=-DWOLFSSL_STATIC_PSK --disable-rsa --disable-ecc --disable-dh --disable-mlkem', + '--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 218f7d8320a..6e86996020d 100644 --- a/.github/workflows/rust-wrapper.yml +++ b/.github/workflows/rust-wrapper.yml @@ -39,36 +39,36 @@ jobs: '', '--enable-all', '--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/CMakeLists.txt b/CMakeLists.txt index c915843737e..5af47f228d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -610,13 +610,67 @@ 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") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_WC_MLKEM") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHA3") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHAKE128") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHAKE256") + + set_wolfssl_definitions("WOLFSSL_HAVE_MLKEM" RESULT) + set_wolfssl_definitions("WOLFSSL_WC_MLKEM" RESULT) + set_wolfssl_definitions("WOLFSSL_SHA3" RESULT) + set_wolfssl_definitions("WOLFSSL_SHAKE128" RESULT) + 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)" "no" "yes;no") +if (WOLFSSL_DILITHIUM) + list(APPEND WOLFSSL_DEFINITIONS "-DHAVE_DILITHIUM") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_WC_DILITHIUM") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHA3") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHAKE128") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_SHAKE256") + + set_wolfssl_definitions("HAVE_DILITHIUM" RESULT) + set_wolfssl_definitions("WOLFSSL_WC_DILITHIUM" RESULT) + set_wolfssl_definitions("WOLFSSL_SHA3" RESULT) + set_wolfssl_definitions("WOLFSSL_SHAKE128" RESULT) + set_wolfssl_definitions("WOLFSSL_SHAKE256" RESULT) +endif() + # LMS add_option(WOLFSSL_LMS "Enable the PQ LMS Stateful Hash-based Signature Scheme (default: disabled)" @@ -626,11 +680,31 @@ add_option(WOLFSSL_LMSSHA256192 "Enable the LMS SHA_256_192 truncated variant (default: disabled)" "no" "yes;no") +if (WOLFSSL_LMS) + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_HAVE_LMS") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_WC_LMS") + + set_wolfssl_definitions("WOLFSSL_HAVE_LMS" RESULT) + set_wolfssl_definitions("WOLFSSL_WC_LMS" RESULT) + + if (WOLFSSL_LMSSHA256192) + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_LMS_SHA256_192") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_NO_LMS_SHA256_256") + + set_wolfssl_definitions("WOLFSSL_LMS_SHA256_192" RESULT) + set_wolfssl_definitions("WOLFSSL_NO_LMS_SHA256_256" RESULT) + endif() +endif() + # Experimental features 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") @@ -666,75 +740,14 @@ if (WOLFSSL_EXPERIMENTAL) message(STATUS "Looking for WOLFSSL_OQS - not found") endif() - # Checking for experimental feature: WOLFSSL_MLKEM - message(STATUS "Looking for WOLFSSL_MLKEM") - if (WOLFSSL_MLKEM) - set(WOLFSSL_FOUND_EXPERIMENTAL_FEATURE 1) - - message(STATUS "Automatically set related requirements for ML-KEM:") - add_definitions("-DWOLFSSL_HAVE_MLKEM") - add_definitions("-DWOLFSSL_WC_MLKEM") - add_definitions("-DWOLFSSL_SHA3") - add_definitions("-DWOLFSSL_SHAKE128") - add_definitions("-DWOLFSSL_SHAKE256") - - set_wolfssl_definitions("WOLFSSL_HAVE_MLKEM" RESULT) - set_wolfssl_definitions("WOLFSSL_WC_MLKEM" RESULT) - set_wolfssl_definitions("WOLFSSL_SHA3" RESULT) - set_wolfssl_definitions("WOLFSSL_SHAKE128" RESULT) - set_wolfssl_definitions("WOLFSSL_SHAKE256" RESULT) - message(STATUS "Looking for WOLFSSL_MLKEM - found") - else() - message(STATUS "Looking for WOLFSSL_MLKEM - not found") - endif() - - # Checking for experimental feature: WOLFSSL_LMS - message(STATUS "Looking for WOLFSSL_LMS") - if (WOLFSSL_LMS) - set(WOLFSSL_FOUND_EXPERIMENTAL_FEATURE 2) - - message(STATUS "Automatically set related requirements for LMS") - add_definitions("-DWOLFSSL_HAVE_LMS") - add_definitions("-DWOLFSSL_WC_LMS") - set_wolfssl_definitions("WOLFSSL_HAVE_LMS" RESULT) - set_wolfssl_definitions("WOLFSSL_WC_LMS" RESULT) - message(STATUS "Looking for WOLFSSL_LMS - found") - # Checking for experimental feature: WOLFSSL_LMSSHA256192 - if (WOLFSSL_LMSSHA256192) - message(STATUS "Automatically set related requirements for LMS SHA256-192") - add_definitions("-DWOLFSSL_LMS_SHA256_192") - add_definitions("-DWOLFSSL_NO_LMS_SHA256_256") - set_wolfssl_definitions("WOLFSSL_LMS_SHA256_192" RESULT) - set_wolfssl_definitions("WOLFSSL_NO_LMS_SHA256_256" RESULT) - message(STATUS "Looking for WOLFSSL_LMSSHA256192 - found") - else() - message(STATUS "Looking for WOLFSSL_LMSSHA256192 - not found") - endif() - else() - message(STATUS "Looking for WOLFSSL_LMS - not found") - endif() - - # Checking for experimental feature: Dilithium - message(STATUS "Looking for WOLFSSL_DILITHIUM") - if (WOLFSSL_DILITHIUM) + # 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 "Automatically set related requirements for Dilithium:") - add_definitions("-DHAVE_DILITHIUM") - add_definitions("-DWOLFSSL_WC_DILITHIUM") - add_definitions("-DWOLFSSL_SHA3") - add_definitions("-DWOLFSSL_SHAKE128") - add_definitions("-DWOLFSSL_SHAKE256") - - message(STATUS "Automatically set related requirements for Dilithium:") - set_wolfssl_definitions("HAVE_DILITHIUM" RESULT) - set_wolfssl_definitions("WOLFSSL_WC_DILITHIUM" RESULT) - set_wolfssl_definitions("WOLFSSL_SHA3" RESULT) - set_wolfssl_definitions("WOLFSSL_SHAKE128" RESULT) - set_wolfssl_definitions("WOLFSSL_SHAKE256" RESULT) - message(STATUS "Looking for WOLFSSL_DILITHIUM - found") + message(STATUS "Looking for WOLFSSL_EXTRA_PQC_HYBRIDS - found") + list(APPEND WOLFSSL_DEFINITIONS "-DWOLFSSL_EXTRA_PQC_HYBRIDS") else() - message(STATUS "Looking for WOLFSSL_DILITHIUM - not found") + message(STATUS "Looking for WOLFSSL_EXTRA_PQC_HYBRIDS - not found") endif() # Other experimental feature detection can be added here... @@ -759,12 +772,6 @@ else() if (WOLFSSL_OQS) message(FATAL_ERROR "Error: WOLFSSL_OQS requires WOLFSSL_EXPERIMENTAL at this time.") endif() - if(WOLFSSL_MLKEM) - message(FATAL_ERROR "Error: WOLFSSL_MLKEM requires WOLFSSL_EXPERIMENTAL at this time.") - endif() - if(WOLFSSL_DILITHIUM) - message(FATAL_ERROR "Error: WOLFSSL_DILITHIUM requires WOLFSSL_EXPERIMENTAL at this time.") - endif() endif() # LMS diff --git a/cmake/options.h.in b/cmake/options.h.in index 62e5ed57bc2..05bbb9fcc80 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 @@ -408,6 +410,10 @@ extern "C" { #cmakedefine WOLFSSL_WC_XMSS #undef WC_RSA_DIRECT #cmakedefine WC_RSA_DIRECT +#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 ed7a512a471..edbdcc2a4a6 100644 --- a/configure.ac +++ b/configure.ac @@ -1639,16 +1639,23 @@ AC_ARG_WITH([liboqs], # Used: # - SHA3, Shake128 and Shake256 AC_ARG_ENABLE([mlkem], - [AS_HELP_STRING([--enable-mlkem],[Enable MLKEM (default: disabled)])], + [AS_HELP_STRING([--enable-mlkem],[Enable MLKEM (default: enabled)])], [ ENABLED_MLKEM=$enableval ], - [ ENABLED_MLKEM=no ] + [ ENABLED_MLKEM=yes ] ) # note, inherits default from "mlkem" clause above. AC_ARG_ENABLE([kyber], - [AS_HELP_STRING([--enable-kyber],[Enable Kyber/MLKEM (default: disabled)])], + [AS_HELP_STRING([--enable-kyber],[Enable Kyber/MLKEM (default: enabled)])], [ 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 @@ -1772,8 +1779,55 @@ 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_MLKEM" = "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_MLKEM" = "no" + then + ENABLED_PQC_HYBRIDS=no + else + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_PQC_HYBRIDS" + fi +fi + +if test "$ENABLED_MLKEM" = "yes" && test "$ENABLED_TLS13" = "yes" && test "$ENABLED_PQC_HYBRIDS" = "no" && test "$ENABLED_MLKEM_STANDALONE" = "no" +then + AC_MSG_ERROR([Both hybrid PQ/T and standalone ML-KEM are disabled, so no PQC hybrid combinations will be available.]) +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_MLKEM" = "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 MLDSA (default: disabled)])], [ ENABLED_DILITHIUM=$enableval ], @@ -4445,6 +4499,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)])], @@ -4452,6 +4517,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)])], @@ -4459,6 +4535,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)])], @@ -5625,6 +5712,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)])], @@ -9693,6 +9789,11 @@ if test "$ENABLED_ASYNCCRYPT" = "yes" then AC_MSG_NOTICE([Enabling asynchronous support]) + if test "$ENABLED_PQC_HYBRIDS" = "yes" || test "$ENABLED_EXTRA_PQC_HYBRIDS" = "yes" + then + AC_MSG_ERROR([PQ/T hybrid combinations are incompatible with asynchronous crypto at the moment]) + fi + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ASYNC_CRYPT -DHAVE_WOLF_EVENT -DHAVE_WOLF_BIGINT -DWOLFSSL_NO_HASH_RAW" # If no async backend (hardware or software) has been explicitly enabled, @@ -11829,6 +11930,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 ede7d8fed76..7cc5b84ecd0 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 11b80d234e2..a9847dda6ff 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -422,61 +422,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; } @@ -553,6 +570,18 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, else { err_sys("unable to use post-quantum KEM"); } + + #ifdef WOLFSSL_DTLS13 + if (wolfSSL_dtls(ssl)) { + /* When the KeyShare is too large for an unfragmented + *ClientHello, DTLS sends an empty KeyShare extension to + * use the Hello Retry Request to enable fragmentation. + * In order to enforce our desired PQC algorithm in the + * second ClientHello, we need to set it as the only one + * allowed in the SupportedGroups extension. */ + setGroups = 1; + } + #endif /* WOLFSSL_DTLS13 */ } } #endif diff --git a/examples/server/server.c b/examples/server/server.c index c7c44409d83..f60edd891b1 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -709,61 +709,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; } diff --git a/src/dtls.c b/src/dtls.c index dff1ffab3a8..274649423cb 100644 --- a/src/dtls.c +++ b/src/dtls.c @@ -822,6 +822,21 @@ static int SendStatelessReplyDtls13(const WOLFSSL* ssl, WolfSSL_CH* ch) ret = TLSX_KeyShare_SetSupported(ssl, &parsedExts); if (ret != 0) goto dtls13_cleanup; + + #ifdef WOLFSSL_DTLS_CH_FRAG + { + /* Get the chosen group. If ret == 0 here, we are sure that the + * extension is present. */ + TLSX* ksExt = TLSX_Find(parsedExts, TLSX_KEY_SHARE); + KeyShareEntry* kse = (KeyShareEntry*)ksExt->data; + if (WOLFSSL_NAMED_GROUP_IS_PQC(kse->group) || + WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(kse->group)) { + /* Allow fragmentation of the second ClientHello due to the + * large PQC key share. */ + wolfSSL_dtls13_allow_ch_frag((WOLFSSL*)ssl, 1); + } + } + #endif } else { /* Need to remove the keyshare ext if we found a common group diff --git a/src/internal.c b/src/internal.c index 818f6e0d5df..848cd5d4b3f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2251,6 +2251,15 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side) WOLFSSL_MSG("DTLS Cookie Secret error"); return ret; } + #if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE) + if (IsAtLeastTLSv1_3(ssl->version)) { + ret = wolfSSL_send_hrr_cookie(ssl, NULL, 0); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("DTLS1.3 Cookie secret error"); + return ret; + } + } + #endif /* WOLFSSL_DTLS13 && WOLFSSL_SEND_HRR_COOKIE */ } #endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ @@ -35034,21 +35043,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: @@ -35063,6 +35079,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 bff77b2ec14..4e4451a8bbf 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2966,18 +2966,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 @@ -10586,49 +10592,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"; @@ -16808,22 +16824,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 843d16f461a..6f34a5ce3a7 100644 --- a/src/tls.c +++ b/src/tls.c @@ -4373,7 +4373,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 @@ -4485,35 +4485,52 @@ 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: + #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 - #endif + #endif /* HAVE_CURVE25519 */ + #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 - #endif + #endif /* HAVE_CURVE448 */ + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ + #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: @@ -5820,7 +5837,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); @@ -5836,7 +5854,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; @@ -8166,26 +8184,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 @@ -8193,13 +8207,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 @@ -8207,7 +8219,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 @@ -8215,7 +8226,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 @@ -8224,6 +8234,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); @@ -8395,6 +8414,12 @@ static int mlkem_id2type(int id, int *type) } #endif +#if defined(WOLFSSL_NO_ML_KEM_768) && defined(WOLFSSL_NO_ML_KEM_1024) && \ + !defined(WOLFSSL_EXTRA_PQC_HYBRIDS) + #error "Non-experimental 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 { @@ -8406,23 +8431,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}, @@ -8688,7 +8723,32 @@ static int TLSX_KeyShare_GenPqcHybridKeyClient(WOLFSSL *ssl, KeyShareEntry* kse) else #endif { + #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_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 + ret = TLSX_KeyShare_GenEccKey(ssl, ecc_kse); + + #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 } /* No error message, TLSX_KeyShare_Gen*Key will do it. */ } @@ -10051,7 +10111,7 @@ int TLSX_KeyShare_Parse_ClientHello(const WOLFSSL* ssl, offset += ret; } - if (ssl->hrr_keyshare_group != 0) { + if (ssl->hrr_keyshare_group != 0 && seenGroupsCnt > 0) { /* * https://datatracker.ietf.org/doc/html/rfc8446#section-4.2.8 * when sending the new ClientHello, the client MUST @@ -10311,6 +10371,7 @@ static int TLSX_KeyShare_HandlePqcKeyServer(WOLFSSL* ssl, keyShareEntry->ke = NULL; keyShareEntry->keLen = 0; + XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); keyShareEntry->pubKey = ciphertext; keyShareEntry->pubKeyLen = ctSz; ciphertext = NULL; @@ -10547,6 +10608,7 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl, XMEMCPY(ciphertext + ecc_kse->pubKeyLen, pqc_kse->pubKey, ctSz); } + XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); keyShareEntry->pubKey = ciphertext; keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen + ctSz; ciphertext = NULL; @@ -10596,7 +10658,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 && @@ -10607,7 +10670,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; @@ -10625,13 +10688,20 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data, #if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE) if (ssl->options.side == WOLFSSL_SERVER_END && WOLFSSL_NAMED_GROUP_IS_PQC(group)) { - ret = TLSX_KeyShare_HandlePqcKeyServer((WOLFSSL*)ssl, - keyShareEntry, - data, len, - ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz); - if (ret != 0) - return ret; + if (TLSX_IsGroupSupported(group)) { + ret = TLSX_KeyShare_HandlePqcKeyServer((WOLFSSL*)ssl, + keyShareEntry, + data, len, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz); + if (ret != 0) + return ret; + } + else { + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = NULL; + keyShareEntry->keLen = 0; + } } else if (ssl->options.side == WOLFSSL_SERVER_END && WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(group)) { @@ -10689,21 +10759,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 @@ -10712,81 +10800,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, @@ -10799,27 +10871,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 }; @@ -10856,7 +10914,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 && @@ -14290,144 +14349,193 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) } #endif /* WOLFSSL_TLS13 */ +#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \ + defined(WOLFSSL_PQC_HYBRIDS) + /* Prefer non-experimental PQ/T hybrid groups */ + #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 /* 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) + 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_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \ + !defined(WOLFSSL_NO_ML_KEM_768) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + 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_HAVE_MLKEM) && !defined(WOLFSSL_NO_ML_KEM) && \ + !defined(WOLFSSL_NO_ML_KEM_512) && !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + 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 @@ -14463,154 +14571,93 @@ 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 + /* 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 !defined(WOLFSSL_NO_ML_KEM_1024) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) 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, + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP521R1MLKEM1024, ssl->heap); - #endif #endif -#ifndef WOLFSSL_NO_ML_KEM_768 - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_ML_KEM_768, - ssl->heap); +#if !defined(WOLFSSL_NO_ML_KEM_768) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) 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); - #endif #if defined(HAVE_CURVE448) && ECC_MIN_KEY_SZ <= 448 if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_X448MLKEM768, ssl->heap); - #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) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP521R1MLKEM1024, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM1024, - ssl->heap); + #endif /* HAVE_CURVE448 */ #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 !defined(WOLFSSL_NO_ML_KEM_512) && \ + defined(WOLFSSL_EXTRA_PQC_HYBRIDS) if (ret == WOLFSSL_SUCCESS) ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP256R1MLKEM512, 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 (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP521R1MLKEM1024, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_SECP384R1MLKEM1024, - ssl->heap); #if defined(HAVE_CURVE25519) && ECC_MIN_KEY_SZ <= 256 if (ret == WOLFSSL_SUCCESS) 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 /* HAVE_CURVE25519 */ +#endif #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); +#ifdef WOLFSSL_KYBER1024 if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P256_KYBER_LEVEL1, + 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, + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_P521_KYBER_LEVEL5, ssl->heap); - #endif #endif #ifdef WOLFSSL_KYBER768 if (ret == WOLFSSL_SUCCESS) @@ -14633,49 +14680,20 @@ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) ssl->heap); #endif #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); +#ifdef WOLFSSL_KYBER512 if (ret == WOLFSSL_SUCCESS) - ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL5, + ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_KYBER_LEVEL1, ssl->heap); if (ret == WOLFSSL_SUCCESS) 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) 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 +#endif /* WOLFSSL_HAVE_MLKEM */ #endif /* WOLFSSL_HAVE_MLKEM */ (void)ssl; diff --git a/src/tls13.c b/src/tls13.c index b9e06896f9e..d1a54872438 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -13848,6 +13848,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 7083040296f..5f70c651899 100644 --- a/tests/api.c +++ b/tests/api.c @@ -28290,6 +28290,9 @@ static int test_dtls13_bad_epoch_ch(void) /* resend the CH */ ExpectIntEQ(wolfSSL_dtls_got_timeout(ssl_c), WOLFSSL_SUCCESS); + /* Re-enable HRR cookie to account for potential CH fragmentation */ + ExpectIntEQ(wolfSSL_send_hrr_cookie(ssl_s, NULL, 0), WOLFSSL_SUCCESS); + ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0); wolfSSL_free(ssl_c); @@ -28882,6 +28885,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++) { @@ -28904,6 +28911,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(OUT_OF_ORDER_E)); diff --git a/tests/api/test_dtls.c b/tests/api/test_dtls.c index a1f592c7063..a22324a88be 100644 --- a/tests/api/test_dtls.c +++ b/tests/api/test_dtls.c @@ -1614,6 +1614,28 @@ 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) + WOLFSSL_X25519MLKEM768, + #elif defined(HAVE_ECC) && defined(WOLFSSL_PQC_HYBRIDS) + WOLFSSL_SECP256R1MLKEM768, + #elif !defined(WOLFSSL_NO_ML_KEM_1024) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) + WOLFSSL_ML_KEM_1024, + #else + WOLFSSL_ML_KEM_768, + #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 +1644,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 +1673,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 a70ea09a1cf..6dbd1c4cedb 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 @@ -150,12 +156,16 @@ int test_tls13_apis(void) ":P256_KYBER_LEVEL5" #endif #else - #ifndef WOLFSSL_NO_KYBER512 + #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(WOLFSSL_EXTRA_PQC_HYBRIDS) ":SecP256r1MLKEM512" - #elif !defined(WOLFSSL_NO_KYBER768) - ":SecP384r1MLKEM768" - #else - ":SecP521r1MLKEM1024" + #elif !defined(WOLFSSL_NO_ML_KEM_768) && defined(WOLFSSL_PQC_HYBRIDS) + ":SecP256r1MLKEM768" + #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 @@ -173,7 +183,7 @@ int test_tls13_apis(void) #else ":KYBER_LEVEL5" #endif -#else +#elif !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) #ifndef WOLFSSL_NO_KYBER512 ":ML_KEM_512" #elif !defined(WOLFSSL_NO_KYBER768) @@ -188,7 +198,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 @@ -351,8 +365,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) @@ -361,6 +379,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) @@ -1919,9 +1944,13 @@ 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_TLS_NO_MLKEM_STANDALONE #ifndef WOLFSSL_NO_ML_KEM_1024 #ifdef WOLFSSL_MLKEM_KYBER int group = WOLFSSL_KYBER_LEVEL5; @@ -1940,6 +1969,11 @@ static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx) #else int group = WOLFSSL_ML_KEM_512; #endif /* WOLFSSL_MLKEM_KYBER */ +#endif +#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768) + int group = WOLFSSL_SECP256R1MLKEM768; +#elif defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) + int group = WOLFSSL_X25519MLKEM768; #endif AssertIntEQ(wolfSSL_CTX_set_groups(ctx, &group, 1), WOLFSSL_SUCCESS); @@ -1947,6 +1981,7 @@ static void test_tls13_pq_groups_ctx_ready(WOLFSSL_CTX* ctx) static void test_tls13_pq_groups_on_result(WOLFSSL* ssl) { +#ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE #ifndef WOLFSSL_NO_ML_KEM_1024 #ifdef WOLFSSL_MLKEM_KYBER AssertStrEQ(wolfSSL_get_curve_name(ssl), "KYBER_LEVEL5"); @@ -1966,6 +2001,11 @@ static void test_tls13_pq_groups_on_result(WOLFSSL* ssl) AssertStrEQ(wolfSSL_get_curve_name(ssl), "ML_KEM_512"); #endif /* WOLFSSL_MLKEM_KYBER */ #endif +#elif defined(HAVE_ECC) && !defined(WOLFSSL_NO_ML_KEM_768) + AssertStrEQ(wolfSSL_get_curve_name(ssl), "SecP256r1MLKEM768"); +#elif defined(HAVE_CURVE25519) && !defined(WOLFSSL_NO_ML_KEM_768) + AssertStrEQ(wolfSSL_get_curve_name(ssl), "X25519MLKEM768"); +#endif } #endif @@ -1975,7 +2015,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; @@ -2160,6 +2203,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 60a727ea021..d30645b71b2 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -180,7 +180,8 @@ static int IsKyberLevelAvailable(const char* line) begin += 6; end = XSTRSTR(begin, " "); - #ifndef WOLFSSL_NO_ML_KEM +#ifndef WOLFSSL_NO_ML_KEM + #ifndef WOLFSSL_TLS_NO_MLKEM_STANDALONE if ((size_t)end - (size_t)begin == 10) { #ifndef WOLFSSL_NO_ML_KEM_512 if (XSTRNCMP(begin, "ML_KEM_512", 10) == 0) { @@ -200,8 +201,71 @@ static int IsKyberLevelAvailable(const char* line) } } #endif - #endif - #ifdef WOLFSSL_MLKEM_KYBER + #endif /* !WOLFSSL_TLS_NO_MLKEM_STANDALONE */ + + #ifdef WOLFSSL_PQC_HYBRIDS + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC) + if ((size_t)end - (size_t)begin == 17) { + if (XSTRNCMP(begin, "SecP256r1MLKEM768", 17) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_ECC */ + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519) + if ((size_t)end - (size_t)begin == 14) { + if (XSTRNCMP(begin, "X25519MLKEM768", 14) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_CURVE25519 */ + #if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC384) + if ((size_t)end - (size_t)begin == 18) { + if (XSTRNCMP(begin, "SecP384r1MLKEM1024", 18) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_1024 */ + #endif /* WOLFSSL_PQC_HYBRIDS */ + + #ifdef WOLFSSL_EXTRA_PQC_HYBRIDS + #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_ECC) + if ((size_t)end - (size_t)begin == 17) { + if (XSTRNCMP(begin, "SecP256r1MLKEM512", 17) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_512 && HAVE_ECC */ + #if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519) + if ((size_t)end - (size_t)begin == 14) { + if (XSTRNCMP(begin, "X25519MLKEM512", 14) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_512 && HAVE_CURVE25519 */ + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC384) + if ((size_t)end - (size_t)begin == 17) { + if (XSTRNCMP(begin, "SecP384r1MLKEM768", 17) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_ECC384 */ + #if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448) + if ((size_t)end - (size_t)begin == 12) { + if (XSTRNCMP(begin, "X448MLKEM768", 12) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_CURVE448 */ + #if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC521) + if ((size_t)end - (size_t)begin == 18) { + if (XSTRNCMP(begin, "SecP521r1MLKEM1024", 18) == 0) { + available = 1; + } + } + #endif /* !WOLFSSL_NO_ML_KEM_1024 */ + #endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ +#endif /* !WOLFSSL_NO_ML_KEM */ +#ifdef WOLFSSL_MLKEM_KYBER if ((size_t)end - (size_t)begin == 12) { #ifndef WOLFSSL_NO_KYBER512 if (XSTRNCMP(begin, "KYBER_LEVEL1", 12) == 0) { @@ -219,7 +283,8 @@ static int IsKyberLevelAvailable(const char* line) } #endif } - #endif +#endif /* WOLFSSL_MLKEM_KYBER */ + (void) end; } #if defined(WOLFSSL_MLKEM_NO_MAKE_KEY) || \ @@ -1024,8 +1089,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) { @@ -1033,6 +1099,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"); @@ -1042,10 +1110,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) { @@ -1053,8 +1134,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) { @@ -1062,9 +1145,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) { @@ -1072,6 +1157,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"); @@ -1081,6 +1168,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 5eca832149a..768b4f1cb61 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3398,6 +3398,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, diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index ed88c090024..3ca25c1877e 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -4684,21 +4684,21 @@ enum { WOLFSSL_P256_KYBER_LEVEL3 = 25498, #endif /* WOLFSSL_MLKEM_KYBER */ #ifndef WOLFSSL_NO_ML_KEM - /* Taken from draft-connolly-tls-mlkem-key-agreement, see: - * https://github.com/dconnolly/draft-connolly-tls-mlkem-key-agreement/ + /* Taken from draft-ietf-tls-mlkem, see: + * https://datatracker.ietf.org/doc/draft-ietf-tls-mlkem/05/ */ WOLFSSL_ML_KEM_512 = 512, WOLFSSL_ML_KEM_768 = 513, WOLFSSL_ML_KEM_1024 = 514, - /* Taken from draft-kwiatkowski-tls-ecdhe-mlkem. see: - * https://github.com/post-quantum-cryptography/ - * draft-kwiatkowski-tls-ecdhe-mlkem/ + /* Taken from draft-ietf-tls-ecdhe-mlkem. see: + * https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/03/ */ WOLFSSL_SECP256R1MLKEM768 = 4587, WOLFSSL_X25519MLKEM768 = 4588, WOLFSSL_SECP384R1MLKEM1024 = 4589, +#ifdef WOLFSSL_EXTRA_PQC_HYBRIDS /* Taken from OQS's openssl provider, see: * https://github.com/open-quantum-safe/oqs-provider/blob/main/oqs-template/ * oqs-kem-info.md @@ -4713,6 +4713,7 @@ enum { WOLFSSL_SECP521R1MLKEM1024 = 12109, WOLFSSL_X25519MLKEM512 = 12214, WOLFSSL_X448MLKEM768 = 12215, +#endif /* WOLFSSL_EXTRA_PQC_HYBRIDS */ #endif /* WOLFSSL_NO_ML_KEM */ #endif /* HAVE_PQC */ WOLF_ENUM_DUMMY_LAST_ELEMENT(SSL_H) diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 49301a4d3af..6427c18f45b 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -4488,15 +4488,20 @@ extern void uITRON4_free(void *p) ; #define WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC #endif -#if defined(HAVE_PQC) && defined(WOLFSSL_DTLS13) && \ - !defined(WOLFSSL_DTLS_CH_FRAG) -#warning "Using DTLS 1.3 + pqc without WOLFSSL_DTLS_CH_FRAG will probably" \ - "fail.Use --enable-dtls-frag-ch to enable it." +#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_MLKEM) && \ + defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS_CH_FRAG) +#define WOLFSSL_DTLS_CH_FRAG #endif #if !defined(WOLFSSL_DTLS13) && defined(WOLFSSL_DTLS_CH_FRAG) #error "WOLFSSL_DTLS_CH_FRAG only works with DTLS 1.3" #endif +#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_PQC_HYBRIDS) && defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE) +#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 9863454ffcd..ea5be59afa2 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 549bc07ab0b..4c61e750626 100644 --- a/zephyr/samples/wolfssl_tls_sock/prj.conf +++ b/zephyr/samples/wolfssl_tls_sock/prj.conf @@ -55,3 +55,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 185a7b24c07..5a7024210f7 100644 --- a/zephyr/samples/wolfssl_tls_thread/prj.conf +++ b/zephyr/samples/wolfssl_tls_thread/prj.conf @@ -41,3 +41,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 4d7e2ebd061..c390aa9f336 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 /* ------------------------------------------------------------------------- */ From 5e3b1e921ebd329bd33589a23d393f515419f305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Frauenschl=C3=A4ger?= Date: Tue, 10 Feb 2026 19:07:15 +0100 Subject: [PATCH 2/2] mlkem Wconversion fixes --- .github/workflows/wolfCrypt-Wconversion.yml | 5 +- configure.ac | 3 + wolfcrypt/src/wc_mlkem.c | 43 +- wolfcrypt/src/wc_mlkem_poly.c | 808 ++++++++++---------- 4 files changed, 450 insertions(+), 409 deletions(-) diff --git a/.github/workflows/wolfCrypt-Wconversion.yml b/.github/workflows/wolfCrypt-Wconversion.yml index b1a7305e4e3..c96c4407741 100644 --- a/.github/workflows/wolfCrypt-Wconversion.yml +++ b/.github/workflows/wolfCrypt-Wconversion.yml @@ -23,7 +23,10 @@ jobs: '--enable-smallstack --disable-asm --enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests CPPFLAGS="-Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion"', '--enable-smallstack --enable-intelasm --enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests CPPFLAGS="-Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion"', '--enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests CPPFLAGS="-Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion -DNO_INT128"', - '--enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests CPPFLAGS="-Wdeclaration-after-statement -Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion" --enable-32bit CFLAGS=-m32' + '--enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests CPPFLAGS="-Wdeclaration-after-statement -Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion" --enable-32bit CFLAGS=-m32', + '--enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests --enable-mlkem=yes,small CPPFLAGS="-Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion -DNO_INT128"', + '--enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests --enable-mlkem=yes,no-large-code CPPFLAGS="-Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion -DNO_INT128"', + '--enable-smallstack --enable-cryptonly --enable-all-crypto --disable-examples --disable-benchmark --disable-crypttests --enable-mlkem=yes CPPFLAGS="-Wconversion -Warith-conversion -Wenum-conversion -Wfloat-conversion -Wsign-conversion -DNO_INT128"', ] name: build library if: github.repository_owner == 'wolfssl' diff --git a/configure.ac b/configure.ac index edbdcc2a4a6..50336803c86 100644 --- a/configure.ac +++ b/configure.ac @@ -1684,6 +1684,9 @@ do small) AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_SMALL" ;; + no-large-code) + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_NO_LARGE_CODE" + ;; cache-a) AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_MLKEM_CACHE_A" ;; diff --git a/wolfcrypt/src/wc_mlkem.c b/wolfcrypt/src/wc_mlkem.c index 6cd325888a7..263e35c8733 100644 --- a/wolfcrypt/src/wc_mlkem.c +++ b/wolfcrypt/src/wc_mlkem.c @@ -516,16 +516,17 @@ int wc_MlKemKey_MakeKeyWithRandom(MlKemKey* key, const unsigned char* rand, #ifndef WOLFSSL_MLKEM_MAKEKEY_SMALL_MEM #ifndef WOLFSSL_MLKEM_CACHE_A /* e (v) | a (m) */ - e = (sword16*)XMALLOC((k + 1) * k * MLKEM_N * sizeof(sword16), + e = (sword16*)XMALLOC((size_t)(k + 1) * (size_t)k * + (size_t)MLKEM_N * sizeof(sword16), key->heap, DYNAMIC_TYPE_TMP_BUFFER); #else /* e (v) */ - e = (sword16*)XMALLOC(k * MLKEM_N * sizeof(sword16), + e = (sword16*)XMALLOC((size_t)k * (size_t)MLKEM_N * sizeof(sword16), key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif #else /* e (v) */ - e = (sword16*)XMALLOC(k * MLKEM_N * sizeof(sword16), + e = (sword16*)XMALLOC((size_t)k * (size_t)MLKEM_N * sizeof(sword16), key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif if (e == NULL) { @@ -557,7 +558,7 @@ int wc_MlKemKey_MakeKeyWithRandom(MlKemKey* key, const unsigned char* rand, #endif #ifndef WOLFSSL_NO_ML_KEM { - buf[0] = k; + buf[0] = (byte)k; /* Expand 33 bytes of random to 32. * Alg 13: Step 1: (rho,sigma) <- G(d||k) */ @@ -582,7 +583,7 @@ int wc_MlKemKey_MakeKeyWithRandom(MlKemKey* key, const unsigned char* rand, /* Generate noise using PRF. * Alg 13: Steps 8-15: generate s and e */ - ret = mlkem_get_noise(&key->prf, k, s, e, NULL, sigma); + ret = mlkem_get_noise(&key->prf, (int)k, s, e, NULL, sigma); } if (ret == 0) { /* Generate the matrix A. @@ -819,10 +820,12 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c) if (ret == 0) { /* Allocate dynamic memory for all matrices, vectors and polynomials. */ #ifndef WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM - y = (sword16*)XMALLOC(((k + 3) * k + 3) * MLKEM_N * sizeof(sword16), + y = (sword16*)XMALLOC(((size_t)(k + 3) * (size_t)k + 3) * + (size_t)MLKEM_N * sizeof(sword16), key->heap, DYNAMIC_TYPE_TMP_BUFFER); #else - y = (sword16*)XMALLOC(3 * k * MLKEM_N * sizeof(sword16), key->heap, + y = (sword16*)XMALLOC((size_t)3 * (size_t)k * + (size_t)MLKEM_N * sizeof(sword16), key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif if (y == NULL) { @@ -849,7 +852,7 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c) /* Generate noise using PRF. * Steps 9-17: generate y, e_1, e_2 */ - ret = mlkem_get_noise(&key->prf, k, y, e1, e2, r); + ret = mlkem_get_noise(&key->prf, (int)k, y, e1, e2, r); } #ifdef WOLFSSL_MLKEM_CACHE_A if ((ret == 0) && ((key->flags & MLKEM_FLAG_A_SET) != 0)) { @@ -870,7 +873,7 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c) if (ret == 0) { /* Generate the transposed matrix. * Step 4-8: generate matrix A_hat */ - ret = mlkem_gen_matrix(&key->prf, a, k, key->pubSeed, 1); + ret = mlkem_gen_matrix(&key->prf, a, (int)k, key->pubSeed, 1); } if (ret == 0) { /* Assign remaining allocated dynamic memory to pointers. @@ -880,7 +883,7 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c) /* Perform encapsulation maths. * Steps 18-19, 21: calculate u and v */ - mlkem_encapsulate(key->pub, u, v, a, y, e1, e2, mu, k); + mlkem_encapsulate(key->pub, u, v, a, y, e1, e2, mu, (int)k); } #else /* WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM */ if (ret == 0) { @@ -892,7 +895,7 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c) mlkem_prf_init(&key->prf); /* Generate noise using PRF. * Steps 9-12: generate y */ - ret = mlkem_get_noise(&key->prf, k, y, NULL, NULL, r); + ret = mlkem_get_noise(&key->prf, (int)k, y, NULL, NULL, r); } if (ret == 0) { /* Assign remaining allocated dynamic memory to pointers. @@ -903,7 +906,7 @@ static int mlkemkey_encapsulate(MlKemKey* key, const byte* m, byte* r, byte* c) /* Perform encapsulation maths. * Steps 13-17: generate e_1 and e_2 * Steps 18-19, 21: calculate u and v */ - ret = mlkem_encapsulate_seeds(key->pub, &key->prf, u, a, y, k, m, + ret = mlkem_encapsulate_seeds(key->pub, &key->prf, u, a, y, (int)k, m, key->pubSeed, r); } #endif /* WOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM */ @@ -1344,7 +1347,7 @@ static MLKEM_NOINLINE int mlkemkey_decapsulate(MlKemKey* key, byte* m, /* Decapsulate the cipher text into polynomial. * Step 6: w <- v' - InvNTT(s_hat_trans o NTT(u')) */ - mlkem_decapsulate(key->priv, w, u, v, k); + mlkem_decapsulate(key->priv, w, u, v, (int)k); /* Convert the polynomial into a array of bytes (message). * Step 7: m <- ByteEncode_1(Compress_1(w)) */ @@ -1498,7 +1501,7 @@ int wc_MlKemKey_Decapsulate(MlKemKey* key, unsigned char* ss, } if (ret == 0) { /* Compare generated cipher text with that passed in. */ - fail = mlkem_cmp(ct, cmp, ctSz); + fail = mlkem_cmp(ct, cmp, (int)ctSz); #if defined(WOLFSSL_MLKEM_KYBER) && !defined(WOLFSSL_NO_ML_KEM) if (key->type & MLKEM_KYBER) @@ -1527,7 +1530,7 @@ int wc_MlKemKey_Decapsulate(MlKemKey* key, unsigned char* ss, if (ret == 0) { /* Set secret to kr or fake secret on comparison failure. */ for (i = 0; i < WC_ML_KEM_SYM_SZ; i++) { - ss[i] = kr[i] ^ ((kr[i] ^ msg[i]) & fail); + ss[i] = (byte)(kr[i] ^ ((kr[i] ^ msg[i]) & fail)); } } } @@ -1568,7 +1571,7 @@ static void mlkemkey_decode_public(sword16* pub, byte* pubSeed, const byte* p, /* Decode public key that is vector of polynomials. * Step 2: t <- ByteDecode_12(ek_PKE[0 : 384k]) */ - mlkem_from_bytes(pub, p, k); + mlkem_from_bytes(pub, p, (int)k); p += k * WC_ML_KEM_POLY_SIZE; /* Read public key seed. @@ -1684,7 +1687,7 @@ int wc_MlKemKey_DecodePrivateKey(MlKemKey* key, const unsigned char* in, /* Decode private key that is vector of polynomials. * Alg 18 Step 1: dk_PKE <- dk[0 : 384k] * Alg 15 Step 5: s_hat <- ByteDecode_12(dk_PKE) */ - mlkem_from_bytes(key->priv, p, k); + mlkem_from_bytes(key->priv, p, (int)k); p += k * WC_ML_KEM_POLY_SIZE; /* Decode the public key that is after the private key. */ @@ -1793,7 +1796,7 @@ int wc_MlKemKey_DecodePublicKey(MlKemKey* key, const unsigned char* in, if (ret == 0) { mlkemkey_decode_public(key->pub, key->pubSeed, p, k); - ret = mlkem_check_public(key->pub, k); + ret = mlkem_check_public(key->pub, (int)k); } if (ret == 0) { /* Calculate public hash. */ @@ -2038,7 +2041,7 @@ int wc_MlKemKey_EncodePrivateKey(MlKemKey* key, unsigned char* out, word32 len) if (ret == 0) { /* Encode private key that is vector of polynomials. */ - mlkem_to_bytes(p, key->priv, k); + mlkem_to_bytes(p, key->priv, (int)k); p += WC_ML_KEM_POLY_SIZE * k; /* Encode public key. */ @@ -2155,7 +2158,7 @@ int wc_MlKemKey_EncodePublicKey(MlKemKey* key, unsigned char* out, word32 len) int i; /* Encode public key polynomial by polynomial. */ - mlkem_to_bytes(p, key->pub, k); + mlkem_to_bytes(p, key->pub, (int)k); p += k * WC_ML_KEM_POLY_SIZE; /* Append public seed. */ diff --git a/wolfcrypt/src/wc_mlkem_poly.c b/wolfcrypt/src/wc_mlkem_poly.c index 6e8ce95f751..4a725b2e983 100644 --- a/wolfcrypt/src/wc_mlkem_poly.c +++ b/wolfcrypt/src/wc_mlkem_poly.c @@ -235,9 +235,9 @@ static void mlkem_ntt(sword16* r) sword16 t = MLKEM_MONT_RED(p); sword16 rj = r[j]; /* Step 9 */ - r[j + len] = rj - t; + r[j + len] = (sword16)(rj - t); /* Step 10 */ - r[j] = rj + t; + r[j] = (sword16)(rj + t); } } } @@ -258,8 +258,8 @@ static void mlkem_ntt(sword16* r) sword32 p = (sword32)zeta * r[j + MLKEM_N / 2]; sword16 t = MLKEM_MONT_RED(p); sword16 rj = r[j]; - r[j + MLKEM_N / 2] = rj - t; - r[j] = rj + t; + r[j + MLKEM_N / 2] = (sword16)(rj - t); + r[j] = (sword16)(rj + t); } for (len = MLKEM_N / 4; len >= 2; len >>= 1) { for (start = 0; start < MLKEM_N; start = j + len) { @@ -268,8 +268,8 @@ static void mlkem_ntt(sword16* r) sword32 p = (sword32)zeta * r[j + len]; sword16 t = MLKEM_MONT_RED(p); sword16 rj = r[j]; - r[j + len] = rj - t; - r[j] = rj + t; + r[j + len] = (sword16)(rj - t); + r[j] = (sword16)(rj + t); } } } @@ -389,27 +389,27 @@ static void mlkem_ntt(sword16* r) t1 = MLKEM_MONT_RED((sword32)zeta128 * r5); t2 = MLKEM_MONT_RED((sword32)zeta128 * r6); t3 = MLKEM_MONT_RED((sword32)zeta128 * r7); - r4 = r0 - t0; - r5 = r1 - t1; - r6 = r2 - t2; - r7 = r3 - t3; - r0 += t0; - r1 += t1; - r2 += t2; - r3 += t3; + r4 = (sword16)(r0 - t0); + r5 = (sword16)(r1 - t1); + r6 = (sword16)(r2 - t2); + r7 = (sword16)(r3 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r2 = (sword16)(r2 + t2); + r3 = (sword16)(r3 + t3); t0 = MLKEM_MONT_RED((sword32)zeta64_0 * r2); t1 = MLKEM_MONT_RED((sword32)zeta64_0 * r3); t2 = MLKEM_MONT_RED((sword32)zeta64_1 * r6); t3 = MLKEM_MONT_RED((sword32)zeta64_1 * r7); - r2 = r0 - t0; - r3 = r1 - t1; - r6 = r4 - t2; - r7 = r5 - t3; - r0 += t0; - r1 += t1; - r4 += t2; - r5 += t3; + r2 = (sword16)(r0 - t0); + r3 = (sword16)(r1 - t1); + r6 = (sword16)(r4 - t2); + r7 = (sword16)(r5 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r4 = (sword16)(r4 + t2); + r5 = (sword16)(r5 + t3); r[j + 0] = r0; r[j + 32] = r1; @@ -423,7 +423,7 @@ static void mlkem_ntt(sword16* r) /* len = 32,16,8 */ for (j = 0; j < MLKEM_N; j += 64) { - int i; + unsigned int i; sword16 zeta32 = zetas[ 4 + j / 64 + 0]; sword16 zeta16_0 = zetas[ 8 + j / 32 + 0]; sword16 zeta16_1 = zetas[ 8 + j / 32 + 1]; @@ -445,40 +445,40 @@ static void mlkem_ntt(sword16* r) t1 = MLKEM_MONT_RED((sword32)zeta32 * r5); t2 = MLKEM_MONT_RED((sword32)zeta32 * r6); t3 = MLKEM_MONT_RED((sword32)zeta32 * r7); - r4 = r0 - t0; - r5 = r1 - t1; - r6 = r2 - t2; - r7 = r3 - t3; - r0 += t0; - r1 += t1; - r2 += t2; - r3 += t3; + r4 = (sword16)(r0 - t0); + r5 = (sword16)(r1 - t1); + r6 = (sword16)(r2 - t2); + r7 = (sword16)(r3 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r2 = (sword16)(r2 + t2); + r3 = (sword16)(r3 + t3); t0 = MLKEM_MONT_RED((sword32)zeta16_0 * r2); t1 = MLKEM_MONT_RED((sword32)zeta16_0 * r3); t2 = MLKEM_MONT_RED((sword32)zeta16_1 * r6); t3 = MLKEM_MONT_RED((sword32)zeta16_1 * r7); - r2 = r0 - t0; - r3 = r1 - t1; - r6 = r4 - t2; - r7 = r5 - t3; - r0 += t0; - r1 += t1; - r4 += t2; - r5 += t3; + r2 = (sword16)(r0 - t0); + r3 = (sword16)(r1 - t1); + r6 = (sword16)(r4 - t2); + r7 = (sword16)(r5 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r4 = (sword16)(r4 + t2); + r5 = (sword16)(r5 + t3); t0 = MLKEM_MONT_RED((sword32)zeta8_0 * r1); t1 = MLKEM_MONT_RED((sword32)zeta8_1 * r3); t2 = MLKEM_MONT_RED((sword32)zeta8_2 * r5); t3 = MLKEM_MONT_RED((sword32)zeta8_3 * r7); - r1 = r0 - t0; - r3 = r2 - t1; - r5 = r4 - t2; - r7 = r6 - t3; - r0 += t0; - r2 += t1; - r4 += t2; - r6 += t3; + r1 = (sword16)(r0 - t0); + r3 = (sword16)(r2 - t1); + r5 = (sword16)(r4 - t2); + r7 = (sword16)(r6 - t3); + r0 = (sword16)(r0 + t0); + r2 = (sword16)(r2 + t1); + r4 = (sword16)(r4 + t2); + r6 = (sword16)(r6 + t3); r[j + i + 0] = r0; r[j + i + 8] = r1; @@ -509,27 +509,27 @@ static void mlkem_ntt(sword16* r) t1 = MLKEM_MONT_RED((sword32)zeta4 * r5); t2 = MLKEM_MONT_RED((sword32)zeta4 * r6); t3 = MLKEM_MONT_RED((sword32)zeta4 * r7); - r4 = r0 - t0; - r5 = r1 - t1; - r6 = r2 - t2; - r7 = r3 - t3; - r0 += t0; - r1 += t1; - r2 += t2; - r3 += t3; + r4 = (sword16)(r0 - t0); + r5 = (sword16)(r1 - t1); + r6 = (sword16)(r2 - t2); + r7 = (sword16)(r3 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r2 = (sword16)(r2 + t2); + r3 = (sword16)(r3 + t3); t0 = MLKEM_MONT_RED((sword32)zeta2_0 * r2); t1 = MLKEM_MONT_RED((sword32)zeta2_0 * r3); t2 = MLKEM_MONT_RED((sword32)zeta2_1 * r6); t3 = MLKEM_MONT_RED((sword32)zeta2_1 * r7); - r2 = r0 - t0; - r3 = r1 - t1; - r6 = r4 - t2; - r7 = r5 - t3; - r0 += t0; - r1 += t1; - r4 += t2; - r5 += t3; + r2 = (sword16)(r0 - t0); + r3 = (sword16)(r1 - t1); + r6 = (sword16)(r4 - t2); + r7 = (sword16)(r5 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r4 = (sword16)(r4 + t2); + r5 = (sword16)(r5 + t3); r[j + 0] = MLKEM_BARRETT_RED(r0); r[j + 1] = MLKEM_BARRETT_RED(r1); @@ -612,10 +612,10 @@ static void mlkem_invntt(sword16* r) sword16 rj = r[j]; sword16 rjl = r[j + len]; /* Step 9 */ - sword16 t = rj + rjl; + sword16 t = (sword16)(rj + rjl); r[j] = MLKEM_BARRETT_RED(t); /* Step 10 */ - rjl = rj - rjl; + rjl = (sword16)(rj - rjl); p = (sword32)zeta * rjl; r[j + len] = MLKEM_MONT_RED(p); } @@ -645,9 +645,9 @@ static void mlkem_invntt(sword16* r) sword32 p; sword16 rj = r[j]; sword16 rjl = r[j + len]; - sword16 t = rj + rjl; + sword16 t = (sword16)(rj + rjl); r[j] = MLKEM_BARRETT_RED(t); - rjl = rj - rjl; + rjl = (sword16)(rj - rjl); p = (sword32)zeta * rjl; r[j + len] = MLKEM_MONT_RED(p); } @@ -660,10 +660,10 @@ static void mlkem_invntt(sword16* r) sword32 p; sword16 rj = r[j]; sword16 rjl = r[j + MLKEM_N / 2]; - sword16 t = rj + rjl; - rjl = rj - rjl; + sword16 t = (sword16)(rj + rjl); + rjl = (sword16)(rj - rjl); p = (sword32)zeta * rjl; - r[j] = t; + r[j] = (sword16)t; r[j + MLKEM_N / 2] = MLKEM_MONT_RED(p); p = (sword32)zeta2 * r[j]; @@ -818,10 +818,10 @@ static void mlkem_invntt(sword16* r) t2 = MLKEM_MONT_RED(p); p = (sword32)zeta2_1 * (sword16)(r5 - r7); t3 = MLKEM_MONT_RED(p); - r0 += r2; - r1 += r3; - r4 += r6; - r5 += r7; + r0 = (sword16)(r0 + r2); + r1 = (sword16)(r1 + r3); + r4 = (sword16)(r4 + r6); + r5 = (sword16)(r5 + r7); r2 = t0; r3 = t1; r6 = t2; @@ -835,10 +835,10 @@ static void mlkem_invntt(sword16* r) t2 = MLKEM_MONT_RED(p); p = (sword32)zeta4 * (sword16)(r3 - r7); t3 = MLKEM_MONT_RED(p); - r0 += r4; - r1 += r5; - r2 += r6; - r3 += r7; + r0 = (sword16)(r0 + r4); + r1 = (sword16)(r1 + r5); + r2 = (sword16)(r2 + r6); + r3 = (sword16)(r3 + r7); r4 = t0; r5 = t1; r6 = t2; @@ -855,7 +855,7 @@ static void mlkem_invntt(sword16* r) } for (j = 0; j < MLKEM_N; j += 64) { - int i; + unsigned int i; sword16 zeta8_0 = zetas_inv[ 96 + j / 16 + 0]; sword16 zeta8_1 = zetas_inv[ 96 + j / 16 + 1]; sword16 zeta8_2 = zetas_inv[ 96 + j / 16 + 2]; @@ -898,10 +898,10 @@ static void mlkem_invntt(sword16* r) t2 = MLKEM_MONT_RED(p); p = (sword32)zeta16_1 * (sword16)(r5 - r7); t3 = MLKEM_MONT_RED(p); - r0 += r2; - r1 += r3; - r4 += r6; - r5 += r7; + r0 = (sword16)(r0 + r2); + r1 = (sword16)(r1 + r3); + r4 = (sword16)(r4 + r6); + r5 = (sword16)(r5 + r7); r2 = t0; r3 = t1; r6 = t2; @@ -915,10 +915,10 @@ static void mlkem_invntt(sword16* r) t2 = MLKEM_MONT_RED(p); p = (sword32)zeta32 * (sword16)(r3 - r7); t3 = MLKEM_MONT_RED(p); - r0 += r4; - r1 += r5; - r2 += r6; - r3 += r7; + r0 = (sword16)(r0 + r4); + r1 = (sword16)(r1 + r5); + r2 = (sword16)(r2 + r6); + r3 = (sword16)(r3 + r7); r4 = t0; r5 = t1; r6 = t2; @@ -974,10 +974,10 @@ static void mlkem_invntt(sword16* r) t2 = MLKEM_MONT_RED(p); p = (sword32)zeta128 * (sword16)(r3 - r7); t3 = MLKEM_MONT_RED(p); - r0 += r4; - r1 += r5; - r2 += r6; - r3 += r7; + r0 = (sword16)(r0 + r4); + r1 = (sword16)(r1 + r5); + r2 = (sword16)(r2 + r6); + r3 = (sword16)(r3 + r7); r4 = t0; r5 = t1; r6 = t2; @@ -1081,29 +1081,36 @@ static void mlkem_basemul_mont(sword16* r, const sword16* a, const sword16* b) for (i = 0; i < MLKEM_N; i += 4, zeta++) { /* Step 2 */ mlkem_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]); - mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, -zeta[0]); + mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, + (sword16)(-zeta[0])); } #elif defined(WOLFSSL_MLKEM_NO_LARGE_CODE) /* Four multiplications per loop. */ unsigned int i; for (i = 0; i < MLKEM_N; i += 8, zeta += 2) { mlkem_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]); - mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, -zeta[0]); + mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, + (sword16)(-zeta[0])); mlkem_basemul(r + i + 4, a + i + 4, b + i + 4, zeta[1]); - mlkem_basemul(r + i + 6, a + i + 6, b + i + 6, -zeta[1]); + mlkem_basemul(r + i + 6, a + i + 6, b + i + 6, + (sword16)(-zeta[1])); } #else /* Eight multiplications per loop. */ unsigned int i; for (i = 0; i < MLKEM_N; i += 16, zeta += 4) { mlkem_basemul(r + i + 0, a + i + 0, b + i + 0, zeta[0]); - mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, -zeta[0]); + mlkem_basemul(r + i + 2, a + i + 2, b + i + 2, + (sword16)(-zeta[0])); mlkem_basemul(r + i + 4, a + i + 4, b + i + 4, zeta[1]); - mlkem_basemul(r + i + 6, a + i + 6, b + i + 6, -zeta[1]); + mlkem_basemul(r + i + 6, a + i + 6, b + i + 6, + (sword16)(-zeta[1])); mlkem_basemul(r + i + 8, a + i + 8, b + i + 8, zeta[2]); - mlkem_basemul(r + i + 10, a + i + 10, b + i + 10, -zeta[2]); + mlkem_basemul(r + i + 10, a + i + 10, b + i + 10, + (sword16)(-zeta[2])); mlkem_basemul(r + i + 12, a + i + 12, b + i + 12, zeta[3]); - mlkem_basemul(r + i + 14, a + i + 14, b + i + 14, -zeta[3]); + mlkem_basemul(r + i + 14, a + i + 14, b + i + 14, + (sword16)(-zeta[3])); } #endif } @@ -1137,12 +1144,12 @@ static void mlkem_basemul_mont_add(sword16* r, const sword16* a, sword16 t2[2]; mlkem_basemul(t0, a + i + 0, b + i + 0, zeta[0]); - mlkem_basemul(t2, a + i + 2, b + i + 2, -zeta[0]); + mlkem_basemul(t2, a + i + 2, b + i + 2, (sword16)(-zeta[0])); - r[i + 0] += t0[0]; - r[i + 1] += t0[1]; - r[i + 2] += t2[0]; - r[i + 3] += t2[1]; + r[i + 0] = (sword16)(r[i + 0] + t0[0]); + r[i + 1] = (sword16)(r[i + 1] + t0[1]); + r[i + 2] = (sword16)(r[i + 2] + t2[0]); + r[i + 3] = (sword16)(r[i + 3] + t2[1]); } #elif defined(WOLFSSL_MLKEM_NO_LARGE_CODE) /* Four multiplications per loop. */ @@ -1154,18 +1161,18 @@ static void mlkem_basemul_mont_add(sword16* r, const sword16* a, sword16 t6[2]; mlkem_basemul(t0, a + i + 0, b + i + 0, zeta[0]); - mlkem_basemul(t2, a + i + 2, b + i + 2, -zeta[0]); + mlkem_basemul(t2, a + i + 2, b + i + 2, (sword16)(-zeta[0])); mlkem_basemul(t4, a + i + 4, b + i + 4, zeta[1]); - mlkem_basemul(t6, a + i + 6, b + i + 6, -zeta[1]); + mlkem_basemul(t6, a + i + 6, b + i + 6, (sword16)(-zeta[1])); - r[i + 0] += t0[0]; - r[i + 1] += t0[1]; - r[i + 2] += t2[0]; - r[i + 3] += t2[1]; - r[i + 4] += t4[0]; - r[i + 5] += t4[1]; - r[i + 6] += t6[0]; - r[i + 7] += t6[1]; + r[i + 0] = (sword16)(r[i + 0] + t0[0]); + r[i + 1] = (sword16)(r[i + 1] + t0[1]); + r[i + 2] = (sword16)(r[i + 2] + t2[0]); + r[i + 3] = (sword16)(r[i + 3] + t2[1]); + r[i + 4] = (sword16)(r[i + 4] + t4[0]); + r[i + 5] = (sword16)(r[i + 5] + t4[1]); + r[i + 6] = (sword16)(r[i + 6] + t6[0]); + r[i + 7] = (sword16)(r[i + 7] + t6[1]); } #else /* Eight multiplications per loop. */ @@ -1181,30 +1188,30 @@ static void mlkem_basemul_mont_add(sword16* r, const sword16* a, sword16 t14[2]; mlkem_basemul(t0, a + i + 0, b + i + 0, zeta[0]); - mlkem_basemul(t2, a + i + 2, b + i + 2, -zeta[0]); + mlkem_basemul(t2, a + i + 2, b + i + 2, (sword16)(-zeta[0])); mlkem_basemul(t4, a + i + 4, b + i + 4, zeta[1]); - mlkem_basemul(t6, a + i + 6, b + i + 6, -zeta[1]); + mlkem_basemul(t6, a + i + 6, b + i + 6, (sword16)(-zeta[1])); mlkem_basemul(t8, a + i + 8, b + i + 8, zeta[2]); - mlkem_basemul(t10, a + i + 10, b + i + 10, -zeta[2]); + mlkem_basemul(t10, a + i + 10, b + i + 10, (sword16)(-zeta[2])); mlkem_basemul(t12, a + i + 12, b + i + 12, zeta[3]); - mlkem_basemul(t14, a + i + 14, b + i + 14, -zeta[3]); - - r[i + 0] += t0[0]; - r[i + 1] += t0[1]; - r[i + 2] += t2[0]; - r[i + 3] += t2[1]; - r[i + 4] += t4[0]; - r[i + 5] += t4[1]; - r[i + 6] += t6[0]; - r[i + 7] += t6[1]; - r[i + 8] += t8[0]; - r[i + 9] += t8[1]; - r[i + 10] += t10[0]; - r[i + 11] += t10[1]; - r[i + 12] += t12[0]; - r[i + 13] += t12[1]; - r[i + 14] += t14[0]; - r[i + 15] += t14[1]; + mlkem_basemul(t14, a + i + 14, b + i + 14, (sword16)(-zeta[3])); + + r[i + 0] = (sword16)(r[i + 0] + t0[0]); + r[i + 1] = (sword16)(r[i + 1] + t0[1]); + r[i + 2] = (sword16)(r[i + 2] + t2[0]); + r[i + 3] = (sword16)(r[i + 3] + t2[1]); + r[i + 4] = (sword16)(r[i + 4] + t4[0]); + r[i + 5] = (sword16)(r[i + 5] + t4[1]); + r[i + 6] = (sword16)(r[i + 6] + t6[0]); + r[i + 7] = (sword16)(r[i + 7] + t6[1]); + r[i + 8] = (sword16)(r[i + 8] + t8[0]); + r[i + 9] = (sword16)(r[i + 9] + t8[1]); + r[i + 10] = (sword16)(r[i + 10] + t10[0]); + r[i + 11] = (sword16)(r[i + 11] + t10[1]); + r[i + 12] = (sword16)(r[i + 12] + t12[0]); + r[i + 13] = (sword16)(r[i + 13] + t12[1]); + r[i + 14] = (sword16)(r[i + 14] + t14[0]); + r[i + 15] = (sword16)(r[i + 15] + t14[1]); } #endif } @@ -1622,27 +1629,27 @@ static void mlkem_ntt_add_to(sword16* r, sword16* a) t1 = MLKEM_MONT_RED((sword32)zeta128 * r5); t2 = MLKEM_MONT_RED((sword32)zeta128 * r6); t3 = MLKEM_MONT_RED((sword32)zeta128 * r7); - r4 = r0 - t0; - r5 = r1 - t1; - r6 = r2 - t2; - r7 = r3 - t3; - r0 += t0; - r1 += t1; - r2 += t2; - r3 += t3; + r4 = (sword16)(r0 - t0); + r5 = (sword16)(r1 - t1); + r6 = (sword16)(r2 - t2); + r7 = (sword16)(r3 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r2 = (sword16)(r2 + t2); + r3 = (sword16)(r3 + t3); t0 = MLKEM_MONT_RED((sword32)zeta64_0 * r2); t1 = MLKEM_MONT_RED((sword32)zeta64_0 * r3); t2 = MLKEM_MONT_RED((sword32)zeta64_1 * r6); t3 = MLKEM_MONT_RED((sword32)zeta64_1 * r7); - r2 = r0 - t0; - r3 = r1 - t1; - r6 = r4 - t2; - r7 = r5 - t3; - r0 += t0; - r1 += t1; - r4 += t2; - r5 += t3; + r2 = (sword16)(r0 - t0); + r3 = (sword16)(r1 - t1); + r6 = (sword16)(r4 - t2); + r7 = (sword16)(r5 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r4 = (sword16)(r4 + t2); + r5 = (sword16)(r5 + t3); r[j + 0] = r0; r[j + 32] = r1; @@ -1656,7 +1663,7 @@ static void mlkem_ntt_add_to(sword16* r, sword16* a) /* len = 32,16,8 */ for (j = 0; j < MLKEM_N; j += 64) { - int i; + unsigned int i; sword16 zeta32 = zetas[ 4 + j / 64 + 0]; sword16 zeta16_0 = zetas[ 8 + j / 32 + 0]; sword16 zeta16_1 = zetas[ 8 + j / 32 + 1]; @@ -1678,40 +1685,40 @@ static void mlkem_ntt_add_to(sword16* r, sword16* a) t1 = MLKEM_MONT_RED((sword32)zeta32 * r5); t2 = MLKEM_MONT_RED((sword32)zeta32 * r6); t3 = MLKEM_MONT_RED((sword32)zeta32 * r7); - r4 = r0 - t0; - r5 = r1 - t1; - r6 = r2 - t2; - r7 = r3 - t3; - r0 += t0; - r1 += t1; - r2 += t2; - r3 += t3; + r4 = (sword16)(r0 - t0); + r5 = (sword16)(r1 - t1); + r6 = (sword16)(r2 - t2); + r7 = (sword16)(r3 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r2 = (sword16)(r2 + t2); + r3 = (sword16)(r3 + t3); t0 = MLKEM_MONT_RED((sword32)zeta16_0 * r2); t1 = MLKEM_MONT_RED((sword32)zeta16_0 * r3); t2 = MLKEM_MONT_RED((sword32)zeta16_1 * r6); t3 = MLKEM_MONT_RED((sword32)zeta16_1 * r7); - r2 = r0 - t0; - r3 = r1 - t1; - r6 = r4 - t2; - r7 = r5 - t3; - r0 += t0; - r1 += t1; - r4 += t2; - r5 += t3; + r2 = (sword16)(r0 - t0); + r3 = (sword16)(r1 - t1); + r6 = (sword16)(r4 - t2); + r7 = (sword16)(r5 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r4 = (sword16)(r4 + t2); + r5 = (sword16)(r5 + t3); t0 = MLKEM_MONT_RED((sword32)zeta8_0 * r1); t1 = MLKEM_MONT_RED((sword32)zeta8_1 * r3); t2 = MLKEM_MONT_RED((sword32)zeta8_2 * r5); t3 = MLKEM_MONT_RED((sword32)zeta8_3 * r7); - r1 = r0 - t0; - r3 = r2 - t1; - r5 = r4 - t2; - r7 = r6 - t3; - r0 += t0; - r2 += t1; - r4 += t2; - r6 += t3; + r1 = (sword16)(r0 - t0); + r3 = (sword16)(r2 - t1); + r5 = (sword16)(r4 - t2); + r7 = (sword16)(r6 - t3); + r0 = (sword16)(r0 + t0); + r2 = (sword16)(r2 + t1); + r4 = (sword16)(r4 + t2); + r6 = (sword16)(r6 + t3); r[j + i + 0] = r0; r[j + i + 8] = r1; @@ -1742,36 +1749,36 @@ static void mlkem_ntt_add_to(sword16* r, sword16* a) t1 = MLKEM_MONT_RED((sword32)zeta4 * r5); t2 = MLKEM_MONT_RED((sword32)zeta4 * r6); t3 = MLKEM_MONT_RED((sword32)zeta4 * r7); - r4 = r0 - t0; - r5 = r1 - t1; - r6 = r2 - t2; - r7 = r3 - t3; - r0 += t0; - r1 += t1; - r2 += t2; - r3 += t3; + r4 = (sword16)(r0 - t0); + r5 = (sword16)(r1 - t1); + r6 = (sword16)(r2 - t2); + r7 = (sword16)(r3 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r2 = (sword16)(r2 + t2); + r3 = (sword16)(r3 + t3); t0 = MLKEM_MONT_RED((sword32)zeta2_0 * r2); t1 = MLKEM_MONT_RED((sword32)zeta2_0 * r3); t2 = MLKEM_MONT_RED((sword32)zeta2_1 * r6); t3 = MLKEM_MONT_RED((sword32)zeta2_1 * r7); - r2 = r0 - t0; - r3 = r1 - t1; - r6 = r4 - t2; - r7 = r5 - t3; - r0 += t0; - r1 += t1; - r4 += t2; - r5 += t3; - - r0 += a[j + 0]; - r1 += a[j + 1]; - r2 += a[j + 2]; - r3 += a[j + 3]; - r4 += a[j + 4]; - r5 += a[j + 5]; - r6 += a[j + 6]; - r7 += a[j + 7]; + r2 = (sword16)(r0 - t0); + r3 = (sword16)(r1 - t1); + r6 = (sword16)(r4 - t2); + r7 = (sword16)(r5 - t3); + r0 = (sword16)(r0 + t0); + r1 = (sword16)(r1 + t1); + r4 = (sword16)(r4 + t2); + r5 = (sword16)(r5 + t3); + + r0 = (sword16)(r0 + a[j + 0]); + r1 = (sword16)(r1 + a[j + 1]); + r2 = (sword16)(r2 + a[j + 2]); + r3 = (sword16)(r3 + a[j + 3]); + r4 = (sword16)(r4 + a[j + 4]); + r5 = (sword16)(r5 + a[j + 5]); + r6 = (sword16)(r6 + a[j + 6]); + r7 = (sword16)(r7 + a[j + 7]); a[j + 0] = MLKEM_BARRETT_RED(r0); a[j + 1] = MLKEM_BARRETT_RED(r1); @@ -1805,22 +1812,23 @@ static void mlkem_ntt_add_to(sword16* r, sword16* a) static void mlkem_keygen_c(sword16* s, sword16* t, sword16* e, const sword16* a, int k) { - int i; + unsigned int i; + unsigned int uk = (unsigned int)k; /* Transform private key. All of result used in public key calculation * Step 16: s_hat = NTT(s) */ - for (i = 0; i < k; ++i) { + for (i = 0; i < uk; ++i) { mlkem_ntt(s + i * MLKEM_N); } /* For each polynomial in the vectors. * Step 17, Step 18: Calculate public from A_hat, s_hat and e_hat. */ - for (i = 0; i < k; ++i) { + for (i = 0; i < uk; ++i) { unsigned int j; /* Multiply a by private into public polynomial. * Step 18: ... A_hat o s_hat ... */ - mlkem_pointwise_acc_mont(t + i * MLKEM_N, a + i * k * MLKEM_N, s, k); + mlkem_pointwise_acc_mont(t + i * MLKEM_N, a + i * uk * MLKEM_N, s, uk); /* Convert public polynomial to Montgomery form. * Step 18: ... MontRed(A_hat o s_hat) ... */ for (j = 0; j < MLKEM_N; ++j) { @@ -1834,7 +1842,7 @@ static void mlkem_keygen_c(sword16* s, sword16* t, sword16* e, const sword16* a, /* Add errors to public key and reduce. * Step 18: t_hat = BarrettRed(MontRed(A_hat o s_hat) + e_hat) */ for (j = 0; j < MLKEM_N; ++j) { - sword16 n = t[i * MLKEM_N + j] + e[i * MLKEM_N + j]; + sword16 n = (sword16)(t[i * MLKEM_N + j] + e[i * MLKEM_N + j]); t[i * MLKEM_N + j] = MLKEM_BARRETT_RED(n); } #else @@ -1985,37 +1993,46 @@ static void mlkem_encapsulate_c(const sword16* pub, sword16* u, sword16* v, const sword16* a, sword16* y, const sword16* e1, const sword16* e2, const sword16* m, int k) { - int i; + unsigned int i; + unsigned int uk = (unsigned int)k; /* Transform y. All of result used in calculation of u and v. */ - for (i = 0; i < k; ++i) { + for (i = 0; i < uk; ++i) { mlkem_ntt(y + i * MLKEM_N); } /* For each polynomial in the vectors. */ - for (i = 0; i < k; ++i) { + for (i = 0; i < uk; ++i) { unsigned int j; /* Multiply at by y into u polynomial. */ - mlkem_pointwise_acc_mont(u + i * MLKEM_N, a + i * k * MLKEM_N, y, k); + mlkem_pointwise_acc_mont(u + i * MLKEM_N, a + i * uk * MLKEM_N, y, uk); /* Inverse transform u polynomial. */ mlkem_invntt(u + i * MLKEM_N); /* Add errors to u and reduce. */ #if defined(WOLFSSL_MLKEM_SMALL) || defined(WOLFSSL_MLKEM_NO_LARGE_CODE) for (j = 0; j < MLKEM_N; ++j) { - sword16 t = u[i * MLKEM_N + j] + e1[i * MLKEM_N + j]; + sword16 t = (sword16)(u[i * MLKEM_N + j] + e1[i * MLKEM_N + j]); u[i * MLKEM_N + j] = MLKEM_BARRETT_RED(t); } #else for (j = 0; j < MLKEM_N; j += 8) { - sword16 t0 = u[i * MLKEM_N + j + 0] + e1[i * MLKEM_N + j + 0]; - sword16 t1 = u[i * MLKEM_N + j + 1] + e1[i * MLKEM_N + j + 1]; - sword16 t2 = u[i * MLKEM_N + j + 2] + e1[i * MLKEM_N + j + 2]; - sword16 t3 = u[i * MLKEM_N + j + 3] + e1[i * MLKEM_N + j + 3]; - sword16 t4 = u[i * MLKEM_N + j + 4] + e1[i * MLKEM_N + j + 4]; - sword16 t5 = u[i * MLKEM_N + j + 5] + e1[i * MLKEM_N + j + 5]; - sword16 t6 = u[i * MLKEM_N + j + 6] + e1[i * MLKEM_N + j + 6]; - sword16 t7 = u[i * MLKEM_N + j + 7] + e1[i * MLKEM_N + j + 7]; + sword16 t0 = (sword16)(u[i * MLKEM_N + j + 0] + + e1[i * MLKEM_N + j + 0]); + sword16 t1 = (sword16)(u[i * MLKEM_N + j + 1] + + e1[i * MLKEM_N + j + 1]); + sword16 t2 = (sword16)(u[i * MLKEM_N + j + 2] + + e1[i * MLKEM_N + j + 2]); + sword16 t3 = (sword16)(u[i * MLKEM_N + j + 3] + + e1[i * MLKEM_N + j + 3]); + sword16 t4 = (sword16)(u[i * MLKEM_N + j + 4] + + e1[i * MLKEM_N + j + 4]); + sword16 t5 = (sword16)(u[i * MLKEM_N + j + 5] + + e1[i * MLKEM_N + j + 5]); + sword16 t6 = (sword16)(u[i * MLKEM_N + j + 6] + + e1[i * MLKEM_N + j + 6]); + sword16 t7 = (sword16)(u[i * MLKEM_N + j + 7] + + e1[i * MLKEM_N + j + 7]); u[i * MLKEM_N + j + 0] = MLKEM_BARRETT_RED(t0); u[i * MLKEM_N + j + 1] = MLKEM_BARRETT_RED(t1); u[i * MLKEM_N + j + 2] = MLKEM_BARRETT_RED(t2); @@ -2029,12 +2046,12 @@ static void mlkem_encapsulate_c(const sword16* pub, sword16* u, sword16* v, } /* Multiply public key by y into v polynomial. */ - mlkem_pointwise_acc_mont(v, pub, y, k); + mlkem_pointwise_acc_mont(v, pub, y, uk); /* Inverse transform v. */ mlkem_invntt(v); /* Add errors and message to v and reduce. */ for (i = 0; i < MLKEM_N; ++i) { - sword16 t = v[i] + e2[i] + m[i]; + sword16 t = (sword16)(v[i] + e2[i] + m[i]); v[i] = MLKEM_BARRETT_RED(t); } } @@ -2209,24 +2226,25 @@ int mlkem_encapsulate_seeds(const sword16* pub, MLKEM_PRF_T* prf, sword16* u, static void mlkem_decapsulate_c(const sword16* s, sword16* w, sword16* u, const sword16* v, int k) { - int i; + unsigned int i; + unsigned int uk = (unsigned int)k; /* Transform u. All of result used in calculation of w. * Step 6: ... NTT(u') */ - for (i = 0; i < k; ++i) { + for (i = 0; i < uk; ++i) { mlkem_ntt(u + i * MLKEM_N); } /* Multiply private key by u into w polynomial. * Step 6: ... s_hat_trans o NTT(u') */ - mlkem_pointwise_acc_mont(w, s, u, k); + mlkem_pointwise_acc_mont(w, s, u, uk); /* Inverse transform w. * Step 6: ... InvNTT(s_hat_trans o NTT(u')) */ mlkem_invntt(w); /* Subtract errors (in w) out of v and reduce into w. * Step 6: w <- v' - InvNTT(s_hat_trans o NTT(u')) */ for (i = 0; i < MLKEM_N; ++i) { - sword16 t = v[i] - w[i]; + sword16 t = (sword16)(v[i] - w[i]); w[i] = MLKEM_BARRETT_RED(t); } } @@ -2424,10 +2442,12 @@ static int mlkem_gen_matrix_k3_avx2(sword16* a, byte* seed, int transposed) for (k = 0; k < 2; k++) { for (i = 0; i < 4; i++) { if (!transposed) { - state[4*4 + i] = 0x1f0000 + (((k*4+i)/3) << 8) + ((k*4+i)%3); + state[4*4 + i] = (word64)(0x1f0000U + + (word32)((((k * 4 + i) / 3) << 8) + ((k * 4 + i) % 3))); } else { - state[4*4 + i] = 0x1f0000 + (((k*4+i)%3) << 8) + ((k*4+i)/3); + state[4*4 + i] = (word64)(0x1f0000U + + (word32)((((k * 4 + i) % 3) << 8) + ((k * 4 + i) / 3))); } } @@ -2577,10 +2597,12 @@ static int mlkem_gen_matrix_k4_avx2(sword16* a, byte* seed, int transposed) for (k = 0; k < 4; k++) { for (i = 0; i < 4; i++) { if (!transposed) { - state[4*4 + i] = 0x1f0000 + (k << 8) + i; + state[4*4 + i] = (word64)(0x1f0000U + + (word32)(((k << 8) + i))); } else { - state[4*4 + i] = 0x1f0000 + (i << 8) + k; + state[4*4 + i] = (word64)(0x1f0000U + + (word32)(((i << 8) + k))); } } @@ -2881,7 +2903,7 @@ static int mlkem_xof_absorb(wc_Shake* shake128, byte* seed, int len) ret = wc_InitShake128(shake128, NULL, INVALID_DEVID); if (ret == 0) { - ret = wc_Shake128_Absorb(shake128, seed, len); + ret = wc_Shake128_Absorb(shake128, seed, (word32)len); } return ret; @@ -2899,7 +2921,7 @@ static int mlkem_xof_absorb(wc_Shake* shake128, byte* seed, int len) */ static int mlkem_xof_squeezeblocks(wc_Shake* shake128, byte* out, int blocks) { - return wc_Shake128_SqueezeBlocks(shake128, out, blocks); + return wc_Shake128_SqueezeBlocks(shake128, out, (word32)blocks); } #endif @@ -3453,13 +3475,13 @@ static int mlkem_gen_matrix_c(MLKEM_PRF_T* prf, sword16* a, int k, byte* seed, for (j = 0; (ret == 0) && (j < k); j++) { if (transposed) { /* Alg 14, Step 6: .. rho||i||j ... */ - extSeed[WC_ML_KEM_SYM_SZ + 0] = i; - extSeed[WC_ML_KEM_SYM_SZ + 1] = j; + extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)i; + extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)j; } else { /* Alg 13, Step 5: .. rho||j||i ... */ - extSeed[WC_ML_KEM_SYM_SZ + 0] = j; - extSeed[WC_ML_KEM_SYM_SZ + 1] = i; + extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)j; + extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)i; } /* Absorb the index specific seed. * Alg 7, Step 1-2 */ @@ -3655,13 +3677,13 @@ static int mlkem_gen_matrix_i(MLKEM_PRF_T* prf, sword16* a, int k, byte* seed, for (j = 0; (ret == 0) && (j < k); j++) { if (transposed) { /* Alg 14, Step 6: .. rho||i||j ... */ - extSeed[WC_ML_KEM_SYM_SZ + 0] = i; - extSeed[WC_ML_KEM_SYM_SZ + 1] = j; + extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)i; + extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)j; } else { /* Alg 13, Step 5: .. rho||j||i ... */ - extSeed[WC_ML_KEM_SYM_SZ + 0] = j; - extSeed[WC_ML_KEM_SYM_SZ + 1] = i; + extSeed[WC_ML_KEM_SYM_SZ + 0] = (byte)j; + extSeed[WC_ML_KEM_SYM_SZ + 1] = (byte)i; } /* Absorb the index specific seed. * Alg 7, Step 1-2 */ @@ -3716,8 +3738,8 @@ static int mlkem_gen_matrix_i(MLKEM_PRF_T* prf, sword16* a, int k, byte* seed, * @return Difference of the two values with range 0..2. */ #define ETA2_SUB(d, i) \ - (((sword16)(((d) >> ((i) * 4 + 0)) & 0x3)) - \ - ((sword16)(((d) >> ((i) * 4 + 2)) & 0x3))) + (sword16)(((sword16)(((d) >> ((i) * 4 + 0)) & 0x3)) - \ + ((sword16)(((d) >> ((i) * 4 + 2)) & 0x3))) /* Compute polynomial with coefficients distributed according to a centered * binomial distribution with parameter eta2 from uniform random bytes. @@ -3832,8 +3854,8 @@ static void mlkem_cbd_eta2(sword16* p, const byte* r) * @return Difference of the two values with range 0..3. */ #define ETA3_SUB(d, i) \ - (((sword16)(((d) >> ((i) * 6 + 0)) & 0x7)) - \ - ((sword16)(((d) >> ((i) * 6 + 3)) & 0x7))) + (sword16)(((sword16)(((d) >> ((i) * 6 + 0)) & 0x7)) - \ + ((sword16)(((d) >> ((i) * 6 + 3)) & 0x7))) /* Compute polynomial with coefficients distributed according to a centered * binomial distribution with parameter eta3 from uniform random bytes. @@ -4093,7 +4115,7 @@ static void mlkem_get_noise_x4_eta2_avx2(byte* rand, byte* seed, byte o) word64 state[25 * 4]; for (i = 0; i < 4; i++) { - state[4*4 + i] = 0x1f00 + i + o; + state[4*4 + i] = (word64)(0x1f00U + (word32)i + (word32)o); } sha3_256_blocksx4_seed_avx2(state, seed); @@ -4554,7 +4576,8 @@ static int mlkem_get_noise_c(MLKEM_PRF_T* prf, int k, sword16* vec1, int eta1, /* Generate noise as private key. */ for (i = 0; (ret == 0) && (i < k); i++) { /* Generate noise for each dimension of vector. */ - ret = mlkem_get_noise_eta1_c(prf, vec1 + i * MLKEM_N, seed, eta1); + ret = mlkem_get_noise_eta1_c(prf, vec1 + i * MLKEM_N, seed, + (byte)eta1); /* Increment value of appended byte. */ seed[WC_ML_KEM_SYM_SZ]++; } @@ -4562,13 +4585,14 @@ static int mlkem_get_noise_c(MLKEM_PRF_T* prf, int k, sword16* vec1, int eta1, /* Generate noise for error. */ for (i = 0; (ret == 0) && (i < k); i++) { /* Generate noise for each dimension of vector. */ - ret = mlkem_get_noise_eta1_c(prf, vec2 + i * MLKEM_N, seed, eta2); + ret = mlkem_get_noise_eta1_c(prf, vec2 + i * MLKEM_N, seed, + (byte)eta2); /* Increment value of appended byte. */ seed[WC_ML_KEM_SYM_SZ]++; } } else { - seed[WC_ML_KEM_SYM_SZ] = 2 * k; + seed[WC_ML_KEM_SYM_SZ] = (byte)(2 * k); } if ((ret == 0) && (poly != NULL)) { /* Generating random error polynomial. */ @@ -4728,7 +4752,7 @@ static int mlkem_cmp_c(const byte* a, const byte* b, int sz) for (i = 0; i < sz; i++) { r |= a[i] ^ b[i]; } - return 0 - ((-(word32)r) >> 31); + return (int)(0 - ((-(word32)r) >> 31)); } #endif @@ -4777,9 +4801,10 @@ static MLKEM_NOINLINE void mlkem_csubq_c(sword16* p) unsigned int i; for (i = 0; i < MLKEM_N; ++i) { - sword16 t = p[i] - MLKEM_Q; + sword16 t = (sword16)(p[i] - MLKEM_Q); /* When top bit set, -ve number - need to add q back. */ - p[i] = (sword16)((word16)(-((word16)t >> 15)) & MLKEM_Q) + t; + p[i] = (sword16)(((word16)(-((word16)t >> 15)) & MLKEM_Q) + + (word16)t); } } @@ -4899,8 +4924,9 @@ static MLKEM_NOINLINE void mlkem_csubq_c(sword16* p) * @return Compressed value. */ #define TO_COMP_WORD_10(v, i, j, k) \ - ((((MLKEM_V54 << 10) * (v)[(i) * MLKEM_N + (j) + (k)]) + \ - MLKEM_V54_HALF) >> 54) + (word16)(((((word64)(MLKEM_V54 << 10)) * \ + (word64)(word16)((v)[(i) * MLKEM_N + (j) + (k)])) + \ + MLKEM_V54_HALF) >> 54) /* Compress value to 11 bits. * @@ -4916,8 +4942,9 @@ static MLKEM_NOINLINE void mlkem_csubq_c(sword16* p) * @return Compressed value. */ #define TO_COMP_WORD_11(v, i, j, k) \ - ((((MLKEM_V53 << 11) * (v)[(i) * MLKEM_N + (j) + (k)]) + \ - MLKEM_V53_HALF) >> 53) + (word16)(((((word64)(MLKEM_V53 << 11)) * \ + (word64)(word16)((v)[(i) * MLKEM_N + (j) + (k)])) + \ + MLKEM_V53_HALF) >> 53) #endif /* CONV_WITH_DIV */ @@ -4966,17 +4993,17 @@ static void mlkem_vec_compress_10_c(byte* r, sword16* v, unsigned int k) r[ 4] = (t[3] >> 2); #else /* Compress four polynomial values to 10 bits each. */ - sword16 t0 = TO_COMP_WORD_10(v, i, j, 0); - sword16 t1 = TO_COMP_WORD_10(v, i, j, 1); - sword16 t2 = TO_COMP_WORD_10(v, i, j, 2); - sword16 t3 = TO_COMP_WORD_10(v, i, j, 3); + word16 t0 = TO_COMP_WORD_10(v, i, j, 0); + word16 t1 = TO_COMP_WORD_10(v, i, j, 1); + word16 t2 = TO_COMP_WORD_10(v, i, j, 2); + word16 t3 = TO_COMP_WORD_10(v, i, j, 3); /* Pack four 10-bit values into byte array. */ - r[ 0] = (t0 >> 0); - r[ 1] = (t0 >> 8) | (t1 << 2); - r[ 2] = (t1 >> 6) | (t2 << 4); - r[ 3] = (t2 >> 4) | (t3 << 6); - r[ 4] = (t3 >> 2); + r[ 0] = (byte)(t0 >> 0); + r[ 1] = (byte)((t0 >> 8) | (t1 << 2)); + r[ 2] = (byte)((t1 >> 6) | (t2 << 4)); + r[ 3] = (byte)((t2 >> 4) | (t3 << 6)); + r[ 4] = (byte)(t3 >> 2); #endif /* Move over set bytes. */ @@ -4986,35 +5013,35 @@ static void mlkem_vec_compress_10_c(byte* r, sword16* v, unsigned int k) /* Each 16 polynomial coefficients. */ for (j = 0; j < MLKEM_N; j += 16) { /* Compress four polynomial values to 10 bits each. */ - sword16 t0 = TO_COMP_WORD_10(v, i, j, 0); - sword16 t1 = TO_COMP_WORD_10(v, i, j, 1); - sword16 t2 = TO_COMP_WORD_10(v, i, j, 2); - sword16 t3 = TO_COMP_WORD_10(v, i, j, 3); - sword16 t4 = TO_COMP_WORD_10(v, i, j, 4); - sword16 t5 = TO_COMP_WORD_10(v, i, j, 5); - sword16 t6 = TO_COMP_WORD_10(v, i, j, 6); - sword16 t7 = TO_COMP_WORD_10(v, i, j, 7); - sword16 t8 = TO_COMP_WORD_10(v, i, j, 8); - sword16 t9 = TO_COMP_WORD_10(v, i, j, 9); - sword16 t10 = TO_COMP_WORD_10(v, i, j, 10); - sword16 t11 = TO_COMP_WORD_10(v, i, j, 11); - sword16 t12 = TO_COMP_WORD_10(v, i, j, 12); - sword16 t13 = TO_COMP_WORD_10(v, i, j, 13); - sword16 t14 = TO_COMP_WORD_10(v, i, j, 14); - sword16 t15 = TO_COMP_WORD_10(v, i, j, 15); + word16 t0 = TO_COMP_WORD_10(v, i, j, 0); + word16 t1 = TO_COMP_WORD_10(v, i, j, 1); + word16 t2 = TO_COMP_WORD_10(v, i, j, 2); + word16 t3 = TO_COMP_WORD_10(v, i, j, 3); + word16 t4 = TO_COMP_WORD_10(v, i, j, 4); + word16 t5 = TO_COMP_WORD_10(v, i, j, 5); + word16 t6 = TO_COMP_WORD_10(v, i, j, 6); + word16 t7 = TO_COMP_WORD_10(v, i, j, 7); + word16 t8 = TO_COMP_WORD_10(v, i, j, 8); + word16 t9 = TO_COMP_WORD_10(v, i, j, 9); + word16 t10 = TO_COMP_WORD_10(v, i, j, 10); + word16 t11 = TO_COMP_WORD_10(v, i, j, 11); + word16 t12 = TO_COMP_WORD_10(v, i, j, 12); + word16 t13 = TO_COMP_WORD_10(v, i, j, 13); + word16 t14 = TO_COMP_WORD_10(v, i, j, 14); + word16 t15 = TO_COMP_WORD_10(v, i, j, 15); word32* r32 = (word32*)r; /* Pack sixteen 10-bit values into byte array. */ - r32[0] = t0 | ((word32)t1 << 10) | ((word32)t2 << 20) | - ((word32)t3 << 30); - r32[1] = (t3 >> 2) | ((word32)t4 << 8) | ((word32)t5 << 18) | - ((word32)t6 << 28); - r32[2] = (t6 >> 4) | ((word32)t7 << 6) | ((word32)t8 << 16) | - ((word32)t9 << 26); - r32[3] = (t9 >> 6) | ((word32)t10 << 4) | ((word32)t11 << 14) | - ((word32)t12 << 24); - r32[4] = (t12 >> 8) | ((word32)t13 << 2) | ((word32)t14 << 12) | - ((word32)t15 << 22); + r32[0] = (word32)t0 | ((word32)t1 << 10) | + ((word32)t2 << 20) | ((word32)t3 << 30); + r32[1] = (word32)(t3 >> 2) | ((word32)t4 << 8) | + ((word32)t5 << 18) | ((word32)t6 << 28); + r32[2] = (word32)(t6 >> 4) | ((word32)t7 << 6) | + ((word32)t8 << 16) | ((word32)t9 << 26); + r32[3] = (word32)(t9 >> 6) | ((word32)t10 << 4) | + ((word32)t11 << 14) | ((word32)t12 << 24); + r32[4] = (word32)(t12 >> 8) | ((word32)t13 << 2) | + ((word32)t14 << 12) | ((word32)t15 << 22); /* Move over set bytes. */ r += 20; @@ -5035,7 +5062,7 @@ void mlkem_vec_compress_10(byte* r, sword16* v, unsigned int k) { #ifdef USE_INTEL_SPEEDUP if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) { - mlkem_compress_10_avx2(r, v, k); + mlkem_compress_10_avx2(r, v, (int)k); RESTORE_VECTOR_REGISTERS(); } else @@ -5073,47 +5100,47 @@ static void mlkem_vec_compress_11_c(byte* r, sword16* v) /* Each 8 polynomial coefficients. */ for (j = 0; j < MLKEM_N; j += 8) { #ifdef WOLFSSL_MLKEM_SMALL - sword16 t[8]; + word16 t[8]; /* Compress eight polynomial values to 11 bits each. */ for (k = 0; k < 8; k++) { t[k] = TO_COMP_WORD_11(v, i, j, k); } /* Pack eight 11-bit values into byte array. */ - r[ 0] = (t[0] >> 0); - r[ 1] = (t[0] >> 8) | (t[1] << 3); - r[ 2] = (t[1] >> 5) | (t[2] << 6); - r[ 3] = (t[2] >> 2); - r[ 4] = (t[2] >> 10) | (t[3] << 1); - r[ 5] = (t[3] >> 7) | (t[4] << 4); - r[ 6] = (t[4] >> 4) | (t[5] << 7); - r[ 7] = (t[5] >> 1); - r[ 8] = (t[5] >> 9) | (t[6] << 2); - r[ 9] = (t[6] >> 6) | (t[7] << 5); - r[10] = (t[7] >> 3); + r[ 0] = (byte)(t[0] >> 0); + r[ 1] = (byte)((t[0] >> 8) | (t[1] << 3)); + r[ 2] = (byte)((t[1] >> 5) | (t[2] << 6)); + r[ 3] = (byte)(t[2] >> 2); + r[ 4] = (byte)((t[2] >> 10) | (t[3] << 1)); + r[ 5] = (byte)((t[3] >> 7) | (t[4] << 4)); + r[ 6] = (byte)((t[4] >> 4) | (t[5] << 7)); + r[ 7] = (byte)(t[5] >> 1); + r[ 8] = (byte)((t[5] >> 9) | (t[6] << 2)); + r[ 9] = (byte)((t[6] >> 6) | (t[7] << 5)); + r[10] = (byte)(t[7] >> 3); #else /* Compress eight polynomial values to 11 bits each. */ - sword16 t0 = TO_COMP_WORD_11(v, i, j, 0); - sword16 t1 = TO_COMP_WORD_11(v, i, j, 1); - sword16 t2 = TO_COMP_WORD_11(v, i, j, 2); - sword16 t3 = TO_COMP_WORD_11(v, i, j, 3); - sword16 t4 = TO_COMP_WORD_11(v, i, j, 4); - sword16 t5 = TO_COMP_WORD_11(v, i, j, 5); - sword16 t6 = TO_COMP_WORD_11(v, i, j, 6); - sword16 t7 = TO_COMP_WORD_11(v, i, j, 7); + word16 t0 = TO_COMP_WORD_11(v, i, j, 0); + word16 t1 = TO_COMP_WORD_11(v, i, j, 1); + word16 t2 = TO_COMP_WORD_11(v, i, j, 2); + word16 t3 = TO_COMP_WORD_11(v, i, j, 3); + word16 t4 = TO_COMP_WORD_11(v, i, j, 4); + word16 t5 = TO_COMP_WORD_11(v, i, j, 5); + word16 t6 = TO_COMP_WORD_11(v, i, j, 6); + word16 t7 = TO_COMP_WORD_11(v, i, j, 7); /* Pack eight 11-bit values into byte array. */ - r[ 0] = (t0 >> 0); - r[ 1] = (t0 >> 8) | (t1 << 3); - r[ 2] = (t1 >> 5) | (t2 << 6); - r[ 3] = (t2 >> 2); - r[ 4] = (t2 >> 10) | (t3 << 1); - r[ 5] = (t3 >> 7) | (t4 << 4); - r[ 6] = (t4 >> 4) | (t5 << 7); - r[ 7] = (t5 >> 1); - r[ 8] = (t5 >> 9) | (t6 << 2); - r[ 9] = (t6 >> 6) | (t7 << 5); - r[10] = (t7 >> 3); + r[ 0] = (byte)(t0 >> 0); + r[ 1] = (byte)((t0 >> 8) | (t1 << 3)); + r[ 2] = (byte)((t1 >> 5) | (t2 << 6)); + r[ 3] = (byte)(t2 >> 2); + r[ 4] = (byte)((t2 >> 10) | (t3 << 1)); + r[ 5] = (byte)((t3 >> 7) | (t4 << 4)); + r[ 6] = (byte)((t4 >> 4) | (t5 << 7)); + r[ 7] = (byte)(t5 >> 1); + r[ 8] = (byte)((t5 >> 9) | (t6 << 2)); + r[ 9] = (byte)((t6 >> 6) | (t7 << 5)); + r[10] = (byte)(t7 >> 3); #endif /* Move over set bytes. */ @@ -5159,7 +5186,7 @@ void mlkem_vec_compress_11(byte* r, sword16* v) */ #define DECOMP_10(v, i, j, k, t) \ v[(i) * MLKEM_N + 4 * (j) + (k)] = \ - (word16)((((word32)((t) & 0x3ff) * MLKEM_Q) + 512) >> 10) + (sword16)((((word32)((t) & 0x3ff) * MLKEM_Q) + 512) >> 10) /* Decompress an 11 bit value. * @@ -5174,7 +5201,7 @@ void mlkem_vec_compress_11(byte* r, sword16* v) */ #define DECOMP_11(v, i, j, k, t) \ v[(i) * MLKEM_N + 8 * (j) + (k)] = \ - (word16)((((word32)((t) & 0x7ff) * MLKEM_Q) + 1024) >> 11) + (sword16)((((word32)((t) & 0x7ff) * MLKEM_Q) + 1024) >> 11) #if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512) || \ defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768) @@ -5201,10 +5228,10 @@ static void mlkem_vec_decompress_10_c(sword16* v, const byte* b, unsigned int k) #ifdef WOLFSSL_MLKEM_SMALL word16 t[4]; /* Extract out 4 values of 10 bits each. */ - t[0] = (b[0] >> 0) | ((word16)b[ 1] << 8); - t[1] = (b[1] >> 2) | ((word16)b[ 2] << 6); - t[2] = (b[2] >> 4) | ((word16)b[ 3] << 4); - t[3] = (b[3] >> 6) | ((word16)b[ 4] << 2); + t[0] = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8)); + t[1] = (word16)((b[1] >> 2) | ((word16)b[ 2] << 6)); + t[2] = (word16)((b[2] >> 4) | ((word16)b[ 3] << 4)); + t[3] = (word16)((b[3] >> 6) | ((word16)b[ 4] << 2)); b += 5; /* Decompress 4 values. */ @@ -5213,10 +5240,10 @@ static void mlkem_vec_decompress_10_c(sword16* v, const byte* b, unsigned int k) } #else /* Extract out 4 values of 10 bits each. */ - sword16 t0 = (b[0] >> 0) | ((word16)b[ 1] << 8); - sword16 t1 = (b[1] >> 2) | ((word16)b[ 2] << 6); - sword16 t2 = (b[2] >> 4) | ((word16)b[ 3] << 4); - sword16 t3 = (b[3] >> 6) | ((word16)b[ 4] << 2); + word16 t0 = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8)); + word16 t1 = (word16)((b[1] >> 2) | ((word16)b[ 2] << 6)); + word16 t2 = (word16)((b[2] >> 4) | ((word16)b[ 3] << 4)); + word16 t3 = (word16)((b[3] >> 6) | ((word16)b[ 4] << 2)); b += 5; /* Decompress 4 values. */ @@ -5241,7 +5268,7 @@ void mlkem_vec_decompress_10(sword16* v, const byte* b, unsigned int k) { #ifdef USE_INTEL_SPEEDUP if (IS_INTEL_AVX2(cpuid_flags) && (SAVE_VECTOR_REGISTERS2() == 0)) { - mlkem_decompress_10_avx2(v, b, k); + mlkem_decompress_10_avx2(v, b, (int)k); RESTORE_VECTOR_REGISTERS(); } else @@ -5274,16 +5301,16 @@ static void mlkem_vec_decompress_11_c(sword16* v, const byte* b) #ifdef WOLFSSL_MLKEM_SMALL word16 t[8]; /* Extract out 8 values of 11 bits each. */ - t[0] = (b[0] >> 0) | ((word16)b[ 1] << 8); - t[1] = (b[1] >> 3) | ((word16)b[ 2] << 5); - t[2] = (b[2] >> 6) | ((word16)b[ 3] << 2) | - ((word16)b[4] << 10); - t[3] = (b[4] >> 1) | ((word16)b[ 5] << 7); - t[4] = (b[5] >> 4) | ((word16)b[ 6] << 4); - t[5] = (b[6] >> 7) | ((word16)b[ 7] << 1) | - ((word16)b[8] << 9); - t[6] = (b[8] >> 2) | ((word16)b[ 9] << 6); - t[7] = (b[9] >> 5) | ((word16)b[10] << 3); + t[0] = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8)); + t[1] = (word16)((b[1] >> 3) | ((word16)b[ 2] << 5)); + t[2] = (word16)((b[2] >> 6) | ((word16)b[ 3] << 2) | + ((word16)b[4] << 10)); + t[3] = (word16)((b[4] >> 1) | ((word16)b[ 5] << 7)); + t[4] = (word16)((b[5] >> 4) | ((word16)b[ 6] << 4)); + t[5] = (word16)((b[6] >> 7) | ((word16)b[ 7] << 1) | + ((word16)b[8] << 9)); + t[6] = (word16)((b[8] >> 2) | ((word16)b[ 9] << 6)); + t[7] = (word16)((b[9] >> 5) | ((word16)b[10] << 3)); b += 11; /* Decompress 8 values. */ @@ -5292,16 +5319,16 @@ static void mlkem_vec_decompress_11_c(sword16* v, const byte* b) } #else /* Extract out 8 values of 11 bits each. */ - sword16 t0 = (b[0] >> 0) | ((word16)b[ 1] << 8); - sword16 t1 = (b[1] >> 3) | ((word16)b[ 2] << 5); - sword16 t2 = (b[2] >> 6) | ((word16)b[ 3] << 2) | - ((word16)b[4] << 10); - sword16 t3 = (b[4] >> 1) | ((word16)b[ 5] << 7); - sword16 t4 = (b[5] >> 4) | ((word16)b[ 6] << 4); - sword16 t5 = (b[6] >> 7) | ((word16)b[ 7] << 1) | - ((word16)b[8] << 9); - sword16 t6 = (b[8] >> 2) | ((word16)b[ 9] << 6); - sword16 t7 = (b[9] >> 5) | ((word16)b[10] << 3); + word16 t0 = (word16)((b[0] >> 0) | ((word16)b[ 1] << 8)); + word16 t1 = (word16)((b[1] >> 3) | ((word16)b[ 2] << 5)); + word16 t2 = (word16)((b[2] >> 6) | ((word16)b[ 3] << 2) | + ((word16)b[4] << 10)); + word16 t3 = (word16)((b[4] >> 1) | ((word16)b[ 5] << 7)); + word16 t4 = (word16)((b[5] >> 4) | ((word16)b[ 6] << 4)); + word16 t5 = (word16)((b[6] >> 7) | ((word16)b[ 7] << 1) | + ((word16)b[8] << 9)); + word16 t6 = (word16)((b[8] >> 2) | ((word16)b[ 9] << 6)); + word16 t7 = (word16)((b[9] >> 5) | ((word16)b[10] << 3)); b += 11; /* Decompress 8 values. */ @@ -5411,7 +5438,8 @@ void mlkem_vec_decompress_11(sword16* v, const byte* b) * @return Compressed value. */ #define TO_COMP_WORD_4(p, i, j) \ - ((((MLKEM_V28 << 4) * (p)[(i) + (j)]) + MLKEM_V28_HALF) >> 28) + (byte)(((((MLKEM_V28 << 4) * (word32)(word16)((p)[(i) + (j)])) + \ + MLKEM_V28_HALF) >> 28)) /* Compress value to 5 bits. * @@ -5425,7 +5453,8 @@ void mlkem_vec_decompress_11(sword16* v, const byte* b) * @return Compressed value. */ #define TO_COMP_WORD_5(p, i, j) \ - ((((MLKEM_V27 << 5) * (p)[(i) + (j)]) + MLKEM_V27_HALF) >> 27) + (byte)(((((MLKEM_V27 << 5) * (word32)(word16)((p)[(i) + (j)])) + \ + MLKEM_V27_HALF) >> 27)) #endif /* CONV_WITH_DIV */ @@ -5460,10 +5489,10 @@ static void mlkem_compress_4_c(byte* b, sword16* p) t[j] = TO_COMP_WORD_4(p, i, j); } - b[0] = t[0] | (t[1] << 4); - b[1] = t[2] | (t[3] << 4); - b[2] = t[4] | (t[5] << 4); - b[3] = t[6] | (t[7] << 4); + b[0] = (byte)(t[0] | (t[1] << 4)); + b[1] = (byte)(t[2] | (t[3] << 4)); + b[2] = (byte)(t[4] | (t[5] << 4)); + b[3] = (byte)(t[6] | (t[7] << 4)); #else /* Compress eight polynomial values to 4 bits each. */ byte t0 = TO_COMP_WORD_4(p, i, 0); @@ -5476,10 +5505,10 @@ static void mlkem_compress_4_c(byte* b, sword16* p) byte t7 = TO_COMP_WORD_4(p, i, 7); /* Pack eight 4-bit values into byte array. */ - b[0] = t0 | (t1 << 4); - b[1] = t2 | (t3 << 4); - b[2] = t4 | (t5 << 4); - b[3] = t6 | (t7 << 4); + b[0] = (byte)(t0 | (t1 << 4)); + b[1] = (byte)(t2 | (t3 << 4)); + b[2] = (byte)(t4 | (t5 << 4)); + b[3] = (byte)(t6 | (t7 << 4)); #endif /* Move over set bytes. */ @@ -5536,11 +5565,11 @@ static void mlkem_compress_5_c(byte* b, sword16* p) } /* Pack 5 bits into byte array. */ - b[0] = (t[0] >> 0) | (t[1] << 5); - b[1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7); - b[2] = (t[3] >> 1) | (t[4] << 4); - b[3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6); - b[4] = (t[6] >> 2) | (t[7] << 3); + b[0] = (byte)((t[0] >> 0) | (t[1] << 5)); + b[1] = (byte)((t[1] >> 3) | (t[2] << 2) | (t[3] << 7)); + b[2] = (byte)((t[3] >> 1) | (t[4] << 4)); + b[3] = (byte)((t[4] >> 4) | (t[5] << 1) | (t[6] << 6)); + b[4] = (byte)((t[6] >> 2) | (t[7] << 3)); #else /* Compress eight polynomial values to 5 bits each. */ byte t0 = TO_COMP_WORD_5(p, i, 0); @@ -5553,11 +5582,11 @@ static void mlkem_compress_5_c(byte* b, sword16* p) byte t7 = TO_COMP_WORD_5(p, i, 7); /* Pack eight 5-bit values into byte array. */ - b[0] = (t0 >> 0) | (t1 << 5); - b[1] = (t1 >> 3) | (t2 << 2) | (t3 << 7); - b[2] = (t3 >> 1) | (t4 << 4); - b[3] = (t4 >> 4) | (t5 << 1) | (t6 << 6); - b[4] = (t6 >> 2) | (t7 << 3); + b[0] = (byte)((t0 >> 0) | (t1 << 5)); + b[1] = (byte)((t1 >> 3) | (t2 << 2) | (t3 << 7)); + b[2] = (byte)((t3 >> 1) | (t4 << 4)); + b[3] = (byte)((t4 >> 4) | (t5 << 1) | (t6 << 6)); + b[4] = (byte)((t6 >> 2) | (t7 << 3)); #endif /* Move over set bytes. */ @@ -5600,7 +5629,7 @@ void mlkem_compress_5(byte* b, sword16* p) * @return Decompressed value. */ #define DECOMP_4(p, i, j, t) \ - p[(i) + (j)] = ((word16)((t) * MLKEM_Q) + 8) >> 4 + p[(i) + (j)] = (sword16)(((word16)((t) * MLKEM_Q) + 8) >> 4) /* Decompress a 5 bit value. * @@ -5613,7 +5642,7 @@ void mlkem_compress_5(byte* b, sword16* p) * @return Decompressed value. */ #define DECOMP_5(p, i, j, t) \ - p[(i) + (j)] = (((word32)((t) & 0x1f) * MLKEM_Q) + 16) >> 5 + p[(i) + (j)] = (sword16)((((word32)((t) & 0x1f) * MLKEM_Q) + 16) >> 5) #if defined(WOLFSSL_KYBER512) || defined(WOLFSSL_WC_ML_KEM_512) || \ defined(WOLFSSL_KYBER768) || defined(WOLFSSL_WC_ML_KEM_768) @@ -5678,12 +5707,12 @@ static void mlkem_decompress_5_c(sword16* p, const byte* b) /* Extract out 8 values of 5 bits each. */ t[0] = (b[0] >> 0); - t[1] = (b[0] >> 5) | (b[1] << 3); + t[1] = (byte)((b[0] >> 5) | (b[1] << 3)); t[2] = (b[1] >> 2); - t[3] = (b[1] >> 7) | (b[2] << 1); - t[4] = (b[2] >> 4) | (b[3] << 4); + t[3] = (byte)((b[1] >> 7) | (b[2] << 1)); + t[4] = (byte)((b[2] >> 4) | (b[3] << 4)); t[5] = (b[3] >> 1); - t[6] = (b[3] >> 6) | (b[4] << 2); + t[6] = (byte)((b[3] >> 6) | (b[4] << 2)); t[7] = (b[4] >> 3); b += 5; @@ -5694,12 +5723,12 @@ static void mlkem_decompress_5_c(sword16* p, const byte* b) #else /* Extract out 8 values of 5 bits each. */ byte t0 = (b[0] >> 0); - byte t1 = (b[0] >> 5) | (b[1] << 3); + byte t1 = (byte)((b[0] >> 5) | (b[1] << 3)); byte t2 = (b[1] >> 2); - byte t3 = (b[1] >> 7) | (b[2] << 1); - byte t4 = (b[2] >> 4) | (b[3] << 4); + byte t3 = (byte)((b[1] >> 7) | (b[2] << 1)); + byte t4 = (byte)((b[2] >> 4) | (b[3] << 4)); byte t5 = (b[3] >> 1); - byte t6 = (b[3] >> 6) | (b[4] << 2); + byte t6 = (byte)((b[3] >> 6) | (b[4] << 2)); byte t7 = (b[4] >> 3); b += 5; @@ -5853,8 +5882,11 @@ void mlkem_from_msg(sword16* p, const byte* msg) * @param [in] j Index of bit in byte. */ #define TO_MSG_BIT(m, p, i, j) \ - (m)[i] |= ((word32)((MLKEM_V31_2 * (p)[8 * (i) + (j)]) + \ - MLKEM_V31_HALF) >> 31) << (j) + do { \ + word32 _t = ((((word32)(word16)((p)[8 * (i) + (j)])) * MLKEM_V31_2) + \ + MLKEM_V31_HALF) >> 31; \ + (m)[i] = (byte)((m)[i] | (byte)((_t & 1U) << (j))); \ + } while (0) #endif /* CONV_WITH_DIV */ @@ -6031,11 +6063,11 @@ static void mlkem_to_bytes_c(byte* b, sword16* p, int k) /* All values are now positive. */ for (i = 0; i < MLKEM_N / 2; i++) { - word16 t0 = p[2 * i]; - word16 t1 = p[2 * i + 1]; - b[3 * i + 0] = (t0 >> 0); - b[3 * i + 1] = (t0 >> 8) | t1 << 4; - b[3 * i + 2] = (t1 >> 4); + word16 t0 = (word16)p[2 * i]; + word16 t1 = (word16)p[2 * i + 1]; + b[3 * i + 0] = (byte)(t0 >> 0); + b[3 * i + 1] = (byte)((t0 >> 8) | (t1 << 4)); + b[3 * i + 2] = (byte)(t1 >> 4); } p += MLKEM_N; b += WC_ML_KEM_POLY_SIZE;