1 /*
   2  * Copyright (c) 2000, 2011, 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</code>, call
  45  * one of the static <code>getInstance</code> methods, passing in the
  46  * algorithm name of the <code>CertPathBuilder</code> desired and optionally
  47  * the name of the provider desired.
  48  * <p>
  49  * Once a <code>CertPathBuilder</code> 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</code> that was built) is returned
  53  * in an object that implements the <code>CertPathBuilderResult</code>
  54  * interface.
  55  *
  56  * <p> Every implementation of the Java platform is required to support the
  57  * following standard <code>CertPathBuilder</code> algorithm:
  58  * <ul>
  59  * <li><tt>PKIX</tt></li>
  60  * </ul>
  61  * This algorithm is described in the <a href=
  62  * "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder">
  63  * CertPathBuilder section</a> of the
  64  * Java Cryptography Architecture Standard Algorithm Name Documentation.
  65  * Consult the release documentation for your implementation to see if any
  66  * other algorithms are supported.
  67  *
  68  * <p>
  69  * <b>Concurrent Access</b>
  70  * <p>
  71  * The static methods of this class are guaranteed to be thread-safe.
  72  * Multiple threads may concurrently invoke the static methods defined in
  73  * this class with no ill effects.
  74  * <p>
  75  * However, this is not true for the non-static methods defined by this class.
  76  * Unless otherwise documented by a specific provider, threads that need to
  77  * access a single <code>CertPathBuilder</code> instance concurrently should
  78  * synchronize amongst themselves and provide the necessary locking. Multiple
  79  * threads each manipulating a different <code>CertPathBuilder</code> instance
  80  * need not synchronize.
  81  *
  82  * @see CertPath
  83  *
  84  * @since       1.4
  85  * @author      Sean Mullan
  86  * @author      Yassir Elley
  87  */
  88 public class CertPathBuilder {
  89 
  90     /*
  91      * Constant to lookup in the Security properties file to determine
  92      * the default certpathbuilder type. In the Security properties file,
  93      * the default certpathbuilder type is given as:
  94      * <pre>
  95      * certpathbuilder.type=PKIX
  96      * </pre>
  97      */
  98     private static final String CPB_TYPE = "certpathbuilder.type";
  99     private static final Debug debug = Debug.getInstance("certpath");
 100     private CertPathBuilderSpi builderSpi;
 101     private Provider provider;
 102     private String algorithm;
 103 
 104     /**
 105      * Creates a <code>CertPathBuilder</code> object of the given algorithm,
 106      * and encapsulates the given provider implementation (SPI object) in it.
 107      *
 108      * @param builderSpi the provider implementation
 109      * @param provider the provider
 110      * @param algorithm the algorithm name
 111      */
 112     protected CertPathBuilder(CertPathBuilderSpi builderSpi, Provider provider,
 113         String algorithm)
 114     {
 115         this.builderSpi = builderSpi;
 116         this.provider = provider;
 117         this.algorithm = algorithm;
 118     }
 119 
 120     /**
 121      * Returns a <code>CertPathBuilder</code> object that implements the
 122      * specified algorithm.
 123      *
 124      * <p> This method traverses the list of registered security Providers,
 125      * starting with the most preferred Provider.
 126      * A new CertPathBuilder object encapsulating the
 127      * CertPathBuilderSpi implementation from the first
 128      * Provider that supports the specified algorithm is returned.
 129      *
 130      * <p> Note that the list of registered providers may be retrieved via
 131      * the {@link Security#getProviders() Security.getProviders()} method.
 132      *
 133      * @param algorithm the name of the requested <code>CertPathBuilder</code>
 134      *  algorithm.  See the CertPathBuilder section in the <a href=
 135      *  "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder">
 136      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 137      * for information about standard algorithm names.
 138      *
 139      * @return a <code>CertPathBuilder</code> object that implements the
 140      *          specified algorithm.
 141      *
 142      * @throws NoSuchAlgorithmException if no Provider supports a
 143      *          CertPathBuilderSpi implementation for the
 144      *          specified algorithm.
 145      *
 146      * @see java.security.Provider
 147      */
 148     public static CertPathBuilder getInstance(String algorithm)
 149             throws NoSuchAlgorithmException {
 150         Instance instance = GetInstance.getInstance("CertPathBuilder",
 151             CertPathBuilderSpi.class, algorithm);
 152         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
 153             instance.provider, algorithm);
 154     }
 155 
 156     /**
 157      * Returns a <code>CertPathBuilder</code> object that implements the
 158      * specified algorithm.
 159      *
 160      * <p> A new CertPathBuilder object encapsulating the
 161      * CertPathBuilderSpi implementation from the specified provider
 162      * is returned.  The specified provider must be registered
 163      * in the security provider list.
 164      *
 165      * <p> Note that the list of registered providers may be retrieved via
 166      * the {@link Security#getProviders() Security.getProviders()} method.
 167      *
 168      * @param algorithm the name of the requested <code>CertPathBuilder</code>
 169      *  algorithm.  See the CertPathBuilder section in the <a href=
 170      *  "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder">
 171      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 172      * for information about standard algorithm names.
 173      *
 174      * @param provider the name of the provider.
 175      *
 176      * @return a <code>CertPathBuilder</code> object that implements the
 177      *          specified algorithm.
 178      *
 179      * @throws NoSuchAlgorithmException if a CertPathBuilderSpi
 180      *          implementation for the specified algorithm is not
 181      *          available from the specified provider.
 182      *
 183      * @throws NoSuchProviderException if the specified provider is not
 184      *          registered in the security provider list.
 185      *
 186      * @exception IllegalArgumentException if the <code>provider</code> is
 187      *          null or empty.
 188      *
 189      * @see java.security.Provider
 190      */
 191     public static CertPathBuilder getInstance(String algorithm, String provider)
 192            throws NoSuchAlgorithmException, NoSuchProviderException {
 193         Instance instance = GetInstance.getInstance("CertPathBuilder",
 194             CertPathBuilderSpi.class, algorithm, provider);
 195         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
 196             instance.provider, algorithm);
 197     }
 198 
 199     /**
 200      * Returns a <code>CertPathBuilder</code> object that implements the
 201      * specified algorithm.
 202      *
 203      * <p> A new CertPathBuilder object encapsulating the
 204      * CertPathBuilderSpi implementation from the specified Provider
 205      * object is returned.  Note that the specified Provider object
 206      * does not have to be registered in the provider list.
 207      *
 208      * @param algorithm the name of the requested <code>CertPathBuilder</code>
 209      *  algorithm.  See the CertPathBuilder section in the <a href=
 210      *  "{@docRoot}/../technotes/guides/security/StandardNames.html#CertPathBuilder">
 211      * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 212      * for information about standard algorithm names.
 213      *
 214      * @param provider the provider.
 215      *
 216      * @return a <code>CertPathBuilder</code> object that implements the
 217      *          specified algorithm.
 218      *
 219      * @exception NoSuchAlgorithmException if a CertPathBuilderSpi
 220      *          implementation for the specified algorithm is not available
 221      *          from the specified Provider object.
 222      *
 223      * @exception IllegalArgumentException if the <code>provider</code> is
 224      *          null.
 225      *
 226      * @see java.security.Provider
 227      */
 228     public static CertPathBuilder getInstance(String algorithm,
 229             Provider provider) throws NoSuchAlgorithmException {
 230         Instance instance = GetInstance.getInstance("CertPathBuilder",
 231             CertPathBuilderSpi.class, algorithm, provider);
 232         return new CertPathBuilder((CertPathBuilderSpi)instance.impl,
 233             instance.provider, algorithm);
 234     }
 235 
 236     /**
 237      * Returns the provider of this <code>CertPathBuilder</code>.
 238      *
 239      * @return the provider of this <code>CertPathBuilder</code>
 240      */
 241     public final Provider getProvider() {
 242         return this.provider;
 243     }
 244 
 245     /**
 246      * Returns the name of the algorithm of this <code>CertPathBuilder</code>.
 247      *
 248      * @return the name of the algorithm of this <code>CertPathBuilder</code>
 249      */
 250     public final String getAlgorithm() {
 251         return this.algorithm;
 252     }
 253 
 254     /**
 255      * Attempts to build a certification path using the specified algorithm
 256      * parameter set.
 257      *
 258      * @param params the algorithm parameters
 259      * @return the result of the build algorithm
 260      * @throws CertPathBuilderException if the builder is unable to construct
 261      *  a certification path that satisfies the specified parameters
 262      * @throws InvalidAlgorithmParameterException if the specified parameters
 263      * are inappropriate for this <code>CertPathBuilder</code>
 264      */
 265     public final CertPathBuilderResult build(CertPathParameters params)
 266         throws CertPathBuilderException, InvalidAlgorithmParameterException
 267     {
 268         return builderSpi.engineBuild(params);
 269     }
 270 
 271     /**
 272      * Returns the default <code>CertPathBuilder</code> type as specified in
 273      * the Java security properties file, or the string &quot;PKIX&quot;
 274      * if no such property exists. The Java security properties file is
 275      * located in the file named &lt;JAVA_HOME&gt;/lib/security/java.security.
 276      * &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
 277      * and specifies the directory where the JRE is installed.
 278      *
 279      * <p>The default <code>CertPathBuilder</code> type can be used by
 280      * applications that do not want to use a hard-coded type when calling one
 281      * of the <code>getInstance</code> methods, and want to provide a default
 282      * type in case a user does not specify its own.
 283      *
 284      * <p>The default <code>CertPathBuilder</code> type can be changed by
 285      * setting the value of the "certpathbuilder.type" security property
 286      * (in the Java security properties file) to the desired type.
 287      *
 288      * @return the default <code>CertPathBuilder</code> type as specified
 289      * in the Java security properties file, or the string &quot;PKIX&quot;
 290      * if no such property exists.
 291      */
 292     public final static String getDefaultType() {
 293         String cpbtype;
 294         cpbtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
 295             public String run() {
 296                 return Security.getProperty(CPB_TYPE);
 297             }
 298         });
 299         if (cpbtype == null) {
 300             cpbtype = "PKIX";
 301         }
 302         return cpbtype;
 303     }
 304 }