1 package org.bouncycastle.x509;
2 
3 import java.io.IOException;
4 import java.math.BigInteger;
5 import java.security.GeneralSecurityException;
6 import java.security.InvalidKeyException;
7 import java.security.NoSuchAlgorithmException;
8 import java.security.NoSuchProviderException;
9 import java.security.PrivateKey;
10 import java.security.SecureRandom;
11 import java.security.SignatureException;
12 import java.security.cert.CRLException;
13 import java.security.cert.X509CRL;
14 import java.security.cert.X509CRLEntry;
15 import java.util.Date;
16 import java.util.Iterator;
17 import java.util.Set;
18 
19 import javax.security.auth.x500.X500Principal;
20 
21 import org.bouncycastle.asn1.ASN1Encodable;
22 import org.bouncycastle.asn1.ASN1EncodableVector;
23 import org.bouncycastle.asn1.ASN1GeneralizedTime;
24 import org.bouncycastle.asn1.ASN1InputStream;
25 import org.bouncycastle.asn1.ASN1Integer;
26 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
27 import org.bouncycastle.asn1.ASN1Sequence;
28 import org.bouncycastle.asn1.DERBitString;
29 import org.bouncycastle.asn1.DERSequence;
30 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
31 import org.bouncycastle.asn1.x509.CertificateList;
32 import org.bouncycastle.asn1.x509.Extensions;
33 import org.bouncycastle.asn1.x509.TBSCertList;
34 import org.bouncycastle.asn1.x509.Time;
35 import org.bouncycastle.asn1.x509.V2TBSCertListGenerator;
36 import org.bouncycastle.asn1.x509.X509Extensions;
37 import org.bouncycastle.asn1.x509.X509ExtensionsGenerator;
38 import org.bouncycastle.asn1.x509.X509Name;
39 import org.bouncycastle.jcajce.util.BCJcaJceHelper;
40 import org.bouncycastle.jcajce.util.JcaJceHelper;
41 import org.bouncycastle.jce.X509Principal;
42 import org.bouncycastle.jce.provider.X509CRLObject;
43 
44 /**
45  * class to produce an X.509 Version 2 CRL.
46  *  @deprecated use org.bouncycastle.cert.X509v2CRLBuilder.
47  */
48 public class X509V2CRLGenerator
49 {
50     private final JcaJceHelper bcHelper = new BCJcaJceHelper(); // needed to force provider loading
51 
52     private V2TBSCertListGenerator      tbsGen;
53     private ASN1ObjectIdentifier         sigOID;
54     private AlgorithmIdentifier         sigAlgId;
55     private String                      signatureAlgorithm;
56     private X509ExtensionsGenerator     extGenerator;
57 
X509V2CRLGenerator()58     public X509V2CRLGenerator()
59     {
60         tbsGen = new V2TBSCertListGenerator();
61         extGenerator = new X509ExtensionsGenerator();
62     }
63 
64     /**
65      * reset the generator
66      */
reset()67     public void reset()
68     {
69         tbsGen = new V2TBSCertListGenerator();
70         extGenerator.reset();
71     }
72 
73     /**
74      * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
75      * certificate.
76      */
setIssuerDN( X500Principal issuer)77     public void setIssuerDN(
78         X500Principal   issuer)
79     {
80         try
81         {
82             tbsGen.setIssuer(new X509Principal(issuer.getEncoded()));
83         }
84         catch (IOException e)
85         {
86             throw new IllegalArgumentException("can't process principal: " + e);
87         }
88     }
89 
90     /**
91      * Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
92      * certificate.
93      */
setIssuerDN( X509Name issuer)94     public void setIssuerDN(
95         X509Name   issuer)
96     {
97         tbsGen.setIssuer(issuer);
98     }
99 
setThisUpdate( Date date)100     public void setThisUpdate(
101         Date    date)
102     {
103         tbsGen.setThisUpdate(new Time(date));
104     }
105 
setNextUpdate( Date date)106     public void setNextUpdate(
107         Date    date)
108     {
109         tbsGen.setNextUpdate(new Time(date));
110     }
111 
112     /**
113      * Reason being as indicated by CRLReason, i.e. CRLReason.keyCompromise
114      * or 0 if CRLReason is not to be used
115      **/
addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason)116     public void addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason)
117     {
118         tbsGen.addCRLEntry(new ASN1Integer(userCertificate), new Time(revocationDate), reason);
119     }
120 
121     /**
122      * Add a CRL entry with an Invalidity Date extension as well as a CRLReason extension.
123      * Reason being as indicated by CRLReason, i.e. CRLReason.keyCompromise
124      * or 0 if CRLReason is not to be used
125      **/
addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason, Date invalidityDate)126     public void addCRLEntry(BigInteger userCertificate, Date revocationDate, int reason, Date invalidityDate)
127     {
128         tbsGen.addCRLEntry(new ASN1Integer(userCertificate), new Time(revocationDate), reason, new ASN1GeneralizedTime(invalidityDate));
129     }
130 
131     /**
132      * Add a CRL entry with extensions.
133      **/
addCRLEntry(BigInteger userCertificate, Date revocationDate, X509Extensions extensions)134     public void addCRLEntry(BigInteger userCertificate, Date revocationDate, X509Extensions extensions)
135     {
136         tbsGen.addCRLEntry(new ASN1Integer(userCertificate), new Time(revocationDate), Extensions.getInstance(extensions));
137     }
138 
139     /**
140      * Add the CRLEntry objects contained in a previous CRL.
141      *
142      * @param other the X509CRL to source the other entries from.
143      */
addCRL(X509CRL other)144     public void addCRL(X509CRL other)
145         throws CRLException
146     {
147         Set revocations = other.getRevokedCertificates();
148 
149         if (revocations != null)
150         {
151             Iterator it = revocations.iterator();
152             while (it.hasNext())
153             {
154                 X509CRLEntry entry = (X509CRLEntry)it.next();
155 
156                 ASN1InputStream aIn = new ASN1InputStream(entry.getEncoded());
157 
158                 try
159                 {
160                     tbsGen.addCRLEntry(ASN1Sequence.getInstance(aIn.readObject()));
161                 }
162                 catch (IOException e)
163                 {
164                     throw new CRLException("exception processing encoding of CRL: " + e.toString());
165                 }
166             }
167         }
168     }
169 
170     /**
171      * Set the signature algorithm. This can be either a name or an OID, names
172      * are treated as case insensitive.
173      *
174      * @param signatureAlgorithm string representation of the algorithm name.
175      */
setSignatureAlgorithm( String signatureAlgorithm)176     public void setSignatureAlgorithm(
177         String  signatureAlgorithm)
178     {
179         this.signatureAlgorithm = signatureAlgorithm;
180 
181         try
182         {
183             sigOID = X509Util.getAlgorithmOID(signatureAlgorithm);
184         }
185         catch (Exception e)
186         {
187             throw new IllegalArgumentException("Unknown signature type requested");
188         }
189 
190         sigAlgId = X509Util.getSigAlgID(sigOID, signatureAlgorithm);
191 
192         tbsGen.setSignature(sigAlgId);
193     }
194 
195     /**
196      * add a given extension field for the standard extensions tag (tag 0)
197      */
addExtension( String oid, boolean critical, ASN1Encodable value)198     public void addExtension(
199         String          oid,
200         boolean         critical,
201         ASN1Encodable    value)
202     {
203         this.addExtension(new ASN1ObjectIdentifier(oid), critical, value);
204     }
205 
206     /**
207      * add a given extension field for the standard extensions tag (tag 0)
208      */
addExtension( ASN1ObjectIdentifier oid, boolean critical, ASN1Encodable value)209     public void addExtension(
210         ASN1ObjectIdentifier oid,
211         boolean             critical,
212         ASN1Encodable value)
213     {
214         extGenerator.addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value);
215     }
216 
217     /**
218      * add a given extension field for the standard extensions tag (tag 0)
219      */
addExtension( String oid, boolean critical, byte[] value)220     public void addExtension(
221         String          oid,
222         boolean         critical,
223         byte[]          value)
224     {
225         this.addExtension(new ASN1ObjectIdentifier(oid), critical, value);
226     }
227 
228     /**
229      * add a given extension field for the standard extensions tag (tag 0)
230      */
addExtension( ASN1ObjectIdentifier oid, boolean critical, byte[] value)231     public void addExtension(
232         ASN1ObjectIdentifier oid,
233         boolean             critical,
234         byte[]              value)
235     {
236         extGenerator.addExtension(new ASN1ObjectIdentifier(oid.getId()), critical, value);
237     }
238 
239     /**
240      * generate an X509 CRL, based on the current issuer and subject
241      * using the default provider "BC".
242      * @deprecated use generate(key, "BC")
243      */
generateX509CRL( PrivateKey key)244     public X509CRL generateX509CRL(
245         PrivateKey      key)
246         throws SecurityException, SignatureException, InvalidKeyException
247     {
248         try
249         {
250             return generateX509CRL(key, "BC", null);
251         }
252         catch (NoSuchProviderException e)
253         {
254             throw new SecurityException("BC provider not installed!");
255         }
256     }
257 
258     /**
259      * generate an X509 CRL, based on the current issuer and subject
260      * using the default provider "BC" and an user defined SecureRandom object as
261      * source of randomness.
262      * @deprecated use generate(key, random, "BC")
263      */
generateX509CRL( PrivateKey key, SecureRandom random)264     public X509CRL generateX509CRL(
265         PrivateKey      key,
266         SecureRandom    random)
267         throws SecurityException, SignatureException, InvalidKeyException
268     {
269         try
270         {
271             return generateX509CRL(key, "BC", random);
272         }
273         catch (NoSuchProviderException e)
274         {
275             throw new SecurityException("BC provider not installed!");
276         }
277     }
278 
279     /**
280      * generate an X509 certificate, based on the current issuer and subject
281      * using the passed in provider for the signing.
282      * @deprecated use generate()
283      */
generateX509CRL( PrivateKey key, String provider)284     public X509CRL generateX509CRL(
285         PrivateKey      key,
286         String          provider)
287         throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
288     {
289         return generateX509CRL(key, provider, null);
290     }
291 
292     /**
293      * generate an X509 CRL, based on the current issuer and subject,
294      * using the passed in provider for the signing.
295      * @deprecated use generate()
296      */
generateX509CRL( PrivateKey key, String provider, SecureRandom random)297     public X509CRL generateX509CRL(
298         PrivateKey      key,
299         String          provider,
300         SecureRandom    random)
301         throws NoSuchProviderException, SecurityException, SignatureException, InvalidKeyException
302     {
303         try
304         {
305             return generate(key, provider, random);
306         }
307         catch (NoSuchProviderException e)
308         {
309             throw e;
310         }
311         catch (SignatureException e)
312         {
313             throw e;
314         }
315         catch (InvalidKeyException e)
316         {
317             throw e;
318         }
319         catch (GeneralSecurityException e)
320         {
321             throw new SecurityException("exception: " + e);
322         }
323     }
324 
325     /**
326      * generate an X509 CRL, based on the current issuer and subject
327      * using the default provider.
328      * <p>
329      * <b>Note:</b> this differs from the deprecated method in that the default provider is
330      * used - not "BC".
331      * </p>
332      */
generate( PrivateKey key)333     public X509CRL generate(
334         PrivateKey      key)
335         throws CRLException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
336     {
337         return generate(key, (SecureRandom)null);
338     }
339 
340     /**
341      * generate an X509 CRL, based on the current issuer and subject
342      * using the default provider and an user defined SecureRandom object as
343      * source of randomness.
344      * <p>
345      * <b>Note:</b> this differs from the deprecated method in that the default provider is
346      * used - not "BC".
347      * </p>
348      */
generate( PrivateKey key, SecureRandom random)349     public X509CRL generate(
350         PrivateKey      key,
351         SecureRandom    random)
352         throws CRLException, IllegalStateException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
353     {
354         TBSCertList tbsCrl = generateCertList();
355         byte[] signature;
356 
357         try
358         {
359             signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, key, random, tbsCrl);
360         }
361         catch (IOException e)
362         {
363             throw new ExtCRLException("cannot generate CRL encoding", e);
364         }
365 
366         return generateJcaObject(tbsCrl, signature);
367     }
368 
369     /**
370      * generate an X509 certificate, based on the current issuer and subject
371      * using the passed in provider for the signing.
372      */
generate( PrivateKey key, String provider)373     public X509CRL generate(
374         PrivateKey      key,
375         String          provider)
376         throws CRLException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
377     {
378         return generate(key, provider, null);
379     }
380 
381     /**
382      * generate an X509 CRL, based on the current issuer and subject,
383      * using the passed in provider for the signing.
384      */
generate( PrivateKey key, String provider, SecureRandom random)385     public X509CRL generate(
386         PrivateKey      key,
387         String          provider,
388         SecureRandom    random)
389         throws CRLException, IllegalStateException, NoSuchProviderException, NoSuchAlgorithmException, SignatureException, InvalidKeyException
390     {
391         TBSCertList tbsCrl = generateCertList();
392         byte[] signature;
393 
394         try
395         {
396             signature = X509Util.calculateSignature(sigOID, signatureAlgorithm, provider, key, random, tbsCrl);
397         }
398         catch (IOException e)
399         {
400             throw new ExtCRLException("cannot generate CRL encoding", e);
401         }
402 
403         return generateJcaObject(tbsCrl, signature);
404     }
405 
generateCertList()406     private TBSCertList generateCertList()
407     {
408         if (!extGenerator.isEmpty())
409         {
410             tbsGen.setExtensions(extGenerator.generate());
411         }
412 
413         return tbsGen.generateTBSCertList();
414     }
415 
generateJcaObject(TBSCertList tbsCrl, byte[] signature)416     private X509CRL generateJcaObject(TBSCertList tbsCrl, byte[] signature)
417         throws CRLException
418     {
419         ASN1EncodableVector v = new ASN1EncodableVector();
420 
421         v.add(tbsCrl);
422         v.add(sigAlgId);
423         v.add(new DERBitString(signature));
424 
425         return new X509CRLObject(new CertificateList(new DERSequence(v)));
426     }
427 
428     /**
429      * Return an iterator of the signature names supported by the generator.
430      *
431      * @return an iterator containing recognised names.
432      */
getSignatureAlgNames()433     public Iterator getSignatureAlgNames()
434     {
435         return X509Util.getAlgNames();
436     }
437 
438     private static class ExtCRLException
439         extends CRLException
440     {
441         Throwable cause;
442 
ExtCRLException(String message, Throwable cause)443         ExtCRLException(String message, Throwable cause)
444         {
445             super(message);
446             this.cause = cause;
447         }
448 
getCause()449         public Throwable getCause()
450         {
451             return cause;
452         }
453     }
454 }
455