mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-07 22:50:49 +00:00
8322971: KEM.getInstance() should check if a 3rd-party security provider is signed
Reviewed-by: mullan, valeriep
This commit is contained in:
parent
b8ae4a8c09
commit
9fd855ed47
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
@ -29,6 +29,7 @@ import sun.security.jca.GetInstance;
|
||||
import java.security.*;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.spec.AlgorithmParameterSpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -539,10 +540,19 @@ public final class KEM {
|
||||
List<Provider.Service> list = GetInstance.getServices(
|
||||
"KEM",
|
||||
Objects.requireNonNull(algorithm, "null algorithm name"));
|
||||
if (list.isEmpty()) {
|
||||
throw new NoSuchAlgorithmException(algorithm + " KEM not available");
|
||||
List<Provider.Service> allowed = new ArrayList<>();
|
||||
for (Provider.Service s : list) {
|
||||
if (!JceSecurity.canUseProvider(s.getProvider())) {
|
||||
continue;
|
||||
}
|
||||
allowed.add(s);
|
||||
}
|
||||
return new KEM(algorithm, new DelayedKEM(list.toArray(new Provider.Service[0])));
|
||||
if (allowed.isEmpty()) {
|
||||
throw new NoSuchAlgorithmException
|
||||
(algorithm + " KEM not available");
|
||||
}
|
||||
|
||||
return new KEM(algorithm, new DelayedKEM(allowed.toArray(new Provider.Service[0])));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -568,7 +578,7 @@ public final class KEM {
|
||||
if (provider == null) {
|
||||
return getInstance(algorithm);
|
||||
}
|
||||
GetInstance.Instance instance = GetInstance.getInstance(
|
||||
GetInstance.Instance instance = JceSecurity.getInstance(
|
||||
"KEM",
|
||||
KEMSpi.class,
|
||||
Objects.requireNonNull(algorithm, "null algorithm name"),
|
||||
@ -601,7 +611,7 @@ public final class KEM {
|
||||
if (provider == null) {
|
||||
return getInstance(algorithm);
|
||||
}
|
||||
GetInstance.Instance instance = GetInstance.getInstance(
|
||||
GetInstance.Instance instance = JceSecurity.getInstance(
|
||||
"KEM",
|
||||
KEMSpi.class,
|
||||
Objects.requireNonNull(algorithm, "null algorithm name"),
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
@ -26,7 +26,9 @@
|
||||
* @bug 8297878
|
||||
* @summary Key Encapsulation Mechanism API
|
||||
* @library /test/lib
|
||||
* @build java.base/com.sun.crypto.provider.EvenKEMImpl
|
||||
* @modules java.base/com.sun.crypto.provider
|
||||
* @run main/othervm Compliance
|
||||
*/
|
||||
import jdk.test.lib.Asserts;
|
||||
import jdk.test.lib.Utils;
|
||||
@ -45,18 +47,19 @@ import java.util.function.Consumer;
|
||||
|
||||
import com.sun.crypto.provider.DHKEM;
|
||||
|
||||
import static com.sun.crypto.provider.EvenKEMImpl.isEven;
|
||||
|
||||
public class Compliance {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
basic();
|
||||
conform();
|
||||
determined();
|
||||
try {
|
||||
Security.insertProviderAt(new ProviderImpl(), 1);
|
||||
delayed();
|
||||
} finally {
|
||||
Security.removeProvider("XP");
|
||||
}
|
||||
// Patch an alternate DHKEM in SunEC which is ahead of SunJCE
|
||||
// in security provider listing.
|
||||
Security.getProvider("SunEC")
|
||||
.put("KEM.DHKEM", "com.sun.crypto.provider.EvenKEMImpl");
|
||||
delayed();
|
||||
}
|
||||
|
||||
// Encapsulated conformance checks
|
||||
@ -220,34 +223,6 @@ public class Compliance {
|
||||
return enc2;
|
||||
}
|
||||
|
||||
public static class ProviderImpl extends Provider {
|
||||
ProviderImpl() {
|
||||
super("XP", "1", "XP");
|
||||
put("KEM.DHKEM", "Compliance$KEMImpl");
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isEven(Key k) {
|
||||
return Arrays.hashCode(k.getEncoded()) % 2 == 0;
|
||||
}
|
||||
|
||||
public static class KEMImpl extends DHKEM {
|
||||
|
||||
@Override
|
||||
public EncapsulatorSpi engineNewEncapsulator(PublicKey pk, AlgorithmParameterSpec spec, SecureRandom secureRandom)
|
||||
throws InvalidAlgorithmParameterException, InvalidKeyException {
|
||||
if (!isEven(pk)) throw new InvalidKeyException("Only accept even keys");
|
||||
return super.engineNewEncapsulator(pk, spec, secureRandom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecapsulatorSpi engineNewDecapsulator(PrivateKey sk, AlgorithmParameterSpec spec)
|
||||
throws InvalidAlgorithmParameterException, InvalidKeyException {
|
||||
if (!isEven(sk)) throw new InvalidKeyException("Only accept even keys");
|
||||
return super.engineNewDecapsulator(sk, spec);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure delayed provider selection
|
||||
static void delayed() throws Exception {
|
||||
KeyPairGenerator g = KeyPairGenerator.getInstance("X25519");
|
||||
@ -266,7 +241,7 @@ public class Compliance {
|
||||
KEM.Encapsulator eodd = kem.newEncapsulator(odd);
|
||||
KEM.Encapsulator eeven = kem.newEncapsulator(even);
|
||||
Asserts.assertEQ(eodd.providerName(), "SunJCE");
|
||||
Asserts.assertEQ(eeven.providerName(), "XP");
|
||||
Asserts.assertEQ(eeven.providerName(), "SunEC");
|
||||
}
|
||||
|
||||
static ECPublicKey badECKey() {
|
||||
|
||||
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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 java.security.*;
|
||||
import java.security.spec.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
// The alternate DHKEM implementation used by the Compliance.java test.
|
||||
public class EvenKEMImpl extends DHKEM {
|
||||
|
||||
public static boolean isEven(Key k) {
|
||||
return Arrays.hashCode(k.getEncoded()) % 2 == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EncapsulatorSpi engineNewEncapsulator(
|
||||
PublicKey pk, AlgorithmParameterSpec spec, SecureRandom secureRandom)
|
||||
throws InvalidAlgorithmParameterException, InvalidKeyException {
|
||||
if (!isEven(pk)) throw new InvalidKeyException("Only accept even keys");
|
||||
return super.engineNewEncapsulator(pk, spec, secureRandom);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DecapsulatorSpi engineNewDecapsulator(
|
||||
PrivateKey sk, AlgorithmParameterSpec spec)
|
||||
throws InvalidAlgorithmParameterException, InvalidKeyException {
|
||||
if (!isEven(sk)) throw new InvalidKeyException("Only accept even keys");
|
||||
return super.engineNewDecapsulator(sk, spec);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 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
|
||||
@ -28,6 +28,7 @@
|
||||
* @modules java.base/sun.security.jca
|
||||
* java.base/sun.security.rsa
|
||||
* java.base/sun.security.util
|
||||
* java.base/javax.crypto:+open
|
||||
*/
|
||||
import sun.security.jca.JCAUtil;
|
||||
import sun.security.rsa.RSACore;
|
||||
@ -88,7 +89,7 @@ public class RSA_KEM {
|
||||
KeyPair kp = g.generateKeyPair();
|
||||
for (RSAKEMParameterSpec kspec : kspecs) {
|
||||
SecretKey cek = KeyGenerator.getInstance("AES").generateKey();
|
||||
KEM kem1 = KEM.getInstance("RSA-KEM", p);
|
||||
KEM kem1 = getKemImpl(p);
|
||||
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
c.init(Cipher.ENCRYPT_MODE, cek, new IvParameterSpec(iv));
|
||||
byte[] ciphertext = c.doFinal(msg);
|
||||
@ -101,7 +102,7 @@ public class RSA_KEM {
|
||||
|
||||
AlgorithmParameters a = AlgorithmParameters.getInstance("RSA-KEM", p);
|
||||
a.init(enc.params());
|
||||
KEM kem2 = KEM.getInstance("RSA-KEM", p);
|
||||
KEM kem2 = getKemImpl(p);
|
||||
KEM.Decapsulator d = kem2.newDecapsulator(kp.getPrivate(), a.getParameterSpec(AlgorithmParameterSpec.class));
|
||||
SecretKey k = d.decapsulate(enc.encapsulation(), 0, d.secretSize(), "AES");
|
||||
Cipher c3 = Cipher.getInstance(kspec.encAlg);
|
||||
@ -122,6 +123,14 @@ public class RSA_KEM {
|
||||
}
|
||||
}
|
||||
|
||||
// To bypass the JCE security provider signature check
|
||||
private static KEM getKemImpl(Provider p) throws Exception {
|
||||
var ctor = KEM.class.getDeclaredConstructor(
|
||||
String.class, KEMSpi.class, Provider.class);
|
||||
ctor.setAccessible(true);
|
||||
return ctor.newInstance("RSA-KEM", new KEMImpl(), p);
|
||||
}
|
||||
|
||||
static final String RSA_KEM = "1.2.840.113549.1.9.16.3.14";
|
||||
static final String KEM_RSA = "1.0.18033.2.2.4";
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user