Skip to content

Commit 6aa5b57

Browse files
committed
BCJSSE: Support hybrid ECDHE-MLKEM groups
1 parent 23183cc commit 6aa5b57

File tree

1 file changed

+87
-25
lines changed

1 file changed

+87
-25
lines changed

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

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.bouncycastle.jsse.provider;
22

33
import java.security.AlgorithmParameters;
4+
import java.security.GeneralSecurityException;
45
import java.util.ArrayList;
56
import java.util.Collections;
67
import java.util.LinkedHashMap;
@@ -81,13 +82,19 @@ private enum All
8182
OQS_mlkem1024(NamedGroup.OQS_mlkem1024, "ML-KEM"),
8283
MLKEM512(NamedGroup.MLKEM512, "ML-KEM"),
8384
MLKEM768(NamedGroup.MLKEM768, "ML-KEM"),
84-
MLKEM1024(NamedGroup.MLKEM1024, "ML-KEM");
85+
MLKEM1024(NamedGroup.MLKEM1024, "ML-KEM"),
86+
87+
SecP256r1MLKEM768(NamedGroup.SecP256r1MLKEM768, "EC", "ML-KEM"),
88+
X25519MLKEM768(NamedGroup.X25519MLKEM768, "ML-KEM", "XDH"),
89+
SecP384r1MLKEM1024(NamedGroup.SecP384r1MLKEM1024, "EC", "ML-KEM");
8590

8691
private final int namedGroup;
8792
private final String name;
8893
private final String text;
89-
private final String jcaAlgorithm;
90-
private final String jcaGroup;
94+
private final String jcaAlgorithm1;
95+
private final String jcaAlgorithm2;
96+
private final String jcaGroup1;
97+
private final String jcaGroup2;
9198
private final boolean char2;
9299
private final boolean supportedPost13;
93100
private final boolean supportedPre13;
@@ -96,17 +103,45 @@ private enum All
96103

97104
private All(int namedGroup, String jcaAlgorithm)
98105
{
106+
if (NamedGroup.refersToASpecificHybrid(namedGroup))
107+
{
108+
throw new IllegalArgumentException("Non-hybrid constructor only");
109+
}
110+
99111
this.namedGroup = namedGroup;
100112
this.name = NamedGroup.getName(namedGroup);
101113
this.text = NamedGroup.getText(namedGroup);
102-
this.jcaAlgorithm = jcaAlgorithm;
103-
this.jcaGroup = NamedGroup.getStandardName(namedGroup);
114+
this.jcaAlgorithm1 = jcaAlgorithm;
115+
this.jcaAlgorithm2 = null;
116+
this.jcaGroup1 = NamedGroup.getStandardName(namedGroup);
117+
this.jcaGroup2 = null;
104118
this.supportedPost13 = NamedGroup.canBeNegotiated(namedGroup, ProtocolVersion.TLSv13);
105119
this.supportedPre13 = NamedGroup.canBeNegotiated(namedGroup, ProtocolVersion.TLSv12);
106120
this.char2 = NamedGroup.isChar2Curve(namedGroup);
107121
this.bitsECDH = NamedGroup.getCurveBits(namedGroup);
108122
this.bitsFFDHE = NamedGroup.getFiniteFieldBits(namedGroup);
109123
}
124+
125+
private All(int namedGroup, String jcaAlgorithm1, String jcaAlgorithm2)
126+
{
127+
if (!NamedGroup.refersToASpecificHybrid(namedGroup))
128+
{
129+
throw new IllegalArgumentException("Hybrid constructor only");
130+
}
131+
132+
this.namedGroup = namedGroup;
133+
this.name = NamedGroup.getName(namedGroup);
134+
this.text = NamedGroup.getText(namedGroup);
135+
this.jcaAlgorithm1 = jcaAlgorithm1;
136+
this.jcaAlgorithm2 = jcaAlgorithm2;
137+
this.jcaGroup1 = NamedGroup.getStandardName(NamedGroup.getHybridFirst(namedGroup));
138+
this.jcaGroup2 = NamedGroup.getStandardName(NamedGroup.getHybridSecond(namedGroup));
139+
this.supportedPost13 = NamedGroup.canBeNegotiated(namedGroup, ProtocolVersion.TLSv13);
140+
this.supportedPre13 = NamedGroup.canBeNegotiated(namedGroup, ProtocolVersion.TLSv12);
141+
this.char2 = false;
142+
this.bitsECDH = -1;
143+
this.bitsFFDHE = -1;
144+
}
110145
}
111146

112147
private static final int[] CANDIDATES_DEFAULT = {
@@ -439,23 +474,37 @@ private static void addNamedGroup(boolean isFipsContext, JcaTlsCrypto crypto, bo
439474

440475
boolean disable = (disableChar2 && all.char2) || (disableFFDHE && all.bitsFFDHE > 0);
441476

442-
boolean enabled = !disable && (null != all.jcaGroup) && crypto.hasNamedGroup(namedGroup);
477+
boolean enabled = !disable && (null != all.jcaGroup1) && (null == all.jcaAlgorithm2 || null != all.jcaGroup2)
478+
&& TlsUtils.isSupportedNamedGroup(crypto, namedGroup);
479+
480+
AlgorithmParameters algorithmParameters1 = null;
481+
AlgorithmParameters algorithmParameters2 = null;
443482

444-
AlgorithmParameters algorithmParameters = null;
445483
if (enabled)
446484
{
447-
// TODO[jsse] Consider also fetching 'jcaAlgorithm'
485+
// TODO[jsse] Consider also fetching 'jcaAlgorithm1', 'jcaAlgorithm2'
486+
448487
try
449488
{
450-
algorithmParameters = crypto.getNamedGroupAlgorithmParameters(namedGroup);
489+
if (NamedGroup.refersToASpecificHybrid(namedGroup))
490+
{
491+
algorithmParameters1 = getAlgorithmParameters(crypto, NamedGroup.getHybridFirst(namedGroup));
492+
algorithmParameters2 = getAlgorithmParameters(crypto, NamedGroup.getHybridSecond(namedGroup));
493+
}
494+
else
495+
{
496+
algorithmParameters1 = getAlgorithmParameters(crypto, namedGroup);
497+
}
451498
}
452499
catch (Exception e)
453500
{
454501
enabled = false;
502+
algorithmParameters1 = null;
503+
algorithmParameters2 = null;
455504
}
456505
}
457506

458-
NamedGroupInfo namedGroupInfo = new NamedGroupInfo(all, algorithmParameters, enabled);
507+
NamedGroupInfo namedGroupInfo = new NamedGroupInfo(all, algorithmParameters1, algorithmParameters2, enabled);
459508

460509
if (null != ng.put(namedGroup, namedGroupInfo))
461510
{
@@ -531,6 +580,12 @@ private static Map<Integer, NamedGroupInfo> createIndex(boolean isFipsContext, J
531580
return ng;
532581
}
533582

583+
private static AlgorithmParameters getAlgorithmParameters(JcaTlsCrypto crypto, int namedGroup)
584+
throws GeneralSecurityException
585+
{
586+
return crypto.getNamedGroupAlgorithmParameters(namedGroup);
587+
}
588+
534589
private static int getNamedGroupByName(String name)
535590
{
536591
for (All all : All.values())
@@ -589,13 +644,16 @@ private static boolean hasAnyECDSA(Map<Integer, NamedGroupInfo> local)
589644
}
590645

591646
private final All all;
592-
private final AlgorithmParameters algorithmParameters;
647+
private final AlgorithmParameters algorithmParameters1;
648+
private final AlgorithmParameters algorithmParameters2;
593649
private final boolean enabled;
594650

595-
NamedGroupInfo(All all, AlgorithmParameters algorithmParameters, boolean enabled)
651+
NamedGroupInfo(All all, AlgorithmParameters algorithmParameters1, AlgorithmParameters algorithmParameters2,
652+
boolean enabled)
596653
{
597654
this.all = all;
598-
this.algorithmParameters = algorithmParameters;
655+
this.algorithmParameters1 = algorithmParameters1;
656+
this.algorithmParameters2 = algorithmParameters2;
599657
this.enabled = enabled;
600658
}
601659

@@ -609,16 +667,6 @@ int getBitsFFDHE()
609667
return all.bitsFFDHE;
610668
}
611669

612-
String getJcaAlgorithm()
613-
{
614-
return all.jcaAlgorithm;
615-
}
616-
617-
String getJcaGroup()
618-
{
619-
return all.jcaGroup;
620-
}
621-
622670
int getNamedGroup()
623671
{
624672
return all.namedGroup;
@@ -656,7 +704,21 @@ private boolean isPermittedBy(BCAlgorithmConstraints algorithmConstraints)
656704
{
657705
Set<BCCryptoPrimitive> primitives = JsseUtils.KEY_AGREEMENT_CRYPTO_PRIMITIVES_BC;
658706

659-
return algorithmConstraints.permits(primitives, getJcaGroup(), null)
660-
&& algorithmConstraints.permits(primitives, getJcaAlgorithm(), algorithmParameters);
707+
if (!algorithmConstraints.permits(primitives, all.jcaGroup1, null) ||
708+
!algorithmConstraints.permits(primitives, all.jcaAlgorithm1, algorithmParameters1))
709+
{
710+
return false;
711+
}
712+
713+
if (all.jcaAlgorithm2 != null)
714+
{
715+
if (!algorithmConstraints.permits(primitives, all.jcaGroup2, null) ||
716+
!algorithmConstraints.permits(primitives, all.jcaAlgorithm2, algorithmParameters2))
717+
{
718+
return false;
719+
}
720+
}
721+
722+
return true;
661723
}
662724
}

0 commit comments

Comments
 (0)