1package org.bouncycastle.jcajce.provider.asymmetric.x509; 2 3import java.io.IOException; 4import java.math.BigInteger; 5import java.security.cert.CRLException; 6import java.security.cert.X509CRLEntry; 7import java.util.Date; 8import java.util.Enumeration; 9import java.util.HashSet; 10import java.util.Set; 11 12import javax.security.auth.x500.X500Principal; 13 14import org.bouncycastle.asn1.ASN1Encoding; 15import org.bouncycastle.asn1.ASN1Enumerated; 16import org.bouncycastle.asn1.ASN1InputStream; 17import org.bouncycastle.asn1.ASN1ObjectIdentifier; 18import org.bouncycastle.asn1.util.ASN1Dump; 19import org.bouncycastle.asn1.x500.X500Name; 20import org.bouncycastle.asn1.x509.CRLReason; 21import org.bouncycastle.asn1.x509.Extension; 22import org.bouncycastle.asn1.x509.Extensions; 23import org.bouncycastle.asn1.x509.GeneralName; 24import org.bouncycastle.asn1.x509.GeneralNames; 25import org.bouncycastle.asn1.x509.TBSCertList; 26 27/** 28 * The following extensions are listed in RFC 2459 as relevant to CRL Entries 29 * 30 * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer 31 * (critical) 32 */ 33class X509CRLEntryObject extends X509CRLEntry 34{ 35 private TBSCertList.CRLEntry c; 36 37 private X500Name certificateIssuer; 38 private int hashValue; 39 private boolean isHashValueSet; 40 41 protected X509CRLEntryObject(TBSCertList.CRLEntry c) 42 { 43 this.c = c; 44 this.certificateIssuer = null; 45 } 46 47 /** 48 * Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code> 49 * is <code>false</code> {@link #getCertificateIssuer()} will always 50 * return <code>null</code>, <code>previousCertificateIssuer</code> is 51 * ignored. If this <code>isIndirect</code> is specified and this CRLEntry 52 * has no certificate issuer CRL entry extension 53 * <code>previousCertificateIssuer</code> is returned by 54 * {@link #getCertificateIssuer()}. 55 * 56 * @param c 57 * TBSCertList.CRLEntry object. 58 * @param isIndirect 59 * <code>true</code> if the corresponding CRL is a indirect 60 * CRL. 61 * @param previousCertificateIssuer 62 * Certificate issuer of the previous CRLEntry. 63 */ 64 protected X509CRLEntryObject( 65 TBSCertList.CRLEntry c, 66 boolean isIndirect, 67 X500Name previousCertificateIssuer) 68 { 69 this.c = c; 70 this.certificateIssuer = loadCertificateIssuer(isIndirect, previousCertificateIssuer); 71 } 72 73 /** 74 * Will return true if any extensions are present and marked as critical as 75 * we currently don't handle any extensions! 76 */ 77 public boolean hasUnsupportedCriticalExtension() 78 { 79 Set extns = getCriticalExtensionOIDs(); 80 81 return extns != null && !extns.isEmpty(); 82 } 83 84 private X500Name loadCertificateIssuer(boolean isIndirect, X500Name previousCertificateIssuer) 85 { 86 if (!isIndirect) 87 { 88 return null; 89 } 90 91 Extension ext = getExtension(Extension.certificateIssuer); 92 if (ext == null) 93 { 94 return previousCertificateIssuer; 95 } 96 97 try 98 { 99 GeneralName[] names = GeneralNames.getInstance(ext.getParsedValue()).getNames(); 100 for (int i = 0; i < names.length; i++) 101 { 102 if (names[i].getTagNo() == GeneralName.directoryName) 103 { 104 return X500Name.getInstance(names[i].getName()); 105 } 106 } 107 return null; 108 } 109 catch (Exception e) 110 { 111 return null; 112 } 113 } 114 115 public X500Principal getCertificateIssuer() 116 { 117 if (certificateIssuer == null) 118 { 119 return null; 120 } 121 try 122 { 123 return new X500Principal(certificateIssuer.getEncoded()); 124 } 125 catch (IOException e) 126 { 127 return null; 128 } 129 } 130 131 private Set getExtensionOIDs(boolean critical) 132 { 133 Extensions extensions = c.getExtensions(); 134 135 if (extensions != null) 136 { 137 Set set = new HashSet(); 138 Enumeration e = extensions.oids(); 139 140 while (e.hasMoreElements()) 141 { 142 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier) e.nextElement(); 143 Extension ext = extensions.getExtension(oid); 144 145 if (critical == ext.isCritical()) 146 { 147 set.add(oid.getId()); 148 } 149 } 150 151 return set; 152 } 153 154 return null; 155 } 156 157 public Set getCriticalExtensionOIDs() 158 { 159 return getExtensionOIDs(true); 160 } 161 162 public Set getNonCriticalExtensionOIDs() 163 { 164 return getExtensionOIDs(false); 165 } 166 167 private Extension getExtension(ASN1ObjectIdentifier oid) 168 { 169 Extensions exts = c.getExtensions(); 170 171 if (exts != null) 172 { 173 return exts.getExtension(oid); 174 } 175 176 return null; 177 } 178 179 public byte[] getExtensionValue(String oid) 180 { 181 Extension ext = getExtension(new ASN1ObjectIdentifier(oid)); 182 183 if (ext != null) 184 { 185 try 186 { 187 return ext.getExtnValue().getEncoded(); 188 } 189 catch (Exception e) 190 { 191 throw new RuntimeException("error encoding " + e.toString()); 192 } 193 } 194 195 return null; 196 } 197 198 /** 199 * Cache the hashCode value - calculating it with the standard method. 200 * @return calculated hashCode. 201 */ 202 public int hashCode() 203 { 204 if (!isHashValueSet) 205 { 206 hashValue = super.hashCode(); 207 isHashValueSet = true; 208 } 209 210 return hashValue; 211 } 212 213 public boolean equals(Object o) 214 { 215 if (o == this) 216 { 217 return true; 218 } 219 220 if (o instanceof X509CRLEntryObject) 221 { 222 X509CRLEntryObject other = (X509CRLEntryObject)o; 223 224 return this.c.equals(other.c); 225 } 226 227 return super.equals(this); 228 } 229 230 public byte[] getEncoded() 231 throws CRLException 232 { 233 try 234 { 235 return c.getEncoded(ASN1Encoding.DER); 236 } 237 catch (IOException e) 238 { 239 throw new CRLException(e.toString()); 240 } 241 } 242 243 public BigInteger getSerialNumber() 244 { 245 return c.getUserCertificate().getValue(); 246 } 247 248 public Date getRevocationDate() 249 { 250 return c.getRevocationDate().getDate(); 251 } 252 253 public boolean hasExtensions() 254 { 255 return c.getExtensions() != null; 256 } 257 258 public String toString() 259 { 260 StringBuffer buf = new StringBuffer(); 261 String nl = System.getProperty("line.separator"); 262 263 buf.append(" userCertificate: ").append(this.getSerialNumber()).append(nl); 264 buf.append(" revocationDate: ").append(this.getRevocationDate()).append(nl); 265 buf.append(" certificateIssuer: ").append(this.getCertificateIssuer()).append(nl); 266 267 Extensions extensions = c.getExtensions(); 268 269 if (extensions != null) 270 { 271 Enumeration e = extensions.oids(); 272 if (e.hasMoreElements()) 273 { 274 buf.append(" crlEntryExtensions:").append(nl); 275 276 while (e.hasMoreElements()) 277 { 278 ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); 279 Extension ext = extensions.getExtension(oid); 280 if (ext.getExtnValue() != null) 281 { 282 byte[] octs = ext.getExtnValue().getOctets(); 283 ASN1InputStream dIn = new ASN1InputStream(octs); 284 buf.append(" critical(").append(ext.isCritical()).append(") "); 285 try 286 { 287 if (oid.equals(Extension.reasonCode)) 288 { 289 buf.append(CRLReason.getInstance(ASN1Enumerated.getInstance(dIn.readObject()))).append(nl); 290 } 291 else if (oid.equals(Extension.certificateIssuer)) 292 { 293 buf.append("Certificate issuer: ").append(GeneralNames.getInstance(dIn.readObject())).append(nl); 294 } 295 else 296 { 297 buf.append(oid.getId()); 298 buf.append(" value = ").append(ASN1Dump.dumpAsString(dIn.readObject())).append(nl); 299 } 300 } 301 catch (Exception ex) 302 { 303 buf.append(oid.getId()); 304 buf.append(" value = ").append("*****").append(nl); 305 } 306 } 307 else 308 { 309 buf.append(nl); 310 } 311 } 312 } 313 } 314 315 return buf.toString(); 316 } 317} 318