9#include <botan/certstor.h>
10#include <botan/der_enc.h>
11#include <botan/ber_dec.h>
12#include <botan/x509_ext.h>
13#include <botan/oids.h>
14#include <botan/base64.h>
15#include <botan/pubkey.h>
16#include <botan/parsing.h>
18#if defined(BOTAN_HAS_HTTP_UTIL)
19 #include <botan/http_util.h>
29void decode_optional_list(BER_Decoder& ber,
31 std::vector<X509_Certificate>& output)
33 BER_Object obj = ber.get_next_object();
41 BER_Decoder list(obj);
43 while(list.more_items())
45 BER_Object certbits = list.get_next_object();
46 X509_Certificate cert(certbits.bits(), certbits.length());
47 output.push_back(std::move(cert));
55 m_issuer(issuer_cert),
56 m_certid(m_issuer,
BigInt::
decode(subject_cert.serial_number()))
59 throw Invalid_Argument(
"Invalid cert pair to OCSP::Request (mismatched issuer,subject args?)");
63 const BigInt& subject_serial) :
64 m_issuer(issuer_cert),
65 m_certid(m_issuer, subject_serial)
71 std::vector<uint8_t> output;
75 .
encode(
static_cast<size_t>(0))
96 m_dummy_response_status =
status;
100 m_response_bits(response_bits, response_bits + response_bits_len)
106 size_t resp_status = 0;
121 "Unknown response type in OCSP response");
131 decode_optional_list(basicresponse,
ASN1_Tag(0), m_certs);
133 size_t responsedata_version = 0;
159 if (m_responses.empty())
160 return m_dummy_response_status;
166 const std::vector<std::string> sig_info =
169 if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
172 std::string padding = sig_info[1];
189 const std::vector<std::shared_ptr<const X509_Certificate>>& ee_cert_path)
const
191 if (m_responses.empty())
192 return m_dummy_response_status;
194 std::shared_ptr<const X509_Certificate> signing_cert;
196 for(
size_t i = 0; i != trusted_roots.size(); ++i)
198 if(m_signer_name.
empty() && m_key_hash.empty())
201 if(!m_signer_name.
empty())
203 signing_cert = trusted_roots[i]->find_cert(m_signer_name, std::vector<uint8_t>());
210 if(m_key_hash.size() > 0)
212 signing_cert = trusted_roots[i]->find_cert_by_pubkey_sha1(m_key_hash);
220 if(!signing_cert && ee_cert_path.size() > 1)
223 for(
size_t i = 1; i < ee_cert_path.size(); ++i)
226 if(!m_signer_name.
empty() && ee_cert_path[i]->subject_dn() == m_signer_name)
228 signing_cert = ee_cert_path[i];
232 if(m_key_hash.size() > 0 && ee_cert_path[i]->subject_public_key_bitstring_sha1() == m_key_hash)
234 signing_cert = ee_cert_path[i];
240 if(!signing_cert && m_certs.size() > 0)
242 for(
size_t i = 0; i < m_certs.size(); ++i)
245 if(!m_signer_name.
empty() && m_certs[i].subject_dn() == m_signer_name)
247 signing_cert = std::make_shared<const X509_Certificate>(m_certs[i]);
251 if(m_key_hash.size() > 0 && m_certs[i].subject_public_key_bitstring_sha1() == m_key_hash)
253 signing_cert = std::make_shared<const X509_Certificate>(m_certs[i]);
262 if(!signing_cert->allowed_usage(
CRL_SIGN) &&
263 !signing_cert->allowed_extended_usage(
"PKIX.OCSPSigning"))
273 std::chrono::system_clock::time_point ref_time,
274 std::chrono::seconds max_age)
const
276 if(m_responses.empty())
277 {
return m_dummy_response_status; }
279 for(
const auto& response : m_responses)
281 if(response.certid().is_id_for(issuer, subject))
285 if(response.cert_status() == 1)
288 if(response.this_update() > x509_ref_time)
291 if(response.next_update().time_is_set())
293 if(x509_ref_time > response.next_update())
296 else if(max_age > std::chrono::seconds::zero() && ref_time - response.this_update().to_std_timepoint() > max_age)
299 if(response.cert_status() == 0)
309#if defined(BOTAN_HAS_HTTP_UTIL)
312 const BigInt& subject_serial,
313 const std::string& ocsp_responder,
315 std::chrono::milliseconds timeout)
317 if(ocsp_responder.empty())
323 "application/ocsp-request",
328 http.throw_unless_ok();
334 std::vector<Certificate_Store*> trusted_roots_vec;
335 trusted_roots_vec.push_back(trusted_roots);
338 response.check_signature(trusted_roots_vec);
347 std::chrono::milliseconds timeout)
350 throw Invalid_Argument(
"Invalid cert pair to OCSP::online_check (mismatched issuer,subject args?)");
352 return online_check(issuer,
const OID & get_oid() const
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Tag type_tag=SEQUENCE, ASN1_Tag class_tag=UNIVERSAL)
BER_Decoder & decode(bool &out)
BER_Decoder & decode_optional_string(std::vector< uint8_t, Alloc > &out, ASN1_Tag real_type, uint16_t type_no, ASN1_Tag class_tag=CONTEXT_SPECIFIC)
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
std::vector< uint8_t > get_next_octet_string()
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
static BigInt decode(const uint8_t buf[], size_t length)
DER_Encoder & end_explicit()
DER_Encoder & start_explicit(uint16_t type_tag)
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
DER_Encoder & encode(bool b)
std::string base64_encode() const
Request(const X509_Certificate &issuer_cert, const X509_Certificate &subject_cert)
std::vector< uint8_t > BER_encode() const
Certificate_Status_Code status_for(const X509_Certificate &issuer, const X509_Certificate &subject, std::chrono::system_clock::time_point ref_time=std::chrono::system_clock::now(), std::chrono::seconds max_age=std::chrono::seconds::zero()) const
Response_Status_Code status() const
Certificate_Status_Code check_signature(const std::vector< Certificate_Store * > &trust_roots, const std::vector< std::shared_ptr< const X509_Certificate > > &cert_path={}) const
Certificate_Status_Code verify_signature(const X509_Certificate &issuer) const
std::string to_formatted_string() const
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
const std::vector< uint8_t > & serial_number() const
const X509_DN & subject_dn() const
const X509_DN & issuer_dn() const
std::string ocsp_responder() const
Public_Key * subject_public_key() const
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Response POST_sync(const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects, std::chrono::milliseconds timeout)
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
std::vector< std::string > split_on(const std::string &str, char delim)
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
@ OCSP_RESPONSE_MISSING_KEYUSAGE