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
26package java.security.cert;
27
28import java.security.AccessController;
29import java.security.InvalidAlgorithmParameterException;
30import java.security.NoSuchAlgorithmException;
31import java.security.NoSuchProviderException;
32import java.security.PrivilegedAction;
33import java.security.Provider;
34import java.security.Security;
35import sun.security.util.Debug;
36
37import sun.security.jca.*;
38import 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 */
112public 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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
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     */
339    public final CertPathChecker getRevocationChecker() {
340        return builderSpi.engineGetRevocationChecker();
341    }
342}
343