X509CRLEntryObject.java revision e6bf3e8dfa2804891a82075cb469b736321b4827
1package org.bouncycastle.jce.provider;
2
3import java.io.IOException;
4import java.math.BigInteger;
5import java.security.cert.CRLException;
6import java.security.cert.X509CRLEntry;
7import java.util.Date;
8import java.util.Enumeration;
9import java.util.HashSet;
10import java.util.Set;
11
12import javax.security.auth.x500.X500Principal;
13
14import org.bouncycastle.asn1.ASN1Encoding;
15import org.bouncycastle.asn1.ASN1InputStream;
16import org.bouncycastle.asn1.ASN1ObjectIdentifier;
17import org.bouncycastle.asn1.DEREnumerated;
18import org.bouncycastle.asn1.util.ASN1Dump;
19import org.bouncycastle.asn1.x500.X500Name;
20import org.bouncycastle.asn1.x509.CRLReason;
21import org.bouncycastle.asn1.x509.Extension;
22import org.bouncycastle.asn1.x509.Extensions;
23import org.bouncycastle.asn1.x509.GeneralName;
24import org.bouncycastle.asn1.x509.GeneralNames;
25import org.bouncycastle.asn1.x509.TBSCertList;
26import org.bouncycastle.asn1.x509.X509Extension;
27import org.bouncycastle.x509.extension.X509ExtensionUtil;
28
29/**
30 * The following extensions are listed in RFC 2459 as relevant to CRL Entries
31 *
32 * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
33 * (critical)
34 */
35public class X509CRLEntryObject extends X509CRLEntry
36{
37    private TBSCertList.CRLEntry c;
38
39    private X500Name certificateIssuer;
40    private int           hashValue;
41    private boolean       isHashValueSet;
42
43    public X509CRLEntryObject(TBSCertList.CRLEntry c)
44    {
45        this.c = c;
46        this.certificateIssuer = null;
47    }
48
49    /**
50     * Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
51     * is <code>false</code> {@link #getCertificateIssuer()} will always
52     * return <code>null</code>, <code>previousCertificateIssuer</code> is
53     * ignored. If this <code>isIndirect</code> is specified and this CRLEntry
54     * has no certificate issuer CRL entry extension
55     * <code>previousCertificateIssuer</code> is returned by
56     * {@link #getCertificateIssuer()}.
57     *
58     * @param c
59     *            TBSCertList.CRLEntry object.
60     * @param isIndirect
61     *            <code>true</code> if the corresponding CRL is a indirect
62     *            CRL.
63     * @param previousCertificateIssuer
64     *            Certificate issuer of the previous CRLEntry.
65     */
66    public X509CRLEntryObject(
67        TBSCertList.CRLEntry c,
68        boolean isIndirect,
69        X500Name previousCertificateIssuer)
70    {
71        this.c = c;
72        this.certificateIssuer = loadCertificateIssuer(isIndirect, previousCertificateIssuer);
73    }
74
75    /**
76     * Will return true if any extensions are present and marked as critical as
77     * we currently don't handle any extensions!
78     */
79    public boolean hasUnsupportedCriticalExtension()
80    {
81        Set extns = getCriticalExtensionOIDs();
82
83        return extns != null && !extns.isEmpty();
84    }
85
86    private X500Name loadCertificateIssuer(boolean isIndirect, X500Name previousCertificateIssuer)
87    {
88        if (!isIndirect)
89        {
90            return null;
91        }
92
93        byte[] ext = getExtensionValue(X509Extension.certificateIssuer.getId());
94        if (ext == null)
95        {
96            return previousCertificateIssuer;
97        }
98
99        try
100        {
101            GeneralName[] names = GeneralNames.getInstance(
102                    X509ExtensionUtil.fromExtensionValue(ext)).getNames();
103            for (int i = 0; i < names.length; i++)
104            {
105                if (names[i].getTagNo() == GeneralName.directoryName)
106                {
107                    return X500Name.getInstance(names[i].getName());
108                }
109            }
110            return null;
111        }
112        catch (IOException e)
113        {
114            return null;
115        }
116    }
117
118    public X500Principal getCertificateIssuer()
119    {
120        if (certificateIssuer == null)
121        {
122            return null;
123        }
124        try
125        {
126            return new X500Principal(certificateIssuer.getEncoded());
127        }
128        catch (IOException e)
129        {
130            return null;
131        }
132    }
133
134    private Set getExtensionOIDs(boolean critical)
135    {
136        Extensions extensions = c.getExtensions();
137
138        if (extensions != null)
139        {
140            Set set = new HashSet();
141            Enumeration e = extensions.oids();
142
143            while (e.hasMoreElements())
144            {
145                ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) e.nextElement();
146                Extension ext = extensions.getExtension(oid);
147
148                if (critical == ext.isCritical())
149                {
150                    set.add(oid.getId());
151                }
152            }
153
154            return set;
155        }
156
157        return null;
158    }
159
160    public Set getCriticalExtensionOIDs()
161    {
162        return getExtensionOIDs(true);
163    }
164
165    public Set getNonCriticalExtensionOIDs()
166    {
167        return getExtensionOIDs(false);
168    }
169
170    public byte[] getExtensionValue(String oid)
171    {
172        Extensions exts = c.getExtensions();
173
174        if (exts != null)
175        {
176            Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid));
177
178            if (ext != null)
179            {
180                try
181                {
182                    return ext.getExtnValue().getEncoded();
183                }
184                catch (Exception e)
185                {
186                    throw new RuntimeException("error encoding " + e.toString());
187                }
188            }
189        }
190
191        return null;
192    }
193
194    /**
195     * Cache the hashCode value - calculating it with the standard method.
196     * @return  calculated hashCode.
197     */
198    public int hashCode()
199    {
200        if (!isHashValueSet)
201        {
202            hashValue = super.hashCode();
203            isHashValueSet = true;
204        }
205
206        return hashValue;
207    }
208
209    public byte[] getEncoded()
210        throws CRLException
211    {
212        try
213        {
214            return c.getEncoded(ASN1Encoding.DER);
215        }
216        catch (IOException e)
217        {
218            throw new CRLException(e.toString());
219        }
220    }
221
222    public BigInteger getSerialNumber()
223    {
224        return c.getUserCertificate().getValue();
225    }
226
227    public Date getRevocationDate()
228    {
229        return c.getRevocationDate().getDate();
230    }
231
232    public boolean hasExtensions()
233    {
234        return c.getExtensions() != null;
235    }
236
237    public String toString()
238    {
239        StringBuffer buf = new StringBuffer();
240        String nl = System.getProperty("line.separator");
241
242        buf.append("      userCertificate: ").append(this.getSerialNumber()).append(nl);
243        buf.append("       revocationDate: ").append(this.getRevocationDate()).append(nl);
244        buf.append("       certificateIssuer: ").append(this.getCertificateIssuer()).append(nl);
245
246        Extensions extensions = c.getExtensions();
247
248        if (extensions != null)
249        {
250            Enumeration e = extensions.oids();
251            if (e.hasMoreElements())
252            {
253                buf.append("   crlEntryExtensions:").append(nl);
254
255                while (e.hasMoreElements())
256                {
257                    ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement();
258                    Extension ext = extensions.getExtension(oid);
259                    if (ext.getExtnValue() != null)
260                    {
261                        byte[]                  octs = ext.getExtnValue().getOctets();
262                        ASN1InputStream dIn = new ASN1InputStream(octs);
263                        buf.append("                       critical(").append(ext.isCritical()).append(") ");
264                        try
265                        {
266                            if (oid.equals(X509Extension.reasonCode))
267                            {
268                                buf.append(CRLReason.getInstance(DEREnumerated.getInstance(dIn.readObject()))).append(nl);
269                            }
270                            else if (oid.equals(X509Extension.certificateIssuer))
271                            {
272                                buf.append("Certificate issuer: ").append(GeneralNames.getInstance(dIn.readObject())).append(nl);
273                            }
274                            else
275                            {
276                                buf.append(oid.getId());
277                                buf.append(" value = ").append(ASN1Dump.dumpAsString(dIn.readObject())).append(nl);
278                            }
279                        }
280                        catch (Exception ex)
281                        {
282                            buf.append(oid.getId());
283                            buf.append(" value = ").append("*****").append(nl);
284                        }
285                    }
286                    else
287                    {
288                        buf.append(nl);
289                    }
290                }
291            }
292        }
293
294        return buf.toString();
295    }
296}
297