Home | History | Annotate | Download | only in cert
      1 /*
      2  * Copyright (c) 2001, 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.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://www.ietf.org/rfc/rfc3280">RFC 3280</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 3280
    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 3280
    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.length() == 0)
    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 3280
    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         StringBuffer sb = new StringBuffer();
    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 }
    334