Skip to content

Commit 9851ab2

Browse files
author
Emma Stensland
committed
internal: derive WOLFSSH_NO_MLDSA when every level is off
With 44, 65 and 87 all off, keygen and key loading still took ML-DSA.
1 parent 6ed8e12 commit 9851ab2

4 files changed

Lines changed: 62 additions & 7 deletions

File tree

‎.github/workflows/mldsa-composite-config.yml‎

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: ML-DSA Composite Configs
22

3-
# Builds wolfSSH with ML-DSA on but traditional halves off, exercising the
3+
# Builds wolfSSH with ML-DSA levels or traditional halves off, exercising the
44
# per-composite gates in wolfssh/internal.h in states the all-on and all-off
55
# builds never reach.
66

@@ -68,6 +68,16 @@ jobs:
6868
defines: -DWOLFSSH_NO_ECDSA_SHA2_NISTP256 -DWOLFSSH_NO_ECDSA_SHA2_NISTP384 -DWOLFSSH_NO_ED25519 -DWOLFSSH_NO_MLDSA87
6969
expect: ''
7070
exclude_tests: tests/api.test tests/testsuite.test
71+
# No level left, so WOLFSSH_NO_MLDSA itself must be derived;
72+
# test_MlDsaLevelsDisabled in unit.test checks that.
73+
- name: no-levels
74+
defines: -DWOLFSSH_NO_MLDSA44 -DWOLFSSH_NO_MLDSA65 -DWOLFSSH_NO_MLDSA87
75+
mldsa_off: true
76+
expect: ''
77+
# ML-DSA-44 alone off; its composites go, 65 and 87 stay.
78+
- name: no-mldsa44
79+
defines: -DWOLFSSH_NO_MLDSA44
80+
expect: ssh-mldsa65-ed25519@wolfssl.com ssh-mldsa65-es256@wolfssl.com ssh-mldsa87-ed448@wolfssl.com ssh-mldsa87-es384@wolfssl.com
7181
# Sets one gate directly rather than deriving it, the rest left on
7282
# to expose a missed site. Only row with --enable-ossh-certs.
7383
- name: single-composite-gate
@@ -143,14 +153,20 @@ jobs:
143153
# A crash must not pass vacuously with an empty list.
144154
echo "$out" | grep -q '^Set Key: '
145155
keys=$(echo "$out" | sed -n 's/^Set Key: //p')
146-
# ML-DSA itself must be on, or an empty composite list proves nothing.
147-
echo "$keys" | grep -q 'ssh-mldsa-44'
156+
acc=$(echo "$out" | sed -n 's/^Set Key Accepted: //p')
157+
if [ '${{ matrix.mldsa_off }}' = 'true' ]; then
158+
# No ML-DSA name of any kind in either table. A bare `!` does
159+
# not trip bash -e, so fail explicitly.
160+
if echo "$keys,$acc" | grep -q 'ssh-mldsa'; then exit 1; fi
161+
else
162+
# ML-DSA itself must be on, or an empty composite list proves nothing.
163+
echo "$keys" | grep -q 'ssh-mldsa-[0-9]'
164+
fi
148165
got=$(echo "$keys" | tr ',' '\n' | { grep -o 'ssh-mldsa[0-9][0-9]-.*' || true; } | LC_ALL=C sort -u | tr '\n' ' ' | sed 's/ $//')
149166
echo "composites offered: '$got'"
150167
test "$got" = "${{ matrix.expect }}"
151168
# Second table, gated in parallel with the host-key one.
152169
echo "$out" | grep -q '^Set Key Accepted: '
153-
acc=$(echo "$out" | sed -n 's/^Set Key Accepted: //p')
154170
gotAcc=$(echo "$acc" | tr ',' '\n' | { grep -o 'ssh-mldsa[0-9][0-9]-.*' || true; } | LC_ALL=C sort -u | tr '\n' ' ' | sed 's/ $//')
155171
echo "composites accepted: '$gotAcc'"
156172
test "$gotAcc" = "${{ matrix.expect }}"

‎src/internal.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,8 @@ typedef char wolfSSH_channel_overhead_check[
211211
HAVE_ED25519_KEY_EXPORT are all set. Disables ssh-ed25519 server and
212212
user authentication as well as the ML-DSA+Ed25519 composites.
213213
WOLFSSH_NO_MLDSA
214-
Set when MLDSA is disabled and/or not included in wolfssl downloaded.
214+
Set when MLDSA is disabled and/or not included in wolfssl downloaded,
215+
or when WOLFSSH_NO_MLDSA44, 65 and 87 are all set.
215216
WOLFSSH_NO_MLDSA44
216217
Set for ML-DSA-44.
217218
WOLFSSH_NO_MLDSA65

‎tests/unit.c‎

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,6 +1031,12 @@ static int test_KDF(void)
10311031
}
10321032

10331033

1034+
/* Checks the internal.h derivation directly, independent of any API. */
1035+
#if defined(WOLFSSH_NO_MLDSA44) && defined(WOLFSSH_NO_MLDSA65) && \
1036+
defined(WOLFSSH_NO_MLDSA87) && !defined(WOLFSSH_NO_MLDSA)
1037+
#error "WOLFSSH_NO_MLDSA must follow from all three levels being off"
1038+
#endif
1039+
10341040
/* Key Generation Unit Test */
10351041

10361042
#ifdef WOLFSSH_KEYGEN
@@ -1369,6 +1375,25 @@ static int test_MlDsaCompositesDisabled(void)
13691375

13701376
#endif /* WOLFSSH_NO_MLDSA */
13711377

1378+
/* API behaviour with no level built; the #error above covers the derivation. */
1379+
#if defined(WOLFSSH_NO_MLDSA44) && defined(WOLFSSH_NO_MLDSA65) && \
1380+
defined(WOLFSSH_NO_MLDSA87)
1381+
static int test_MlDsaLevelsDisabled(void)
1382+
{
1383+
byte dummy[1];
1384+
int result = 0;
1385+
int sz;
1386+
1387+
sz = wolfSSH_MakeMlDsaKey(dummy, sizeof(dummy), WOLFSSH_MLDSAKEY_44);
1388+
if (sz != WS_NOT_COMPILED) {
1389+
printf("MlDsaLevelsDisabled: MakeMlDsaKey wrong result %d\n", sz);
1390+
result = -133;
1391+
}
1392+
1393+
return result;
1394+
}
1395+
#endif
1396+
13721397
#endif /* WOLFSSH_KEYGEN */
13731398

13741399
/* Exercises the malformed-input error paths of the WOLFSSH_FORMAT_OPENSSH
@@ -13223,7 +13248,7 @@ static int test_KEY_clean_osshCert(void)
1322313248
}
1322413249
#endif /* WOLFSSH_OSSH_CERTS */
1322513250

13226-
#if !defined(WOLFSSH_NO_MLDSA)
13251+
#if !defined(WOLFSSH_NO_MLDSA) && !defined(WOLFSSH_NO_MLDSA44)
1322713252
/* keys/server-key-mldsa44.der - MlDsa44 OneAsymmetricKey */
1322813253
static const byte unitTestMlDsaPrivKey[] = {
1322913254
0x30, 0x82, 0x0a, 0x3e, 0x02, 0x01, 0x00, 0x30,
@@ -13556,7 +13581,7 @@ static const byte unitTestMlDsaPrivKey[] = {
1355613581
0x27, 0xfe, 0x32, 0x26, 0x3c, 0x33, 0x83, 0xda,
1355713582
0x18, 0xc9
1355813583
};
13559-
#endif /* !WOLFSSH_NO_MLDSA */
13584+
#endif /* !WOLFSSH_NO_MLDSA && !WOLFSSH_NO_MLDSA44 */
1356013585

1356113586
#ifndef WOLFSSH_NO_ECDSA
1356213587
/* P-256 DER with the OID last byte changed 0x07 -> 0x01 (secp192r1).
@@ -23755,6 +23780,13 @@ int wolfSSH_UnitTest(int argc, char** argv)
2375523780
testResult = testResult || unitResult;
2375623781
#endif /* WOLFSSH_NO_MLDSA_COMPOSITES */
2375723782
#endif
23783+
#if defined(WOLFSSH_NO_MLDSA44) && defined(WOLFSSH_NO_MLDSA65) && \
23784+
defined(WOLFSSH_NO_MLDSA87)
23785+
unitResult = test_MlDsaLevelsDisabled();
23786+
printf("MlDsaLevelsDisabled: %s\n",
23787+
(unitResult == 0 ? "SUCCESS" : "FAILED"));
23788+
testResult = testResult || unitResult;
23789+
#endif
2375823790
#endif /* WOLFSSH_KEYGEN */
2375923791
unitResult = test_OpenSshPemNegative();
2376023792
printf("OpenSshPemNegative: %s\n",

‎wolfssh/internal.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ extern "C" {
146146
#define WOLFSSH_NO_MLDSA65
147147
#define WOLFSSH_NO_MLDSA87
148148
#endif
149+
/* Each composite needs its ML-DSA level, so no level leaves no ML-DSA. */
150+
#if defined(WOLFSSH_NO_MLDSA44) && defined(WOLFSSH_NO_MLDSA65) && \
151+
defined(WOLFSSH_NO_MLDSA87)
152+
#undef WOLFSSH_NO_MLDSA
153+
#define WOLFSSH_NO_MLDSA
154+
#endif
149155

150156
#ifdef NO_SHA
151157
#undef WOLFSSH_NO_SHA1

0 commit comments

Comments
 (0)