8369282: Distrust TLS server certificates anchored by Chunghwa ePKI Root CA

Reviewed-by: mullan
This commit is contained in:
Mark Powers 2026-01-08 17:35:43 +00:00
parent afd216ec3f
commit 92abc6dfe4
5 changed files with 244 additions and 2 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2026, 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
@ -83,6 +83,22 @@ enum CADistrustPolicy {
}
CamerfirmaTLSPolicy.checkDistrust(chain);
}
},
/**
* Distrust TLS Server certificates anchored by the Chunghwa ePKI root CA
* and issued after March 17, 2026. If enabled, this policy is currently
* enforced by the PKIX and SunX509 TrustManager implementations
* of the SunJSSE provider implementation.
*/
CHUNGHWA_TLS {
void checkDistrust(String variant, X509Certificate[] chain)
throws ValidatorException {
if (!variant.equals(Validator.VAR_TLS_SERVER)) {
return;
}
ChunghwaTLSPolicy.checkDistrust(chain);
}
};
/**

View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2026, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package sun.security.validator;
import java.security.cert.X509Certificate;
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.util.Debug;
import sun.security.x509.X509CertImpl;
/**
* This class checks if Chunghwa issued TLS Server certificates should be
* restricted.
*/
final class ChunghwaTLSPolicy {
private static final Debug debug = Debug.getInstance("certpath");
// SHA-256 certificate fingerprint of distrusted root for TLS
// cacerts alias: chunghwaepkirootca
// DN: OU=ePKI Root Certification Authority,
// O="Chunghwa Telecom Co., Ltd.", C=TW
private static final String FINGERPRINT =
"C0A6F4DC63A24BFDCF54EF2A6A082A0A72DE35803E2FF5FF527AE5D87206DFD5";
// Any TLS Server certificate that is anchored by the Chunghwa
// root above and is issued after this date will be distrusted.
private static final LocalDate MARCH_17_2026 =
LocalDate.of(2026, Month.MARCH, 17);
/**
* This method assumes the eeCert is a TLS Server Cert and chains back to
* the anchor.
*
* @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[] chain)
throws ValidatorException {
X509Certificate anchor = chain[chain.length-1];
String fp = fingerprint(anchor);
if (fp == null) {
throw new ValidatorException("Cannot generate fingerprint for "
+ "trust anchor of TLS server certificate");
}
if (FINGERPRINT.equalsIgnoreCase(fp)) {
Date notBefore = chain[0].getNotBefore();
LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
ZoneOffset.UTC);
// reject if certificate is issued after March 17, 2026
checkNotBefore(ldNotBefore, MARCH_17_2026, anchor);
}
}
private static String fingerprint(X509Certificate cert) {
return X509CertImpl.getFingerprint("SHA-256", cert, debug);
}
// Check whether the certificate's notBeforeDate is after the
// distrust date for the anchor (root CA). Throw ValidatorException
// if it is after the distrust date.
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 Chunghwa root CA: "
+ anchor.getSubjectX500Principal(),
ValidatorException.T_UNTRUSTED_CERT, anchor);
}
}
private ChunghwaTLSPolicy() {}
}

View File

@ -1437,6 +1437,9 @@ jdk.sasl.disabledMechanisms=
# CAMERFIRMA_TLS : Distrust TLS Server certificates anchored by
# a Camerfirma root CA and issued after April 15, 2025.
#
# CHUNGHWA_TLS : Distrust TLS Server certificates anchored by
# a Chunghwa root CA and issued after March 17, 2026.
#
# Leading and trailing whitespace surrounding each value are ignored.
# Unknown values are ignored. If the property is commented out or set to the
# empty String, no policies are enforced.
@ -1448,7 +1451,8 @@ jdk.sasl.disabledMechanisms=
# jdk.certpath.disabledAlgorithms; those restrictions are still enforced even
# if this property is not enabled.
#
jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS,CAMERFIRMA_TLS
jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS,CAMERFIRMA_TLS,\
CHUNGHWA_TLS
#
# FilePermission path canonicalization

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2026, 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.security.Security;
import java.time.LocalDate;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
/*
* @test
* @bug 8369282
* @summary Check that TLS Server certificates chaining back to distrusted
* Chunghwa root are invalid
* @library /test/lib
* @modules java.base/sun.security.validator
* @run main/othervm Chunghwa after policyOn invalid
* @run main/othervm Chunghwa after policyOff valid
* @run main/othervm Chunghwa before policyOn valid
* @run main/othervm Chunghwa before policyOff valid
*/
public class Chunghwa {
private static final String CERT_PATH = "chains" + File.separator + "chunghwa";
// The ePKI root has a test certificate chain stored in a file
// named "<root>-chain.pem".
private static final String ROOT_TO_TEST = "chunghwaepkirootca";
// Date after the restrictions take effect
private static final ZonedDateTime DISTRUST_DATE =
LocalDate.of(2026, 03, 18).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(CERT_PATH, notBefore, tms, ROOT_TO_TEST);
}
}

View File

@ -0,0 +1,50 @@
Owner: CN=HiPKI Root CA - G1,
O="Chunghwa Telecom Co., Ltd.", C=TW
Issuer: OU=ePKI Root Certification Authority,
O="Chunghwa Telecom Co., Ltd.", C=TW
Serial number: 23fba648360e15e92ba78aedb67a0ae5
Valid from: Wed Dec 20 19:11:23 MST 2023 until: Tue Dec 19 08:59:59 MST 2034
Certificate fingerprints:
SHA1: 87:F1:DD:3B:8E:F1:E0:8C:A8:CA:CB:9B:CE:4E:26:5A:E4:4E:05:F2
SHA256: 68:07:C9:72:35:C5:EC:60:90:26:9A:4B:5F:ED:FA:B4:69:86:E4:2F:4D:67:D2:ED:DD:CF:6E:45:CF:0D:FA:80
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIGjDCCBHSgAwIBAgIQI/umSDYOFekrp4rttnoK5TANBgkqhkiG9w0BAQsFADBe
MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
Fw0yMzEyMjEwMjExMjNaFw0zNDEyMTkxNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMw
IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQ
S0kgUm9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
9B5/UnMyDHPkvRN0o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh
8Ge6zCFovkRTv4354twvVcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux5
5199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEu
iAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRt
U6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXT
T3OUM3ECoWqj1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK
9p/7qxj3ccC2HTHsOyDry+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8
b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8Pg
cSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NV
vxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaOCAVMwggFPMB8G
A1UdIwQYMBaAFB4M97Zn8uGSJglFwFU5Lnc/QkqiMB0GA1UdDgQWBBTydxf6Xqj+
9j1x1Wi6yUYMONivsDAOBgNVHQ8BAf8EBAMCAYYwQAYDVR0fBDkwNzA1oDOgMYYv
aHR0cDovL2VjYS5oaW5ldC5uZXQvcmVwb3NpdG9yeS9DUkxfU0hBMi9DQS5jcmww
gYIGCCsGAQUFBwEBBHYwdDA7BggrBgEFBQcwAoYvaHR0cDovL2VjYS5oaW5ldC5u
ZXQvcmVwb3NpdG9yeS9DZXJ0cy9lQ0FHMS5jcnQwNQYIKwYBBQUHMAGGKWh0dHA6
Ly9vY3NwLmVjYS5oaW5ldC5uZXQvT0NTUC9vY3NwRzFzaGEyMBIGA1UdEwEB/wQI
MAYBAf8CAQEwIgYDVR0gBBswGTAIBgZngQwBAgIwDQYLKwYBBAGBtyNkAAMwDQYJ
KoZIhvcNAQELBQADggIBACY9pps8fqk3p8Xqv/qr26I1aFA4jOEG3VWd2bqn68Y9
InOMZozTMVh7iOnOfat7mEqn/RNhikvR5MOV3qAeg4gwgNb1OMuGltwfXWGiuGeT
vhimsV6E2hhJFAmZyXtfuoV9vSrnr1a5pCWqhVYWSCvoAQ/8Kv0tATKbIe21CYXz
NIo7O9QBSXt0BiaP9+CVQtJAYYuy2MNAcXgzgL4rownrYYAixhPmkxQE0Dt1gVbW
s2htBLJGse0z1fJDblY0Zar4t2ly+kIScx5DhRrrd8XKMK0YvID9Ythb+ao8m7Wd
Kymqr36benGL3GsvmSypLPlqZtfEqVITFhXwQiL8ruxoL+3WfNQJ09x0iV4xaP+E
bZSLLVzIiyhU49YdFHaqKyAJQvzgF2Za3DOwQWlP7OngtUx0ScEGHsoo78AM+Y0T
eLFxmr82kuyH18wZkUT9bLZlot11P2aC8VTprBGr+jEAMJjpmEjSA83ja/ttmqgh
qjj29Jnw3Lgy91XIhzBFMxMYo+hhYeBRmBFWl5+Y5oxBgPVLZpDJvg2rKa8xdqim
KgvF0DMKHntE0hhVy7JfUCnKovNQ0pf0NodLfjpqcCS2GBZ1mNcsW2MG2uBPANcn
LRXmt7N4XX11mctQTADwt8yZZ+2HDrST4kghOz+FXgftrPBdtDtM0T6WJcHWR1uS
-----END CERTIFICATE-----