Skip to content

Commit 9fd855e

Browse files
committedJan 11, 2024
8322971: KEM.getInstance() should check if a 3rd-party security provider is signed
Reviewed-by: mullan, valeriep
1 parent b8ae4a8 commit 9fd855e

File tree

4 files changed

+90
-45
lines changed

4 files changed

+90
-45
lines changed
 

‎src/java.base/share/classes/javax/crypto/KEM.java

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
2929
import java.security.*;
3030
import java.security.InvalidAlgorithmParameterException;
3131
import java.security.spec.AlgorithmParameterSpec;
32+
import java.util.ArrayList;
3233
import java.util.List;
3334
import java.util.Objects;
3435

@@ -539,10 +540,19 @@ public static KEM getInstance(String algorithm)
539540
List<Provider.Service> list = GetInstance.getServices(
540541
"KEM",
541542
Objects.requireNonNull(algorithm, "null algorithm name"));
542-
if (list.isEmpty()) {
543-
throw new NoSuchAlgorithmException(algorithm + " KEM not available");
543+
List<Provider.Service> allowed = new ArrayList<>();
544+
for (Provider.Service s : list) {
545+
if (!JceSecurity.canUseProvider(s.getProvider())) {
546+
continue;
547+
}
548+
allowed.add(s);
549+
}
550+
if (allowed.isEmpty()) {
551+
throw new NoSuchAlgorithmException
552+
(algorithm + " KEM not available");
544553
}
545-
return new KEM(algorithm, new DelayedKEM(list.toArray(new Provider.Service[0])));
554+
555+
return new KEM(algorithm, new DelayedKEM(allowed.toArray(new Provider.Service[0])));
546556
}
547557

548558
/**
@@ -568,7 +578,7 @@ public static KEM getInstance(String algorithm, Provider provider)
568578
if (provider == null) {
569579
return getInstance(algorithm);
570580
}
571-
GetInstance.Instance instance = GetInstance.getInstance(
581+
GetInstance.Instance instance = JceSecurity.getInstance(
572582
"KEM",
573583
KEMSpi.class,
574584
Objects.requireNonNull(algorithm, "null algorithm name"),
@@ -601,7 +611,7 @@ public static KEM getInstance(String algorithm, String provider)
601611
if (provider == null) {
602612
return getInstance(algorithm);
603613
}
604-
GetInstance.Instance instance = GetInstance.getInstance(
614+
GetInstance.Instance instance = JceSecurity.getInstance(
605615
"KEM",
606616
KEMSpi.class,
607617
Objects.requireNonNull(algorithm, "null algorithm name"),

‎test/jdk/com/sun/crypto/provider/DHKEM/Compliance.java

+11-36
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,9 @@
2626
* @bug 8297878
2727
* @summary Key Encapsulation Mechanism API
2828
* @library /test/lib
29+
* @build java.base/com.sun.crypto.provider.EvenKEMImpl
2930
* @modules java.base/com.sun.crypto.provider
31+
* @run main/othervm Compliance
3032
*/
3133
import jdk.test.lib.Asserts;
3234
import jdk.test.lib.Utils;
@@ -45,18 +47,19 @@
4547

4648
import com.sun.crypto.provider.DHKEM;
4749

50+
import static com.sun.crypto.provider.EvenKEMImpl.isEven;
51+
4852
public class Compliance {
4953

5054
public static void main(String[] args) throws Exception {
5155
basic();
5256
conform();
5357
determined();
54-
try {
55-
Security.insertProviderAt(new ProviderImpl(), 1);
56-
delayed();
57-
} finally {
58-
Security.removeProvider("XP");
59-
}
58+
// Patch an alternate DHKEM in SunEC which is ahead of SunJCE
59+
// in security provider listing.
60+
Security.getProvider("SunEC")
61+
.put("KEM.DHKEM", "com.sun.crypto.provider.EvenKEMImpl");
62+
delayed();
6063
}
6164

6265
// Encapsulated conformance checks
@@ -220,34 +223,6 @@ static byte[] calcDetermined(long seed) throws Exception {
220223
return enc2;
221224
}
222225

223-
public static class ProviderImpl extends Provider {
224-
ProviderImpl() {
225-
super("XP", "1", "XP");
226-
put("KEM.DHKEM", "Compliance$KEMImpl");
227-
}
228-
}
229-
230-
static boolean isEven(Key k) {
231-
return Arrays.hashCode(k.getEncoded()) % 2 == 0;
232-
}
233-
234-
public static class KEMImpl extends DHKEM {
235-
236-
@Override
237-
public EncapsulatorSpi engineNewEncapsulator(PublicKey pk, AlgorithmParameterSpec spec, SecureRandom secureRandom)
238-
throws InvalidAlgorithmParameterException, InvalidKeyException {
239-
if (!isEven(pk)) throw new InvalidKeyException("Only accept even keys");
240-
return super.engineNewEncapsulator(pk, spec, secureRandom);
241-
}
242-
243-
@Override
244-
public DecapsulatorSpi engineNewDecapsulator(PrivateKey sk, AlgorithmParameterSpec spec)
245-
throws InvalidAlgorithmParameterException, InvalidKeyException {
246-
if (!isEven(sk)) throw new InvalidKeyException("Only accept even keys");
247-
return super.engineNewDecapsulator(sk, spec);
248-
}
249-
}
250-
251226
// Ensure delayed provider selection
252227
static void delayed() throws Exception {
253228
KeyPairGenerator g = KeyPairGenerator.getInstance("X25519");
@@ -266,7 +241,7 @@ static void delayed() throws Exception {
266241
KEM.Encapsulator eodd = kem.newEncapsulator(odd);
267242
KEM.Encapsulator eeven = kem.newEncapsulator(even);
268243
Asserts.assertEQ(eodd.providerName(), "SunJCE");
269-
Asserts.assertEQ(eeven.providerName(), "XP");
244+
Asserts.assertEQ(eeven.providerName(), "SunEC");
270245
}
271246

272247
static ECPublicKey badECKey() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package com.sun.crypto.provider;
24+
25+
import java.security.*;
26+
import java.security.spec.*;
27+
import java.util.Arrays;
28+
29+
// The alternate DHKEM implementation used by the Compliance.java test.
30+
public class EvenKEMImpl extends DHKEM {
31+
32+
public static boolean isEven(Key k) {
33+
return Arrays.hashCode(k.getEncoded()) % 2 == 0;
34+
}
35+
36+
@Override
37+
public EncapsulatorSpi engineNewEncapsulator(
38+
PublicKey pk, AlgorithmParameterSpec spec, SecureRandom secureRandom)
39+
throws InvalidAlgorithmParameterException, InvalidKeyException {
40+
if (!isEven(pk)) throw new InvalidKeyException("Only accept even keys");
41+
return super.engineNewEncapsulator(pk, spec, secureRandom);
42+
}
43+
44+
@Override
45+
public DecapsulatorSpi engineNewDecapsulator(
46+
PrivateKey sk, AlgorithmParameterSpec spec)
47+
throws InvalidAlgorithmParameterException, InvalidKeyException {
48+
if (!isEven(sk)) throw new InvalidKeyException("Only accept even keys");
49+
return super.engineNewDecapsulator(sk, spec);
50+
}
51+
}

‎test/jdk/javax/crypto/KEM/RSA_KEM.java

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
2828
* @modules java.base/sun.security.jca
2929
* java.base/sun.security.rsa
3030
* java.base/sun.security.util
31+
* java.base/javax.crypto:+open
3132
*/
3233
import sun.security.jca.JCAUtil;
3334
import sun.security.rsa.RSACore;
@@ -88,7 +89,7 @@ public static void main(String[] args) throws Exception {
8889
KeyPair kp = g.generateKeyPair();
8990
for (RSAKEMParameterSpec kspec : kspecs) {
9091
SecretKey cek = KeyGenerator.getInstance("AES").generateKey();
91-
KEM kem1 = KEM.getInstance("RSA-KEM", p);
92+
KEM kem1 = getKemImpl(p);
9293
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
9394
c.init(Cipher.ENCRYPT_MODE, cek, new IvParameterSpec(iv));
9495
byte[] ciphertext = c.doFinal(msg);
@@ -101,7 +102,7 @@ public static void main(String[] args) throws Exception {
101102

102103
AlgorithmParameters a = AlgorithmParameters.getInstance("RSA-KEM", p);
103104
a.init(enc.params());
104-
KEM kem2 = KEM.getInstance("RSA-KEM", p);
105+
KEM kem2 = getKemImpl(p);
105106
KEM.Decapsulator d = kem2.newDecapsulator(kp.getPrivate(), a.getParameterSpec(AlgorithmParameterSpec.class));
106107
SecretKey k = d.decapsulate(enc.encapsulation(), 0, d.secretSize(), "AES");
107108
Cipher c3 = Cipher.getInstance(kspec.encAlg);
@@ -122,6 +123,14 @@ public static void main(String[] args) throws Exception {
122123
}
123124
}
124125

126+
// To bypass the JCE security provider signature check
127+
private static KEM getKemImpl(Provider p) throws Exception {
128+
var ctor = KEM.class.getDeclaredConstructor(
129+
String.class, KEMSpi.class, Provider.class);
130+
ctor.setAccessible(true);
131+
return ctor.newInstance("RSA-KEM", new KEMImpl(), p);
132+
}
133+
125134
static final String RSA_KEM = "1.2.840.113549.1.9.16.3.14";
126135
static final String KEM_RSA = "1.0.18033.2.2.4";
127136

0 commit comments

Comments
 (0)