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