1 /*
2  * Copyright (c) 2002, 2018, 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.AlgorithmConstraints;
31 import java.security.KeyStore;
32 import java.security.cert.*;
33 
34 /**
35  * Validator abstract base class. Concrete classes are instantiated by calling
36  * one of the getInstance() methods. All methods defined in this class
37  * must be safe for concurrent use by multiple threads.<p>
38  *
39  * The model is that a Validator instance is created specifying validation
40  * settings, such as trust anchors or PKIX parameters. Then one or more
41  * paths are validated using those parameters. In some cases, additional
42  * information can be provided per path validation. This is independent of
43  * the validation parameters and currently only used for TLS server validation.
44  * <p>
45  * Path validation is performed by calling one of the validate() methods. It
46  * specifies a suggested path to be used for validation if available, or only
47  * the end entity certificate otherwise. Optionally additional certificates can
48  * be specified that the caller believes could be helpful. Implementations are
49  * free to make use of this information or validate the path using other means.
50  * validate() also checks that the end entity certificate is suitable for the
51  * intended purpose as described below.
52  *
53  * <p>There are two orthogonal parameters to select the Validator
54  * implementation: type and variant. Type selects the validation algorithm.
55  * Currently supported are TYPE_SIMPLE and TYPE_PKIX. See SimpleValidator and
56  * PKIXValidator for details.
57  * <p>
58  * Variant controls additional extension checks. Currently supported are
59  * five variants:
60  * <ul>
61  * <li>VAR_GENERIC (no additional checks),
62  * <li>VAR_TLS_CLIENT (TLS client specific checks)
63  * <li>VAR_TLS_SERVER (TLS server specific checks), and
64  * <li>VAR_CODE_SIGNING (code signing specific checks).
65  * <li>VAR_JCE_SIGNING (JCE code signing specific checks).
66  * <li>VAR_TSA_SERVER (TSA server specific checks).
67  * <li>VAR_PLUGIN_CODE_SIGNING (Plugin/WebStart code signing specific checks).
68  * </ul>
69  * See EndEntityChecker for more information.
70  * <p>
71  * Examples:
72  * <pre>
73  *   // instantiate validator specifying type, variant, and trust anchors
74  *   Validator validator = Validator.getInstance(Validator.TYPE_PKIX,
75  *                                               Validator.VAR_TLS_CLIENT,
76  *                                               trustedCerts);
77  *   // validate one or more chains using the validator
78  *   validator.validate(chain); // throws CertificateException if failed
79  * </pre>
80  *
81  * @see SimpleValidator
82  * @see PKIXValidator
83  * @see EndEntityChecker
84  *
85  * @author Andreas Sterbenz
86  */
87 public abstract class Validator {
88 
89     final static X509Certificate[] CHAIN0 = {};
90 
91     /**
92      * Constant for a validator of type Simple.
93      * @see #getInstance
94      */
95     public final static String TYPE_SIMPLE = "Simple";
96 
97     /**
98      * Constant for a validator of type PKIX.
99      * @see #getInstance
100      */
101     public final static String TYPE_PKIX = "PKIX";
102 
103     /**
104      * Constant for a Generic variant of a validator.
105      * @see #getInstance
106      */
107     public final static String VAR_GENERIC = "generic";
108 
109     /**
110      * Constant for a Code Signing variant of a validator.
111      * @see #getInstance
112      */
113     public final static String VAR_CODE_SIGNING = "code signing";
114 
115     /**
116      * Constant for a JCE Code Signing variant of a validator.
117      * @see #getInstance
118      */
119     public final static String VAR_JCE_SIGNING = "jce signing";
120 
121     /**
122      * Constant for a TLS Client variant of a validator.
123      * @see #getInstance
124      */
125     public final static String VAR_TLS_CLIENT = "tls client";
126 
127     /**
128      * Constant for a TLS Server variant of a validator.
129      * @see #getInstance
130      */
131     public final static String VAR_TLS_SERVER = "tls server";
132 
133     /**
134      * Constant for a TSA Server variant of a validator.
135      * @see #getInstance
136      */
137     public final static String VAR_TSA_SERVER = "tsa server";
138 
139     /**
140      * Constant for a Code Signing variant of a validator for use by
141      * the J2SE Plugin/WebStart code.
142      * @see #getInstance
143      */
144     public final static String VAR_PLUGIN_CODE_SIGNING = "plugin code signing";
145 
146     private final String type;
147     final EndEntityChecker endEntityChecker;
148     final String variant;
149 
150     /**
151      * @deprecated
152      * @see #setValidationDate
153      */
154     @Deprecated
155     volatile Date validationDate;
156 
Validator(String type, String variant)157     Validator(String type, String variant) {
158         this.type = type;
159         this.variant = variant;
160         endEntityChecker = EndEntityChecker.getInstance(type, variant);
161     }
162 
163     /**
164      * Get a new Validator instance using the trusted certificates from the
165      * specified KeyStore as trust anchors.
166      */
getInstance(String type, String variant, KeyStore ks)167     public static Validator getInstance(String type, String variant,
168             KeyStore ks) {
169         return getInstance(type, variant, TrustStoreUtil.getTrustedCerts(ks));
170     }
171 
172     /**
173      * Get a new Validator instance using the Set of X509Certificates as trust
174      * anchors.
175      */
getInstance(String type, String variant, Collection<X509Certificate> trustedCerts)176     public static Validator getInstance(String type, String variant,
177             Collection<X509Certificate> trustedCerts) {
178         if (type.equals(TYPE_SIMPLE)) {
179             return new SimpleValidator(variant, trustedCerts);
180         } else if (type.equals(TYPE_PKIX)) {
181             return new PKIXValidator(variant, trustedCerts);
182         } else {
183             throw new IllegalArgumentException
184                 ("Unknown validator type: " + type);
185         }
186     }
187 
188     /**
189      * Get a new Validator instance using the provided PKIXBuilderParameters.
190      * This method can only be used with the PKIX validator.
191      */
getInstance(String type, String variant, PKIXBuilderParameters params)192     public static Validator getInstance(String type, String variant,
193             PKIXBuilderParameters params) {
194         if (type.equals(TYPE_PKIX) == false) {
195             throw new IllegalArgumentException
196                 ("getInstance(PKIXBuilderParameters) can only be used "
197                 + "with PKIX validator");
198         }
199         return new PKIXValidator(variant, params);
200     }
201 
202     /**
203      * Validate the given certificate chain.
204      */
validate(X509Certificate[] chain)205     public final X509Certificate[] validate(X509Certificate[] chain)
206             throws CertificateException {
207         return validate(chain, null, null);
208     }
209 
210     /**
211      * Validate the given certificate chain. If otherCerts is non-null, it is
212      * a Collection of additional X509Certificates that could be helpful for
213      * path building.
214      */
validate(X509Certificate[] chain, Collection<X509Certificate> otherCerts)215     public final X509Certificate[] validate(X509Certificate[] chain,
216         Collection<X509Certificate> otherCerts) throws CertificateException {
217         return validate(chain, otherCerts, null);
218     }
219 
220     /**
221      * Validate the given certificate chain. If otherCerts is non-null, it is
222      * a Collection of additional X509Certificates that could be helpful for
223      * path building.
224      * <p>
225      * Parameter is an additional parameter with variant specific meaning.
226      * Currently, it is only defined for TLS_SERVER variant validators, where
227      * it must be non null and the name of the TLS key exchange algorithm being
228      * used (see JSSE X509TrustManager specification). In the future, it
229      * could be used to pass in a PKCS#7 object for code signing to check time
230      * stamps.
231      * <p>
232      * @return a non-empty chain that was used to validate the path. The
233      * end entity cert is at index 0, the trust anchor at index n-1.
234      */
validate(X509Certificate[] chain, Collection<X509Certificate> otherCerts, Object parameter)235     public final X509Certificate[] validate(X509Certificate[] chain,
236             Collection<X509Certificate> otherCerts, Object parameter)
237             throws CertificateException {
238         return validate(chain, otherCerts, Collections.emptyList(), null,
239                 parameter);
240     }
241 
242     /**
243      * Validate the given certificate chain.
244      *
245      * @param chain the target certificate chain
246      * @param otherCerts a Collection of additional X509Certificates that
247      *        could be helpful for path building (or null)
248      * @param responseList a List of zero or more byte arrays, each
249      *        one being a DER-encoded OCSP response (per RFC 6960).  Entries
250      *        in the List must match the order of the certificates in the
251      *        chain parameter.  It is possible that fewer responses may be
252      *        in the list than are elements in {@code chain} and a missing
253      *        response for a matching element in {@code chain} can be
254      *        represented with a zero-length byte array.
255      * @param constraints algorithm constraints for certification path
256      *        processing
257      * @param parameter an additional parameter with variant specific meaning.
258      *        Currently, it is only defined for TLS_SERVER variant validators,
259      *        where it must be non null and the name of the TLS key exchange
260      *        algorithm being used (see JSSE X509TrustManager specification).
261      *        In the future, it could be used to pass in a PKCS#7 object for
262      *        code signing to check time stamps.
263      * @return a non-empty chain that was used to validate the path. The
264      *        end entity cert is at index 0, the trust anchor at index n-1.
265      */
validate(X509Certificate[] chain, Collection<X509Certificate> otherCerts, List<byte[]> responseList, AlgorithmConstraints constraints, Object parameter)266     public final X509Certificate[] validate(X509Certificate[] chain,
267                 Collection<X509Certificate> otherCerts,
268                 List<byte[]> responseList,
269                 AlgorithmConstraints constraints,
270                 Object parameter) throws CertificateException {
271         chain = engineValidate(chain, otherCerts, responseList, constraints,
272                 parameter);
273 
274         // omit EE extension check if EE cert is also trust anchor
275         if (chain.length > 1) {
276             // EndEntityChecker does not need to check unresolved critical
277             // extensions when validating with a TYPE_PKIX Validator.
278             // A TYPE_PKIX Validator will already have run checks on all
279             // certs' extensions, including checks by any PKIXCertPathCheckers
280             // included in the PKIXParameters, so the extra checks would be
281             // redundant.
282             boolean checkUnresolvedCritExts =
283                     (type == TYPE_PKIX) ? false : true;
284             endEntityChecker.check(chain, parameter,
285                                    checkUnresolvedCritExts);
286         }
287 
288         return chain;
289     }
290 
engineValidate(X509Certificate[] chain, Collection<X509Certificate> otherCerts, List<byte[]> responseList, AlgorithmConstraints constraints, Object parameter)291     abstract X509Certificate[] engineValidate(X509Certificate[] chain,
292                 Collection<X509Certificate> otherCerts,
293                 List<byte[]> responseList,
294                 AlgorithmConstraints constraints,
295                 Object parameter) throws CertificateException;
296 
297     /**
298      * Returns an immutable Collection of the X509Certificates this instance
299      * uses as trust anchors.
300      */
getTrustedCertificates()301     public abstract Collection<X509Certificate> getTrustedCertificates();
302 
303     /**
304      * Set the date to be used for subsequent validations. NOTE that
305      * this is not a supported API, it is provided to simplify
306      * writing tests only.
307      *
308      * @deprecated
309      */
310     @Deprecated
setValidationDate(Date validationDate)311     public void setValidationDate(Date validationDate) {
312         this.validationDate = validationDate;
313     }
314 
315 }
316