package org.bouncycastle.jce.cert; import java.security.InvalidAlgorithmParameterException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.cert.Certificate; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; /** * Parameters used as input for the PKIX CertPathValidator algorithm.<br /> * <br /> * A PKIX <code>CertPathValidator</code> uses these parameters to validate a * <code>CertPath</code> according to the PKIX certification path validation * algorithm.<br /> * <br /> * To instantiate a <code>PKIXParameters</code> object, an application must * specify one or more <i>most-trusted CAs</i> as defined by the PKIX * certification path validation algorithm. The most-trusted CAs can be * specified using one of two constructors. An application can call * {@link #PKIXParameters(Set)}, specifying a Set of <code>TrustAnchor</code> * objects, each of which identify a most-trusted CA. Alternatively, an * application can call {@link #PKIXParameters(KeyStore)}, specifying a * <code>KeyStore</code> instance containing trusted certificate entries, each * of which will be considered as a most-trusted CA.<br /> * <br /> * Once a <code>PKIXParameters</code> object has been created, other * parameters can be specified (by calling {@link #setInitialPolicies} or * {@link #setDate}, for instance) and then the <code>PKIXParameters</code> * is passed along with the <code>CertPath</code> to be validated to * {@link CertPathValidator#validate}.<br /> * <br /> * Any parameter that is not set (or is set to null) will be set to the default * value for that parameter. The default value for the date parameter is null, * which indicates the current time when the path is validated. The default for * the remaining parameters is the least constrained.<br /> * <br /> * <b>Concurrent Access</b><br /> * <br /> * Unless otherwise specified, the methods defined in this class are not * thread-safe. Multiple threads that need to access a single object * concurrently should synchronize amongst themselves and provide the necessary * locking. Multiple threads each manipulating separate objects need not * synchronize. * * @see CertPathValidator */ public class PKIXParameters implements CertPathParameters { private Set trustAnchors; private Set initialPolicies = new HashSet(); private List certStores = new ArrayList(); private CertSelector certSelector; private List certPathCheckers = new ArrayList(); private boolean revocationEnabled = true; private boolean explicitPolicyRequired = false; private boolean policyMappingInhibited = false; private boolean anyPolicyInhibited = false; private boolean policyQualifiersRejected = true; private Date date; private String sigProvider; /** * Creates an instance of PKIXParameters with the specified Set of * most-trusted CAs. Each element of the set is a TrustAnchor.<br /> * <br /> * Note that the Set is copied to protect against subsequent modifications. * * @param trustAnchors * a Set of TrustAnchors * * @exception InvalidAlgorithmParameterException * if the specified Set is empty * <code>(trustAnchors.isEmpty() == true)</code> * @exception NullPointerException * if the specified Set is <code>null</code> * @exception ClassCastException * if any of the elements in the Set are not of type * <code>java.security.cert.TrustAnchor</code> */ public PKIXParameters(Set trustAnchors) throws InvalidAlgorithmParameterException { setTrustAnchors(trustAnchors); } /** * Creates an instance of PKIXParameters that populates the set of * most-trusted CAs from the trusted certificate entries contained in the * specified KeyStore. Only keystore entries that contain trusted * X509Certificates are considered; all other certificate types are ignored. * * @param keystore * a KeyStore from which the set of most-trusted CAs will be * populated * * @exception KeyStoreException * if the keystore has not been initialized * @exception InvalidAlgorithmParameterException * if the keystore does not contain at least one trusted * certificate entry * @exception NullPointerException * if the keystore is null */ public PKIXParameters(KeyStore keystore) throws KeyStoreException, InvalidAlgorithmParameterException { if (keystore == null) { throw new NullPointerException( "the keystore parameter must be non-null"); } Set trustAnchors = new HashSet(); String alias; Certificate cert; Enumeration enum = keystore.aliases(); while (enum.hasMoreElements()) { alias = (String)enum.nextElement(); if (keystore.isCertificateEntry(alias)) { cert = keystore.getCertificate(alias); if (cert instanceof X509Certificate) { trustAnchors.add(new TrustAnchor((X509Certificate)cert, null)); } } } setTrustAnchors(trustAnchors); } /** * Returns an immutable Set of the most-trusted CAs. * * @return an immutable <code>Set</code> of <code>TrustAnchors</code> * (never <code>null</code>) * * @see #setTrustAnchors */ public Set getTrustAnchors() { return Collections.unmodifiableSet(trustAnchors); } /** * Sets the Set of most-trusted CAs.<br /> * <br /> * Note that the Set is copied to protect against subsequent modifications.<br /> * <br /> * * @param trustAnchors * a Set of TrustAnchors * * @exception InvalidAlgorithmParameterException * if the specified Set is empty * <code>(trustAnchors.isEmpty() == true)</code> * @exception NullPointerException * if the specified Set is <code>null</code> * @exception ClassCastException * if any of the elements in the set are not of type * java.security.cert.TrustAnchor * * @see #getTrustAnchors */ public void setTrustAnchors(Set trustAnchors) throws InvalidAlgorithmParameterException { if (trustAnchors == null) { throw new NullPointerException( "the trustAnchors parameter must be non-null"); } if (trustAnchors.isEmpty()) { throw new InvalidAlgorithmParameterException( "the trustAnchors parameter must be non-empty"); } Iterator iter = trustAnchors.iterator(); TrustAnchor obj; this.trustAnchors = new HashSet(); while (iter.hasNext()) { obj = (TrustAnchor)iter.next(); if (obj != null) { this.trustAnchors.add(obj); } } } /** * Returns an immutable Set of initial policy identifiers (OID strings), * indicating that any one of these policies would be acceptable to the * certificate user for the purposes of certification path processing. The * default return value is an empty <code>Set</code>, which is * interpreted as meaning that any policy would be acceptable. * * @return an immutable <code>Set</code> of initial policy OIDs in String * format, or an empty <code>Set</code> (implying any policy is * acceptable). Never returns <code>null</code>. * * @see #setInitialPolicies(java.util.Set) */ public Set getInitialPolicies() { Set returnSet = initialPolicies; if (initialPolicies == null) { returnSet = new HashSet(); } return Collections.unmodifiableSet(returnSet); } /** * Sets the <code>Set</code> of initial policy identifiers (OID strings), * indicating that any one of these policies would be acceptable to the * certificate user for the purposes of certification path processing. By * default, any policy is acceptable (i.e. all policies), so a user that * wants to allow any policy as acceptable does not need to call this * method, or can call it with an empty <code>Set</code> (or * <code>null</code>).<br /> * <br /> * Note that the Set is copied to protect against subsequent modifications.<br /> * <br /> * * @param initialPolicies * a Set of initial policy OIDs in String format (or * <code>null</code>) * * @exception ClassCastException * if any of the elements in the set are not of type String * * @see #getInitialPolicies() */ public void setInitialPolicies(Set initialPolicies) { if (initialPolicies == null || initialPolicies.isEmpty()) { this.initialPolicies = null; } else { Iterator iter = initialPolicies.iterator(); this.initialPolicies = new HashSet(); String obj; while (iter.hasNext()) { obj = (String)iter.next(); if (obj != null) { this.initialPolicies.add(obj); } } } } /** * Sets the list of CertStores to be used in finding certificates and CRLs. * May be null, in which case no CertStores will be used. The first * CertStores in the list may be preferred to those that appear later.<br /> * <br /> * Note that the List is copied to protect against subsequent modifications.<br /> * <br /> * * @param stores * a List of CertStores (or <code>null</code>) * * @exception ClassCastException * if any of the elements in the list are not of type * <code>java.security.cert.CertStore</code> * * @see #getCertStores() */ public void setCertStores(List stores) { certStores = new ArrayList(); if (stores != null && !stores.isEmpty()) { Iterator iter = stores.iterator(); CertStore obj; while (iter.hasNext()) { obj = (CertStore)iter.next(); if (obj != null) { certStores.add(obj); } } } } /** * Adds a CertStore to the end of the list of CertStores used in finding * certificates and CRLs. * * @param store * the <code>CertStore</code> to add. If * <code>null</code<, the store is ignored (not added to * list). */ public void addCertStore(CertStore store) { if (store != null) { certStores.add(store); } } /** * Returns an immutable List of CertStores that are used to find * certificates and CRLs. * * @return an immutable List of CertStores (may be empty, but never * <code>null</code>) * * @see #setCertStores(java.util.List) */ public List getCertStores() { return Collections.unmodifiableList(certStores); } /** * Sets the RevocationEnabled flag. If this flag is true, the default * revocation checking mechanism of the underlying PKIX service provider * will be used. If this flag is false, the default revocation checking * mechanism will be disabled (not used).<br /> * <br /> * When a <code>PKIXParameters</code> object is created, this flag is set * to true. This setting reflects the most common strategy for checking * revocation, since each service provider must support revocation checking * to be PKIX compliant. Sophisticated applications should set this flag to * false when it is not practical to use a PKIX service provider's default * revocation checking mechanism or when an alternative revocation checking * mechanism is to be substituted (by also calling the * {@link #addCertPathChecker addCertPathChecker} or {@link * #setCertPathCheckers setCertPathCheckers} methods). * * @param val * the new value of the RevocationEnabled flag */ public void setRevocationEnabled(boolean val) { revocationEnabled = val; } /** * Checks the RevocationEnabled flag. If this flag is true, the default * revocation checking mechanism of the underlying PKIX service provider * will be used. If this flag is false, the default revocation checking * mechanism will be disabled (not used). See the setRevocationEnabled * method for more details on setting the value of this flag. * * @return the current value of the RevocationEnabled flag */ public boolean isRevocationEnabled() { return revocationEnabled; } /** * Sets the ExplicitPolicyRequired flag. If this flag is true, an acceptable * policy needs to be explicitly identified in every certificate. By * default, the ExplicitPolicyRequired flag is false. * * @param val * true if explicit policy is to be required, false otherwise */ public void setExplicitPolicyRequired(boolean val) { explicitPolicyRequired = val; } /** * Checks if explicit policy is required. If this flag is true, an * acceptable policy needs to be explicitly identified in every certificate. * By default, the ExplicitPolicyRequired flag is false. * * @return true if explicit policy is required, false otherwise */ public boolean isExplicitPolicyRequired() { return explicitPolicyRequired; } /** * Sets the PolicyMappingInhibited flag. If this flag is true, policy * mapping is inhibited. By default, policy mapping is not inhibited (the * flag is false). * * @param val * true if policy mapping is to be inhibited, false otherwise */ public void setPolicyMappingInhibited(boolean val) { policyMappingInhibited = val; } /** * Checks if policy mapping is inhibited. If this flag is true, policy * mapping is inhibited. By default, policy mapping is not inhibited (the * flag is false). * * @return true if policy mapping is inhibited, false otherwise */ public boolean isPolicyMappingInhibited() { return policyMappingInhibited; } /** * Sets state to determine if the any policy OID should be processed if it * is included in a certificate. By default, the any policy OID is not * inhibited ({@link #isAnyPolicyInhibited()} returns false). * * @return val - <code>true</code> if the any policy OID is to be * inhibited, <code>false</code> otherwise */ public void setAnyPolicyInhibited(boolean val) { anyPolicyInhibited = val; } /** * Checks whether the any policy OID should be processed if it is included * in a certificate. * * @return <code>true</code> if the any policy OID is inhibited, * <code>false</code> otherwise */ public boolean isAnyPolicyInhibited() { return anyPolicyInhibited; } /** * Sets the PolicyQualifiersRejected flag. If this flag is true, * certificates that include policy qualifiers in a certificate policies * extension that is marked critical are rejected. If the flag is false, * certificates are not rejected on this basis.<br /> * <br /> * When a <code>PKIXParameters</code> object is created, this flag is set * to true. This setting reflects the most common (and simplest) strategy * for processing policy qualifiers. Applications that want to use a more * sophisticated policy must set this flag to false.<br /> * <br /> * Note that the PKIX certification path validation algorithm specifies that * any policy qualifier in a certificate policies extension that is marked * critical must be processed and validated. Otherwise the certification * path must be rejected. If the policyQualifiersRejected flag is set to * false, it is up to the application to validate all policy qualifiers in * this manner in order to be PKIX compliant. * * @param qualifiersRejected * the new value of the PolicyQualifiersRejected flag * * @see #getPolicyQualifiersRejected() * @see PolicyQualifierInfo */ public void setPolicyQualifiersRejected(boolean qualifiersRejected) { policyQualifiersRejected = qualifiersRejected; } /** * Gets the PolicyQualifiersRejected flag. If this flag is true, * certificates that include policy qualifiers in a certificate policies * extension that is marked critical are rejected. If the flag is false, * certificates are not rejected on this basis.<br /> * <br /> * When a PKIXParameters object is created, this flag is set to true. This * setting reflects the most common (and simplest) strategy for processing * policy qualifiers. Applications that want to use a more sophisticated * policy must set this flag to false. * * @return the current value of the PolicyQualifiersRejected flag * * @see #setPolicyQualifiersRejected(boolean) */ public boolean getPolicyQualifiersRejected() { return policyQualifiersRejected; } /** * Returns the time for which the validity of the certification path should * be determined. If null, the current time is used.<br /> * <br /> * Note that the Date returned is copied to protect against subsequent * modifications. * * @return the Date, or <code>null</code> if not set * * @see #setDate(java.util.Date) */ public Date getDate() { if (date == null) { return null; } return new Date(date.getTime()); } /** * Sets the time for which the validity of the certification path should be * determined. If null, the current time is used.<br /> * <br /> * Note that the Date supplied here is copied to protect against subsequent * modifications. * * @param date * the Date, or <code>null</code> for the current time * * @see #getDate() */ public void setDate(Date date) { if (date == null) { this.date = null; } else { this.date = new Date(date.getTime()); } } /** * Sets a <code>List</code> of additional certification path checkers. If * the specified List contains an object that is not a PKIXCertPathChecker, * it is ignored.<br /> * <br /> * Each <code>PKIXCertPathChecker</code> specified implements additional * checks on a certificate. Typically, these are checks to process and * verify private extensions contained in certificates. Each * <code>PKIXCertPathChecker</code> should be instantiated with any * initialization parameters needed to execute the check.<br /> * <br /> * This method allows sophisticated applications to extend a PKIX * <code>CertPathValidator</code> or <code>CertPathBuilder</code>. Each * of the specified PKIXCertPathCheckers will be called, in turn, by a PKIX * <code>CertPathValidator</code> or <code>CertPathBuilder</code> for * each certificate processed or validated.<br /> * <br /> * Regardless of whether these additional PKIXCertPathCheckers are set, a * PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code> * must perform all of the required PKIX checks on each certificate. The one * exception to this rule is if the RevocationEnabled flag is set to false * (see the {@link #setRevocationEnabled(boolean) setRevocationEnabled} * method).<br /> * <br /> * Note that the List supplied here is copied and each PKIXCertPathChecker * in the list is cloned to protect against subsequent modifications. * * @param checkers * a List of PKIXCertPathCheckers. May be null, in which case no * additional checkers will be used. * @exception ClassCastException * if any of the elements in the list are not of type * <code>java.security.cert.PKIXCertPathChecker</code> * @see #getCertPathCheckers() */ public void setCertPathCheckers(List checkers) { certPathCheckers = new ArrayList(); if (checkers == null) { return; } Iterator iter = checkers.iterator(); while (iter.hasNext()) { certPathCheckers .add((PKIXCertPathChecker)((PKIXCertPathChecker)iter.next()) .clone()); } } /** * Returns the List of certification path checkers. The returned List is * immutable, and each PKIXCertPathChecker in the List is cloned to protect * against subsequent modifications. * * @return an immutable List of PKIXCertPathCheckers (may be empty, but not * <code>null</code>) * * @see #setCertPathCheckers(java.util.List) */ public List getCertPathCheckers() { List checkers = new ArrayList(); Iterator iter = certPathCheckers.iterator(); while (iter.hasNext()) { checkers .add((PKIXCertPathChecker)((PKIXCertPathChecker)iter.next()) .clone()); } return Collections.unmodifiableList(checkers); } /** * Adds a PKIXCertPathChecker to the list of certification path checkers. * See the {@link #setCertPathCheckers} method for more details.<br /> * <br /> * Note that the <code>PKIXCertPathChecker</code> is cloned to protect * against subsequent modifications. * * @param checker * a <code>PKIXCertPathChecker</code> to add to the list of * checks. If <code>null</code>, the checker is ignored (not * added to list). */ public void addCertPathChecker(PKIXCertPathChecker checker) { if (checker != null) { certPathCheckers.add(checker.clone()); } } /** * Returns the signature provider's name, or <code>null</code> if not set. * * @return the signature provider's name (or <code>null</code>) * * @see #setSigProvider(java.lang.String) */ public String getSigProvider() { return sigProvider; } /** * Sets the signature provider's name. The specified provider will be * preferred when creating Signature objects. If null or not set, the first * provider found supporting the algorithm will be used. * * @param sigProvider * the signature provider's name (or <code>null</code>) * * @see #getSigProvider() */ public void setSigProvider(String sigProvider) { this.sigProvider = sigProvider; } /** * Returns the required constraints on the target certificate. The * constraints are returned as an instance of CertSelector. If * <code>null</code>, no constraints are defined.<br /> * <br /> * Note that the CertSelector returned is cloned to protect against * subsequent modifications. * * @return a CertSelector specifying the constraints on the target * certificate (or <code>null</code>) * * @see #setTargetCertConstraints(CertSelector) */ public CertSelector getTargetCertConstraints() { if (certSelector == null) { return null; } return (CertSelector)certSelector.clone(); } /** * Sets the required constraints on the target certificate. The constraints * are specified as an instance of CertSelector. If null, no constraints are * defined.<br /> * <br /> * Note that the CertSelector specified is cloned to protect against * subsequent modifications. * * @param selector * a CertSelector specifying the constraints on the target * certificate (or <code>null</code>) * * @see #getTargetCertConstraints() */ public void setTargetCertConstraints(CertSelector selector) { if (selector == null) { certSelector = null; } else { certSelector = (CertSelector)selector.clone(); } } /** * Makes a copy of this PKIXParameters object. Changes to the copy will not * affect the original and vice versa. * * @return a copy of this <code>PKIXParameters</code> object */ public Object clone() { try { PKIXParameters obj = (PKIXParameters)super.clone(); obj.certStores = new ArrayList(certStores); Iterator iter = certPathCheckers.iterator(); obj.certPathCheckers = new ArrayList(); while (iter.hasNext()) { obj.certPathCheckers.add(((PKIXCertPathChecker)iter.next()) .clone()); } if (initialPolicies != null) { obj.initialPolicies = new HashSet(initialPolicies); } if (trustAnchors != null) { obj.trustAnchors = new HashSet(trustAnchors); } if (certSelector != null) { obj.certSelector = (CertSelector)certSelector.clone(); } return obj; } catch (CloneNotSupportedException ex) { throw new InternalError(); } } /** * Returns a formatted string describing the parameters. * * @return a formatted string describing the parameters. */ public String toString() { StringBuffer s = new StringBuffer(); s.append("[\n"); if (trustAnchors != null) { s.append(" Trust Anchors: ").append(trustAnchors).append('\n'); } if (initialPolicies != null) { if (initialPolicies.isEmpty()) { s.append(" Initial Policy OIDs: any\n"); } else { s.append(" Initial Policy OIDs: [") .append(initialPolicies).append("]\n"); } } s.append(" Validity Date: "); if (date != null) { s.append(date); } else { s.append("null"); } s.append('\n'); s.append(" Signature Provider: "); if (sigProvider != null) { s.append(sigProvider); } else { s.append("null"); } s.append('\n'); s.append(" Default Revocation Enabled: "); s.append(revocationEnabled); s.append('\n'); s.append(" Explicit Policy Required: "); s.append(explicitPolicyRequired); s.append('\n'); s.append(" Policy Mapping Inhibited: "); s.append(policyMappingInhibited); s.append('\n'); s.append(" Any Policy Inhibited: "); s.append(anyPolicyInhibited); s.append('\n'); s.append(" Policy Qualifiers Rejected: "); s.append(policyQualifiersRejected); s.append('\n'); s.append(" Target Cert Constraints: "); s.append(certSelector); s.append('\n'); s.append(" Certification Path Checkers: ["); s.append(certPathCheckers); s.append("}\n"); s.append(" CertStores: ["); s.append(certStores); s.append("}\n"); s.append("]\n"); return s.toString(); } }