Botan 3.0.0-alpha0
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#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/internal/parsing.h>
17
18#if defined(BOTAN_HAS_HTTP_UTIL)
19 #include <botan/internal/http_util.h>
20#endif
21
22namespace Botan::OCSP {
23
24namespace {
25
26// TODO: should this be in a header somewhere?
27void decode_optional_list(BER_Decoder& ber,
28 ASN1_Type tag,
29 std::vector<X509_Certificate>& output)
30 {
31 BER_Object obj = ber.get_next_object();
32
33 if(obj.is_a(tag, ASN1_Class::ContextSpecific | ASN1_Class::Constructed) == false)
34 {
35 ber.push_back(obj);
36 return;
37 }
38
39 BER_Decoder list(obj);
40
41 while(list.more_items())
42 {
43 BER_Object certbits = list.get_next_object();
44 X509_Certificate cert(certbits.bits(), certbits.length());
45 output.push_back(std::move(cert));
46 }
47 }
48
49}
50
52 const X509_Certificate& subject_cert) :
53 m_issuer(issuer_cert),
54 m_certid(m_issuer, BigInt::decode(subject_cert.serial_number()))
55 {
56 if(subject_cert.issuer_dn() != issuer_cert.subject_dn())
57 throw Invalid_Argument("Invalid cert pair to OCSP::Request (mismatched issuer,subject args?)");
58 }
59
61 const BigInt& subject_serial) :
62 m_issuer(issuer_cert),
63 m_certid(m_issuer, subject_serial)
64 {
65 }
66
67std::vector<uint8_t> Request::BER_encode() const
68 {
69 std::vector<uint8_t> output;
73 .encode(static_cast<size_t>(0)) // version #
77 .encode(m_certid)
78 .end_cons()
79 .end_cons()
80 .end_cons()
81 .end_cons();
82
83 return output;
84 }
85
86std::string Request::base64_encode() const
87 {
89 }
90
92 {
94 m_dummy_response_status = status;
95 }
96
97Response::Response(const uint8_t response_bits[], size_t response_bits_len) :
98 m_response_bits(response_bits, response_bits + response_bits_len)
99 {
100 m_dummy_response_status = Certificate_Status_Code::OCSP_RESPONSE_INVALID;
101
102 BER_Decoder response_outer = BER_Decoder(m_response_bits).start_sequence();
103
104 size_t resp_status = 0;
105
106 response_outer.decode(resp_status, ASN1_Type::Enumerated, ASN1_Class::Universal);
107
108 m_status = static_cast<Response_Status_Code>(resp_status);
109
111 { return; }
112
113 if(response_outer.more_items())
114 {
115 BER_Decoder response_bytes =
116 response_outer.start_context_specific(0).start_sequence();
117
118 response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"),
119 "Unknown response type in OCSP response");
120
121 BER_Decoder basicresponse =
123
124 basicresponse.start_sequence()
125 .raw_bytes(m_tbs_bits)
126 .end_cons()
127 .decode(m_sig_algo)
128 .decode(m_signature, ASN1_Type::BitString);
129 decode_optional_list(basicresponse, ASN1_Type(0), m_certs);
130
131 size_t responsedata_version = 0;
132 Extensions extensions;
133
134 BER_Decoder(m_tbs_bits)
135 .decode_optional(responsedata_version, ASN1_Type(0),
137
138 .decode_optional(m_signer_name, ASN1_Type(1),
140
143
144 .decode(m_produced_at)
145
146 .decode_list(m_responses)
147
148 .decode_optional(extensions, ASN1_Type(1),
150 }
151
152 response_outer.end_cons();
153 }
154
156 {
157 if (m_responses.empty())
158 return m_dummy_response_status;
159
160 try
161 {
162 std::unique_ptr<Public_Key> pub_key(issuer.subject_public_key());
163
164 const std::vector<std::string> sig_info =
165 split_on(m_sig_algo.get_oid().to_formatted_string(), '/');
166
167 if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
169
170 std::string padding = sig_info[1];
171 const Signature_Format format = pub_key->default_x509_signature_format();
172
173 PK_Verifier verifier(*pub_key, padding, format);
174
175 if(verifier.verify_message(ASN1::put_in_sequence(m_tbs_bits), m_signature))
177 else
179 }
180 catch(Exception&)
181 {
183 }
184 }
185
186Certificate_Status_Code Response::check_signature(const std::vector<Certificate_Store*>& trusted_roots,
187 const std::vector<X509_Certificate>& ee_cert_path) const
188 {
189 if (m_responses.empty())
190 return m_dummy_response_status;
191
192 std::optional<X509_Certificate> signing_cert;
193
194 for(const auto& trusted_root : trusted_roots)
195 {
196 if(m_signer_name.empty() && m_key_hash.empty())
198
199 if(!m_signer_name.empty())
200 {
201 signing_cert = trusted_root->find_cert(m_signer_name, std::vector<uint8_t>());
202 if(signing_cert)
203 {
204 break;
205 }
206 }
207
208 if(!m_key_hash.empty())
209 {
210 signing_cert = trusted_root->find_cert_by_pubkey_sha1(m_key_hash);
211 if(signing_cert)
212 {
213 break;
214 }
215 }
216 }
217
218 if(!signing_cert && ee_cert_path.size() > 1)
219 {
220 // End entity cert is not allowed to sign their own OCSP request :)
221 for(size_t i = 1; i < ee_cert_path.size(); ++i)
222 {
223 // Check all CA certificates in the (assumed validated) EE cert path
224 if(!m_signer_name.empty() && ee_cert_path[i].subject_dn() == m_signer_name)
225 {
226 signing_cert = ee_cert_path[i];
227 break;
228 }
229
230 if(!m_key_hash.empty() && ee_cert_path[i].subject_public_key_bitstring_sha1() == m_key_hash)
231 {
232 signing_cert = ee_cert_path[i];
233 break;
234 }
235 }
236 }
237
238 if(!signing_cert && !m_certs.empty())
239 {
240 for(const auto& cert : m_certs)
241 {
242 // Check all CA certificates in the (assumed validated) EE cert path
243 if(!m_signer_name.empty() && cert.subject_dn() == m_signer_name)
244 {
245 signing_cert = cert;
246 break;
247 }
248
249 if(!m_key_hash.empty() && cert.subject_public_key_bitstring_sha1() == m_key_hash)
250 {
251 signing_cert = cert;
252 break;
253 }
254 }
255 }
256
257 if(!signing_cert)
259
260 if(!signing_cert->allowed_usage(CRL_SIGN) &&
261 !signing_cert->allowed_extended_usage("PKIX.OCSPSigning"))
262 {
264 }
265
266 return this->verify_signature(*signing_cert);
267 }
268
270 const X509_Certificate& subject,
271 std::chrono::system_clock::time_point ref_time,
272 std::chrono::seconds max_age) const
273 {
274 if(m_responses.empty())
275 { return m_dummy_response_status; }
276
277 for(const auto& response : m_responses)
278 {
279 if(response.certid().is_id_for(issuer, subject))
280 {
281 X509_Time x509_ref_time(ref_time);
282
283 if(response.cert_status() == 1)
285
286 if(response.this_update() > x509_ref_time)
288
289 if(response.next_update().time_is_set())
290 {
291 if(x509_ref_time > response.next_update())
293 }
294 else if(max_age > std::chrono::seconds::zero() && ref_time - response.this_update().to_std_timepoint() > max_age)
296
297 if(response.cert_status() == 0)
299 else
301 }
302 }
303
305 }
306
307#if defined(BOTAN_HAS_HTTP_UTIL)
308
309Response online_check(const X509_Certificate& issuer,
310 const BigInt& subject_serial,
311 const std::string& ocsp_responder,
312 Certificate_Store* trusted_roots,
313 std::chrono::milliseconds timeout)
314 {
315 if(ocsp_responder.empty())
316 throw Invalid_Argument("No OCSP responder specified");
317
318 OCSP::Request req(issuer, subject_serial);
319
320 auto http = HTTP::POST_sync(ocsp_responder,
321 "application/ocsp-request",
322 req.BER_encode(),
323 1,
324 timeout);
325
326 http.throw_unless_ok();
327
328 // Check the MIME type?
329
330 OCSP::Response response(http.body());
331
332 std::vector<Certificate_Store*> trusted_roots_vec;
333 trusted_roots_vec.push_back(trusted_roots);
334
335 if(trusted_roots)
336 response.check_signature(trusted_roots_vec);
337
338 return response;
339 }
340
341
342Response online_check(const X509_Certificate& issuer,
343 const X509_Certificate& subject,
344 Certificate_Store* trusted_roots,
345 std::chrono::milliseconds timeout)
346 {
347 if(subject.issuer_dn() != issuer.subject_dn())
348 throw Invalid_Argument("Invalid cert pair to OCSP::online_check (mismatched issuer,subject args?)");
349
350 return online_check(issuer,
351 BigInt::decode(subject.serial_number()),
352 subject.ocsp_responder(),
353 trusted_roots,
354 timeout);
355 }
356
357#endif
358
359}
const OID & get_oid() const
Definition: asn1_obj.h:447
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:187
bool more_items() const
Definition: ber_dec.cpp:200
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
Definition: ber_dec.h:294
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition: ber_dec.h:173
std::vector< uint8_t > get_next_octet_string()
Definition: ber_dec.h:208
BER_Decoder & end_cons()
Definition: ber_dec.cpp:303
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:426
BER_Decoder start_sequence()
Definition: ber_dec.h:111
BER_Decoder start_context_specific(uint32_t tag)
Definition: ber_dec.h:121
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
Definition: ber_dec.h:365
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:310
static BigInt decode(const uint8_t buf[], size_t length)
Definition: bigint.h:790
DER_Encoder & end_explicit()
Definition: der_enc.cpp:223
DER_Encoder & start_explicit(uint16_t type_tag)
Definition: der_enc.cpp:209
DER_Encoder & start_sequence()
Definition: der_enc.h:66
DER_Encoder & end_cons()
Definition: der_enc.cpp:194
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:288
std::string base64_encode() const
Definition: ocsp.cpp:86
Request(const X509_Certificate &issuer_cert, const X509_Certificate &subject_cert)
Definition: ocsp.cpp:51
std::vector< uint8_t > BER_encode() const
Definition: ocsp.cpp:67
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:269
Response_Status_Code status() const
Definition: ocsp.h:183
Certificate_Status_Code verify_signature(const X509_Certificate &issuer) const
Definition: ocsp.cpp:155
Certificate_Status_Code check_signature(const std::vector< Certificate_Store * > &trust_roots, const std::vector< X509_Certificate > &cert_path={}) const
Definition: ocsp.cpp:186
std::string to_formatted_string() const
Definition: asn1_oid.cpp:109
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
Definition: pubkey.cpp:320
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:449
const X509_DN & subject_dn() const
Definition: x509cert.cpp:465
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:460
std::string ocsp_responder() const
Definition: x509cert.cpp:597
Public_Key * subject_public_key() const
Definition: x509cert.cpp:673
bool empty() const
Definition: pkix_types.h:71
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:191
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)
Definition: http_util.cpp:261
Response_Status_Code
Definition: ocsp.h:117
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:66
ASN1_Type
Definition: asn1_obj.h:39
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:185
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:111
Signature_Format
Definition: pk_keys.h:23
Certificate_Status_Code
Definition: pkix_enums.h:17
@ CRL_SIGN
Definition: pkix_enums.h:110