1. /*
  2. * @(#)TrustAnchor.java 1.8 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package java.security.cert;
  8. import java.io.IOException;
  9. import java.security.PublicKey;
  10. import javax.security.auth.x500.X500Principal;
  11. import sun.security.x509.NameConstraintsExtension;
  12. import sun.security.x509.X500Name;
  13. /**
  14. * A trust anchor or most-trusted Certification Authority (CA).
  15. * <p>
  16. * This class represents a "most-trusted CA", which is used as a trust anchor
  17. * for validating X.509 certification paths. A most-trusted CA includes the
  18. * public key of the CA, the CA's name, and any constraints upon the set of
  19. * paths which may be validated using this key. These parameters can be
  20. * specified in the form of a trusted <code>X509Certificate</code> or as
  21. * individual parameters.
  22. * <p>
  23. * <b>Concurrent Access</b>
  24. * <p>
  25. * <p>All <code>TrustAnchor</code> objects must be immutable and
  26. * thread-safe. That is, multiple threads may concurrently invoke the
  27. * methods defined in this class on a single <code>TrustAnchor</code>
  28. * object (or more than one) with no ill effects. Requiring
  29. * <code>TrustAnchor</code> objects to be immutable and thread-safe
  30. * allows them to be passed around to various pieces of code without
  31. * worrying about coordinating access. This stipulation applies to all
  32. * public fields and methods of this class and any added or overridden
  33. * by subclasses.
  34. *
  35. * @see PKIXParameters#PKIXParameters(Set)
  36. * @see PKIXBuilderParameters#PKIXBuilderParameters(Set, CertSelector)
  37. *
  38. * @version 1.8 01/23/03
  39. * @since 1.4
  40. * @author Sean Mullan
  41. */
  42. public class TrustAnchor {
  43. static {
  44. CertPathHelperImpl.initialize();
  45. }
  46. private PublicKey pubKey;
  47. private String caName;
  48. private X500Principal caPrincipal;
  49. private X509Certificate trustedCert;
  50. private byte [] ncBytes;
  51. private NameConstraintsExtension nc;
  52. /**
  53. * Creates an instance of <code>TrustAnchor</code> with the specified
  54. * <code>X509Certificate</code> and optional name constraints, which
  55. * are intended to be used as additional constraints when validating
  56. * an X.509 certification path.
  57. * <p>
  58. * The name constraints are specified as a byte array. This byte array
  59. * should contain the DER encoded form of the name constraints, as they
  60. * would appear in the NameConstraints structure defined in RFC 2459
  61. * and X.509. The ASN.1 definition of this structure appears below.
  62. *
  63. * <pre><code>
  64. * NameConstraints ::= SEQUENCE {
  65. * permittedSubtrees [0] GeneralSubtrees OPTIONAL,
  66. * excludedSubtrees [1] GeneralSubtrees OPTIONAL }
  67. *
  68. * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
  69. *
  70. * GeneralSubtree ::= SEQUENCE {
  71. * base GeneralName,
  72. * minimum [0] BaseDistance DEFAULT 0,
  73. * maximum [1] BaseDistance OPTIONAL }
  74. *
  75. * BaseDistance ::= INTEGER (0..MAX)
  76. *
  77. * GeneralName ::= CHOICE {
  78. * otherName [0] OtherName,
  79. * rfc822Name [1] IA5String,
  80. * dNSName [2] IA5String,
  81. * x400Address [3] ORAddress,
  82. * directoryName [4] Name,
  83. * ediPartyName [5] EDIPartyName,
  84. * uniformResourceIdentifier [6] IA5String,
  85. * iPAddress [7] OCTET STRING,
  86. * registeredID [8] OBJECT IDENTIFIER}
  87. * </code></pre>
  88. * <p>
  89. * Note that the name constraints byte array supplied is cloned to protect
  90. * against subsequent modifications.
  91. *
  92. * @param trustedCert a trusted <code>X509Certificate</code>
  93. * @param nameConstraints a byte array containing the ASN.1 DER encoding of
  94. * a NameConstraints extension to be used for checking name constraints.
  95. * Only the value of the extension is included, not the OID or criticality
  96. * flag. Specify <code>null</code> to omit the parameter.
  97. * @throws IllegalArgumentException if the name constraints cannot be
  98. * decoded
  99. * @throws NullPointerException if the specified
  100. * <code>X509Certificate</code> is <code>null</code>
  101. */
  102. public TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints)
  103. {
  104. if (trustedCert == null)
  105. throw new NullPointerException("the trustedCert parameter must " +
  106. "be non-null");
  107. this.trustedCert = trustedCert;
  108. this.pubKey = null;
  109. this.caName = null;
  110. setNameConstraints(nameConstraints);
  111. }
  112. /**
  113. * Creates an instance of <code>TrustAnchor</code> where the
  114. * most-trusted CA is specified as a distinguished name and public key.
  115. * Name constraints are an optional parameter, and are intended to be used
  116. * as additional constraints when validating an X.509 certification path.
  117. * <p>
  118. * The name constraints are specified as a byte array. This byte array
  119. * contains the DER encoded form of the name constraints, as they
  120. * would appear in the NameConstraints structure defined in RFC 2459
  121. * and X.509. The ASN.1 notation for this structure is supplied in the
  122. * documentation for
  123. * {@link #TrustAnchor(X509Certificate, byte[])
  124. * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
  125. * <p>
  126. * Note that the name constraints byte array supplied here is cloned to
  127. * protect against subsequent modifications.
  128. *
  129. * @param caName the X.500 distinguished name of the most-trusted CA in
  130. * RFC 2253 <code>String</code> format
  131. * @param pubKey the public key of the most-trusted CA
  132. * @param nameConstraints a byte array containing the ASN.1 DER encoding of
  133. * a NameConstraints extension to be used for checking name constraints.
  134. * Only the value of the extension is included, not the OID or criticality
  135. * flag. Specify <code>null</code> to omit the parameter.
  136. * @throws IllegalArgumentException if the specified <code>
  137. * caName</code> parameter is empty <code>(caName.length() == 0)</code>
  138. * or incorrectly formatted or the name constraints cannot be decoded
  139. * @throws NullPointerException if the specified <code>caName</code> or
  140. * <code>pubKey</code> parameter is <code>null</code>
  141. */
  142. public TrustAnchor(String caName, PublicKey pubKey, byte[] nameConstraints)
  143. {
  144. if (pubKey == null)
  145. throw new NullPointerException("the pubKey parameter must be " +
  146. "non-null");
  147. if (caName == null)
  148. throw new NullPointerException("the caName parameter must be " +
  149. "non-null");
  150. if (caName.length() == 0)
  151. throw new IllegalArgumentException("the caName " +
  152. "parameter must be a non-empty String");
  153. // check if caName is formatted correctly
  154. try {
  155. caPrincipal = new X500Name(caName, "RFC2253").asX500Principal();
  156. } catch (IOException ioe) {
  157. IllegalArgumentException iae =
  158. new IllegalArgumentException(ioe.getMessage());
  159. iae.initCause(ioe);
  160. throw iae;
  161. }
  162. this.pubKey = pubKey;
  163. this.caName = caName;
  164. this.trustedCert = null;
  165. setNameConstraints(nameConstraints);
  166. }
  167. /**
  168. * Returns the most-trusted CA certificate.
  169. *
  170. * @return a trusted <code>X509Certificate</code> or <code>null</code>
  171. * if the trust anchor was not specified as a trusted certificate
  172. */
  173. public final X509Certificate getTrustedCert() {
  174. return this.trustedCert;
  175. }
  176. /**
  177. * Returns the name of the most-trusted CA in RFC 2253 <code>String</code>
  178. * format.
  179. *
  180. * @return the X.500 distinguished name of the most-trusted CA, or
  181. * <code>null</code> if the trust anchor was not specified as a trusted
  182. * public key and name pair
  183. */
  184. public final String getCAName() {
  185. return this.caName;
  186. }
  187. final X500Principal getCA() {
  188. return this.caPrincipal;
  189. }
  190. /**
  191. * Returns the public key of the most-trusted CA.
  192. *
  193. * @return the public key of the most-trusted CA, or <code>null</code>
  194. * if the trust anchor was not specified as a trusted public key and name
  195. * pair
  196. */
  197. public final PublicKey getCAPublicKey() {
  198. return this.pubKey;
  199. }
  200. /**
  201. * Decode the name constraints and clone them if not null.
  202. */
  203. private void setNameConstraints(byte[] bytes) {
  204. if (bytes == null) {
  205. ncBytes = null;
  206. nc = null;
  207. } else {
  208. ncBytes = (byte []) bytes.clone();
  209. // validate DER encoding
  210. try {
  211. nc = new NameConstraintsExtension(Boolean.FALSE, bytes);
  212. } catch (IOException ioe) {
  213. IllegalArgumentException iae =
  214. new IllegalArgumentException(ioe.getMessage());
  215. iae.initCause(ioe);
  216. throw iae;
  217. }
  218. }
  219. }
  220. /**
  221. * Returns the name constraints parameter. The specified name constraints
  222. * are associated with this trust anchor and are intended to be used
  223. * as additional constraints when validating an X.509 certification path.
  224. * <p>
  225. * The name constraints are returned as a byte array. This byte array
  226. * contains the DER encoded form of the name constraints, as they
  227. * would appear in the NameConstraints structure defined in RFC 2459
  228. * and X.509. The ASN.1 notation for this structure is supplied in the
  229. * documentation for
  230. * {@link TrustAnchor#(X509Certificate, byte[])
  231. * TrustAnchor(X509Certificate trustedCert, byte[] nameConstraints) }.
  232. * <p>
  233. * Note that the byte array returned is cloned to protect against
  234. * subsequent modifications.
  235. *
  236. * @return a byte array containing the ASN.1 DER encoding of
  237. * a NameConstraints extension used for checking name constraints,
  238. * or <code>null</code> if not set.
  239. */
  240. public final byte [] getNameConstraints() {
  241. return (ncBytes == null ? null : (byte []) ncBytes.clone());
  242. }
  243. /**
  244. * Returns a formatted string describing the <code>TrustAnchor</code>.
  245. *
  246. * @return a formatted string describing the <code>TrustAnchor</code>
  247. */
  248. public String toString() {
  249. StringBuffer sb = new StringBuffer();
  250. sb.append("[\n");
  251. if (pubKey != null) {
  252. sb.append(" Trusted CA Public Key: " + pubKey.toString() + "\n");
  253. sb.append(" Trusted CA Issuer Name: "
  254. + String.valueOf(caName) + "\n");
  255. } else {
  256. sb.append(" Trusted CA cert: " + trustedCert.toString() + "\n");
  257. }
  258. if (nc != null)
  259. sb.append(" Name Constraints: " + nc.toString() + "\n");
  260. return sb.toString();
  261. }
  262. }