1 package org.bouncycastle.x509;
2 
3 import org.bouncycastle.asn1.ASN1Integer;
4 import org.bouncycastle.asn1.x509.X509Extensions;
5 import org.bouncycastle.util.Arrays;
6 import org.bouncycastle.util.Selector;
7 import org.bouncycastle.x509.extension.X509ExtensionUtil;
8 
9 import java.io.IOException;
10 import java.math.BigInteger;
11 import java.security.cert.CRL;
12 import java.security.cert.X509CRL;
13 import org.bouncycastle.jce.cert.X509CRLSelector;
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  */
23 public 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      */
isIssuingDistributionPointEnabled()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      */
setIssuingDistributionPointEnabled( boolean issuingDistributionPointEnabled)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      */
setAttrCertificateChecking(X509AttributeCertificate attrCert)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      */
getAttrCertificateChecking()87     public X509AttributeCertificate getAttrCertificateChecking()
88     {
89         return attrCertChecking;
90     }
91 
match(Object obj)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 
match(CRL crl)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      */
isDeltaCRLIndicatorEnabled()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      */
setDeltaCRLIndicatorEnabled(boolean deltaCRLIndicator)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      */
getInstance(X509CRLSelector selector)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 
clone()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      */
isCompleteCRLEnabled()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      */
setCompleteCRLEnabled(boolean completeCRLEnabled)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      */
getMaxBaseCRLNumber()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      */
setMaxBaseCRLNumber(BigInteger maxBaseCRLNumber)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      */
getIssuingDistributionPoint()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      */
setIssuingDistributionPoint(byte[] issuingDistributionPoint)326     public void setIssuingDistributionPoint(byte[] issuingDistributionPoint)
327     {
328         this.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint);
329     }
330 }
331