1 package org.bouncycastle.asn1.x509; 2 3 import java.util.Enumeration; 4 import java.util.NoSuchElementException; 5 6 import org.bouncycastle.asn1.ASN1EncodableVector; 7 import org.bouncycastle.asn1.ASN1GeneralizedTime; 8 import org.bouncycastle.asn1.ASN1Integer; 9 import org.bouncycastle.asn1.ASN1Object; 10 import org.bouncycastle.asn1.ASN1Primitive; 11 import org.bouncycastle.asn1.ASN1Sequence; 12 import org.bouncycastle.asn1.ASN1TaggedObject; 13 import org.bouncycastle.asn1.ASN1UTCTime; 14 import org.bouncycastle.asn1.DERSequence; 15 import org.bouncycastle.asn1.DERTaggedObject; 16 import org.bouncycastle.asn1.x500.X500Name; 17 18 /** 19 * PKIX RFC-2459 - TBSCertList object. 20 * <pre> 21 * TBSCertList ::= SEQUENCE { 22 * version Version OPTIONAL, 23 * -- if present, shall be v2 24 * signature AlgorithmIdentifier, 25 * issuer Name, 26 * thisUpdate Time, 27 * nextUpdate Time OPTIONAL, 28 * revokedCertificates SEQUENCE OF SEQUENCE { 29 * userCertificate CertificateSerialNumber, 30 * revocationDate Time, 31 * crlEntryExtensions Extensions OPTIONAL 32 * -- if present, shall be v2 33 * } OPTIONAL, 34 * crlExtensions [0] EXPLICIT Extensions OPTIONAL 35 * -- if present, shall be v2 36 * } 37 * </pre> 38 */ 39 public class TBSCertList 40 extends ASN1Object 41 { 42 public static class CRLEntry 43 extends ASN1Object 44 { 45 ASN1Sequence seq; 46 47 Extensions crlEntryExtensions; 48 49 private CRLEntry( 50 ASN1Sequence seq) 51 { 52 if (seq.size() < 2 || seq.size() > 3) 53 { 54 throw new IllegalArgumentException("Bad sequence size: " + seq.size()); 55 } 56 57 this.seq = seq; 58 } 59 60 public static CRLEntry getInstance(Object o) 61 { 62 if (o instanceof CRLEntry) 63 { 64 return ((CRLEntry)o); 65 } 66 else if (o != null) 67 { 68 return new CRLEntry(ASN1Sequence.getInstance(o)); 69 } 70 71 return null; 72 } 73 74 public ASN1Integer getUserCertificate() 75 { 76 return ASN1Integer.getInstance(seq.getObjectAt(0)); 77 } 78 79 public Time getRevocationDate() 80 { 81 return Time.getInstance(seq.getObjectAt(1)); 82 } 83 84 public Extensions getExtensions() 85 { 86 if (crlEntryExtensions == null && seq.size() == 3) 87 { 88 crlEntryExtensions = Extensions.getInstance(seq.getObjectAt(2)); 89 } 90 91 return crlEntryExtensions; 92 } 93 94 public ASN1Primitive toASN1Primitive() 95 { 96 return seq; 97 } 98 99 public boolean hasExtensions() 100 { 101 return seq.size() == 3; 102 } 103 } 104 105 private class RevokedCertificatesEnumeration 106 implements Enumeration 107 { 108 private final Enumeration en; 109 110 RevokedCertificatesEnumeration(Enumeration en) 111 { 112 this.en = en; 113 } 114 115 public boolean hasMoreElements() 116 { 117 return en.hasMoreElements(); 118 } 119 120 public Object nextElement() 121 { 122 return CRLEntry.getInstance(en.nextElement()); 123 } 124 } 125 126 private class EmptyEnumeration 127 implements Enumeration 128 { 129 public boolean hasMoreElements() 130 { 131 return false; 132 } 133 134 public Object nextElement() 135 { 136 throw new NoSuchElementException("Empty Enumeration"); 137 } 138 } 139 140 ASN1Integer version; 141 AlgorithmIdentifier signature; 142 X500Name issuer; 143 Time thisUpdate; 144 Time nextUpdate; 145 ASN1Sequence revokedCertificates; 146 Extensions crlExtensions; 147 148 public static TBSCertList getInstance( 149 ASN1TaggedObject obj, 150 boolean explicit) 151 { 152 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 153 } 154 155 public static TBSCertList getInstance( 156 Object obj) 157 { 158 if (obj instanceof TBSCertList) 159 { 160 return (TBSCertList)obj; 161 } 162 else if (obj != null) 163 { 164 return new TBSCertList(ASN1Sequence.getInstance(obj)); 165 } 166 167 return null; 168 } 169 170 public TBSCertList( 171 ASN1Sequence seq) 172 { 173 if (seq.size() < 3 || seq.size() > 7) 174 { 175 throw new IllegalArgumentException("Bad sequence size: " + seq.size()); 176 } 177 178 int seqPos = 0; 179 180 if (seq.getObjectAt(seqPos) instanceof ASN1Integer) 181 { 182 version = ASN1Integer.getInstance(seq.getObjectAt(seqPos++)); 183 } 184 else 185 { 186 version = null; // version is optional 187 } 188 189 signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++)); 190 issuer = X500Name.getInstance(seq.getObjectAt(seqPos++)); 191 thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); 192 193 if (seqPos < seq.size() 194 && (seq.getObjectAt(seqPos) instanceof ASN1UTCTime 195 || seq.getObjectAt(seqPos) instanceof ASN1GeneralizedTime 196 || seq.getObjectAt(seqPos) instanceof Time)) 197 { 198 nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); 199 } 200 201 if (seqPos < seq.size() 202 && !(seq.getObjectAt(seqPos) instanceof ASN1TaggedObject)) 203 { 204 revokedCertificates = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++)); 205 } 206 207 if (seqPos < seq.size() 208 && seq.getObjectAt(seqPos) instanceof ASN1TaggedObject) 209 { 210 crlExtensions = Extensions.getInstance(ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(seqPos), true)); 211 } 212 } 213 214 public int getVersionNumber() 215 { 216 if (version == null) 217 { 218 return 1; 219 } 220 return version.getValue().intValue() + 1; 221 } 222 223 public ASN1Integer getVersion() 224 { 225 return version; 226 } 227 228 public AlgorithmIdentifier getSignature() 229 { 230 return signature; 231 } 232 233 public X500Name getIssuer() 234 { 235 return issuer; 236 } 237 238 public Time getThisUpdate() 239 { 240 return thisUpdate; 241 } 242 243 public Time getNextUpdate() 244 { 245 return nextUpdate; 246 } 247 248 public CRLEntry[] getRevokedCertificates() 249 { 250 if (revokedCertificates == null) 251 { 252 return new CRLEntry[0]; 253 } 254 255 CRLEntry[] entries = new CRLEntry[revokedCertificates.size()]; 256 257 for (int i = 0; i < entries.length; i++) 258 { 259 entries[i] = CRLEntry.getInstance(revokedCertificates.getObjectAt(i)); 260 } 261 262 return entries; 263 } 264 265 public Enumeration getRevokedCertificateEnumeration() 266 { 267 if (revokedCertificates == null) 268 { 269 return new EmptyEnumeration(); 270 } 271 272 return new RevokedCertificatesEnumeration(revokedCertificates.getObjects()); 273 } 274 275 public Extensions getExtensions() 276 { 277 return crlExtensions; 278 } 279 280 public ASN1Primitive toASN1Primitive() 281 { 282 ASN1EncodableVector v = new ASN1EncodableVector(); 283 284 if (version != null) 285 { 286 v.add(version); 287 } 288 v.add(signature); 289 v.add(issuer); 290 291 v.add(thisUpdate); 292 if (nextUpdate != null) 293 { 294 v.add(nextUpdate); 295 } 296 297 // Add CRLEntries if they exist 298 if (revokedCertificates != null) 299 { 300 v.add(revokedCertificates); 301 } 302 303 if (crlExtensions != null) 304 { 305 v.add(new DERTaggedObject(0, crlExtensions)); 306 } 307 308 return new DERSequence(v); 309 } 310 } 311