• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 19012754211

02 Nov 2025 01:10PM UTC coverage: 90.677% (+0.006%) from 90.671%
19012754211

push

github

web-flow
Merge pull request #5137 from randombit/jack/clang-tidy-includes

Remove various unused includes flagged by clang-tidy misc-include-cleaner

100457 of 110786 relevant lines covered (90.68%)

12189873.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.05
/src/tests/test_ocsp.cpp
1
/*
2
* (C) 2016 Jack Lloyd
3
* (C) 2022 René Meusel, Rohde & Schwarz Cybersecurity
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include "tests.h"
9

10
#if defined(BOTAN_HAS_OCSP)
11
   #include <botan/certstor.h>
12
   #include <botan/ocsp.h>
13
   #include <botan/x509path.h>
14
   #include <botan/internal/calendar.h>
15
#endif
16

17
namespace Botan_Tests {
18

19
#if defined(BOTAN_HAS_OCSP) && defined(BOTAN_HAS_RSA) && defined(BOTAN_HAS_EMSA_PKCS1) && \
20
   defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
21

22
class OCSP_Tests final : public Test {
×
23
   private:
24
      static Botan::X509_Certificate load_test_X509_cert(const std::string& path) {
23✔
25
         return Botan::X509_Certificate(Test::data_file(path));
46✔
26
      }
27

28
      static Botan::OCSP::Response load_test_OCSP_resp(const std::string& path) {
9✔
29
         return Botan::OCSP::Response(Test::read_binary_data_file(path));
27✔
30
      }
31

32
      static Test::Result test_response_parsing() {
1✔
33
         Test::Result result("OCSP response parsing");
1✔
34

35
         // Simple parsing tests
36
         const std::vector<std::string> ocsp_input_paths = {
1✔
37
            "x509/ocsp/resp1.der", "x509/ocsp/resp2.der", "x509/ocsp/resp3.der"};
1✔
38

39
         for(const std::string& ocsp_input_path : ocsp_input_paths) {
4✔
40
            try {
3✔
41
               Botan::OCSP::Response resp(Test::read_binary_data_file(ocsp_input_path));
6✔
42
               result.confirm("parsing was successful", resp.status() == Botan::OCSP::Response_Status_Code::Successful);
6✔
43
               result.test_success("Parsed input " + ocsp_input_path);
3✔
44
            } catch(Botan::Exception& e) {
3✔
45
               result.test_failure("Parsing failed", e.what());
×
46
            }
×
47
         }
48

49
         Botan::OCSP::Response resp(
1✔
50
            Test::read_binary_data_file("x509/ocsp/patrickschmidt_ocsp_try_later_wrong_sig.der"));
3✔
51
         result.confirm("parsing exposes correct status code",
2✔
52
                        resp.status() == Botan::OCSP::Response_Status_Code::Try_Later);
1✔
53

54
         return result;
1✔
55
      }
1✔
56

57
      static Test::Result test_response_certificate_access() {
1✔
58
         Test::Result result("OCSP response certificate access");
1✔
59

60
         try {
1✔
61
            Botan::OCSP::Response resp1(Test::read_binary_data_file("x509/ocsp/resp1.der"));
3✔
62
            const auto& certs1 = resp1.certificates();
1✔
63
            if(result.test_eq("Expected count of certificates", certs1.size(), 1)) {
1✔
64
               const auto& cert = certs1.front();
1✔
65
               const Botan::X509_DN expected_dn(
1✔
66
                  {std::make_pair("X520.CommonName", "Symantec Class 3 EV SSL CA - G3 OCSP Responder")});
1✔
67
               const bool matches = cert.subject_dn() == expected_dn;
1✔
68
               result.test_eq("CN matches expected", matches, true);
1✔
69
            }
1✔
70

71
            Botan::OCSP::Response resp2(Test::read_binary_data_file("x509/ocsp/resp2.der"));
3✔
72
            const auto& certs2 = resp2.certificates();
1✔
73
            result.test_eq("Expect no certificates", certs2.size(), 0);
1✔
74
         } catch(Botan::Exception& e) {
1✔
75
            result.test_failure("Parsing failed", e.what());
×
76
         }
×
77

78
         return result;
1✔
79
      }
×
80

81
      static Test::Result test_request_encoding() {
1✔
82
         Test::Result result("OCSP request encoding");
1✔
83

84
         const Botan::X509_Certificate end_entity(Test::data_file("x509/ocsp/gmail.pem"));
2✔
85
         const Botan::X509_Certificate issuer(Test::data_file("x509/ocsp/google_g2.pem"));
2✔
86

87
         try {
1✔
88
            const Botan::OCSP::Request bogus(end_entity, issuer);
1✔
89
            result.test_failure("Bad arguments (swapped end entity, issuer) accepted");
×
90
         } catch(Botan::Invalid_Argument&) {
1✔
91
            result.test_success("Bad arguments rejected");
1✔
92
         }
1✔
93

94
         const std::string expected_request =
1✔
95
            "ME4wTKADAgEAMEUwQzBBMAkGBSsOAwIaBQAEFPLgavmFih2NcJtJGSN6qbUaKH5kBBRK3QYWG7z2aLV29YG2u2IaulqBLwIIQkg+DF+RYMY=";
1✔
96

97
         const Botan::OCSP::Request req1(issuer, end_entity);
1✔
98
         result.test_eq("Encoded OCSP request", req1.base64_encode(), expected_request);
2✔
99

100
         const Botan::OCSP::Request req2(issuer, BigInt::from_bytes(end_entity.serial_number()));
1✔
101
         result.test_eq("Encoded OCSP request", req2.base64_encode(), expected_request);
2✔
102

103
         return result;
2✔
104
      }
2✔
105

106
      static Test::Result test_response_find_signing_certificate() {
1✔
107
         Test::Result result("OCSP response finding signature certificates");
1✔
108

109
         const std::optional<Botan::X509_Certificate> nullopt_cert;
1✔
110

111
         // OCSP response is signed by the issuing CA itself
112
         auto randombit_ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp.der");
1✔
113
         auto randombit_ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
1✔
114

115
         // OCSP response is signed by an authorized responder certificate
116
         // issued by the issuing CA and embedded in the response
117
         auto bdr_ocsp = load_test_OCSP_resp("x509/ocsp/bdr-ocsp-resp.der");
1✔
118
         auto bdr_responder = load_test_X509_cert("x509/ocsp/bdr-ocsp-responder.pem");
1✔
119
         auto bdr_ca = load_test_X509_cert("x509/ocsp/bdr-int.pem");
1✔
120

121
         // The response in bdr_ocsp contains two certificates
122
         if(result.test_eq("both certificates found", bdr_ocsp.certificates().size(), 2)) {
1✔
123
            result.test_eq("first cert in response",
2✔
124
                           bdr_ocsp.certificates()[0].subject_info("X520.CommonName").at(0),
3✔
125
                           "D-TRUST OCSP 4 2-2 EV 2016");
126
            result.test_eq("second cert in response",
3✔
127
                           bdr_ocsp.certificates()[1].subject_info("X520.CommonName").at(0),
3✔
128
                           "D-TRUST CA 2-2 EV 2016");
129
         }
130

131
         // Dummy OCSP response is not signed at all
132
         auto dummy_ocsp = Botan::OCSP::Response(Botan::Certificate_Status_Code::OCSP_SERVER_NOT_AVAILABLE);
1✔
133

134
         // OCSP response is signed by 3rd party responder certificate that is
135
         // not included in the OCSP response itself
136
         // See `src/scripts/randombit_ocsp_forger.sh` for a helper script to recreate those.
137
         auto randombit_alt_resp_ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp_forged_valid_nocerts.der");
1✔
138
         auto randombit_alt_resp_cert = load_test_X509_cert("x509/ocsp/randombit_ocsp_forged_responder.pem");
1✔
139

140
         result.test_is_eq("Dummy has no signing certificate",
2✔
141
                           dummy_ocsp.find_signing_certificate(Botan::X509_Certificate()),
2✔
142
                           nullopt_cert);
143

144
         result.test_is_eq("CA is returned as signing certificate",
3✔
145
                           randombit_ocsp.find_signing_certificate(randombit_ca),
1✔
146
                           std::optional(randombit_ca));
1✔
147
         result.test_is_eq("No signer certificate is returned when signer couldn't be determined",
2✔
148
                           randombit_ocsp.find_signing_certificate(bdr_ca),
1✔
149
                           nullopt_cert);
150

151
         result.test_is_eq("Delegated responder certificate is returned for further validation",
3✔
152
                           bdr_ocsp.find_signing_certificate(bdr_ca),
1✔
153
                           std::optional(bdr_responder));
1✔
154

155
         result.test_is_eq("Delegated responder without stapled certs does not find signer without user-provided certs",
2✔
156
                           randombit_alt_resp_ocsp.find_signing_certificate(randombit_ca),
1✔
157
                           nullopt_cert);
158
         auto trusted_responders = std::make_unique<Botan::Certificate_Store_In_Memory>(randombit_alt_resp_cert);
1✔
159
         result.test_is_eq("Delegated responder returns user-provided cert",
3✔
160
                           randombit_alt_resp_ocsp.find_signing_certificate(randombit_ca, trusted_responders.get()),
2✔
161
                           std::optional(randombit_alt_resp_cert));
1✔
162

163
         return result;
2✔
164
      }
1✔
165

166
      static Test::Result test_response_verification_with_next_update_without_max_age() {
1✔
167
         Test::Result result("OCSP request check with next_update w/o max_age");
1✔
168

169
         auto ee = load_test_X509_cert("x509/ocsp/randombit.pem");
1✔
170
         auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
1✔
171
         auto trust_root = load_test_X509_cert("x509/ocsp/geotrust.pem");
1✔
172

173
         const std::vector<Botan::X509_Certificate> cert_path = {ee, ca, trust_root};
4✔
174

175
         auto ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp.der");
1✔
176

177
         Botan::Certificate_Store_In_Memory certstore;
1✔
178
         certstore.add_certificate(trust_root);
1✔
179

180
         auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
5✔
181
                               const Botan::Certificate_Status_Code expected) {
182
            const auto ocsp_status = Botan::PKIX::check_ocsp(
8✔
183
               cert_path, {ocsp}, {&certstore}, valid_time, Botan::Path_Validation_Restrictions());
16✔
184

185
            return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
8✔
186
                   result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
12✔
187
                   result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
28✔
188
                                  ocsp_status[0].contains(expected));
12✔
189
         };
8✔
190

191
         check_ocsp(Botan::calendar_point(2016, 11, 11, 12, 30, 0).to_std_timepoint(),
1✔
192
                    Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
193
         check_ocsp(Botan::calendar_point(2016, 11, 18, 12, 30, 0).to_std_timepoint(),
1✔
194
                    Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
195
         check_ocsp(Botan::calendar_point(2016, 11, 20, 8, 30, 0).to_std_timepoint(),
1✔
196
                    Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
197
         check_ocsp(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(),
1✔
198
                    Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED);
199

200
         return result;
1✔
201
      }
2✔
202

203
      static Test::Result test_response_verification_with_next_update_with_max_age() {
1✔
204
         Test::Result result("OCSP request check with next_update with max_age");
1✔
205

206
         auto ee = load_test_X509_cert("x509/ocsp/randombit.pem");
1✔
207
         auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
1✔
208
         auto trust_root = load_test_X509_cert("x509/ocsp/geotrust.pem");
1✔
209

210
         const std::vector<Botan::X509_Certificate> cert_path = {ee, ca, trust_root};
4✔
211

212
         auto ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp.der");
1✔
213

214
         Botan::Certificate_Store_In_Memory certstore;
1✔
215
         certstore.add_certificate(trust_root);
1✔
216

217
         // Some arbitrary time within the validity period of the test certs
218
         const auto max_age = std::chrono::minutes(59);
1✔
219

220
         auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
5✔
221
                               const Botan::Certificate_Status_Code expected) {
222
            Botan::Path_Validation_Restrictions pvr(false, 110, false, max_age);
4✔
223
            const auto ocsp_status = Botan::PKIX::check_ocsp(cert_path, {ocsp}, {&certstore}, valid_time, pvr);
12✔
224

225
            return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
8✔
226
                   result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
12✔
227
                   result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
28✔
228
                                  ocsp_status[0].contains(expected));
12✔
229
         };
8✔
230

231
         check_ocsp(Botan::calendar_point(2016, 11, 11, 12, 30, 0).to_std_timepoint(),
1✔
232
                    Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
233
         check_ocsp(Botan::calendar_point(2016, 11, 18, 12, 30, 0).to_std_timepoint(),
1✔
234
                    Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
235
         check_ocsp(Botan::calendar_point(2016, 11, 20, 8, 30, 0).to_std_timepoint(),
1✔
236
                    Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
237
         check_ocsp(Botan::calendar_point(2016, 11, 28, 8, 30, 0).to_std_timepoint(),
1✔
238
                    Botan::Certificate_Status_Code::OCSP_HAS_EXPIRED);
239

240
         return result;
1✔
241
      }
2✔
242

243
      static Test::Result test_response_verification_without_next_update_with_max_age() {
1✔
244
         Test::Result result("OCSP request check w/o next_update with max_age");
1✔
245

246
         auto ee = load_test_X509_cert("x509/ocsp/patrickschmidt.pem");
1✔
247
         auto ca = load_test_X509_cert("x509/ocsp/bdrive_encryption.pem");
1✔
248
         auto trust_root = load_test_X509_cert("x509/ocsp/bdrive_root.pem");
1✔
249

250
         const std::vector<Botan::X509_Certificate> cert_path = {ee, ca, trust_root};
4✔
251

252
         auto ocsp = load_test_OCSP_resp("x509/ocsp/patrickschmidt_ocsp.der");
1✔
253

254
         Botan::Certificate_Store_In_Memory certstore;
1✔
255
         certstore.add_certificate(trust_root);
1✔
256

257
         // Some arbitrary time within the validity period of the test certs
258
         const auto max_age = std::chrono::minutes(59);
1✔
259

260
         auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
4✔
261
                               const Botan::Certificate_Status_Code expected) {
262
            Botan::Path_Validation_Restrictions pvr(false, 110, false, max_age);
3✔
263
            const auto ocsp_status = Botan::PKIX::check_ocsp(cert_path, {ocsp}, {&certstore}, valid_time, pvr);
9✔
264

265
            return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
6✔
266
                   result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
9✔
267
                   result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
21✔
268
                                  ocsp_status[0].contains(expected));
9✔
269
         };
6✔
270

271
         check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 0, 0).to_std_timepoint(),
1✔
272
                    Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
273
         check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 30, 0).to_std_timepoint(),
1✔
274
                    Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
275
         check_ocsp(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(),
1✔
276
                    Botan::Certificate_Status_Code::OCSP_IS_TOO_OLD);
277

278
         return result;
1✔
279
      }
2✔
280

281
      static Test::Result test_response_verification_without_next_update_without_max_age() {
1✔
282
         Test::Result result("OCSP request check w/o next_update w/o max_age");
1✔
283

284
         auto ee = load_test_X509_cert("x509/ocsp/patrickschmidt.pem");
1✔
285
         auto ca = load_test_X509_cert("x509/ocsp/bdrive_encryption.pem");
1✔
286
         auto trust_root = load_test_X509_cert("x509/ocsp/bdrive_root.pem");
1✔
287

288
         const std::vector<Botan::X509_Certificate> cert_path = {ee, ca, trust_root};
4✔
289

290
         auto ocsp = load_test_OCSP_resp("x509/ocsp/patrickschmidt_ocsp.der");
1✔
291

292
         Botan::Certificate_Store_In_Memory certstore;
1✔
293
         certstore.add_certificate(trust_root);
1✔
294

295
         auto check_ocsp = [&](const std::chrono::system_clock::time_point valid_time,
4✔
296
                               const Botan::Certificate_Status_Code expected) {
297
            const auto ocsp_status = Botan::PKIX::check_ocsp(
6✔
298
               cert_path, {ocsp}, {&certstore}, valid_time, Botan::Path_Validation_Restrictions());
12✔
299

300
            return result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1) &&
6✔
301
                   result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1) &&
9✔
302
                   result.confirm(std::string("Status: '") + Botan::to_string(expected) + "'",
21✔
303
                                  ocsp_status[0].contains(expected));
9✔
304
         };
6✔
305

306
         check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 0, 0).to_std_timepoint(),
1✔
307
                    Botan::Certificate_Status_Code::OCSP_NOT_YET_VALID);
308
         check_ocsp(Botan::calendar_point(2019, 5, 28, 7, 30, 0).to_std_timepoint(),
1✔
309
                    Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
310
         check_ocsp(Botan::calendar_point(2019, 5, 28, 8, 0, 0).to_std_timepoint(),
1✔
311
                    Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
312

313
         return result;
1✔
314
      }
2✔
315

316
      static Test::Result test_response_verification_softfail() {
1✔
317
         Test::Result result("OCSP request softfail check");
1✔
318

319
         auto ee = load_test_X509_cert("x509/ocsp/randombit.pem");
1✔
320
         auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
1✔
321
         auto trust_root = load_test_X509_cert("x509/ocsp/geotrust.pem");
1✔
322

323
         const std::vector<Botan::X509_Certificate> cert_path = {ee, ca, trust_root};
4✔
324

325
         Botan::OCSP::Response ocsp(Botan::Certificate_Status_Code::OCSP_NO_REVOCATION_URL);
1✔
326

327
         Botan::Certificate_Store_In_Memory certstore;
1✔
328
         certstore.add_certificate(trust_root);
1✔
329

330
         // Some arbitrary time within the validity period of the test certs
331
         const auto valid_time = Botan::calendar_point(2016, 11, 20, 8, 30, 0).to_std_timepoint();
1✔
332
         const auto ocsp_status =
1✔
333
            Botan::PKIX::check_ocsp(cert_path, {ocsp}, {&certstore}, valid_time, Botan::Path_Validation_Restrictions());
4✔
334

335
         if(result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1)) {
1✔
336
            if(result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1)) {
1✔
337
               result.test_gt(
3✔
338
                  "Status warning", ocsp_status[0].count(Botan::Certificate_Status_Code::OCSP_NO_REVOCATION_URL), 0);
1✔
339
            }
340
         }
341

342
         return result;
1✔
343
      }
3✔
344

345
   #if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
346
      static Test::Result test_online_request() {
1✔
347
         Test::Result result("OCSP online check");
1✔
348

349
         auto cert = load_test_X509_cert("x509/ocsp/digicert-ecdsa-int.pem");
1✔
350
         auto trust_root = load_test_X509_cert("x509/ocsp/digicert-root.pem");
1✔
351

352
         const std::vector<Botan::X509_Certificate> cert_path = {cert, trust_root};
3✔
353

354
         Botan::Certificate_Store_In_Memory certstore;
1✔
355
         certstore.add_certificate(trust_root);
1✔
356

357
         const auto ocsp_timeout = std::chrono::milliseconds(3000);
1✔
358
         const auto now = std::chrono::system_clock::now();
1✔
359
         auto ocsp_status = Botan::PKIX::check_ocsp_online(
1✔
360
            cert_path, {&certstore}, now, ocsp_timeout, Botan::Path_Validation_Restrictions());
2✔
361

362
         if(result.test_eq("Expected size of ocsp_status", ocsp_status.size(), 1)) {
1✔
363
            if(result.test_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1)) {
1✔
364
               const bool status_good = ocsp_status[0].contains(Botan::Certificate_Status_Code::OCSP_RESPONSE_GOOD);
1✔
365
               const bool server_not_found =
1✔
366
                  ocsp_status[0].contains(Botan::Certificate_Status_Code::OCSP_SERVER_NOT_AVAILABLE);
1✔
367
               result.confirm("Expected status", status_good || server_not_found);
2✔
368
            }
369
         }
370

371
         return result;
1✔
372
      }
2✔
373
   #endif
374

375
      static Test::Result test_response_verification_with_additionally_trusted_responder() {
1✔
376
         Test::Result result("OCSP response with user-defined (additional) responder certificate");
1✔
377

378
         // OCSP response is signed by 3rd party responder certificate that is
379
         // not included in the OCSP response itself
380
         // See `src/scripts/randombit_ocsp_forger.sh` for a helper script to recreate those.
381
         auto ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp_forged_valid_nocerts.der");
1✔
382
         auto responder = load_test_X509_cert("x509/ocsp/randombit_ocsp_forged_responder.pem");
1✔
383
         auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
1✔
384

385
         std::optional<Botan::X509_Certificate> nullopt_cert;
1✔
386

387
         Botan::Certificate_Store_In_Memory trusted_responders;
1✔
388

389
         // without providing the 3rd party responder certificate no issuer will be found
390
         result.test_is_eq("cannot find signing certificate without trusted responders",
2✔
391
                           ocsp.find_signing_certificate(ca),
1✔
392
                           nullopt_cert);
393
         result.test_is_eq("cannot find signing certificate without additional help",
2✔
394
                           ocsp.find_signing_certificate(ca, &trusted_responders),
1✔
395
                           nullopt_cert);
396

397
         // add the 3rd party responder certificate to the list of trusted OCSP responder certs
398
         // to find the issuer certificate of this response
399
         trusted_responders.add_certificate(responder);
1✔
400
         result.test_is_eq("the responder certificate is returned when it is trusted",
3✔
401
                           ocsp.find_signing_certificate(ca, &trusted_responders),
1✔
402
                           std::optional(responder));
1✔
403

404
         result.test_is_eq("the responder's signature checks out",
1✔
405
                           ocsp.verify_signature(responder),
1✔
406
                           Botan::Certificate_Status_Code::OCSP_SIGNATURE_OK);
1✔
407

408
         return result;
1✔
409
      }
1✔
410

411
      static Test::Result test_responder_cert_with_nocheck_extension() {
1✔
412
         Test::Result result("BDr's OCSP response contains certificate featuring NoCheck extension");
1✔
413

414
         auto ocsp = load_test_OCSP_resp("x509/ocsp/bdr-ocsp-resp.der");
1✔
415
         const bool contains_cert_with_nocheck =
1✔
416
            std::find_if(ocsp.certificates().cbegin(), ocsp.certificates().cend(), [](const auto& cert) {
1✔
417
               return cert.v3_extensions().extension_set(Botan::OID::from_string("PKIX.OCSP.NoCheck"));
1✔
418
            }) != ocsp.certificates().end();
1✔
419

420
         result.confirm("Contains NoCheck extension", contains_cert_with_nocheck);
2✔
421

422
         return result;
1✔
423
      }
1✔
424

425
   public:
426
      std::vector<Test::Result> run() override {
1✔
427
         std::vector<Test::Result> results;
1✔
428

429
         results.push_back(test_request_encoding());
2✔
430
         results.push_back(test_response_parsing());
2✔
431
         results.push_back(test_response_certificate_access());
2✔
432
         results.push_back(test_response_find_signing_certificate());
2✔
433
         results.push_back(test_response_verification_with_next_update_without_max_age());
2✔
434
         results.push_back(test_response_verification_with_next_update_with_max_age());
2✔
435
         results.push_back(test_response_verification_without_next_update_with_max_age());
2✔
436
         results.push_back(test_response_verification_without_next_update_without_max_age());
2✔
437
         results.push_back(test_response_verification_softfail());
2✔
438
         results.push_back(test_response_verification_with_additionally_trusted_responder());
2✔
439
         results.push_back(test_responder_cert_with_nocheck_extension());
2✔
440

441
   #if defined(BOTAN_HAS_ONLINE_REVOCATION_CHECKS)
442
         if(Test::options().run_online_tests()) {
1✔
443
            results.push_back(test_online_request());
2✔
444
         }
445
   #endif
446

447
         return results;
1✔
448
      }
×
449
};
450

451
BOTAN_REGISTER_TEST("x509", "ocsp", OCSP_Tests);
452

453
#endif
454

455
}  // namespace Botan_Tests
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc