1:
37:
38:
39: package ;
40:
41: import ;
42: import ;
43: import ;
44: import ;
45: import ;
46: import ;
47: import ;
48:
49: import ;
50: import ;
51: import ;
52: import ;
53: import ;
54: import ;
55: import ;
56: import ;
57: import ;
58: import ;
59: import ;
60: import ;
61: import ;
62: import ;
63: import ;
64: import ;
65: import ;
66: import ;
67: import ;
68: import ;
69:
70: import ;
71:
72:
77: public class X509CRL extends java.security.cert.X509CRL
78: implements GnuPKIExtension
79: {
80: private static final Logger log = Configuration.DEBUG ?
81: Logger.getLogger(X509CRL.class.getName()) : null;
82:
83: private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
84: private static final OID ID_DSA_WITH_SHA1 = new OID("1.2.840.10040.4.3");
85: private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
86: private static final OID ID_RSA_WITH_MD2 = new OID("1.2.840.113549.1.1.2");
87: private static final OID ID_RSA_WITH_MD5 = new OID("1.2.840.113549.1.1.4");
88: private static final OID ID_RSA_WITH_SHA1 = new OID("1.2.840.113549.1.1.5");
89:
90: private byte[] encoded;
91:
92: private byte[] tbsCRLBytes;
93: private int version;
94: private OID algId;
95: private byte[] algParams;
96: private Date thisUpdate;
97: private Date nextUpdate;
98: private X500DistinguishedName issuerDN;
99: private HashMap revokedCerts;
100: private HashMap extensions;
101:
102: private OID sigAlg;
103: private byte[] sigAlgParams;
104: private byte[] rawSig;
105: private byte[] signature;
106:
107:
108:
109:
110:
117: public X509CRL(InputStream encoded) throws CRLException, IOException
118: {
119: super();
120: revokedCerts = new HashMap();
121: extensions = new HashMap();
122: try
123: {
124: parse(encoded);
125: }
126: catch (IOException ioe)
127: {
128: ioe.printStackTrace();
129: throw ioe;
130: }
131: catch (Exception x)
132: {
133: x.printStackTrace();
134: throw new CRLException(x.toString());
135: }
136: }
137:
138:
139:
140:
141: public boolean equals(Object o)
142: {
143: if (!(o instanceof X509CRL))
144: return false;
145: return ((X509CRL) o).getRevokedCertificates().equals(revokedCerts.values());
146: }
147:
148: public int hashCode()
149: {
150: return revokedCerts.hashCode();
151: }
152:
153: public byte[] getEncoded() throws CRLException
154: {
155: return (byte[]) encoded.clone();
156: }
157:
158: public void verify(PublicKey key)
159: throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
160: NoSuchProviderException, SignatureException
161: {
162: Signature sig = Signature.getInstance(sigAlg.toString());
163: doVerify(sig, key);
164: }
165:
166: public void verify(PublicKey key, String provider)
167: throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
168: NoSuchProviderException, SignatureException
169: {
170: Signature sig = Signature.getInstance(sigAlg.toString(), provider);
171: doVerify(sig, key);
172: }
173:
174: public int getVersion()
175: {
176: return version;
177: }
178:
179: public Principal getIssuerDN()
180: {
181: return issuerDN;
182: }
183:
184: public X500Principal getIssuerX500Principal()
185: {
186: return new X500Principal(issuerDN.getDer());
187: }
188:
189: public Date getThisUpdate()
190: {
191: return (Date) thisUpdate.clone();
192: }
193:
194: public Date getNextUpdate()
195: {
196: if (nextUpdate != null)
197: return (Date) nextUpdate.clone();
198: return null;
199: }
200:
201: public java.security.cert.X509CRLEntry getRevokedCertificate(BigInteger serialNo)
202: {
203: return (java.security.cert.X509CRLEntry) revokedCerts.get(serialNo);
204: }
205:
206: public Set getRevokedCertificates()
207: {
208: return Collections.unmodifiableSet(new HashSet(revokedCerts.values()));
209: }
210:
211: public byte[] getTBSCertList() throws CRLException
212: {
213: return (byte[]) tbsCRLBytes.clone();
214: }
215:
216: public byte[] getSignature()
217: {
218: return (byte[]) rawSig.clone();
219: }
220:
221: public String getSigAlgName()
222: {
223: if (sigAlg.equals(ID_DSA_WITH_SHA1))
224: return "SHA1withDSA";
225: if (sigAlg.equals(ID_RSA_WITH_MD2))
226: return "MD2withRSA";
227: if (sigAlg.equals(ID_RSA_WITH_MD5))
228: return "MD5withRSA";
229: if (sigAlg.equals(ID_RSA_WITH_SHA1))
230: return "SHA1withRSA";
231: return "unknown";
232: }
233:
234: public String getSigAlgOID()
235: {
236: return sigAlg.toString();
237: }
238:
239: public byte[] getSigAlgParams()
240: {
241: if (sigAlgParams != null)
242: return (byte[]) sigAlgParams.clone();
243: return null;
244: }
245:
246:
247:
248:
249: public boolean hasUnsupportedCriticalExtension()
250: {
251: for (Iterator it = extensions.values().iterator(); it.hasNext(); )
252: {
253: Extension e = (Extension) it.next();
254: if (e.isCritical() && !e.isSupported())
255: return true;
256: }
257: return false;
258: }
259:
260: public Set getCriticalExtensionOIDs()
261: {
262: HashSet s = new HashSet();
263: for (Iterator it = extensions.values().iterator(); it.hasNext(); )
264: {
265: Extension e = (Extension) it.next();
266: if (e.isCritical())
267: s.add(e.getOid().toString());
268: }
269: return Collections.unmodifiableSet(s);
270: }
271:
272: public Set getNonCriticalExtensionOIDs()
273: {
274: HashSet s = new HashSet();
275: for (Iterator it = extensions.values().iterator(); it.hasNext(); )
276: {
277: Extension e = (Extension) it.next();
278: if (!e.isCritical())
279: s.add(e.getOid().toString());
280: }
281: return Collections.unmodifiableSet(s);
282: }
283:
284: public byte[] getExtensionValue(String oid)
285: {
286: Extension e = getExtension(new OID(oid));
287: if (e != null)
288: {
289: return e.getValue().getEncoded();
290: }
291: return null;
292: }
293:
294:
295:
296:
297: public Extension getExtension(OID oid)
298: {
299: return (Extension) extensions.get(oid);
300: }
301:
302: public Collection getExtensions()
303: {
304: return extensions.values();
305: }
306:
307:
308:
309:
310: public String toString()
311: {
312: return X509CRL.class.getName();
313: }
314:
315: public boolean isRevoked(Certificate cert)
316: {
317: if (!(cert instanceof java.security.cert.X509Certificate))
318: throw new IllegalArgumentException("not a X.509 certificate");
319: BigInteger certSerial =
320: ((java.security.cert.X509Certificate) cert).getSerialNumber();
321: X509CRLEntry ent = (X509CRLEntry) revokedCerts.get(certSerial);
322: if (ent == null)
323: return false;
324: return ent.getRevocationDate().compareTo(new Date()) < 0;
325: }
326:
327:
328:
329:
330: private void doVerify(Signature sig, PublicKey key)
331: throws CRLException, InvalidKeyException, SignatureException
332: {
333: sig.initVerify(key);
334: sig.update(tbsCRLBytes);
335: if (!sig.verify(signature))
336: throw new CRLException("signature not verified");
337: }
338:
339: private void parse(InputStream in) throws Exception
340: {
341:
342: DERReader der = new DERReader(in);
343: DERValue val = der.read();
344: if (Configuration.DEBUG)
345: log.fine("start CertificateList len == " + val.getLength());
346: if (!val.isConstructed())
347: throw new IOException("malformed CertificateList");
348: encoded = val.getEncoded();
349:
350:
351: val = der.read();
352: if (!val.isConstructed())
353: throw new IOException("malformed TBSCertList");
354: if (Configuration.DEBUG)
355: log.fine("start tbsCertList len == " + val.getLength());
356: tbsCRLBytes = val.getEncoded();
357:
358:
359:
360: val = der.read();
361: if (val.getValue() instanceof BigInteger)
362: {
363: version = ((BigInteger) val.getValue()).intValue() + 1;
364: val = der.read();
365: }
366: else
367: version = 1;
368: if (Configuration.DEBUG)
369: log.fine("read version == " + version);
370:
371:
372: if (Configuration.DEBUG)
373: log.fine("start AlgorithmIdentifier len == " + val.getLength());
374: if (!val.isConstructed())
375: throw new IOException("malformed AlgorithmIdentifier");
376: DERValue algIdVal = der.read();
377: algId = (OID) algIdVal.getValue();
378: if (Configuration.DEBUG)
379: log.fine("read object identifier == " + algId);
380: if (val.getLength() > algIdVal.getEncodedLength())
381: {
382: val = der.read();
383: if (Configuration.DEBUG)
384: log.fine("read parameters len == " + val.getEncodedLength());
385: algParams = val.getEncoded();
386: if (val.isConstructed())
387: in.skip(val.getLength());
388: }
389:
390:
391: val = der.read();
392: issuerDN = new X500DistinguishedName(val.getEncoded());
393: der.skip(val.getLength());
394: if (Configuration.DEBUG)
395: log.fine("read issuer == " + issuerDN);
396:
397:
398: thisUpdate = (Date) der.read().getValue();
399: if (Configuration.DEBUG)
400: log.fine("read thisUpdate == " + thisUpdate);
401:
402:
403: val = der.read();
404: if (val.getValue() instanceof Date)
405: {
406: nextUpdate = (Date) val.getValue();
407: if (Configuration.DEBUG)
408: log.fine("read nextUpdate == " + nextUpdate);
409: val = der.read();
410: }
411:
412:
413:
414:
415: if (val.getTag() != 0)
416: {
417: int len = 0;
418: while (len < val.getLength())
419: {
420: X509CRLEntry entry = new X509CRLEntry(version, der);
421: revokedCerts.put(entry.getSerialNumber(), entry);
422: len += entry.getEncoded().length;
423: }
424: val = der.read();
425: }
426:
427:
428:
429: if (val.getTagClass() != DER.UNIVERSAL && val.getTag() == 0)
430: {
431: if (version < 2)
432: throw new IOException("extra data in CRL");
433: DERValue exts = der.read();
434: if (!exts.isConstructed())
435: throw new IOException("malformed Extensions");
436: if (Configuration.DEBUG)
437: log.fine("start Extensions len == " + exts.getLength());
438: int len = 0;
439: while (len < exts.getLength())
440: {
441: DERValue ext = der.read();
442: if (!ext.isConstructed())
443: throw new IOException("malformed Extension");
444: Extension e = new Extension(ext.getEncoded());
445: extensions.put(e.getOid(), e);
446: der.skip(ext.getLength());
447: len += ext.getEncodedLength();
448: if (Configuration.DEBUG)
449: log.fine("current count == " + len);
450: }
451: val = der.read();
452: }
453:
454: if (Configuration.DEBUG)
455: log.fine("read tag == " + val.getTag());
456: if (!val.isConstructed())
457: throw new IOException("malformed AlgorithmIdentifier");
458: if (Configuration.DEBUG)
459: log.fine("start AlgorithmIdentifier len == " + val.getLength());
460: DERValue sigAlgVal = der.read();
461: if (Configuration.DEBUG)
462: log.fine("read tag == " + sigAlgVal.getTag());
463: if (sigAlgVal.getTag() != DER.OBJECT_IDENTIFIER)
464: throw new IOException("malformed AlgorithmIdentifier");
465: sigAlg = (OID) sigAlgVal.getValue();
466: if (Configuration.DEBUG)
467: {
468: log.fine("signature id == " + sigAlg);
469: log.fine("sigAlgVal length == " + sigAlgVal.getEncodedLength());
470: }
471: if (val.getLength() > sigAlgVal.getEncodedLength())
472: {
473: val = der.read();
474: if (Configuration.DEBUG)
475: log.fine("sig params tag = " + val.getTag() + " len == "
476: + val.getEncodedLength());
477: sigAlgParams = (byte[]) val.getEncoded();
478: if (val.isConstructed())
479: in.skip(val.getLength());
480: }
481: val = der.read();
482: if (Configuration.DEBUG)
483: log.fine("read tag = " + val.getTag());
484: rawSig = val.getEncoded();
485: signature = ((BitString) val.getValue()).toByteArray();
486: }
487: }