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
26package java.security.cert;
27
28import java.io.IOException;
29import java.security.PublicKey;
30
31import javax.security.auth.x500.X500Principal;
32
33import sun.security.x509.NameConstraintsExtension;
34import 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 */
63public 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