Botan 3.4.0
Crypto and TLS for C&
ocsp.cpp
Go to the documentation of this file.
1/*
2* OCSP
3* (C) 2012,2013 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/ocsp.h>
9
10#include <botan/base64.h>
11#include <botan/ber_dec.h>
12#include <botan/certstor.h>
13#include <botan/der_enc.h>
14#include <botan/pubkey.h>
15#include <botan/x509_ext.h>
16#include <botan/internal/parsing.h>
17
18#include <functional>
19
20#if defined(BOTAN_HAS_HTTP_UTIL)
21 #include <botan/internal/http_util.h>
22#endif
23
24namespace Botan::OCSP {
25
26namespace {
27
28// TODO: should this be in a header somewhere?
29void decode_optional_list(BER_Decoder& ber, ASN1_Type tag, std::vector<X509_Certificate>& output) {
30 BER_Object obj = ber.get_next_object();
31
32 if(obj.is_a(tag, ASN1_Class::ContextSpecific | ASN1_Class::Constructed) == false) {
33 ber.push_back(obj);
34 return;
35 }
36
37 BER_Decoder list(obj);
38
39 while(list.more_items()) {
40 BER_Object certbits = list.get_next_object();
41 X509_Certificate cert(certbits.bits(), certbits.length());
42 output.push_back(std::move(cert));
43 }
44}
45
46} // namespace
47
48Request::Request(const X509_Certificate& issuer_cert, const X509_Certificate& subject_cert) :
49 m_issuer(issuer_cert), m_certid(m_issuer, BigInt::decode(subject_cert.serial_number())) {
50 if(subject_cert.issuer_dn() != issuer_cert.subject_dn()) {
51 throw Invalid_Argument("Invalid cert pair to OCSP::Request (mismatched issuer,subject args?)");
52 }
53}
54
55Request::Request(const X509_Certificate& issuer_cert, const BigInt& subject_serial) :
56 m_issuer(issuer_cert), m_certid(m_issuer, subject_serial) {}
57
58std::vector<uint8_t> Request::BER_encode() const {
59 std::vector<uint8_t> output;
60 DER_Encoder(output)
64 .encode(static_cast<size_t>(0)) // version #
68 .encode(m_certid)
69 .end_cons()
70 .end_cons()
71 .end_cons()
72 .end_cons();
73
74 return output;
75}
76
77std::string Request::base64_encode() const {
79}
80
82 m_status(Response_Status_Code::Successful), m_dummy_response_status(status) {}
83
84Response::Response(const uint8_t response_bits[], size_t response_bits_len) :
85 m_response_bits(response_bits, response_bits + response_bits_len) {
86 BER_Decoder response_outer = BER_Decoder(m_response_bits).start_sequence();
87
88 size_t resp_status = 0;
89
90 response_outer.decode(resp_status, ASN1_Type::Enumerated, ASN1_Class::Universal);
91
92 m_status = static_cast<Response_Status_Code>(resp_status);
93
94 if(m_status != Response_Status_Code::Successful) {
95 return;
96 }
97
98 if(response_outer.more_items()) {
99 BER_Decoder response_bytes = response_outer.start_context_specific(0).start_sequence();
100
101 response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"), "Unknown response type in OCSP response");
102
103 BER_Decoder basicresponse = BER_Decoder(response_bytes.get_next_octet_string()).start_sequence();
104
105 basicresponse.start_sequence()
106 .raw_bytes(m_tbs_bits)
107 .end_cons()
108 .decode(m_sig_algo)
109 .decode(m_signature, ASN1_Type::BitString);
110 decode_optional_list(basicresponse, ASN1_Type(0), m_certs);
111
112 size_t responsedata_version = 0;
113 Extensions extensions;
114
115 BER_Decoder(m_tbs_bits)
117
119
122
123 .decode(m_produced_at)
124
125 .decode_list(m_responses)
126
128
129 const bool has_signer = !m_signer_name.empty();
130 const bool has_key_hash = !m_key_hash.empty();
131
132 if(has_signer && has_key_hash) {
133 throw Decoding_Error("OCSP response includes both byName and byKey in responderID field");
134 }
135 if(!has_signer && !has_key_hash) {
136 throw Decoding_Error("OCSP response contains neither byName nor byKey in responderID field");
137 }
138 }
139
140 response_outer.end_cons();
141}
142
143bool Response::is_issued_by(const X509_Certificate& candidate) const {
144 if(!m_signer_name.empty()) {
145 return (candidate.subject_dn() == m_signer_name);
146 }
147
148 if(!m_key_hash.empty()) {
149 return (candidate.subject_public_key_bitstring_sha1() == m_key_hash);
150 }
151
152 return false;
153}
154
156 if(m_dummy_response_status) {
157 return m_dummy_response_status.value();
158 }
159
160 if(m_signer_name.empty() && m_key_hash.empty()) {
162 }
163
164 if(!is_issued_by(issuer)) {
166 }
167
168 try {
169 auto pub_key = issuer.subject_public_key();
170
171 PK_Verifier verifier(*pub_key, m_sig_algo);
172
173 if(verifier.verify_message(ASN1::put_in_sequence(m_tbs_bits), m_signature)) {
175 } else {
177 }
178 } catch(Exception&) {
180 }
181}
182
183std::optional<X509_Certificate> Response::find_signing_certificate(
184 const X509_Certificate& issuer_certificate, const Certificate_Store* trusted_ocsp_responders) const {
185 using namespace std::placeholders;
186
187 // Check whether the CA issuing the certificate in question also signed this
188 if(is_issued_by(issuer_certificate)) {
189 return issuer_certificate;
190 }
191
192 // Then try to find a delegated responder certificate in the stapled certs
193 auto match = std::find_if(m_certs.begin(), m_certs.end(), std::bind(&Response::is_issued_by, this, _1));
194 if(match != m_certs.end()) {
195 return *match;
196 }
197
198 // Last resort: check the additionally provides trusted OCSP responders
199 if(trusted_ocsp_responders) {
200 if(!m_key_hash.empty()) {
201 auto signing_cert = trusted_ocsp_responders->find_cert_by_pubkey_sha1(m_key_hash);
202 if(signing_cert) {
203 return signing_cert;
204 }
205 }
206
207 if(!m_signer_name.empty()) {
208 auto signing_cert = trusted_ocsp_responders->find_cert(m_signer_name, {});
209 if(signing_cert) {
210 return signing_cert;
211 }
212 }
213 }
214
215 return std::nullopt;
216}
217
219 const X509_Certificate& subject,
220 std::chrono::system_clock::time_point ref_time,
221 std::chrono::seconds max_age) const {
222 if(m_dummy_response_status) {
223 return m_dummy_response_status.value();
224 }
225
226 for(const auto& response : m_responses) {
227 if(response.certid().is_id_for(issuer, subject)) {
228 X509_Time x509_ref_time(ref_time);
229
230 if(response.cert_status() == 1) {
232 }
233
234 if(response.this_update() > x509_ref_time) {
236 }
237
238 if(response.next_update().time_is_set()) {
239 if(x509_ref_time > response.next_update()) {
241 }
242 } else if(max_age > std::chrono::seconds::zero() &&
243 ref_time - response.this_update().to_std_timepoint() > max_age) {
245 }
246
247 if(response.cert_status() == 0) {
249 } else {
251 }
252 }
253 }
254
256}
257
258#if defined(BOTAN_HAS_HTTP_UTIL)
259
260Response online_check(const X509_Certificate& issuer,
261 const BigInt& subject_serial,
262 std::string_view ocsp_responder,
263 std::chrono::milliseconds timeout) {
264 if(ocsp_responder.empty()) {
265 throw Invalid_Argument("No OCSP responder specified");
266 }
267
268 OCSP::Request req(issuer, subject_serial);
269
270 auto http = HTTP::POST_sync(ocsp_responder, "application/ocsp-request", req.BER_encode(), 1, timeout);
271
272 http.throw_unless_ok();
273
274 // Check the MIME type?
275
276 return OCSP::Response(http.body());
277}
278
279Response online_check(const X509_Certificate& issuer,
280 const X509_Certificate& subject,
281 std::chrono::milliseconds timeout) {
282 if(subject.issuer_dn() != issuer.subject_dn()) {
283 throw Invalid_Argument("Invalid cert pair to OCSP::online_check (mismatched issuer,subject args?)");
284 }
285
286 return online_check(issuer, BigInt::decode(subject.serial_number()), subject.ocsp_responder(), timeout);
287}
288
289#endif
290
291} // namespace Botan::OCSP
BER_Decoder & decode(bool &out)
Definition ber_dec.h:176
bool more_items() const
Definition ber_dec.cpp:195
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition ber_dec.h:162
std::vector< uint8_t > get_next_octet_string()
Definition ber_dec.h:188
BER_Decoder & end_cons()
Definition ber_dec.cpp:295
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Type type_tag=ASN1_Type::Sequence, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.h:364
BER_Decoder start_sequence()
Definition ber_dec.h:113
BER_Decoder start_context_specific(uint32_t tag)
Definition ber_dec.h:117
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
Definition ber_dec.h:317
BER_Decoder & decode_and_check(const T &expected, std::string_view error_msg)
Definition ber_dec.h:257
BER_Decoder & decode_optional_string(std::vector< uint8_t, Alloc > &out, ASN1_Type real_type, uint32_t expected_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:272
static BigInt decode(const uint8_t buf[], size_t length)
Definition bigint.h:773
virtual std::optional< X509_Certificate > find_cert_by_pubkey_sha1(const std::vector< uint8_t > &key_hash) const =0
virtual std::optional< X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const
Definition certstor.cpp:20
DER_Encoder & end_explicit()
Definition der_enc.cpp:200
DER_Encoder & start_explicit(uint16_t type_tag)
Definition der_enc.cpp:186
DER_Encoder & start_sequence()
Definition der_enc.h:65
DER_Encoder & end_cons()
Definition der_enc.cpp:171
DER_Encoder & encode(bool b)
Definition der_enc.cpp:250
std::string base64_encode() const
Definition ocsp.cpp:77
Request(const X509_Certificate &issuer_cert, const X509_Certificate &subject_cert)
Definition ocsp.cpp:48
std::vector< uint8_t > BER_encode() const
Definition ocsp.cpp:58
Response(Certificate_Status_Code status)
Definition ocsp.cpp:81
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
Definition ocsp.cpp:218
std::optional< X509_Certificate > find_signing_certificate(const X509_Certificate &issuer_certificate, const Certificate_Store *trusted_ocsp_responders=nullptr) const
Definition ocsp.cpp:183
Certificate_Status_Code verify_signature(const X509_Certificate &signing_certificate) const
Definition ocsp.cpp:155
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
Definition pubkey.cpp:368
const X509_DN & subject_dn() const
Definition x509cert.cpp:362
const std::vector< uint8_t > & subject_public_key_bitstring_sha1() const
Definition x509cert.cpp:334
const X509_DN & issuer_dn() const
Definition x509cert.cpp:358
std::unique_ptr< Public_Key > subject_public_key() const
Definition x509cert.cpp:546
bool empty() const
Definition pkix_types.h:66
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition asn1_obj.cpp:172
Response POST_sync(std::string_view url, std::string_view content_type, const std::vector< uint8_t > &body, size_t allowable_redirects, std::chrono::milliseconds timeout)
Response_Status_Code
Definition ocsp.h:113
ASN1_Type
Definition asn1_obj.h:43
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition base64.cpp:146
Certificate_Status_Code
Definition pkix_enums.h:20