Skip to content

Commit

Permalink
8315487: Security Providers Filter
Browse files Browse the repository at this point in the history
Co-authored-by: Francisco Ferrari Bihurriet <[email protected]>
Co-authored-by: Martin Balao <[email protected]>
  • Loading branch information
martinuy and franferrax committed Nov 28, 2023
1 parent 21d361e commit ef6eafc
Show file tree
Hide file tree
Showing 23 changed files with 4,248 additions and 542 deletions.
4 changes: 3 additions & 1 deletion src/java.base/share/classes/java/security/KeyStore.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import javax.security.auth.DestroyFailedException;
import javax.security.auth.callback.*;

import sun.security.jca.ProvidersFilter;
import sun.security.util.Debug;

/**
Expand Down Expand Up @@ -1793,7 +1794,8 @@ private static final KeyStore getInstance(File file, char[] password,
// Detect the keystore type
for (Provider p : Security.getProviders()) {
for (Provider.Service s : p.getServices()) {
if (s.getType().equals("KeyStore")) {
if (ProvidersFilter.isAllowed(s) &&
s.getType().equals("KeyStore")) {
try {
KeyStoreSpi impl = (KeyStoreSpi) s.newInstance(null);
if (impl.engineProbe(dataStream)) {
Expand Down
1,696 changes: 1,303 additions & 393 deletions src/java.base/share/classes/java/security/Provider.java

Large diffs are not rendered by default.

16 changes: 14 additions & 2 deletions src/java.base/share/classes/java/security/SecureRandom.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import sun.security.jca.GetInstance;
import sun.security.jca.GetInstance.Instance;
import sun.security.jca.Providers;
import sun.security.jca.ProvidersFilter;
import sun.security.provider.SunEntries;
import sun.security.util.Debug;

Expand Down Expand Up @@ -277,7 +278,13 @@ private void getDefaultPRNG(boolean setSeed, byte[] seed) {
if (p.getName().equals("SUN")) {
prngAlgorithm = SunEntries.DEF_SECURE_RANDOM_ALGO;
prngService = p.getService("SecureRandom", prngAlgorithm);
break;
if (prngService != null) {
if (ProvidersFilter.isAllowed(prngService)) {
break;
} else {
prngService = null;
}
}
} else {
prngService = p.getDefaultSecureRandomService();
if (prngService != null) {
Expand All @@ -290,8 +297,13 @@ private void getDefaultPRNG(boolean setSeed, byte[] seed) {
// then an implementation-specific default is returned.
if (prngService == null) {
prngAlgorithm = "SHA1PRNG";
this.secureRandomSpi = new sun.security.provider.SecureRandom();
this.provider = Providers.getSunProvider();
try {
this.secureRandomSpi = SecureRandom.getInstance(prngAlgorithm,
this.provider).secureRandomSpi;
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException("Default PRNG not found", nsae);
}
} else {
try {
this.secureRandomSpi = (SecureRandomSpi)
Expand Down
67 changes: 27 additions & 40 deletions src/java.base/share/classes/java/security/Security.java
Original file line number Diff line number Diff line change
Expand Up @@ -237,23 +237,26 @@ private static ProviderProperty getProviderProperty(String key) {
}

/**
* Returns the property (if any) mapping the key for the given provider.
* Returns a service allowed by the Providers filter given a service type,
* algorithm and provider. Search is case-insensitive.
*/
private static String getProviderProperty(String key, Provider provider) {
String prop = provider.getProperty(key);
if (prop == null) {
// Is there a match if we do a case-insensitive property name
// comparison? Let's try ...
for (Enumeration<Object> e = provider.keys();
e.hasMoreElements(); ) {
String matchKey = (String)e.nextElement();
if (key.equalsIgnoreCase(matchKey)) {
prop = provider.getProperty(matchKey);
private static Provider.Service findService(String type, String algo,
Provider provider) {
// Try the fast path (when "type" has the exact case).
Provider.Service foundSvc = provider.getService(type, algo);
if (foundSvc == null) {
// Try the slow path (when "type" does not have the exact case).
for (Provider.Service svc : provider.getServices()) {
if (svc.getType().equalsIgnoreCase(type)) {
foundSvc = provider.getService(svc.getType(), algo);
break;
}
}
}
return prop;
if (foundSvc != null && ProvidersFilter.isAllowed(foundSvc)) {
return foundSvc;
}
return null;
}

/**
Expand Down Expand Up @@ -877,30 +880,9 @@ private boolean isCompositeValue() {
* the selection criterion key:value.
*/
private boolean isCriterionSatisfied(Provider prov) {
// Constructed key have ONLY 1 space between algName and attrName
String key = serviceName + '.' + algName +
(attrName != null ? (' ' + attrName) : "");

// Check whether the provider has a property
// whose key is the same as the given key.
String propValue = getProviderProperty(key, prov);

if (propValue == null) {
// Check whether we have an alias instead
// of a standard name in the key.
String standardName = getProviderProperty("Alg.Alias." +
serviceName + "." + algName, prov);
if (standardName != null) {
key = serviceName + "." + standardName +
(attrName != null ? ' ' + attrName : "");
propValue = getProviderProperty(key, prov);
}

if (propValue == null) {
// The provider doesn't have the given
// key in its property list.
return false;
}
Provider.Service svc = findService(serviceName, algName, prov);
if (svc == null) {
return false;
}

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

String foundAttrValue = svc.getAttribute(attrName);
if (foundAttrValue == null) {
return false;
}

// If we get here, the key must be in the
// format of <crypto_service>.<algorithm_or_type> <attribute_name>.

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

// Handle attributes with composite values
if (isCompositeValue()) {
String attrValue2 = attrValue.toUpperCase(Locale.ENGLISH);
propValue = propValue.toUpperCase(Locale.ENGLISH);
foundAttrValue = foundAttrValue.toUpperCase(Locale.ENGLISH);

// match value to the property components
String[] propComponents = propValue.split("\\|");
String[] propComponents = foundAttrValue.split("\\|");
for (String pc : propComponents) {
if (attrValue2.equals(pc)) return true;
}
return false;
} else {
// direct string compare (ignore case)
return attrValue.equalsIgnoreCase(propValue);
return attrValue.equalsIgnoreCase(foundAttrValue);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/java.base/share/classes/java/security/Signature.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2023, 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 @@ -456,7 +456,7 @@ private static Signature getInstanceRSA(Provider p)
throws NoSuchAlgorithmException {
// try Signature first
Service s = p.getService("Signature", RSA_SIGNATURE);
if (s != null) {
if (s != null && ProvidersFilter.isAllowed(s)) {
Instance instance = GetInstance.getInstance(s, SignatureSpi.class);
return getInstance(instance, RSA_SIGNATURE);
}
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/share/classes/javax/crypto/Cipher.java
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ public static final Cipher getInstance(String transformation,
String paddingError = null;
for (Transform tr : transforms) {
Service s = provider.getService("Cipher", tr.transform);
if (s == null) {
if (s == null || !ProvidersFilter.isAllowed(s)) {
continue;
}
if (providerChecked == false) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2023, Red Hat, Inc.
*
* 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 @@ -23,34 +24,14 @@
* questions.
*/

package sun.security.action;

import java.util.Map;
package jdk.internal.access;

import java.security.Provider;
import java.security.PrivilegedAction;

/**
* A convenience PrivilegedAction class for setting the properties of
* a provider. See the SunRsaSign provider for a usage example.
*
* @see sun.security.rsa.SunRsaSign
* @author Andreas Sterbenz
* @since 1.5
*/
public class PutAllAction implements PrivilegedAction<Void> {

private final Provider provider;
private final Map<?, ?> map;

public PutAllAction(Provider provider, Map<?, ?> map) {
this.provider = provider;
this.map = map;
}

public Void run() {
provider.putAll(map);
return null;
}
import java.util.List;
import java.util.Set;

public interface JavaSecurityProviderAccess {
Set<Provider.Service> getServicesNotAllowed(Provider p);
List<String> getAliases(Provider.Service svc);
boolean getIsAllowed(Provider.Service svc);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2023, 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 @@ -43,6 +43,7 @@
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.security.ProtectionDomain;
import java.security.Provider;
import java.security.Signature;

/** A repository of "shared secrets", which are a mechanism for
Expand Down Expand Up @@ -85,6 +86,7 @@ public class SharedSecrets {
private static JavaUtilResourceBundleAccess javaUtilResourceBundleAccess;
private static JavaSecurityAccess javaSecurityAccess;
private static JavaSecurityPropertiesAccess javaSecurityPropertiesAccess;
private static JavaSecurityProviderAccess javaSecurityProviderAccess;
private static JavaSecuritySignatureAccess javaSecuritySignatureAccess;
private static JavaSecuritySpecAccess javaSecuritySpecAccess;
private static JavaxCryptoSealedObjectAccess javaxCryptoSealedObjectAccess;
Expand Down Expand Up @@ -359,6 +361,20 @@ public static JavaSecurityPropertiesAccess getJavaSecurityPropertiesAccess() {
return access;
}

public static void setJavaSecurityProviderAccess(
JavaSecurityProviderAccess jspa) {
javaSecurityProviderAccess = jspa;
}

public static JavaSecurityProviderAccess getJavaSecurityProviderAccess() {
var access = javaSecurityProviderAccess;
if (access == null) {
ensureClassInitialized(Provider.class);
access = javaSecurityProviderAccess;
}
return access;
}

public static JavaUtilZipFileAccess getJavaUtilZipFileAccess() {
var access = javaUtilZipFileAccess;
if (access == null) {
Expand Down
2 changes: 2 additions & 0 deletions src/java.base/share/classes/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,9 @@
exports sun.security.internal.spec to
jdk.crypto.cryptoki;
exports sun.security.jca to
java.security.sasl,
java.smartcardio,
java.xml.crypto,
jdk.crypto.cryptoki,
jdk.naming.dns;
exports sun.security.pkcs to
Expand Down
66 changes: 32 additions & 34 deletions src/java.base/share/classes/sun/launcher/SecuritySettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;
Expand Down Expand Up @@ -140,6 +139,30 @@ private static void printSecurityTLSConfig(boolean verbose) {
ostream.println();
}

private static void printSecurityProviderServices(
Set<Provider.Service> services) {
if (!services.isEmpty()) {
services.stream().sorted(
Comparator.comparing(Provider.Service::getType)
.thenComparing(Provider.Service::getAlgorithm))
.forEach(ps -> {
ostream.println(THREEINDENT +
ps.getType() + "." + ps.getAlgorithm());
List<String> aliases = SharedSecrets
.getJavaSecurityProviderAccess().getAliases(ps);

if (!aliases.isEmpty()) {
ostream.println(wrappedString(
aliases.stream().sorted()
.collect(Collectors.joining(", ", INDENT + " aliases: [", "]")),
80, " " + TWOINDENT, INDENT + THREEINDENT));
}
});
} else {
ostream.println(THREEINDENT + "<none>");
}
}

private static void printSecurityProviderConfig(boolean verbose) {
ostream.println(INDENT + "Security provider static configuration: (in order of preference)");
for (Provider p : Security.getProviders()) {
Expand All @@ -149,39 +172,14 @@ private static void printSecurityProviderConfig(boolean verbose) {
}
ostream.println(TWOINDENT + "Provider name: " + p.getName());
if (verbose) {
ostream.println(wrappedString(PROV_INFO_STRING + p.getInfo(), 80,
TWOINDENT, THREEINDENT));
ostream.println(TWOINDENT + "Provider services: (type : algorithm)");
Set<Provider.Service> services = p.getServices();
Set<String> keys = Collections.list(p.keys())
.stream()
.map(String.class::cast)
.filter(s -> s.startsWith("Alg.Alias."))
.collect(Collectors.toSet());
if (!services.isEmpty()) {
services.stream()
.sorted(Comparator.comparing(Provider.Service::getType)
.thenComparing(Provider.Service::getAlgorithm))
.forEach(ps -> {
ostream.println(THREEINDENT +
ps.getType() + "." + ps.getAlgorithm());
List<String> aliases = keys
.stream()
.filter(s -> s.startsWith("Alg.Alias." + ps.getType()))
.filter(s -> p.getProperty(s).equals(ps.getAlgorithm()))
.map(s -> s.substring(("Alg.Alias." + ps.getType() + ".").length()))
.toList();

if (!aliases.isEmpty()) {
ostream.println(wrappedString(
aliases.stream()
.collect(Collectors.joining(", ", INDENT + " aliases: [", "]")),
80, " " + TWOINDENT, INDENT + THREEINDENT));
}
});
} else {
ostream.println(THREEINDENT + "<none>");
}
ostream.println(wrappedString(PROV_INFO_STRING + p.getInfo(),
80, TWOINDENT, THREEINDENT));
ostream.println(TWOINDENT + "Provider services allowed: (type : algorithm)");
printSecurityProviderServices(p.getServices());
ostream.println(TWOINDENT + "Provider services NOT allowed: (type : algorithm)");
printSecurityProviderServices(
SharedSecrets.getJavaSecurityProviderAccess()
.getServicesNotAllowed(p));
}
}
if (verbose) {
Expand Down
Loading

0 comments on commit ef6eafc

Please sign in to comment.