Skip to content

Commit ef6eafc

Browse files
martinuyfranferrax
andcommitted
8315487: Security Providers Filter
Co-authored-by: Francisco Ferrari Bihurriet <[email protected]> Co-authored-by: Martin Balao <[email protected]>
1 parent 21d361e commit ef6eafc

File tree

23 files changed

+4248
-542
lines changed

23 files changed

+4248
-542
lines changed

src/java.base/share/classes/java/security/KeyStore.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import javax.security.auth.DestroyFailedException;
3737
import javax.security.auth.callback.*;
3838

39+
import sun.security.jca.ProvidersFilter;
3940
import sun.security.util.Debug;
4041

4142
/**
@@ -1793,7 +1794,8 @@ private static final KeyStore getInstance(File file, char[] password,
17931794
// Detect the keystore type
17941795
for (Provider p : Security.getProviders()) {
17951796
for (Provider.Service s : p.getServices()) {
1796-
if (s.getType().equals("KeyStore")) {
1797+
if (ProvidersFilter.isAllowed(s) &&
1798+
s.getType().equals("KeyStore")) {
17971799
try {
17981800
KeyStoreSpi impl = (KeyStoreSpi) s.newInstance(null);
17991801
if (impl.engineProbe(dataStream)) {

src/java.base/share/classes/java/security/Provider.java

Lines changed: 1303 additions & 393 deletions
Large diffs are not rendered by default.

src/java.base/share/classes/java/security/SecureRandom.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import sun.security.jca.GetInstance;
3030
import sun.security.jca.GetInstance.Instance;
3131
import sun.security.jca.Providers;
32+
import sun.security.jca.ProvidersFilter;
3233
import sun.security.provider.SunEntries;
3334
import sun.security.util.Debug;
3435

@@ -277,7 +278,13 @@ private void getDefaultPRNG(boolean setSeed, byte[] seed) {
277278
if (p.getName().equals("SUN")) {
278279
prngAlgorithm = SunEntries.DEF_SECURE_RANDOM_ALGO;
279280
prngService = p.getService("SecureRandom", prngAlgorithm);
280-
break;
281+
if (prngService != null) {
282+
if (ProvidersFilter.isAllowed(prngService)) {
283+
break;
284+
} else {
285+
prngService = null;
286+
}
287+
}
281288
} else {
282289
prngService = p.getDefaultSecureRandomService();
283290
if (prngService != null) {
@@ -290,8 +297,13 @@ private void getDefaultPRNG(boolean setSeed, byte[] seed) {
290297
// then an implementation-specific default is returned.
291298
if (prngService == null) {
292299
prngAlgorithm = "SHA1PRNG";
293-
this.secureRandomSpi = new sun.security.provider.SecureRandom();
294300
this.provider = Providers.getSunProvider();
301+
try {
302+
this.secureRandomSpi = SecureRandom.getInstance(prngAlgorithm,
303+
this.provider).secureRandomSpi;
304+
} catch (NoSuchAlgorithmException nsae) {
305+
throw new RuntimeException("Default PRNG not found", nsae);
306+
}
295307
} else {
296308
try {
297309
this.secureRandomSpi = (SecureRandomSpi)

src/java.base/share/classes/java/security/Security.java

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -237,23 +237,26 @@ private static ProviderProperty getProviderProperty(String key) {
237237
}
238238

239239
/**
240-
* Returns the property (if any) mapping the key for the given provider.
240+
* Returns a service allowed by the Providers filter given a service type,
241+
* algorithm and provider. Search is case-insensitive.
241242
*/
242-
private static String getProviderProperty(String key, Provider provider) {
243-
String prop = provider.getProperty(key);
244-
if (prop == null) {
245-
// Is there a match if we do a case-insensitive property name
246-
// comparison? Let's try ...
247-
for (Enumeration<Object> e = provider.keys();
248-
e.hasMoreElements(); ) {
249-
String matchKey = (String)e.nextElement();
250-
if (key.equalsIgnoreCase(matchKey)) {
251-
prop = provider.getProperty(matchKey);
243+
private static Provider.Service findService(String type, String algo,
244+
Provider provider) {
245+
// Try the fast path (when "type" has the exact case).
246+
Provider.Service foundSvc = provider.getService(type, algo);
247+
if (foundSvc == null) {
248+
// Try the slow path (when "type" does not have the exact case).
249+
for (Provider.Service svc : provider.getServices()) {
250+
if (svc.getType().equalsIgnoreCase(type)) {
251+
foundSvc = provider.getService(svc.getType(), algo);
252252
break;
253253
}
254254
}
255255
}
256-
return prop;
256+
if (foundSvc != null && ProvidersFilter.isAllowed(foundSvc)) {
257+
return foundSvc;
258+
}
259+
return null;
257260
}
258261

259262
/**
@@ -877,30 +880,9 @@ private boolean isCompositeValue() {
877880
* the selection criterion key:value.
878881
*/
879882
private boolean isCriterionSatisfied(Provider prov) {
880-
// Constructed key have ONLY 1 space between algName and attrName
881-
String key = serviceName + '.' + algName +
882-
(attrName != null ? (' ' + attrName) : "");
883-
884-
// Check whether the provider has a property
885-
// whose key is the same as the given key.
886-
String propValue = getProviderProperty(key, prov);
887-
888-
if (propValue == null) {
889-
// Check whether we have an alias instead
890-
// of a standard name in the key.
891-
String standardName = getProviderProperty("Alg.Alias." +
892-
serviceName + "." + algName, prov);
893-
if (standardName != null) {
894-
key = serviceName + "." + standardName +
895-
(attrName != null ? ' ' + attrName : "");
896-
propValue = getProviderProperty(key, prov);
897-
}
898-
899-
if (propValue == null) {
900-
// The provider doesn't have the given
901-
// key in its property list.
902-
return false;
903-
}
883+
Provider.Service svc = findService(serviceName, algName, prov);
884+
if (svc == null) {
885+
return false;
904886
}
905887

906888
// If the key is in the format of:
@@ -910,6 +892,11 @@ private boolean isCriterionSatisfied(Provider prov) {
910892
return true;
911893
}
912894

895+
String foundAttrValue = svc.getAttribute(attrName);
896+
if (foundAttrValue == null) {
897+
return false;
898+
}
899+
913900
// If we get here, the key must be in the
914901
// format of <crypto_service>.<algorithm_or_type> <attribute_name>.
915902

@@ -920,24 +907,24 @@ private boolean isCriterionSatisfied(Provider prov) {
920907
// for a specific <crypto_service>.<algorithm>.
921908
if (attrName.equalsIgnoreCase("KeySize")) {
922909
int requestedSize = Integer.parseInt(attrValue);
923-
int maxSize = Integer.parseInt(propValue);
910+
int maxSize = Integer.parseInt(foundAttrValue);
924911
return requestedSize <= maxSize;
925912
}
926913

927914
// Handle attributes with composite values
928915
if (isCompositeValue()) {
929916
String attrValue2 = attrValue.toUpperCase(Locale.ENGLISH);
930-
propValue = propValue.toUpperCase(Locale.ENGLISH);
917+
foundAttrValue = foundAttrValue.toUpperCase(Locale.ENGLISH);
931918

932919
// match value to the property components
933-
String[] propComponents = propValue.split("\\|");
920+
String[] propComponents = foundAttrValue.split("\\|");
934921
for (String pc : propComponents) {
935922
if (attrValue2.equals(pc)) return true;
936923
}
937924
return false;
938925
} else {
939926
// direct string compare (ignore case)
940-
return attrValue.equalsIgnoreCase(propValue);
927+
return attrValue.equalsIgnoreCase(foundAttrValue);
941928
}
942929
}
943930
}

src/java.base/share/classes/java/security/Signature.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1996, 2023, 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
@@ -456,7 +456,7 @@ private static Signature getInstanceRSA(Provider p)
456456
throws NoSuchAlgorithmException {
457457
// try Signature first
458458
Service s = p.getService("Signature", RSA_SIGNATURE);
459-
if (s != null) {
459+
if (s != null && ProvidersFilter.isAllowed(s)) {
460460
Instance instance = GetInstance.getInstance(s, SignatureSpi.class);
461461
return getInstance(instance, RSA_SIGNATURE);
462462
}

src/java.base/share/classes/javax/crypto/Cipher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ public static final Cipher getInstance(String transformation,
712712
String paddingError = null;
713713
for (Transform tr : transforms) {
714714
Service s = provider.getService("Cipher", tr.transform);
715-
if (s == null) {
715+
if (s == null || !ProvidersFilter.isAllowed(s)) {
716716
continue;
717717
}
718718
if (providerChecked == false) {
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*
2-
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, Red Hat, Inc.
3+
*
34
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
45
*
56
* This code is free software; you can redistribute it and/or modify it
@@ -23,34 +24,14 @@
2324
* questions.
2425
*/
2526

26-
package sun.security.action;
27-
28-
import java.util.Map;
27+
package jdk.internal.access;
2928

3029
import java.security.Provider;
31-
import java.security.PrivilegedAction;
32-
33-
/**
34-
* A convenience PrivilegedAction class for setting the properties of
35-
* a provider. See the SunRsaSign provider for a usage example.
36-
*
37-
* @see sun.security.rsa.SunRsaSign
38-
* @author Andreas Sterbenz
39-
* @since 1.5
40-
*/
41-
public class PutAllAction implements PrivilegedAction<Void> {
42-
43-
private final Provider provider;
44-
private final Map<?, ?> map;
45-
46-
public PutAllAction(Provider provider, Map<?, ?> map) {
47-
this.provider = provider;
48-
this.map = map;
49-
}
50-
51-
public Void run() {
52-
provider.putAll(map);
53-
return null;
54-
}
30+
import java.util.List;
31+
import java.util.Set;
5532

33+
public interface JavaSecurityProviderAccess {
34+
Set<Provider.Service> getServicesNotAllowed(Provider p);
35+
List<String> getAliases(Provider.Service svc);
36+
boolean getIsAllowed(Provider.Service svc);
5637
}

src/java.base/share/classes/jdk/internal/access/SharedSecrets.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2023, 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
@@ -43,6 +43,7 @@
4343
import java.io.PrintWriter;
4444
import java.io.RandomAccessFile;
4545
import java.security.ProtectionDomain;
46+
import java.security.Provider;
4647
import java.security.Signature;
4748

4849
/** A repository of "shared secrets", which are a mechanism for
@@ -85,6 +86,7 @@ public class SharedSecrets {
8586
private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess;
8687
private static JavaSecurityAccess javaSecurityAccess;
8788
private static JavaSecurityPropertiesAccess javaSecurityPropertiesAccess;
89+
private static JavaSecurityProviderAccess javaSecurityProviderAccess;
8890
private static JavaSecuritySignatureAccess javaSecuritySignatureAccess;
8991
private static JavaSecuritySpecAccess javaSecuritySpecAccess;
9092
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
@@ -359,6 +361,20 @@ public static JavaSecurityPropertiesAccess getJavaSecurityPropertiesAccess() {
359361
return access;
360362
}
361363

364+
public static void setJavaSecurityProviderAccess(
365+
JavaSecurityProviderAccess jspa) {
366+
javaSecurityProviderAccess = jspa;
367+
}
368+
369+
public static JavaSecurityProviderAccess getJavaSecurityProviderAccess() {
370+
var access = javaSecurityProviderAccess;
371+
if (access == null) {
372+
ensureClassInitialized(Provider.class);
373+
access = javaSecurityProviderAccess;
374+
}
375+
return access;
376+
}
377+
362378
public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
363379
var access = javaUtilZipFileAccess;
364380
if (access == null) {

src/java.base/share/classes/module-info.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,9 @@
338338
exports sun.security.internal.spec to
339339
jdk.crypto.cryptoki;
340340
exports sun.security.jca to
341+
java.security.sasl,
341342
java.smartcardio,
343+
java.xml.crypto,
342344
jdk.crypto.cryptoki,
343345
jdk.naming.dns;
344346
exports sun.security.pkcs to

src/java.base/share/classes/sun/launcher/SecuritySettings.java

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
import java.security.NoSuchAlgorithmException;
3333
import java.security.Provider;
3434
import java.security.Security;
35-
import java.util.Collections;
3635
import java.util.Comparator;
3736
import java.util.List;
3837
import java.util.Properties;
@@ -140,6 +139,30 @@ private static void printSecurityTLSConfig(boolean verbose) {
140139
ostream.println();
141140
}
142141

142+
private static void printSecurityProviderServices(
143+
Set<Provider.Service> services) {
144+
if (!services.isEmpty()) {
145+
services.stream().sorted(
146+
Comparator.comparing(Provider.Service::getType)
147+
.thenComparing(Provider.Service::getAlgorithm))
148+
.forEach(ps -> {
149+
ostream.println(THREEINDENT +
150+
ps.getType() + "." + ps.getAlgorithm());
151+
List<String> aliases = SharedSecrets
152+
.getJavaSecurityProviderAccess().getAliases(ps);
153+
154+
if (!aliases.isEmpty()) {
155+
ostream.println(wrappedString(
156+
aliases.stream().sorted()
157+
.collect(Collectors.joining(", ", INDENT + " aliases: [", "]")),
158+
80, " " + TWOINDENT, INDENT + THREEINDENT));
159+
}
160+
});
161+
} else {
162+
ostream.println(THREEINDENT + "<none>");
163+
}
164+
}
165+
143166
private static void printSecurityProviderConfig(boolean verbose) {
144167
ostream.println(INDENT + "Security provider static configuration: (in order of preference)");
145168
for (Provider p : Security.getProviders()) {
@@ -149,39 +172,14 @@ private static void printSecurityProviderConfig(boolean verbose) {
149172
}
150173
ostream.println(TWOINDENT + "Provider name: " + p.getName());
151174
if (verbose) {
152-
ostream.println(wrappedString(PROV_INFO_STRING + p.getInfo(), 80,
153-
TWOINDENT, THREEINDENT));
154-
ostream.println(TWOINDENT + "Provider services: (type : algorithm)");
155-
Set<Provider.Service> services = p.getServices();
156-
Set<String> keys = Collections.list(p.keys())
157-
.stream()
158-
.map(String.class::cast)
159-
.filter(s -> s.startsWith("Alg.Alias."))
160-
.collect(Collectors.toSet());
161-
if (!services.isEmpty()) {
162-
services.stream()
163-
.sorted(Comparator.comparing(Provider.Service::getType)
164-
.thenComparing(Provider.Service::getAlgorithm))
165-
.forEach(ps -> {
166-
ostream.println(THREEINDENT +
167-
ps.getType() + "." + ps.getAlgorithm());
168-
List<String> aliases = keys
169-
.stream()
170-
.filter(s -> s.startsWith("Alg.Alias." + ps.getType()))
171-
.filter(s -> p.getProperty(s).equals(ps.getAlgorithm()))
172-
.map(s -> s.substring(("Alg.Alias." + ps.getType() + ".").length()))
173-
.toList();
174-
175-
if (!aliases.isEmpty()) {
176-
ostream.println(wrappedString(
177-
aliases.stream()
178-
.collect(Collectors.joining(", ", INDENT + " aliases: [", "]")),
179-
80, " " + TWOINDENT, INDENT + THREEINDENT));
180-
}
181-
});
182-
} else {
183-
ostream.println(THREEINDENT + "<none>");
184-
}
175+
ostream.println(wrappedString(PROV_INFO_STRING + p.getInfo(),
176+
80, TWOINDENT, THREEINDENT));
177+
ostream.println(TWOINDENT + "Provider services allowed: (type : algorithm)");
178+
printSecurityProviderServices(p.getServices());
179+
ostream.println(TWOINDENT + "Provider services NOT allowed: (type : algorithm)");
180+
printSecurityProviderServices(
181+
SharedSecrets.getJavaSecurityProviderAccess()
182+
.getServicesNotAllowed(p));
185183
}
186184
}
187185
if (verbose) {

0 commit comments

Comments
 (0)