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