8230318: Better trust store usage
Reviewed-by: weijun, rhalade, ahgross
This commit is contained in:
parent
10b1e756e2
commit
a0f8febb8b
@ -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 {
|
||||
|
@ -244,8 +244,8 @@ public class ConciseJarsigner {
|
||||
// ==========================================================
|
||||
|
||||
kt("-genkeypair -alias ee -dname CN=ee");
|
||||
kt("-genkeypair -alias caone -dname CN=caone");
|
||||
kt("-genkeypair -alias catwo -dname CN=catwo");
|
||||
kt("-genkeypair -alias caone -dname CN=caone -ext bc:c");
|
||||
kt("-genkeypair -alias catwo -dname CN=catwo -ext bc:c");
|
||||
|
||||
kt("-certreq -alias ee -file ee.req");
|
||||
kt("-certreq -alias catwo -file catwo.req");
|
||||
|
@ -59,7 +59,7 @@ public class DefaultOptions {
|
||||
public static void main(String[] args) throws Throwable {
|
||||
keytool("-genkeypair -dname CN=A -alias a -keyalg rsa")
|
||||
.shouldHaveExitValue(0);
|
||||
keytool("-genkeypair -dname CN=CA -alias ca -keyalg rsa")
|
||||
keytool("-genkeypair -dname CN=CA -alias ca -keyalg rsa -ext bc:c")
|
||||
.shouldHaveExitValue(0);
|
||||
keytool("-alias a -certreq -file a.req");
|
||||
keytool("-alias ca -gencert -infile a.req -outfile a.cert");
|
||||
|
@ -59,7 +59,7 @@ public class EC {
|
||||
Files.write(Path.of("A"), List.of("A"));
|
||||
JarUtils.createJarFile(Path.of("a.jar"), Path.of("."), Path.of("A"));
|
||||
|
||||
kt("-alias ca -dname CN=ca -keyalg ec -genkey -validity 300")
|
||||
kt("-alias ca -dname CN=ca -keyalg ec -genkey -validity 300 -ext bc:c")
|
||||
.shouldHaveExitValue(0);
|
||||
kt("-alias a -dname CN=a -keyalg ec -genkey")
|
||||
.shouldHaveExitValue(0);
|
||||
|
@ -90,7 +90,7 @@ public class JavaKeyStoreAliasCaseInsensitive {
|
||||
+ " test-alias-storeHash-case.jks -storepass changeit";
|
||||
SecurityTools.keytool(KEYSTORE_OPTIONS + " -genkeypair -keyalg DSA"
|
||||
+ " -keypass changeit -alias " + ALIAS + "1 -dname CN=" +
|
||||
ALIAS + "1").shouldHaveExitValue(0);
|
||||
ALIAS + "1" + " -ext bc:c").shouldHaveExitValue(0);
|
||||
SecurityTools.keytool(KEYSTORE_OPTIONS + " -genkeypair -keyalg DSA"
|
||||
+ " -keypass changeit -alias " + ALIAS + "2 -dname CN="
|
||||
+ ALIAS + "2").shouldHaveExitValue(0);
|
||||
|
@ -52,7 +52,7 @@ public class OnlyManifest {
|
||||
Files.write(Path.of("manifest"), List.of("Key: Value"));
|
||||
SecurityTools.jar("cvfm a.jar manifest");
|
||||
|
||||
kt("-alias ca -dname CN=ca -genkey -validity 300")
|
||||
kt("-alias ca -dname CN=ca -genkey -validity 300 -ext bc:c")
|
||||
.shouldHaveExitValue(0);
|
||||
kt("-alias a -dname CN=a -genkey -validity 300")
|
||||
.shouldHaveExitValue(0);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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
|
||||
@ -74,6 +74,7 @@ public class TsacertOptionTest extends Test {
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=CA",
|
||||
"-ext", "bc:c",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
keytool(
|
||||
"-genkey",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -44,7 +44,7 @@ public class Warning {
|
||||
|
||||
Files.deleteIfExists(Paths.get("ks"));
|
||||
|
||||
newCert("ca", "-validity 365000");
|
||||
newCert("ca", "-validity 365000", "-ext bc:c");
|
||||
|
||||
recreateJar();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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
|
||||
@ -53,7 +53,7 @@ public class BadExtendedKeyUsageTest extends Test {
|
||||
// create a certificate whose signer certificate's
|
||||
// ExtendedKeyUsage extension doesn't allow code signing
|
||||
// create key pair for jar signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
|
||||
issueCert(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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
|
||||
@ -54,7 +54,7 @@ public class BadNetscapeCertTypeTest extends Test {
|
||||
// create a certificate whose signer certificate's
|
||||
// NetscapeCertType extension doesn't allow code signing
|
||||
// create key pair for jar signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
|
||||
issueCert(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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
|
||||
@ -54,7 +54,7 @@ public class ChainNotValidatedTest extends Test {
|
||||
// Root CA is not checked at all. If the intermediate CA has
|
||||
// BasicConstraints extension set to true, it will be valid.
|
||||
// Otherwise, chain validation will fail.
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(CA2_KEY_ALIAS);
|
||||
issueCert(CA2_KEY_ALIAS,
|
||||
"-ext",
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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
|
||||
@ -52,7 +52,7 @@ public class HasExpiringCertTest extends Test {
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair for jar signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
|
||||
issueCert(
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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
|
||||
@ -51,7 +51,7 @@ public class HasUnsignedEntryTest extends Test {
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair for signing
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
issueCert(
|
||||
KEY_ALIAS,
|
||||
|
@ -72,7 +72,7 @@ public class NoTimestampTest extends Test {
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
createAlias(KEY_ALIAS);
|
||||
issueCert(KEY_ALIAS,
|
||||
"-validity", Integer.toString(VALIDITY));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2019, 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
|
||||
@ -49,7 +49,7 @@ public class NotSignedByAliasTest extends Test {
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
createAlias(CA_KEY_ALIAS);
|
||||
createAlias(CA_KEY_ALIAS, "-ext", "bc:c");
|
||||
|
||||
// create first key pair for signing
|
||||
createAlias(FIRST_KEY_ALIAS);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, 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
|
||||
@ -27,6 +27,7 @@
|
||||
* @summary EndEntityChecker should not process custom extensions
|
||||
* after PKIX validation
|
||||
* @modules java.base/sun.security.validator
|
||||
* @run main/othervm -Djdk.security.allowNonCaAnchor EndEntityExtensionCheck
|
||||
*/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
Loading…
x
Reference in New Issue
Block a user