1 /*
2 * Copyright (c) 2002, 2008, 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
106
107 // TLS key exchange algorithms requiring digitalSignature key usage
108 private final static Collection<String> KU_SERVER_SIGNATURE =
109 Arrays.asList("DHE_DSS", "DHE_RSA", "ECDHE_ECDSA", "ECDHE_RSA",
110 "RSA_EXPORT", "UNKNOWN");
111
112 // TLS key exchange algorithms requiring keyEncipherment key usage
113 private final static Collection<String> KU_SERVER_ENCRYPTION =
114 Arrays.asList("RSA");
115
116 // TLS key exchange algorithms requiring keyAgreement key usage
117 private final static Collection<String> KU_SERVER_KEY_AGREEMENT =
118 Arrays.asList("DH_DSS", "DH_RSA", "ECDH_ECDSA", "ECDH_RSA");
119
120 // variant of this end entity cert checker
121 private final String variant;
122
123 // type of the validator this checker belongs to
124 private final String type;
125
126 private EndEntityChecker(String type, String variant) {
127 this.type = type;
128 this.variant = variant;
129 }
130
131 static EndEntityChecker getInstance(String type, String variant) {
132 return new EndEntityChecker(type, variant);
133 }
134
135 void check(X509Certificate cert, Object parameter)
136 throws CertificateException {
137 if (variant.equals(Validator.VAR_GENERIC)) {
138 // no checks
139 return;
140 } else if (variant.equals(Validator.VAR_TLS_SERVER)) {
141 checkTLSServer(cert, (String)parameter);
142 } else if (variant.equals(Validator.VAR_TLS_CLIENT)) {
143 checkTLSClient(cert);
144 } else if (variant.equals(Validator.VAR_CODE_SIGNING)) {
145 checkCodeSigning(cert);
146 } else if (variant.equals(Validator.VAR_JCE_SIGNING)) {
147 checkCodeSigning(cert);
148 } else if (variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING)) {
149 checkCodeSigning(cert);
150 } else if (variant.equals(Validator.VAR_TSA_SERVER)) {
151 checkTSAServer(cert);
152 } else {
153 throw new CertificateException("Unknown variant: " + variant);
154 }
155 }
156
157 /**
158 * Utility method returning the Set of critical extensions for
159 * certificate cert (never null).
160 */
161 private Set<String> getCriticalExtensions(X509Certificate cert) {
162 Set<String> exts = cert.getCriticalExtensionOIDs();
163 if (exts == null) {
164 exts = Collections.emptySet();
165 }
166 return exts;
167 }
168
169 /**
170 * Utility method checking if there are any unresolved critical extensions.
171 * @throws CertificateException if so.
172 */
173 private void checkRemainingExtensions(Set<String> exts)
174 throws CertificateException {
204 * Utility method checking if bit 'bit' is set in this certificates
205 * key usage extension.
206 * @throws CertificateException if not
207 */
208 private boolean checkKeyUsage(X509Certificate cert, int bit)
209 throws CertificateException {
210 boolean[] keyUsage = cert.getKeyUsage();
211 if (keyUsage == null) {
212 return true;
213 }
214 return (keyUsage.length > bit) && keyUsage[bit];
215 }
216
217 /**
218 * Check whether this certificate can be used for TLS client
219 * authentication.
220 * @throws CertificateException if not.
221 */
222 private void checkTLSClient(X509Certificate cert)
223 throws CertificateException {
224 Set<String> exts = getCriticalExtensions(cert);
225
226 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
227 throw new ValidatorException
228 ("KeyUsage does not allow digital signatures",
229 ValidatorException.T_EE_EXTENSIONS, cert);
230 }
231
232 if (checkEKU(cert, exts, OID_EKU_TLS_CLIENT) == false) {
233 throw new ValidatorException("Extended key usage does not "
234 + "permit use for TLS client authentication",
235 ValidatorException.T_EE_EXTENSIONS, cert);
236 }
237
238 if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_CLIENT)) {
239 throw new ValidatorException
240 ("Netscape cert type does not permit use for SSL client",
241 ValidatorException.T_EE_EXTENSIONS, cert);
242 }
243
244 // remove extensions we checked
245 exts.remove(SimpleValidator.OID_KEY_USAGE);
246 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
247 exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
248
249 checkRemainingExtensions(exts);
250 }
251
252 /**
253 * Check whether this certificate can be used for TLS server authentication
254 * using the specified authentication type parameter. See X509TrustManager
255 * specification for details.
256 * @throws CertificateException if not.
257 */
258 private void checkTLSServer(X509Certificate cert, String parameter)
259 throws CertificateException {
260 Set<String> exts = getCriticalExtensions(cert);
261
262 if (KU_SERVER_ENCRYPTION.contains(parameter)) {
263 if (checkKeyUsage(cert, KU_KEY_ENCIPHERMENT) == false) {
264 throw new ValidatorException
265 ("KeyUsage does not allow key encipherment",
266 ValidatorException.T_EE_EXTENSIONS, cert);
267 }
268 } else if (KU_SERVER_SIGNATURE.contains(parameter)) {
269 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
270 throw new ValidatorException
271 ("KeyUsage does not allow digital signatures",
272 ValidatorException.T_EE_EXTENSIONS, cert);
273 }
274 } else if (KU_SERVER_KEY_AGREEMENT.contains(parameter)) {
275 if (checkKeyUsage(cert, KU_KEY_AGREEMENT) == false) {
276 throw new ValidatorException
277 ("KeyUsage does not allow key agreement",
278 ValidatorException.T_EE_EXTENSIONS, cert);
279 }
280 } else {
281 throw new CertificateException("Unknown authType: " + parameter);
286 // (aka Step-Up, 128 bit) EKU OIDs
287 if ((checkEKU(cert, exts, OID_EKU_MS_SGC) == false) &&
288 (checkEKU(cert, exts, OID_EKU_NS_SGC) == false)) {
289 throw new ValidatorException
290 ("Extended key usage does not permit use for TLS "
291 + "server authentication",
292 ValidatorException.T_EE_EXTENSIONS, cert);
293 }
294 }
295
296 if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_SERVER)) {
297 throw new ValidatorException
298 ("Netscape cert type does not permit use for SSL server",
299 ValidatorException.T_EE_EXTENSIONS, cert);
300 }
301
302 // remove extensions we checked
303 exts.remove(SimpleValidator.OID_KEY_USAGE);
304 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
305 exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
306
307 checkRemainingExtensions(exts);
308 }
309
310 /**
311 * Check whether this certificate can be used for code signing.
312 * @throws CertificateException if not.
313 */
314 private void checkCodeSigning(X509Certificate cert)
315 throws CertificateException {
316 Set<String> exts = getCriticalExtensions(cert);
317
318 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
319 throw new ValidatorException
320 ("KeyUsage does not allow digital signatures",
321 ValidatorException.T_EE_EXTENSIONS, cert);
322 }
323
324 if (checkEKU(cert, exts, OID_EKU_CODE_SIGNING) == false) {
325 throw new ValidatorException
326 ("Extended key usage does not permit use for code signing",
327 ValidatorException.T_EE_EXTENSIONS, cert);
328 }
329
330 // do not check Netscape cert type for JCE code signing checks
331 // (some certs were issued with incorrect extensions)
332 if (variant.equals(Validator.VAR_JCE_SIGNING) == false) {
333 if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING)) {
334 throw new ValidatorException
335 ("Netscape cert type does not permit use for code signing",
336 ValidatorException.T_EE_EXTENSIONS, cert);
337 }
338 exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
339 }
340
341 // remove extensions we checked
342 exts.remove(SimpleValidator.OID_KEY_USAGE);
343 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
344
345 checkRemainingExtensions(exts);
346 }
347
348 /**
349 * Check whether this certificate can be used by a time stamping authority
350 * server (see RFC 3161, section 2.3).
351 * @throws CertificateException if not.
352 */
353 private void checkTSAServer(X509Certificate cert)
354 throws CertificateException {
355 Set<String> exts = getCriticalExtensions(cert);
356
357 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
358 throw new ValidatorException
359 ("KeyUsage does not allow digital signatures",
360 ValidatorException.T_EE_EXTENSIONS, cert);
361 }
362
363 if (cert.getExtendedKeyUsage() == null) {
364 throw new ValidatorException
365 ("Certificate does not contain an extended key usage " +
366 "extension required for a TSA server",
367 ValidatorException.T_EE_EXTENSIONS, cert);
368 }
369
370 if (checkEKU(cert, exts, OID_EKU_TIME_STAMPING) == false) {
371 throw new ValidatorException
372 ("Extended key usage does not permit use for TSA server",
373 ValidatorException.T_EE_EXTENSIONS, cert);
374 }
375
376 // remove extensions we checked
377 exts.remove(SimpleValidator.OID_KEY_USAGE);
378 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
379
380 checkRemainingExtensions(exts);
381 }
382 }
|
1 /*
2 * Copyright (c) 2002, 2015, 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
106
107 // TLS key exchange algorithms requiring digitalSignature key usage
108 private final static Collection<String> KU_SERVER_SIGNATURE =
109 Arrays.asList("DHE_DSS", "DHE_RSA", "ECDHE_ECDSA", "ECDHE_RSA",
110 "RSA_EXPORT", "UNKNOWN");
111
112 // TLS key exchange algorithms requiring keyEncipherment key usage
113 private final static Collection<String> KU_SERVER_ENCRYPTION =
114 Arrays.asList("RSA");
115
116 // TLS key exchange algorithms requiring keyAgreement key usage
117 private final static Collection<String> KU_SERVER_KEY_AGREEMENT =
118 Arrays.asList("DH_DSS", "DH_RSA", "ECDH_ECDSA", "ECDH_RSA");
119
120 // variant of this end entity cert checker
121 private final String variant;
122
123 // type of the validator this checker belongs to
124 private final String type;
125
126 // the end entity certificate's extensions
127 private Set<String> exts;
128
129 private EndEntityChecker(String type, String variant) {
130 this.type = type;
131 this.variant = variant;
132 }
133
134 static EndEntityChecker getInstance(String type, String variant) {
135 return new EndEntityChecker(type, variant);
136 }
137
138 void check(X509Certificate cert, Object parameter,
139 boolean checkExtraExtensions) throws CertificateException {
140 if (variant.equals(Validator.VAR_GENERIC)) {
141 return; // no checks
142 }
143
144 exts = getCriticalExtensions(cert);
145 if (variant.equals(Validator.VAR_TLS_SERVER)) {
146 checkTLSServer(cert, (String)parameter);
147 } else if (variant.equals(Validator.VAR_TLS_CLIENT)) {
148 checkTLSClient(cert);
149 } else if (variant.equals(Validator.VAR_CODE_SIGNING)) {
150 checkCodeSigning(cert);
151 } else if (variant.equals(Validator.VAR_JCE_SIGNING)) {
152 checkCodeSigning(cert);
153 } else if (variant.equals(Validator.VAR_PLUGIN_CODE_SIGNING)) {
154 checkCodeSigning(cert);
155 } else if (variant.equals(Validator.VAR_TSA_SERVER)) {
156 checkTSAServer(cert);
157 } else {
158 throw new CertificateException("Unknown variant: " + variant);
159 }
160
161 // if neither VAR_GENERIC variant nor unknown variant
162 if (checkExtraExtensions) {
163 checkRemainingExtensions(exts);
164 }
165 }
166
167 /**
168 * Utility method returning the Set of critical extensions for
169 * certificate cert (never null).
170 */
171 private Set<String> getCriticalExtensions(X509Certificate cert) {
172 Set<String> exts = cert.getCriticalExtensionOIDs();
173 if (exts == null) {
174 exts = Collections.emptySet();
175 }
176 return exts;
177 }
178
179 /**
180 * Utility method checking if there are any unresolved critical extensions.
181 * @throws CertificateException if so.
182 */
183 private void checkRemainingExtensions(Set<String> exts)
184 throws CertificateException {
214 * Utility method checking if bit 'bit' is set in this certificates
215 * key usage extension.
216 * @throws CertificateException if not
217 */
218 private boolean checkKeyUsage(X509Certificate cert, int bit)
219 throws CertificateException {
220 boolean[] keyUsage = cert.getKeyUsage();
221 if (keyUsage == null) {
222 return true;
223 }
224 return (keyUsage.length > bit) && keyUsage[bit];
225 }
226
227 /**
228 * Check whether this certificate can be used for TLS client
229 * authentication.
230 * @throws CertificateException if not.
231 */
232 private void checkTLSClient(X509Certificate cert)
233 throws CertificateException {
234 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
235 throw new ValidatorException
236 ("KeyUsage does not allow digital signatures",
237 ValidatorException.T_EE_EXTENSIONS, cert);
238 }
239
240 if (checkEKU(cert, exts, OID_EKU_TLS_CLIENT) == false) {
241 throw new ValidatorException("Extended key usage does not "
242 + "permit use for TLS client authentication",
243 ValidatorException.T_EE_EXTENSIONS, cert);
244 }
245
246 if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_CLIENT)) {
247 throw new ValidatorException
248 ("Netscape cert type does not permit use for SSL client",
249 ValidatorException.T_EE_EXTENSIONS, cert);
250 }
251
252 // remove extensions we checked
253 exts.remove(SimpleValidator.OID_KEY_USAGE);
254 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
255 exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
256 }
257
258 /**
259 * Check whether this certificate can be used for TLS server authentication
260 * using the specified authentication type parameter. See X509TrustManager
261 * specification for details.
262 * @throws CertificateException if not.
263 */
264 private void checkTLSServer(X509Certificate cert, String parameter)
265 throws CertificateException {
266 if (KU_SERVER_ENCRYPTION.contains(parameter)) {
267 if (checkKeyUsage(cert, KU_KEY_ENCIPHERMENT) == false) {
268 throw new ValidatorException
269 ("KeyUsage does not allow key encipherment",
270 ValidatorException.T_EE_EXTENSIONS, cert);
271 }
272 } else if (KU_SERVER_SIGNATURE.contains(parameter)) {
273 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
274 throw new ValidatorException
275 ("KeyUsage does not allow digital signatures",
276 ValidatorException.T_EE_EXTENSIONS, cert);
277 }
278 } else if (KU_SERVER_KEY_AGREEMENT.contains(parameter)) {
279 if (checkKeyUsage(cert, KU_KEY_AGREEMENT) == false) {
280 throw new ValidatorException
281 ("KeyUsage does not allow key agreement",
282 ValidatorException.T_EE_EXTENSIONS, cert);
283 }
284 } else {
285 throw new CertificateException("Unknown authType: " + parameter);
290 // (aka Step-Up, 128 bit) EKU OIDs
291 if ((checkEKU(cert, exts, OID_EKU_MS_SGC) == false) &&
292 (checkEKU(cert, exts, OID_EKU_NS_SGC) == false)) {
293 throw new ValidatorException
294 ("Extended key usage does not permit use for TLS "
295 + "server authentication",
296 ValidatorException.T_EE_EXTENSIONS, cert);
297 }
298 }
299
300 if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_SSL_SERVER)) {
301 throw new ValidatorException
302 ("Netscape cert type does not permit use for SSL server",
303 ValidatorException.T_EE_EXTENSIONS, cert);
304 }
305
306 // remove extensions we checked
307 exts.remove(SimpleValidator.OID_KEY_USAGE);
308 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
309 exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
310 }
311
312 /**
313 * Check whether this certificate can be used for code signing.
314 * @throws CertificateException if not.
315 */
316 private void checkCodeSigning(X509Certificate cert)
317 throws CertificateException {
318 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
319 throw new ValidatorException
320 ("KeyUsage does not allow digital signatures",
321 ValidatorException.T_EE_EXTENSIONS, cert);
322 }
323
324 if (checkEKU(cert, exts, OID_EKU_CODE_SIGNING) == false) {
325 throw new ValidatorException
326 ("Extended key usage does not permit use for code signing",
327 ValidatorException.T_EE_EXTENSIONS, cert);
328 }
329
330 // do not check Netscape cert type for JCE code signing checks
331 // (some certs were issued with incorrect extensions)
332 if (variant.equals(Validator.VAR_JCE_SIGNING) == false) {
333 if (!SimpleValidator.getNetscapeCertTypeBit(cert, NSCT_CODE_SIGNING)) {
334 throw new ValidatorException
335 ("Netscape cert type does not permit use for code signing",
336 ValidatorException.T_EE_EXTENSIONS, cert);
337 }
338 exts.remove(SimpleValidator.OID_NETSCAPE_CERT_TYPE);
339 }
340
341 // remove extensions we checked
342 exts.remove(SimpleValidator.OID_KEY_USAGE);
343 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
344 }
345
346 /**
347 * Check whether this certificate can be used by a time stamping authority
348 * server (see RFC 3161, section 2.3).
349 * @throws CertificateException if not.
350 */
351 private void checkTSAServer(X509Certificate cert)
352 throws CertificateException {
353 if (checkKeyUsage(cert, KU_SIGNATURE) == false) {
354 throw new ValidatorException
355 ("KeyUsage does not allow digital signatures",
356 ValidatorException.T_EE_EXTENSIONS, cert);
357 }
358
359 if (cert.getExtendedKeyUsage() == null) {
360 throw new ValidatorException
361 ("Certificate does not contain an extended key usage " +
362 "extension required for a TSA server",
363 ValidatorException.T_EE_EXTENSIONS, cert);
364 }
365
366 if (checkEKU(cert, exts, OID_EKU_TIME_STAMPING) == false) {
367 throw new ValidatorException
368 ("Extended key usage does not permit use for TSA server",
369 ValidatorException.T_EE_EXTENSIONS, cert);
370 }
371
372 // remove extensions we checked
373 exts.remove(SimpleValidator.OID_KEY_USAGE);
374 exts.remove(SimpleValidator.OID_EXTENDED_KEY_USAGE);
375 }
376 }
|