X509CRLStoreSelector.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.x509;
2
3import org.bouncycastle.asn1.DERInteger;
4import org.bouncycastle.asn1.x509.X509Extensions;
5import org.bouncycastle.util.Arrays;
6import org.bouncycastle.util.Selector;
7import org.bouncycastle.x509.extension.X509ExtensionUtil;
8
9import java.io.IOException;
10import java.math.BigInteger;
11import java.security.cert.CRL;
12import java.security.cert.X509CRL;
13import java.security.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 */
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        DERInteger dci = null;
100        try
101        {
102            byte[] bytes = crl
103                .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId());
104            if (bytes != null)
105            {
106                dci = DERInteger.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