1 /*
   2  * Copyright (c) 2001, 2014, 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.io.IOException;
  29 import java.security.PublicKey;
  30 
  31 import javax.security.auth.x500.X500Principal;
  32 
  33 import sun.security.x509.NameConstraintsExtension;
  34 import sun.security.x509.X500Name;
  35 
  36 /**
  37  * A trust anchor or most-trusted Certification Authority (CA).
  38  * <p>
  39  * This class represents a "most-trusted CA", which is used as a trust anchor
  40  * for validating X.509 certification paths. A most-trusted CA includes the
  41  * public key of the CA, the CA's name, and any constraints upon the set of
  42  * paths which may be validated using this key. These parameters can be
  43  * specified in the form of a trusted {@code X509Certificate} or as
  44  * individual parameters.
  45  * <p>
  46  * <b>Concurrent Access</b>
  47  * <p>All {@code TrustAnchor} objects must be immutable and
  48  * thread-safe. That is, multiple threads may concurrently invoke the
  49  * methods defined in this class on a single {@code TrustAnchor}
  50  * object (or more than one) with no ill effects. Requiring
  51  * {@code TrustAnchor} objects to be immutable and thread-safe
  52  * allows them to be passed around to various pieces of code without
  53  * worrying about coordinating access. This stipulation applies to all
  54  * public fields and methods of this class and any added or overridden
  55  * by subclasses.
  56  *
  57  * @see PKIXParameters#PKIXParameters(Set)
  58  * @see PKIXBuilderParameters#PKIXBuilderParameters(Set, CertSelector)
  59  *
  60  * @since       1.4
  61  * @author      Sean Mullan
  62  */
  63 public class TrustAnchor {
  64 
  65     private final PublicKey pubKey;
  66     private final String caName;
  67     private final X500Principal caPrincipal;
  68     private final X509Certificate trustedCert;
  69     private byte[] ncBytes;
  70     private NameConstraintsExtension nc;
  71 
  72     /**
  73      * Creates an instance of {@code TrustAnchor} with the specified
  74      * {@code X509Certificate} and optional name constraints, which
  75      * are intended to be used as additional constraints when validating
  76      * an X.509 certification path.
  77      * <p>
  78      * The name constraints are specified as a byte array. This byte array
  79      * should contain the DER encoded form of the name constraints, as they
  80      * would appear in the NameConstraints structure defined in
  81      * <a href="http://tools.ietf.org/html/rfc5280">RFC 5280</a>
  82      * and X.509. The ASN.1 definition of this structure appears below.
  83      *
  84      * <pre>{@code
  85      *  NameConstraints ::= SEQUENCE {
  86      *       permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
  87      *       excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
  88      *
  89      *  GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
  90      *
  91      *  GeneralSubtree ::= SEQUENCE {
  92      *       base                    GeneralName,
  93      *       minimum         [0]     BaseDistance DEFAULT 0,
  94      *       maximum         [1]     BaseDistance OPTIONAL }
  95      *
  96      *  BaseDistance ::= INTEGER (0..MAX)
  97      *
  98      *  GeneralName ::= CHOICE {
  99      *       otherName                       [0]     OtherName,
 100      *       rfc822Name                      [1]     IA5String,
 101      *       dNSName                         [2]     IA5String,
 102      *       x400Address                     [3]     ORAddress,
 103      *       directoryName                   [4]     Name,
 104      *       ediPartyName                    [5]     EDIPartyName,
 105      *       uniformResourceIdentifier       [6]     IA5String,
 106      *       iPAddress                       [7]     OCTET STRING,
 107      *       registeredID                    [8]     OBJECT IDENTIFIER}
 108      * }</pre>
 109      * <p>
 110      * Note that the name constraints byte array supplied is cloned to protect
 111      * against subsequent modifications.
 112      *
 113      * @param trustedCert a trusted {@code X509Certificate}
 114      * @param nameConstraints a byte array containing the ASN.1 DER encoding of
 115      * a NameConstraints extension to be used for checking name constraints.
 116      * Only the value of the extension is included, not the OID or criticality
 117      * flag. Specify {@code null} to omit the parameter.
 118      * @throws IllegalArgumentException if the name constraints cannot be
 119      * decoded
 120      * @throws NullPointerException if the specified
 121      * {@code X509Certificate} is {@code null}
 122      */
 123     public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints)
 124     {
 125         if (trustedCert == null)
 126             throw new NullPointerException("the trustedCert parameter must " +
 127                 "be non-null");
 128         this.trustedCert = trustedCert;
 129         this.pubKey = null;
 130         this.caName = null;
 131         this.caPrincipal = null;
 132         setNameConstraints(nameConstraints);
 133     }
 134 
 135     /**
 136      * Creates an instance of {@code TrustAnchor} where the
 137      * most-trusted CA is specified as an X500Principal and public key.
 138      * Name constraints are an optional parameter, and are intended to be used
 139      * as additional constraints when validating an X.509 certification path.
 140      * <p>
 141      * The name constraints are specified as a byte array. This byte array
 142      * contains the DER encoded form of the name constraints, as they
 143      * would appear in the NameConstraints structure defined in RFC 5280
 144      * and X.509. The ASN.1 notation for this structure is supplied in the
 145      * documentation for
 146      * {@link #TrustAnchor(X509Certificate, byte[])
 147      * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
 148      * <p>
 149      * Note that the name constraints byte array supplied here is cloned to
 150      * protect against subsequent modifications.
 151      *
 152      * @param caPrincipal the name of the most-trusted CA as X500Principal
 153      * @param pubKey the public key of the most-trusted CA
 154      * @param nameConstraints a byte array containing the ASN.1 DER encoding of
 155      * a NameConstraints extension to be used for checking name constraints.
 156      * Only the value of the extension is included, not the OID or criticality
 157      * flag. Specify {@code null} to omit the parameter.
 158      * @throws NullPointerException if the specified {@code caPrincipal} or
 159      * {@code pubKey} parameter is {@code null}
 160      * @since 1.5
 161      */
 162     public TrustAnchor(X500Principal caPrincipal, PublicKey pubKey,
 163             byte[] nameConstraints) {
 164         if ((caPrincipal == null) || (pubKey == null)) {
 165             throw new NullPointerException();
 166         }
 167         this.trustedCert = null;
 168         this.caPrincipal = caPrincipal;
 169         this.caName = caPrincipal.getName();
 170         this.pubKey = pubKey;
 171         setNameConstraints(nameConstraints);
 172     }
 173 
 174     /**
 175      * Creates an instance of {@code TrustAnchor} where the
 176      * most-trusted CA is specified as a distinguished name and public key.
 177      * Name constraints are an optional parameter, and are intended to be used
 178      * as additional constraints when validating an X.509 certification path.
 179      * <p>
 180      * The name constraints are specified as a byte array. This byte array
 181      * contains the DER encoded form of the name constraints, as they
 182      * would appear in the NameConstraints structure defined in RFC 5280
 183      * and X.509. The ASN.1 notation for this structure is supplied in the
 184      * documentation for
 185      * {@link #TrustAnchor(X509Certificate, byte[])
 186      * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
 187      * <p>
 188      * Note that the name constraints byte array supplied here is cloned to
 189      * protect against subsequent modifications.
 190      *
 191      * @param caName the X.500 distinguished name of the most-trusted CA in
 192      * <a href="http://www.ietf.org/rfc/rfc2253.txt">RFC 2253</a>
 193      * {@code String} format
 194      * @param pubKey the public key of the most-trusted CA
 195      * @param nameConstraints a byte array containing the ASN.1 DER encoding of
 196      * a NameConstraints extension to be used for checking name constraints.
 197      * Only the value of the extension is included, not the OID or criticality
 198      * flag. Specify {@code null} to omit the parameter.
 199      * @throws IllegalArgumentException if the specified
 200      * {@code caName} parameter is empty {@code (caName.length() == 0)}
 201      * or incorrectly formatted or the name constraints cannot be decoded
 202      * @throws NullPointerException if the specified {@code caName} or
 203      * {@code pubKey} parameter is {@code null}
 204      */
 205     public TrustAnchor(String caName, PublicKey pubKey, byte[] nameConstraints)
 206     {
 207         if (pubKey == null)
 208             throw new NullPointerException("the pubKey parameter must be " +
 209                 "non-null");
 210         if (caName == null)
 211             throw new NullPointerException("the caName parameter must be " +
 212                 "non-null");
 213         if (caName.isEmpty())
 214             throw new IllegalArgumentException("the caName " +
 215                 "parameter must be a non-empty String");
 216         // check if caName is formatted correctly
 217         this.caPrincipal = new X500Principal(caName);
 218         this.pubKey = pubKey;
 219         this.caName = caName;
 220         this.trustedCert = null;
 221         setNameConstraints(nameConstraints);
 222     }
 223 
 224     /**
 225      * Returns the most-trusted CA certificate.
 226      *
 227      * @return a trusted {@code X509Certificate} or {@code null}
 228      * if the trust anchor was not specified as a trusted certificate
 229      */
 230     public final X509Certificate getTrustedCert() {
 231         return this.trustedCert;
 232     }
 233 
 234     /**
 235      * Returns the name of the most-trusted CA as an X500Principal.
 236      *
 237      * @return the X.500 distinguished name of the most-trusted CA, or
 238      * {@code null} if the trust anchor was not specified as a trusted
 239      * public key and name or X500Principal pair
 240      * @since 1.5
 241      */
 242     public final X500Principal getCA() {
 243         return this.caPrincipal;
 244     }
 245 
 246     /**
 247      * Returns the name of the most-trusted CA in RFC 2253 {@code String}
 248      * format.
 249      *
 250      * @return the X.500 distinguished name of the most-trusted CA, or
 251      * {@code null} if the trust anchor was not specified as a trusted
 252      * public key and name or X500Principal pair
 253      */
 254     public final String getCAName() {
 255         return this.caName;
 256     }
 257 
 258     /**
 259      * Returns the public key of the most-trusted CA.
 260      *
 261      * @return the public key of the most-trusted CA, or {@code null}
 262      * if the trust anchor was not specified as a trusted public key and name
 263      * or X500Principal pair
 264      */
 265     public final PublicKey getCAPublicKey() {
 266         return this.pubKey;
 267     }
 268 
 269     /**
 270      * Decode the name constraints and clone them if not null.
 271      */
 272     private void setNameConstraints(byte[] bytes) {
 273         if (bytes == null) {
 274             ncBytes = null;
 275             nc = null;
 276         } else {
 277             ncBytes = bytes.clone();
 278             // validate DER encoding
 279             try {
 280                 nc = new NameConstraintsExtension(Boolean.FALSE, bytes);
 281             } catch (IOException ioe) {
 282                 IllegalArgumentException iae =
 283                     new IllegalArgumentException(ioe.getMessage());
 284                 iae.initCause(ioe);
 285                 throw iae;
 286             }
 287         }
 288     }
 289 
 290     /**
 291      * Returns the name constraints parameter. The specified name constraints
 292      * are associated with this trust anchor and are intended to be used
 293      * as additional constraints when validating an X.509 certification path.
 294      * <p>
 295      * The name constraints are returned as a byte array. This byte array
 296      * contains the DER encoded form of the name constraints, as they
 297      * would appear in the NameConstraints structure defined in RFC 5280
 298      * and X.509. The ASN.1 notation for this structure is supplied in the
 299      * documentation for
 300      * {@link #TrustAnchor(X509Certificate, byte[])
 301      * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
 302      * <p>
 303      * Note that the byte array returned is cloned to protect against
 304      * subsequent modifications.
 305      *
 306      * @return a byte array containing the ASN.1 DER encoding of
 307      *         a NameConstraints extension used for checking name constraints,
 308      *         or {@code null} if not set.
 309      */
 310     public final byte [] getNameConstraints() {
 311         return ncBytes == null ? null : ncBytes.clone();
 312     }
 313 
 314     /**
 315      * Returns a formatted string describing the {@code TrustAnchor}.
 316      *
 317      * @return a formatted string describing the {@code TrustAnchor}
 318      */
 319     public String toString() {
 320         StringBuilder sb = new StringBuilder();
 321         sb.append("[\n");
 322         if (pubKey != null) {
 323             sb.append("  Trusted CA Public Key: " + pubKey.toString() + "\n");
 324             sb.append("  Trusted CA Issuer Name: "
 325                 + String.valueOf(caName) + "\n");
 326         } else {
 327             sb.append("  Trusted CA cert: " + trustedCert.toString() + "\n");
 328         }
 329         if (nc != null)
 330             sb.append("  Name Constraints: " + nc.toString() + "\n");
 331         return sb.toString();
 332     }
 333 }