View Javadoc
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 }