diff options
author | David Hook <dgh@cryptoworkshop.com> | 2013-05-12 09:21:33 +0400 |
---|---|---|
committer | David Hook <dgh@cryptoworkshop.com> | 2013-05-12 09:21:33 +0400 |
commit | bcd5d7192db73ea15afbeb35b00d6d8e2ebed765 (patch) | |
tree | d4aaad17e8cefc8fe2415fc373aa62d22dd25f59 | |
parent | 9f94c6cae30c0d8296564fbc146248c8da6a5ff1 (diff) |
BJA-438 fixed constructors to detect empty data
3 files changed, 284 insertions, 100 deletions
diff --git a/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java b/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java index 8a376952..7e50621a 100644 --- a/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java +++ b/src/main/java/org/bouncycastle/cert/ocsp/OCSPReq.java @@ -1,27 +1,37 @@ -package org.bouncycastle.cert.ocsp; +package org.bouncycastle.ocsp; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; +import java.io.InputStream; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PublicKey; +import java.security.Signature; +import java.security.cert.CertStore; +import java.security.cert.CertStoreParameters; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.CollectionCertStoreParameters; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; import java.util.List; import java.util.Set; +import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Encoding; -import org.bouncycastle.asn1.ASN1Exception; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1OutputStream; import org.bouncycastle.asn1.ASN1Sequence; import org.bouncycastle.asn1.ocsp.OCSPRequest; import org.bouncycastle.asn1.ocsp.Request; -import org.bouncycastle.asn1.x509.Certificate; -import org.bouncycastle.asn1.x509.Extension; -import org.bouncycastle.asn1.x509.Extensions; import org.bouncycastle.asn1.x509.GeneralName; -import org.bouncycastle.cert.CertIOException; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.operator.ContentVerifier; -import org.bouncycastle.operator.ContentVerifierProvider; +import org.bouncycastle.asn1.x509.X509Extension; +import org.bouncycastle.asn1.x509.X509Extensions; /** * <pre> @@ -52,19 +62,18 @@ import org.bouncycastle.operator.ContentVerifierProvider; * issuerKeyHash OCTET STRING, -- Hash of Issuers public key * serialNumber CertificateSerialNumber } * </pre> + * + * @deprecated use classes in org.bouncycastle.cert.ocsp. */ public class OCSPReq + implements java.security.cert.X509Extension { - private static final X509CertificateHolder[] EMPTY_CERTS = new X509CertificateHolder[0]; - - private OCSPRequest req; - private Extensions extensions; + private OCSPRequest req; public OCSPReq( OCSPRequest req) { this.req = req; - this.extensions = req.getTbsRequest().getRequestExtensions(); } public OCSPReq( @@ -74,34 +83,54 @@ public class OCSPReq this(new ASN1InputStream(req)); } + public OCSPReq( + InputStream in) + throws IOException + { + this(new ASN1InputStream(in)); + } + private OCSPReq( - ASN1InputStream aIn) + ASN1InputStream aIn) throws IOException { try { this.req = OCSPRequest.getInstance(aIn.readObject()); - this.extensions = req.getTbsRequest().getRequestExtensions(); } catch (IllegalArgumentException e) { - throw new CertIOException("malformed request: " + e.getMessage(), e); + throw new IOException("malformed request: " + e.getMessage()); } catch (ClassCastException e) { - throw new CertIOException("malformed request: " + e.getMessage(), e); + throw new IOException("malformed request: " + e.getMessage()); + } + } + + /** + * Return the DER encoding of the tbsRequest field. + * @return DER encoding of tbsRequest + * @throws OCSPException in the event of an encoding error. + */ + public byte[] getTBSRequest() + throws OCSPException + { + try + { + return req.getTbsRequest().getEncoded(); } - catch (ASN1Exception e) + catch (IOException e) { - throw new CertIOException("malformed request: " + e.getMessage(), e); + throw new OCSPException("problem encoding tbsRequest", e); } } - - public int getVersionNumber() + + public int getVersion() { return req.getTbsRequest().getVersion().getValue().intValue() + 1; } - + public GeneralName getRequestorName() { return GeneralName.getInstance(req.getTbsRequest().getRequestorName()); @@ -120,47 +149,22 @@ public class OCSPReq return requests; } - public boolean hasExtensions() - { - return extensions != null; - } - - public Extension getExtension(ASN1ObjectIdentifier oid) - { - if (extensions != null) - { - return extensions.getExtension(oid); - } - - return null; - } - - public List getExtensionOIDs() + public X509Extensions getRequestExtensions() { - return OCSPUtils.getExtensionOIDs(extensions); - } - - public Set getCriticalExtensionOIDs() - { - return OCSPUtils.getCriticalExtensionOIDs(extensions); - } - - public Set getNonCriticalExtensionOIDs() - { - return OCSPUtils.getNonCriticalExtensionOIDs(extensions); + return X509Extensions.getInstance(req.getTbsRequest().getRequestExtensions()); } /** * return the object identifier representing the signature algorithm */ - public ASN1ObjectIdentifier getSignatureAlgOID() + public String getSignatureAlgOID() { if (!this.isSigned()) { return null; } - return req.getOptionalSignature().getSignatureAlgorithm().getAlgorithm(); + return req.getOptionalSignature().getSignatureAlgorithm().getObjectId().getId(); } public byte[] getSignature() @@ -172,33 +176,104 @@ public class OCSPReq return req.getOptionalSignature().getSignature().getBytes(); } - - public X509CertificateHolder[] getCerts() + + private List getCertList( + String provider) + throws OCSPException, NoSuchProviderException { + List certs = new ArrayList(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ASN1OutputStream aOut = new ASN1OutputStream(bOut); + CertificateFactory cf; + + try + { + cf = OCSPUtil.createX509CertificateFactory(provider); + } + catch (CertificateException ex) + { + throw new OCSPException("can't get certificate factory.", ex); + } + // // load the certificates if we have any // - if (req.getOptionalSignature() != null) + ASN1Sequence s = req.getOptionalSignature().getCerts(); + + if (s != null) { - ASN1Sequence s = req.getOptionalSignature().getCerts(); + Enumeration e = s.getObjects(); - if (s != null) + while (e.hasMoreElements()) { - X509CertificateHolder[] certs = new X509CertificateHolder[s.size()]; + try + { + aOut.writeObject((ASN1Encodable)e.nextElement()); - for (int i = 0; i != certs.length; i++) + certs.add(cf.generateCertificate( + new ByteArrayInputStream(bOut.toByteArray()))); + } + catch (IOException ex) + { + throw new OCSPException( + "can't re-encode certificate!", ex); + } + catch (CertificateException ex) { - certs[i] = new X509CertificateHolder(Certificate.getInstance(s.getObjectAt(i))); + throw new OCSPException( + "can't re-encode certificate!", ex); } - return certs; + bOut.reset(); } - - return EMPTY_CERTS; } - else + + return certs; + } + + public X509Certificate[] getCerts( + String provider) + throws OCSPException, NoSuchProviderException + { + if (!this.isSigned()) + { + return null; + } + + List certs = this.getCertList(provider); + + return (X509Certificate[])certs.toArray(new X509Certificate[certs.size()]); + } + + /** + * If the request is signed return a possibly empty CertStore containing the certificates in the + * request. If the request is not signed the method returns null. + * + * @param type type of CertStore to return + * @param provider provider to use + * @return null if not signed, a CertStore otherwise + * @throws NoSuchAlgorithmException + * @throws NoSuchProviderException + * @throws OCSPException + */ + public CertStore getCertificates( + String type, + String provider) + throws NoSuchAlgorithmException, NoSuchProviderException, OCSPException + { + if (!this.isSigned()) + { + return null; + } + + try + { + CertStoreParameters params = new CollectionCertStoreParameters(this.getCertList(provider)); + return OCSPUtil.createCertStoreInstance(type, params, provider); + } + catch (InvalidAlgorithmParameterException e) { - return EMPTY_CERTS; + throw new OCSPException("can't setup the CertStore", e); } } @@ -215,9 +290,10 @@ public class OCSPReq /** * verify the signature against the TBSRequest object we contain. */ - public boolean isSignatureValid( - ContentVerifierProvider verifierProvider) - throws OCSPException + public boolean verify( + PublicKey key, + String sigProvider) + throws OCSPException, NoSuchProviderException { if (!this.isSigned()) { @@ -226,16 +302,27 @@ public class OCSPReq try { - ContentVerifier verifier = verifierProvider.get(req.getOptionalSignature().getSignatureAlgorithm()); - OutputStream sOut = verifier.getOutputStream(); + Signature signature = OCSPUtil.createSignatureInstance(this.getSignatureAlgOID(), sigProvider); + + signature.initVerify(key); + + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ASN1OutputStream aOut = new ASN1OutputStream(bOut); + + aOut.writeObject(req.getTbsRequest()); - sOut.write(req.getTbsRequest().getEncoded(ASN1Encoding.DER)); + signature.update(bOut.toByteArray()); - return verifier.verify(this.getSignature()); + return signature.verify(this.getSignature()); + } + catch (NoSuchProviderException e) + { + // TODO Why this special case? + throw e; } catch (Exception e) { - throw new OCSPException("exception processing signature: " + e, e); + throw new OCSPException("exception processing sig: " + e, e); } } @@ -252,4 +339,79 @@ public class OCSPReq return bOut.toByteArray(); } + + /** + * RFC 2650 doesn't specify any critical extensions so we return true + * if any are encountered. + * + * @return true if any critical extensions are present. + */ + public boolean hasUnsupportedCriticalExtension() + { + Set extns = getCriticalExtensionOIDs(); + if (extns != null && !extns.isEmpty()) + { + return true; + } + + return false; + } + + private Set getExtensionOIDs(boolean critical) + { + Set set = new HashSet(); + X509Extensions extensions = this.getRequestExtensions(); + + if (extensions != null) + { + Enumeration e = extensions.oids(); + + while (e.hasMoreElements()) + { + ASN1ObjectIdentifier oid = (ASN1ObjectIdentifier)e.nextElement(); + X509Extension ext = extensions.getExtension(oid); + + if (critical == ext.isCritical()) + { + set.add(oid.getId()); + } + } + } + + return set; + } + + public Set getCriticalExtensionOIDs() + { + return getExtensionOIDs(true); + } + + public Set getNonCriticalExtensionOIDs() + { + return getExtensionOIDs(false); + } + + public byte[] getExtensionValue(String oid) + { + X509Extensions exts = this.getRequestExtensions(); + + if (exts != null) + { + X509Extension ext = exts.getExtension(new ASN1ObjectIdentifier(oid)); + + if (ext != null) + { + try + { + return ext.getValue().getEncoded(ASN1Encoding.DER); + } + catch (Exception e) + { + throw new RuntimeException("error encoding " + e.toString()); + } + } + } + + return null; + } } diff --git a/src/main/java/org/bouncycastle/cert/ocsp/OCSPResp.java b/src/main/java/org/bouncycastle/cert/ocsp/OCSPResp.java index 43c240fc..978c9411 100644 --- a/src/main/java/org/bouncycastle/cert/ocsp/OCSPResp.java +++ b/src/main/java/org/bouncycastle/cert/ocsp/OCSPResp.java @@ -1,48 +1,49 @@ -package org.bouncycastle.cert.ocsp; +package org.bouncycastle.ocsp; -import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import org.bouncycastle.asn1.ASN1Exception; import org.bouncycastle.asn1.ASN1InputStream; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.ocsp.BasicOCSPResponse; import org.bouncycastle.asn1.ocsp.OCSPObjectIdentifiers; import org.bouncycastle.asn1.ocsp.OCSPResponse; import org.bouncycastle.asn1.ocsp.ResponseBytes; -import org.bouncycastle.cert.CertIOException; +/** + * @deprecated use classes in org.bouncycastle.cert.ocsp. + */ public class OCSPResp { - public static final int SUCCESSFUL = 0; // Response has valid confirmations - public static final int MALFORMED_REQUEST = 1; // Illegal confirmation request - public static final int INTERNAL_ERROR = 2; // Internal error in issuer - public static final int TRY_LATER = 3; // Try again later - // (4) is not used - public static final int SIG_REQUIRED = 5; // Must sign the request - public static final int UNAUTHORIZED = 6; // Request unauthorized - private OCSPResponse resp; + /** + * @deprecated use classes in org.bouncycastle.cert.ocsp. + */ public OCSPResp( OCSPResponse resp) { this.resp = resp; } + /** + * @deprecated use classes in org.bouncycastle.cert.ocsp. + */ public OCSPResp( byte[] resp) throws IOException { - this(new ByteArrayInputStream(resp)); + this(new ASN1InputStream(resp)); } + /** + * @deprecated use classes in org.bouncycastle.cert.ocsp. + */ public OCSPResp( - InputStream resp) + InputStream in) throws IOException { - this(new ASN1InputStream(resp)); + this(new ASN1InputStream(in)); } private OCSPResp( @@ -55,15 +56,11 @@ public class OCSPResp } catch (IllegalArgumentException e) { - throw new CertIOException("malformed response: " + e.getMessage(), e); + throw new IOException("malformed response: " + e.getMessage()); } catch (ClassCastException e) { - throw new CertIOException("malformed response: " + e.getMessage(), e); - } - catch (ASN1Exception e) - { - throw new CertIOException("malformed response: " + e.getMessage(), e); + throw new IOException("malformed response: " + e.getMessage()); } } @@ -128,9 +125,4 @@ public class OCSPResp { return resp.hashCode(); } - - public OCSPResponse toASN1Structure() - { - return resp; - } } diff --git a/src/test/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java b/src/test/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java index 06a8ef29..5df298ae 100644 --- a/src/test/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java +++ b/src/test/java/org/bouncycastle/cert/ocsp/test/OCSPTest.java @@ -1,5 +1,6 @@ package org.bouncycastle.cert.ocsp.test; +import java.io.IOException; import java.math.BigInteger; import java.security.KeyPair; import java.security.Security; @@ -931,6 +932,35 @@ public class OCSPTest testRSA(); testIrregularVersionReq(); testInvalidResp(); + + // + // Empty data test + // + try + { + response = new OCSPResp(new byte[0]); + fail("no exception thrown"); + } + catch (IOException e) + { + if (!e.getMessage().equals("malformed response: no response data found")) + { + fail("wrong exception"); + } + } + + try + { + req = new OCSPReq(new byte[0]); + fail("no exception thrown"); + } + catch (IOException e) + { + if (!e.getMessage().equals("malformed request: no request data found")) + { + fail("wrong exception"); + } + } } public static void main( |