aboutsummaryrefslogtreecommitdiffstats
path: root/src/cert/ocsp/ocsp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cert/ocsp/ocsp.cpp')
-rw-r--r--src/cert/ocsp/ocsp.cpp252
1 files changed, 0 insertions, 252 deletions
diff --git a/src/cert/ocsp/ocsp.cpp b/src/cert/ocsp/ocsp.cpp
deleted file mode 100644
index 2ea413e76..000000000
--- a/src/cert/ocsp/ocsp.cpp
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
-* OCSP
-* (C) 2012,2013 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/ocsp.h>
-#include <botan/certstor.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/x509_ext.h>
-#include <botan/oids.h>
-#include <botan/base64.h>
-#include <botan/pubkey.h>
-#include <botan/x509path.h>
-#include <botan/http_util.h>
-#include <memory>
-
-namespace Botan {
-
-namespace OCSP {
-
-namespace {
-
-void decode_optional_list(BER_Decoder& ber,
- ASN1_Tag tag,
- std::vector<X509_Certificate>& output)
- {
- BER_Object obj = ber.get_next_object();
-
- if(obj.type_tag != tag || obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED))
- {
- ber.push_back(obj);
- return;
- }
-
- BER_Decoder list(obj.value);
-
- while(list.more_items())
- {
- BER_Object certbits = list.get_next_object();
- X509_Certificate cert(unlock(certbits.value));
- output.push_back(std::move(cert));
- }
- }
-
-void check_signature(const std::vector<byte>& tbs_response,
- const AlgorithmIdentifier& sig_algo,
- const std::vector<byte>& signature,
- const X509_Certificate& cert)
- {
- 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())
- throw std::runtime_error("Information in OCSP response does not match cert");
-
- 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);
-
- if(!verifier.verify_message(ASN1::put_in_sequence(tbs_response), signature))
- throw std::runtime_error("Signature on OCSP response does not verify");
- }
-
-void 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(certs.size() < 1)
- throw std::invalid_argument("Short cert chain for check_signature");
-
- 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
-
- if(!certs[0].allowed_usage("PKIX.OCSPSigning"))
- throw std::runtime_error("OCSP response cert does not allow OCSP signing");
-
- auto 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())) // not needed anymore?
- throw std::runtime_error("Certificate chain roots in unknown/untrusted CA");
-
- const std::vector<X509_Certificate>& cert_path = result.cert_path();
-
- check_signature(tbs_response, sig_algo, signature, cert_path[0]);
- }
-
-}
-
-std::vector<byte> Request::BER_encode() const
- {
- CertID certid(m_issuer, m_subject);
-
- return DER_Encoder().start_cons(SEQUENCE)
- .start_cons(SEQUENCE)
- .start_explicit(0)
- .encode(static_cast<size_t>(0)) // version #
- .end_explicit()
- .start_cons(SEQUENCE)
- .start_cons(SEQUENCE)
- .encode(certid)
- .end_cons()
- .end_cons()
- .end_cons()
- .end_cons().get_contents_unlocked();
- }
-
-std::string Request::base64_encode() const
- {
- return Botan::base64_encode(BER_encode());
- }
-
-Response::Response(const Certificate_Store& trusted_roots,
- const std::vector<byte>& response_bits)
- {
- BER_Decoder response_outer = BER_Decoder(response_bits).start_cons(SEQUENCE);
-
- size_t resp_status = 0;
-
- response_outer.decode(resp_status, ENUMERATED, UNIVERSAL);
-
- if(resp_status != 0)
- throw std::runtime_error("OCSP response status " + std::to_string(resp_status));
-
- if(response_outer.more_items())
- {
- BER_Decoder response_bytes =
- 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 type in OCSP response");
-
- BER_Decoder basicresponse =
- BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE);
-
- std::vector<byte> tbs_bits;
- AlgorithmIdentifier sig_algo;
- std::vector<byte> signature;
- 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);
-
- size_t responsedata_version = 0;
- X509_DN name;
- std::vector<byte> key_hash;
- X509_Time produced_at;
- Extensions extensions;
-
- BER_Decoder(tbs_bits)
- .decode_optional(responsedata_version, ASN1_Tag(0),
- ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
-
- .decode_optional(name, ASN1_Tag(1),
- ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
-
- .decode_optional_string(key_hash, ASN1_Tag(2),
- ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
-
- .decode(produced_at)
-
- .decode_list(m_responses)
-
- .decode_optional(extensions, ASN1_Tag(1),
- ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC));
-
- if(certs.empty())
- {
- if(auto cert = trusted_roots.find_cert(name, std::vector<byte>()))
- certs.push_back(*cert);
- else
- throw std::runtime_error("Could not find certificate that signed OCSP response");
- }
-
- check_signature(tbs_bits, sig_algo, signature, trusted_roots, certs);
- }
-
- response_outer.end_cons();
- }
-
-Certificate_Status_Code Response::status_for(const X509_Certificate& issuer,
- const X509_Certificate& subject) const
- {
- for(const auto& response : m_responses)
- {
- if(response.certid().is_id_for(issuer, subject))
- {
- X509_Time current_time(std::chrono::system_clock::now());
-
- if(response.this_update() > current_time)
- return Certificate_Status_Code::OCSP_NOT_YET_VALID;
-
- if(response.next_update().time_is_set() && current_time > response.next_update())
- return Certificate_Status_Code::OCSP_EXPIRED;
-
- if(response.cert_status() == 1)
- return Certificate_Status_Code::CERT_IS_REVOKED;
- else if(response.cert_status() == 0)
- return Certificate_Status_Code::OCSP_RESPONSE_GOOD;
- else
- return Certificate_Status_Code::OCSP_BAD_STATUS;
- }
- }
-
- return Certificate_Status_Code::OCSP_CERT_NOT_LISTED;
- }
-
-Response online_check(const X509_Certificate& issuer,
- const X509_Certificate& subject,
- const Certificate_Store& trusted_roots)
- {
- const std::string responder_url = subject.ocsp_responder();
-
- if(responder_url == "")
- throw std::runtime_error("No OCSP responder specified");
-
- OCSP::Request req(issuer, subject);
-
- auto http = HTTP::POST_sync(responder_url,
- "application/ocsp-request",
- req.BER_encode());
-
- if(http.status_code() != 200)
- throw std::runtime_error("HTTP error: " + http.status_message());
-
- // Check the MIME type?
-
- OCSP::Response response(trusted_roots, http.body());
-
- return response;
- }
-
-}
-
-}