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