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