Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / gnu / java / security / x509 / X509CRL.java
blob33263af43254fd5a61dcc85a6b7ec4e1f2f89cfb
1 /* X509CRL.java -- X.509 certificate revocation list.
2 Copyright (C) 2003, 2004 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.java.security.x509;
41 import gnu.java.security.OID;
42 import gnu.java.security.der.BitString;
43 import gnu.java.security.der.DER;
44 import gnu.java.security.der.DERReader;
45 import gnu.java.security.der.DERValue;
46 import gnu.java.security.x509.ext.Extension;
48 import java.io.InputStream;
49 import java.io.IOException;
50 import java.math.BigInteger;
51 import java.security.InvalidKeyException;
52 import java.security.NoSuchAlgorithmException;
53 import java.security.NoSuchProviderException;
54 import java.security.PublicKey;
55 import java.security.Principal;
56 import java.security.Signature;
57 import java.security.SignatureException;
58 import java.security.cert.Certificate;
59 import java.security.cert.CRLException;
60 import java.util.Collection;
61 import java.util.Collections;
62 import java.util.Date;
63 import java.util.HashSet;
64 import java.util.HashMap;
65 import java.util.Iterator;
66 import java.util.Set;
68 import javax.security.auth.x500.X500Principal;
70 /**
71 * X.509 certificate revocation lists.
73 * @author Casey Marshall (rsdio@metastatic.org)
75 public class X509CRL extends java.security.cert.X509CRL
76 implements GnuPKIExtension
79 // Constants and fields.
80 // ------------------------------------------------------------------------
82 private static final boolean DEBUG = false;
83 private static void debug(String msg)
85 if (DEBUG)
87 System.err.print(">> X509CRL: ");
88 System.err.println(msg);
92 private static final OID ID_DSA = new OID("1.2.840.10040.4.1");
93 private static final OID ID_DSA_WITH_SHA1 = new OID("1.2.840.10040.4.3");
94 private static final OID ID_RSA = new OID("1.2.840.113549.1.1.1");
95 private static final OID ID_RSA_WITH_MD2 = new OID("1.2.840.113549.1.1.2");
96 private static final OID ID_RSA_WITH_MD5 = new OID("1.2.840.113549.1.1.4");
97 private static final OID ID_RSA_WITH_SHA1 = new OID("1.2.840.113549.1.1.5");
99 private byte[] encoded;
101 private byte[] tbsCRLBytes;
102 private int version;
103 private OID algId;
104 private byte[] algParams;
105 private Date thisUpdate;
106 private Date nextUpdate;
107 private X500DistinguishedName issuerDN;
108 private HashMap revokedCerts;
109 private HashMap extensions;
111 private OID sigAlg;
112 private byte[] sigAlgParams;
113 private byte[] rawSig;
114 private byte[] signature;
116 // Constructors.
117 // ------------------------------------------------------------------------
120 * Create a new X.509 CRL.
122 * @param encoded The DER encoded CRL.
123 * @throws CRLException If the input bytes are incorrect.
124 * @throws IOException If the input bytes cannot be read.
126 public X509CRL(InputStream encoded) throws CRLException, IOException
128 super();
129 revokedCerts = new HashMap();
130 extensions = new HashMap();
133 parse(encoded);
135 catch (IOException ioe)
137 ioe.printStackTrace();
138 throw ioe;
140 catch (Exception x)
142 x.printStackTrace();
143 throw new CRLException(x.toString());
147 // X509CRL methods.
148 // ------------------------------------------------------------------------
150 public boolean equals(Object o)
152 if (!(o instanceof X509CRL))
153 return false;
154 return ((X509CRL) o).getRevokedCertificates().equals(revokedCerts.values());
157 public int hashCode()
159 return revokedCerts.hashCode();
162 public byte[] getEncoded() throws CRLException
164 return (byte[]) encoded.clone();
167 public void verify(PublicKey key)
168 throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
169 NoSuchProviderException, SignatureException
171 Signature sig = Signature.getInstance(sigAlg.toString());
172 doVerify(sig, key);
175 public void verify(PublicKey key, String provider)
176 throws CRLException, NoSuchAlgorithmException, InvalidKeyException,
177 NoSuchProviderException, SignatureException
179 Signature sig = Signature.getInstance(sigAlg.toString(), provider);
180 doVerify(sig, key);
183 public int getVersion()
185 return version;
188 public Principal getIssuerDN()
190 return issuerDN;
193 public X500Principal getIssuerX500Principal()
195 return new X500Principal(issuerDN.getDer());
198 public Date getThisUpdate()
200 return (Date) thisUpdate.clone();
203 public Date getNextUpdate()
205 if (nextUpdate != null)
206 return (Date) nextUpdate.clone();
207 return null;
210 public java.security.cert.X509CRLEntry getRevokedCertificate(BigInteger serialNo)
212 return (java.security.cert.X509CRLEntry) revokedCerts.get(serialNo);
215 public Set getRevokedCertificates()
217 return Collections.unmodifiableSet(new HashSet(revokedCerts.values()));
220 public byte[] getTBSCertList() throws CRLException
222 return (byte[]) tbsCRLBytes.clone();
225 public byte[] getSignature()
227 return (byte[]) rawSig.clone();
230 public String getSigAlgName()
232 if (sigAlg.equals(ID_DSA_WITH_SHA1))
233 return "SHA1withDSA";
234 if (sigAlg.equals(ID_RSA_WITH_MD2))
235 return "MD2withRSA";
236 if (sigAlg.equals(ID_RSA_WITH_MD5))
237 return "MD5withRSA";
238 if (sigAlg.equals(ID_RSA_WITH_SHA1))
239 return "SHA1withRSA";
240 return "unknown";
243 public String getSigAlgOID()
245 return sigAlg.toString();
248 public byte[] getSigAlgParams()
250 if (sigAlgParams != null)
251 return (byte[]) sigAlgParams.clone();
252 return null;
255 // X509Extension methods.
256 // ------------------------------------------------------------------------
258 public boolean hasUnsupportedCriticalExtension()
260 for (Iterator it = extensions.values().iterator(); it.hasNext(); )
262 Extension e = (Extension) it.next();
263 if (e.isCritical() && !e.isSupported())
264 return true;
266 return false;
269 public Set getCriticalExtensionOIDs()
271 HashSet s = new HashSet();
272 for (Iterator it = extensions.values().iterator(); it.hasNext(); )
274 Extension e = (Extension) it.next();
275 if (e.isCritical())
276 s.add(e.getOid().toString());
278 return Collections.unmodifiableSet(s);
281 public Set getNonCriticalExtensionOIDs()
283 HashSet s = new HashSet();
284 for (Iterator it = extensions.values().iterator(); it.hasNext(); )
286 Extension e = (Extension) it.next();
287 if (!e.isCritical())
288 s.add(e.getOid().toString());
290 return Collections.unmodifiableSet(s);
293 public byte[] getExtensionValue(String oid)
295 Extension e = getExtension(new OID(oid));
296 if (e != null)
298 return e.getValue().getEncoded();
300 return null;
303 // GnuPKIExtension method.
304 // -------------------------------------------------------------------------
306 public Extension getExtension(OID oid)
308 return (Extension) extensions.get(oid);
311 public Collection getExtensions()
313 return extensions.values();
316 // CRL methods.
317 // -------------------------------------------------------------------------
319 public String toString()
321 return X509CRL.class.getName();
324 public boolean isRevoked(Certificate cert)
326 if (!(cert instanceof java.security.cert.X509Certificate))
327 throw new IllegalArgumentException("not a X.509 certificate");
328 BigInteger certSerial =
329 ((java.security.cert.X509Certificate) cert).getSerialNumber();
330 X509CRLEntry ent = (X509CRLEntry) revokedCerts.get(certSerial);
331 if (ent == null)
332 return false;
333 return ent.getRevocationDate().compareTo(new Date()) < 0;
336 // Own methods.
337 // ------------------------------------------------------------------------
339 private void doVerify(Signature sig, PublicKey key)
340 throws CRLException, InvalidKeyException, SignatureException
342 sig.initVerify(key);
343 sig.update(tbsCRLBytes);
344 if (!sig.verify(signature))
345 throw new CRLException("signature not verified");
348 private void parse(InputStream in) throws Exception
350 // CertificateList ::= SEQUENCE {
351 DERReader der = new DERReader(in);
352 DERValue val = der.read();
353 debug("start CertificateList len == " + val.getLength());
354 if (!val.isConstructed())
355 throw new IOException("malformed CertificateList");
356 encoded = val.getEncoded();
358 // tbsCertList ::= SEQUENCE { -- TBSCertList
359 val = der.read();
360 if (!val.isConstructed())
361 throw new IOException("malformed TBSCertList");
362 debug("start tbsCertList len == " + val.getLength());
363 tbsCRLBytes = val.getEncoded();
365 // version Version OPTIONAL,
366 // -- If present must be v2
367 val = der.read();
368 if (val.getValue() instanceof BigInteger)
370 version = ((BigInteger) val.getValue()).intValue() + 1;
371 val = der.read();
373 else
374 version = 1;
375 debug("read version == " + version);
377 // signature AlgorithmIdentifier,
378 debug("start AlgorithmIdentifier len == " + val.getLength());
379 if (!val.isConstructed())
380 throw new IOException("malformed AlgorithmIdentifier");
381 DERValue algIdVal = der.read();
382 algId = (OID) algIdVal.getValue();
383 debug("read object identifier == " + algId);
384 if (val.getLength() > algIdVal.getEncodedLength())
386 val = der.read();
387 debug("read parameters len == " + val.getEncodedLength());
388 algParams = val.getEncoded();
389 if (val.isConstructed())
390 in.skip(val.getLength());
393 // issuer Name,
394 val = der.read();
395 issuerDN = new X500DistinguishedName(val.getEncoded());
396 der.skip(val.getLength());
397 debug("read issuer == " + issuerDN);
399 // thisUpdate Time,
400 thisUpdate = (Date) der.read().getValue();
401 debug("read thisUpdate == " + thisUpdate);
403 // nextUpdate Time OPTIONAL,
404 val = der.read();
405 if (val.getValue() instanceof Date)
407 nextUpdate = (Date) val.getValue();
408 debug("read nextUpdate == " + nextUpdate);
409 val = der.read();
412 // revokedCertificates SEQUENCE OF SEQUENCE {
413 // -- X509CRLEntry objects...
414 // } OPTIONAL,
415 if (val.getTag() != 0)
417 int len = 0;
418 while (len < val.getLength())
420 X509CRLEntry entry = new X509CRLEntry(version, der);
421 revokedCerts.put(entry.getSerialNumber(), entry);
422 len += entry.getEncoded().length;
424 val = der.read();
427 // crlExtensions [0] EXPLICIT Extensions OPTIONAL
428 // -- if present MUST be v2
429 if (val.getTagClass() != DER.UNIVERSAL && val.getTag() == 0)
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 debug("start Extensions len == " + exts.getLength());
437 int len = 0;
438 while (len < exts.getLength())
440 DERValue ext = der.read();
441 if (!ext.isConstructed())
442 throw new IOException("malformed Extension");
443 Extension e = new Extension(ext.getEncoded());
444 extensions.put(e.getOid(), e);
445 der.skip(ext.getLength());
446 len += ext.getEncodedLength();
447 debug("current count == " + len);
449 val = der.read();
452 debug("read tag == " + val.getTag());
453 if (!val.isConstructed())
454 throw new IOException("malformed AlgorithmIdentifier");
455 debug("start AlgorithmIdentifier len == " + val.getLength());
456 DERValue sigAlgVal = der.read();
457 debug("read tag == " + sigAlgVal.getTag());
458 if (sigAlgVal.getTag() != DER.OBJECT_IDENTIFIER)
459 throw new IOException("malformed AlgorithmIdentifier");
460 sigAlg = (OID) sigAlgVal.getValue();
461 debug("signature id == " + sigAlg);
462 debug("sigAlgVal length == " + sigAlgVal.getEncodedLength());
463 if (val.getLength() > sigAlgVal.getEncodedLength())
465 val = der.read();
466 debug("sig params tag = " + val.getTag() + " len == " + val.getEncodedLength());
467 sigAlgParams = (byte[]) val.getEncoded();
468 if (val.isConstructed())
469 in.skip(val.getLength());
471 val = der.read();
472 debug("read tag = " + val.getTag());
473 rawSig = val.getEncoded();
474 signature = ((BitString) val.getValue()).toByteArray();