Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.
/ jdk22 Public archive

Commit

Permalink
8322971: KEM.getInstance() should check if a 3rd-party security provi…
Browse files Browse the repository at this point in the history
…der is signed

Reviewed-by: mullan, valeriep
Backport-of: 9fd855ed477bb0849ce5c774854844deec0f4c6b
  • Loading branch information
wangweij committed Jan 11, 2024
1 parent 3daa936 commit 4ea14b2
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 45 deletions.
22 changes: 16 additions & 6 deletions src/java.base/share/classes/javax/crypto/KEM.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -29,6 +29,7 @@
import java.security.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

Expand Down Expand Up @@ -539,10 +540,19 @@ public static KEM getInstance(String algorithm)
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);
}
if (allowed.isEmpty()) {
throw new NoSuchAlgorithmException
(algorithm + " KEM not available");
}
return new KEM(algorithm, new DelayedKEM(list.toArray(new Provider.Service[0])));

return new KEM(algorithm, new DelayedKEM(allowed.toArray(new Provider.Service[0])));
}

/**
Expand All @@ -568,7 +578,7 @@ public static KEM getInstance(String algorithm, Provider provider)
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"),
Expand Down Expand Up @@ -601,7 +611,7 @@ public static KEM getInstance(String algorithm, String provider)
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"),
Expand Down
47 changes: 11 additions & 36 deletions test/jdk/com/sun/crypto/provider/DHKEM/Compliance.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
Expand All @@ -45,18 +47,19 @@

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
Expand Down Expand Up @@ -220,34 +223,6 @@ static byte[] calcDetermined(long seed) throws Exception {
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");
Expand All @@ -266,7 +241,7 @@ static void delayed() throws Exception {
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() {
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
15 changes: 12 additions & 3 deletions test/jdk/javax/crypto/KEM/RSA_KEM.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -88,7 +89,7 @@ public static void main(String[] args) throws Exception {
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);
Expand All @@ -101,7 +102,7 @@ public static void main(String[] args) throws Exception {

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);
Expand All @@ -122,6 +123,14 @@ public static void main(String[] args) throws Exception {
}
}

// 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";

Expand Down

1 comment on commit 4ea14b2

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.