Home | History | Annotate | Download | only in cert
      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      */
    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