View Javadoc

1   /**
2    *
3    *  Licensed to the Apache Software Foundation (ASF) under one or more
4    *  contributor license agreements.  See the NOTICE file distributed with
5    *  this work for additional information regarding copyright ownership.
6    *  The ASF licenses this file to You under the Apache License, Version 2.0
7    *  (the "License"); you may not use this file except in compliance with
8    *  the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing, software
13   *  distributed under the License is distributed on an "AS IS" BASIS,
14   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   *  See the License for the specific language governing permissions and
16   *  limitations under the License.
17   */
18  
19  package org.apache.geronimo.util.jce.provider;
20  
21  import java.io.ByteArrayOutputStream;
22  import java.io.IOException;
23  import java.math.BigInteger;
24  import java.security.InvalidKeyException;
25  import java.security.NoSuchAlgorithmException;
26  import java.security.NoSuchProviderException;
27  import java.security.Principal;
28  import java.security.Provider;
29  import java.security.PublicKey;
30  import java.security.Security;
31  import java.security.Signature;
32  import java.security.SignatureException;
33  import java.security.cert.CRLException;
34  import java.security.cert.Certificate;
35  import java.security.cert.X509CRL;
36  import java.security.cert.X509CRLEntry;
37  import java.security.cert.X509Certificate;
38  import java.util.Date;
39  import java.util.Enumeration;
40  import java.util.HashSet;
41  import java.util.Set;
42  
43  import javax.security.auth.x500.X500Principal;
44  
45  import org.apache.geronimo.util.asn1.ASN1OutputStream;
46  import org.apache.geronimo.util.asn1.DERObjectIdentifier;
47  import org.apache.geronimo.util.asn1.DEROutputStream;
48  import org.apache.geronimo.util.asn1.x509.CertificateList;
49  import org.apache.geronimo.util.asn1.x509.TBSCertList;
50  import org.apache.geronimo.util.asn1.x509.X509Extension;
51  import org.apache.geronimo.util.asn1.x509.X509Extensions;
52  import org.apache.geronimo.util.jce.X509Principal;
53  
54  /**
55   * The following extensions are listed in RFC 2459 as relevant to CRLs
56   *
57   * Authority Key Identifier
58   * Issuer Alternative Name
59   * CRL Number
60   * Delta CRL Indicator (critical)
61   * Issuing Distribution Point (critical)
62   */
63  public class X509CRLObject
64      extends X509CRL
65  {
66      private CertificateList c;
67  
68      public X509CRLObject(
69          CertificateList c)
70      {
71          this.c = c;
72      }
73  
74      /**
75       * Will return true if any extensions are present and marked
76       * as critical as we currently dont handle any extensions!
77       */
78      public boolean hasUnsupportedCriticalExtension()
79      {
80          Set extns = getCriticalExtensionOIDs();
81          if ( extns != null && !extns.isEmpty() )
82          {
83              return true;
84          }
85  
86          return false;
87      }
88  
89      private Set getExtensionOIDs(boolean critical)
90      {
91          if (this.getVersion() == 2)
92          {
93              HashSet         set = new HashSet();
94              X509Extensions  extensions = c.getTBSCertList().getExtensions();
95              Enumeration     e = extensions.oids();
96  
97              while (e.hasMoreElements())
98              {
99                  DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
100                 X509Extension       ext = extensions.getExtension(oid);
101 
102                 if (critical == ext.isCritical())
103                 {
104                     set.add(oid.getId());
105                 }
106             }
107 
108             return set;
109         }
110 
111         return null;
112     }
113 
114     public Set getCriticalExtensionOIDs()
115     {
116         return getExtensionOIDs(true);
117     }
118 
119     public Set getNonCriticalExtensionOIDs()
120     {
121         return getExtensionOIDs(false);
122     }
123 
124     public byte[] getExtensionValue(String oid)
125     {
126         X509Extensions exts = c.getTBSCertList().getExtensions();
127 
128         if (exts != null)
129         {
130             X509Extension   ext = exts.getExtension(new DERObjectIdentifier(oid));
131 
132             if (ext != null)
133             {
134                 ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
135                 DEROutputStream dOut = new DEROutputStream(bOut);
136 
137                 try
138                 {
139                     dOut.writeObject(ext.getValue());
140 
141                     return bOut.toByteArray();
142                 }
143                 catch (Exception e)
144                 {
145                     throw new RuntimeException("error encoding " + e.toString());
146                 }
147             }
148         }
149 
150         return null;
151     }
152 
153     public byte[] getEncoded()
154         throws CRLException
155     {
156         ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
157         DEROutputStream            dOut = new DEROutputStream(bOut);
158 
159         try
160         {
161             dOut.writeObject(c);
162 
163             return bOut.toByteArray();
164         }
165         catch (IOException e)
166         {
167             throw new CRLException(e.toString());
168         }
169     }
170 
171     public void verify(PublicKey key)
172         throws CRLException,  NoSuchAlgorithmException,
173         InvalidKeyException, NoSuchProviderException,
174         SignatureException
175     {
176         verify(key, "BC");
177     }
178 
179     public void verify(PublicKey key, String sigProvider)
180         throws CRLException, NoSuchAlgorithmException,
181         InvalidKeyException, NoSuchProviderException,
182         SignatureException
183     {
184         if ( !c.getSignatureAlgorithm().equals(c.getTBSCertList().getSignature()) )
185         {
186             throw new CRLException("Signature algorithm on CertifcateList does not match TBSCertList.");
187         }
188 
189         Signature sig = Signature.getInstance(getSigAlgName(), sigProvider);
190 
191         sig.initVerify(key);
192         sig.update(this.getTBSCertList());
193         if ( !sig.verify(this.getSignature()) )
194         {
195             throw new SignatureException("CRL does not verify with supplied public key.");
196         }
197     }
198 
199     public int getVersion()
200     {
201         return c.getVersion();
202     }
203 
204     public Principal getIssuerDN()
205     {
206         return new X509Principal(c.getIssuer());
207     }
208 
209     public X500Principal getIssuerX500Principal()
210     {
211         try
212         {
213             ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
214             ASN1OutputStream        aOut = new ASN1OutputStream(bOut);
215 
216             aOut.writeObject(c.getIssuer());
217 
218             return new X500Principal(bOut.toByteArray());
219         }
220         catch (IOException e)
221         {
222             throw new IllegalStateException("can't encode issuer DN");
223         }
224     }
225 
226     public Date getThisUpdate()
227     {
228         return c.getThisUpdate().getDate();
229     }
230 
231     public Date getNextUpdate()
232     {
233         if (c.getNextUpdate() != null)
234         {
235             return c.getNextUpdate().getDate();
236         }
237 
238         return null;
239     }
240 
241     public X509CRLEntry getRevokedCertificate(BigInteger serialNumber)
242     {
243         TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
244 
245         if ( certs != null )
246         {
247             for ( int i = 0; i < certs.length; i++ )
248             {
249                 if ( certs[i].getUserCertificate().getValue().equals(serialNumber) ) {
250                     return new X509CRLEntryObject(certs[i]);
251                 }
252             }
253         }
254 
255         return null;
256     }
257 
258     public Set getRevokedCertificates()
259     {
260         TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
261 
262         if ( certs != null )
263         {
264             HashSet set = new HashSet();
265             for ( int i = 0; i < certs.length; i++ )
266             {
267                 set.add(new X509CRLEntryObject(certs[i]));
268 
269             }
270 
271             return set;
272         }
273 
274         return null;
275     }
276 
277     public byte[] getTBSCertList()
278         throws CRLException
279     {
280         ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
281         DEROutputStream            dOut = new DEROutputStream(bOut);
282 
283         try
284         {
285             dOut.writeObject(c.getTBSCertList());
286 
287             return bOut.toByteArray();
288         }
289         catch (IOException e)
290         {
291             throw new CRLException(e.toString());
292         }
293     }
294 
295     public byte[] getSignature()
296     {
297         return c.getSignature().getBytes();
298     }
299 
300     public String getSigAlgName()
301     {
302         Provider[] provs = Security.getProviders();
303 
304         //
305         // search every provider looking for a real algorithm
306         //
307         for (int i = 0; i != provs.length; i++)
308         {
309             String algName = provs[i].getProperty("Alg.Alias.Signature." + this.getSigAlgOID());
310             if ( algName != null )
311             {
312                 return algName;
313             }
314         }
315 
316         return this.getSigAlgOID();
317     }
318 
319     public String getSigAlgOID()
320     {
321         return c.getSignatureAlgorithm().getObjectId().getId();
322     }
323 
324     public byte[] getSigAlgParams()
325     {
326         ByteArrayOutputStream    bOut = new ByteArrayOutputStream();
327 
328         if ( c.getSignatureAlgorithm().getParameters() != null )
329         {
330             try
331             {
332                 DEROutputStream    dOut = new DEROutputStream(bOut);
333 
334                 dOut.writeObject(c.getSignatureAlgorithm().getParameters());
335             }
336             catch (Exception e)
337             {
338                 throw new RuntimeException("exception getting sig parameters " + e);
339             }
340 
341             return bOut.toByteArray();
342         }
343 
344         return null;
345     }
346 
347     /**
348      * Returns a string representation of this CRL.
349      *
350      * @return a string representation of this CRL.
351      */
352     public String toString()
353     {
354         return "X.509 CRL";
355     }
356 
357     /**
358      * Checks whether the given certificate is on this CRL.
359      *
360      * @param cert the certificate to check for.
361      * @return true if the given certificate is on this CRL,
362      * false otherwise.
363      */
364     public boolean isRevoked(Certificate cert)
365     {
366         if ( !cert.getType().equals("X.509") )
367         {
368             throw new RuntimeException("X.509 CRL used with non X.509 Cert");
369         }
370 
371         TBSCertList.CRLEntry[] certs = c.getRevokedCertificates();
372 
373         if ( certs != null )
374         {
375             BigInteger serial = ((X509Certificate)cert).getSerialNumber();
376 
377             for ( int i = 0; i < certs.length; i++ )
378             {
379                 if ( certs[i].getUserCertificate().getValue().equals(serial) )
380                 {
381                     return true;
382                 }
383             }
384         }
385 
386         return false;
387     }
388 }
389