1package org.bouncycastle.cert.ocsp; 2 3import java.io.ByteArrayOutputStream; 4import java.io.IOException; 5import java.io.OutputStream; 6import java.util.List; 7import java.util.Set; 8 9import org.bouncycastle.asn1.ASN1Encoding; 10import org.bouncycastle.asn1.ASN1Exception; 11import org.bouncycastle.asn1.ASN1InputStream; 12import org.bouncycastle.asn1.ASN1ObjectIdentifier; 13import org.bouncycastle.asn1.ASN1OutputStream; 14import org.bouncycastle.asn1.ASN1Sequence; 15import org.bouncycastle.asn1.ocsp.OCSPRequest; 16import org.bouncycastle.asn1.ocsp.Request; 17import org.bouncycastle.asn1.x509.Certificate; 18import org.bouncycastle.asn1.x509.Extension; 19import org.bouncycastle.asn1.x509.Extensions; 20import org.bouncycastle.asn1.x509.GeneralName; 21import org.bouncycastle.cert.CertIOException; 22import org.bouncycastle.cert.X509CertificateHolder; 23import org.bouncycastle.operator.ContentVerifier; 24import org.bouncycastle.operator.ContentVerifierProvider; 25 26/** 27 * <pre> 28 * OCSPRequest ::= SEQUENCE { 29 * tbsRequest TBSRequest, 30 * optionalSignature [0] EXPLICIT Signature OPTIONAL } 31 * 32 * TBSRequest ::= SEQUENCE { 33 * version [0] EXPLICIT Version DEFAULT v1, 34 * requestorName [1] EXPLICIT GeneralName OPTIONAL, 35 * requestList SEQUENCE OF Request, 36 * requestExtensions [2] EXPLICIT Extensions OPTIONAL } 37 * 38 * Signature ::= SEQUENCE { 39 * signatureAlgorithm AlgorithmIdentifier, 40 * signature BIT STRING, 41 * certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL} 42 * 43 * Version ::= INTEGER { v1(0) } 44 * 45 * Request ::= SEQUENCE { 46 * reqCert CertID, 47 * singleRequestExtensions [0] EXPLICIT Extensions OPTIONAL } 48 * 49 * CertID ::= SEQUENCE { 50 * hashAlgorithm AlgorithmIdentifier, 51 * issuerNameHash OCTET STRING, -- Hash of Issuer's DN 52 * issuerKeyHash OCTET STRING, -- Hash of Issuers public key 53 * serialNumber CertificateSerialNumber } 54 * </pre> 55 */ 56public class OCSPReq 57{ 58 private static final X509CertificateHolder[] EMPTY_CERTS = new X509CertificateHolder[0]; 59 60 private OCSPRequest req; 61 private Extensions extensions; 62 63 public OCSPReq( 64 OCSPRequest req) 65 { 66 this.req = req; 67 this.extensions = req.getTbsRequest().getRequestExtensions(); 68 } 69 70 public OCSPReq( 71 byte[] req) 72 throws IOException 73 { 74 this(new ASN1InputStream(req)); 75 } 76 77 private OCSPReq( 78 ASN1InputStream aIn) 79 throws IOException 80 { 81 try 82 { 83 this.req = OCSPRequest.getInstance(aIn.readObject()); 84 if (req == null) 85 { 86 throw new CertIOException("malformed request: no request data found"); 87 } 88 this.extensions = req.getTbsRequest().getRequestExtensions(); 89 } 90 catch (IllegalArgumentException e) 91 { 92 throw new CertIOException("malformed request: " + e.getMessage(), e); 93 } 94 catch (ClassCastException e) 95 { 96 throw new CertIOException("malformed request: " + e.getMessage(), e); 97 } 98 catch (ASN1Exception e) 99 { 100 throw new CertIOException("malformed request: " + e.getMessage(), e); 101 } 102 } 103 104 public int getVersionNumber() 105 { 106 return req.getTbsRequest().getVersion().getValue().intValue() + 1; 107 } 108 109 public GeneralName getRequestorName() 110 { 111 return GeneralName.getInstance(req.getTbsRequest().getRequestorName()); 112 } 113 114 public Req[] getRequestList() 115 { 116 ASN1Sequence seq = req.getTbsRequest().getRequestList(); 117 Req[] requests = new Req[seq.size()]; 118 119 for (int i = 0; i != requests.length; i++) 120 { 121 requests[i] = new Req(Request.getInstance(seq.getObjectAt(i))); 122 } 123 124 return requests; 125 } 126 127 public boolean hasExtensions() 128 { 129 return extensions != null; 130 } 131 132 public Extension getExtension(ASN1ObjectIdentifier oid) 133 { 134 if (extensions != null) 135 { 136 return extensions.getExtension(oid); 137 } 138 139 return null; 140 } 141 142 public List getExtensionOIDs() 143 { 144 return OCSPUtils.getExtensionOIDs(extensions); 145 } 146 147 public Set getCriticalExtensionOIDs() 148 { 149 return OCSPUtils.getCriticalExtensionOIDs(extensions); 150 } 151 152 public Set getNonCriticalExtensionOIDs() 153 { 154 return OCSPUtils.getNonCriticalExtensionOIDs(extensions); 155 } 156 157 /** 158 * return the object identifier representing the signature algorithm 159 */ 160 public ASN1ObjectIdentifier getSignatureAlgOID() 161 { 162 if (!this.isSigned()) 163 { 164 return null; 165 } 166 167 return req.getOptionalSignature().getSignatureAlgorithm().getAlgorithm(); 168 } 169 170 public byte[] getSignature() 171 { 172 if (!this.isSigned()) 173 { 174 return null; 175 } 176 177 return req.getOptionalSignature().getSignature().getOctets(); 178 } 179 180 public X509CertificateHolder[] getCerts() 181 { 182 // 183 // load the certificates if we have any 184 // 185 if (req.getOptionalSignature() != null) 186 { 187 ASN1Sequence s = req.getOptionalSignature().getCerts(); 188 189 if (s != null) 190 { 191 X509CertificateHolder[] certs = new X509CertificateHolder[s.size()]; 192 193 for (int i = 0; i != certs.length; i++) 194 { 195 certs[i] = new X509CertificateHolder(Certificate.getInstance(s.getObjectAt(i))); 196 } 197 198 return certs; 199 } 200 201 return EMPTY_CERTS; 202 } 203 else 204 { 205 return EMPTY_CERTS; 206 } 207 } 208 209 /** 210 * Return whether or not this request is signed. 211 * 212 * @return true if signed false otherwise. 213 */ 214 public boolean isSigned() 215 { 216 return req.getOptionalSignature() != null; 217 } 218 219 /** 220 * verify the signature against the TBSRequest object we contain. 221 */ 222 public boolean isSignatureValid( 223 ContentVerifierProvider verifierProvider) 224 throws OCSPException 225 { 226 if (!this.isSigned()) 227 { 228 throw new OCSPException("attempt to verify signature on unsigned object"); 229 } 230 231 try 232 { 233 ContentVerifier verifier = verifierProvider.get(req.getOptionalSignature().getSignatureAlgorithm()); 234 OutputStream sOut = verifier.getOutputStream(); 235 236 sOut.write(req.getTbsRequest().getEncoded(ASN1Encoding.DER)); 237 238 return verifier.verify(this.getSignature()); 239 } 240 catch (Exception e) 241 { 242 throw new OCSPException("exception processing signature: " + e, e); 243 } 244 } 245 246 /** 247 * return the ASN.1 encoded representation of this object. 248 */ 249 public byte[] getEncoded() 250 throws IOException 251 { 252 ByteArrayOutputStream bOut = new ByteArrayOutputStream(); 253 ASN1OutputStream aOut = new ASN1OutputStream(bOut); 254 255 aOut.writeObject(req); 256 257 return bOut.toByteArray(); 258 } 259} 260