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