aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/log.txt2
-rw-r--r--src/cert/ocsp/info.txt2
-rw-r--r--src/cert/ocsp/ocsp.cpp96
-rw-r--r--src/cert/ocsp/ocsp.h7
-rw-r--r--src/cert/ocsp/ocsp_types.cpp2
5 files changed, 91 insertions, 18 deletions
diff --git a/doc/log.txt b/doc/log.txt
index 9db96396b..701497220 100644
--- a/doc/log.txt
+++ b/doc/log.txt
@@ -29,6 +29,8 @@ Version 1.11.0, Not Yet Released
handles path validation and Certificate_Store handles storage of
certificates and CRLs.
+* Add support for OCSP
+
* TLS v1.2 is now supported
* TLS now supports session resumption. Session information can be
diff --git a/src/cert/ocsp/info.txt b/src/cert/ocsp/info.txt
index 5f2eb2ca5..0db22f687 100644
--- a/src/cert/ocsp/info.txt
+++ b/src/cert/ocsp/info.txt
@@ -1,7 +1,5 @@
define OCSP
-load_on never
-
<requires>
x509
sha1
diff --git a/src/cert/ocsp/ocsp.cpp b/src/cert/ocsp/ocsp.cpp
index c08f09efb..4dfaaad40 100644
--- a/src/cert/ocsp/ocsp.cpp
+++ b/src/cert/ocsp/ocsp.cpp
@@ -9,10 +9,11 @@
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/x509_ext.h>
+#include <botan/oids.h>
#include <botan/base64.h>
-
-#include <iostream>
-#include <botan/hex.h>
+#include <botan/pubkey.h>
+#include <botan/x509path.h>
+#include <memory>
namespace Botan {
@@ -42,6 +43,61 @@ void decode_optional_list(BER_Decoder& ber,
}
}
+bool check_signature(const std::vector<byte>& tbs_response,
+ const AlgorithmIdentifier& sig_algo,
+ const std::vector<byte>& signature,
+ const X509_Certificate& cert)
+ {
+ try
+ {
+ std::unique_ptr<Public_Key> pub_key(cert.subject_public_key());
+
+ const std::vector<std::string> sig_info =
+ split_on(OIDS::lookup(sig_algo.oid), '/');
+
+ if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
+ return false;
+
+ std::string padding = sig_info[1];
+ Signature_Format format =
+ (pub_key->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
+
+ PK_Verifier verifier(*pub_key, padding, format);
+
+ return verifier.verify_message(
+ ASN1::put_in_sequence(tbs_response), signature);
+ }
+ catch(std::exception& e)
+ {
+ return false;
+ }
+ }
+
+bool check_signature(const std::vector<byte>& tbs_response,
+ const AlgorithmIdentifier& sig_algo,
+ const std::vector<byte>& signature,
+ const Certificate_Store& trusted_roots,
+ const std::vector<X509_Certificate>& certs)
+ {
+ if(trusted_roots.certificate_known(certs[0]))
+ return check_signature(tbs_response, sig_algo, signature, certs[0]);
+
+ // Otherwise attempt to chain the signing cert to a trust root
+
+ Path_Validation_Result result =
+ x509_path_validate(certs,
+ Path_Validation_Restrictions(),
+ trusted_roots);
+
+ if(!result.successful_validation())
+ throw std::runtime_error("Certificate validation failure: " + result.result_string());
+
+ if(!trusted_roots.certificate_known(result.trust_root()))
+ throw std::runtime_error("Certificate chain roots in unknown/untrusted CA");
+
+ return check_signature(tbs_response, sig_algo, signature, result.cert_path()[0]);
+ }
+
}
std::vector<byte> Request::BER_encode() const
@@ -67,7 +123,8 @@ std::string Request::base64_encode() const
return Botan::base64_encode(BER_encode());
}
-Response::Response(const std::vector<byte>& response_bits)
+Response::Response(const Certificate_Store& trusted_roots,
+ const std::vector<byte>& response_bits)
{
BER_Decoder ber(response_bits);
@@ -83,7 +140,7 @@ Response::Response(const std::vector<byte>& response_bits)
response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE);
response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"),
- "Unknown response OID in OCSP response");
+ "Unknown response type in OCSP response");
std::vector<byte> response_vec;
response_bytes.decode(response_vec, OCTET_STRING);
@@ -91,17 +148,21 @@ Response::Response(const std::vector<byte>& response_bits)
BER_Decoder basicresponse_x(response_vec);
BER_Decoder basicresponse = basicresponse_x.start_cons(SEQUENCE);
- BER_Decoder tbs_response = basicresponse.start_cons(SEQUENCE);
+ std::vector<byte> tbs_bits;
AlgorithmIdentifier sig_algo;
std::vector<byte> signature;
-
- basicresponse.decode(sig_algo);
- basicresponse.decode(signature, BIT_STRING);
-
std::vector<X509_Certificate> certs;
+
+ basicresponse.start_cons(SEQUENCE)
+ .raw_bytes(tbs_bits)
+ .end_cons()
+ .decode(sig_algo)
+ .decode(signature, BIT_STRING);
decode_optional_list(basicresponse, ASN1_Tag(0), certs);
+ BER_Decoder tbs_response(tbs_bits);
+
size_t responsedata_version = 0;
X509_DN name;
std::vector<byte> key_hash;
@@ -125,16 +186,27 @@ Response::Response(const std::vector<byte>& response_bits)
Extensions extensions;
tbs_response.decode_optional(extensions, ASN1_Tag(1),
ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC));
+
+ if(certs.empty())
+ {
+ certs = trusted_roots.find_cert_by_subject_and_key_id(name, std::vector<byte>());
+ if(certs.empty())
+ throw std::runtime_error("Could not find certificate that signed OCSP response");
+ }
+
+ if(!check_signature(tbs_bits, sig_algo, signature, trusted_roots, certs))
+ throw std::runtime_error("Invalid OCSP response");
}
response_outer.end_cons();
}
-bool Response::affirmative_response_for(const Request& req)
+bool Response::affirmative_response_for(const X509_Certificate& issuer,
+ const X509_Certificate& subject) const
{
for(auto response : m_responses)
- if(response.affirmative_response_for(req.issuer(), req.subject()))
+ if(response.affirmative_response_for(issuer, subject))
return true;
return false;
diff --git a/src/cert/ocsp/ocsp.h b/src/cert/ocsp/ocsp.h
index f576ba41e..ad2d2cf81 100644
--- a/src/cert/ocsp/ocsp.h
+++ b/src/cert/ocsp/ocsp.h
@@ -9,6 +9,7 @@
#define BOTAN_OCSP_H__
#include <botan/ocsp_types.h>
+#include <botan/certstor.h>
namespace Botan {
@@ -37,9 +38,11 @@ class BOTAN_DLL Request
class BOTAN_DLL Response
{
public:
- Response(const std::vector<byte>& response);
+ Response(const Certificate_Store& trusted_roots,
+ const std::vector<byte>& response);
- bool affirmative_response_for(const Request&);
+ bool affirmative_response_for(const X509_Certificate& issuer,
+ const X509_Certificate& subject) const;
private:
std::vector<SingleResponse> m_responses;
diff --git a/src/cert/ocsp/ocsp_types.cpp b/src/cert/ocsp/ocsp_types.cpp
index bead099ab..14e3f393f 100644
--- a/src/cert/ocsp/ocsp_types.cpp
+++ b/src/cert/ocsp/ocsp_types.cpp
@@ -9,11 +9,9 @@
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/x509_ext.h>
-
#include <botan/lookup.h>
#include <botan/hash.h>
#include <botan/oids.h>
-
#include <memory>
namespace Botan {