Home | History | Annotate | Download | only in provider
      1 package org.bouncycastle.jce.provider;
      2 
      3 import java.io.ByteArrayOutputStream;
      4 import java.io.IOException;
      5 import java.math.BigInteger;
      6 import java.security.InvalidKeyException;
      7 import java.security.NoSuchAlgorithmException;
      8 import java.security.NoSuchProviderException;
      9 import java.security.Principal;
     10 import java.security.PublicKey;
     11 import java.security.Signature;
     12 import java.security.SignatureException;
     13 import java.security.cert.CRLException;
     14 import java.security.cert.Certificate;
     15 import java.security.cert.X509CRL;
     16 import java.security.cert.X509CRLEntry;
     17 import java.security.cert.X509Certificate;
     18 import java.util.Date;
     19 import java.util.Enumeration;
     20 import java.util.HashSet;
     21 import java.util.Set;
     22 
     23 import javax.security.auth.x500.X500Principal;
     24 
     25 import org.bouncycastle.asn1.ASN1Encodable;
     26 import org.bouncycastle.asn1.ASN1OutputStream;
     27 import org.bouncycastle.asn1.DERObjectIdentifier;
     28 import org.bouncycastle.asn1.DEROutputStream;
     29 import org.bouncycastle.asn1.x509.CertificateList;
     30 import org.bouncycastle.asn1.x509.IssuingDistributionPoint;
     31 import org.bouncycastle.asn1.x509.TBSCertList;
     32 import org.bouncycastle.asn1.x509.X509Extension;
     33 import org.bouncycastle.asn1.x509.X509Extensions;
     34 import org.bouncycastle.jce.X509Principal;
     35 import org.bouncycastle.x509.extension.X509ExtensionUtil;
     36 
     37 /**
     38  * The following extensions are listed in RFC 2459 as relevant to CRLs
     39  *
     40  * Authority Key Identifier
     41  * Issuer Alternative Name
     42  * CRL Number
     43  * Delta CRL Indicator (critical)
     44  * Issuing Distribution Point (critical)
     45  */
     46 public class X509CRLObject
     47     extends X509CRL
     48 {
     49     private CertificateList c;
     50     private String sigAlgName;
     51     private byte[] sigAlgParams;
     52 
     53     public X509CRLObject(
     54         CertificateList c)
     55         throws CRLException
     56     {
     57         this.c = c;
     58 
     59         try
     60         {
     61             this.sigAlgName = X509SignatureUtil.getSignatureName(c.getSignatureAlgorithm());
     62 
     63             if (c.getSignatureAlgorithm().getParameters() != null)
     64             {
     65                 this.sigAlgParams = ((ASN1Encodable)c.getSignatureAlgorithm().getParameters()).getDEREncoded();
     66             }
     67             else
     68             {
     69                 this.sigAlgParams = null;
     70             }
     71         }
     72         catch (Exception e)
     73         {
     74             throw new CRLException("CRL contents invalid: " + e);
     75         }
     76     }
     77 
     78     /**
     79      * Will return true if any extensions are present and marked
     80      * as critical as we currently dont handle any extensions!
     81      */
     82     public boolean hasUnsupportedCriticalExtension()
     83     {
     84         Set extns = getCriticalExtensionOIDs();
     85         if (extns != null && !extns.isEmpty())
     86         {
     87             return true;
     88         }
     89 
     90         return false;
     91     }
     92 
     93     private Set getExtensionOIDs(boolean critical)
     94     {
     95         if (this.getVersion() == 2)
     96         {
     97             Set             set = new HashSet();
     98             X509Extensions  extensions = c.getTBSCertList().getExtensions();
     99             Enumeration     e = extensions.oids();
    100 
    101             while (e.hasMoreElements())
    102             {
    103                 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
    104                 X509Extension       ext = extensions.getExtension(oid);
    105 
    106                 if (critical == ext.isCritical())
    107                 {
    108                     set.add(oid.getId());
    109                 }
    110             }
    111 
    112             return set;
    113         }
    114 
    115         return null;
    116     }
    117 
    118     public Set getCriticalExtensionOIDs()
    119     {
    120         return getExtensionOIDs(true);
    121     }
    122 
    123     public Set getNonCriticalExtensionOIDs()
    124     {
    125         return getExtensionOIDs(false);
    126     }
    127 
    128     public byte[] getExtensionValue(String oid)
    129     {
    130         X509Extensions exts = c.getTBSCertList().getExtensions();
    131 
    132         if (exts != null)
    133         {
    134             X509Extension   ext = exts.getExtension(new DERObjectIdentifier(oid));
    135 
    136             if (ext != null)
    137             {
    138                 ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
    139                 DEROutputStream dOut = new DEROutputStream(bOut);
    140 
    141                 try
    142                 {
    143                     dOut.writeObject(ext.getValue());
    144 
    145                     return bOut.toByteArray();
    146                 }
    147                 catch (Exception e)
    148                 {
    149                     throw new RuntimeException("error encoding " + e.toString());
    150                 }
    151             }
    152         }
    153 
    154         return null;
    155     }
    156 
    157     public byte[] getEncoded()
    158         throws CRLException
    159     {
    160         ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
    161         DEROutputStream            dOut = new DEROutputStream(bOut);
    162 
    163         try
    164         {
    165             dOut.writeObject(c);
    166 
    167             return bOut.toByteArray();
    168         }
    169         catch (IOException e)
    170         {
    171             throw new CRLException(e.toString());
    172         }
    173     }
    174 
    175     public void verify(PublicKey key)
    176         throws CRLException,  NoSuchAlgorithmException,
    177             InvalidKeyException, NoSuchProviderException, SignatureException
    178     {
    179         verify(key, "BC");
    180     }
    181 
    182     public void verify(PublicKey key, String sigProvider)
    183         throws CRLException, NoSuchAlgorithmException,
    184             InvalidKeyException, NoSuchProviderException, SignatureException
    185     {
    186         if (!c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature()))
    187         {
    188             throw new CRLException("Signature algorithm on CertifcateList does not match TBSCertList.");
    189         }
    190 
    191         Signature sig = Signature.getInstance(getSigAlgName(), sigProvider);
    192 
    193         sig.initVerify(key);
    194         sig.update(this.getTBSCertList());
    195         if (!sig.verify(this.getSignature()))
    196         {
    197             throw new SignatureException("CRL does not verify with supplied public key.");
    198         }
    199     }
    200 
    201     public int getVersion()
    202     {
    203         return c.getVersion();
    204     }
    205 
    206     public Principal getIssuerDN()
    207     {
    208         return new X509Principal(c.getIssuer());
    209     }
    210 
    211     public X500Principal getIssuerX500Principal()
    212     {
    213         try
    214         {
    215             ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
    216             ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
    217 
    218             aOut.writeObject(c.getIssuer());
    219 
    220             return new X500Principal(bOut.toByteArray());
    221         }
    222         catch (IOException e)
    223         {
    224             throw new IllegalStateException("can't encode issuer DN");
    225         }
    226     }
    227 
    228     public Date getThisUpdate()
    229     {
    230         return c.getThisUpdate().getDate();
    231     }
    232 
    233     public Date getNextUpdate()
    234     {
    235         if (c.getNextUpdate() != null)
    236         {
    237             return c.getNextUpdate().getDate();
    238         }
    239 
    240         return null;
    241     }
    242 
    243     public X509CRLEntry getRevokedCertificate(BigInteger serialNumber)
    244     {
    245         TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
    246         boolean isIndirect = isIndirectCRL();
    247         if (certs != null)
    248         {
    249             X500Principal previousCertificateIssuer = getIssuerX500Principal();
    250             for (int i = 0; i < certs.length; i++)
    251             {
    252                 X509CRLEntryObject crlentry = new X509CRLEntryObject(certs[i],
    253                         isIndirect, previousCertificateIssuer);
    254                 previousCertificateIssuer = crlentry.getCertificateIssuer();
    255                 if (crlentry.getSerialNumber().equals(serialNumber))
    256                 {
    257                     return crlentry;
    258                 }
    259             }
    260         }
    261 
    262         return null;
    263     }
    264 
    265     private boolean isIndirectCRL()
    266     {
    267         byte[] idp = getExtensionValue(X509Extensions.IssuingDistributionPoint.getId());
    268         boolean isIndirect = false;
    269         try
    270         {
    271             if (idp != null)
    272             {
    273                 isIndirect = IssuingDistributionPoint.getInstance(
    274                         X509ExtensionUtil.fromExtensionValue(idp))
    275                         .isIndirectCRL();
    276             }
    277         }
    278         catch (IOException e)
    279         {
    280             throw new RuntimeException(
    281                     "Exception reading IssuingDistributionPoint" + e);
    282         }
    283 
    284         return isIndirect;
    285     }
    286 
    287     public Set getRevokedCertificates()
    288     {
    289         TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
    290         boolean isIndirect = isIndirectCRL();
    291         if (certs != null)
    292         {
    293             Set set = new HashSet();
    294             X500Principal previousCertificateIssuer = getIssuerX500Principal();
    295             for (int i = 0; i < certs.length; i++)
    296             {
    297                 X509CRLEntryObject crlentry = new X509CRLEntryObject(certs[i],
    298                         isIndirect, previousCertificateIssuer);
    299                 set.add(crlentry);
    300                 previousCertificateIssuer = crlentry.getCertificateIssuer();
    301             }
    302 
    303             return set;
    304         }
    305 
    306         return null;
    307     }
    308 
    309     public byte[] getTBSCertList()
    310         throws CRLException
    311     {
    312         ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
    313         DEROutputStream            dOut = new DEROutputStream(bOut);
    314 
    315         try
    316         {
    317             dOut.writeObject(c.getTBSCertList());
    318 
    319             return bOut.toByteArray();
    320         }
    321         catch (IOException e)
    322         {
    323             throw new CRLException(e.toString());
    324         }
    325     }
    326 
    327     public byte[] getSignature()
    328     {
    329         return c.getSignature().getBytes();
    330     }
    331 
    332     public String getSigAlgName()
    333     {
    334         return sigAlgName;
    335     }
    336 
    337     public String getSigAlgOID()
    338     {
    339         return c.getSignatureAlgorithm().getObjectId().getId();
    340     }
    341 
    342     public byte[] getSigAlgParams()
    343     {
    344         if (sigAlgParams != null)
    345         {
    346             byte[] tmp = new byte[sigAlgParams.length];
    347 
    348             System.arraycopy(sigAlgParams, 0, tmp, 0, tmp.length);
    349 
    350             return tmp;
    351         }
    352 
    353         return null;
    354     }
    355 
    356     /**
    357      * Returns a string representation of this CRL.
    358      *
    359      * @return a string representation of this CRL.
    360      */
    361     public String toString()
    362     {
    363         return "X.509 CRL";
    364     }
    365 
    366     /**
    367      * Checks whether the given certificate is on this CRL.
    368      *
    369      * @param cert the certificate to check for.
    370      * @return true if the given certificate is on this CRL,
    371      * false otherwise.
    372      */
    373     public boolean isRevoked(Certificate cert)
    374     {
    375         if (!cert.getType().equals("X.509"))
    376         {
    377             throw new RuntimeException("X.509 CRL used with non X.509 Cert");
    378         }
    379 
    380         TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
    381 
    382         if (certs != null)
    383         {
    384             BigInteger serial = ((X509Certificate)cert).getSerialNumber();
    385 
    386             for (int i = 0; i < certs.length; i++)
    387             {
    388                 if (certs[i].getUserCertificate().getValue().equals(serial))
    389                 {
    390                     return true;
    391                 }
    392             }
    393         }
    394 
    395         return false;
    396     }
    397 }
    398 
    399