OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / harmony / security / x509 / TBSCertList.java
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 /**
19 * @author Alexander Y. Kleymenov
20 * @version $Revision$
21 */
22
23 package org.apache.harmony.security.x509;
24
25 import java.io.IOException;
26 import java.math.BigInteger;
27 import java.util.Arrays;
28 import java.util.Date;
29 import java.util.Iterator;
30 import java.util.List;
31 import javax.security.auth.x500.X500Principal;
32 import org.apache.harmony.security.asn1.ASN1Explicit;
33 import org.apache.harmony.security.asn1.ASN1Integer;
34 import org.apache.harmony.security.asn1.ASN1Sequence;
35 import org.apache.harmony.security.asn1.ASN1SequenceOf;
36 import org.apache.harmony.security.asn1.ASN1Type;
37 import org.apache.harmony.security.asn1.BerInputStream;
38 import org.apache.harmony.security.x501.Name;
39
40
41 /**
42  * The class encapsulates the ASN.1 DER encoding/decoding work
43  * with TBSCertList structure which is the part of X.509 CRL
44  * (as specified in RFC 3280 -
45  *  Internet X.509 Public Key Infrastructure.
46  *  Certificate and Certificate Revocation List (CRL) Profile.
47  *  http://www.ietf.org/rfc/rfc3280.txt):
48  *
49  * <pre>
50  *   TBSCertList  ::=  SEQUENCE  {
51  *        version                 Version OPTIONAL,
52  *                                     -- if present, MUST be v2
53  *        signature               AlgorithmIdentifier,
54  *        issuer                  Name,
55  *        thisUpdate              Time,
56  *        nextUpdate              Time OPTIONAL,
57  *        revokedCertificates     SEQUENCE OF SEQUENCE  {
58  *             userCertificate         CertificateSerialNumber,
59  *             revocationDate          Time,
60  *             crlEntryExtensions      Extensions OPTIONAL
61  *                                           -- if present, MUST be v2
62  *                                  }  OPTIONAL,
63  *        crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
64  *                                           -- if present, MUST be v2
65  *   }
66  * </pre>
67  */
68 public class TBSCertList {
69
70     // the value of version field of the structure
71     private final int version;
72     // the value of signature field of the structure
73     private final AlgorithmIdentifier signature;
74     // the value of issuer field of the structure
75     private final Name issuer;
76     // the value of thisUpdate of the structure
77     private final Date thisUpdate;
78     // the value of nextUpdate of the structure
79     private final Date nextUpdate;
80     // the value of revokedCertificates of the structure
81     private final List revokedCertificates;
82     // the value of crlExtensions field of the structure
83     private final Extensions crlExtensions;
84     // the ASN.1 encoded form of TBSCertList
85     private byte[] encoding;
86
87     public static class RevokedCertificate {
88         private final BigInteger userCertificate;
89         private final Date revocationDate;
90         private final Extensions crlEntryExtensions;
91
92         private boolean issuerRetrieved;
93         private X500Principal issuer;
94         private byte[] encoding;
95
96         public RevokedCertificate(BigInteger userCertificate,
97                 Date revocationDate, Extensions crlEntryExtensions) {
98             this.userCertificate = userCertificate;
99             this.revocationDate = revocationDate;
100             this.crlEntryExtensions = crlEntryExtensions;
101         }
102
103         public Extensions getCrlEntryExtensions() {
104             return crlEntryExtensions;
105         }
106
107         public BigInteger getUserCertificate() {
108             return userCertificate;
109         }
110
111         public Date getRevocationDate() {
112             return revocationDate;
113         }
114
115         /**
116          * Returns the value of Certificate Issuer Extension, if it is
117          * presented.
118          */
119         public X500Principal getIssuer() {
120             if (crlEntryExtensions == null) {
121                 return null;
122             }
123             if (!issuerRetrieved) {
124                 try {
125                     issuer =
126                         crlEntryExtensions.valueOfCertificateIssuerExtension();
127                 } catch (IOException e) {
128                     e.printStackTrace();
129                 }
130                 issuerRetrieved = true;
131             }
132             return issuer;
133         }
134
135         public byte[] getEncoded() {
136             if (encoding == null) {
137                 encoding = ASN1.encode(this);
138             }
139             return encoding;
140         }
141
142         public boolean equals(Object rc) {
143             if (!(rc instanceof RevokedCertificate)) {
144                 return false;
145             }
146             RevokedCertificate rcert = (RevokedCertificate) rc;
147             return userCertificate.equals(rcert.userCertificate)
148                 && ((revocationDate.getTime() / 1000)
149                         == (rcert.revocationDate.getTime() / 1000))
150                 && ((crlEntryExtensions == null)
151                     ? rcert.crlEntryExtensions == null
152                     : crlEntryExtensions.equals(rcert.crlEntryExtensions));
153         }
154
155         public int hashCode() {
156                 return userCertificate.hashCode() * 37 + (int)revocationDate.getTime() / 1000
157                 + (crlEntryExtensions == null ? 0 : crlEntryExtensions.hashCode());
158         }
159
160         /**
161          * Places the string representation of extension value
162          * into the StringBuffer object.
163          */
164         public void dumpValue(StringBuffer buffer, String prefix) {
165             buffer.append(prefix).append("Certificate Serial Number: ")
166                 .append(userCertificate).append('\n');
167             buffer.append(prefix).append("Revocation Date: ")
168                 .append(revocationDate);
169             if (crlEntryExtensions != null) {
170                 buffer.append('\n').append(prefix)
171                     .append("CRL Entry Extensions: [");
172                 crlEntryExtensions.dumpValue(buffer, prefix + "  ");
173                 buffer.append(prefix).append(']');
174             }
175         }
176
177         public static final ASN1Sequence ASN1 = new ASN1Sequence(
178                 new ASN1Type[] {ASN1Integer.getInstance(), Time.ASN1,
179                 Extensions.ASN1}) {
180             {
181                 setOptional(2);
182             }
183
184             protected Object getDecodedObject(BerInputStream in) {
185                 Object[] values = (Object[]) in.content;
186
187                 return new RevokedCertificate(
188                             new BigInteger((byte[]) values[0]),
189                             (Date) values[1],
190                             (Extensions) values[2]
191                         );
192             }
193
194             protected void getValues(Object object, Object[] values) {
195                 RevokedCertificate rcert = (RevokedCertificate) object;
196
197                 values[0] = rcert.userCertificate.toByteArray();
198                 values[1] = rcert.revocationDate;
199                 values[2] = rcert.crlEntryExtensions;
200             }
201         };
202     }
203
204     /**
205      * Constructs the instance of TBSCertList without optional fields.
206      * Take a note, that regarding to the rfc 3280 (p. 49):
207      * "When CRLs are issued, the CRLs MUST be version 2 CRLs, include the date
208      * by which the next CRL will be issued in the nextUpdate field (section
209      * 5.1.2.5), include the CRL number extension (section 5.2.3), and include
210      * the authority key identifier extension (section 5.2.1). Conforming
211      * applications that support CRLs are REQUIRED to process both version 1 and
212      * version 2 complete CRLs that provide revocation information for all
213      * certificates issued by one CA. Conforming applications are NOT REQUIRED
214      * to support processing of delta CRLs, indirect CRLs, or CRLs with a scope
215      * other than all certificates issued by one CA."
216      * @param   signature:  AlgorithmIdentifier
217      * @param   issuer: Name
218      * @param   thisUpdate: Time
219      */
220     public TBSCertList(AlgorithmIdentifier signature,
221             Name issuer, Date thisUpdate) {
222         this.version = 1;
223         this.signature = signature;
224         this.issuer = issuer;
225         this.thisUpdate = thisUpdate;
226         this.nextUpdate = null;
227         this.revokedCertificates = null;
228         this.crlExtensions = null;
229     }
230
231     /**
232      * Constructs the instance of TBSCertList with all optional fields
233      * @param   version: version of the CRL. Should be 1 or 2.
234      * Note that if the version of CRL is 1, then nextUpdate,
235      * crlExtensions fields of CRL and crlEntryExtensions field
236      * of CRL entry must not be presented in CRL.
237      * FIXME: do check for it.
238      * @param   signature:  AlgorithmIdentifier
239      * @param   issuer: Name
240      * @param   thisUpdate: Time
241      * @param   nextUpdate: Time
242      * @param   revokedCertificates:    List
243      * @param   crlExtensions:  Extensions
244      */
245     public TBSCertList(int version, AlgorithmIdentifier signature,
246             Name issuer, Date thisUpdate, Date nextUpdate,
247             List revokedCertificates, Extensions crlExtensions) {
248         this.version = version;
249         this.signature = signature;
250         this.issuer = issuer;
251         this.thisUpdate = thisUpdate;
252         this.nextUpdate = nextUpdate;
253         this.revokedCertificates = revokedCertificates;
254         this.crlExtensions = crlExtensions;
255     }
256
257     // Constructs the object with associated ASN.1 encoding
258     private TBSCertList(int version, AlgorithmIdentifier signature,
259             Name issuer, Date thisUpdate, Date nextUpdate,
260             List revokedCertificates, Extensions crlExtensions,
261             byte[] encoding) {
262         this.version = version;
263         this.signature = signature;
264         this.issuer = issuer;
265         this.thisUpdate = thisUpdate;
266         this.nextUpdate = nextUpdate;
267         this.revokedCertificates = revokedCertificates;
268         this.crlExtensions = crlExtensions;
269         this.encoding = encoding;
270     }
271
272     /**
273      * Returns the value of version field of the structure.
274      * @return  version
275      */
276     public int getVersion() {
277         return version;
278     }
279
280     /**
281      * Returns the value of signature field of the structure.
282      * @return  signature
283      */
284     public AlgorithmIdentifier getSignature() {
285         return signature;
286     }
287
288     /**
289      * Returns the value of issuer field of the structure.
290      * @return  issuer
291      */
292     public Name getIssuer() {
293         return issuer;
294     }
295
296     /**
297      * Returns the value of thisUpdate field of the structure.
298      * @return thisUpdate
299      */
300     public Date getThisUpdate() {
301         return thisUpdate;
302     }
303
304     /**
305      * Returns the value of nextUpdate field of the structure.
306      * @return nextUpdate
307      */
308     public Date getNextUpdate() {
309         return nextUpdate;
310     }
311
312     /**
313      * Returns the value of revokedCertificates field of the structure.
314      * @return revokedCertificates
315      */
316     public List getRevokedCertificates() {
317         return revokedCertificates;
318     }
319
320     /**
321      * Returns the value of crlExtensions field of the structure.
322      * @return  extensions
323      */
324     public Extensions getCrlExtensions() {
325         return crlExtensions;
326     }
327
328     /**
329      * Returns ASN.1 encoded form of this X.509 TBSCertList value.
330      * @return a byte array containing ASN.1 encode form.
331      */
332     public byte[] getEncoded() {
333         if (encoding == null) {
334             encoding = ASN1.encode(this);
335         }
336         return encoding;
337     }
338
339     public boolean equals(Object tbs) {
340         if (!(tbs instanceof TBSCertList)) {
341             return false;
342         }
343         TBSCertList tbscert = (TBSCertList) tbs;
344         return (version == tbscert.version)
345             && (signature.equals(tbscert.signature))
346             // FIXME use Name.equals when it will be implemented
347             && (Arrays.equals(issuer.getEncoded(), tbscert.issuer.getEncoded()))
348             && ((thisUpdate.getTime() / 1000)
349                     == (tbscert.thisUpdate.getTime() / 1000))
350             && ((nextUpdate == null)
351                     ? tbscert.nextUpdate == null
352                     : ((nextUpdate.getTime() / 1000)
353                         == (tbscert.nextUpdate.getTime() / 1000)))
354             && ((((revokedCertificates == null)
355                             || (tbscert.revokedCertificates == null))
356                     && (revokedCertificates == tbscert.revokedCertificates))
357                 || (revokedCertificates.containsAll(tbscert.revokedCertificates)
358                     && (revokedCertificates.size()
359                         == tbscert.revokedCertificates.size())))
360             && ((crlExtensions == null)
361                     ? tbscert.crlExtensions == null
362                     : crlExtensions.equals(tbscert.crlExtensions));
363     }
364
365     public int hashCode() {
366         return ((version * 37 + signature.hashCode()) * 37
367                 + issuer.getEncoded().hashCode()) * 37
368                 + (int)thisUpdate.getTime() / 1000;
369     }
370
371     /**
372      * Places the string representation of extension value
373      * into the StringBuffer object.
374      */
375     public void dumpValue(StringBuffer buffer) {
376         buffer.append("X.509 CRL v").append(version);
377         buffer.append("\nSignature Algorithm: [");
378         signature.dumpValue(buffer);
379         buffer.append(']');
380         buffer.append("\nIssuer: ").append(issuer.getName(X500Principal.RFC2253));
381         buffer.append("\n\nThis Update: ").append(thisUpdate);
382         buffer.append("\nNext Update: ").append(nextUpdate).append('\n');
383         if (revokedCertificates != null) {
384             buffer.append("\nRevoked Certificates: ")
385                 .append(revokedCertificates.size()).append(" [");
386             int number = 1;
387             for (Iterator it = revokedCertificates.iterator();it.hasNext();) {
388                 buffer.append("\n  [").append(number++).append(']');
389                 ((RevokedCertificate) it.next()).dumpValue(buffer, "  ");
390                 buffer.append('\n');
391             }
392             buffer.append("]\n");
393         }
394         if (crlExtensions != null) {
395             buffer.append("\nCRL Extensions: ")
396                 .append(crlExtensions.size()).append(" [");
397             crlExtensions.dumpValue(buffer, "  ");
398             buffer.append("]\n");
399         }
400     }
401
402     /**
403      * X.509 TBSCertList encoder/decoder.
404      */
405     public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] {
406             ASN1Integer.getInstance(), // version
407             AlgorithmIdentifier.ASN1,  // signature
408             Name.ASN1, // issuer
409             Time.ASN1, // thisUpdate
410             Time.ASN1, // nextUpdate
411             new ASN1SequenceOf(RevokedCertificate.ASN1), // revokedCertificates
412             new ASN1Explicit(0, Extensions.ASN1) // crlExtensions
413                 }) {
414         {
415             setOptional(0);
416             setOptional(4);
417             setOptional(5);
418             setOptional(6);
419         }
420
421         protected Object getDecodedObject(BerInputStream in)
422                         throws IOException {
423             Object[] values = (Object[]) in.content;
424             return new TBSCertList(
425                         (values[0] == null)
426                             ? 1
427                             : ASN1Integer.toIntValue(values[0])+1,
428                         (AlgorithmIdentifier) values[1],
429                         (Name) values[2],
430                         (Date) values[3],
431                         (Date) values[4],
432                         (List) values[5],
433                         (Extensions) values[6],
434                         in.getEncoded()
435                     );
436         }
437
438         protected void getValues(Object object, Object[] values) {
439             TBSCertList tbs = (TBSCertList) object;
440             values[0] = (tbs.version > 1)
441                 ? ASN1Integer.fromIntValue(tbs.version - 1) : null;
442             values[1] = tbs.signature;
443             values[2] = tbs.issuer;
444             values[3] = tbs.thisUpdate;
445             values[4] = tbs.nextUpdate;
446             values[5] = tbs.revokedCertificates;
447             values[6] = tbs.crlExtensions;
448         }
449     };
450 }
451