Emma Stensland 2026-09-17 10:29:37 -07:00 committed by GitHub
commit 0a3fe84f03
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 301 additions and 169 deletions

View File

@ -0,0 +1,131 @@
name: ML-DSA Composite Configs
# Builds wolfSSH in configurations where ML-DSA is on but some of the
# traditional halves are off, so the per-composite gates in
# wolfssh/internal.h are exercised in states where they differ from the
# all-on and all-off builds the other workflows cover.
on:
push:
branches: [ 'master', 'main', 'release/**' ]
pull_request:
branches: [ '*' ]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build_wolfssl:
name: Build wolfSSL
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout wolfSSL
uses: actions/checkout@v6
with:
repository: wolfssl/wolfssl
path: wolfssl
- name: Build wolfSSL
working-directory: ./wolfssl
run: |
./autogen.sh
./configure --enable-all --enable-mldsa --enable-ed25519-stream
make -j$(nproc)
sudo make install
sudo ldconfig
- name: tar build-dir
run: tar -zcf wolfssl-install.tgz /usr/local/lib/libwolfssl* /usr/local/include/wolfssl
- name: Upload built lib
uses: actions/upload-artifact@v7
with:
name: wolfssl-mldsa-composite
path: wolfssl-install.tgz
retention-days: 5
partial_config:
name: ${{ matrix.name }}
runs-on: ubuntu-latest
timeout-minutes: 30
needs: build_wolfssl
strategy:
fail-fast: false
matrix:
include:
# Only the Ed448 half is left, so exactly one composite survives.
- name: ed448-only
defines: -DWOLFSSH_NO_ECDSA_SHA2_NISTP256 -DWOLFSSH_NO_ECDSA_SHA2_NISTP384 -DWOLFSSH_NO_ED25519
expect: ssh-mldsa87-ed448@wolfssl.com
# ML-DSA is on but nothing pairs with it, so
# WOLFSSH_NO_MLDSA_COMPOSITES must be derived rather than given.
- name: no-pairing
defines: -DWOLFSSH_NO_ECDSA_SHA2_NISTP256 -DWOLFSSH_NO_ECDSA_SHA2_NISTP384 -DWOLFSSH_NO_ED25519 -DWOLFSSH_NO_MLDSA87
expect: ''
# Directly sets one per-composite gate instead of deriving it, with
# every other composite left enabled to expose a missed site.
# Also the only row to build --enable-ossh-certs, so it's the one
# that exercises the cannedKeyAlgoNamesHostKey gates.
- name: single-composite-gate
defines: -DWOLFSSH_NO_MLDSA44_ES256
configure_flags: --enable-ossh-certs
expect: ssh-mldsa44-ed25519@openssh.com ssh-mldsa65-ed25519@wolfssl.com ssh-mldsa65-es256@wolfssl.com ssh-mldsa87-ed448@wolfssl.com ssh-mldsa87-es384@wolfssl.com
# User turns every composite off while ML-DSA and all the
# traditional halves stay on; the six gates must follow.
- name: composites-off
defines: -DWOLFSSH_NO_MLDSA_COMPOSITES
expect: ''
steps:
- name: Checkout wolfSSH
uses: actions/checkout@v6
- name: Download wolfSSL
uses: actions/download-artifact@v8
with:
name: wolfssl-mldsa-composite
- name: Install wolfSSL
run: |
sudo tar -zxf wolfssl-install.tgz -C /
sudo ldconfig
- name: Build wolfSSH
run: |
./autogen.sh
./configure --enable-all ${{ matrix.configure_flags }} CPPFLAGS="${{ matrix.defines }}"
make -j$(nproc)
# The client's -E list is what gets negotiated; the composites in it
# must be exactly the ones the gates leave enabled.
- name: Check negotiated composites
run: |
out=$(./examples/client/client -E -u "${USER:-runner}" 2>&1)
# Require evidence the client actually ran and printed its algo
# list, so a crash or missing-lib failure can't pass vacuously
# by producing an empty composite list.
echo "$out" | grep -q '^Set Key: '
keys=$(echo "$out" | sed -n 's/^Set Key: //p')
# ML-DSA itself must be on, or an empty composite list proves nothing.
echo "$keys" | grep -q 'ssh-mldsa-44'
got=$(echo "$keys" | tr ',' '\n' | { grep -o 'ssh-mldsa[0-9][0-9]-.*' || true; } | sort -u | tr '\n' ' ' | sed 's/ $//')
echo "composites offered: '$got'"
test "$got" = "${{ matrix.expect }}"
# api/testsuite/regress still build (check_PROGRAMS is unconditional)
# but are left out of TESTS: they need the NISTP256 sample keys and
# certs, which ed448-only/no-pairing/composites-off disable.
- name: Run tests that do not need the disabled algorithms
run: |
timeout -k 30 600 make check -j$(nproc) TESTS="tests/unit.test tests/kex.test tests/auth.test apps/wolfsshd/test/test_configuration"
- name: Print test logs on failure
if: failure()
run: |
echo "=== test-suite.log ==="
cat test-suite.log || true
for f in tests/*.log apps/wolfsshd/test/*.log; do
echo "=== $f ==="; cat "$f" || true
done

View File

@ -147,13 +147,27 @@ int main(void)
#ifndef WOLFSSH_NO_MLDSA
printf("MLDSA\n");
#endif
/* Same guard as cannedKeyAlgoNamesHostKey in src/internal.c: composites
* as a whole can be compiled out, and this one needs the ECDSA half. */
#if !defined(WOLFSSH_NO_MLDSA_COMPOSITES) && \
!defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
printf("MLDSA_COMPOSITES\n");
#endif
#ifndef WOLFSSH_NO_MLDSA44_ES256
printf("MLDSA44_ES256\n");
#endif
#ifndef WOLFSSH_NO_MLDSA65_ES256
printf("MLDSA65_ES256\n");
#endif
#ifndef WOLFSSH_NO_MLDSA87_ES384
printf("MLDSA87_ES384\n");
#endif
#ifndef WOLFSSH_NO_MLDSA44_ED25519
printf("MLDSA44_ED25519\n");
#endif
#ifndef WOLFSSH_NO_MLDSA65_ED25519
printf("MLDSA65_ED25519\n");
#endif
#ifndef WOLFSSH_NO_MLDSA87_ED448
printf("MLDSA87_ED448\n");
#endif
/* Applications. */
#ifdef WOLFSSH_SSHCLIENT

View File

@ -3082,26 +3082,22 @@ static int test_CheckAuthKeysLineTypes(void)
#endif
#endif
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
"ssh-mldsa44-es256@wolfssl.com",
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
"ssh-mldsa65-es256@wolfssl.com",
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
"ssh-mldsa87-es384@wolfssl.com",
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
"ssh-mldsa44-ed25519@openssh.com",
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
"ssh-mldsa65-ed25519@wolfssl.com",
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
"ssh-mldsa87-ed448@wolfssl.com",
#endif
};
@ -3264,9 +3260,9 @@ static int test_CheckAuthKeysLineMaxSz(void)
#if !defined(WOLFSSH_NO_MLDSA87)
keySz = WC_MLDSA_87_PUB_KEY_SIZE + COMPOSITE_MAX_TRAD_PUB_SZ;
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
type = "ssh-mldsa87-es384@wolfssl.com";
#elif defined(HAVE_ED448)
#elif !defined(WOLFSSH_NO_MLDSA87_ED448)
type = "ssh-mldsa87-ed448@wolfssl.com";
#else
type = "ssh-mldsa-87";
@ -3274,9 +3270,9 @@ static int test_CheckAuthKeysLineMaxSz(void)
#endif
#elif !defined(WOLFSSH_NO_MLDSA65)
keySz = WC_MLDSA_65_PUB_KEY_SIZE + COMPOSITE_MAX_TRAD_PUB_SZ;
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
type = "ssh-mldsa65-es256@wolfssl.com";
#elif !defined(WOLFSSH_NO_ED25519) && !defined(NO_SHA512)
#elif !defined(WOLFSSH_NO_MLDSA65_ED25519)
type = "ssh-mldsa65-ed25519@wolfssl.com";
#else
type = "ssh-mldsa-65";
@ -3284,9 +3280,9 @@ static int test_CheckAuthKeysLineMaxSz(void)
#endif
#else
keySz = WC_MLDSA_44_PUB_KEY_SIZE + COMPOSITE_MAX_TRAD_PUB_SZ;
#if !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
type = "ssh-mldsa44-es256@wolfssl.com";
#elif !defined(WOLFSSH_NO_ED25519) && !defined(NO_SHA512)
#elif !defined(WOLFSSH_NO_MLDSA44_ED25519)
type = "ssh-mldsa44-ed25519@openssh.com";
#else
type = "ssh-mldsa-44";

View File

@ -2438,39 +2438,32 @@ typedef struct {
const char* label;
} MlDsaCompositeEntry;
/* NULL-terminated so the table is never empty if composites are compiled
* out or ECDSA and Ed25519/Ed448 are both disabled */
/* NULL-terminated so the table is never empty. */
static const MlDsaCompositeEntry mldsaCompositeEntries[] = {
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
{ "mldsa44-ed25519", "./keys/server-key-mldsa44ed25519",
"ML-DSA-44+Ed25519" },
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
{ "mldsa44-es256", "./keys/server-key-mldsa44es256",
"ML-DSA-44+ES256" },
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
{ "mldsa65-ed25519", "./keys/server-key-mldsa65ed25519",
"ML-DSA-65+Ed25519" },
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
{ "mldsa65-es256", "./keys/server-key-mldsa65es256",
"ML-DSA-65+ES256" },
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
{ "mldsa87-ed448", "./keys/server-key-mldsa87ed448",
"ML-DSA-87+Ed448" },
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
{ "mldsa87-es384", "./keys/server-key-mldsa87es384",
"ML-DSA-87+ES384" },
#endif
#endif /* !WOLFSSH_NO_MLDSA_COMPOSITES */
{ NULL, NULL, NULL }
};

View File

@ -213,6 +213,13 @@ Flags:
Set for ML-DSA-65.
WOLFSSH_NO_MLDSA87
Set for ML-DSA-87.
WOLFSSH_NO_MLDSA44_ES256, WOLFSSH_NO_MLDSA65_ES256,
WOLFSSH_NO_MLDSA87_ES384, WOLFSSH_NO_MLDSA44_ED25519,
WOLFSSH_NO_MLDSA65_ED25519, WOLFSSH_NO_MLDSA87_ED448
Set when the ML-DSA level or the traditional algorithm it pairs with is
disabled. Set to disable that one composite.
WOLFSSH_NO_MLDSA_COMPOSITES
Set when every composite above is disabled. Set to disable them all.
WOLFSSH_NO_ECDSA
Set when ECC is disabled. Set to disable use of ECDSA server and user
authentication.
@ -1121,30 +1128,24 @@ static const char cannedKexAlgoNames[] =
/* ML-DSA listed first (post-quantum priority), then ECDSA, ED25519, RSA. */
static const char cannedKeyAlgoNames[] =
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
"ssh-mldsa87-ed448@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
"ssh-mldsa87-es384@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
"ssh-mldsa65-ed25519@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
"ssh-mldsa65-es256@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
"ssh-mldsa44-ed25519@openssh.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
"ssh-mldsa44-es256@wolfssl.com,"
#endif
#endif /* !WOLFSSH_NO_MLDSA_COMPOSITES */
#ifndef WOLFSSH_NO_MLDSA87
"ssh-mldsa-87,"
#endif
@ -1230,30 +1231,24 @@ static const char cannedKeyAlgoNames[] =
* ("*-cert-v01@openssh.com") names: host-cert verification is unimplemented, so
* a client must not advertise them as host keys. Keep plain/X.509 in sync. */
static const char cannedKeyAlgoNamesHostKey[] =
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
"ssh-mldsa87-ed448@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
"ssh-mldsa87-es384@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
"ssh-mldsa65-ed25519@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
"ssh-mldsa65-es256@wolfssl.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
"ssh-mldsa44-ed25519@openssh.com,"
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
"ssh-mldsa44-es256@wolfssl.com,"
#endif
#endif /* !WOLFSSH_NO_MLDSA_COMPOSITES */
#ifndef WOLFSSH_NO_MLDSA87
"ssh-mldsa-87,"
#endif
@ -3811,30 +3806,24 @@ static const NameIdPair NameIdMap[] = {
#ifndef WOLFSSH_NO_MLDSA44
{ ID_MLDSA44, TYPE_KEY, "ssh-mldsa-44" },
#endif
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
{ ID_MLDSA44_ES256, TYPE_KEY, "ssh-mldsa44-es256@wolfssl.com" },
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
{ ID_MLDSA65_ES256, TYPE_KEY, "ssh-mldsa65-es256@wolfssl.com" },
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
{ ID_MLDSA87_ES384, TYPE_KEY, "ssh-mldsa87-es384@wolfssl.com" },
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
{ ID_MLDSA44_ED25519, TYPE_KEY, "ssh-mldsa44-ed25519@openssh.com" },
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
{ ID_MLDSA65_ED25519, TYPE_KEY, "ssh-mldsa65-ed25519@wolfssl.com" },
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
{ ID_MLDSA87_ED448, TYPE_KEY, "ssh-mldsa87-ed448@wolfssl.com" },
#endif
#endif /* !WOLFSSH_NO_MLDSA_COMPOSITES */
#ifndef WOLFSSH_NO_MLDSA65
{ ID_MLDSA65, TYPE_KEY, "ssh-mldsa-65" },
#endif
@ -5983,30 +5972,24 @@ static const byte cannedKeyAlgoClient[] = {
#endif /* WOLFSSH_NO_SSH_RSA_SHA1 */
#endif /* WOLFSSH_NO_SHA1_SOFT_DISABLE */
#endif /* WOLFSSH_CERTS */
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
ID_MLDSA87_ED448,
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
ID_MLDSA87_ES384,
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
ID_MLDSA65_ED25519,
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
ID_MLDSA65_ES256,
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
ID_MLDSA44_ED25519,
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
ID_MLDSA44_ES256,
#endif
#endif /* !WOLFSSH_NO_MLDSA_COMPOSITES */
#ifndef WOLFSSH_NO_MLDSA87
ID_MLDSA87,
#endif
@ -24380,7 +24363,7 @@ int WS_GetCompositeParams(byte keyId, CompositeParams* params)
return WS_NOT_COMPILED;
#else
switch (keyId) {
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
case ID_MLDSA44_ES256:
params->mldsaLevel = WC_ML_DSA_44;
params->mldsaSigSz = WC_MLDSA_44_SIG_SIZE;
@ -24398,8 +24381,7 @@ int WS_GetCompositeParams(byte keyId, CompositeParams* params)
params->eccCurveId = ECC_SECP256R1;
break;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
case ID_MLDSA65_ES256:
params->mldsaLevel = WC_ML_DSA_65;
params->mldsaSigSz = WC_MLDSA_65_SIG_SIZE;
@ -24417,8 +24399,7 @@ int WS_GetCompositeParams(byte keyId, CompositeParams* params)
params->eccCurveId = ECC_SECP256R1;
break;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
case ID_MLDSA87_ES384:
params->mldsaLevel = WC_ML_DSA_87;
params->mldsaSigSz = WC_MLDSA_87_SIG_SIZE;
@ -24436,8 +24417,7 @@ int WS_GetCompositeParams(byte keyId, CompositeParams* params)
params->eccCurveId = ECC_SECP384R1;
break;
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
case ID_MLDSA44_ED25519:
params->mldsaLevel = WC_ML_DSA_44;
params->mldsaSigSz = WC_MLDSA_44_SIG_SIZE;
@ -24452,8 +24432,7 @@ int WS_GetCompositeParams(byte keyId, CompositeParams* params)
params->tradPrivSz = ED25519_KEY_SIZE;
break;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
case ID_MLDSA65_ED25519:
params->mldsaLevel = WC_ML_DSA_65;
params->mldsaSigSz = WC_MLDSA_65_SIG_SIZE;
@ -24468,7 +24447,7 @@ int WS_GetCompositeParams(byte keyId, CompositeParams* params)
params->tradPrivSz = ED25519_KEY_SIZE;
break;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
case ID_MLDSA87_ED448:
params->mldsaLevel = WC_ML_DSA_87;
params->mldsaSigSz = WC_MLDSA_87_SIG_SIZE;
@ -24855,7 +24834,7 @@ static const CompositeTradOps compositeEd25519Ops = {
};
#endif /* !WOLFSSH_NO_ED25519 */
#ifdef HAVE_ED448
#ifdef WOLFSSH_HAVE_COMPOSITE_ED448
/* returns 0 on success, negative wc_ed448_init_ex() code on failure */
static int CompositeEd448Init(void* key, void* heap)
{
@ -24962,7 +24941,7 @@ static const CompositeTradOps compositeEd448Ops = {
CompositeEd448Sign, CompositeEd448Verify,
TRAD_TYPE_ED448
};
#endif /* HAVE_ED448 */
#endif /* WOLFSSH_HAVE_COMPOSITE_ED448 */
/* returns matching CompositeTradOps for tradType, NULL if unsupported */
const CompositeTradOps* WS_GetTradOps(byte tradType)
@ -24976,7 +24955,7 @@ const CompositeTradOps* WS_GetTradOps(byte tradType)
case TRAD_TYPE_ED25519:
return &compositeEd25519Ops;
#endif
#ifdef HAVE_ED448
#ifdef WOLFSSH_HAVE_COMPOSITE_ED448
case TRAD_TYPE_ED448:
return &compositeEd448Ops;
#endif

View File

@ -376,7 +376,7 @@ int wolfSSH_MakeMlDsaKey(byte* out, word32 outSz, word32 level)
/* Build OpenSSH-key-v1 envelope. */
#if !defined(WOLFSSH_NO_MLDSA)
/* Guard matches MakeCompositeTradKey() callers to avoid unused warnings. */
#if !defined(WOLFSSH_NO_ED25519) || defined(HAVE_ED448) || \
#if !defined(WOLFSSH_NO_ED25519) || defined(WOLFSSH_HAVE_COMPOSITE_ED448) || \
!defined(WOLFSSH_NO_ECDSA)
/* Shared init/makeKey/export/free chain for traditional types. */
static int MakeCompositeTradKeyGeneric(const CompositeTradOps* ops, void* key,
@ -386,6 +386,7 @@ static int MakeCompositeTradKeyGeneric(const CompositeTradOps* ops, void* key,
int ret;
word32 sz;
/* NULL heap; the ops init with INVALID_DEVID, so keygen stays software. */
if (ops->init(key, NULL) != 0) {
return WS_CRYPTO_FAILED;
}
@ -434,7 +435,7 @@ static int MakeCompositeTradKey(WC_RNG* rng, const CompositeParams* params,
#endif
}
else if (params->tradType == TRAD_TYPE_ED448) {
#ifdef HAVE_ED448
#ifdef WOLFSSH_HAVE_COMPOSITE_ED448
ed448_key key;
ret = MakeCompositeTradKeyGeneric(ops, &key, rng, params, tradPub,
tradPriv);

View File

@ -518,39 +518,33 @@ int wolfSSH_KexTest(int argc, char** argv)
#ifndef WOLFSSH_NO_MLDSA87
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa-87"), EXIT_SUCCESS);
#endif
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
/* Uses the "@openssh.com" wire name that OpenSSH negotiates for this
* algorithm, matching what wolfSSH now emits (see NameIdMap). */
AssertIntEQ(
wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa44-ed25519@openssh.com"),
EXIT_SUCCESS);
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa44-es256@wolfssl.com"),
EXIT_SUCCESS);
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa65-es256@wolfssl.com"),
EXIT_SUCCESS);
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa65-ed25519@wolfssl.com"),
EXIT_SUCCESS);
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa87-es384@wolfssl.com"),
EXIT_SUCCESS);
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
AssertIntEQ(wolfSSH_KexTest_MlDsaHostKey("ssh-mldsa87-ed448@wolfssl.com"),
EXIT_SUCCESS);
#endif
#endif /* WOLFSSH_NO_MLDSA_COMPOSITES */
AssertIntEQ(wolfSSH_Cleanup(), WS_SUCCESS);

View File

@ -1164,33 +1164,28 @@ static int test_MlDsaKeyGen(void)
#ifndef WOLFSSH_NO_MLDSA_COMPOSITES
static int test_MlDsaCompositeKeyGen(void)
{
/* NULL-terminated so the table is never empty if ECDSA and
* Ed25519/Ed448 are all disabled while ML-DSA is enabled */
/* NULL-terminated sentinel bounds the loop. */
static const struct {
word32 level;
word32 tradType;
const char* name;
} params[] = {
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
{ WOLFSSH_MLDSAKEY_44, WOLFSSH_COMPOSITE_TRAD_ED25519, "44+Ed25519" },
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
{ WOLFSSH_MLDSAKEY_44, WOLFSSH_COMPOSITE_TRAD_ECDSA, "44+ES256" },
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
{ WOLFSSH_MLDSAKEY_65, WOLFSSH_COMPOSITE_TRAD_ED25519, "65+Ed25519" },
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
{ WOLFSSH_MLDSAKEY_65, WOLFSSH_COMPOSITE_TRAD_ECDSA, "65+ES256" },
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
{ WOLFSSH_MLDSAKEY_87, WOLFSSH_COMPOSITE_TRAD_ED448, "87+Ed448" },
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
{ WOLFSSH_MLDSAKEY_87, WOLFSSH_COMPOSITE_TRAD_ECDSA, "87+ES384" },
#endif
{ 0, 0, NULL }
@ -1218,7 +1213,7 @@ static int test_MlDsaCompositeKeyGen(void)
sz = wolfSSH_MakeMlDsaCompositeKey(buf, bufSz, params[i].level,
params[i].tradType);
if (sz < 0) {
if (sz <= 0) {
printf("MlDsaCompositeKeyGen: MakeMlDsaCompositeKey %s "
"failed (%d)\n", params[i].name, sz);
WFREE(buf, NULL, DYNTYPE_BUFFER);
@ -1255,7 +1250,7 @@ static int test_MlDsaCompositeKeyGen(void)
}
}
if (result == 0 && firstSz > 0) {
if (result == 0) {
/* out == NULL is a size query for a valid (level, tradType): it
* should return the required buffer size, not an error. */
int sz = wolfSSH_MakeMlDsaCompositeKey(NULL, 0, firstLevel,
@ -1289,8 +1284,7 @@ static int test_MlDsaCompositeKeyGen(void)
}
}
/* Skip undersize check if no algorithms enabled. */
if (result == 0 && firstSz > 0) {
if (result == 0) {
byte* buf = (byte*)WMALLOC(firstSz, NULL, DYNTYPE_BUFFER);
if (buf == NULL) {
@ -15241,36 +15235,32 @@ done:
static int test_SignHMlDsaComposite(void)
{
int ret = 0;
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
ret = test_SignHMlDsaComposite_Params("ssh-mldsa44-es256@wolfssl.com",
ID_MLDSA44_ES256);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
ret = test_SignHMlDsaComposite_Params("ssh-mldsa65-es256@wolfssl.com",
ID_MLDSA65_ES256);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
ret = test_SignHMlDsaComposite_Params("ssh-mldsa87-es384@wolfssl.com",
ID_MLDSA87_ES384);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
ret = test_SignHMlDsaComposite_Params("ssh-mldsa44-ed25519@openssh.com",
ID_MLDSA44_ED25519);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
ret = test_SignHMlDsaComposite_Params("ssh-mldsa65-ed25519@wolfssl.com",
ID_MLDSA65_ED25519);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
ret = test_SignHMlDsaComposite_Params("ssh-mldsa87-ed448@wolfssl.com",
ID_MLDSA87_ED448);
if (ret != 0) return ret;
@ -15278,8 +15268,7 @@ static int test_SignHMlDsaComposite(void)
return 0;
}
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
/* Reset a WS_KeySignature to a clean slate before (re)using it as an
* ID_MLDSA44_ED25519 decode target. */
static void MlDsaTest_ResetKeySig(WS_KeySignature* keySig)
@ -15293,8 +15282,7 @@ static void MlDsaTest_ResetKeySig(WS_KeySignature* keySig)
/* E2E parser test with minimal OpenSSH-key-v1 envelope. */
static int test_PrepareUserAuthRequestMlDsaComposite_OpenSshEnvelope(void)
{
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
static const char keyTypeName[] = "ssh-mldsa44-ed25519@openssh.com";
static const char magic[] = "openssh-key-v1";
static const char none[] = "none";
@ -15751,41 +15739,37 @@ done:
static int test_BuildUserAuthRequestMlDsaComposite(void)
{
int ret = 0;
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
ret = test_BuildUserAuthRequestMlDsaComposite_Params(
"ssh-mldsa44-es256@wolfssl.com", WOLFSSH_MLDSAKEY_44,
WOLFSSH_COMPOSITE_TRAD_ECDSA, ID_MLDSA44_ES256);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
ret = test_BuildUserAuthRequestMlDsaComposite_Params(
"ssh-mldsa65-es256@wolfssl.com", WOLFSSH_MLDSAKEY_65,
WOLFSSH_COMPOSITE_TRAD_ECDSA, ID_MLDSA65_ES256);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
ret = test_BuildUserAuthRequestMlDsaComposite_Params(
"ssh-mldsa87-es384@wolfssl.com", WOLFSSH_MLDSAKEY_87,
WOLFSSH_COMPOSITE_TRAD_ECDSA, ID_MLDSA87_ES384);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
ret = test_BuildUserAuthRequestMlDsaComposite_Params(
"ssh-mldsa44-ed25519@openssh.com", WOLFSSH_MLDSAKEY_44,
WOLFSSH_COMPOSITE_TRAD_ED25519, ID_MLDSA44_ED25519);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
ret = test_BuildUserAuthRequestMlDsaComposite_Params(
"ssh-mldsa65-ed25519@wolfssl.com", WOLFSSH_MLDSAKEY_65,
WOLFSSH_COMPOSITE_TRAD_ED25519, ID_MLDSA65_ED25519);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
ret = test_BuildUserAuthRequestMlDsaComposite_Params(
"ssh-mldsa87-ed448@wolfssl.com", WOLFSSH_MLDSAKEY_87,
WOLFSSH_COMPOSITE_TRAD_ED448, ID_MLDSA87_ED448);
@ -15800,7 +15784,7 @@ static int test_BuildUserAuthRequestMlDsaComposite(void)
static int test_DoUserAuthRequestMlDsaComposite(void)
{
int ret = 0;
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256)
#ifndef WOLFSSH_NO_MLDSA44_ES256
ret = test_DoUserAuthRequestMlDsaComposite_Params("ssh-mldsa44-es256@wolfssl.com",
ID_MLDSA44_ES256, 0);
if (ret != 0) return ret;
@ -15817,8 +15801,7 @@ static int test_DoUserAuthRequestMlDsaComposite(void)
ID_MLDSA44_ES256, 4);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ES256
ret = test_DoUserAuthRequestMlDsaComposite_Params("ssh-mldsa65-es256@wolfssl.com",
ID_MLDSA65_ES256, 0);
if (ret != 0) return ret;
@ -15835,8 +15818,7 @@ static int test_DoUserAuthRequestMlDsaComposite(void)
ID_MLDSA65_ES256, 4);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && \
!defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) && !defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA87_ES384
ret = test_DoUserAuthRequestMlDsaComposite_Params("ssh-mldsa87-es384@wolfssl.com",
ID_MLDSA87_ES384, 0);
if (ret != 0) return ret;
@ -15853,8 +15835,7 @@ static int test_DoUserAuthRequestMlDsaComposite(void)
ID_MLDSA87_ES384, 4);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA44) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA44_ED25519
ret = test_DoUserAuthRequestMlDsaComposite_Params(
"ssh-mldsa44-ed25519@openssh.com", ID_MLDSA44_ED25519, 0);
if (ret != 0) return ret;
@ -15871,8 +15852,7 @@ static int test_DoUserAuthRequestMlDsaComposite(void)
"ssh-mldsa44-ed25519@openssh.com", ID_MLDSA44_ED25519, 4);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA65) && !defined(WOLFSSH_NO_ED25519) && \
!defined(NO_SHA512)
#ifndef WOLFSSH_NO_MLDSA65_ED25519
ret = test_DoUserAuthRequestMlDsaComposite_Params("ssh-mldsa65-ed25519@wolfssl.com",
ID_MLDSA65_ED25519, 0);
if (ret != 0) return ret;
@ -15889,7 +15869,7 @@ static int test_DoUserAuthRequestMlDsaComposite(void)
ID_MLDSA65_ED25519, 4);
if (ret != 0) return ret;
#endif
#if !defined(WOLFSSH_NO_MLDSA87) && defined(HAVE_ED448)
#ifndef WOLFSSH_NO_MLDSA87_ED448
ret = test_DoUserAuthRequestMlDsaComposite_Params("ssh-mldsa87-ed448@wolfssl.com",
ID_MLDSA87_ED448, 0);
if (ret != 0) return ret;

View File

@ -153,6 +153,8 @@ extern "C" {
#endif
#if !defined(HAVE_ED25519) \
|| !defined(HAVE_ED25519_SIGN) \
|| !defined(HAVE_ED25519_VERIFY) \
|| !defined(WOLFSSL_ED25519_STREAMING_VERIFY) \
|| !defined(HAVE_ED25519_KEY_IMPORT) \
|| !defined(HAVE_ED25519_KEY_EXPORT)
@ -381,11 +383,53 @@ extern "C" {
#undef WOLFSSH_NO_PUBKEY_AUTH
#define WOLFSSH_NO_PUBKEY_AUTH
#endif
/* A composite needs an ML-DSA level and a traditional algorithm. */
#if (defined(WOLFSSH_NO_MLDSA44) && defined(WOLFSSH_NO_MLDSA65) && \
defined(WOLFSSH_NO_MLDSA87)) || \
(defined(WOLFSSH_NO_ECDSA) && defined(WOLFSSH_NO_ED25519) && \
!defined(HAVE_ED448))
/* Ed448 needs all five sub-feature macros, not just HAVE_ED448; every
* composite Ed448 site (sizing, key storage, keygen, sign/verify) keys
* off this one macro so the condition can't drift between copies. */
#if defined(HAVE_ED448) && defined(HAVE_ED448_SIGN) && \
defined(HAVE_ED448_VERIFY) && defined(HAVE_ED448_KEY_IMPORT) && \
defined(HAVE_ED448_KEY_EXPORT)
#define WOLFSSH_HAVE_COMPOSITE_ED448
#endif
/* One gate per ML-DSA composite: the ML-DSA level plus the traditional
* algorithm it pairs with. Every composite site keys off these, so the
* pairing rules live here only. WOLFSSH_NO_MLDSA_COMPOSITES turns them all
* off, and is set when none are left. It governs negotiation and key
* loading only, not code size footprint. */
#if defined(WOLFSSH_NO_MLDSA44) || defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
defined(WOLFSSH_NO_MLDSA_COMPOSITES)
#undef WOLFSSH_NO_MLDSA44_ES256
#define WOLFSSH_NO_MLDSA44_ES256
#endif
#if defined(WOLFSSH_NO_MLDSA65) || defined(WOLFSSH_NO_ECDSA_SHA2_NISTP256) || \
!defined(WOLFSSL_SHA512) || defined(WOLFSSH_NO_MLDSA_COMPOSITES)
#undef WOLFSSH_NO_MLDSA65_ES256
#define WOLFSSH_NO_MLDSA65_ES256
#endif
#if defined(WOLFSSH_NO_MLDSA87) || defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) || \
!defined(WOLFSSL_SHA512) || defined(WOLFSSH_NO_MLDSA_COMPOSITES)
#undef WOLFSSH_NO_MLDSA87_ES384
#define WOLFSSH_NO_MLDSA87_ES384
#endif
#if defined(WOLFSSH_NO_MLDSA44) || defined(WOLFSSH_NO_ED25519) || \
!defined(WOLFSSL_SHA512) || defined(WOLFSSH_NO_MLDSA_COMPOSITES)
#undef WOLFSSH_NO_MLDSA44_ED25519
#define WOLFSSH_NO_MLDSA44_ED25519
#endif
#if defined(WOLFSSH_NO_MLDSA65) || defined(WOLFSSH_NO_ED25519) || \
!defined(WOLFSSL_SHA512) || defined(WOLFSSH_NO_MLDSA_COMPOSITES)
#undef WOLFSSH_NO_MLDSA65_ED25519
#define WOLFSSH_NO_MLDSA65_ED25519
#endif
#if defined(WOLFSSH_NO_MLDSA87) || !defined(WOLFSSH_HAVE_COMPOSITE_ED448) || \
defined(WOLFSSH_NO_MLDSA_COMPOSITES)
#undef WOLFSSH_NO_MLDSA87_ED448
#define WOLFSSH_NO_MLDSA87_ED448
#endif
#if defined(WOLFSSH_NO_MLDSA44_ES256) && defined(WOLFSSH_NO_MLDSA65_ES256) && \
defined(WOLFSSH_NO_MLDSA87_ES384) && \
defined(WOLFSSH_NO_MLDSA44_ED25519) && \
defined(WOLFSSH_NO_MLDSA65_ED25519) && defined(WOLFSSH_NO_MLDSA87_ED448)
#undef WOLFSSH_NO_MLDSA_COMPOSITES
#define WOLFSSH_NO_MLDSA_COMPOSITES
#endif
@ -1504,11 +1548,11 @@ typedef struct WS_MlDsaCompositeBody {
#ifndef WOLFSSH_NO_ED25519
ed25519_key ed25519;
#endif
#ifdef HAVE_ED448
#ifdef WOLFSSH_HAVE_COMPOSITE_ED448
ed448_key ed448;
#endif
#if defined(WOLFSSH_NO_ECDSA) && defined(WOLFSSH_NO_ED25519) && \
!defined(HAVE_ED448)
!defined(WOLFSSH_HAVE_COMPOSITE_ED448)
/* keep union non-empty */
byte placeholder;
#endif
@ -1575,13 +1619,13 @@ typedef struct WS_KeySignature {
/* max trad pubkey size */
#define COMPOSITE_MAX_TRAD_PUB_SZ (1 + (2 * ECC_P384_COORD_SZ))
/* max trad privkey size */
#ifdef HAVE_ED448
#ifdef WOLFSSH_HAVE_COMPOSITE_ED448
#define COMPOSITE_MAX_TRAD_PRIV_SZ ED448_KEY_SIZE
#else
#define COMPOSITE_MAX_TRAD_PRIV_SZ ECC_P384_COORD_SZ
#endif
/* max trad sig size */
#ifdef HAVE_ED448
#ifdef WOLFSSH_HAVE_COMPOSITE_ED448
#define COMPOSITE_MAX_TRAD_SIG_SZ ED448_SIG_SIZE
#else
#define COMPOSITE_MAX_TRAD_SIG_SZ (2 * (LENGTH_SZ + ECC_P384_COORD_SZ + 1))