Skip to content

Commit 13987b4

Browse files
Ben Perezferakocz
Ben Perez
andcommitted
8298390: Implement JEP 496: Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism
Co-authored-by: Ferenc Rakoczi <ferenc.r.rakoczi@oracle.com> Reviewed-by: valeriep
1 parent 6d3becb commit 13987b4

File tree

10 files changed

+4781
-1
lines changed

10 files changed

+4781
-1
lines changed

src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java

+1,511
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package com.sun.crypto.provider;
27+
28+
import sun.security.jca.JCAUtil;
29+
import sun.security.provider.NamedKEM;
30+
import sun.security.provider.NamedKeyFactory;
31+
import sun.security.provider.NamedKeyPairGenerator;
32+
33+
import java.security.*;
34+
import java.util.Arrays;
35+
36+
import javax.crypto.DecapsulateException;
37+
38+
public final class ML_KEM_Impls {
39+
40+
static int name2int(String name) {
41+
if (name.endsWith("512")) {
42+
return 512;
43+
} else if (name.endsWith("768")) {
44+
return 768;
45+
} else if (name.endsWith("1024")) {
46+
return 1024;
47+
} else {
48+
// should not happen
49+
throw new ProviderException("Unknown name " + name);
50+
}
51+
}
52+
53+
public sealed static class KPG
54+
extends NamedKeyPairGenerator permits KPG2, KPG3, KPG5 {
55+
56+
public KPG() {
57+
// ML-KEM-768 is the default
58+
super("ML-KEM", "ML-KEM-768", "ML-KEM-512", "ML-KEM-1024");
59+
}
60+
61+
protected KPG(String pname) {
62+
super("ML-KEM", pname);
63+
}
64+
65+
@Override
66+
protected byte[][] implGenerateKeyPair(String name, SecureRandom random) {
67+
byte[] seed = new byte[32];
68+
var r = random != null ? random : JCAUtil.getDefSecureRandom();
69+
r.nextBytes(seed);
70+
byte[] z = new byte[32];
71+
r.nextBytes(z);
72+
73+
ML_KEM mlKem = new ML_KEM(name);
74+
ML_KEM.ML_KEM_KeyPair kp;
75+
try {
76+
kp = mlKem.generateKemKeyPair(seed, z);
77+
} finally {
78+
Arrays.fill(seed, (byte)0);
79+
Arrays.fill(z, (byte)0);
80+
}
81+
return new byte[][] {
82+
kp.encapsulationKey().keyBytes(),
83+
kp.decapsulationKey().keyBytes()
84+
};
85+
}
86+
}
87+
88+
public final static class KPG2 extends KPG {
89+
public KPG2() {
90+
super("ML-KEM-512");
91+
}
92+
}
93+
94+
public final static class KPG3 extends KPG {
95+
public KPG3() {
96+
super("ML-KEM-768");
97+
}
98+
}
99+
100+
public final static class KPG5 extends KPG {
101+
public KPG5() {
102+
super("ML-KEM-1024");
103+
}
104+
}
105+
106+
public sealed static class KF extends NamedKeyFactory permits KF2, KF3, KF5 {
107+
public KF() {
108+
super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024");
109+
}
110+
public KF(String name) {
111+
super("ML-KEM", name);
112+
}
113+
}
114+
115+
public final static class KF2 extends KF {
116+
public KF2() {
117+
super("ML-KEM-512");
118+
}
119+
}
120+
121+
public final static class KF3 extends KF {
122+
public KF3() {
123+
super("ML-KEM-768");
124+
}
125+
}
126+
127+
public final static class KF5 extends KF {
128+
public KF5() {
129+
super("ML-KEM-1024");
130+
}
131+
}
132+
133+
public sealed static class K extends NamedKEM permits K2, K3, K5 {
134+
private static final int SEED_SIZE = 32;
135+
136+
@Override
137+
protected byte[][] implEncapsulate(String name, byte[] encapsulationKey,
138+
Object ek, SecureRandom secureRandom) {
139+
140+
byte[] randomBytes = new byte[SEED_SIZE];
141+
var r = secureRandom != null ? secureRandom : JCAUtil.getDefSecureRandom();
142+
r.nextBytes(randomBytes);
143+
144+
ML_KEM mlKem = new ML_KEM(name);
145+
ML_KEM.ML_KEM_EncapsulateResult mlKemEncapsulateResult = null;
146+
try {
147+
mlKemEncapsulateResult = mlKem.encapsulate(
148+
new ML_KEM.ML_KEM_EncapsulationKey(
149+
encapsulationKey), randomBytes);
150+
} finally {
151+
Arrays.fill(randomBytes, (byte) 0);
152+
}
153+
154+
return new byte[][] {
155+
mlKemEncapsulateResult.cipherText().encryptedBytes(),
156+
mlKemEncapsulateResult.sharedSecret()
157+
};
158+
}
159+
160+
@Override
161+
protected byte[] implDecapsulate(String name, byte[] decapsulationKey,
162+
Object dk, byte[] cipherText)
163+
throws DecapsulateException {
164+
165+
ML_KEM mlKem = new ML_KEM(name);
166+
var kpkeCipherText = new ML_KEM.K_PKE_CipherText(cipherText);
167+
168+
byte[] decapsulateResult;
169+
try {
170+
decapsulateResult = mlKem.decapsulate(
171+
new ML_KEM.ML_KEM_DecapsulationKey(
172+
decapsulationKey), kpkeCipherText);
173+
} catch (DecapsulateException e) {
174+
throw new DecapsulateException("Decapsulate error", e) ;
175+
}
176+
177+
return decapsulateResult;
178+
}
179+
180+
@Override
181+
protected int implSecretSize(String name) {
182+
return ML_KEM.SECRET_SIZE;
183+
}
184+
185+
@Override
186+
protected int implEncapsulationSize(String name) {
187+
ML_KEM mlKem = new ML_KEM(name);
188+
return mlKem.getEncapsulationSize();
189+
}
190+
191+
@Override
192+
protected Object implCheckPublicKey(String name, byte[] pk)
193+
throws InvalidKeyException {
194+
195+
ML_KEM mlKem = new ML_KEM(name);
196+
return mlKem.checkPublicKey(pk);
197+
}
198+
199+
@Override
200+
protected Object implCheckPrivateKey(String name, byte[] sk)
201+
throws InvalidKeyException {
202+
203+
ML_KEM mlKem = new ML_KEM(name);
204+
return mlKem.checkPrivateKey(sk);
205+
}
206+
207+
public K() {
208+
super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024");
209+
}
210+
211+
public K(String name) {
212+
super("ML-KEM", name);
213+
}
214+
}
215+
216+
public final static class K2 extends K {
217+
public K2() {
218+
super("ML-KEM-512");
219+
}
220+
}
221+
222+
public final static class K3 extends K {
223+
public K3() {
224+
super("ML-KEM-768");
225+
}
226+
}
227+
228+
public final static class K5 extends K {
229+
public K5() {
230+
super("ML-KEM-1024");
231+
}
232+
}
233+
}

src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
*
7777
* - DHKEM
7878
*
79+
* - ML-KEM
80+
*
7981
*/
8082

8183
public final class SunJCE extends Provider {
@@ -85,7 +87,7 @@ public final class SunJCE extends Provider {
8587

8688
private static final String info = "SunJCE Provider " +
8789
"(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, "
88-
+ "Diffie-Hellman, HMAC, ChaCha20)";
90+
+ "Diffie-Hellman, HMAC, ChaCha20, DHKEM, and ML-KEM)";
8991

9092
/* Are we debugging? -- for developers */
9193
static final boolean debug = false;
@@ -752,6 +754,23 @@ void putEntries() {
752754
"|java.security.interfaces.XECKey");
753755
ps("KEM", "DHKEM", "com.sun.crypto.provider.DHKEM", null, attrs);
754756

757+
attrs.clear();
758+
attrs.put("ImplementedIn", "Software");
759+
ps("KEM", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$K", null, attrs);
760+
psA("KEM", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$K2", attrs);
761+
psA("KEM", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$K3", attrs);
762+
psA("KEM", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$K5",attrs);
763+
764+
ps("KeyPairGenerator", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$KPG", null, attrs);
765+
psA("KeyPairGenerator", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$KPG2", attrs);
766+
psA("KeyPairGenerator", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$KPG3", attrs);
767+
psA("KeyPairGenerator", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$KPG5", attrs);
768+
769+
ps("KeyFactory", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$KF", null, attrs);
770+
psA("KeyFactory", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$KF2", attrs);
771+
psA("KeyFactory", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$KF3", attrs);
772+
psA("KeyFactory", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$KF5", attrs);
773+
755774
/*
756775
* SSL/TLS mechanisms
757776
*

src/java.base/share/classes/java/security/spec/NamedParameterSpec.java

+24
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,30 @@ public class NamedParameterSpec implements AlgorithmParameterSpec {
6868
public static final NamedParameterSpec ED448
6969
= new NamedParameterSpec("Ed448");
7070

71+
/**
72+
* The ML-KEM-512 parameters
73+
*
74+
* @since 24
75+
*/
76+
public static final NamedParameterSpec ML_KEM_512
77+
= new NamedParameterSpec("ML-KEM-512");
78+
79+
/**
80+
* The ML-KEM-768 parameters
81+
*
82+
* @since 24
83+
*/
84+
public static final NamedParameterSpec ML_KEM_768
85+
= new NamedParameterSpec("ML-KEM-768");
86+
87+
/**
88+
* The ML-KEM-1024 parameters
89+
*
90+
* @since 24
91+
*/
92+
public static final NamedParameterSpec ML_KEM_1024
93+
= new NamedParameterSpec("ML-KEM-1024");
94+
7195
private final String name;
7296

7397
/**

0 commit comments

Comments
 (0)