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 {

View File

@ -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");

View File

@ -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");

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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",

View File

@ -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();

View File

@ -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(

View File

@ -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(

View File

@ -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",

View File

@ -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(

View File

@ -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,

View File

@ -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));

View File

@ -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);

View File

@ -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;