1package org.bouncycastle.x509; 2 3import java.io.IOException; 4import java.math.BigInteger; 5import java.security.cert.CRL; 6import java.security.cert.X509CRL; 7import java.security.cert.X509CRLSelector; 8 9import org.bouncycastle.asn1.ASN1Integer; 10import org.bouncycastle.asn1.x509.X509Extensions; 11import org.bouncycastle.util.Arrays; 12import org.bouncycastle.util.Selector; 13import org.bouncycastle.x509.extension.X509ExtensionUtil; 14 15/** 16 * This class is a Selector implementation for X.509 certificate revocation 17 * lists. 18 * 19 * @see org.bouncycastle.util.Selector 20 * @see org.bouncycastle.x509.X509Store 21 * @see org.bouncycastle.jce.provider.X509StoreCRLCollection 22 */ 23public class X509CRLStoreSelector 24 extends X509CRLSelector 25 implements Selector 26{ 27 private boolean deltaCRLIndicator = false; 28 29 private boolean completeCRLEnabled = false; 30 31 private BigInteger maxBaseCRLNumber = null; 32 33 private byte[] issuingDistributionPoint = null; 34 35 private boolean issuingDistributionPointEnabled = false; 36 37 private X509AttributeCertificate attrCertChecking; 38 39 /** 40 * Returns if the issuing distribution point criteria should be applied. 41 * Defaults to <code>false</code>. 42 * <p> 43 * You may also set the issuing distribution point criteria if not a missing 44 * issuing distribution point should be assumed. 45 * 46 * @return Returns if the issuing distribution point check is enabled. 47 */ 48 public boolean isIssuingDistributionPointEnabled() 49 { 50 return issuingDistributionPointEnabled; 51 } 52 53 /** 54 * Enables or disables the issuing distribution point check. 55 * 56 * @param issuingDistributionPointEnabled <code>true</code> to enable the 57 * issuing distribution point check. 58 */ 59 public void setIssuingDistributionPointEnabled( 60 boolean issuingDistributionPointEnabled) 61 { 62 this.issuingDistributionPointEnabled = issuingDistributionPointEnabled; 63 } 64 65 /** 66 * Sets the attribute certificate being checked. This is not a criterion. 67 * Rather, it is optional information that may help a {@link X509Store} find 68 * CRLs that would be relevant when checking revocation for the specified 69 * attribute certificate. If <code>null</code> is specified, then no such 70 * optional information is provided. 71 * 72 * @param attrCert the <code>X509AttributeCertificate</code> being checked (or 73 * <code>null</code>) 74 * @see #getAttrCertificateChecking() 75 */ 76 public void setAttrCertificateChecking(X509AttributeCertificate attrCert) 77 { 78 attrCertChecking = attrCert; 79 } 80 81 /** 82 * Returns the attribute certificate being checked. 83 * 84 * @return Returns the attribute certificate being checked. 85 * @see #setAttrCertificateChecking(X509AttributeCertificate) 86 */ 87 public X509AttributeCertificate getAttrCertificateChecking() 88 { 89 return attrCertChecking; 90 } 91 92 public boolean match(Object obj) 93 { 94 if (!(obj instanceof X509CRL)) 95 { 96 return false; 97 } 98 X509CRL crl = (X509CRL)obj; 99 ASN1Integer dci = null; 100 try 101 { 102 byte[] bytes = crl 103 .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId()); 104 if (bytes != null) 105 { 106 dci = ASN1Integer.getInstance(X509ExtensionUtil 107 .fromExtensionValue(bytes)); 108 } 109 } 110 catch (Exception e) 111 { 112 return false; 113 } 114 if (isDeltaCRLIndicatorEnabled()) 115 { 116 if (dci == null) 117 { 118 return false; 119 } 120 } 121 if (isCompleteCRLEnabled()) 122 { 123 if (dci != null) 124 { 125 return false; 126 } 127 } 128 if (dci != null) 129 { 130 131 if (maxBaseCRLNumber != null) 132 { 133 if (dci.getPositiveValue().compareTo(maxBaseCRLNumber) == 1) 134 { 135 return false; 136 } 137 } 138 } 139 if (issuingDistributionPointEnabled) 140 { 141 byte[] idp = crl 142 .getExtensionValue(X509Extensions.IssuingDistributionPoint 143 .getId()); 144 if (issuingDistributionPoint == null) 145 { 146 if (idp != null) 147 { 148 return false; 149 } 150 } 151 else 152 { 153 if (!Arrays.areEqual(idp, issuingDistributionPoint)) 154 { 155 return false; 156 } 157 } 158 159 } 160 return super.match((X509CRL)obj); 161 } 162 163 public boolean match(CRL crl) 164 { 165 return match((Object)crl); 166 } 167 168 /** 169 * Returns if this selector must match CRLs with the delta CRL indicator 170 * extension set. Defaults to <code>false</code>. 171 * 172 * @return Returns <code>true</code> if only CRLs with the delta CRL 173 * indicator extension are selected. 174 */ 175 public boolean isDeltaCRLIndicatorEnabled() 176 { 177 return deltaCRLIndicator; 178 } 179 180 /** 181 * If this is set to <code>true</code> the CRL reported contains the delta 182 * CRL indicator CRL extension. 183 * <p> 184 * {@link #setCompleteCRLEnabled(boolean)} and 185 * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. 186 * 187 * @param deltaCRLIndicator <code>true</code> if the delta CRL indicator 188 * extension must be in the CRL. 189 */ 190 public void setDeltaCRLIndicatorEnabled(boolean deltaCRLIndicator) 191 { 192 this.deltaCRLIndicator = deltaCRLIndicator; 193 } 194 195 /** 196 * Returns an instance of this from a <code>X509CRLSelector</code>. 197 * 198 * @param selector A <code>X509CRLSelector</code> instance. 199 * @return An instance of an <code>X509CRLStoreSelector</code>. 200 * @exception IllegalArgumentException if selector is null or creation 201 * fails. 202 */ 203 public static X509CRLStoreSelector getInstance(X509CRLSelector selector) 204 { 205 if (selector == null) 206 { 207 throw new IllegalArgumentException( 208 "cannot create from null selector"); 209 } 210 X509CRLStoreSelector cs = new X509CRLStoreSelector(); 211 cs.setCertificateChecking(selector.getCertificateChecking()); 212 cs.setDateAndTime(selector.getDateAndTime()); 213 try 214 { 215 cs.setIssuerNames(selector.getIssuerNames()); 216 } 217 catch (IOException e) 218 { 219 // cannot happen 220 throw new IllegalArgumentException(e.getMessage()); 221 } 222 cs.setIssuers(selector.getIssuers()); 223 cs.setMaxCRLNumber(selector.getMaxCRL()); 224 cs.setMinCRLNumber(selector.getMinCRL()); 225 return cs; 226 } 227 228 public Object clone() 229 { 230 X509CRLStoreSelector sel = X509CRLStoreSelector.getInstance(this); 231 sel.deltaCRLIndicator = deltaCRLIndicator; 232 sel.completeCRLEnabled = completeCRLEnabled; 233 sel.maxBaseCRLNumber = maxBaseCRLNumber; 234 sel.attrCertChecking = attrCertChecking; 235 sel.issuingDistributionPointEnabled = issuingDistributionPointEnabled; 236 sel.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); 237 return sel; 238 } 239 240 /** 241 * If <code>true</code> only complete CRLs are returned. Defaults to 242 * <code>false</code>. 243 * 244 * @return <code>true</code> if only complete CRLs are returned. 245 */ 246 public boolean isCompleteCRLEnabled() 247 { 248 return completeCRLEnabled; 249 } 250 251 /** 252 * If set to <code>true</code> only complete CRLs are returned. 253 * <p> 254 * {@link #setCompleteCRLEnabled(boolean)} and 255 * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. 256 * 257 * @param completeCRLEnabled <code>true</code> if only complete CRLs 258 * should be returned. 259 */ 260 public void setCompleteCRLEnabled(boolean completeCRLEnabled) 261 { 262 this.completeCRLEnabled = completeCRLEnabled; 263 } 264 265 /** 266 * Get the maximum base CRL number. Defaults to <code>null</code>. 267 * 268 * @return Returns the maximum base CRL number. 269 * @see #setMaxBaseCRLNumber(BigInteger) 270 */ 271 public BigInteger getMaxBaseCRLNumber() 272 { 273 return maxBaseCRLNumber; 274 } 275 276 /** 277 * Sets the maximum base CRL number. Setting to <code>null</code> disables 278 * this cheack. 279 * <p> 280 * This is only meaningful for delta CRLs. Complete CRLs must have a CRL 281 * number which is greater or equal than the base number of the 282 * corresponding CRL. 283 * 284 * @param maxBaseCRLNumber The maximum base CRL number to set. 285 */ 286 public void setMaxBaseCRLNumber(BigInteger maxBaseCRLNumber) 287 { 288 this.maxBaseCRLNumber = maxBaseCRLNumber; 289 } 290 291 /** 292 * Returns the issuing distribution point. Defaults to <code>null</code>, 293 * which is a missing issuing distribution point extension. 294 * <p> 295 * The internal byte array is cloned before it is returned. 296 * <p> 297 * The criteria must be enable with 298 * {@link #setIssuingDistributionPointEnabled(boolean)}. 299 * 300 * @return Returns the issuing distribution point. 301 * @see #setIssuingDistributionPoint(byte[]) 302 */ 303 public byte[] getIssuingDistributionPoint() 304 { 305 return Arrays.clone(issuingDistributionPoint); 306 } 307 308 /** 309 * Sets the issuing distribution point. 310 * <p> 311 * The issuing distribution point extension is a CRL extension which 312 * identifies the scope and the distribution point of a CRL. The scope 313 * contains among others information about revocation reasons contained in 314 * the CRL. Delta CRLs and complete CRLs must have matching issuing 315 * distribution points. 316 * <p> 317 * The byte array is cloned to protect against subsequent modifications. 318 * <p> 319 * You must also enable or disable this criteria with 320 * {@link #setIssuingDistributionPointEnabled(boolean)}. 321 * 322 * @param issuingDistributionPoint The issuing distribution point to set. 323 * This is the DER encoded OCTET STRING extension value. 324 * @see #getIssuingDistributionPoint() 325 */ 326 public void setIssuingDistributionPoint(byte[] issuingDistributionPoint) 327 { 328 this.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); 329 } 330} 331