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