8216280: Allow later Symantec Policy distrust date for two Apple SubCAs

Reviewed-by: coffeys
This commit is contained in:
Sean Mullan 2019-01-22 09:27:19 -05:00
parent c0de8f27a5
commit c9bea6a8ea
8 changed files with 295 additions and 61 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -39,17 +39,19 @@ import sun.security.util.Debug;
enum CADistrustPolicy {
/**
* Distrust TLS Server certificates anchored by a Symantec root CA and
* issued after April 16, 2019. If enabled, this policy is currently
* enforced by the PKIX and SunX509 TrustManager implementations of the
* SunJSSE provider implementation.
* issued after April 16, 2019 (with exceptions for a couple of subordinate
* CAs, see the jdk.security.caDistrustPolicies definition in the
* java.security file for more details). If enabled, this policy is
* currently enforced by the PKIX and SunX509 TrustManager implementations
* of the SunJSSE provider implementation.
*/
SYMANTEC_TLS {
void checkDistrust(String variant, X509Certificate anchor,
X509Certificate ee) throws ValidatorException {
void checkDistrust(String variant, X509Certificate[] chain)
throws ValidatorException {
if (!variant.equals(Validator.VAR_TLS_SERVER)) {
return;
}
SymantecTLSPolicy.checkDistrust(anchor, ee);
SymantecTLSPolicy.checkDistrust(chain);
}
};
@ -57,13 +59,13 @@ enum CADistrustPolicy {
* Checks if the end-entity certificate is distrusted.
*
* @param variant the type of certificate being checked
* @param anchor the trust anchor certificate
* @param ee the end-entity certificate to check
* @param chain the end-entity's certificate chain. The end entity cert
* is at index 0, the trust anchor at index n-1.
* @throws ValidatorException if the end-entity certificate is distrusted
*/
abstract void checkDistrust(String variant,
X509Certificate anchor,
X509Certificate ee) throws ValidatorException;
X509Certificate[] chain)
throws ValidatorException;
// The policies set in the jdk.security.caDistrustPolicies property.
static final EnumSet<CADistrustPolicy> POLICIES = parseProperty();

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
@ -132,27 +132,26 @@ class EndEntityChecker {
return new EndEntityChecker(type, variant);
}
void check(X509Certificate cert, Object parameter,
boolean checkUnresolvedCritExts, X509Certificate anchor)
throws CertificateException {
void check(X509Certificate[] chain, Object parameter,
boolean checkUnresolvedCritExts) throws CertificateException {
if (variant.equals(Validator.VAR_GENERIC)) {
return; // no checks
}
Set<String> exts = getCriticalExtensions(cert);
Set<String> exts = getCriticalExtensions(chain[0]);
if (variant.equals(Validator.VAR_TLS_SERVER)) {
checkTLSServer(cert, (String)parameter, exts);
checkTLSServer(chain[0], (String)parameter, exts);
} else if (variant.equals(Validator.VAR_TLS_CLIENT)) {
checkTLSClient(cert, exts);
checkTLSClient(chain[0], exts);
} else if (variant.equals(Validator.VAR_CODE_SIGNING)) {
checkCodeSigning(cert, exts);
checkCodeSigning(chain[0], exts);
} else if (variant.equals(Validator.VAR_JCE_SIGNING)) {
checkCodeSigning(cert, exts);
checkCodeSigning(chain[0], exts);
} else if (variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING)) {
checkCodeSigning(cert, exts);
checkCodeSigning(chain[0], exts);
} else if (variant.equals(Validator.VAR_TSA_SERVER)) {
checkTSAServer(cert, exts);
checkTSAServer(chain[0], exts);
} else {
throw new CertificateException("Unknown variant: " + variant);
}
@ -165,7 +164,7 @@ class EndEntityChecker {
// check if certificate should be distrusted according to policies
// set in the jdk.security.caDistrustPolicies security property
for (CADistrustPolicy policy : CADistrustPolicy.POLICIES) {
policy.checkDistrust(variant, anchor, cert);
policy.checkDistrust(variant, chain);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 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
@ -29,6 +29,7 @@ import java.time.LocalDate;
import java.time.Month;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import sun.security.x509.X509CertImpl;
@ -119,6 +120,24 @@ final class SymantecTLSPolicy {
"2399561127A57125DE8CEFEA610DDF2FA078B5C8067F4E828290BFB860E84B3C"
);
private static final LocalDate DECEMBER_31_2019 =
LocalDate.of(2019, Month.DECEMBER, 31);
// SHA-256 certificate fingerprints of subCAs with later distrust dates
private static final Map<String, LocalDate> EXEMPT_SUBCAS = Map.of(
// Subject DN: C=US, O=Apple Inc., OU=Certification Authority,
// CN=Apple IST CA 2 - G1
// Issuer DN: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US
"AC2B922ECFD5E01711772FEA8ED372DE9D1E2245FCE3F57A9CDBEC77296A424B",
DECEMBER_31_2019,
// Subject DN: C=US, O=Apple Inc., OU=Certification Authority,
// CN=Apple IST CA 8 - G1
// Issuer DN: CN=GeoTrust Primary Certification Authority - G2,
// OU=(c) 2007 GeoTrust Inc. - For authorized use only,
// O=GeoTrust Inc., C=US
"A4FE7C7F15155F3F0AEF7AAA83CF6E06DEB97CA3F909DF920AC1490882D488ED",
DECEMBER_31_2019
);
// Any TLS Server certificate that is anchored by one of the Symantec
// roots above and is issued after this date will be distrusted.
private static final LocalDate APRIL_16_2019 =
@ -128,28 +147,47 @@ final class SymantecTLSPolicy {
* This method assumes the eeCert is a TLS Server Cert and chains back to
* the anchor.
*
* @param anchor the trust anchor certificate
* @param eeCert the certificate to check
* @param chain the end-entity's certificate chain. The end entity cert
* is at index 0, the trust anchor at index n-1.
* @throws ValidatorException if the certificate is distrusted
*/
static void checkDistrust(X509Certificate anchor,
X509Certificate eeCert)
static void checkDistrust(X509Certificate[] chain)
throws ValidatorException {
String fp = (anchor instanceof X509CertImpl)
? ((X509CertImpl)anchor).getFingerprint("SHA-256")
: X509CertImpl.getFingerprint("SHA-256", anchor);
if (FINGERPRINTS.contains(fp)) {
// reject if certificate is issued after April 16, 2019
Date notBefore = eeCert.getNotBefore();
X509Certificate anchor = chain[chain.length-1];
if (FINGERPRINTS.contains(fingerprint(anchor))) {
Date notBefore = chain[0].getNotBefore();
LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
ZoneOffset.UTC);
if (ldNotBefore.isAfter(APRIL_16_2019)) {
throw new ValidatorException
("TLS Server certificate issued after " + APRIL_16_2019 +
" and anchored by a distrusted legacy Symantec root CA: "
+ anchor.getSubjectX500Principal(),
ValidatorException.T_UNTRUSTED_CERT, anchor);
// check if chain goes through one of the subCAs
if (chain.length > 2) {
X509Certificate subCA = chain[chain.length-2];
LocalDate distrustDate = EXEMPT_SUBCAS.get(fingerprint(subCA));
if (distrustDate != null) {
// reject if certificate is issued after specified date
checkNotBefore(ldNotBefore, distrustDate, anchor);
return; // success
}
}
// reject if certificate is issued after April 16, 2019
checkNotBefore(ldNotBefore, APRIL_16_2019, anchor);
}
}
private static String fingerprint(X509Certificate cert) {
return (cert instanceof X509CertImpl)
? ((X509CertImpl)cert).getFingerprint("SHA-256")
: X509CertImpl.getFingerprint("SHA-256", cert);
}
private static void checkNotBefore(LocalDate notBeforeDate,
LocalDate distrustDate, X509Certificate anchor)
throws ValidatorException {
if (notBeforeDate.isAfter(distrustDate)) {
throw new ValidatorException
("TLS Server certificate issued after " + distrustDate +
" and anchored by a distrusted legacy Symantec root CA: "
+ anchor.getSubjectX500Principal(),
ValidatorException.T_UNTRUSTED_CERT, anchor);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 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
@ -274,9 +274,8 @@ public abstract class Validator {
// redundant.
boolean checkUnresolvedCritExts =
(type == TYPE_PKIX) ? false : true;
endEntityChecker.check(chain[0], parameter,
checkUnresolvedCritExts,
chain[chain.length-1]);
endEntityChecker.check(chain, parameter,
checkUnresolvedCritExts);
}
return chain;