1    package org.bouncycastle.asn1.x509;
2    
3    import java.io.*;
4    import java.util.Vector;
5    import java.util.Enumeration;
6    
7    import org.bouncycastle.asn1.*;
8    
9    /**
10    * Generator for Version 2 TBSCertList structures.
11    * <pre>
12    *  TBSCertList  ::=  SEQUENCE  {
13    *       version                 Version OPTIONAL,
14    *                                    -- if present, shall be v2
15    *       signature               AlgorithmIdentifier,
16    *       issuer                  Name,
17    *       thisUpdate              Time,
18    *       nextUpdate              Time OPTIONAL,
19    *       revokedCertificates     SEQUENCE OF SEQUENCE  {
20    *            userCertificate         CertificateSerialNumber,
21    *            revocationDate          Time,
22    *            crlEntryExtensions      Extensions OPTIONAL
23    *                                          -- if present, shall be v2
24    *                                 }  OPTIONAL,
25    *       crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
26    *                                          -- if present, shall be v2
27    *                                 }
28    * </pre>
29    *
30    * <b>Note: This class may be subject to change</b>
31    */
32   public class V2TBSCertListGenerator
33   {
34       DERInteger version = new DERInteger(1);
35   
36       AlgorithmIdentifier     signature;
37       X509Name                issuer;
38       TimeTime                thisUpdate, nextUpdate=null;
39       X509Extensions          extensions=null;
40       private Vector          crlentries=null;
41   
42       public V2TBSCertListGenerator()
43       {
44       }
45   
46   
47       public void setSignature(
48           AlgorithmIdentifier    signature)
49       {
50           this.signature = signature;
51       }
52   
53       public void setIssuer(
54           X509Name    issuer)
55       {
56           this.issuer = issuer;
57       }
58   
59       public void setThisUpdate(
60           DERUTCTime thisUpdate)
61       {
62           this.thisUpdate = new Time(thisUpdate);
63       }
64   
65       public void setNextUpdate(
66           DERUTCTime nextUpdate)
67       {
68           this.nextUpdate = new Time(nextUpdate);
69       }
70   
71       public void setThisUpdate(
72           Time thisUpdate)
73       {
74           this.thisUpdate = thisUpdate;
75       }
76   
77       public void setNextUpdate(
78           Time nextUpdate)
79       {
80           this.nextUpdate = nextUpdate;
81       }
82   
83       public void addCRLEntry(
84           DERConstructedSequence crlEntry)
85       {
86           if (crlentries == null)
87               crlentries = new Vector();
88           crlentries.addElement(crlEntry);
89       }
90   
91       public void addCRLEntry(DERInteger userCertificate, DERUTCTime revocationDate, int reason)
92       {
93           addCRLEntry(userCertificate, new Time(revocationDate), reason);
94       }
95   
96       public void addCRLEntry(DERInteger userCertificate, Time revocationDate, int reason)
97       {
98           DERConstructedSequence seq = new DERConstructedSequence();
99           seq.addObject(userCertificate);
100          seq.addObject(revocationDate);
101          
102          if (reason != 0)
103          {
104              CRLReason rf = new CRLReason(reason);
105              ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
106              DEROutputStream         dOut = new DEROutputStream(bOut);
107              try
108              {
109                  dOut.writeObject(rf);
110              }
111              catch (IOException e)
112              {
113                  throw new IllegalArgumentException("error encoding value: " + e);
114              }
115              byte[] value = bOut.toByteArray();
116              DERConstructedSequence eseq = new DERConstructedSequence();
117              DERConstructedSequence eseq1 = new DERConstructedSequence();
118              eseq1.addObject(X509Extensions.ReasonCode);
119              eseq1.addObject(new DEROctetString(value));
120              eseq.addObject(eseq1);
121              X509Extensions ex = new X509Extensions(eseq);
122              seq.addObject(ex);
123          }
124          if (crlentries == null)
125              crlentries = new Vector();
126          crlentries.addElement(seq);
127      }
128  
129      public void setExtensions(
130          X509Extensions    extensions)
131      {
132          this.extensions = extensions;
133      }
134  
135      public TBSCertList generateTBSCertList()
136      {
137          if ((signature == null) || (issuer == null) || (thisUpdate == null))
138          {
139              throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
140          }
141  
142          DERConstructedSequence  seq = new DERConstructedSequence();
143  
144          seq.addObject(version);
145          seq.addObject(signature);
146          seq.addObject(issuer);
147  
148          seq.addObject(thisUpdate);
149          if (nextUpdate != null)
150              seq.addObject(nextUpdate);
151  
152          // Add CRLEntries if they exist
153          if (crlentries != null) {
154              DERConstructedSequence certseq = new DERConstructedSequence();
155              Enumeration it = crlentries.elements();
156              while( it.hasMoreElements() ) {
157                  certseq.addObject((DERConstructedSequence)it.nextElement());
158              }
159              seq.addObject(certseq);
160          }
161  
162          if (extensions != null)
163          {
164              seq.addObject(new DERTaggedObject(0, extensions));
165          }
166  
167          return new TBSCertList(seq);
168      }
169  }
170