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