CertificateFactory.java revision a198e1ecc615e26a167d0f2dca9fa7e5fc62de10
15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)package org.bouncycastle.jcajce.provider.asymmetric.x509;
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.io.IOException;
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.io.InputStream;
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.io.PushbackInputStream;
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.security.cert.CRL;
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.security.cert.CRLException;
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.security.cert.CertPath;
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.security.cert.CertificateException;
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.security.cert.CertificateFactorySpi;
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.security.cert.CertificateParsingException;
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.security.cert.X509Certificate;
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.util.ArrayList;
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.util.Collection;
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.util.Iterator;
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import java.util.List;
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.ASN1InputStream;
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.ASN1ObjectIdentifier;
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.ASN1Sequence;
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.ASN1Set;
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.ASN1TaggedObject;
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.pkcs.SignedData;
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.x509.Certificate;
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)import org.bouncycastle.asn1.x509.CertificateList;
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)/**
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * class for dealing with X509 certificates.
30197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch * <p>
315d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) * At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
328abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) * base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * objects.
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) */
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)public class CertificateFactory
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    extends CertificateFactorySpi
37c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles){
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    private static final PEMUtil PEM_CERT_PARSER = new PEMUtil("CERTIFICATE");
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    private static final PEMUtil PEM_CRL_PARSER = new PEMUtil("CRL");
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private ASN1Set sData = null;
42c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    private int                sDataObjectCount = 0;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private InputStream currentStream = null;
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private ASN1Set sCrlData = null;
468abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    private int                sCrlDataObjectCount = 0;
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private InputStream currentCrlStream = null;
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private java.security.cert.Certificate readDERCertificate(
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASN1InputStream dIn)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throws IOException, CertificateParsingException
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
538abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        ASN1Sequence seq = (ASN1Sequence)dIn.readObject();
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (seq.size() > 1
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                && seq.getObjectAt(0) instanceof ASN1ObjectIdentifier)
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData))
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                sData = SignedData.getInstance(ASN1Sequence.getInstance(
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    (ASN1TaggedObject)seq.getObjectAt(1), true)).getCertificates();
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return getCertificate();
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return new X509CertificateObject(
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            Certificate.getInstance(seq));
6902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    }
7002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
7102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    private java.security.cert.Certificate getCertificate()
7202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        throws CertificateParsingException
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
7402772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        if (sData != null)
7502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        {
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            while (sDataObjectCount < sData.size())
77d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            {
78d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                Object obj = sData.getObjectAt(sDataObjectCount++);
79d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)
80d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                if (obj instanceof ASN1Sequence)
81d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                {
82d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                   return new X509CertificateObject(
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                    Certificate.getInstance(obj));
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
89d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    }
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
91d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    private java.security.cert.Certificate readPEMCertificate(
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        InputStream in)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throws IOException, CertificateParsingException
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASN1Sequence seq = PEM_CERT_PARSER.readPEMObject(in);
968abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (seq != null)
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return new X509CertificateObject(
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            Certificate.getInstance(seq));
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    protected CRL createCRL(CertificateList c)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    throws CRLException
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return new X509CRLObject(c);
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private CRL readPEMCRL(
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        InputStream in)
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throws IOException, CRLException
115c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    {
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASN1Sequence seq = PEM_CRL_PARSER.readPEMObject(in);
117c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (seq != null)
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return createCRL(
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            CertificateList.getInstance(seq));
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return null;
125a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
126a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
127a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    private CRL readDERCRL(
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASN1InputStream aIn)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throws IOException, CRLException
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASN1Sequence seq = (ASN1Sequence)aIn.readObject();
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (seq.size() > 1
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                && seq.getObjectAt(0) instanceof ASN1ObjectIdentifier)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
136d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (seq.getObjectAt(0).equals(PKCSObjectIdentifiers.signedData))
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                sCrlData = SignedData.getInstance(ASN1Sequence.getInstance(
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    (ASN1TaggedObject)seq.getObjectAt(1), true)).getCRLs();
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return getCRL();
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
14302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch        }
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return createCRL(
146d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                     CertificateList.getInstance(seq));
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private CRL getCRL()
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throws CRLException
1518abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    {
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (sCrlData == null || sCrlDataObjectCount >= sCrlData.size())
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1541e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            return null;
1551e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)        }
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return createCRL(
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                            CertificateList.getInstance(
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                sCrlData.getObjectAt(sCrlDataObjectCount++)));
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * Generates a certificate object and initializes it with the data
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * read from the input stream inStream.
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public java.security.cert.Certificate engineGenerateCertificate(
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        InputStream in)
16851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        throws CertificateException
16951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    {
17051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        if (currentStream == null)
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentStream = in;
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sData = null;
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sDataObjectCount = 0;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (currentStream != in) // reset if input stream has changed
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1788abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            currentStream = in;
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sData = null;
1808abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)            sDataObjectCount = 0;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        try
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (sData != null)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (sDataObjectCount != sData.size())
18807a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch                {
1898abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)                    return getCertificate();
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                {
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    sData = null;
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    sDataObjectCount = 0;
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return null;
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
197d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            }
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            PushbackInputStream pis = new PushbackInputStream(in);
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            int tag = pis.read();
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (tag == -1)
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return null;
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            pis.unread(tag);
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (tag != 0x30)  // assume ascii PEM encoded.
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return readPEMCertificate(pis);
2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return readDERCertificate(new ASN1InputStream(pis));
21607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch            }
2178abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)        }
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        catch (Exception e)
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            throw new ExCertificateException(e);
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * Returns a (possibly empty) collection view of the certificates
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * read from the given input stream inStream.
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public Collection engineGenerateCertificates(
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        InputStream inStream)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throws CertificateException
231d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    {
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        java.security.cert.Certificate     cert;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        List certs = new ArrayList();
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        while ((cert = engineGenerateCertificate(inStream)) != null)
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            certs.add(cert);
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return certs;
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    /**
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * Generates a certificate revocation list (CRL) object and initializes
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     * it with the data read from the input stream inStream.
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)     */
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public CRL engineGenerateCRL(
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        InputStream inStream)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        throws CRLException
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (currentCrlStream == null)
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentCrlStream = inStream;
254d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)            sCrlData = null;
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sCrlDataObjectCount = 0;
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        else if (currentCrlStream != inStream) // reset if input stream has changed
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            currentCrlStream = inStream;
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sCrlData = null;
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            sCrlDataObjectCount = 0;
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        try
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        {
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (sCrlData != null)
2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                if (sCrlDataObjectCount != sCrlData.size())
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                {
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return getCRL();
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                else
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                {
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    sCrlData = null;
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    sCrlDataObjectCount = 0;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return null;
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            PushbackInputStream pis = new PushbackInputStream(inStream);
281d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            int tag = pis.read();
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (tag == -1)
284c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            {
2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return null;
286c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            }
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            pis.unread(tag);
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (tag != 0x30)  // assume ascii PEM encoded.
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            {
292f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                return readPEMCRL(pis);
293f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            }
294f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            else
295f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            {       // lazy evaluate to help processing of large CRLs
296f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)                return readDERCRL(new ASN1InputStream(pis, true));
297f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            }
2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
299        catch (CRLException e)
300        {
301            throw e;
302        }
303        catch (Exception e)
304        {
305            throw new CRLException(e.toString());
306        }
307    }
308
309    /**
310     * Returns a (possibly empty) collection view of the CRLs read from
311     * the given input stream inStream.
312     *
313     * The inStream may contain a sequence of DER-encoded CRLs, or
314     * a PKCS#7 CRL set.  This is a PKCS#7 SignedData object, with the
315     * only signficant field being crls.  In particular the signature
316     * and the contents are ignored.
317     */
318    public Collection engineGenerateCRLs(
319        InputStream inStream)
320        throws CRLException
321    {
322        CRL crl;
323        List crls = new ArrayList();
324
325        while ((crl = engineGenerateCRL(inStream)) != null)
326        {
327            crls.add(crl);
328        }
329
330        return crls;
331    }
332
333    public Iterator engineGetCertPathEncodings()
334    {
335        return PKIXCertPath.certPathEncodings.iterator();
336    }
337
338    public CertPath engineGenerateCertPath(
339        InputStream inStream)
340        throws CertificateException
341    {
342        return engineGenerateCertPath(inStream, "PkiPath");
343    }
344
345    public CertPath engineGenerateCertPath(
346        InputStream inStream,
347        String encoding)
348        throws CertificateException
349    {
350        return new PKIXCertPath(inStream, encoding);
351    }
352
353    public CertPath engineGenerateCertPath(
354        List certificates)
355        throws CertificateException
356    {
357        Iterator iter = certificates.iterator();
358        Object obj;
359        while (iter.hasNext())
360        {
361            obj = iter.next();
362            if (obj != null)
363            {
364                if (!(obj instanceof X509Certificate))
365                {
366                    throw new CertificateException("list contains non X509Certificate object while creating CertPath\n" + obj.toString());
367                }
368            }
369        }
370        return new PKIXCertPath(certificates);
371    }
372
373    private class ExCertificateException
374        extends CertificateException
375    {
376        private Throwable cause;
377
378        public ExCertificateException(Throwable cause)
379        {
380            this.cause = cause;
381        }
382
383        public ExCertificateException(String msg, Throwable cause)
384        {
385            super(msg);
386
387            this.cause = cause;
388        }
389
390        public Throwable getCause()
391        {
392            return cause;
393        }
394    }
395}
396