Skip to content

Commit 5aeba12

Browse files
committed
BCJSSE: Initial implementation of SLH-DSA support
- see draft-reddy-tls-slhdsa-01
1 parent b5fb497 commit 5aeba12

22 files changed

+1074
-61
lines changed

tls/src/main/java/org/bouncycastle/jsse/provider/FipsUtils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,18 @@ static boolean isFipsSignatureScheme(int signatureScheme)
218218
case SignatureScheme.mldsa44:
219219
case SignatureScheme.mldsa65:
220220
case SignatureScheme.mldsa87:
221+
case SignatureScheme.DRAFT_slhdsa_sha2_128s:
222+
case SignatureScheme.DRAFT_slhdsa_sha2_128f:
223+
case SignatureScheme.DRAFT_slhdsa_sha2_192s:
224+
case SignatureScheme.DRAFT_slhdsa_sha2_192f:
225+
case SignatureScheme.DRAFT_slhdsa_sha2_256s:
226+
case SignatureScheme.DRAFT_slhdsa_sha2_256f:
227+
case SignatureScheme.DRAFT_slhdsa_shake_128s:
228+
case SignatureScheme.DRAFT_slhdsa_shake_128f:
229+
case SignatureScheme.DRAFT_slhdsa_shake_192s:
230+
case SignatureScheme.DRAFT_slhdsa_shake_192f:
231+
case SignatureScheme.DRAFT_slhdsa_shake_256s:
232+
case SignatureScheme.DRAFT_slhdsa_shake_256f:
221233
default:
222234
return false;
223235
}

tls/src/main/java/org/bouncycastle/jsse/provider/ProvAlgorithmChecker.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,24 @@ private static Map<String, String> createSigAlgNames()
6868

6969
names.put(EdECObjectIdentifiers.id_Ed25519.getId(), "Ed25519");
7070
names.put(EdECObjectIdentifiers.id_Ed448.getId(), "Ed448");
71+
7172
names.put(NISTObjectIdentifiers.id_ml_dsa_44.getId(), "ML-DSA-44");
7273
names.put(NISTObjectIdentifiers.id_ml_dsa_65.getId(), "ML-DSA-65");
7374
names.put(NISTObjectIdentifiers.id_ml_dsa_87.getId(), "ML-DSA-87");
75+
76+
names.put(NISTObjectIdentifiers.id_slh_dsa_sha2_128s.getId(), "SLH-DSA-SHA2-128S");
77+
names.put(NISTObjectIdentifiers.id_slh_dsa_sha2_128f.getId(), "SLH-DSA-SHA2-128F");
78+
names.put(NISTObjectIdentifiers.id_slh_dsa_sha2_192s.getId(), "SLH-DSA-SHA2-192S");
79+
names.put(NISTObjectIdentifiers.id_slh_dsa_sha2_192f.getId(), "SLH-DSA-SHA2-192F");
80+
names.put(NISTObjectIdentifiers.id_slh_dsa_sha2_256s.getId(), "SLH-DSA-SHA2-256S");
81+
names.put(NISTObjectIdentifiers.id_slh_dsa_sha2_256f.getId(), "SLH-DSA-SHA2-256F");
82+
names.put(NISTObjectIdentifiers.id_slh_dsa_shake_128s.getId(), "SLH-DSA-SHAKE-128S");
83+
names.put(NISTObjectIdentifiers.id_slh_dsa_shake_128f.getId(), "SLH-DSA-SHAKE-128F");
84+
names.put(NISTObjectIdentifiers.id_slh_dsa_shake_192s.getId(), "SLH-DSA-SHAKE-192S");
85+
names.put(NISTObjectIdentifiers.id_slh_dsa_shake_192f.getId(), "SLH-DSA-SHAKE-192F");
86+
names.put(NISTObjectIdentifiers.id_slh_dsa_shake_256s.getId(), "SLH-DSA-SHAKE-256S");
87+
names.put(NISTObjectIdentifiers.id_slh_dsa_shake_256f.getId(), "SLH-DSA-SHAKE-256F");
88+
7489
names.put(OIWObjectIdentifiers.dsaWithSHA1.getId(), "SHA1withDSA");
7590
names.put(X9ObjectIdentifiers.id_dsa_with_sha1.getId(), "SHA1withDSA");
7691

tls/src/main/java/org/bouncycastle/jsse/provider/ProvX509KeyManager.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,19 @@ private static Map<String, PublicKeyFilter> createFiltersClient()
162162
addFilter(filters, "ML-DSA-65");
163163
addFilter(filters, "ML-DSA-87");
164164

165+
addFilter(filters, "SLH-DSA-SHA2-128S");
166+
addFilter(filters, "SLH-DSA-SHA2-128F");
167+
addFilter(filters, "SLH-DSA-SHA2-192S");
168+
addFilter(filters, "SLH-DSA-SHA2-192F");
169+
addFilter(filters, "SLH-DSA-SHA2-256S");
170+
addFilter(filters, "SLH-DSA-SHA2-256F");
171+
addFilter(filters, "SLH-DSA-SHAKE-128S");
172+
addFilter(filters, "SLH-DSA-SHAKE-128F");
173+
addFilter(filters, "SLH-DSA-SHAKE-192S");
174+
addFilter(filters, "SLH-DSA-SHAKE-192F");
175+
addFilter(filters, "SLH-DSA-SHAKE-256S");
176+
addFilter(filters, "SLH-DSA-SHAKE-256F");
177+
165178
addECFilter13(filters, NamedGroup.brainpoolP256r1tls13);
166179
addECFilter13(filters, NamedGroup.brainpoolP384r1tls13);
167180
addECFilter13(filters, NamedGroup.brainpoolP512r1tls13);
@@ -191,6 +204,19 @@ private static Map<String, PublicKeyFilter> createFiltersServer()
191204
addFilter(filters, "ML-DSA-65");
192205
addFilter(filters, "ML-DSA-87");
193206

207+
addFilter(filters, "SLH-DSA-SHA2-128S");
208+
addFilter(filters, "SLH-DSA-SHA2-128F");
209+
addFilter(filters, "SLH-DSA-SHA2-192S");
210+
addFilter(filters, "SLH-DSA-SHA2-192F");
211+
addFilter(filters, "SLH-DSA-SHA2-256S");
212+
addFilter(filters, "SLH-DSA-SHA2-256F");
213+
addFilter(filters, "SLH-DSA-SHAKE-128S");
214+
addFilter(filters, "SLH-DSA-SHAKE-128F");
215+
addFilter(filters, "SLH-DSA-SHAKE-192S");
216+
addFilter(filters, "SLH-DSA-SHAKE-192F");
217+
addFilter(filters, "SLH-DSA-SHAKE-256S");
218+
addFilter(filters, "SLH-DSA-SHAKE-256F");
219+
194220
addECFilter13(filters, NamedGroup.brainpoolP256r1tls13);
195221
addECFilter13(filters, NamedGroup.brainpoolP384r1tls13);
196222
addECFilter13(filters, NamedGroup.brainpoolP512r1tls13);

tls/src/main/java/org/bouncycastle/jsse/provider/SignatureSchemeInfo.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,19 @@ private enum All
6969
mldsa65(SignatureScheme.mldsa65, "ML-DSA-65", false),
7070
mldsa87(SignatureScheme.mldsa87, "ML-DSA-87", false),
7171

72+
slhdsa_sha2_128s(SignatureScheme.DRAFT_slhdsa_sha2_128s, "SLH-DSA-SHA2-128S", false),
73+
slhdsa_sha2_128f(SignatureScheme.DRAFT_slhdsa_sha2_128f, "SLH-DSA-SHA2-128F", false),
74+
slhdsa_sha2_192s(SignatureScheme.DRAFT_slhdsa_sha2_192s, "SLH-DSA-SHA2-192S", false),
75+
slhdsa_sha2_192f(SignatureScheme.DRAFT_slhdsa_sha2_192f, "SLH-DSA-SHA2-192F", false),
76+
slhdsa_sha2_256s(SignatureScheme.DRAFT_slhdsa_sha2_256s, "SLH-DSA-SHA2-256S", false),
77+
slhdsa_sha2_256f(SignatureScheme.DRAFT_slhdsa_sha2_256f, "SLH-DSA-SHA2-256F", false),
78+
slhdsa_shake_128s(SignatureScheme.DRAFT_slhdsa_shake_128s, "SLH-DSA-SHAKE-128S", false),
79+
slhdsa_shake_128f(SignatureScheme.DRAFT_slhdsa_shake_128f, "SLH-DSA-SHAKE-128F", false),
80+
slhdsa_shake_192s(SignatureScheme.DRAFT_slhdsa_shake_192s, "SLH-DSA-SHAKE-192S", false),
81+
slhdsa_shake_192f(SignatureScheme.DRAFT_slhdsa_shake_192f, "SLH-DSA-SHAKE-192F", false),
82+
slhdsa_shake_256s(SignatureScheme.DRAFT_slhdsa_shake_256s, "SLH-DSA-SHAKE-256S", false),
83+
slhdsa_shake_256f(SignatureScheme.DRAFT_slhdsa_shake_256f, "SLH-DSA-SHAKE-256F", false),
84+
7285
sm2sig_sm3(SignatureScheme.sm2sig_sm3, "SM3withSM2", "EC"),
7386

7487
// Deprecated: only for certs in 1.3
@@ -577,10 +590,26 @@ private static int[] createCandidates(Map<Integer, SignatureSchemeInfo> index, S
577590
private static int[] createCandidatesDefault()
578591
{
579592
All[] values = All.values();
580-
int[] result = new int[values.length];
581-
for (int i = 0; i < values.length; ++i)
593+
int count = values.length, pos = 0;
594+
int[] result = new int[count];
595+
for (int i = 0; i < count; ++i)
596+
{
597+
int signatureScheme = values[i].signatureScheme;
598+
599+
/*
600+
* SLH-DSA signing is quite slow; users will most likely be interested in it for the certificate
601+
* chain, so we'll leave it to them to configure signature_algorithms_cert.
602+
*/
603+
if (!SignatureScheme.isSLHDSA(signatureScheme))
604+
{
605+
result[pos++] = signatureScheme;
606+
}
607+
}
608+
if (pos < count)
582609
{
583-
result[i] = values[i].signatureScheme;
610+
int[] tmp = new int[pos];
611+
System.arraycopy(result, 0, tmp, 0, pos);
612+
return tmp;
584613
}
585614
return result;
586615
}

tls/src/main/java/org/bouncycastle/tls/SignatureAndHashAlgorithm.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@ public class SignatureAndHashAlgorithm
3636
create(SignatureScheme.rsa_pss_pss_sha384);
3737
public static final SignatureAndHashAlgorithm rsa_pss_pss_sha512 =
3838
create(SignatureScheme.rsa_pss_pss_sha512);
39+
public static final SignatureAndHashAlgorithm slhdsa_sha2_128s = create(SignatureScheme.DRAFT_slhdsa_sha2_128s);
40+
public static final SignatureAndHashAlgorithm slhdsa_sha2_128f = create(SignatureScheme.DRAFT_slhdsa_sha2_128f);
41+
public static final SignatureAndHashAlgorithm slhdsa_sha2_192s = create(SignatureScheme.DRAFT_slhdsa_sha2_192s);
42+
public static final SignatureAndHashAlgorithm slhdsa_sha2_192f = create(SignatureScheme.DRAFT_slhdsa_sha2_192f);
43+
public static final SignatureAndHashAlgorithm slhdsa_sha2_256s = create(SignatureScheme.DRAFT_slhdsa_sha2_256s);
44+
public static final SignatureAndHashAlgorithm slhdsa_sha2_256f = create(SignatureScheme.DRAFT_slhdsa_sha2_256f);
45+
public static final SignatureAndHashAlgorithm slhdsa_shake_128s = create(SignatureScheme.DRAFT_slhdsa_shake_128s);
46+
public static final SignatureAndHashAlgorithm slhdsa_shake_128f = create(SignatureScheme.DRAFT_slhdsa_shake_128f);
47+
public static final SignatureAndHashAlgorithm slhdsa_shake_192s = create(SignatureScheme.DRAFT_slhdsa_shake_192s);
48+
public static final SignatureAndHashAlgorithm slhdsa_shake_192f = create(SignatureScheme.DRAFT_slhdsa_shake_192f);
49+
public static final SignatureAndHashAlgorithm slhdsa_shake_256s = create(SignatureScheme.DRAFT_slhdsa_shake_256s);
50+
public static final SignatureAndHashAlgorithm slhdsa_shake_256f = create(SignatureScheme.DRAFT_slhdsa_shake_256f);
3951

4052
public static SignatureAndHashAlgorithm getInstance(short hashAlgorithm, short signatureAlgorithm)
4153
{

tls/src/main/java/org/bouncycastle/tls/SignatureScheme.java

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,22 @@ public class SignatureScheme
5959
/** @deprecated Use 'mldsa87' instead. */
6060
public static final int DRAFT_mldsa87 = mldsa87;
6161

62+
/*
63+
* draft-reddy-tls-slhdsa-01
64+
*/
65+
public static final int DRAFT_slhdsa_sha2_128s = 0x0911;
66+
public static final int DRAFT_slhdsa_sha2_128f = 0x0912;
67+
public static final int DRAFT_slhdsa_sha2_192s = 0x0913;
68+
public static final int DRAFT_slhdsa_sha2_192f = 0x0914;
69+
public static final int DRAFT_slhdsa_sha2_256s = 0x0915;
70+
public static final int DRAFT_slhdsa_sha2_256f = 0x0916;
71+
public static final int DRAFT_slhdsa_shake_128s = 0x0917;
72+
public static final int DRAFT_slhdsa_shake_128f = 0x0918;
73+
public static final int DRAFT_slhdsa_shake_192s = 0x0919;
74+
public static final int DRAFT_slhdsa_shake_192f = 0x091A;
75+
public static final int DRAFT_slhdsa_shake_256s = 0x091B;
76+
public static final int DRAFT_slhdsa_shake_256f = 0x091C;
77+
6278
/*
6379
* RFC 8446 reserved for private use (0xFE00..0xFFFF)
6480
*/
@@ -87,6 +103,18 @@ public static int getCryptoHashAlgorithm(int signatureScheme)
87103
case mldsa44:
88104
case mldsa65:
89105
case mldsa87:
106+
case DRAFT_slhdsa_sha2_128s:
107+
case DRAFT_slhdsa_sha2_128f:
108+
case DRAFT_slhdsa_sha2_192s:
109+
case DRAFT_slhdsa_sha2_192f:
110+
case DRAFT_slhdsa_sha2_256s:
111+
case DRAFT_slhdsa_sha2_256f:
112+
case DRAFT_slhdsa_shake_128s:
113+
case DRAFT_slhdsa_shake_128f:
114+
case DRAFT_slhdsa_shake_192s:
115+
case DRAFT_slhdsa_shake_192f:
116+
case DRAFT_slhdsa_shake_256s:
117+
case DRAFT_slhdsa_shake_256f:
90118
return -1;
91119
case ecdsa_brainpoolP256r1tls13_sha256:
92120
case rsa_pss_pss_sha256:
@@ -169,6 +197,30 @@ public static String getName(int signatureScheme)
169197
return "mldsa65";
170198
case mldsa87:
171199
return "mldsa87";
200+
case DRAFT_slhdsa_sha2_128s:
201+
return "slhdsa_sha2_128s";
202+
case DRAFT_slhdsa_sha2_128f:
203+
return "slhdsa_sha2_128f";
204+
case DRAFT_slhdsa_sha2_192s:
205+
return "slhdsa_sha2_192s";
206+
case DRAFT_slhdsa_sha2_192f:
207+
return "slhdsa_sha2_192f";
208+
case DRAFT_slhdsa_sha2_256s:
209+
return "slhdsa_sha2_256s";
210+
case DRAFT_slhdsa_sha2_256f:
211+
return "slhdsa_sha2_256f";
212+
case DRAFT_slhdsa_shake_128s:
213+
return "slhdsa_shake_128s";
214+
case DRAFT_slhdsa_shake_128f:
215+
return "slhdsa_shake_128f";
216+
case DRAFT_slhdsa_shake_192s:
217+
return "slhdsa_shake_192s";
218+
case DRAFT_slhdsa_shake_192f:
219+
return "slhdsa_shake_192f";
220+
case DRAFT_slhdsa_shake_256s:
221+
return "slhdsa_shake_256s";
222+
case DRAFT_slhdsa_shake_256f:
223+
return "slhdsa_shake_256f";
172224
default:
173225
return "UNKNOWN";
174226
}
@@ -246,6 +298,30 @@ public static SignatureAndHashAlgorithm getSignatureAndHashAlgorithm(int signatu
246298
return SignatureAndHashAlgorithm.mldsa65;
247299
case mldsa87:
248300
return SignatureAndHashAlgorithm.mldsa87;
301+
case DRAFT_slhdsa_sha2_128s:
302+
return SignatureAndHashAlgorithm.slhdsa_sha2_128s;
303+
case DRAFT_slhdsa_sha2_128f:
304+
return SignatureAndHashAlgorithm.slhdsa_sha2_128f;
305+
case DRAFT_slhdsa_sha2_192s:
306+
return SignatureAndHashAlgorithm.slhdsa_sha2_192s;
307+
case DRAFT_slhdsa_sha2_192f:
308+
return SignatureAndHashAlgorithm.slhdsa_sha2_192f;
309+
case DRAFT_slhdsa_sha2_256s:
310+
return SignatureAndHashAlgorithm.slhdsa_sha2_256s;
311+
case DRAFT_slhdsa_sha2_256f:
312+
return SignatureAndHashAlgorithm.slhdsa_sha2_256f;
313+
case DRAFT_slhdsa_shake_128s:
314+
return SignatureAndHashAlgorithm.slhdsa_shake_128s;
315+
case DRAFT_slhdsa_shake_128f:
316+
return SignatureAndHashAlgorithm.slhdsa_shake_128f;
317+
case DRAFT_slhdsa_shake_192s:
318+
return SignatureAndHashAlgorithm.slhdsa_shake_192s;
319+
case DRAFT_slhdsa_shake_192f:
320+
return SignatureAndHashAlgorithm.slhdsa_shake_192f;
321+
case DRAFT_slhdsa_shake_256s:
322+
return SignatureAndHashAlgorithm.slhdsa_shake_256s;
323+
case DRAFT_slhdsa_shake_256f:
324+
return SignatureAndHashAlgorithm.slhdsa_shake_256f;
249325
default:
250326
return SignatureAndHashAlgorithm.getInstance(
251327
getHashAlgorithm(signatureScheme),
@@ -304,4 +380,26 @@ public static boolean isRSAPSS(int signatureScheme)
304380
return false;
305381
}
306382
}
383+
384+
public static boolean isSLHDSA(int signatureScheme)
385+
{
386+
switch (signatureScheme)
387+
{
388+
case DRAFT_slhdsa_sha2_128s:
389+
case DRAFT_slhdsa_sha2_128f:
390+
case DRAFT_slhdsa_sha2_192s:
391+
case DRAFT_slhdsa_sha2_192f:
392+
case DRAFT_slhdsa_sha2_256s:
393+
case DRAFT_slhdsa_sha2_256f:
394+
case DRAFT_slhdsa_shake_128s:
395+
case DRAFT_slhdsa_shake_128f:
396+
case DRAFT_slhdsa_shake_192s:
397+
case DRAFT_slhdsa_shake_192f:
398+
case DRAFT_slhdsa_shake_256s:
399+
case DRAFT_slhdsa_shake_256f:
400+
return true;
401+
default:
402+
return false;
403+
}
404+
}
307405
}

tls/src/main/java/org/bouncycastle/tls/TlsUtils.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,19 @@ private static Hashtable createCertSigAlgOIDs()
120120
addCertSigAlgOID(h, NISTObjectIdentifiers.id_ml_dsa_65, SignatureAndHashAlgorithm.mldsa65);
121121
addCertSigAlgOID(h, NISTObjectIdentifiers.id_ml_dsa_87, SignatureAndHashAlgorithm.mldsa87);
122122

123+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_sha2_128s, SignatureAndHashAlgorithm.slhdsa_sha2_128s);
124+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_sha2_128f, SignatureAndHashAlgorithm.slhdsa_sha2_128f);
125+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_sha2_192s, SignatureAndHashAlgorithm.slhdsa_sha2_192s);
126+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_sha2_192f, SignatureAndHashAlgorithm.slhdsa_sha2_192f);
127+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_sha2_256s, SignatureAndHashAlgorithm.slhdsa_sha2_256s);
128+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_sha2_256f, SignatureAndHashAlgorithm.slhdsa_sha2_256f);
129+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_shake_128s, SignatureAndHashAlgorithm.slhdsa_shake_128s);
130+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_shake_128f, SignatureAndHashAlgorithm.slhdsa_shake_128f);
131+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_shake_192s, SignatureAndHashAlgorithm.slhdsa_shake_192s);
132+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_shake_192f, SignatureAndHashAlgorithm.slhdsa_shake_192f);
133+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_shake_256s, SignatureAndHashAlgorithm.slhdsa_shake_256s);
134+
addCertSigAlgOID(h, NISTObjectIdentifiers.id_slh_dsa_shake_256f, SignatureAndHashAlgorithm.slhdsa_shake_256f);
135+
123136
addCertSigAlgOID(h, RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_256,
124137
SignatureAndHashAlgorithm.gostr34102012_256);
125138
addCertSigAlgOID(h, RosstandartObjectIdentifiers.id_tc26_signwithdigest_gost_3410_12_512,
@@ -1550,7 +1563,8 @@ static void verify12SignatureAlgorithm(SignatureAndHashAlgorithm signatureAlgori
15501563
int signatureScheme = SignatureScheme.from(signatureAlgorithm);
15511564

15521565
// TODO In future there might be more cases, so we'd need a more general method.
1553-
if (SignatureScheme.isMLDSA(signatureScheme))
1566+
if (SignatureScheme.isMLDSA(signatureScheme) ||
1567+
SignatureScheme.isSLHDSA(signatureScheme))
15541568
{
15551569
throw new TlsFatalAlert(alertDescription);
15561570
}

0 commit comments

Comments
 (0)