Coverage Report

Created: 2021-01-13 07:05

/src/botan/src/lib/x509/ocsp.cpp
Line
Count
Source (jump to first uncovered line)
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
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_Type tag,
31
                          std::vector<X509_Certificate>& output)
32
2.56k
   {
33
2.56k
   BER_Object obj = ber.get_next_object();
34
35
2.56k
   if(obj.is_a(tag, ASN1_Class::CONTEXT_SPECIFIC | ASN1_Class::CONSTRUCTED) == false)
36
1.06k
      {
37
1.06k
      ber.push_back(obj);
38
1.06k
      return;
39
1.06k
      }
40
41
1.50k
   BER_Decoder list(obj);
42
43
2.86k
   while(list.more_items())
44
1.36k
      {
45
1.36k
      BER_Object certbits = list.get_next_object();
46
1.36k
      X509_Certificate cert(certbits.bits(), certbits.length());
47
1.36k
      output.push_back(std::move(cert));
48
1.36k
      }
49
1.50k
   }
50
51
}
52
53
Request::Request(const X509_Certificate& issuer_cert,
54
                 const X509_Certificate& subject_cert) :
55
   m_issuer(issuer_cert),
56
   m_certid(m_issuer, BigInt::decode(subject_cert.serial_number()))
57
0
   {
58
0
   if(subject_cert.issuer_dn() != issuer_cert.subject_dn())
59
0
      throw Invalid_Argument("Invalid cert pair to OCSP::Request (mismatched issuer,subject args?)");
60
0
   }
61
62
Request::Request(const X509_Certificate& issuer_cert,
63
                 const BigInt& subject_serial) :
64
   m_issuer(issuer_cert),
65
   m_certid(m_issuer, subject_serial)
66
0
   {
67
0
   }
68
69
std::vector<uint8_t> Request::BER_encode() const
70
0
   {
71
0
   std::vector<uint8_t> output;
72
0
   DER_Encoder(output).start_sequence()
73
0
        .start_sequence()
74
0
          .start_explicit(0)
75
0
            .encode(static_cast<size_t>(0)) // version #
76
0
          .end_explicit()
77
0
            .start_sequence()
78
0
              .start_sequence()
79
0
                .encode(m_certid)
80
0
              .end_cons()
81
0
            .end_cons()
82
0
          .end_cons()
83
0
      .end_cons();
84
85
0
   return output;
86
0
   }
87
88
std::string Request::base64_encode() const
89
0
   {
90
0
   return Botan::base64_encode(BER_encode());
91
0
   }
92
93
Response::Response(Certificate_Status_Code status)
94
0
   {
95
0
   m_status = Response_Status_Code::Successful;
96
0
   m_dummy_response_status = status;
97
0
   }
98
99
Response::Response(const uint8_t response_bits[], size_t response_bits_len) :
100
   m_response_bits(response_bits, response_bits + response_bits_len)
101
3.84k
   {
102
3.84k
   m_dummy_response_status = Certificate_Status_Code::OCSP_RESPONSE_INVALID;
103
104
3.84k
   BER_Decoder response_outer = BER_Decoder(m_response_bits).start_sequence();
105
106
3.84k
   size_t resp_status = 0;
107
108
3.84k
   response_outer.decode(resp_status, ASN1_Type::ENUMERATED, ASN1_Class::UNIVERSAL);
109
110
3.84k
   m_status = static_cast<Response_Status_Code>(resp_status);
111
112
3.84k
   if(m_status != Response_Status_Code::Successful)
113
72
      { return; }
114
115
3.77k
   if(response_outer.more_items())
116
3.03k
      {
117
3.03k
      BER_Decoder response_bytes =
118
3.03k
         response_outer.start_cons(ASN1_Type(0), ASN1_Class::CONTEXT_SPECIFIC).start_sequence();
119
120
3.03k
      response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"),
121
3.03k
                                      "Unknown response type in OCSP response");
122
123
3.03k
      BER_Decoder basicresponse =
124
3.03k
         BER_Decoder(response_bytes.get_next_octet_string()).start_sequence();
125
126
3.03k
      basicresponse.start_sequence()
127
3.03k
           .raw_bytes(m_tbs_bits)
128
3.03k
         .end_cons()
129
3.03k
         .decode(m_sig_algo)
130
3.03k
         .decode(m_signature, ASN1_Type::BIT_STRING);
131
3.03k
      decode_optional_list(basicresponse, ASN1_Type(0), m_certs);
132
133
3.03k
      size_t responsedata_version = 0;
134
3.03k
      Extensions extensions;
135
136
3.03k
      BER_Decoder(m_tbs_bits)
137
3.03k
         .decode_optional(responsedata_version, ASN1_Type(0),
138
3.03k
                          ASN1_Class::CONTEXT_SPECIFIC | ASN1_Class::CONSTRUCTED)
139
140
3.03k
         .decode_optional(m_signer_name, ASN1_Type(1),
141
3.03k
                          ASN1_Class::CONTEXT_SPECIFIC | ASN1_Class::CONSTRUCTED)
142
143
3.03k
         .decode_optional_string(m_key_hash, ASN1_Type::OCTET_STRING, 2,
144
3.03k
                                 ASN1_Class::CONTEXT_SPECIFIC | ASN1_Class::CONSTRUCTED)
145
146
3.03k
         .decode(m_produced_at)
147
148
3.03k
         .decode_list(m_responses)
149
150
3.03k
         .decode_optional(extensions, ASN1_Type(1),
151
3.03k
                          ASN1_Class::CONTEXT_SPECIFIC | ASN1_Class::CONSTRUCTED);
152
3.03k
      }
153
154
3.77k
   response_outer.end_cons();
155
3.77k
   }
156
157
Certificate_Status_Code Response::verify_signature(const X509_Certificate& issuer) const
158
0
   {
159
0
   if (m_responses.empty())
160
0
      return m_dummy_response_status;
161
162
0
   try
163
0
      {
164
0
      std::unique_ptr<Public_Key> pub_key(issuer.subject_public_key());
165
166
0
      const std::vector<std::string> sig_info =
167
0
         split_on(m_sig_algo.get_oid().to_formatted_string(), '/');
168
169
0
      if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
170
0
         return Certificate_Status_Code::OCSP_RESPONSE_INVALID;
171
172
0
      std::string padding = sig_info[1];
173
0
      const Signature_Format format = pub_key->default_x509_signature_format();
174
175
0
      PK_Verifier verifier(*pub_key, padding, format);
176
177
0
      if(verifier.verify_message(ASN1::put_in_sequence(m_tbs_bits), m_signature))
178
0
         return Certificate_Status_Code::OCSP_SIGNATURE_OK;
179
0
      else
180
0
         return Certificate_Status_Code::OCSP_SIGNATURE_ERROR;
181
0
      }
182
0
   catch(Exception&)
183
0
      {
184
0
      return Certificate_Status_Code::OCSP_SIGNATURE_ERROR;
185
0
      }
186
0
   }
187
188
Certificate_Status_Code Response::check_signature(const std::vector<Certificate_Store*>& trusted_roots,
189
                                                  const std::vector<X509_Certificate>& ee_cert_path) const
190
0
   {
191
0
   if (m_responses.empty())
192
0
      return m_dummy_response_status;
193
194
0
   std::optional<X509_Certificate> signing_cert;
195
196
0
   for(size_t i = 0; i != trusted_roots.size(); ++i)
197
0
      {
198
0
      if(m_signer_name.empty() && m_key_hash.empty())
199
0
         return Certificate_Status_Code::OCSP_RESPONSE_INVALID;
200
201
0
      if(!m_signer_name.empty())
202
0
         {
203
0
         signing_cert = trusted_roots[i]->find_cert(m_signer_name, std::vector<uint8_t>());
204
0
         if(signing_cert)
205
0
            {
206
0
            break;
207
0
            }
208
0
         }
209
210
0
      if(m_key_hash.size() > 0)
211
0
         {
212
0
         signing_cert = trusted_roots[i]->find_cert_by_pubkey_sha1(m_key_hash);
213
0
         if(signing_cert)
214
0
            {
215
0
            break;
216
0
            }
217
0
         }
218
0
      }
219
220
0
   if(!signing_cert && ee_cert_path.size() > 1)
221
0
      {
222
      // End entity cert is not allowed to sign their own OCSP request :)
223
0
      for(size_t i = 1; i < ee_cert_path.size(); ++i)
224
0
         {
225
         // Check all CA certificates in the (assumed validated) EE cert path
226
0
         if(!m_signer_name.empty() && ee_cert_path[i].subject_dn() == m_signer_name)
227
0
            {
228
0
            signing_cert = ee_cert_path[i];
229
0
            break;
230
0
            }
231
232
0
         if(m_key_hash.size() > 0 && ee_cert_path[i].subject_public_key_bitstring_sha1() == m_key_hash)
233
0
            {
234
0
            signing_cert = ee_cert_path[i];
235
0
            break;
236
0
            }
237
0
         }
238
0
      }
239
240
0
   if(!signing_cert && m_certs.size() > 0)
241
0
      {
242
0
      for(size_t i = 0; i < m_certs.size(); ++i)
243
0
         {
244
         // Check all CA certificates in the (assumed validated) EE cert path
245
0
         if(!m_signer_name.empty() && m_certs[i].subject_dn() == m_signer_name)
246
0
            {
247
0
            signing_cert = m_certs[i];
248
0
            break;
249
0
            }
250
251
0
         if(m_key_hash.size() > 0 && m_certs[i].subject_public_key_bitstring_sha1() == m_key_hash)
252
0
            {
253
0
            signing_cert = m_certs[i];
254
0
            break;
255
0
            }
256
0
         }
257
0
      }
258
259
0
   if(!signing_cert)
260
0
      return Certificate_Status_Code::OCSP_ISSUER_NOT_FOUND;
261
262
0
   if(!signing_cert->allowed_usage(CRL_SIGN) &&
263
0
      !signing_cert->allowed_extended_usage("PKIX.OCSPSigning"))
264
0
      {
265
0
      return Certificate_Status_Code::OCSP_RESPONSE_MISSING_KEYUSAGE;
266
0
      }
267
268
0
   return this->verify_signature(*signing_cert);
269
0
   }
270
271
Certificate_Status_Code Response::status_for(const X509_Certificate& issuer,
272
      const X509_Certificate& subject,
273
      std::chrono::system_clock::time_point ref_time,
274
      std::chrono::seconds max_age) const
275
0
   {
276
0
   if(m_responses.empty())
277
0
      { return m_dummy_response_status; }
278
279
0
   for(const auto& response : m_responses)
280
0
      {
281
0
      if(response.certid().is_id_for(issuer, subject))
282
0
         {
283
0
         X509_Time x509_ref_time(ref_time);
284
285
0
         if(response.cert_status() == 1)
286
0
            { return Certificate_Status_Code::CERT_IS_REVOKED; }
287
288
0
         if(response.this_update() > x509_ref_time)
289
0
            { return Certificate_Status_Code::OCSP_NOT_YET_VALID; }
290
291
0
         if(response.next_update().time_is_set())
292
0
            {
293
0
            if(x509_ref_time > response.next_update())
294
0
               { return Certificate_Status_Code::OCSP_HAS_EXPIRED; }
295
0
            }
296
0
         else if(max_age > std::chrono::seconds::zero() && ref_time - response.this_update().to_std_timepoint() > max_age)
297
0
            { return Certificate_Status_Code::OCSP_IS_TOO_OLD; }
298
299
0
         if(response.cert_status() == 0)
300
0
            { return Certificate_Status_Code::OCSP_RESPONSE_GOOD; }
301
0
         else
302
0
            { return Certificate_Status_Code::OCSP_BAD_STATUS; }
303
0
         }
304
0
      }
305
306
0
   return Certificate_Status_Code::OCSP_CERT_NOT_LISTED;
307
0
   }
308
309
#if defined(BOTAN_HAS_HTTP_UTIL)
310
311
Response 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
0
   {
317
0
   if(ocsp_responder.empty())
318
0
      throw Invalid_Argument("No OCSP responder specified");
319
320
0
   OCSP::Request req(issuer, subject_serial);
321
322
0
   auto http = HTTP::POST_sync(ocsp_responder,
323
0
                               "application/ocsp-request",
324
0
                               req.BER_encode(),
325
0
                               1,
326
0
                               timeout);
327
328
0
   http.throw_unless_ok();
329
330
   // Check the MIME type?
331
332
0
   OCSP::Response response(http.body());
333
334
0
   std::vector<Certificate_Store*> trusted_roots_vec;
335
0
   trusted_roots_vec.push_back(trusted_roots);
336
337
0
   if(trusted_roots)
338
0
      response.check_signature(trusted_roots_vec);
339
340
0
   return response;
341
0
   }
342
343
344
Response online_check(const X509_Certificate& issuer,
345
                      const X509_Certificate& subject,
346
                      Certificate_Store* trusted_roots,
347
                      std::chrono::milliseconds timeout)
348
0
   {
349
0
   if(subject.issuer_dn() != issuer.subject_dn())
350
0
      throw Invalid_Argument("Invalid cert pair to OCSP::online_check (mismatched issuer,subject args?)");
351
352
0
   return online_check(issuer,
353
0
                       BigInt::decode(subject.serial_number()),
354
0
                       subject.ocsp_responder(),
355
0
                       trusted_roots,
356
0
                       timeout);
357
0
   }
358
359
#endif
360
361
}
362
363
}