1 /*
2  * Copyright (c) 2000, 2013, 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 java.security.cert;
27 
28 import java.security.AccessController;
29 import java.security.InvalidAlgorithmParameterException;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.NoSuchProviderException;
32 import java.security.PrivilegedAction;
33 import java.security.Provider;
34 import java.security.Security;
35 import sun.security.util.Debug;
36 
37 import sun.security.jca.*;
38 import sun.security.jca.GetInstance.Instance;
39 
40 /**
41  * A class for building certification paths (also known as certificate chains).
42  * <p>
43  * This class uses a provider-based architecture.
44  * To create a {@code CertPathBuilder}, call
45  * one of the static {@code getInstance} methods, passing in the
46  * algorithm name of the {@code CertPathBuilder} desired and optionally
47  * the name of the provider desired.
48  *
49  * <p>Once a {@code CertPathBuilder} object has been created, certification
50  * paths can be constructed by calling the {@link #build build} method and
51  * passing it an algorithm-specific set of parameters. If successful, the
52  * result (including the {@code CertPath} that was built) is returned
53  * in an object that implements the {@code CertPathBuilderResult}
54  * interface.
55  *
56  * <p>The {@link #getRevocationChecker} method allows an application to specify
57  * additional algorithm-specific parameters and options used by the
58  * {@code CertPathBuilder} when checking the revocation status of certificates.
59  * Here is an example demonstrating how it is used with the PKIX algorithm:
60  *
61  * <pre>
62  * CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
63  * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
64  * rc.setOptions(EnumSet.of(Option.PREFER_CRLS));
65  * params.addCertPathChecker(rc);
66  * CertPathBuilderResult cpbr = cpb.build(params);
67  * </pre>
68  *
69  * <p> Android provides the following {@code CertPathBuilder} algorithms:
70  * <table>
71  *   <thead>
72  *     <tr>
73  *       <th>Algorithm</th>
74  *       <th>Supported API Levels</th>
75  *     </tr>
76  *   </thead>
77  *   <tbody>
78  *     <tr>
79  *       <td>PKIX</td>
80  *       <td>1+</td>
81  *     </tr>
82  *   </tbody>
83  * </table>
84  *
85  * This algorithm is described in the <a href=
86  * "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
87  * CertPathBuilder section</a> of the
88  * Java Cryptography Architecture Standard Algorithm Name Documentation.
89  * Consult the release documentation for your implementation to see if any
90  * other algorithms are supported.
91  *
92  * <p>
93  * <b>Concurrent Access</b>
94  * <p>
95  * The static methods of this class are guaranteed to be thread-safe.
96  * Multiple threads may concurrently invoke the static methods defined in
97  * this class with no ill effects.
98  * <p>
99  * However, this is not true for the non-static methods defined by this class.
100  * Unless otherwise documented by a specific provider, threads that need to
101  * access a single {@code CertPathBuilder} instance concurrently should
102  * synchronize amongst themselves and provide the necessary locking. Multiple
103  * threads each manipulating a different {@code CertPathBuilder} instance
104  * need not synchronize.
105  *
106  * @see CertPath
107  *
108  * @since       1.4
109  * @author      Sean Mullan
110  * @author      Yassir Elley
111  */
112 public class CertPathBuilder {
113 
114     /*
115      * Constant to lookup in the Security properties file to determine
116      * the default certpathbuilder type. In the Security properties file,
117      * the default certpathbuilder type is given as:
118      * <pre>
119      * certpathbuilder.type=PKIX
120      * </pre>
121      */
122     private static final String CPB_TYPE = "certpathbuilder.type";
123     private final CertPathBuilderSpi builderSpi;
124     private final Provider provider;
125     private final String algorithm;
126 
127     /**
128      * Creates a {@code CertPathBuilder} object of the given algorithm,
129      * and encapsulates the given provider implementation (SPI object) in it.
130      *
131      * @param builderSpi the provider implementation
132      * @param provider the provider
133      * @param algorithm the algorithm name
134      */
CertPathBuilder(CertPathBuilderSpi builderSpi, Provider provider, String algorithm)135     protected CertPathBuilder(CertPathBuilderSpi builderSpi, Provider provider,
136         String algorithm)
137     {
138         this.builderSpi = builderSpi;
139         this.provider = provider;
140         this.algorithm = algorithm;
141     }
142 
143     /**
144      * Returns a {@code CertPathBuilder} object that implements the
145      * specified algorithm.
146      *
147      * <p> This method traverses the list of registered security Providers,
148      * starting with the most preferred Provider.
149      * A new CertPathBuilder object encapsulating the
150      * CertPathBuilderSpi implementation from the first
151      * Provider that supports the specified algorithm is returned.
152      *
153      * <p> Note that the list of registered providers may be retrieved via
154      * the {@link Security#getProviders() Security.getProviders()} method.
155      *
156      * @param algorithm the name of the requested {@code CertPathBuilder}
157      *  algorithm.  See the CertPathBuilder section in the <a href=
158      *  "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
159      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
160      * for information about standard algorithm names.
161      *
162      * @return a {@code CertPathBuilder} object that implements the
163      *          specified algorithm.
164      *
165      * @throws NoSuchAlgorithmException if no Provider supports a
166      *          CertPathBuilderSpi implementation for the
167      *          specified algorithm.
168      *
169      * @see java.security.Provider
170      */
getInstance(String algorithm)171     public static CertPathBuilder getInstance(String algorithm)
172             throws NoSuchAlgorithmException {
173         Instance instance = GetInstance.getInstance("CertPathBuilder",
174             CertPathBuilderSpi.class, algorithm);
175         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
176             instance.provider, algorithm);
177     }
178 
179     /**
180      * Returns a {@code CertPathBuilder} object that implements the
181      * specified algorithm.
182      *
183      * <p> A new CertPathBuilder object encapsulating the
184      * CertPathBuilderSpi implementation from the specified provider
185      * is returned.  The specified provider must be registered
186      * in the security provider list.
187      *
188      * <p> Note that the list of registered providers may be retrieved via
189      * the {@link Security#getProviders() Security.getProviders()} method.
190      *
191      * @param algorithm the name of the requested {@code CertPathBuilder}
192      *  algorithm.  See the CertPathBuilder section in the <a href=
193      *  "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
194      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
195      * for information about standard algorithm names.
196      *
197      * @param provider the name of the provider.
198      *
199      * @return a {@code CertPathBuilder} object that implements the
200      *          specified algorithm.
201      *
202      * @throws NoSuchAlgorithmException if a CertPathBuilderSpi
203      *          implementation for the specified algorithm is not
204      *          available from the specified provider.
205      *
206      * @throws NoSuchProviderException if the specified provider is not
207      *          registered in the security provider list.
208      *
209      * @exception IllegalArgumentException if the {@code provider} is
210      *          null or empty.
211      *
212      * @see java.security.Provider
213      */
getInstance(String algorithm, String provider)214     public static CertPathBuilder getInstance(String algorithm, String provider)
215            throws NoSuchAlgorithmException, NoSuchProviderException {
216         Instance instance = GetInstance.getInstance("CertPathBuilder",
217             CertPathBuilderSpi.class, algorithm, provider);
218         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
219             instance.provider, algorithm);
220     }
221 
222     /**
223      * Returns a {@code CertPathBuilder} object that implements the
224      * specified algorithm.
225      *
226      * <p> A new CertPathBuilder object encapsulating the
227      * CertPathBuilderSpi implementation from the specified Provider
228      * object is returned.  Note that the specified Provider object
229      * does not have to be registered in the provider list.
230      *
231      * @param algorithm the name of the requested {@code CertPathBuilder}
232      *  algorithm.  See the CertPathBuilder section in the <a href=
233      *  "{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/security/StandardNames.html#CertPathBuilder">
234      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
235      * for information about standard algorithm names.
236      *
237      * @param provider the provider.
238      *
239      * @return a {@code CertPathBuilder} object that implements the
240      *          specified algorithm.
241      *
242      * @exception NoSuchAlgorithmException if a CertPathBuilderSpi
243      *          implementation for the specified algorithm is not available
244      *          from the specified Provider object.
245      *
246      * @exception IllegalArgumentException if the {@code provider} is
247      *          null.
248      *
249      * @see java.security.Provider
250      */
getInstance(String algorithm, Provider provider)251     public static CertPathBuilder getInstance(String algorithm,
252             Provider provider) throws NoSuchAlgorithmException {
253         Instance instance = GetInstance.getInstance("CertPathBuilder",
254             CertPathBuilderSpi.class, algorithm, provider);
255         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
256             instance.provider, algorithm);
257     }
258 
259     /**
260      * Returns the provider of this {@code CertPathBuilder}.
261      *
262      * @return the provider of this {@code CertPathBuilder}
263      */
getProvider()264     public final Provider getProvider() {
265         return this.provider;
266     }
267 
268     /**
269      * Returns the name of the algorithm of this {@code CertPathBuilder}.
270      *
271      * @return the name of the algorithm of this {@code CertPathBuilder}
272      */
getAlgorithm()273     public final String getAlgorithm() {
274         return this.algorithm;
275     }
276 
277     /**
278      * Attempts to build a certification path using the specified algorithm
279      * parameter set.
280      *
281      * @param params the algorithm parameters
282      * @return the result of the build algorithm
283      * @throws CertPathBuilderException if the builder is unable to construct
284      *  a certification path that satisfies the specified parameters
285      * @throws InvalidAlgorithmParameterException if the specified parameters
286      * are inappropriate for this {@code CertPathBuilder}
287      */
build(CertPathParameters params)288     public final CertPathBuilderResult build(CertPathParameters params)
289         throws CertPathBuilderException, InvalidAlgorithmParameterException
290     {
291         return builderSpi.engineBuild(params);
292     }
293 
294     /**
295      * Returns the default {@code CertPathBuilder} type as specified by
296      * the {@code certpathbuilder.type} security property, or the string
297      * {@literal "PKIX"} if no such property exists.
298      *
299      * <p>The default {@code CertPathBuilder} type can be used by
300      * applications that do not want to use a hard-coded type when calling one
301      * of the {@code getInstance} methods, and want to provide a default
302      * type in case a user does not specify its own.
303      *
304      * <p>The default {@code CertPathBuilder} type can be changed by
305      * setting the value of the {@code certpathbuilder.type} security property
306      * to the desired type.
307      *
308      * @see java.security.Security security properties
309      * @return the default {@code CertPathBuilder} type as specified
310      * by the {@code certpathbuilder.type} security property, or the string
311      * {@literal "PKIX"} if no such property exists.
312      */
getDefaultType()313     public final static String getDefaultType() {
314         String cpbtype =
315             AccessController.doPrivileged(new PrivilegedAction<String>() {
316                 public String run() {
317                     return Security.getProperty(CPB_TYPE);
318                 }
319             });
320         return (cpbtype == null) ? "PKIX" : cpbtype;
321     }
322 
323     /**
324      * Returns a {@code CertPathChecker} that the encapsulated
325      * {@code CertPathBuilderSpi} implementation uses to check the revocation
326      * status of certificates. A PKIX implementation returns objects of
327      * type {@code PKIXRevocationChecker}. Each invocation of this method
328      * returns a new instance of {@code CertPathChecker}.
329      *
330      * <p>The primary purpose of this method is to allow callers to specify
331      * additional input parameters and options specific to revocation checking.
332      * See the class description for an example.
333      *
334      * @return a {@code CertPathChecker}
335      * @throws UnsupportedOperationException if the service provider does not
336      *         support this method
337      * @since 1.8
338      */
getRevocationChecker()339     public final CertPathChecker getRevocationChecker() {
340         return builderSpi.engineGetRevocationChecker();
341     }
342 }
343