Botan  2.9.0
Crypto and TLS for C++11
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 
22 namespace Botan {
23 
24 namespace OCSP {
25 
26 namespace {
27 
28 // TODO: should this be in a header somewhere?
29 void 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 
69 std::vector<uint8_t> Request::BER_encode() const
70  {
71  std::vector<uint8_t> output;
74  .start_explicit(0)
75  .encode(static_cast<size_t>(0)) // version #
76  .end_explicit()
79  .encode(m_certid)
80  .end_cons()
81  .end_cons()
82  .end_cons()
83  .end_cons();
84 
85  return output;
86  }
87 
88 std::string Request::base64_encode() const
89  {
91  }
92 
94  {
95  m_dummy_response_status = status;
96  }
97 
98 Response::Response(const uint8_t response_bits[], size_t response_bits_len) :
99  m_response_bits(response_bits, response_bits + response_bits_len)
100  {
101  m_dummy_response_status = Certificate_Status_Code::OCSP_RESPONSE_INVALID;
102 
103  BER_Decoder response_outer = BER_Decoder(m_response_bits).start_cons(SEQUENCE);
104 
105  size_t resp_status = 0;
106 
107  response_outer.decode(resp_status, ENUMERATED, UNIVERSAL);
108 
109  /*
110  * FIXME: properly decode error responses
111  */
112  if(resp_status != 0)
113  throw Decoding_Error("OCSP response status " + std::to_string(resp_status));
114 
115  if(response_outer.more_items())
116  {
117  BER_Decoder response_bytes =
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 =
124  BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE);
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(OIDS::lookup(m_sig_algo.get_oid()), '/');
168 
169  if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
171 
172  std::string padding = sig_info[1];
173  Signature_Format format = (pub_key->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
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 
188 Certificate_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) const
274  {
275  if (m_responses.empty())
276  return m_dummy_response_status;
277 
278  for(const auto& response : m_responses)
279  {
280  if(response.certid().is_id_for(issuer, subject))
281  {
282  X509_Time x509_ref_time(ref_time);
283 
284  if(response.cert_status() == 1)
286 
287  if(response.this_update() > x509_ref_time)
289 
290  if(response.next_update().time_is_set() && x509_ref_time > response.next_update())
292 
293  if(response.cert_status() == 0)
295  else
297  }
298  }
299 
301  }
302 
303 #if defined(BOTAN_HAS_HTTP_UTIL)
304 
305 Response online_check(const X509_Certificate& issuer,
306  const BigInt& subject_serial,
307  const std::string& ocsp_responder,
308  Certificate_Store* trusted_roots,
309  std::chrono::milliseconds timeout)
310  {
311  if(ocsp_responder.empty())
312  throw Invalid_Argument("No OCSP responder specified");
313 
314  OCSP::Request req(issuer, subject_serial);
315 
316  auto http = HTTP::POST_sync(ocsp_responder,
317  "application/ocsp-request",
318  req.BER_encode(),
319  1,
320  timeout);
321 
322  http.throw_unless_ok();
323 
324  // Check the MIME type?
325 
326  OCSP::Response response(http.body());
327 
328  std::vector<Certificate_Store*> trusted_roots_vec;
329  trusted_roots_vec.push_back(trusted_roots);
330 
331  if(trusted_roots)
332  response.check_signature(trusted_roots_vec);
333 
334  return response;
335  }
336 
337 
338 Response online_check(const X509_Certificate& issuer,
339  const X509_Certificate& subject,
340  Certificate_Store* trusted_roots,
341  std::chrono::milliseconds timeout)
342  {
343  if(subject.issuer_dn() != issuer.subject_dn())
344  throw Invalid_Argument("Invalid cert pair to OCSP::online_check (mismatched issuer,subject args?)");
345 
346  return online_check(issuer,
347  BigInt::decode(subject.serial_number()),
348  subject.ocsp_responder(),
349  trusted_roots,
350  timeout);
351  }
352 
353 #endif
354 
355 }
356 
357 }
bool verify_message(const uint8_t msg[], size_t msg_length, const uint8_t sig[], size_t sig_length)
Definition: pubkey.cpp:324
bool empty() const
Definition: x509_dn.h:52
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:144
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:242
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
std::vector< uint8_t > get_next_octet_string()
Definition: ber_dec.h:191
Signature_Format
Definition: pubkey.h:28
Public_Key * subject_public_key() const
Definition: x509cert.h:49
DER_Encoder & end_explicit()
Definition: der_enc.cpp:220
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
ASN1_Tag
Definition: asn1_obj.h:22
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition: ber_dec.h:156
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
std::string ocsp_responder() const
Definition: x509cert.cpp:556
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
Definition: ber_dec.h:337
std::string base64_encode() const
Definition: ocsp.cpp:88
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
Definition: ocsp.cpp:271
const X509_DN & subject_dn() const
Definition: x509cert.cpp:428
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t &input_consumed, bool final_inputs)
Definition: base64.cpp:166
BER_Decoder & end_cons()
Definition: ber_dec.cpp:300
Certificate_Status_Code verify_signature(const X509_Certificate &issuer) const
Definition: ocsp.cpp:157
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:423
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
Definition: alg_id.cpp:13
std::vector< uint8_t > put_in_sequence(const std::vector< uint8_t > &contents)
Definition: asn1_obj.cpp:192
Request(const X509_Certificate &issuer_cert, const X509_Certificate &subject_cert)
Definition: ocsp.cpp:53
static BigInt decode(const uint8_t buf[], size_t length)
Definition: bigint.h:786
const OID & get_oid() const
Definition: alg_id.h:37
std::vector< uint8_t > BER_encode() const
Definition: ocsp.cpp:69
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Tag type_tag=SEQUENCE, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.h:398
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:412
Certificate_Status_Code
Definition: cert_status.h:19
bool more_items() const
Definition: ber_dec.cpp:198
std::string lookup(const OID &oid)
Definition: oids.cpp:113
DER_Encoder & start_explicit(uint16_t type_tag)
Definition: der_enc.cpp:206
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