mirror of
https://github.com/openjdk/jdk23u.git
synced 2025-12-10 20:36:28 -06:00
8339560: Unaddressed comments during code review of JDK-8337664
Reviewed-by: coffeys Backport-of: 95d3e9d199600bac0284f9151b99aef152e027ac
This commit is contained in:
parent
605f8dda34
commit
83aab07c9a
@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2018, 2022, 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
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.math.BigInteger;
|
|
||||||
import java.security.*;
|
|
||||||
import java.security.cert.*;
|
|
||||||
import java.time.*;
|
|
||||||
import java.util.*;
|
|
||||||
import javax.net.ssl.*;
|
|
||||||
import sun.security.validator.Validator;
|
|
||||||
import sun.security.validator.ValidatorException;
|
|
||||||
|
|
||||||
import jdk.test.lib.security.SecurityUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @test
|
|
||||||
* @bug 8207258 8216280
|
|
||||||
* @summary Check that TLS Server certificates chaining back to distrusted
|
|
||||||
* Symantec roots are invalid
|
|
||||||
* @library /test/lib
|
|
||||||
* @modules java.base/sun.security.validator
|
|
||||||
* @run main/othervm Distrust after policyOn invalid
|
|
||||||
* @run main/othervm Distrust after policyOff valid
|
|
||||||
* @run main/othervm Distrust before policyOn valid
|
|
||||||
* @run main/othervm Distrust before policyOff valid
|
|
||||||
*/
|
|
||||||
|
|
||||||
public class Distrust {
|
|
||||||
|
|
||||||
private static final String TEST_SRC = System.getProperty("test.src", ".");
|
|
||||||
private static CertificateFactory cf;
|
|
||||||
|
|
||||||
// Each of the roots have a test certificate chain stored in a file
|
|
||||||
// named "<root>-chain.pem".
|
|
||||||
private static String[] rootsToTest = new String[] {
|
|
||||||
"geotrustprimarycag2", "geotrustprimarycag3",
|
|
||||||
"geotrustuniversalca", "thawteprimaryrootca", "thawteprimaryrootcag2",
|
|
||||||
"thawteprimaryrootcag3", "verisignclass3g3ca", "verisignclass3g4ca",
|
|
||||||
"verisignclass3g5ca", "verisignuniversalrootca" };
|
|
||||||
|
|
||||||
// Each of the subCAs with a delayed distrust date have a test certificate
|
|
||||||
// chain stored in a file named "<subCA>-chain.pem".
|
|
||||||
private static String[] subCAsToTest = new String[]{"appleistca8g1"};
|
|
||||||
|
|
||||||
// A date that is after the restrictions take affect
|
|
||||||
private static final Date APRIL_17_2019 =
|
|
||||||
Date.from(LocalDate.of(2019, 4, 17)
|
|
||||||
.atStartOfDay(ZoneOffset.UTC)
|
|
||||||
.toInstant());
|
|
||||||
|
|
||||||
// A date that is a second before the restrictions take affect
|
|
||||||
private static final Date BEFORE_APRIL_17_2019 =
|
|
||||||
Date.from(LocalDate.of(2019, 4, 17)
|
|
||||||
.atStartOfDay(ZoneOffset.UTC)
|
|
||||||
.minusSeconds(1)
|
|
||||||
.toInstant());
|
|
||||||
|
|
||||||
// A date that is after the subCA restrictions take affect
|
|
||||||
private static final Date JANUARY_1_2020 =
|
|
||||||
Date.from(LocalDate.of(2020, 1, 1)
|
|
||||||
.atStartOfDay(ZoneOffset.UTC)
|
|
||||||
.toInstant());
|
|
||||||
|
|
||||||
// A date that is a second before the subCA restrictions take affect
|
|
||||||
private static final Date BEFORE_JANUARY_1_2020 =
|
|
||||||
Date.from(LocalDate.of(2020, 1, 1)
|
|
||||||
.atStartOfDay(ZoneOffset.UTC)
|
|
||||||
.minusSeconds(1)
|
|
||||||
.toInstant());
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
|
|
||||||
cf = CertificateFactory.getInstance("X.509");
|
|
||||||
|
|
||||||
boolean before = args[0].equals("before");
|
|
||||||
boolean policyOn = args[1].equals("policyOn");
|
|
||||||
boolean isValid = args[2].equals("valid");
|
|
||||||
|
|
||||||
if (!policyOn) {
|
|
||||||
// disable policy (default is on)
|
|
||||||
Security.setProperty("jdk.security.caDistrustPolicies", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
Date notBefore = before ? BEFORE_APRIL_17_2019 : APRIL_17_2019;
|
|
||||||
|
|
||||||
X509TrustManager pkixTM = getTMF("PKIX", null);
|
|
||||||
X509TrustManager sunX509TM = getTMF("SunX509", null);
|
|
||||||
for (String test : rootsToTest) {
|
|
||||||
System.err.println("Testing " + test);
|
|
||||||
X509Certificate[] chain = loadCertificateChain(test);
|
|
||||||
|
|
||||||
testTM(sunX509TM, chain, notBefore, isValid);
|
|
||||||
testTM(pkixTM, chain, notBefore, isValid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// test chain if params are passed to TrustManager
|
|
||||||
System.err.println("Testing verisignuniversalrootca with params");
|
|
||||||
testTM(getTMF("PKIX", getParams()),
|
|
||||||
loadCertificateChain("verisignuniversalrootca"),
|
|
||||||
notBefore, isValid);
|
|
||||||
|
|
||||||
// test code-signing chain (should be valid as restrictions don't apply)
|
|
||||||
System.err.println("Testing verisignclass3g5ca code-signing chain");
|
|
||||||
Validator v = Validator.getInstance(Validator.TYPE_PKIX,
|
|
||||||
Validator.VAR_CODE_SIGNING,
|
|
||||||
getParams());
|
|
||||||
// set validation date so this will still pass when cert expires
|
|
||||||
v.setValidationDate(new Date(1544197375493l));
|
|
||||||
v.validate(loadCertificateChain("verisignclass3g5ca-codesigning"));
|
|
||||||
|
|
||||||
// test chains issued through subCAs
|
|
||||||
notBefore = before ? BEFORE_JANUARY_1_2020 : JANUARY_1_2020;
|
|
||||||
for (String test : subCAsToTest) {
|
|
||||||
System.err.println("Testing " + test);
|
|
||||||
X509Certificate[] chain = loadCertificateChain(test);
|
|
||||||
|
|
||||||
testTM(sunX509TM, chain, notBefore, isValid);
|
|
||||||
testTM(pkixTM, chain, notBefore, isValid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static X509TrustManager getTMF(String type,
|
|
||||||
PKIXBuilderParameters params) throws Exception {
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(type);
|
|
||||||
if (params == null) {
|
|
||||||
tmf.init((KeyStore)null);
|
|
||||||
} else {
|
|
||||||
tmf.init(new CertPathTrustManagerParameters(params));
|
|
||||||
}
|
|
||||||
TrustManager[] tms = tmf.getTrustManagers();
|
|
||||||
for (TrustManager tm : tms) {
|
|
||||||
X509TrustManager xtm = (X509TrustManager)tm;
|
|
||||||
return xtm;
|
|
||||||
}
|
|
||||||
throw new Exception("No TrustManager for " + type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static PKIXBuilderParameters getParams() throws Exception {
|
|
||||||
PKIXBuilderParameters pbp =
|
|
||||||
new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(),
|
|
||||||
new X509CertSelector());
|
|
||||||
pbp.setRevocationEnabled(false);
|
|
||||||
return pbp;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void testTM(X509TrustManager xtm, X509Certificate[] chain,
|
|
||||||
Date notBefore, boolean valid) throws Exception {
|
|
||||||
// Check if TLS Server certificate (the first element of the chain)
|
|
||||||
// is issued after the specified notBefore date (should be rejected
|
|
||||||
// unless distrust property is false). To do this, we need to
|
|
||||||
// fake the notBefore date since none of the test certs are issued
|
|
||||||
// after then.
|
|
||||||
chain[0] = new DistrustedTLSServerCert(chain[0], notBefore);
|
|
||||||
|
|
||||||
try {
|
|
||||||
xtm.checkServerTrusted(chain, "ECDHE_RSA");
|
|
||||||
if (!valid) {
|
|
||||||
throw new Exception("chain should be invalid");
|
|
||||||
}
|
|
||||||
} catch (CertificateException ce) {
|
|
||||||
// expired TLS certificates should not be treated as failure
|
|
||||||
if (expired(ce)) {
|
|
||||||
System.err.println("Test is N/A, chain is expired");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (valid) {
|
|
||||||
throw new Exception("Unexpected exception, chain " +
|
|
||||||
"should be valid", ce);
|
|
||||||
}
|
|
||||||
if (ce instanceof ValidatorException) {
|
|
||||||
ValidatorException ve = (ValidatorException)ce;
|
|
||||||
if (ve.getErrorType() != ValidatorException.T_UNTRUSTED_CERT) {
|
|
||||||
ce.printStackTrace(System.err);
|
|
||||||
throw new Exception("Unexpected exception: " + ce);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new Exception("Unexpected exception: " + ce);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if a cause of exception is an expired cert
|
|
||||||
private static boolean expired(CertificateException ce) {
|
|
||||||
if (ce instanceof CertificateExpiredException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Throwable t = ce.getCause();
|
|
||||||
while (t != null) {
|
|
||||||
if (t instanceof CertificateExpiredException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
t = t.getCause();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static X509Certificate[] loadCertificateChain(String name)
|
|
||||||
throws Exception {
|
|
||||||
try (InputStream in = new FileInputStream(TEST_SRC + File.separator +
|
|
||||||
name + "-chain.pem")) {
|
|
||||||
Collection<X509Certificate> certs =
|
|
||||||
(Collection<X509Certificate>)cf.generateCertificates(in);
|
|
||||||
return certs.toArray(new X509Certificate[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class DistrustedTLSServerCert extends X509Certificate {
|
|
||||||
private final X509Certificate cert;
|
|
||||||
private final Date notBefore;
|
|
||||||
DistrustedTLSServerCert(X509Certificate cert, Date notBefore) {
|
|
||||||
this.cert = cert;
|
|
||||||
this.notBefore = notBefore;
|
|
||||||
}
|
|
||||||
public Set<String> getCriticalExtensionOIDs() {
|
|
||||||
return cert.getCriticalExtensionOIDs();
|
|
||||||
}
|
|
||||||
public byte[] getExtensionValue(String oid) {
|
|
||||||
return cert.getExtensionValue(oid);
|
|
||||||
}
|
|
||||||
public Set<String> getNonCriticalExtensionOIDs() {
|
|
||||||
return cert.getNonCriticalExtensionOIDs();
|
|
||||||
}
|
|
||||||
public boolean hasUnsupportedCriticalExtension() {
|
|
||||||
return cert.hasUnsupportedCriticalExtension();
|
|
||||||
}
|
|
||||||
public void checkValidity() throws CertificateExpiredException,
|
|
||||||
CertificateNotYetValidException {
|
|
||||||
// always pass
|
|
||||||
}
|
|
||||||
public void checkValidity(Date date) throws CertificateExpiredException,
|
|
||||||
CertificateNotYetValidException {
|
|
||||||
// always pass
|
|
||||||
}
|
|
||||||
public int getVersion() { return cert.getVersion(); }
|
|
||||||
public BigInteger getSerialNumber() { return cert.getSerialNumber(); }
|
|
||||||
public Principal getIssuerDN() { return cert.getIssuerDN(); }
|
|
||||||
public Principal getSubjectDN() { return cert.getSubjectDN(); }
|
|
||||||
public Date getNotBefore() { return notBefore; }
|
|
||||||
public Date getNotAfter() { return cert.getNotAfter(); }
|
|
||||||
public byte[] getTBSCertificate() throws CertificateEncodingException {
|
|
||||||
return cert.getTBSCertificate();
|
|
||||||
}
|
|
||||||
public byte[] getSignature() { return cert.getSignature(); }
|
|
||||||
public String getSigAlgName() { return cert.getSigAlgName(); }
|
|
||||||
public String getSigAlgOID() { return cert.getSigAlgOID(); }
|
|
||||||
public byte[] getSigAlgParams() { return cert.getSigAlgParams(); }
|
|
||||||
public boolean[] getIssuerUniqueID() {
|
|
||||||
return cert.getIssuerUniqueID();
|
|
||||||
}
|
|
||||||
public boolean[] getSubjectUniqueID() {
|
|
||||||
return cert.getSubjectUniqueID();
|
|
||||||
}
|
|
||||||
public boolean[] getKeyUsage() { return cert.getKeyUsage(); }
|
|
||||||
public int getBasicConstraints() { return cert.getBasicConstraints(); }
|
|
||||||
public byte[] getEncoded() throws CertificateEncodingException {
|
|
||||||
return cert.getEncoded();
|
|
||||||
}
|
|
||||||
public void verify(PublicKey key) throws CertificateException,
|
|
||||||
InvalidKeyException, NoSuchAlgorithmException,
|
|
||||||
NoSuchProviderException, SignatureException {
|
|
||||||
cert.verify(key);
|
|
||||||
}
|
|
||||||
public void verify(PublicKey key, String sigProvider) throws
|
|
||||||
CertificateException, InvalidKeyException, NoSuchAlgorithmException,
|
|
||||||
NoSuchProviderException, SignatureException {
|
|
||||||
cert.verify(key, sigProvider);
|
|
||||||
}
|
|
||||||
public PublicKey getPublicKey() { return cert.getPublicKey(); }
|
|
||||||
public String toString() { return cert.toString(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -25,7 +25,7 @@ import java.io.*;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.cert.*;
|
import java.security.cert.*;
|
||||||
import java.time.*;
|
import java.time.ZonedDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javax.net.ssl.*;
|
import javax.net.ssl.*;
|
||||||
import sun.security.validator.Validator;
|
import sun.security.validator.Validator;
|
||||||
@ -34,95 +34,80 @@ import sun.security.validator.ValidatorException;
|
|||||||
import jdk.test.lib.security.SecurityUtils;
|
import jdk.test.lib.security.SecurityUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* Helper class that provides methods to facilitate testing of distrusted roots.
|
||||||
* @bug 8337664 8341059
|
|
||||||
* @summary Check that TLS Server certificates chaining back to distrusted
|
|
||||||
* Entrust roots are invalid
|
|
||||||
* @library /test/lib
|
|
||||||
* @modules java.base/sun.security.validator
|
|
||||||
* @run main/othervm Distrust after policyOn invalid
|
|
||||||
* @run main/othervm Distrust after policyOff valid
|
|
||||||
* @run main/othervm Distrust before policyOn valid
|
|
||||||
* @run main/othervm Distrust before policyOff valid
|
|
||||||
*/
|
*/
|
||||||
|
public final class Distrust {
|
||||||
public class Distrust {
|
|
||||||
|
|
||||||
private static final String TEST_SRC = System.getProperty("test.src", ".");
|
private static final String TEST_SRC = System.getProperty("test.src", ".");
|
||||||
private static CertificateFactory cf;
|
private static CertificateFactory cf;
|
||||||
|
|
||||||
// Each of the roots have a test certificate chain stored in a file
|
private final boolean before;
|
||||||
// named "<root>-chain.pem".
|
private final boolean policyOn;
|
||||||
private static String[] rootsToTest = new String[] {
|
private final boolean isValid;
|
||||||
"entrustevca", "entrustrootcaec1", "entrustrootcag2", "entrustrootcag4",
|
|
||||||
"entrust2048ca", "affirmtrustcommercialca", "affirmtrustnetworkingca",
|
|
||||||
"affirmtrustpremiumca", "affirmtrustpremiumeccca" };
|
|
||||||
|
|
||||||
// A date that is after the restrictions take effect
|
public Distrust(String[] args) {
|
||||||
private static final Date NOVEMBER_12_2024 =
|
before = args[0].equals("before");
|
||||||
Date.from(LocalDate.of(2024, 11, 12)
|
policyOn = args[1].equals("policyOn");
|
||||||
.atStartOfDay(ZoneOffset.UTC)
|
isValid = args[2].equals("valid");
|
||||||
.toInstant());
|
|
||||||
|
|
||||||
// A date that is a second before the restrictions take effect
|
|
||||||
private static final Date BEFORE_NOVEMBER_12_2024 =
|
|
||||||
Date.from(LocalDate.of(2024, 11, 12)
|
|
||||||
.atStartOfDay(ZoneOffset.UTC)
|
|
||||||
.minusSeconds(1)
|
|
||||||
.toInstant());
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
|
|
||||||
cf = CertificateFactory.getInstance("X.509");
|
|
||||||
|
|
||||||
boolean before = args[0].equals("before");
|
|
||||||
boolean policyOn = args[1].equals("policyOn");
|
|
||||||
boolean isValid = args[2].equals("valid");
|
|
||||||
|
|
||||||
if (!policyOn) {
|
if (!policyOn) {
|
||||||
// disable policy (default is on)
|
// disable policy (default is on)
|
||||||
Security.setProperty("jdk.security.caDistrustPolicies", "");
|
Security.setProperty("jdk.security.caDistrustPolicies", "");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Date notBefore = before ? BEFORE_NOVEMBER_12_2024 : NOVEMBER_12_2024;
|
public Date getNotBefore(ZonedDateTime distrustDate) {
|
||||||
|
ZonedDateTime notBefore = before ? distrustDate.minusSeconds(1) : distrustDate;
|
||||||
|
return Date.from(notBefore.toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
X509TrustManager pkixTM = getTMF("PKIX", null);
|
public void testCodeSigningChain(String certPath, String name, Date validationDate)
|
||||||
X509TrustManager sunX509TM = getTMF("SunX509", null);
|
throws Exception {
|
||||||
for (String test : rootsToTest) {
|
System.err.println("Testing " + name + " code-signing chain");
|
||||||
|
Validator v = Validator.getInstance(Validator.TYPE_PKIX,
|
||||||
|
Validator.VAR_CODE_SIGNING,
|
||||||
|
getParams());
|
||||||
|
// set validation date so this will still pass when cert expires
|
||||||
|
v.setValidationDate(validationDate);
|
||||||
|
v.validate(loadCertificateChain(certPath, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCertificateChain(String certPath, Date notBefore, X509TrustManager[] tms,
|
||||||
|
String... tests) throws Exception {
|
||||||
|
for (String test : tests) {
|
||||||
System.err.println("Testing " + test);
|
System.err.println("Testing " + test);
|
||||||
X509Certificate[] chain = loadCertificateChain(test);
|
X509Certificate[] chain = loadCertificateChain(certPath, test);
|
||||||
|
|
||||||
testTM(sunX509TM, chain, notBefore, isValid);
|
for (X509TrustManager tm : tms) {
|
||||||
testTM(pkixTM, chain, notBefore, isValid);
|
testTM(tm, chain, notBefore, isValid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static X509TrustManager getTMF(String type,
|
public X509TrustManager getTMF(String type, PKIXBuilderParameters params) throws Exception {
|
||||||
PKIXBuilderParameters params) throws Exception {
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(type);
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance(type);
|
||||||
if (params == null) {
|
if (params == null) {
|
||||||
tmf.init((KeyStore)null);
|
tmf.init((KeyStore) null);
|
||||||
} else {
|
} else {
|
||||||
tmf.init(new CertPathTrustManagerParameters(params));
|
tmf.init(new CertPathTrustManagerParameters(params));
|
||||||
}
|
}
|
||||||
TrustManager[] tms = tmf.getTrustManagers();
|
TrustManager[] tms = tmf.getTrustManagers();
|
||||||
for (TrustManager tm : tms) {
|
for (TrustManager tm : tms) {
|
||||||
X509TrustManager xtm = (X509TrustManager)tm;
|
return (X509TrustManager) tm;
|
||||||
return xtm;
|
|
||||||
}
|
}
|
||||||
throw new Exception("No TrustManager for " + type);
|
throw new RuntimeException("No TrustManager for " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PKIXBuilderParameters getParams() throws Exception {
|
public PKIXBuilderParameters getParams() throws Exception {
|
||||||
PKIXBuilderParameters pbp =
|
PKIXBuilderParameters pbp =
|
||||||
new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(),
|
new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(),
|
||||||
new X509CertSelector());
|
new X509CertSelector());
|
||||||
pbp.setRevocationEnabled(false);
|
pbp.setRevocationEnabled(false);
|
||||||
return pbp;
|
return pbp;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testTM(X509TrustManager xtm, X509Certificate[] chain,
|
public void testTM(X509TrustManager xtm, X509Certificate[] chain,
|
||||||
Date notBefore, boolean valid) throws Exception {
|
Date notBefore, boolean valid) {
|
||||||
// Check if TLS Server certificate (the first element of the chain)
|
// Check if TLS Server certificate (the first element of the chain)
|
||||||
// is issued after the specified notBefore date (should be rejected
|
// is issued after the specified notBefore date (should be rejected
|
||||||
// unless distrust property is false). To do this, we need to
|
// unless distrust property is false). To do this, we need to
|
||||||
@ -130,67 +115,54 @@ public class Distrust {
|
|||||||
// after then.
|
// after then.
|
||||||
chain[0] = new DistrustedTLSServerCert(chain[0], notBefore);
|
chain[0] = new DistrustedTLSServerCert(chain[0], notBefore);
|
||||||
|
|
||||||
|
// Wrap the intermediate and root CA certs in NonExpiringTLSServerCert
|
||||||
|
// so it will never throw a CertificateExpiredException
|
||||||
|
for (int i = 1; i < chain.length; i++) {
|
||||||
|
chain[i] = new NonExpiringTLSServerCert(chain[i]);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
xtm.checkServerTrusted(chain, "ECDHE_RSA");
|
xtm.checkServerTrusted(chain, "ECDHE_RSA");
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
throw new Exception("chain should be invalid");
|
throw new RuntimeException("chain should be invalid");
|
||||||
}
|
}
|
||||||
} catch (CertificateException ce) {
|
} catch (CertificateException ce) {
|
||||||
// expired TLS certificates should not be treated as failure
|
|
||||||
if (expired(ce)) {
|
|
||||||
System.err.println("Test is N/A, chain is expired");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
throw new Exception("Unexpected exception, chain " +
|
throw new RuntimeException("Unexpected exception, chain " +
|
||||||
"should be valid", ce);
|
"should be valid", ce);
|
||||||
}
|
}
|
||||||
if (ce instanceof ValidatorException) {
|
if (ce instanceof ValidatorException) {
|
||||||
ValidatorException ve = (ValidatorException)ce;
|
ValidatorException ve = (ValidatorException) ce;
|
||||||
if (ve.getErrorType() != ValidatorException.T_UNTRUSTED_CERT) {
|
if (ve.getErrorType() != ValidatorException.T_UNTRUSTED_CERT) {
|
||||||
ce.printStackTrace(System.err);
|
ce.printStackTrace(System.err);
|
||||||
throw new Exception("Unexpected exception: " + ce);
|
throw new RuntimeException("Unexpected exception: " + ce);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new Exception("Unexpected exception: " + ce);
|
throw new RuntimeException(ce);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a cause of exception is an expired cert
|
private X509Certificate[] loadCertificateChain(String certPath, String name)
|
||||||
private static boolean expired(CertificateException ce) {
|
|
||||||
if (ce instanceof CertificateExpiredException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
Throwable t = ce.getCause();
|
|
||||||
while (t != null) {
|
|
||||||
if (t instanceof CertificateExpiredException) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
t = t.getCause();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static X509Certificate[] loadCertificateChain(String name)
|
|
||||||
throws Exception {
|
throws Exception {
|
||||||
try (InputStream in = new FileInputStream(TEST_SRC + File.separator +
|
if (cf == null) {
|
||||||
name + "-chain.pem")) {
|
cf = CertificateFactory.getInstance("X.509");
|
||||||
|
}
|
||||||
|
try (InputStream in = new FileInputStream(TEST_SRC + File.separator + certPath +
|
||||||
|
File.separator + name + "-chain.pem")) {
|
||||||
Collection<X509Certificate> certs =
|
Collection<X509Certificate> certs =
|
||||||
(Collection<X509Certificate>)cf.generateCertificates(in);
|
(Collection<X509Certificate>) cf.generateCertificates(in);
|
||||||
return certs.toArray(new X509Certificate[0]);
|
return certs.toArray(new X509Certificate[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DistrustedTLSServerCert extends X509Certificate {
|
private static class NonExpiringTLSServerCert extends X509Certificate {
|
||||||
private final X509Certificate cert;
|
private final X509Certificate cert;
|
||||||
private final Date notBefore;
|
NonExpiringTLSServerCert(X509Certificate cert) {
|
||||||
DistrustedTLSServerCert(X509Certificate cert, Date notBefore) {
|
|
||||||
this.cert = cert;
|
this.cert = cert;
|
||||||
this.notBefore = notBefore;
|
|
||||||
}
|
}
|
||||||
public Set<String> getCriticalExtensionOIDs() {
|
public Set<String> getCriticalExtensionOIDs() {
|
||||||
return cert.getCriticalExtensionOIDs();
|
return cert.getCriticalExtensionOIDs();
|
||||||
}
|
}
|
||||||
public byte[] getExtensionValue(String oid) {
|
public byte[] getExtensionValue(String oid) {
|
||||||
return cert.getExtensionValue(oid);
|
return cert.getExtensionValue(oid);
|
||||||
@ -201,19 +173,17 @@ public class Distrust {
|
|||||||
public boolean hasUnsupportedCriticalExtension() {
|
public boolean hasUnsupportedCriticalExtension() {
|
||||||
return cert.hasUnsupportedCriticalExtension();
|
return cert.hasUnsupportedCriticalExtension();
|
||||||
}
|
}
|
||||||
public void checkValidity() throws CertificateExpiredException,
|
public void checkValidity() {
|
||||||
CertificateNotYetValidException {
|
|
||||||
// always pass
|
// always pass
|
||||||
}
|
}
|
||||||
public void checkValidity(Date date) throws CertificateExpiredException,
|
public void checkValidity(Date date) {
|
||||||
CertificateNotYetValidException {
|
|
||||||
// always pass
|
// always pass
|
||||||
}
|
}
|
||||||
public int getVersion() { return cert.getVersion(); }
|
public int getVersion() { return cert.getVersion(); }
|
||||||
public BigInteger getSerialNumber() { return cert.getSerialNumber(); }
|
public BigInteger getSerialNumber() { return cert.getSerialNumber(); }
|
||||||
public Principal getIssuerDN() { return cert.getIssuerDN(); }
|
public Principal getIssuerDN() { return cert.getIssuerDN(); }
|
||||||
public Principal getSubjectDN() { return cert.getSubjectDN(); }
|
public Principal getSubjectDN() { return cert.getSubjectDN(); }
|
||||||
public Date getNotBefore() { return notBefore; }
|
public Date getNotBefore() { return cert.getNotBefore(); }
|
||||||
public Date getNotAfter() { return cert.getNotAfter(); }
|
public Date getNotAfter() { return cert.getNotAfter(); }
|
||||||
public byte[] getTBSCertificate() throws CertificateEncodingException {
|
public byte[] getTBSCertificate() throws CertificateEncodingException {
|
||||||
return cert.getTBSCertificate();
|
return cert.getTBSCertificate();
|
||||||
@ -234,16 +204,25 @@ public class Distrust {
|
|||||||
return cert.getEncoded();
|
return cert.getEncoded();
|
||||||
}
|
}
|
||||||
public void verify(PublicKey key) throws CertificateException,
|
public void verify(PublicKey key) throws CertificateException,
|
||||||
InvalidKeyException, NoSuchAlgorithmException,
|
InvalidKeyException, NoSuchAlgorithmException,
|
||||||
NoSuchProviderException, SignatureException {
|
NoSuchProviderException, SignatureException {
|
||||||
cert.verify(key);
|
cert.verify(key);
|
||||||
}
|
}
|
||||||
public void verify(PublicKey key, String sigProvider) throws
|
public void verify(PublicKey key, String sigProvider) throws
|
||||||
CertificateException, InvalidKeyException, NoSuchAlgorithmException,
|
CertificateException, InvalidKeyException, NoSuchAlgorithmException,
|
||||||
NoSuchProviderException, SignatureException {
|
NoSuchProviderException, SignatureException {
|
||||||
cert.verify(key, sigProvider);
|
cert.verify(key, sigProvider);
|
||||||
}
|
}
|
||||||
public PublicKey getPublicKey() { return cert.getPublicKey(); }
|
public PublicKey getPublicKey() { return cert.getPublicKey(); }
|
||||||
public String toString() { return cert.toString(); }
|
public String toString() { return cert.toString(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class DistrustedTLSServerCert extends NonExpiringTLSServerCert {
|
||||||
|
private final Date notBefore;
|
||||||
|
DistrustedTLSServerCert(X509Certificate cert, Date notBefore) {
|
||||||
|
super(cert);
|
||||||
|
this.notBefore = notBefore;
|
||||||
|
}
|
||||||
|
public Date getNotBefore() { return notBefore; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.time.*;
|
||||||
|
import java.util.*;
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8337664
|
||||||
|
* @summary Check that TLS Server certificates chaining back to distrusted
|
||||||
|
* Entrust roots are invalid
|
||||||
|
* @library /test/lib
|
||||||
|
* @modules java.base/sun.security.validator
|
||||||
|
* @run main/othervm Entrust after policyOn invalid
|
||||||
|
* @run main/othervm Entrust after policyOff valid
|
||||||
|
* @run main/othervm Entrust before policyOn valid
|
||||||
|
* @run main/othervm Entrust before policyOff valid
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Entrust {
|
||||||
|
|
||||||
|
private static final String certPath = "chains" + File.separator + "entrust";
|
||||||
|
|
||||||
|
// Each of the roots have a test certificate chain stored in a file
|
||||||
|
// named "<root>-chain.pem".
|
||||||
|
private static String[] rootsToTest = new String[]{
|
||||||
|
"entrustevca", "entrustrootcaec1", "entrustrootcag2", "entrustrootcag4",
|
||||||
|
"entrust2048ca", "affirmtrustcommercialca", "affirmtrustnetworkingca",
|
||||||
|
"affirmtrustpremiumca", "affirmtrustpremiumeccca"};
|
||||||
|
|
||||||
|
// Date when the restrictions take effect
|
||||||
|
private static final ZonedDateTime DISTRUST_DATE =
|
||||||
|
LocalDate.of(2024, 11, 12).atStartOfDay(ZoneOffset.UTC);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Distrust distrust = new Distrust(args);
|
||||||
|
|
||||||
|
X509TrustManager[] tms = new X509TrustManager[]{
|
||||||
|
distrust.getTMF("PKIX", null),
|
||||||
|
distrust.getTMF("SunX509", null)
|
||||||
|
};
|
||||||
|
|
||||||
|
Date notBefore = distrust.getNotBefore(DISTRUST_DATE);
|
||||||
|
distrust.testCertificateChain(certPath, notBefore, tms, rootsToTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, 2024, 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
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
import java.io.File;
|
||||||
|
import java.time.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8207258 8216280
|
||||||
|
* @summary Check that TLS Server certificates chaining back to distrusted
|
||||||
|
* Symantec roots are invalid
|
||||||
|
* @library /test/lib
|
||||||
|
* @modules java.base/sun.security.validator
|
||||||
|
* @run main/othervm Symantec after policyOn invalid
|
||||||
|
* @run main/othervm Symantec after policyOff valid
|
||||||
|
* @run main/othervm Symantec before policyOn valid
|
||||||
|
* @run main/othervm Symantec before policyOff valid
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Symantec {
|
||||||
|
|
||||||
|
private static final String certPath = "chains" + File.separator + "symantec";
|
||||||
|
|
||||||
|
// Each of the roots have a test certificate chain stored in a file
|
||||||
|
// named "<root>-chain.pem".
|
||||||
|
private static final String[] rootsToTest = new String[]{
|
||||||
|
"geotrustprimarycag2", "geotrustprimarycag3", "geotrustuniversalca",
|
||||||
|
"thawteprimaryrootca", "thawteprimaryrootcag2", "thawteprimaryrootcag3",
|
||||||
|
"verisignclass3g3ca", "verisignclass3g4ca", "verisignclass3g5ca",
|
||||||
|
"verisignuniversalrootca"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Each of the subCAs with a delayed distrust date have a test certificate
|
||||||
|
// chain stored in a file named "<subCA>-chain.pem".
|
||||||
|
private static String[] subCAsToTest = new String[]{"appleistca8g1"};
|
||||||
|
|
||||||
|
// Date when the restrictions take effect
|
||||||
|
private static final ZonedDateTime ROOTS_DISTRUST_DATE =
|
||||||
|
LocalDate.of(2019, 4, 17).atStartOfDay(ZoneOffset.UTC);
|
||||||
|
|
||||||
|
// Date when the subCA restrictions take effect
|
||||||
|
private static final ZonedDateTime SUBCA_DISTRUST_DATE =
|
||||||
|
LocalDate.of(2020, 1, 1).atStartOfDay(ZoneOffset.UTC);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Distrust distrust = new Distrust(args);
|
||||||
|
X509TrustManager[] tms = new X509TrustManager[]{
|
||||||
|
distrust.getTMF("PKIX", null),
|
||||||
|
distrust.getTMF("SunX509", null)
|
||||||
|
};
|
||||||
|
|
||||||
|
// test chains issued through roots
|
||||||
|
Date notBefore = distrust.getNotBefore(ROOTS_DISTRUST_DATE);
|
||||||
|
distrust.testCertificateChain(certPath, notBefore, tms, rootsToTest);
|
||||||
|
|
||||||
|
// test chain if params are passed to TrustManager
|
||||||
|
System.err.println("Testing verisignuniversalrootca with params");
|
||||||
|
X509TrustManager[] tmsParams = new X509TrustManager[]{
|
||||||
|
distrust.getTMF("PKIX", distrust.getParams())
|
||||||
|
};
|
||||||
|
distrust.testCertificateChain(certPath, notBefore, tmsParams,
|
||||||
|
"verisignuniversalrootca");
|
||||||
|
|
||||||
|
// test code-signing chain (should be valid as restrictions don't apply)
|
||||||
|
Date validationDate = new Date(1544197375493L);
|
||||||
|
distrust.testCodeSigningChain(certPath, "verisignclass3g5ca-codesigning", validationDate);
|
||||||
|
|
||||||
|
// test chains issued through subCAs
|
||||||
|
notBefore = distrust.getNotBefore(SUBCA_DISTRUST_DATE);
|
||||||
|
distrust.testCertificateChain(certPath, notBefore, tms, subCAsToTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user