001package org.apache.commons.ssl.org.bouncycastle.asn1.x509; 002 003import java.util.Enumeration; 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.ASN1Object; 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence; 011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject; 012import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1UTCTime; 013import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence; 014import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject; 015import org.apache.commons.ssl.org.bouncycastle.asn1.x500.X500Name; 016 017/** 018 * PKIX RFC-2459 - TBSCertList object. 019 * <pre> 020 * TBSCertList ::= SEQUENCE { 021 * version Version OPTIONAL, 022 * -- if present, shall be v2 023 * signature AlgorithmIdentifier, 024 * issuer Name, 025 * thisUpdate Time, 026 * nextUpdate Time OPTIONAL, 027 * revokedCertificates SEQUENCE OF SEQUENCE { 028 * userCertificate CertificateSerialNumber, 029 * revocationDate Time, 030 * crlEntryExtensions Extensions OPTIONAL 031 * -- if present, shall be v2 032 * } OPTIONAL, 033 * crlExtensions [0] EXPLICIT Extensions OPTIONAL 034 * -- if present, shall be v2 035 * } 036 * </pre> 037 */ 038public class TBSCertList 039 extends ASN1Object 040{ 041 public static class CRLEntry 042 extends ASN1Object 043 { 044 ASN1Sequence seq; 045 046 Extensions crlEntryExtensions; 047 048 private CRLEntry( 049 ASN1Sequence seq) 050 { 051 if (seq.size() < 2 || seq.size() > 3) 052 { 053 throw new IllegalArgumentException("Bad sequence size: " + seq.size()); 054 } 055 056 this.seq = seq; 057 } 058 059 public static CRLEntry getInstance(Object o) 060 { 061 if (o instanceof CRLEntry) 062 { 063 return ((CRLEntry)o); 064 } 065 else if (o != null) 066 { 067 return new CRLEntry(ASN1Sequence.getInstance(o)); 068 } 069 070 return null; 071 } 072 073 public ASN1Integer getUserCertificate() 074 { 075 return ASN1Integer.getInstance(seq.getObjectAt(0)); 076 } 077 078 public Time getRevocationDate() 079 { 080 return Time.getInstance(seq.getObjectAt(1)); 081 } 082 083 public Extensions getExtensions() 084 { 085 if (crlEntryExtensions == null && seq.size() == 3) 086 { 087 crlEntryExtensions = Extensions.getInstance(seq.getObjectAt(2)); 088 } 089 090 return crlEntryExtensions; 091 } 092 093 public ASN1Primitive toASN1Primitive() 094 { 095 return seq; 096 } 097 098 public boolean hasExtensions() 099 { 100 return seq.size() == 3; 101 } 102 } 103 104 private class RevokedCertificatesEnumeration 105 implements Enumeration 106 { 107 private final Enumeration en; 108 109 RevokedCertificatesEnumeration(Enumeration en) 110 { 111 this.en = en; 112 } 113 114 public boolean hasMoreElements() 115 { 116 return en.hasMoreElements(); 117 } 118 119 public Object nextElement() 120 { 121 return CRLEntry.getInstance(en.nextElement()); 122 } 123 } 124 125 private class EmptyEnumeration 126 implements Enumeration 127 { 128 public boolean hasMoreElements() 129 { 130 return false; 131 } 132 133 public Object nextElement() 134 { 135 return null; // TODO: check exception handling 136 } 137 } 138 139 ASN1Integer version; 140 AlgorithmIdentifier signature; 141 X500Name issuer; 142 Time thisUpdate; 143 Time nextUpdate; 144 ASN1Sequence revokedCertificates; 145 Extensions crlExtensions; 146 147 public static TBSCertList getInstance( 148 ASN1TaggedObject obj, 149 boolean explicit) 150 { 151 return getInstance(ASN1Sequence.getInstance(obj, explicit)); 152 } 153 154 public static TBSCertList getInstance( 155 Object obj) 156 { 157 if (obj instanceof TBSCertList) 158 { 159 return (TBSCertList)obj; 160 } 161 else if (obj != null) 162 { 163 return new TBSCertList(ASN1Sequence.getInstance(obj)); 164 } 165 166 return null; 167 } 168 169 public TBSCertList( 170 ASN1Sequence seq) 171 { 172 if (seq.size() < 3 || seq.size() > 7) 173 { 174 throw new IllegalArgumentException("Bad sequence size: " + seq.size()); 175 } 176 177 int seqPos = 0; 178 179 if (seq.getObjectAt(seqPos) instanceof ASN1Integer) 180 { 181 version = ASN1Integer.getInstance(seq.getObjectAt(seqPos++)); 182 } 183 else 184 { 185 version = null; // version is optional 186 } 187 188 signature = AlgorithmIdentifier.getInstance(seq.getObjectAt(seqPos++)); 189 issuer = X500Name.getInstance(seq.getObjectAt(seqPos++)); 190 thisUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); 191 192 if (seqPos < seq.size() 193 && (seq.getObjectAt(seqPos) instanceof ASN1UTCTime 194 || seq.getObjectAt(seqPos) instanceof ASN1GeneralizedTime 195 || seq.getObjectAt(seqPos) instanceof Time)) 196 { 197 nextUpdate = Time.getInstance(seq.getObjectAt(seqPos++)); 198 } 199 200 if (seqPos < seq.size() 201 && !(seq.getObjectAt(seqPos) instanceof DERTaggedObject)) 202 { 203 revokedCertificates = ASN1Sequence.getInstance(seq.getObjectAt(seqPos++)); 204 } 205 206 if (seqPos < seq.size() 207 && seq.getObjectAt(seqPos) instanceof DERTaggedObject) 208 { 209 crlExtensions = Extensions.getInstance(ASN1Sequence.getInstance((ASN1TaggedObject)seq.getObjectAt(seqPos), true)); 210 } 211 } 212 213 public int getVersionNumber() 214 { 215 if (version == null) 216 { 217 return 1; 218 } 219 return version.getValue().intValue() + 1; 220 } 221 222 public ASN1Integer getVersion() 223 { 224 return version; 225 } 226 227 public AlgorithmIdentifier getSignature() 228 { 229 return signature; 230 } 231 232 public X500Name getIssuer() 233 { 234 return issuer; 235 } 236 237 public Time getThisUpdate() 238 { 239 return thisUpdate; 240 } 241 242 public Time getNextUpdate() 243 { 244 return nextUpdate; 245 } 246 247 public CRLEntry[] getRevokedCertificates() 248 { 249 if (revokedCertificates == null) 250 { 251 return new CRLEntry[0]; 252 } 253 254 CRLEntry[] entries = new CRLEntry[revokedCertificates.size()]; 255 256 for (int i = 0; i < entries.length; i++) 257 { 258 entries[i] = CRLEntry.getInstance(revokedCertificates.getObjectAt(i)); 259 } 260 261 return entries; 262 } 263 264 public Enumeration getRevokedCertificateEnumeration() 265 { 266 if (revokedCertificates == null) 267 { 268 return new EmptyEnumeration(); 269 } 270 271 return new RevokedCertificatesEnumeration(revokedCertificates.getObjects()); 272 } 273 274 public Extensions getExtensions() 275 { 276 return crlExtensions; 277 } 278 279 public ASN1Primitive toASN1Primitive() 280 { 281 ASN1EncodableVector v = new ASN1EncodableVector(); 282 283 if (version != null) 284 { 285 v.add(version); 286 } 287 v.add(signature); 288 v.add(issuer); 289 290 v.add(thisUpdate); 291 if (nextUpdate != null) 292 { 293 v.add(nextUpdate); 294 } 295 296 // Add CRLEntries if they exist 297 if (revokedCertificates != null) 298 { 299 v.add(revokedCertificates); 300 } 301 302 if (crlExtensions != null) 303 { 304 v.add(new DERTaggedObject(0, crlExtensions)); 305 } 306 307 return new DERSequence(v); 308 } 309}