History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/validator/EndEntityChecker.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/validator/EndEntityChecker.java+382−0
@@ -0,0 +1,382 @@
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
23+ * questions.
24+ */
25+
26+package sun.security.validator;
27+
28+import java.util.*;
29+
30+import java.security.cert.*;
31+
32+import sun.security.x509.NetscapeCertTypeExtension;
33+
34+/**
35+ * Class to check if an end entity cert is suitable for use in some
36+ * context.<p>
37+ *
38+ * This class is used internally by the validator. Currently, seven variants
39+ * are supported defined as VAR_XXX constants in the Validator class:
40+ * <ul>
41+ * <li>Generic. No additional requirements, all certificates are ok.
42+ *
43+ * <li>TLS server. Requires that a String parameter is passed to
44+ * validate that specifies the name of the TLS key exchange algorithm
45+ * in use. See the JSSE X509TrustManager spec for details.
46+ *
47+ * <li>TLS client.
48+ *
49+ * <li>Code signing.
50+ *
51+ * <li>JCE code signing. Some early JCE code signing certs issued to
52+ * providers had incorrect extensions. In this mode the checks
53+ * are relaxed compared to standard code signing checks in order to
54+ * allow these certificates to pass.
55+ *
56+ * <li>Plugin code signing. WebStart and Plugin require their own variant
57+ * which is equivalent to VAR_CODE_SIGNING with additional checks for
58+ * compatibility/special cases. See also PKIXValidator.
59+ *
60+ * <li>TSA Server (see RFC 3161, section 2.3).
61+ *
62+ * </ul>
63+ *
64+ * @author Andreas Sterbenz
65+ */
66+class EndEntityChecker {
67+
68+ // extended key usage OIDs for TLS server, TLS client, code signing
69+ // and any usage
70+
71+ private final static String OID_EXTENDED_KEY_USAGE =
72+ SimpleValidator.OID_EXTENDED_KEY_USAGE;
73+
74+ private final static String OID_EKU_TLS_SERVER = "1.3.6.1.5.5.7.3.1";
75+
76+ private final static String OID_EKU_TLS_CLIENT = "1.3.6.1.5.5.7.3.2";
77+
78+ private final static String OID_EKU_CODE_SIGNING = "1.3.6.1.5.5.7.3.3";
79+
80+ private final static String OID_EKU_TIME_STAMPING = "1.3.6.1.5.5.7.3.8";
81+
82+ private final static String OID_EKU_ANY_USAGE = "2.5.29.37.0";
83+
84+ // the Netscape Server-Gated-Cryptography EKU extension OID
85+ private final static String OID_EKU_NS_SGC = "2.16.840.1.113730.4.1";
86+
87+ // the Microsoft Server-Gated-Cryptography EKU extension OID
88+ private final static String OID_EKU_MS_SGC = "1.3.6.1.4.1.311.10.3.3";
89+
90+ // the recognized extension OIDs
91+ private final static String OID_SUBJECT_ALT_NAME = "2.5.29.17";
92+
93+ private final static String NSCT_SSL_CLIENT =
94+ NetscapeCertTypeExtension.SSL_CLIENT;
95+
96+ private final static String NSCT_SSL_SERVER =
97+ NetscapeCertTypeExtension.SSL_SERVER;
98+
99+ private final static String NSCT_CODE_SIGNING =
100+ NetscapeCertTypeExtension.OBJECT_SIGNING;
101+
102+ // bit numbers in the key usage extension
103+ private final static int KU_SIGNATURE = 0;
104+ private final static int KU_KEY_ENCIPHERMENT = 2;
105+ private final static int KU_KEY_AGREEMENT = 4;
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 {
175+ // basic constraints irrelevant in EE certs
176+ exts.remove(SimpleValidator.OID_BASIC_CONSTRAINTS);
177+
178+ // If the subject field contains an empty sequence, the subjectAltName
179+ // extension MUST be marked critical.
180+ // We do not check the validity of the critical extension, just mark
181+ // it recognizable here.
182+ exts.remove(OID_SUBJECT_ALT_NAME);
183+
184+ if (!exts.isEmpty()) {
185+ throw new CertificateException("Certificate contains unsupported "
186+ + "critical extensions: " + exts);
187+ }
188+ }
189+
190+ /**
191+ * Utility method checking if the extended key usage extension in
192+ * certificate cert allows use for expectedEKU.
193+ */
194+ private boolean checkEKU(X509Certificate cert, Set<String> exts,
195+ String expectedEKU) throws CertificateException {
196+ List<String> eku = cert.getExtendedKeyUsage();
197+ if (eku == null) {
198+ return true;
199+ }
200+ return eku.contains(expectedEKU) || eku.contains(OID_EKU_ANY_USAGE);
201+ }
202+
203+ /**
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);
282+ }
283+
284+ if (checkEKU(cert, exts, OID_EKU_TLS_SERVER) == false) {
285+ // check for equivalent but now obsolete Server-Gated-Cryptography
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+}