package org.bouncycastle.x509; import org.bouncycastle.asn1.DERInteger; import org.bouncycastle.asn1.x509.X509Extensions; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.Selector; import org.bouncycastle.x509.extension.X509ExtensionUtil; import java.io.IOException; import java.math.BigInteger; import java.security.cert.CRL; import java.security.cert.X509CRL; import java.security.cert.X509CRLSelector; /** * This class is a Selector implementation for X.509 certificate revocation * lists. * * @see org.bouncycastle.util.Selector * @see org.bouncycastle.x509.X509Store * @see org.bouncycastle.jce.provider.X509StoreCRLCollection */ public class X509CRLStoreSelector extends X509CRLSelector implements Selector { private boolean deltaCRLIndicator = false; private boolean completeCRLEnabled = false; private BigInteger maxBaseCRLNumber = null; private byte[] issuingDistributionPoint = null; private boolean issuingDistributionPointEnabled = false; private X509AttributeCertificate attrCertChecking; /** * Returns if the issuing distribution point criteria should be applied. * Defaults to <code>false</code>. * <p> * You may also set the issuing distribution point criteria if not a missing * issuing distribution point should be assumed. * * @return Returns if the issuing distribution point check is enabled. */ public boolean isIssuingDistributionPointEnabled() { return issuingDistributionPointEnabled; } /** * Enables or disables the issuing distribution point check. * * @param issuingDistributionPointEnabled <code>true</code> to enable the * issuing distribution point check. */ public void setIssuingDistributionPointEnabled( boolean issuingDistributionPointEnabled) { this.issuingDistributionPointEnabled = issuingDistributionPointEnabled; } /** * Sets the attribute certificate being checked. This is not a criterion. * Rather, it is optional information that may help a {@link X509Store} find * CRLs that would be relevant when checking revocation for the specified * attribute certificate. If <code>null</code> is specified, then no such * optional information is provided. * * @param attrCert the <code>X509AttributeCertificate</code> being checked (or * <code>null</code>) * @see #getAttrCertificateChecking() */ public void setAttrCertificateChecking(X509AttributeCertificate attrCert) { attrCertChecking = attrCert; } /** * Returns the attribute certificate being checked. * * @return Returns the attribute certificate being checked. * @see #setAttrCertificateChecking(X509AttributeCertificate) */ public X509AttributeCertificate getAttrCertificateChecking() { return attrCertChecking; } public boolean match(Object obj) { if (!(obj instanceof X509CRL)) { return false; } X509CRL crl = (X509CRL)obj; DERInteger dci = null; try { byte[] bytes = crl .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId()); if (bytes != null) { dci = DERInteger.getInstance(X509ExtensionUtil .fromExtensionValue(bytes)); } } catch (Exception e) { return false; } if (isDeltaCRLIndicatorEnabled()) { if (dci == null) { return false; } } if (isCompleteCRLEnabled()) { if (dci != null) { return false; } } if (dci != null) { if (maxBaseCRLNumber != null) { if (dci.getPositiveValue().compareTo(maxBaseCRLNumber) == 1) { return false; } } } if (issuingDistributionPointEnabled) { byte[] idp = crl .getExtensionValue(X509Extensions.IssuingDistributionPoint .getId()); if (issuingDistributionPoint == null) { if (idp != null) { return false; } } else { if (!Arrays.areEqual(idp, issuingDistributionPoint)) { return false; } } } return super.match((X509CRL)obj); } public boolean match(CRL crl) { return match((Object)crl); } /** * Returns if this selector must match CRLs with the delta CRL indicator * extension set. Defaults to <code>false</code>. * * @return Returns <code>true</code> if only CRLs with the delta CRL * indicator extension are selected. */ public boolean isDeltaCRLIndicatorEnabled() { return deltaCRLIndicator; } /** * If this is set to <code>true</code> the CRL reported contains the delta * CRL indicator CRL extension. * <p> * {@link #setCompleteCRLEnabled(boolean)} and * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. * * @param deltaCRLIndicator <code>true</code> if the delta CRL indicator * extension must be in the CRL. */ public void setDeltaCRLIndicatorEnabled(boolean deltaCRLIndicator) { this.deltaCRLIndicator = deltaCRLIndicator; } /** * Returns an instance of this from a <code>X509CRLSelector</code>. * * @param selector A <code>X509CRLSelector</code> instance. * @return An instance of an <code>X509CRLStoreSelector</code>. * @exception IllegalArgumentException if selector is null or creation * fails. */ public static X509CRLStoreSelector getInstance(X509CRLSelector selector) { if (selector == null) { throw new IllegalArgumentException( "cannot create from null selector"); } X509CRLStoreSelector cs = new X509CRLStoreSelector(); cs.setCertificateChecking(selector.getCertificateChecking()); cs.setDateAndTime(selector.getDateAndTime()); try { cs.setIssuerNames(selector.getIssuerNames()); } catch (IOException e) { // cannot happen throw new IllegalArgumentException(e.getMessage()); } cs.setIssuers(selector.getIssuers()); cs.setMaxCRLNumber(selector.getMaxCRL()); cs.setMinCRLNumber(selector.getMinCRL()); return cs; } public Object clone() { X509CRLStoreSelector sel = X509CRLStoreSelector.getInstance(this); sel.deltaCRLIndicator = deltaCRLIndicator; sel.completeCRLEnabled = completeCRLEnabled; sel.maxBaseCRLNumber = maxBaseCRLNumber; sel.attrCertChecking = attrCertChecking; sel.issuingDistributionPointEnabled = issuingDistributionPointEnabled; sel.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); return sel; } /** * If <code>true</code> only complete CRLs are returned. Defaults to * <code>false</code>. * * @return <code>true</code> if only complete CRLs are returned. */ public boolean isCompleteCRLEnabled() { return completeCRLEnabled; } /** * If set to <code>true</code> only complete CRLs are returned. * <p> * {@link #setCompleteCRLEnabled(boolean)} and * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. * * @param completeCRLEnabled <code>true</code> if only complete CRLs * should be returned. */ public void setCompleteCRLEnabled(boolean completeCRLEnabled) { this.completeCRLEnabled = completeCRLEnabled; } /** * Get the maximum base CRL number. Defaults to <code>null</code>. * * @return Returns the maximum base CRL number. * @see #setMaxBaseCRLNumber(BigInteger) */ public BigInteger getMaxBaseCRLNumber() { return maxBaseCRLNumber; } /** * Sets the maximum base CRL number. Setting to <code>null</code> disables * this cheack. * <p> * This is only meaningful for delta CRLs. Complete CRLs must have a CRL * number which is greater or equal than the base number of the * corresponding CRL. * * @param maxBaseCRLNumber The maximum base CRL number to set. */ public void setMaxBaseCRLNumber(BigInteger maxBaseCRLNumber) { this.maxBaseCRLNumber = maxBaseCRLNumber; } /** * Returns the issuing distribution point. Defaults to <code>null</code>, * which is a missing issuing distribution point extension. * <p> * The internal byte array is cloned before it is returned. * <p> * The criteria must be enable with * {@link #setIssuingDistributionPointEnabled(boolean)}. * * @return Returns the issuing distribution point. * @see #setIssuingDistributionPoint(byte[]) */ public byte[] getIssuingDistributionPoint() { return Arrays.clone(issuingDistributionPoint); } /** * Sets the issuing distribution point. * <p> * The issuing distribution point extension is a CRL extension which * identifies the scope and the distribution point of a CRL. The scope * contains among others information about revocation reasons contained in * the CRL. Delta CRLs and complete CRLs must have matching issuing * distribution points. * <p> * The byte array is cloned to protect against subsequent modifications. * <p> * You must also enable or disable this criteria with * {@link #setIssuingDistributionPointEnabled(boolean)}. * * @param issuingDistributionPoint The issuing distribution point to set. * This is the DER encoded OCTET STRING extension value. * @see #getIssuingDistributionPoint() */ public void setIssuingDistributionPoint(byte[] issuingDistributionPoint) { this.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); } }