mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
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
This commit is contained in:
parent
6d3becb486
commit
13987b4244
10 changed files with 4781 additions and 1 deletions
1511
src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java
Normal file
1511
src/java.base/share/classes/com/sun/crypto/provider/ML_KEM.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.crypto.provider;
|
||||
|
||||
import sun.security.jca.JCAUtil;
|
||||
import sun.security.provider.NamedKEM;
|
||||
import sun.security.provider.NamedKeyFactory;
|
||||
import sun.security.provider.NamedKeyPairGenerator;
|
||||
|
||||
import java.security.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.DecapsulateException;
|
||||
|
||||
public final class ML_KEM_Impls {
|
||||
|
||||
static int name2int(String name) {
|
||||
if (name.endsWith("512")) {
|
||||
return 512;
|
||||
} else if (name.endsWith("768")) {
|
||||
return 768;
|
||||
} else if (name.endsWith("1024")) {
|
||||
return 1024;
|
||||
} else {
|
||||
// should not happen
|
||||
throw new ProviderException("Unknown name " + name);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed static class KPG
|
||||
extends NamedKeyPairGenerator permits KPG2, KPG3, KPG5 {
|
||||
|
||||
public KPG() {
|
||||
// ML-KEM-768 is the default
|
||||
super("ML-KEM", "ML-KEM-768", "ML-KEM-512", "ML-KEM-1024");
|
||||
}
|
||||
|
||||
protected KPG(String pname) {
|
||||
super("ML-KEM", pname);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[][] implGenerateKeyPair(String name, SecureRandom random) {
|
||||
byte[] seed = new byte[32];
|
||||
var r = random != null ? random : JCAUtil.getDefSecureRandom();
|
||||
r.nextBytes(seed);
|
||||
byte[] z = new byte[32];
|
||||
r.nextBytes(z);
|
||||
|
||||
ML_KEM mlKem = new ML_KEM(name);
|
||||
ML_KEM.ML_KEM_KeyPair kp;
|
||||
try {
|
||||
kp = mlKem.generateKemKeyPair(seed, z);
|
||||
} finally {
|
||||
Arrays.fill(seed, (byte)0);
|
||||
Arrays.fill(z, (byte)0);
|
||||
}
|
||||
return new byte[][] {
|
||||
kp.encapsulationKey().keyBytes(),
|
||||
kp.decapsulationKey().keyBytes()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public final static class KPG2 extends KPG {
|
||||
public KPG2() {
|
||||
super("ML-KEM-512");
|
||||
}
|
||||
}
|
||||
|
||||
public final static class KPG3 extends KPG {
|
||||
public KPG3() {
|
||||
super("ML-KEM-768");
|
||||
}
|
||||
}
|
||||
|
||||
public final static class KPG5 extends KPG {
|
||||
public KPG5() {
|
||||
super("ML-KEM-1024");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed static class KF extends NamedKeyFactory permits KF2, KF3, KF5 {
|
||||
public KF() {
|
||||
super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024");
|
||||
}
|
||||
public KF(String name) {
|
||||
super("ML-KEM", name);
|
||||
}
|
||||
}
|
||||
|
||||
public final static class KF2 extends KF {
|
||||
public KF2() {
|
||||
super("ML-KEM-512");
|
||||
}
|
||||
}
|
||||
|
||||
public final static class KF3 extends KF {
|
||||
public KF3() {
|
||||
super("ML-KEM-768");
|
||||
}
|
||||
}
|
||||
|
||||
public final static class KF5 extends KF {
|
||||
public KF5() {
|
||||
super("ML-KEM-1024");
|
||||
}
|
||||
}
|
||||
|
||||
public sealed static class K extends NamedKEM permits K2, K3, K5 {
|
||||
private static final int SEED_SIZE = 32;
|
||||
|
||||
@Override
|
||||
protected byte[][] implEncapsulate(String name, byte[] encapsulationKey,
|
||||
Object ek, SecureRandom secureRandom) {
|
||||
|
||||
byte[] randomBytes = new byte[SEED_SIZE];
|
||||
var r = secureRandom != null ? secureRandom : JCAUtil.getDefSecureRandom();
|
||||
r.nextBytes(randomBytes);
|
||||
|
||||
ML_KEM mlKem = new ML_KEM(name);
|
||||
ML_KEM.ML_KEM_EncapsulateResult mlKemEncapsulateResult = null;
|
||||
try {
|
||||
mlKemEncapsulateResult = mlKem.encapsulate(
|
||||
new ML_KEM.ML_KEM_EncapsulationKey(
|
||||
encapsulationKey), randomBytes);
|
||||
} finally {
|
||||
Arrays.fill(randomBytes, (byte) 0);
|
||||
}
|
||||
|
||||
return new byte[][] {
|
||||
mlKemEncapsulateResult.cipherText().encryptedBytes(),
|
||||
mlKemEncapsulateResult.sharedSecret()
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected byte[] implDecapsulate(String name, byte[] decapsulationKey,
|
||||
Object dk, byte[] cipherText)
|
||||
throws DecapsulateException {
|
||||
|
||||
ML_KEM mlKem = new ML_KEM(name);
|
||||
var kpkeCipherText = new ML_KEM.K_PKE_CipherText(cipherText);
|
||||
|
||||
byte[] decapsulateResult;
|
||||
try {
|
||||
decapsulateResult = mlKem.decapsulate(
|
||||
new ML_KEM.ML_KEM_DecapsulationKey(
|
||||
decapsulationKey), kpkeCipherText);
|
||||
} catch (DecapsulateException e) {
|
||||
throw new DecapsulateException("Decapsulate error", e) ;
|
||||
}
|
||||
|
||||
return decapsulateResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int implSecretSize(String name) {
|
||||
return ML_KEM.SECRET_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int implEncapsulationSize(String name) {
|
||||
ML_KEM mlKem = new ML_KEM(name);
|
||||
return mlKem.getEncapsulationSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object implCheckPublicKey(String name, byte[] pk)
|
||||
throws InvalidKeyException {
|
||||
|
||||
ML_KEM mlKem = new ML_KEM(name);
|
||||
return mlKem.checkPublicKey(pk);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object implCheckPrivateKey(String name, byte[] sk)
|
||||
throws InvalidKeyException {
|
||||
|
||||
ML_KEM mlKem = new ML_KEM(name);
|
||||
return mlKem.checkPrivateKey(sk);
|
||||
}
|
||||
|
||||
public K() {
|
||||
super("ML-KEM", "ML-KEM-512", "ML-KEM-768", "ML-KEM-1024");
|
||||
}
|
||||
|
||||
public K(String name) {
|
||||
super("ML-KEM", name);
|
||||
}
|
||||
}
|
||||
|
||||
public final static class K2 extends K {
|
||||
public K2() {
|
||||
super("ML-KEM-512");
|
||||
}
|
||||
}
|
||||
|
||||
public final static class K3 extends K {
|
||||
public K3() {
|
||||
super("ML-KEM-768");
|
||||
}
|
||||
}
|
||||
|
||||
public final static class K5 extends K {
|
||||
public K5() {
|
||||
super("ML-KEM-1024");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -76,6 +76,8 @@ import static sun.security.util.SecurityProviderConstants.*;
|
|||
*
|
||||
* - DHKEM
|
||||
*
|
||||
* - ML-KEM
|
||||
*
|
||||
*/
|
||||
|
||||
public final class SunJCE extends Provider {
|
||||
|
@ -85,7 +87,7 @@ public final class SunJCE extends Provider {
|
|||
|
||||
private static final String info = "SunJCE Provider " +
|
||||
"(implements RSA, DES, Triple DES, AES, Blowfish, ARCFOUR, RC2, PBE, "
|
||||
+ "Diffie-Hellman, HMAC, ChaCha20)";
|
||||
+ "Diffie-Hellman, HMAC, ChaCha20, DHKEM, and ML-KEM)";
|
||||
|
||||
/* Are we debugging? -- for developers */
|
||||
static final boolean debug = false;
|
||||
|
@ -752,6 +754,23 @@ public final class SunJCE extends Provider {
|
|||
"|java.security.interfaces.XECKey");
|
||||
ps("KEM", "DHKEM", "com.sun.crypto.provider.DHKEM", null, attrs);
|
||||
|
||||
attrs.clear();
|
||||
attrs.put("ImplementedIn", "Software");
|
||||
ps("KEM", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$K", null, attrs);
|
||||
psA("KEM", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$K2", attrs);
|
||||
psA("KEM", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$K3", attrs);
|
||||
psA("KEM", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$K5",attrs);
|
||||
|
||||
ps("KeyPairGenerator", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$KPG", null, attrs);
|
||||
psA("KeyPairGenerator", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$KPG2", attrs);
|
||||
psA("KeyPairGenerator", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$KPG3", attrs);
|
||||
psA("KeyPairGenerator", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$KPG5", attrs);
|
||||
|
||||
ps("KeyFactory", "ML-KEM", "com.sun.crypto.provider.ML_KEM_Impls$KF", null, attrs);
|
||||
psA("KeyFactory", "ML-KEM-512", "com.sun.crypto.provider.ML_KEM_Impls$KF2", attrs);
|
||||
psA("KeyFactory", "ML-KEM-768", "com.sun.crypto.provider.ML_KEM_Impls$KF3", attrs);
|
||||
psA("KeyFactory", "ML-KEM-1024", "com.sun.crypto.provider.ML_KEM_Impls$KF5", attrs);
|
||||
|
||||
/*
|
||||
* SSL/TLS mechanisms
|
||||
*
|
||||
|
|
|
@ -68,6 +68,30 @@ public class NamedParameterSpec implements AlgorithmParameterSpec {
|
|||
public static final NamedParameterSpec ED448
|
||||
= new NamedParameterSpec("Ed448");
|
||||
|
||||
/**
|
||||
* The ML-KEM-512 parameters
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
public static final NamedParameterSpec ML_KEM_512
|
||||
= new NamedParameterSpec("ML-KEM-512");
|
||||
|
||||
/**
|
||||
* The ML-KEM-768 parameters
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
public static final NamedParameterSpec ML_KEM_768
|
||||
= new NamedParameterSpec("ML-KEM-768");
|
||||
|
||||
/**
|
||||
* The ML-KEM-1024 parameters
|
||||
*
|
||||
* @since 24
|
||||
*/
|
||||
public static final NamedParameterSpec ML_KEM_1024
|
||||
= new NamedParameterSpec("ML-KEM-1024");
|
||||
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.security.provider;
|
||||
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static sun.security.provider.ByteArrayAccess.b2lLittle;
|
||||
import static sun.security.provider.ByteArrayAccess.l2bLittle;
|
||||
|
||||
import static sun.security.provider.SHA3.keccak;
|
||||
|
||||
public class SHA3Parallel {
|
||||
private int blockSize = 0;
|
||||
private static final int DM = 5; // dimension of lanesArr
|
||||
private byte[][] buffers;
|
||||
private long[][] lanesArr;
|
||||
private static final int NRPAR = 2;
|
||||
|
||||
private SHA3Parallel(byte[][] buffers, int blockSize) throws InvalidAlgorithmParameterException {
|
||||
if ((buffers.length != NRPAR) || (buffers[0].length < blockSize)) {
|
||||
throw new InvalidAlgorithmParameterException("Bad buffersize.");
|
||||
}
|
||||
this.buffers = buffers;
|
||||
this.blockSize = blockSize;
|
||||
lanesArr = new long[NRPAR][];
|
||||
for (int i = 0; i < NRPAR; i++) {
|
||||
lanesArr[i] = new long[DM * DM];
|
||||
b2lLittle(buffers[i], 0, lanesArr[i], 0, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
public void reset(byte[][] buffers) throws InvalidAlgorithmParameterException {
|
||||
if ((buffers.length != NRPAR) || (buffers[0].length < blockSize)) {
|
||||
throw new InvalidAlgorithmParameterException("Bad buffersize.");
|
||||
}
|
||||
this.buffers = buffers;
|
||||
for (int i = 0; i < NRPAR; i++) {
|
||||
Arrays.fill(lanesArr[i], 0L);
|
||||
b2lLittle(buffers[i], 0, lanesArr[i], 0, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
public int squeezeBlock() {
|
||||
int retVal = doubleKeccak(lanesArr[0], lanesArr[1]);
|
||||
for (int i = 0; i < NRPAR; i++) {
|
||||
l2bLittle(lanesArr[i], 0, buffers[i], 0, blockSize);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
@IntrinsicCandidate
|
||||
private static int doubleKeccak(long[] lanes0, long[] lanes1) {
|
||||
doubleKeccakJava(lanes0, lanes1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
private static int doubleKeccakJava(long[] lanes0, long[] lanes1) {
|
||||
keccak(lanes0);
|
||||
keccak(lanes1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static final class Shake128Parallel extends SHA3Parallel {
|
||||
public Shake128Parallel(byte[][] buf) throws InvalidAlgorithmParameterException {
|
||||
super(buf, 168);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -179,6 +179,11 @@ public enum KnownOIDs {
|
|||
SHA3_384withRSA("2.16.840.1.101.3.4.3.15", "SHA3-384withRSA"),
|
||||
SHA3_512withRSA("2.16.840.1.101.3.4.3.16", "SHA3-512withRSA"),
|
||||
|
||||
// kems 2.16.840.1.101.3.4.4.*
|
||||
ML_KEM_512("2.16.840.1.101.3.4.4.1", "ML-KEM-512"),
|
||||
ML_KEM_768("2.16.840.1.101.3.4.4.2", "ML-KEM-768"),
|
||||
ML_KEM_1024("2.16.840.1.101.3.4.4.3", "ML-KEM-1024"),
|
||||
|
||||
// RSASecurity
|
||||
// PKCS1 1.2.840.113549.1.1.*
|
||||
PKCS1("1.2.840.113549.1.1", "RSA") { // RSA KeyPairGenerator and KeyFactory
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue