Skip to content

Commit e476901

Browse files
committed
8369282: Distrust TLS server certificates anchored by Chunghwa ePKI Root CA
Backport-of: 92abc6dfe43a2c1f10dcfcf1e197fc9369f70ee3
1 parent d877cf1 commit e476901

5 files changed

Lines changed: 244 additions & 2 deletions

File tree

src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -85,6 +85,22 @@ void checkDistrust(String variant, X509Certificate[] chain)
8585
}
8686
CamerfirmaTLSPolicy.checkDistrust(chain);
8787
}
88+
},
89+
90+
/**
91+
* Distrust TLS Server certificates anchored by the Chunghwa ePKI root CA
92+
* and issued after March 17, 2026. If enabled, this policy is currently
93+
* enforced by the PKIX and SunX509 TrustManager implementations
94+
* of the SunJSSE provider implementation.
95+
*/
96+
CHUNGHWA_TLS {
97+
void checkDistrust(String variant, X509Certificate[] chain)
98+
throws ValidatorException {
99+
if (!variant.equals(Validator.VAR_TLS_SERVER)) {
100+
return;
101+
}
102+
ChunghwaTLSPolicy.checkDistrust(chain);
103+
}
88104
};
89105

90106
/**
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package sun.security.validator;
26+
27+
import java.security.cert.X509Certificate;
28+
import java.time.LocalDate;
29+
import java.time.Month;
30+
import java.time.ZoneOffset;
31+
import java.util.Date;
32+
import java.util.Map;
33+
import java.util.Set;
34+
35+
import sun.security.util.Debug;
36+
import sun.security.x509.X509CertImpl;
37+
38+
/**
39+
* This class checks if Chunghwa issued TLS Server certificates should be
40+
* restricted.
41+
*/
42+
final class ChunghwaTLSPolicy {
43+
44+
private static final Debug debug = Debug.getInstance("certpath");
45+
46+
// SHA-256 certificate fingerprint of distrusted root for TLS
47+
// cacerts alias: chunghwaepkirootca
48+
// DN: OU=ePKI Root Certification Authority,
49+
// O="Chunghwa Telecom Co., Ltd.", C=TW
50+
private static final String FINGERPRINT =
51+
"C0A6F4DC63A24BFDCF54EF2A6A082A0A72DE35803E2FF5FF527AE5D87206DFD5";
52+
53+
// Any TLS Server certificate that is anchored by the Chunghwa
54+
// root above and is issued after this date will be distrusted.
55+
private static final LocalDate MARCH_17_2026 =
56+
LocalDate.of(2026, Month.MARCH, 17);
57+
58+
/**
59+
* This method assumes the eeCert is a TLS Server Cert and chains back to
60+
* the anchor.
61+
*
62+
* @param chain the end-entity's certificate chain. The end entity cert
63+
* is at index 0, the trust anchor at index n-1.
64+
* @throws ValidatorException if the certificate is distrusted
65+
*/
66+
static void checkDistrust(X509Certificate[] chain)
67+
throws ValidatorException {
68+
X509Certificate anchor = chain[chain.length-1];
69+
String fp = fingerprint(anchor);
70+
if (fp == null) {
71+
throw new ValidatorException("Cannot generate fingerprint for "
72+
+ "trust anchor of TLS server certificate");
73+
}
74+
if (FINGERPRINT.equalsIgnoreCase(fp)) {
75+
Date notBefore = chain[0].getNotBefore();
76+
LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(),
77+
ZoneOffset.UTC);
78+
// reject if certificate is issued after March 17, 2026
79+
checkNotBefore(ldNotBefore, MARCH_17_2026, anchor);
80+
}
81+
}
82+
83+
private static String fingerprint(X509Certificate cert) {
84+
return X509CertImpl.getFingerprint("SHA-256", cert, debug);
85+
}
86+
87+
// Check whether the certificate's notBeforeDate is after the
88+
// distrust date for the anchor (root CA). Throw ValidatorException
89+
// if it is after the distrust date.
90+
private static void checkNotBefore(LocalDate notBeforeDate,
91+
LocalDate distrustDate, X509Certificate anchor)
92+
throws ValidatorException {
93+
if (notBeforeDate.isAfter(distrustDate)) {
94+
throw new ValidatorException
95+
("TLS Server certificate issued after " + distrustDate +
96+
" and anchored by a distrusted legacy Chunghwa root CA: "
97+
+ anchor.getSubjectX500Principal(),
98+
ValidatorException.T_UNTRUSTED_CERT, anchor);
99+
}
100+
}
101+
102+
private ChunghwaTLSPolicy() {}
103+
}

src/java.base/share/conf/security/java.security

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,9 @@ jdk.sasl.disabledMechanisms=
13111311
# CAMERFIRMA_TLS : Distrust TLS Server certificates anchored by
13121312
# a Camerfirma root CA and issued after April 15, 2025.
13131313
#
1314+
# CHUNGHWA_TLS : Distrust TLS Server certificates anchored by
1315+
# a Chunghwa root CA and issued after March 17, 2026.
1316+
#
13141317
# Leading and trailing whitespace surrounding each value are ignored.
13151318
# Unknown values are ignored. If the property is commented out or set to the
13161319
# empty String, no policies are enforced.
@@ -1322,7 +1325,8 @@ jdk.sasl.disabledMechanisms=
13221325
# jdk.certpath.disabledAlgorithms; those restrictions are still enforced even
13231326
# if this property is not enabled.
13241327
#
1325-
jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS,CAMERFIRMA_TLS
1328+
jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS,CAMERFIRMA_TLS,\
1329+
CHUNGHWA_TLS
13261330

13271331
#
13281332
# FilePermission path canonicalization
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import javax.net.ssl.X509TrustManager;
25+
import java.io.File;
26+
import java.security.Security;
27+
import java.time.LocalDate;
28+
import java.time.ZoneOffset;
29+
import java.time.ZonedDateTime;
30+
import java.util.Date;
31+
32+
/*
33+
* @test
34+
* @bug 8369282
35+
* @summary Check that TLS Server certificates chaining back to distrusted
36+
* Chunghwa root are invalid
37+
* @library /test/lib
38+
* @modules java.base/sun.security.validator
39+
* @run main/othervm Chunghwa after policyOn invalid
40+
* @run main/othervm Chunghwa after policyOff valid
41+
* @run main/othervm Chunghwa before policyOn valid
42+
* @run main/othervm Chunghwa before policyOff valid
43+
*/
44+
45+
public class Chunghwa {
46+
47+
private static final String CERT_PATH = "chains" + File.separator + "chunghwa";
48+
49+
// The ePKI root has a test certificate chain stored in a file
50+
// named "<root>-chain.pem".
51+
private static final String ROOT_TO_TEST = "chunghwaepkirootca";
52+
53+
// Date after the restrictions take effect
54+
private static final ZonedDateTime DISTRUST_DATE =
55+
LocalDate.of(2026, 03, 18).atStartOfDay(ZoneOffset.UTC);
56+
57+
public static void main(String[] args) throws Exception {
58+
59+
Distrust distrust = new Distrust(args);
60+
61+
X509TrustManager[] tms = new X509TrustManager[]{
62+
distrust.getTMF("PKIX", null),
63+
distrust.getTMF("SunX509", null)
64+
};
65+
66+
Date notBefore = distrust.getNotBefore(DISTRUST_DATE);
67+
distrust.testCertificateChain(CERT_PATH, notBefore, tms, ROOT_TO_TEST);
68+
}
69+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
Owner: CN=HiPKI Root CA - G1,
2+
O="Chunghwa Telecom Co., Ltd.", C=TW
3+
Issuer: OU=ePKI Root Certification Authority,
4+
O="Chunghwa Telecom Co., Ltd.", C=TW
5+
Serial number: 23fba648360e15e92ba78aedb67a0ae5
6+
Valid from: Wed Dec 20 19:11:23 MST 2023 until: Tue Dec 19 08:59:59 MST 2034
7+
Certificate fingerprints:
8+
SHA1: 87:F1:DD:3B:8E:F1:E0:8C:A8:CA:CB:9B:CE:4E:26:5A:E4:4E:05:F2
9+
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
10+
Signature algorithm name: SHA256withRSA
11+
Subject Public Key Algorithm: 4096-bit RSA key
12+
Version: 3
13+
14+
-----BEGIN CERTIFICATE-----
15+
MIIGjDCCBHSgAwIBAgIQI/umSDYOFekrp4rttnoK5TANBgkqhkiG9w0BAQsFADBe
16+
MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
17+
ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
18+
Fw0yMzEyMjEwMjExMjNaFw0zNDEyMTkxNTU5NTlaME8xCzAJBgNVBAYTAlRXMSMw
19+
IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQ
20+
S0kgUm9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
21+
9B5/UnMyDHPkvRN0o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh
22+
8Ge6zCFovkRTv4354twvVcg3Px+kwJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux5
23+
5199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SEYYwNHl98h5ZeQa/rh+r4XfEu
24+
iAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsAGJZMoYFL3QRt
25+
U6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd
26+
hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXT
27+
T3OUM3ECoWqj1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK
28+
9p/7qxj3ccC2HTHsOyDry+K49a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8
29+
b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/Vm+h+fbkEkj9Bn8SV7apI09bA8Pg
30+
cSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF8ez3ABHfZfjcK0NV
31+
vxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaOCAVMwggFPMB8G
32+
A1UdIwQYMBaAFB4M97Zn8uGSJglFwFU5Lnc/QkqiMB0GA1UdDgQWBBTydxf6Xqj+
33+
9j1x1Wi6yUYMONivsDAOBgNVHQ8BAf8EBAMCAYYwQAYDVR0fBDkwNzA1oDOgMYYv
34+
aHR0cDovL2VjYS5oaW5ldC5uZXQvcmVwb3NpdG9yeS9DUkxfU0hBMi9DQS5jcmww
35+
gYIGCCsGAQUFBwEBBHYwdDA7BggrBgEFBQcwAoYvaHR0cDovL2VjYS5oaW5ldC5u
36+
ZXQvcmVwb3NpdG9yeS9DZXJ0cy9lQ0FHMS5jcnQwNQYIKwYBBQUHMAGGKWh0dHA6
37+
Ly9vY3NwLmVjYS5oaW5ldC5uZXQvT0NTUC9vY3NwRzFzaGEyMBIGA1UdEwEB/wQI
38+
MAYBAf8CAQEwIgYDVR0gBBswGTAIBgZngQwBAgIwDQYLKwYBBAGBtyNkAAMwDQYJ
39+
KoZIhvcNAQELBQADggIBACY9pps8fqk3p8Xqv/qr26I1aFA4jOEG3VWd2bqn68Y9
40+
InOMZozTMVh7iOnOfat7mEqn/RNhikvR5MOV3qAeg4gwgNb1OMuGltwfXWGiuGeT
41+
vhimsV6E2hhJFAmZyXtfuoV9vSrnr1a5pCWqhVYWSCvoAQ/8Kv0tATKbIe21CYXz
42+
NIo7O9QBSXt0BiaP9+CVQtJAYYuy2MNAcXgzgL4rownrYYAixhPmkxQE0Dt1gVbW
43+
s2htBLJGse0z1fJDblY0Zar4t2ly+kIScx5DhRrrd8XKMK0YvID9Ythb+ao8m7Wd
44+
Kymqr36benGL3GsvmSypLPlqZtfEqVITFhXwQiL8ruxoL+3WfNQJ09x0iV4xaP+E
45+
bZSLLVzIiyhU49YdFHaqKyAJQvzgF2Za3DOwQWlP7OngtUx0ScEGHsoo78AM+Y0T
46+
eLFxmr82kuyH18wZkUT9bLZlot11P2aC8VTprBGr+jEAMJjpmEjSA83ja/ttmqgh
47+
qjj29Jnw3Lgy91XIhzBFMxMYo+hhYeBRmBFWl5+Y5oxBgPVLZpDJvg2rKa8xdqim
48+
KgvF0DMKHntE0hhVy7JfUCnKovNQ0pf0NodLfjpqcCS2GBZ1mNcsW2MG2uBPANcn
49+
LRXmt7N4XX11mctQTADwt8yZZ+2HDrST4kghOz+FXgftrPBdtDtM0T6WJcHWR1uS
50+
-----END CERTIFICATE-----

0 commit comments

Comments
 (0)