From 7a7c87c8dba5432fcbba98ef1e467d86a7b3456b Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 7 Jul 2026 21:24:10 +0000 Subject: [PATCH] Support post-quantum-only (ML-KEM + ML-DSA) TLS 1.3 builds Allow wolfSSL to build and run a quantum-safe-only TLS 1.3 stack - ML-KEM for key exchange and ML-DSA (FIPS 204) for authentication - with RSA, ECC and DH all disabled (the CNSA 2.0 / EO 14412 posture). Core enablement: - internal.h: the "No cipher suites available" #error is an authentication check, so treat Falcon and ML-DSA as valid signature algorithms. - ssl.c: the "No cipher suites defined" #error is a key-exchange check, so treat a usable standalone ML-KEM group as a valid key exchange (WOLFSSL_HAVE_MLKEM && !WOLFSSL_TLS_NO_MLKEM_STANDALONE). - internal.c: extend the CopyDecodedToX509 pkCurveOID guard to Falcon/ML-DSA to match the sibling struct-field guards. - tls13.c: silence an unused hashAlgo parameter in EncodeSigAlg and refresh a stale #endif comment. - asn.c: guard the RSA/ECC-only certificate signing callback helpers so cert generation compiles cleanly with RSA and ECC disabled, while keeping MakeSignatureCb available for the WOLFSSL_CERT_SIGN_CB (TPM/HSM) offload path. TLS 1.3 session-ticket resumption: - tls.c: advertise the psk_dhe_ke pre-shared-key exchange mode when a usable standalone ML-KEM group is available, not only for classic (EC)DHE groups. Without this an ML-KEM-only build fell back to psk_ke, the resumption key schedules diverged, and the first AEAD record failed to authenticate (AES_GCM_AUTH_E), breaking resumption whenever ECC and DH were disabled. Examples and tests: - test.h: default to TLS 1.3 when no classic authentication algorithm is built in (ML-DSA is TLS 1.3 only), factor the shared "no classic auth" condition into TEST_NO_CLASSIC_AUTH, and add ML-DSA cert macros that track the enabled level, target base path and PEM/DER encoding. These reuse the existing self-signed certs/mldsa material; no new certificate files are added. - client.c/server.c/echoclient.c/echoserver.c/test_tls13.c: add an ML-DSA branch to the certificate-selection ladders and stop forcing PSK when ML-DSA can authenticate. CI: - Add a PQC-only (RSA/ECC/DH-disabled, ML-KEM + ML-DSA, session tickets) entry to the pq-all.yml matrix so the build, a full TLS 1.3 handshake, and ML-KEM-only session-ticket resumption are exercised by make check. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01FnWzwJUrkZ7LroWXiQnM8S --- .github/workflows/pq-all.yml | 7 ++- examples/client/client.c | 7 ++- examples/echoclient/echoclient.c | 7 ++- examples/echoserver/echoserver.c | 15 +++++- examples/server/server.c | 7 ++- src/internal.c | 6 ++- src/ssl.c | 4 +- src/tls.c | 4 +- src/tls13.c | 4 +- tests/api/test_tls13.c | 3 ++ wolfcrypt/src/asn.c | 30 +++++++++++ wolfssl/internal.h | 3 +- wolfssl/test.h | 86 +++++++++++++++++++++++++++++--- 13 files changed, 162 insertions(+), 21 deletions(-) diff --git a/.github/workflows/pq-all.yml b/.github/workflows/pq-all.yml index 5b370e3f5f2..6d7c9a728df 100644 --- a/.github/workflows/pq-all.yml +++ b/.github/workflows/pq-all.yml @@ -225,7 +225,12 @@ jobs: {"name": "mldsa-verify-only-dynamic-keys", "minutes": 1.2, "configure": ["--disable-intelasm", "--enable-dilithium=44,65,87,verify-only", - "CPPFLAGS=-DWOLFSSL_MLDSA_DYNAMIC_KEYS"]} + "CPPFLAGS=-DWOLFSSL_MLDSA_DYNAMIC_KEYS"]}, + {"name": "pqc-only", "minutes": 2, + "comment": "PQC-only TLS 1.3: ML-KEM key exchange + ML-DSA auth with RSA, ECC and DH disabled (CNSA 2.0 / EO 14412). Session tickets exercise ML-KEM-only resumption.", + "configure": ["--enable-mlkem", "--enable-mldsa", + "--enable-tls-mlkem-standalone", "--enable-session-ticket", + "--disable-rsa", "--disable-ecc", "--disable-dh"]} ] EOF .github/scripts/parallel-make-check.py \ diff --git a/examples/client/client.c b/examples/client/client.c index 64958f2091e..f95f138b4a1 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -2405,6 +2405,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) verifyCert = caEd448CertFile; ourCert = cliEd448CertFile; ourKey = cliEd448KeyFile; + #elif defined(WOLFSSL_HAVE_MLDSA) + verifyCert = caMldsaCertFile; + ourCert = cliMldsaCertFile; + ourKey = cliMldsaKeyFile; #else verifyCert = NULL; ourCert = NULL; @@ -3477,8 +3481,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif -#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ - !defined(HAVE_ED448) +#if defined(TEST_NO_CLASSIC_AUTH) && !defined(WOLFSSL_HAVE_MLDSA) if (!usePsk) { usePsk = 1; } diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index b35fd3c2c43..9b108f37487 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -121,8 +121,8 @@ void echoclient_test(void* args) #ifdef WOLFSSL_LEANPSK doPSK = 1; #endif -#if defined(NO_CERTS) || (defined(NO_RSA) && !defined(HAVE_ECC) && \ - !defined(HAVE_ED25519) && !defined(HAVE_ED448)) +#if defined(NO_CERTS) || \ + (defined(TEST_NO_CLASSIC_AUTH) && !defined(WOLFSSL_HAVE_MLDSA)) doPSK = 1; #endif (void)doPSK; @@ -160,6 +160,9 @@ void echoclient_test(void* args) #elif defined(HAVE_ED448) if (SSL_CTX_load_verify_locations(ctx, caEd448CertFile, 0) != WOLFSSL_SUCCESS) err_sys("can't load ca file, Please run from wolfSSL home dir"); + #elif defined(WOLFSSL_HAVE_MLDSA) + if (SSL_CTX_load_verify_locations(ctx, caMldsaCertFile, 0) != WOLFSSL_SUCCESS) + err_sys("can't load ca file, Please run from wolfSSL home dir"); #endif #elif !defined(NO_CERTS) if (!doPSK) diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index c6e368033e1..a18f4226dfb 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -124,8 +124,7 @@ THREAD_RETURN WOLFSSL_THREAD echoserver_test(void* args) ((func_args*)args)->return_code = -1; /* error state */ #if defined(NO_CERTS) || defined(WOLFSSL_LEANPSK) || \ - (defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ - !defined(HAVE_ED448)) + (defined(TEST_NO_CLASSIC_AUTH) && !defined(WOLFSSL_HAVE_MLDSA)) doPSK = 1; #else doPSK = 0; @@ -212,6 +211,18 @@ THREAD_RETURN WOLFSSL_THREAD echoserver_test(void* args) CERT_FILETYPE) != WOLFSSL_SUCCESS) err_sys("can't load server key file, " "Please run from wolfSSL home dir"); + #elif defined(WOLFSSL_HAVE_MLDSA) && !defined(NO_CERTS) && \ + !defined(WOLFSSL_SNIFFER) + /* ML-DSA (post-quantum-only) */ + if (wolfSSL_CTX_use_certificate_chain_file(ctx, mldsaCertFile) + != WOLFSSL_SUCCESS) + err_sys("can't load server cert file, " + "Please run from wolfSSL home dir"); + + if (wolfSSL_CTX_use_PrivateKey_file(ctx, mldsaKeyFile, CERT_FILETYPE) + != WOLFSSL_SUCCESS) + err_sys("can't load server key file, " + "Please run from wolfSSL home dir"); #elif defined(NO_CERTS) /* do nothing, just don't load cert files */ #else diff --git a/examples/server/server.c b/examples/server/server.c index 8ea1fcf6b4b..ec815659b88 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1895,6 +1895,10 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) verifyCert = cliEd448CertFile; ourCert = ed448CertFile; ourKey = ed448KeyFile; + #elif defined(WOLFSSL_HAVE_MLDSA) + verifyCert = caMldsaCertFile; + ourCert = mldsaCertFile; + ourKey = mldsaKeyFile; #else verifyCert = NULL; ourCert = NULL; @@ -2948,8 +2952,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) } #endif -#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ - !defined(HAVE_ED448) +#if defined(TEST_NO_CLASSIC_AUTH) && !defined(WOLFSSL_HAVE_MLDSA) if (!usePsk) { usePsk = 1; } diff --git a/src/internal.c b/src/internal.c index 8c73463766b..69695a688d0 100644 --- a/src/internal.c +++ b/src/internal.c @@ -14531,9 +14531,11 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) ret = MEMORY_E; } #endif -#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \ + defined(HAVE_FALCON) || defined(WOLFSSL_HAVE_MLDSA) x509->pkCurveOID = dCert->pkCurveOID; -#endif /* HAVE_ECC || HAVE_CURVE25519 || HAVE_CURVE448 */ +#endif /* HAVE_ECC || HAVE_ED25519 || HAVE_ED448 || HAVE_FALCON || + * WOLFSSL_HAVE_MLDSA */ #ifdef WOLFSSL_DUAL_ALG_CERTS /* Copy over alternative sig and pubkey. In this case we will allocate new diff --git a/src/ssl.c b/src/ssl.c index dbc39dcc1e7..c964a19af89 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -49,7 +49,9 @@ #if !defined(WOLFSSL_ALLOW_NO_SUITES) && !defined(WOLFCRYPT_ONLY) #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \ && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \ - && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) + && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \ + && (!defined(WOLFSSL_HAVE_MLKEM) || \ + defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)) #error "No cipher suites defined because DH disabled, ECC disabled, " \ "and no static suites defined. Please see top of README" #endif diff --git a/src/tls.c b/src/tls.c index 2bad38b1c06..a546b0e9ac2 100644 --- a/src/tls.c +++ b/src/tls.c @@ -16642,7 +16642,9 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) modes = 1 << PSK_KE; } #if !defined(NO_DH) || defined(HAVE_ECC) || \ - defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) || \ + (defined(WOLFSSL_HAVE_MLKEM) && \ + !defined(WOLFSSL_TLS_NO_MLKEM_STANDALONE)) if (!ssl->options.noPskDheKe) { modes |= 1 << PSK_DHE_KE; } diff --git a/src/tls13.c b/src/tls13.c index a20b6ec9e21..5dc2ef0c350 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -8696,6 +8696,7 @@ static WC_INLINE void EncodeSigAlg(const WOLFSSL * ssl, byte hashAlgo, byte hsType, byte* output) { (void)ssl; + (void)hashAlgo; switch (hsType) { #ifdef HAVE_ECC case ecc_dsa_sa_algo: @@ -11864,7 +11865,8 @@ static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, return ret; } -#endif /* !NO_RSA || HAVE_ECC */ +#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 || HAVE_ED448 || + * HAVE_FALCON || WOLFSSL_HAVE_MLDSA */ #endif /* !NO_CERTS */ /* Parse and handle a TLS v1.3 Finished message. diff --git a/tests/api/test_tls13.c b/tests/api/test_tls13.c index eb9e0d5bbe1..cbb1de75e35 100644 --- a/tests/api/test_tls13.c +++ b/tests/api/test_tls13.c @@ -84,6 +84,9 @@ int test_tls13_apis(void) #elif defined(HAVE_ED448) const char* ourCert = ed448CertFile; const char* ourKey = ed448KeyFile; +#elif defined(WOLFSSL_HAVE_MLDSA) + const char* ourCert = mldsaCertFile; + const char* ourKey = mldsaKeyFile; #endif #endif #endif diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5d961fc9aaf..5a13899b58d 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -28648,11 +28648,24 @@ static int SetValidity(byte* before, byte* after, int daysValid) #if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ) +/* MakeSignatureCb is used both by MakeSignature() (local RSA/ECC signing) and + * by the public wc_SignCert_cb() offload path (WOLFSSL_CERT_SIGN_CB), so it + * must be available whenever either of those is compiled in. */ +#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)) || \ + defined(WOLFSSL_CERT_SIGN_CB) /* Forward declaration for internal use */ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf, word32 sz, byte* sig, word32 sigSz, int sigAlgoType, int keyType, wc_SignCertCb signCb, void* signCtx, WC_RNG* rng, void* heap); +#endif /* (!NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY && !WOLFSSL_RSA_VERIFY_ONLY) || + * (HAVE_ECC && HAVE_ECC_SIGN) || WOLFSSL_CERT_SIGN_CB */ +/* InternalSignCb is only used by MakeSignature()'s local signing path. */ +#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)) /* Internal context for default signing operations (when no callback provided) */ typedef struct { void* key; @@ -28739,6 +28752,8 @@ static int InternalSignCb(const byte* in, word32 inLen, return ret; } +#endif /* (!NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY && !WOLFSSL_RSA_VERIFY_ONLY) || + * (HAVE_ECC && HAVE_ECC_SIGN) */ #endif /* WOLFSSL_CERT_GEN || WOLFSSL_CERT_REQ */ @@ -29018,10 +29033,13 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, word32 sz, { int ret = 0; + (void)certSignCtx; (void)buf; (void)sz; (void)sig; (void)sigSz; + (void)rsaKey; + (void)eccKey; (void)ed25519Key; (void)ed448Key; (void)falconKey; @@ -29030,6 +29048,7 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, word32 sz, (void)lmsKey; (void)xmssKey; (void)rng; + (void)sigAlgoType; (void)heap; /* For RSA and ECC, use the callback path to eliminate duplication */ @@ -29145,7 +29164,12 @@ static int MakeSignature(CertSignCtx* certSignCtx, const byte* buf, word32 sz, if (ret == -1) ret = ALGO_ID_E; +#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)) exit_ms: +#endif /* (!NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY && !WOLFSSL_RSA_VERIFY_ONLY) || + * (HAVE_ECC && HAVE_ECC_SIGN) */ if (ret < 0) { WOLFSSL_ERROR_VERBOSE(ret); } @@ -30141,6 +30165,10 @@ int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, #if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_REQ) +#if (!defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) && \ + !defined(WOLFSSL_RSA_VERIFY_ONLY)) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_SIGN)) || \ + defined(WOLFSSL_CERT_SIGN_CB) /* Internal function to create signature using callback * This allows external signing implementations (e.g., TPM, HSM) without * requiring the crypto callback infrastructure. @@ -30273,6 +30301,8 @@ static int MakeSignatureCb(CertSignCtx* certSignCtx, const byte* buf, return ret; } +#endif /* (!NO_RSA && !WOLFSSL_RSA_PUBLIC_ONLY && !WOLFSSL_RSA_VERIFY_ONLY) || + * (HAVE_ECC && HAVE_ECC_SIGN) || WOLFSSL_CERT_SIGN_CB */ #endif /* WOLFSSL_CERT_GEN || WOLFSSL_CERT_REQ */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ebafb498af5..c6f22be57af 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -851,7 +851,8 @@ #if !defined(WOLFCRYPT_ONLY) && defined(NO_PSK) && \ (defined(NO_DH) || !defined(HAVE_ANON)) && \ defined(NO_RSA) && !defined(HAVE_ECC) && \ - !defined(HAVE_ED25519) && !defined(HAVE_ED448) + !defined(HAVE_ED25519) && !defined(HAVE_ED448) && \ + !defined(HAVE_FALCON) && !defined(WOLFSSL_HAVE_MLDSA) #error "No cipher suites available with this build" #endif diff --git a/wolfssl/test.h b/wolfssl/test.h index 97454e1702b..b7c6492e078 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -458,18 +458,35 @@ err_sys_with_errno(const char* msg) } while(0) -#ifndef WOLFSSL_NO_TLS12 -#define SERVER_DEFAULT_VERSION 3 -#else +/* True when no classic public-key authentication algorithm is compiled in + * (RSA, ECC, Ed25519 and Ed448 all disabled). Shared by the version-default + * logic below and the PSK-fallback logic in the client/server examples so the + * duplicated conditions cannot drift apart. */ +#if defined(NO_RSA) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) && \ + !defined(HAVE_ED448) + #define TEST_NO_CLASSIC_AUTH +#endif + +/* With no classic authentication algorithm, a certificate-authenticated + * handshake relies on a post-quantum signature (ML-DSA), which is TLS 1.3 + * only, so default the examples to TLS 1.3 for such post-quantum-only builds. + * A PSK-only build (no ML-DSA) keeps the historic TLS 1.2 default. */ +#if defined(WOLFSSL_NO_TLS12) || \ + (defined(TEST_NO_CLASSIC_AUTH) && defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_HAVE_MLDSA)) #define SERVER_DEFAULT_VERSION 4 +#else +#define SERVER_DEFAULT_VERSION 3 #endif #define SERVER_DTLS_DEFAULT_VERSION (-2) #define SERVER_INVALID_VERSION (-99) #define SERVER_DOWNGRADE_VERSION (-98) -#ifndef WOLFSSL_NO_TLS12 -#define CLIENT_DEFAULT_VERSION 3 -#else +#if defined(WOLFSSL_NO_TLS12) || \ + (defined(TEST_NO_CLASSIC_AUTH) && defined(WOLFSSL_TLS13) && \ + defined(WOLFSSL_HAVE_MLDSA)) #define CLIENT_DEFAULT_VERSION 4 +#else +#define CLIENT_DEFAULT_VERSION 3 #endif #define CLIENT_DTLS_DEFAULT_VERSION (-2) #define CLIENT_INVALID_VERSION (-99) @@ -679,6 +696,63 @@ err_sys_with_errno(const char* msg) #endif #endif +/* ML-DSA (FIPS 204) certificate material for post-quantum-only TLS 1.3 tests. + * The mldsa-cert files are self-signed, so the same file serves as both the + * peer certificate and the trust anchor (CA) used to verify it. + * + * Defined under the same WOLFSSL_HAVE_MLDSA condition the client/server example + * ladders reference these macros under, so definition and use cannot diverge. + * MLDSA_TEST_LEVEL/MLDSA_TEST_DIR are internal composition helpers: unlike the + * fixed cert paths above, the ML-DSA path depends on whichever level is built + * (WOLFSSL_HAVE_MLDSA does not imply a level) and on the target base path, so + * there is no single literal to inline. They are consumed by the mldsa*File + * macros at point of use and are therefore left defined. */ +#if defined(WOLFSSL_HAVE_MLDSA) + +#if !defined(WOLFSSL_NO_ML_DSA_65) + #define MLDSA_TEST_LEVEL "mldsa65" +#elif !defined(WOLFSSL_NO_ML_DSA_44) + #define MLDSA_TEST_LEVEL "mldsa44" +#elif !defined(WOLFSSL_NO_ML_DSA_87) + #define MLDSA_TEST_LEVEL "mldsa87" +#else + #error "WOLFSSL_HAVE_MLDSA is set but no ML-DSA parameter level is enabled" +#endif + +#if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL) + #define MLDSA_TEST_DIR "certs/mldsa/" +#elif defined(NETOS) && defined(HAVE_FIPS) + #define MLDSA_TEST_DIR FS_VOLUME1_DIR "certs/mldsa/" +#else + #define MLDSA_TEST_DIR "./certs/mldsa/" +#endif + +#ifdef WOLFSSL_PEM_TO_DER + #ifndef mldsaCertFile + #define mldsaCertFile MLDSA_TEST_DIR MLDSA_TEST_LEVEL "-cert.pem" + #endif + #ifndef mldsaKeyFile + #define mldsaKeyFile MLDSA_TEST_DIR MLDSA_TEST_LEVEL "-key.pem" + #endif +#else + #ifndef mldsaCertFile + #define mldsaCertFile MLDSA_TEST_DIR MLDSA_TEST_LEVEL "-cert.der" + #endif + #ifndef mldsaKeyFile + #define mldsaKeyFile MLDSA_TEST_DIR MLDSA_TEST_LEVEL "_priv-only.der" + #endif +#endif +#ifndef cliMldsaCertFile + #define cliMldsaCertFile mldsaCertFile +#endif +#ifndef cliMldsaKeyFile + #define cliMldsaKeyFile mldsaKeyFile +#endif +#ifndef caMldsaCertFile + #define caMldsaCertFile mldsaCertFile +#endif +#endif /* WOLFSSL_HAVE_MLDSA */ + #ifdef WOLFSSL_PEM_TO_DER #define CERT_FILETYPE WOLFSSL_FILETYPE_PEM #else