changeset 57699:bba2f6e36c17

8230318: Better trust store usage Reviewed-by: weijun, rhalade, ahgross
author mullan
date Tue, 22 Oct 2019 17:25:34 -0400
parents 7d517b51dea5
children 14e425e3a23c
files src/java.base/share/classes/sun/security/validator/PKIXValidator.java test/jdk/sun/security/tools/jarsigner/ConciseJarsigner.java test/jdk/sun/security/tools/jarsigner/DefaultOptions.java test/jdk/sun/security/tools/jarsigner/EC.java test/jdk/sun/security/tools/jarsigner/JavaKeyStoreAliasCaseInsensitive.java test/jdk/sun/security/tools/jarsigner/OnlyManifest.java test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java test/jdk/sun/security/tools/jarsigner/Warning.java test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java test/jdk/sun/security/validator/EndEntityExtensionCheck.java
diffstat 16 files changed, 80 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/sun/security/validator/PKIXValidator.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/src/java.base/share/classes/sun/security/validator/PKIXValidator.java	Tue Oct 22 17:25:34 2019 -0400
@@ -32,6 +32,7 @@
 
 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 @@
     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 @@
 
     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 @@
         }
     }
 
+    /**
+     * 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 {
--- a/test/jdk/sun/security/tools/jarsigner/ConciseJarsigner.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/ConciseJarsigner.java	Tue Oct 22 17:25:34 2019 -0400
@@ -244,8 +244,8 @@
         // ==========================================================
 
         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");
--- a/test/jdk/sun/security/tools/jarsigner/DefaultOptions.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/DefaultOptions.java	Tue Oct 22 17:25:34 2019 -0400
@@ -59,7 +59,7 @@
     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");
--- a/test/jdk/sun/security/tools/jarsigner/EC.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/EC.java	Tue Oct 22 17:25:34 2019 -0400
@@ -59,7 +59,7 @@
         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);
--- a/test/jdk/sun/security/tools/jarsigner/JavaKeyStoreAliasCaseInsensitive.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/JavaKeyStoreAliasCaseInsensitive.java	Tue Oct 22 17:25:34 2019 -0400
@@ -90,7 +90,7 @@
                 + " 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);
--- a/test/jdk/sun/security/tools/jarsigner/OnlyManifest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/OnlyManifest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -52,7 +52,7 @@
         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);
--- a/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/TsacertOptionTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
                 "-storepass", PASSWORD,
                 "-keypass", PASSWORD,
                 "-dname", "CN=CA",
+                "-ext", "bc:c",
                 "-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
         keytool(
                 "-genkey",
--- a/test/jdk/sun/security/tools/jarsigner/Warning.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/Warning.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
 
         Files.deleteIfExists(Paths.get("ks"));
 
-        newCert("ca", "-validity 365000");
+        newCert("ca", "-validity 365000", "-ext bc:c");
 
         recreateJar();
 
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadExtendedKeyUsageTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
         // 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(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/BadNetscapeCertTypeTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
         // 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(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/ChainNotValidatedTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
         // 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",
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasExpiringCertTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
         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(
--- a/test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/HasUnsignedEntryTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
         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,
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NoTimestampTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -72,7 +72,7 @@
         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));
--- a/test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/tools/jarsigner/warnings/NotSignedByAliasTest.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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 @@
         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);
--- a/test/jdk/sun/security/validator/EndEntityExtensionCheck.java	Wed Oct 16 19:01:22 2019 +0100
+++ b/test/jdk/sun/security/validator/EndEntityExtensionCheck.java	Tue Oct 22 17:25:34 2019 -0400
@@ -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;