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