001package org.apache.commons.ssl.org.bouncycastle.asn1.x509;
002
003import java.io.IOException;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1GeneralizedTime;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1UTCTime;
010import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
012import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
013import org.apache.commons.ssl.org.bouncycastle.asn1.x500.X500Name;
014
015/**
016 * Generator for Version 2 TBSCertList structures.
017 * <pre>
018 *  TBSCertList  ::=  SEQUENCE  {
019 *       version                 Version OPTIONAL,
020 *                                    -- if present, shall be v2
021 *       signature               AlgorithmIdentifier,
022 *       issuer                  Name,
023 *       thisUpdate              Time,
024 *       nextUpdate              Time OPTIONAL,
025 *       revokedCertificates     SEQUENCE OF SEQUENCE  {
026 *            userCertificate         CertificateSerialNumber,
027 *            revocationDate          Time,
028 *            crlEntryExtensions      Extensions OPTIONAL
029 *                                          -- if present, shall be v2
030 *                                 }  OPTIONAL,
031 *       crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
032 *                                          -- if present, shall be v2
033 *                                 }
034 * </pre>
035 *
036 * <b>Note: This class may be subject to change</b>
037 */
038public class V2TBSCertListGenerator
039{
040    private ASN1Integer         version = new ASN1Integer(1);
041    private AlgorithmIdentifier signature;
042    private X500Name            issuer;
043    private Time                thisUpdate, nextUpdate=null;
044    private Extensions          extensions = null;
045    private ASN1EncodableVector crlentries = new ASN1EncodableVector();
046
047    private final static ASN1Sequence[] reasons;
048
049    static
050    {
051       reasons = new ASN1Sequence[11];
052
053        reasons[0] = createReasonExtension(CRLReason.unspecified);
054        reasons[1] = createReasonExtension(CRLReason.keyCompromise);
055        reasons[2] = createReasonExtension(CRLReason.cACompromise);
056        reasons[3] = createReasonExtension(CRLReason.affiliationChanged);
057        reasons[4] = createReasonExtension(CRLReason.superseded);
058        reasons[5] = createReasonExtension(CRLReason.cessationOfOperation);
059        reasons[6] = createReasonExtension(CRLReason.certificateHold);
060        reasons[7] = createReasonExtension(7); // 7 -> unknown
061        reasons[8] = createReasonExtension(CRLReason.removeFromCRL);
062        reasons[9] = createReasonExtension(CRLReason.privilegeWithdrawn);
063        reasons[10] = createReasonExtension(CRLReason.aACompromise);
064    }
065
066    public V2TBSCertListGenerator()
067    {
068    }
069
070
071    public void setSignature(
072        AlgorithmIdentifier    signature)
073    {
074        this.signature = signature;
075    }
076
077    /**
078     * @deprecated use X500Name method
079     */
080    public void setIssuer(
081        X509Name    issuer)
082    {
083        this.issuer = X500Name.getInstance(issuer.toASN1Primitive());
084    }
085
086    public void setIssuer(X500Name issuer)
087    {
088        this.issuer = issuer;
089    }
090
091    public void setThisUpdate(
092        ASN1UTCTime thisUpdate)
093    {
094        this.thisUpdate = new Time(thisUpdate);
095    }
096
097    public void setNextUpdate(
098        ASN1UTCTime nextUpdate)
099    {
100        this.nextUpdate = new Time(nextUpdate);
101    }
102
103    public void setThisUpdate(
104        Time thisUpdate)
105    {
106        this.thisUpdate = thisUpdate;
107    }
108
109    public void setNextUpdate(
110        Time nextUpdate)
111    {
112        this.nextUpdate = nextUpdate;
113    }
114
115    public void addCRLEntry(
116        ASN1Sequence crlEntry)
117    {
118        crlentries.add(crlEntry);
119    }
120
121    public void addCRLEntry(ASN1Integer userCertificate, ASN1UTCTime revocationDate, int reason)
122    {
123        addCRLEntry(userCertificate, new Time(revocationDate), reason);
124    }
125
126    public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason)
127    {
128        addCRLEntry(userCertificate, revocationDate, reason, null);
129    }
130
131    public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, int reason, ASN1GeneralizedTime invalidityDate)
132    {
133        if (reason != 0)
134        {
135            ASN1EncodableVector v = new ASN1EncodableVector();
136
137            if (reason < reasons.length)
138            {
139                if (reason < 0)
140                {
141                    throw new IllegalArgumentException("invalid reason value: " + reason);
142                }
143                v.add(reasons[reason]);
144            }
145            else
146            {
147                v.add(createReasonExtension(reason));
148            }
149
150            if (invalidityDate != null)
151            {
152                v.add(createInvalidityDateExtension(invalidityDate));
153            }
154
155            internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
156        }
157        else if (invalidityDate != null)
158        {
159            ASN1EncodableVector v = new ASN1EncodableVector();
160
161            v.add(createInvalidityDateExtension(invalidityDate));
162
163            internalAddCRLEntry(userCertificate, revocationDate, new DERSequence(v));
164        }
165        else
166        {
167            addCRLEntry(userCertificate, revocationDate, null);
168        }
169    }
170
171    private void internalAddCRLEntry(ASN1Integer userCertificate, Time revocationDate, ASN1Sequence extensions)
172    {
173        ASN1EncodableVector v = new ASN1EncodableVector();
174
175        v.add(userCertificate);
176        v.add(revocationDate);
177
178        if (extensions != null)
179        {
180            v.add(extensions);
181        }
182
183        addCRLEntry(new DERSequence(v));
184    }
185
186    public void addCRLEntry(ASN1Integer userCertificate, Time revocationDate, Extensions extensions)
187    {
188        ASN1EncodableVector v = new ASN1EncodableVector();
189
190        v.add(userCertificate);
191        v.add(revocationDate);
192        
193        if (extensions != null)
194        {
195            v.add(extensions);
196        }
197        
198        addCRLEntry(new DERSequence(v));
199    }
200
201    public void setExtensions(
202        X509Extensions    extensions)
203    {
204        setExtensions(Extensions.getInstance(extensions));
205    }
206
207    public void setExtensions(
208        Extensions    extensions)
209    {
210        this.extensions = extensions;
211    }
212
213    public TBSCertList generateTBSCertList()
214    {
215        if ((signature == null) || (issuer == null) || (thisUpdate == null))
216        {
217            throw new IllegalStateException("Not all mandatory fields set in V2 TBSCertList generator.");
218        }
219
220        ASN1EncodableVector  v = new ASN1EncodableVector();
221
222        v.add(version);
223        v.add(signature);
224        v.add(issuer);
225
226        v.add(thisUpdate);
227        if (nextUpdate != null)
228        {
229            v.add(nextUpdate);
230        }
231
232        // Add CRLEntries if they exist
233        if (crlentries.size() != 0)
234        {
235            v.add(new DERSequence(crlentries));
236        }
237
238        if (extensions != null)
239        {
240            v.add(new DERTaggedObject(0, extensions));
241        }
242
243        return new TBSCertList(new DERSequence(v));
244    }
245
246    private static ASN1Sequence createReasonExtension(int reasonCode)
247    {
248        ASN1EncodableVector v = new ASN1EncodableVector();
249
250        CRLReason crlReason = CRLReason.lookup(reasonCode);
251
252        try
253        {
254            v.add(Extension.reasonCode);
255            v.add(new DEROctetString(crlReason.getEncoded()));
256        }
257        catch (IOException e)
258        {
259            throw new IllegalArgumentException("error encoding reason: " + e);
260        }
261
262        return new DERSequence(v);
263    }
264
265    private static ASN1Sequence createInvalidityDateExtension(ASN1GeneralizedTime invalidityDate)
266    {
267        ASN1EncodableVector v = new ASN1EncodableVector();
268
269        try
270        {
271            v.add(Extension.invalidityDate);
272            v.add(new DEROctetString(invalidityDate.getEncoded()));
273        }
274        catch (IOException e)
275        {
276            throw new IllegalArgumentException("error encoding reason: " + e);
277        }
278
279        return new DERSequence(v);
280    }
281}