117 // OU="(c) 2008 VeriSign, Inc. - For authorized use only", |
118 // OU="(c) 2008 VeriSign, Inc. - For authorized use only", |
118 // OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US |
119 // OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US |
119 "2399561127A57125DE8CEFEA610DDF2FA078B5C8067F4E828290BFB860E84B3C" |
120 "2399561127A57125DE8CEFEA610DDF2FA078B5C8067F4E828290BFB860E84B3C" |
120 ); |
121 ); |
121 |
122 |
|
123 private static final LocalDate DECEMBER_31_2019 = |
|
124 LocalDate.of(2019, Month.DECEMBER, 31); |
|
125 // SHA-256 certificate fingerprints of subCAs with later distrust dates |
|
126 private static final Map<String, LocalDate> EXEMPT_SUBCAS = Map.of( |
|
127 // Subject DN: C=US, O=Apple Inc., OU=Certification Authority, |
|
128 // CN=Apple IST CA 2 - G1 |
|
129 // Issuer DN: CN=GeoTrust Global CA, O=GeoTrust Inc., C=US |
|
130 "AC2B922ECFD5E01711772FEA8ED372DE9D1E2245FCE3F57A9CDBEC77296A424B", |
|
131 DECEMBER_31_2019, |
|
132 // Subject DN: C=US, O=Apple Inc., OU=Certification Authority, |
|
133 // CN=Apple IST CA 8 - G1 |
|
134 // Issuer DN: CN=GeoTrust Primary Certification Authority - G2, |
|
135 // OU=(c) 2007 GeoTrust Inc. - For authorized use only, |
|
136 // O=GeoTrust Inc., C=US |
|
137 "A4FE7C7F15155F3F0AEF7AAA83CF6E06DEB97CA3F909DF920AC1490882D488ED", |
|
138 DECEMBER_31_2019 |
|
139 ); |
|
140 |
122 // Any TLS Server certificate that is anchored by one of the Symantec |
141 // Any TLS Server certificate that is anchored by one of the Symantec |
123 // roots above and is issued after this date will be distrusted. |
142 // roots above and is issued after this date will be distrusted. |
124 private static final LocalDate APRIL_16_2019 = |
143 private static final LocalDate APRIL_16_2019 = |
125 LocalDate.of(2019, Month.APRIL, 16); |
144 LocalDate.of(2019, Month.APRIL, 16); |
126 |
145 |
127 /** |
146 /** |
128 * This method assumes the eeCert is a TLS Server Cert and chains back to |
147 * This method assumes the eeCert is a TLS Server Cert and chains back to |
129 * the anchor. |
148 * the anchor. |
130 * |
149 * |
131 * @param anchor the trust anchor certificate |
150 * @param chain the end-entity's certificate chain. The end entity cert |
132 * @param eeCert the certificate to check |
151 * is at index 0, the trust anchor at index n-1. |
133 * @throws ValidatorException if the certificate is distrusted |
152 * @throws ValidatorException if the certificate is distrusted |
134 */ |
153 */ |
135 static void checkDistrust(X509Certificate anchor, |
154 static void checkDistrust(X509Certificate[] chain) |
136 X509Certificate eeCert) |
|
137 throws ValidatorException { |
155 throws ValidatorException { |
138 String fp = (anchor instanceof X509CertImpl) |
156 X509Certificate anchor = chain[chain.length-1]; |
139 ? ((X509CertImpl)anchor).getFingerprint("SHA-256") |
157 if (FINGERPRINTS.contains(fingerprint(anchor))) { |
140 : X509CertImpl.getFingerprint("SHA-256", anchor); |
158 Date notBefore = chain[0].getNotBefore(); |
141 if (FINGERPRINTS.contains(fp)) { |
|
142 // reject if certificate is issued after April 16, 2019 |
|
143 Date notBefore = eeCert.getNotBefore(); |
|
144 LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(), |
159 LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(), |
145 ZoneOffset.UTC); |
160 ZoneOffset.UTC); |
146 if (ldNotBefore.isAfter(APRIL_16_2019)) { |
161 // check if chain goes through one of the subCAs |
147 throw new ValidatorException |
162 if (chain.length > 2) { |
148 ("TLS Server certificate issued after " + APRIL_16_2019 + |
163 X509Certificate subCA = chain[chain.length-2]; |
149 " and anchored by a distrusted legacy Symantec root CA: " |
164 LocalDate distrustDate = EXEMPT_SUBCAS.get(fingerprint(subCA)); |
150 + anchor.getSubjectX500Principal(), |
165 if (distrustDate != null) { |
151 ValidatorException.T_UNTRUSTED_CERT, anchor); |
166 // reject if certificate is issued after specified date |
|
167 checkNotBefore(ldNotBefore, distrustDate, anchor); |
|
168 return; // success |
|
169 } |
152 } |
170 } |
|
171 // reject if certificate is issued after April 16, 2019 |
|
172 checkNotBefore(ldNotBefore, APRIL_16_2019, anchor); |
|
173 } |
|
174 } |
|
175 |
|
176 private static String fingerprint(X509Certificate cert) { |
|
177 return (cert instanceof X509CertImpl) |
|
178 ? ((X509CertImpl)cert).getFingerprint("SHA-256") |
|
179 : X509CertImpl.getFingerprint("SHA-256", cert); |
|
180 } |
|
181 |
|
182 private static void checkNotBefore(LocalDate notBeforeDate, |
|
183 LocalDate distrustDate, X509Certificate anchor) |
|
184 throws ValidatorException { |
|
185 if (notBeforeDate.isAfter(distrustDate)) { |
|
186 throw new ValidatorException |
|
187 ("TLS Server certificate issued after " + distrustDate + |
|
188 " and anchored by a distrusted legacy Symantec root CA: " |
|
189 + anchor.getSubjectX500Principal(), |
|
190 ValidatorException.T_UNTRUSTED_CERT, anchor); |
153 } |
191 } |
154 } |
192 } |
155 |
193 |
156 private SymantecTLSPolicy() {} |
194 private SymantecTLSPolicy() {} |
157 } |
195 } |