8230318: Better trust store usage

Reviewed-by: weijun, rhalade, ahgross
This commit is contained in:
Sean Mullan 2019-10-22 17:25:34 -04:00
parent 10b1e756e2
commit a0f8febb8b
16 changed files with 80 additions and 27 deletions

View file

@ -32,6 +32,7 @@ import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
import sun.security.action.GetBooleanAction;
import sun.security.action.GetPropertyAction;
import sun.security.provider.certpath.AlgorithmChecker;
import sun.security.provider.certpath.PKIXExtendedParameters;
@ -60,6 +61,18 @@ public final class PKIXValidator extends Validator {
private static final boolean checkTLSRevocation = GetBooleanAction
.privilegedGetProperty("com.sun.net.ssl.checkRevocation");
/**
* System property that if set (or set to "true"), allows trust anchor
* certificates to be used if they do not have the proper CA extensions.
* Set to false if prop is not set, or set to any other value.
*/
private static final boolean ALLOW_NON_CA_ANCHOR = allowNonCaAnchor();
private static boolean allowNonCaAnchor() {
String prop = GetPropertyAction
.privilegedGetProperty("jdk.security.allowNonCaAnchor");
return prop != null && (prop.isEmpty() || prop.equalsIgnoreCase("true"));
}
private final Set<X509Certificate> trustedCerts;
private final PKIXBuilderParameters parameterTemplate;
private int certPathLength = -1;
@ -311,15 +324,18 @@ public final class PKIXValidator extends Validator {
private static X509Certificate[] toArray(CertPath path, TrustAnchor anchor)
throws CertificateException {
List<? extends java.security.cert.Certificate> list =
path.getCertificates();
X509Certificate[] chain = new X509Certificate[list.size() + 1];
list.toArray(chain);
X509Certificate trustedCert = anchor.getTrustedCert();
if (trustedCert == null) {
throw new ValidatorException
("TrustAnchor must be specified as certificate");
}
verifyTrustAnchor(trustedCert);
List<? extends java.security.cert.Certificate> list =
path.getCertificates();
X509Certificate[] chain = new X509Certificate[list.size() + 1];
list.toArray(chain);
chain[chain.length - 1] = trustedCert;
return chain;
}
@ -354,6 +370,41 @@ public final class PKIXValidator extends Validator {
}
}
/**
* Verify that a trust anchor certificate is a CA certificate.
*/
private static void verifyTrustAnchor(X509Certificate trustedCert)
throws ValidatorException {
// skip check if jdk.security.allowNonCAAnchor system property is set
if (ALLOW_NON_CA_ANCHOR) {
return;
}
// allow v1 trust anchor certificates
if (trustedCert.getVersion() < 3) {
return;
}
// check that the BasicConstraints cA field is not set to false
if (trustedCert.getBasicConstraints() == -1) {
throw new ValidatorException
("TrustAnchor with subject \"" +
trustedCert.getSubjectX500Principal() +
"\" is not a CA certificate");
}
// check that the KeyUsage extension, if included, asserts the
// keyCertSign bit
boolean[] keyUsageBits = trustedCert.getKeyUsage();
if (keyUsageBits != null && !keyUsageBits[5]) {
throw new ValidatorException
("TrustAnchor with subject \"" +
trustedCert.getSubjectX500Principal() +
"\" does not have keyCertSign bit set in KeyUsage extension");
}
}
private X509Certificate[] doBuild(X509Certificate[] chain,
Collection<X509Certificate> otherCerts,
PKIXBuilderParameters params) throws CertificateException {