blob: 638661826fc89c08b6a5fcdf90ee62eaa9c32621 [file] [log] [blame]
package org.bouncycastle.x509;
import org.bouncycastle.util.Selector;
import org.bouncycastle.util.Store;
import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CertSelector;
import java.security.cert.CertStore;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509CertSelector;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* This class extends the PKIXParameters with a validity model parameter.
*/
public class ExtendedPKIXParameters
extends PKIXParameters
{
private List stores;
private Selector selector;
private boolean additionalLocationsEnabled;
private List additionalStores;
private Set trustedACIssuers;
private Set necessaryACAttributes;
private Set prohibitedACAttributes;
private Set attrCertCheckers;
/**
* Creates an instance of <code>PKIXParameters</code> with the specified
* <code>Set</code> of most-trusted CAs. Each element of the set is a
* {@link TrustAnchor TrustAnchor}. <p/> Note that the <code>Set</code>
* is copied to protect against subsequent modifications.
*
* @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
* @throws InvalidAlgorithmParameterException if the specified
* <code>Set</code> is empty.
* @throws NullPointerException if the specified <code>Set</code> is
* <code>null</code>
* @throws ClassCastException if any of the elements in the <code>Set</code>
* is not of type <code>java.security.cert.TrustAnchor</code>
*/
public ExtendedPKIXParameters(Set trustAnchors)
throws InvalidAlgorithmParameterException
{
super(trustAnchors);
stores = new ArrayList();
additionalStores = new ArrayList();
trustedACIssuers = new HashSet();
necessaryACAttributes = new HashSet();
prohibitedACAttributes = new HashSet();
attrCertCheckers = new HashSet();
}
/**
* Returns an instance with the parameters of a given
* <code>PKIXParameters</code> object.
*
* @param pkixParams The given <code>PKIXParameters</code>
* @return an extended PKIX params object
*/
public static ExtendedPKIXParameters getInstance(PKIXParameters pkixParams)
{
ExtendedPKIXParameters params;
try
{
params = new ExtendedPKIXParameters(pkixParams.getTrustAnchors());
}
catch (Exception e)
{
// cannot happen
throw new RuntimeException(e.getMessage());
}
params.setParams(pkixParams);
return params;
}
/**
* Method to support <code>clone()</code> under J2ME.
* <code>super.clone()</code> does not exist and fields are not copied.
*
* @param params Parameters to set. If this are
* <code>ExtendedPKIXParameters</code> they are copied to.
*/
protected void setParams(PKIXParameters params)
{
setDate(params.getDate());
setCertPathCheckers(params.getCertPathCheckers());
setCertStores(params.getCertStores());
setAnyPolicyInhibited(params.isAnyPolicyInhibited());
setExplicitPolicyRequired(params.isExplicitPolicyRequired());
setPolicyMappingInhibited(params.isPolicyMappingInhibited());
setRevocationEnabled(params.isRevocationEnabled());
setInitialPolicies(params.getInitialPolicies());
setPolicyQualifiersRejected(params.getPolicyQualifiersRejected());
setSigProvider(params.getSigProvider());
setTargetCertConstraints(params.getTargetCertConstraints());
try
{
setTrustAnchors(params.getTrustAnchors());
}
catch (Exception e)
{
// cannot happen
throw new RuntimeException(e.getMessage());
}
if (params instanceof ExtendedPKIXParameters)
{
ExtendedPKIXParameters _params = (ExtendedPKIXParameters) params;
validityModel = _params.validityModel;
useDeltas = _params.useDeltas;
additionalLocationsEnabled = _params.additionalLocationsEnabled;
selector = _params.selector == null ? null
: (Selector) _params.selector.clone();
stores = new ArrayList(_params.stores);
additionalStores = new ArrayList(_params.additionalStores);
trustedACIssuers = new HashSet(_params.trustedACIssuers);
prohibitedACAttributes = new HashSet(_params.prohibitedACAttributes);
necessaryACAttributes = new HashSet(_params.necessaryACAttributes);
attrCertCheckers = new HashSet(_params.attrCertCheckers);
}
}
/**
* This is the default PKIX validity model. Actually there are two variants
* of this: The PKIX model and the modified PKIX model. The PKIX model
* verifies that all involved certificates must have been valid at the
* current time. The modified PKIX model verifies that all involved
* certificates were valid at the signing time. Both are indirectly choosen
* with the {@link PKIXParameters#setDate(java.util.Date)} method, so this
* methods sets the Date when <em>all</em> certificates must have been
* valid.
*/
public static final int PKIX_VALIDITY_MODEL = 0;
/**
* This model uses the following validity model. Each certificate must have
* been valid at the moment where is was used. That means the end
* certificate must have been valid at the time the signature was done. The
* CA certificate which signed the end certificate must have been valid,
* when the end certificate was signed. The CA (or Root CA) certificate must
* have been valid, when the CA certificate was signed and so on. So the
* {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when
* the <em>end certificate</em> must have been valid. <p/> It is used e.g.
* in the German signature law.
*/
public static final int CHAIN_VALIDITY_MODEL = 1;
private int validityModel = PKIX_VALIDITY_MODEL;
private boolean useDeltas = false;
/**
* Defaults to <code>false</code>.
*
* @return Returns if delta CRLs should be used.
*/
public boolean isUseDeltasEnabled()
{
return useDeltas;
}
/**
* Sets if delta CRLs should be used for checking the revocation status.
*
* @param useDeltas <code>true</code> if delta CRLs should be used.
*/
public void setUseDeltasEnabled(boolean useDeltas)
{
this.useDeltas = useDeltas;
}
/**
* @return Returns the validity model.
* @see #CHAIN_VALIDITY_MODEL
* @see #PKIX_VALIDITY_MODEL
*/
public int getValidityModel()
{
return validityModel;
}
/**
* Sets the Java CertStore to this extended PKIX parameters.
*
* @throws ClassCastException if an element of <code>stores</code> is not
* a <code>CertStore</code>.
*/
public void setCertStores(List stores)
{
if (stores != null)
{
Iterator it = stores.iterator();
while (it.hasNext())
{
addCertStore((CertStore)it.next());
}
}
}
/**
* Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute
* certificates or cross certificates.
* <p>
* The <code>List</code> is cloned.
*
* @param stores A list of stores to use.
* @see #getStores
* @throws ClassCastException if an element of <code>stores</code> is not
* a {@link Store}.
*/
public void setStores(List stores)
{
if (stores == null)
{
this.stores = new ArrayList();
}
else
{
for (Iterator i = stores.iterator(); i.hasNext();)
{
if (!(i.next() instanceof Store))
{
throw new ClassCastException(
"All elements of list must be "
+ "of type org.bouncycastle.util.Store.");
}
}
this.stores = new ArrayList(stores);
}
}
/**
* Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute
* certificates or cross certificates.
* <p>
* This method should be used to add local stores, like collection based
* X.509 stores, if available. Local stores should be considered first,
* before trying to use additional (remote) locations, because they do not
* need possible additional network traffic.
* <p>
* If <code>store</code> is <code>null</code> it is ignored.
*
* @param store The store to add.
* @see #getStores
*/
public void addStore(Store store)
{
if (store != null)
{
stores.add(store);
}
}
/**
* Adds an additional Bouncy Castle {@link Store} to find CRLs, certificates,
* attribute certificates or cross certificates.
* <p>
* You should not use this method. This method is used for adding additional
* X.509 stores, which are used to add (remote) locations, e.g. LDAP, found
* during X.509 object processing, e.g. in certificates or CRLs. This method
* is used in PKIX certification path processing.
* <p>
* If <code>store</code> is <code>null</code> it is ignored.
*
* @param store The store to add.
* @see #getStores()
*/
public void addAdditionalStore(Store store)
{
if (store != null)
{
additionalStores.add(store);
}
}
/**
* @deprecated
*/
public void addAddionalStore(Store store)
{
addAdditionalStore(store);
}
/**
* Returns an immutable <code>List</code> of additional Bouncy Castle
* <code>Store</code>s used for finding CRLs, certificates, attribute
* certificates or cross certificates.
*
* @return an immutable <code>List</code> of additional Bouncy Castle
* <code>Store</code>s. Never <code>null</code>.
*
* @see #addAdditionalStore(Store)
*/
public List getAdditionalStores()
{
return Collections.unmodifiableList(additionalStores);
}
/**
* Returns an immutable <code>List</code> of Bouncy Castle
* <code>Store</code>s used for finding CRLs, certificates, attribute
* certificates or cross certificates.
*
* @return an immutable <code>List</code> of Bouncy Castle
* <code>Store</code>s. Never <code>null</code>.
*
* @see #setStores(List)
*/
public List getStores()
{
return Collections.unmodifiableList(new ArrayList(stores));
}
/**
* @param validityModel The validity model to set.
* @see #CHAIN_VALIDITY_MODEL
* @see #PKIX_VALIDITY_MODEL
*/
public void setValidityModel(int validityModel)
{
this.validityModel = validityModel;
}
public Object clone()
{
ExtendedPKIXParameters params;
try
{
params = new ExtendedPKIXParameters(getTrustAnchors());
}
catch (Exception e)
{
// cannot happen
throw new RuntimeException(e.getMessage());
}
params.setParams(this);
return params;
}
/**
* Returns if additional {@link X509Store}s for locations like LDAP found
* in certificates or CRLs should be used.
*
* @return Returns <code>true</code> if additional stores are used.
*/
public boolean isAdditionalLocationsEnabled()
{
return additionalLocationsEnabled;
}
/**
* Sets if additional {@link X509Store}s for locations like LDAP found in
* certificates or CRLs should be used.
*
* @param enabled <code>true</code> if additional stores are used.
*/
public void setAdditionalLocationsEnabled(boolean enabled)
{
additionalLocationsEnabled = enabled;
}
/**
* Returns the required constraints on the target certificate or attribute
* certificate. The constraints are returned as an instance of
* <code>Selector</code>. If <code>null</code>, no constraints are
* defined.
*
* <p>
* The target certificate in a PKIX path may be a certificate or an
* attribute certificate.
* <p>
* Note that the <code>Selector</code> returned is cloned to protect
* against subsequent modifications.
*
* @return a <code>Selector</code> specifying the constraints on the
* target certificate or attribute certificate (or <code>null</code>)
* @see #setTargetConstraints
* @see X509CertStoreSelector
* @see X509AttributeCertStoreSelector
*/
public Selector getTargetConstraints()
{
if (selector != null)
{
return (Selector) selector.clone();
}
else
{
return null;
}
}
/**
* Sets the required constraints on the target certificate or attribute
* certificate. The constraints are specified as an instance of
* <code>Selector</code>. If <code>null</code>, no constraints are
* defined.
* <p>
* The target certificate in a PKIX path may be a certificate or an
* attribute certificate.
* <p>
* Note that the <code>Selector</code> specified is cloned to protect
* against subsequent modifications.
*
* @param selector a <code>Selector</code> specifying the constraints on
* the target certificate or attribute certificate (or
* <code>null</code>)
* @see #getTargetConstraints
* @see X509CertStoreSelector
* @see X509AttributeCertStoreSelector
*/
public void setTargetConstraints(Selector selector)
{
if (selector != null)
{
this.selector = (Selector) selector.clone();
}
else
{
this.selector = null;
}
}
/**
* Sets the required constraints on the target certificate. The constraints
* are specified as an instance of <code>X509CertSelector</code>. If
* <code>null</code>, no constraints are defined.
*
* <p>
* This method wraps the given <code>X509CertSelector</code> into a
* <code>X509CertStoreSelector</code>.
* <p>
* Note that the <code>X509CertSelector</code> specified is cloned to
* protect against subsequent modifications.
*
* @param selector a <code>X509CertSelector</code> specifying the
* constraints on the target certificate (or <code>null</code>)
* @see #getTargetCertConstraints
* @see X509CertStoreSelector
*/
public void setTargetCertConstraints(CertSelector selector)
{
super.setTargetCertConstraints(selector);
if (selector != null)
{
this.selector = X509CertStoreSelector
.getInstance((X509CertSelector) selector);
}
else
{
this.selector = null;
}
}
/**
* Returns the trusted attribute certificate issuers. If attribute
* certificates is verified the trusted AC issuers must be set.
* <p>
* The returned <code>Set</code> consists of <code>TrustAnchor</code>s.
* <p>
* The returned <code>Set</code> is immutable. Never <code>null</code>
*
* @return Returns an immutable set of the trusted AC issuers.
*/
public Set getTrustedACIssuers()
{
return Collections.unmodifiableSet(trustedACIssuers);
}
/**
* Sets the trusted attribute certificate issuers. If attribute certificates
* is verified the trusted AC issuers must be set.
* <p>
* The <code>trustedACIssuers</code> must be a <code>Set</code> of
* <code>TrustAnchor</code>
* <p>
* The given set is cloned.
*
* @param trustedACIssuers The trusted AC issuers to set. Is never
* <code>null</code>.
* @throws ClassCastException if an element of <code>stores</code> is not
* a <code>TrustAnchor</code>.
*/
public void setTrustedACIssuers(Set trustedACIssuers)
{
if (trustedACIssuers == null)
{
this.trustedACIssuers.clear();
return;
}
for (Iterator it = trustedACIssuers.iterator(); it.hasNext();)
{
if (!(it.next() instanceof TrustAnchor))
{
throw new ClassCastException("All elements of set must be "
+ "of type " + TrustAnchor.class.getName() + ".");
}
}
this.trustedACIssuers.clear();
this.trustedACIssuers.addAll(trustedACIssuers);
}
/**
* Returns the neccessary attributes which must be contained in an attribute
* certificate.
* <p>
* The returned <code>Set</code> is immutable and contains
* <code>String</code>s with the OIDs.
*
* @return Returns the necessary AC attributes.
*/
public Set getNecessaryACAttributes()
{
return Collections.unmodifiableSet(necessaryACAttributes);
}
/**
* Sets the neccessary which must be contained in an attribute certificate.
* <p>
* The <code>Set</code> must contain <code>String</code>s with the
* OIDs.
* <p>
* The set is cloned.
*
* @param necessaryACAttributes The necessary AC attributes to set.
* @throws ClassCastException if an element of
* <code>necessaryACAttributes</code> is not a
* <code>String</code>.
*/
public void setNecessaryACAttributes(Set necessaryACAttributes)
{
if (necessaryACAttributes == null)
{
this.necessaryACAttributes.clear();
return;
}
for (Iterator it = necessaryACAttributes.iterator(); it.hasNext();)
{
if (!(it.next() instanceof String))
{
throw new ClassCastException("All elements of set must be "
+ "of type String.");
}
}
this.necessaryACAttributes.clear();
this.necessaryACAttributes.addAll(necessaryACAttributes);
}
/**
* Returns the attribute certificates which are not allowed.
* <p>
* The returned <code>Set</code> is immutable and contains
* <code>String</code>s with the OIDs.
*
* @return Returns the prohibited AC attributes. Is never <code>null</code>.
*/
public Set getProhibitedACAttributes()
{
return Collections.unmodifiableSet(prohibitedACAttributes);
}
/**
* Sets the attribute certificates which are not allowed.
* <p>
* The <code>Set</code> must contain <code>String</code>s with the
* OIDs.
* <p>
* The set is cloned.
*
* @param prohibitedACAttributes The prohibited AC attributes to set.
* @throws ClassCastException if an element of
* <code>prohibitedACAttributes</code> is not a
* <code>String</code>.
*/
public void setProhibitedACAttributes(Set prohibitedACAttributes)
{
if (prohibitedACAttributes == null)
{
this.prohibitedACAttributes.clear();
return;
}
for (Iterator it = prohibitedACAttributes.iterator(); it.hasNext();)
{
if (!(it.next() instanceof String))
{
throw new ClassCastException("All elements of set must be "
+ "of type String.");
}
}
this.prohibitedACAttributes.clear();
this.prohibitedACAttributes.addAll(prohibitedACAttributes);
}
/**
* Returns the attribute certificate checker. The returned set contains
* {@link PKIXAttrCertChecker}s and is immutable.
*
* @return Returns the attribute certificate checker. Is never
* <code>null</code>.
*/
public Set getAttrCertCheckers()
{
return Collections.unmodifiableSet(attrCertCheckers);
}
/**
* Sets the attribute certificate checkers.
* <p>
* All elements in the <code>Set</code> must a {@link PKIXAttrCertChecker}.
* <p>
* The given set is cloned.
*
* @param attrCertCheckers The attribute certificate checkers to set. Is
* never <code>null</code>.
* @throws ClassCastException if an element of <code>attrCertCheckers</code>
* is not a <code>PKIXAttrCertChecker</code>.
*/
public void setAttrCertCheckers(Set attrCertCheckers)
{
if (attrCertCheckers == null)
{
this.attrCertCheckers.clear();
return;
}
for (Iterator it = attrCertCheckers.iterator(); it.hasNext();)
{
if (!(it.next() instanceof PKIXAttrCertChecker))
{
throw new ClassCastException("All elements of set must be "
+ "of type " + PKIXAttrCertChecker.class.getName() + ".");
}
}
this.attrCertCheckers.clear();
this.attrCertCheckers.addAll(attrCertCheckers);
}
}