8 #include <botan/ocsp.h>
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/x509path.h>
18 #if defined(BOTAN_HAS_HTTP_UTIL)
19 #include <botan/http_util.h>
29 void 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.value);
43 while(list.more_items())
45 BER_Object certbits = list.get_next_object();
46 X509_Certificate cert(
unlock(certbits.value));
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)
74 .
encode(static_cast<size_t>(0))
91 m_response_bits(response_bits, response_bits + response_bits_len)
95 size_t resp_status = 0;
108 "Unknown response type in OCSP response");
118 decode_optional_list(basicresponse,
ASN1_Tag(0), m_certs);
120 size_t responsedata_version = 0;
150 const std::vector<std::string> sig_info =
153 if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
156 std::string padding = sig_info[1];
173 const std::vector<std::shared_ptr<const X509_Certificate>>& ee_cert_path)
const
175 std::shared_ptr<const X509_Certificate> signing_cert;
177 for(
size_t i = 0; i != trusted_roots.size(); ++i)
179 if(m_signer_name.
empty() && m_key_hash.empty())
182 if(!m_signer_name.
empty())
184 signing_cert = trusted_roots[i]->find_cert(m_signer_name, std::vector<uint8_t>());
191 if(m_key_hash.size() > 0)
193 signing_cert = trusted_roots[i]->find_cert_by_pubkey_sha1(m_key_hash);
201 if(!signing_cert && ee_cert_path.size() > 1)
204 for(
size_t i = 1; i < ee_cert_path.size(); ++i)
207 if(!m_signer_name.
empty() && ee_cert_path[i]->subject_dn() == m_signer_name)
209 signing_cert = ee_cert_path[i];
213 if(m_key_hash.size() > 0 && ee_cert_path[i]->subject_public_key_bitstring_sha1() == m_key_hash)
215 signing_cert = ee_cert_path[i];
221 if(!signing_cert && m_certs.size() > 0)
223 for(
size_t i = 0; i < m_certs.size(); ++i)
226 if(!m_signer_name.
empty() && m_certs[i].subject_dn() == m_signer_name)
228 signing_cert = std::make_shared<const X509_Certificate>(m_certs[i]);
232 if(m_key_hash.size() > 0 && m_certs[i].subject_public_key_bitstring_sha1() == m_key_hash)
234 signing_cert = std::make_shared<const X509_Certificate>(m_certs[i]);
243 if(!signing_cert->allowed_usage(
CRL_SIGN) &&
244 !signing_cert->allowed_extended_usage(
"PKIX.OCSPSigning"))
254 std::chrono::system_clock::time_point ref_time)
const
256 for(
const auto& response : m_responses)
258 if(response.certid().is_id_for(issuer, subject))
262 if(response.cert_status() == 1)
265 if(response.this_update() > x509_ref_time)
268 if(response.next_update().time_is_set() && x509_ref_time > response.next_update())
271 if(response.cert_status() == 0)
281 #if defined(BOTAN_HAS_HTTP_UTIL)
284 const BigInt& subject_serial,
285 const std::string& ocsp_responder,
288 if(ocsp_responder.empty())
294 "application/ocsp-request",
297 http.throw_unless_ok();
303 std::vector<Certificate_Store*> trusted_roots_vec;
304 trusted_roots_vec.push_back(trusted_roots);
318 throw Invalid_Argument(
"Invalid cert pair to OCSP::online_check (mismatched issuer,subject args?)");
320 return online_check(issuer,
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()) const
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
std::vector< uint8_t > serial_number() const
std::vector< uint8_t > get_contents_unlocked()
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
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)
Certificate_Status_Code check_signature(const std::vector< Certificate_Store * > &trust_roots, const std::vector< std::shared_ptr< const X509_Certificate >> &cert_path={}) const
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
std::string base64_encode() const
std::vector< std::string > split_on(const std::string &str, char delim)
std::string ocsp_responder() const
BER_Decoder & decode(bool &v)
DER_Encoder & end_explicit()
std::string to_string(const BER_Object &obj)
DER_Encoder & encode(bool b)
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
std::string lookup(const OID &oid)
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Response POST_sync(const std::string &url, const std::string &content_type, const std::vector< uint8_t > &body, size_t allowable_redirects)
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Request(const X509_Certificate &issuer_cert, const X509_Certificate &subject_cert)
std::vector< T > unlock(const secure_vector< T > &in)
X509_DN issuer_dn() const
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
DER_Encoder & 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)
Public_Key * subject_public_key() const
std::vector< uint8_t > get_next_octet_string()
BER_Decoder & raw_bytes(secure_vector< uint8_t > &v)
X509_DN subject_dn() const
Certificate_Status_Code verify_signature(const X509_Certificate &issuer) const
static BigInt decode(const uint8_t buf[], size_t length, Base base=Binary)
DER_Encoder & start_explicit(uint16_t type_tag)
std::vector< uint8_t > BER_encode() const