Skip to content

Commit 32dab66

Browse files
committed
TLS: Cleanup JCA ML-KEM code
- reduce dependency on BC provider
1 parent 6a62b22 commit 32dab66

File tree

5 files changed

+152
-145
lines changed

5 files changed

+152
-145
lines changed
Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,14 @@
11
package org.bouncycastle.tls.crypto;
22

3-
import org.bouncycastle.jcajce.spec.KEMParameterSpec;
4-
import org.bouncycastle.jcajce.spec.KTSParameterSpec;
5-
63
public class TlsKemConfig
74
{
8-
protected final KTSParameterSpec ktsParameterSpec;
95
protected final int namedGroup;
106
protected final boolean isServer;
117

128
public TlsKemConfig(int namedGroup, boolean isServer)
139
{
1410
this.namedGroup = namedGroup;
1511
this.isServer = isServer;
16-
this.ktsParameterSpec = new KTSParameterSpec.Builder("AES-KWP", 256).withNoKdf().build();
17-
}
18-
public TlsKemConfig(int namedGroup, boolean isServer, KTSParameterSpec ktsParameterSpec)
19-
{
20-
this.namedGroup = namedGroup;
21-
this.isServer = isServer;
22-
this.ktsParameterSpec = ktsParameterSpec;
2312
}
2413

2514
public int getNamedGroup()
@@ -31,9 +20,4 @@ public boolean isServer()
3120
{
3221
return isServer;
3322
}
34-
35-
public KTSParameterSpec getKtsParameterSpec()
36-
{
37-
return ktsParameterSpec;
38-
}
3923
}

tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JcaTlsCrypto.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -442,18 +442,13 @@ public AlgorithmParameters getNamedGroupAlgorithmParameters(int namedGroup)
442442
{
443443
if (NamedGroup.refersToAnXDHCurve(namedGroup))
444444
{
445-
switch (namedGroup)
446-
{
447445
/*
448-
* TODO Return AlgorithmParameters to check against disabled algorithms
446+
* TODO Return AlgorithmParameters to check against disabled algorithms?
449447
*
450448
* NOTE: The JDK doesn't even support AlgorithmParameters for XDH, so SunJSSE also winds
451449
* up using null AlgorithmParameters when checking algorithm constraints.
452450
*/
453-
case NamedGroup.x25519:
454-
case NamedGroup.x448:
455-
return null;
456-
}
451+
return null;
457452
}
458453
else if (NamedGroup.refersToAnECDSACurve(namedGroup))
459454
{
@@ -465,8 +460,12 @@ else if (NamedGroup.refersToASpecificFiniteField(namedGroup))
465460
}
466461
else if (NamedGroup.refersToASpecificKem(namedGroup))
467462
{
468-
//Note: There is no AlgorithmParametersSpi for ML-KEM
469-
return KemUtil.getAlgorithmParameters(this, NamedGroup.getKemName(namedGroup));
463+
/*
464+
* TODO Return AlgorithmParameters to check against disabled algorithms?
465+
*
466+
* NOTE: See what the JDK/SunJSSE implementation does.
467+
*/
468+
return null;
470469
}
471470

472471
throw new IllegalArgumentException("NamedGroup not supported: " + NamedGroup.getText(namedGroup));

tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JceTlsMLKem.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22

33
import java.io.IOException;
44
import java.security.KeyPair;
5+
import java.security.PrivateKey;
6+
import java.security.PublicKey;
57

68
import org.bouncycastle.jcajce.SecretKeyWithEncapsulation;
7-
import org.bouncycastle.jcajce.provider.asymmetric.mlkem.BCMLKEMPrivateKey;
8-
import org.bouncycastle.jcajce.provider.asymmetric.mlkem.BCMLKEMPublicKey;
99
import org.bouncycastle.tls.crypto.TlsAgreement;
1010
import org.bouncycastle.tls.crypto.TlsSecret;
1111

1212
public class JceTlsMLKem implements TlsAgreement
1313
{
1414
protected final JceTlsMLKemDomain domain;
1515

16-
protected BCMLKEMPrivateKey privateKey;
17-
protected BCMLKEMPublicKey publicKey;
16+
protected PrivateKey privateKey;
17+
protected PublicKey publicKey;
1818
protected TlsSecret secret;
1919

2020
public JceTlsMLKem(JceTlsMLKemDomain domain)
@@ -34,8 +34,8 @@ public byte[] generateEphemeral() throws IOException
3434
else
3535
{
3636
KeyPair kp = domain.generateKeyPair();
37-
this.privateKey = (BCMLKEMPrivateKey)kp.getPrivate();
38-
return ((BCMLKEMPublicKey)kp.getPublic()).getPublicData();
37+
this.privateKey = kp.getPrivate();
38+
return KemUtil.encodePublicKey(kp.getPublic());
3939
}
4040
}
4141

tls/src/main/java/org/bouncycastle/tls/crypto/impl/jcajce/JceTlsMLKemDomain.java

Lines changed: 22 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,32 @@
11
package org.bouncycastle.tls.crypto.impl.jcajce;
22

3+
import java.io.IOException;
34
import java.security.KeyPair;
45
import java.security.KeyPairGenerator;
5-
import java.security.NoSuchAlgorithmException;
6-
import java.security.NoSuchProviderException;
76
import java.security.PrivateKey;
87
import java.security.PublicKey;
98

109
import javax.crypto.KeyGenerator;
1110

1211
import org.bouncycastle.jcajce.SecretKeyWithEncapsulation;
13-
import org.bouncycastle.jcajce.provider.asymmetric.mlkem.BCMLKEMPublicKey;
1412
import org.bouncycastle.jcajce.spec.KEMExtractSpec;
1513
import org.bouncycastle.jcajce.spec.KEMGenerateSpec;
16-
import org.bouncycastle.pqc.crypto.mlkem.MLKEMParameters;
17-
import org.bouncycastle.pqc.crypto.mlkem.MLKEMPublicKeyParameters;
1814
import org.bouncycastle.tls.NamedGroup;
1915
import org.bouncycastle.tls.crypto.TlsAgreement;
2016
import org.bouncycastle.tls.crypto.TlsKemConfig;
2117
import org.bouncycastle.tls.crypto.TlsKemDomain;
2218

2319
public class JceTlsMLKemDomain implements TlsKemDomain
2420
{
25-
public static MLKEMParameters getDomainParameters(TlsKemConfig kemConfig)
26-
{
27-
switch (kemConfig.getNamedGroup())
28-
{
29-
case NamedGroup.OQS_mlkem512:
30-
case NamedGroup.MLKEM512:
31-
return MLKEMParameters.ml_kem_512;
32-
case NamedGroup.OQS_mlkem768:
33-
case NamedGroup.MLKEM768:
34-
return MLKEMParameters.ml_kem_768;
35-
case NamedGroup.OQS_mlkem1024:
36-
case NamedGroup.MLKEM1024:
37-
return MLKEMParameters.ml_kem_1024;
38-
default:
39-
throw new IllegalArgumentException("No ML-KEM configuration provided");
40-
}
41-
}
42-
4321
protected final JcaTlsCrypto crypto;
44-
protected final TlsKemConfig config;
45-
protected final MLKEMParameters domainParameters;
22+
protected final String kemName;
4623
protected final boolean isServer;
47-
protected KeyGenerator keyGen;
48-
// protected KeyPairGenerator kpg;
49-
// protected Cipher cipher;
50-
5124

5225
public JceTlsMLKemDomain(JcaTlsCrypto crypto, TlsKemConfig kemConfig)
5326
{
5427
this.crypto = crypto;
55-
this.config = kemConfig;
56-
this.domainParameters = getDomainParameters(kemConfig);
28+
this.kemName = NamedGroup.getKemName(kemConfig.getNamedGroup());
5729
this.isServer = kemConfig.isServer();
58-
try
59-
{
60-
this.keyGen = crypto.getHelper().createKeyGenerator(domainParameters.getName());
61-
}
62-
catch (NoSuchAlgorithmException e)
63-
{
64-
throw new RuntimeException(e);
65-
}
66-
catch (NoSuchProviderException e)
67-
{
68-
throw new RuntimeException(e);
69-
}
7030
}
7131

7232
public JceTlsSecret adoptLocalSecret(byte[] secret)
@@ -83,85 +43,59 @@ public JceTlsSecret decapsulate(PrivateKey privateKey, byte[] ciphertext)
8343
{
8444
try
8545
{
86-
keyGen.init(new KEMExtractSpec.Builder(privateKey, ciphertext, "DEF", 256).withNoKdf().build());
87-
SecretKeyWithEncapsulation secEnc = (SecretKeyWithEncapsulation)keyGen.generateKey();
88-
46+
KeyGenerator keyGenerator = KemUtil.getKeyGenerator(crypto, kemName);
47+
keyGenerator.init(new KEMExtractSpec.Builder(privateKey, ciphertext, "DEF", 256).withNoKdf().build());
48+
SecretKeyWithEncapsulation secEnc = (SecretKeyWithEncapsulation)keyGenerator.generateKey();
8949
return adoptLocalSecret(secEnc.getEncoded());
9050
}
9151
catch (Exception e)
9252
{
9353
throw Exceptions.illegalArgumentException("invalid key: " + e.getMessage(), e);
9454
}
95-
96-
97-
// MLKEMExtractor kemExtract = new MLKEMExtractor(privateKey);
98-
// byte[] secret = kemExtract.extractSecret(ciphertext);
99-
// return adoptLocalSecret(secret);
10055
}
10156

102-
public BCMLKEMPublicKey decodePublicKey(byte[] encoding)
57+
public PublicKey decodePublicKey(byte[] encoding)
58+
throws IOException
10359
{
104-
return new BCMLKEMPublicKey(new MLKEMPublicKeyParameters(domainParameters, encoding));
60+
return KemUtil.decodePublicKey(crypto, kemName, encoding);
10561
}
10662

10763
public SecretKeyWithEncapsulation encapsulate(PublicKey publicKey)
10864
{
10965
try
11066
{
111-
keyGen.init(new KEMGenerateSpec.Builder(publicKey, "DEF", 256).withNoKdf().build());
112-
return (SecretKeyWithEncapsulation)keyGen.generateKey();
67+
KeyGenerator keyGenerator = KemUtil.getKeyGenerator(crypto, kemName);
68+
keyGenerator.init(new KEMGenerateSpec.Builder(publicKey, "DEF", 256).withNoKdf().build());
69+
return (SecretKeyWithEncapsulation)keyGenerator.generateKey();
11370
}
11471
catch (Exception e)
11572
{
11673
throw Exceptions.illegalArgumentException("invalid key: " + e.getMessage(), e);
11774
}
11875
}
11976

120-
public byte[] encodePublicKey(MLKEMPublicKeyParameters publicKey)
77+
public byte[] encodePublicKey(PublicKey publicKey)
78+
throws IOException
12179
{
122-
return publicKey.getEncoded();
80+
return KemUtil.encodePublicKey(publicKey);
12381
}
12482

125-
private void init()
83+
public KeyPair generateKeyPair()
12684
{
85+
// TODO How to pass only the SecureRandom?
12786
// try
12887
// {
129-
//// kpg = KeyPairGenerator.getInstance("MLKEM");
130-
//// kpg.initialize(MLKEMParameterSpec.fromName(domainParameters.getName()), crypto.getSecureRandom());
131-
//// keyGen = KeyGenerator.getInstance(domainParameters.getName(), "BC");
132-
//
133-
//// cipher = KemUtil.getCipher(crypto, domainParameters.getName());
134-
//
135-
//
88+
// KeyPairGenerator keyPairGenerator = KemUtil.getKeyPairGenerator(crypto, kemName);
89+
// keyPairGenerator.initialize((AlgorithmParameterSpec)null, crypto.getSecureRandom());
90+
// return keyPairGenerator.generateKeyPair();
13691
// }
13792
// catch (GeneralSecurityException e)
13893
// {
13994
// throw Exceptions.illegalStateException("unable to create key pair: " + e.getMessage(), e);
14095
// }
14196

142-
143-
}
144-
public KeyPair generateKeyPair()
145-
{
146-
// AlgorithmParameters params = KemUtil.getAlgorithmParameters(crypto, domainParameters.getName());
147-
// if (params == null)
148-
// {
149-
// throw new IllegalStateException("KEM parameters unavailable");
150-
// }
151-
KeyPairGenerator kpg = null;
152-
try
153-
{
154-
kpg = crypto.getHelper().createKeyPairGenerator(domainParameters.getName());
155-
}
156-
catch (NoSuchAlgorithmException e)
157-
{
158-
throw new RuntimeException(e);
159-
}
160-
catch (NoSuchProviderException e)
161-
{
162-
throw new RuntimeException(e);
163-
}
164-
return kpg.generateKeyPair();
97+
KeyPairGenerator keyPairGenerator = KemUtil.getKeyPairGenerator(crypto, kemName);
98+
return keyPairGenerator.generateKeyPair();
16599
}
166100

167101
public boolean isServer()

0 commit comments

Comments
 (0)