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

randombit / botan / 22045109103

15 Feb 2026 11:27PM UTC coverage: 90.043% (-0.01%) from 90.054%
22045109103

push

github

web-flow
Merge pull request #5342 from randombit/jack/test-h-arb-eq

Rename test_is_eq to test_arb_eq and require the type be printable

102325 of 113640 relevant lines covered (90.04%)

11463137.71 hits per line

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

97.4
/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 "test_arb_eq.h"
12
   #include <botan/certstor.h>
13
   #include <botan/ocsp.h>
14
   #include <botan/x509path.h>
15
   #include <botan/internal/calendar.h>
16
#endif
17

18
namespace Botan_Tests {
19

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

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

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

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

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

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

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

56
         return result;
1✔
57
      }
1✔
58

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

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

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

80
         return result;
1✔
81
      }
×
82

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

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

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

96
         const std::string expected_request =
1✔
97
            "ME4wTKADAgEAMEUwQzBBMAkGBSsOAwIaBQAEFPLgavmFih2NcJtJGSN6qbUaKH5kBBRK3QYWG7z2aLV29YG2u2IaulqBLwIIQkg+DF+RYMY=";
1✔
98

99
         const Botan::OCSP::Request req1(issuer, end_entity);
1✔
100
         result.test_str_eq("Encoded OCSP request", req1.base64_encode(), expected_request);
1✔
101

102
         const Botan::OCSP::Request req2(issuer, BigInt::from_bytes(end_entity.serial_number()));
1✔
103
         result.test_str_eq("Encoded OCSP request", req2.base64_encode(), expected_request);
1✔
104

105
         return result;
2✔
106
      }
2✔
107

108
      static Test::Result test_response_find_signing_certificate() {
1✔
109
         Test::Result result("OCSP response finding signature certificates");
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_sz_eq("both certificates found", bdr_ocsp.certificates().size(), 2)) {
1✔
123
            result.test_str_eq("first cert in response",
2✔
124
                               bdr_ocsp.certificates()[0].subject_info("X520.CommonName").at(0),
2✔
125
                               "D-TRUST OCSP 4 2-2 EV 2016");
126
            result.test_str_eq("second cert in response",
2✔
127
                               bdr_ocsp.certificates()[1].subject_info("X520.CommonName").at(0),
2✔
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_opt_is_null("Dummy has no signing certificate",
1✔
141
                                 dummy_ocsp.find_signing_certificate(Botan::X509_Certificate()));
2✔
142

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

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

155
         result.test_opt_is_null(
1✔
156
            "Delegated responder without stapled certs does not find signer without user-provided certs",
157
            randombit_alt_resp_ocsp.find_signing_certificate(randombit_ca));
1✔
158

159
         auto trusted_responders = std::make_unique<Botan::Certificate_Store_In_Memory>(randombit_alt_resp_cert);
1✔
160
         test_arb_eq(result,
2✔
161
                     "Delegated responder returns user-provided cert",
162
                     randombit_alt_resp_ocsp.find_signing_certificate(randombit_ca, trusted_responders.get()),
2✔
163
                     std::optional(randombit_alt_resp_cert));
1✔
164

165
         return result;
1✔
166
      }
1✔
167

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

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

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

177
         auto ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp.der");
1✔
178

179
         Botan::Certificate_Store_In_Memory certstore;
1✔
180
         certstore.add_certificate(trust_root);
1✔
181

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

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

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

202
         return result;
1✔
203
      }
2✔
204

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

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

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

214
         auto ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp.der");
1✔
215

216
         Botan::Certificate_Store_In_Memory certstore;
1✔
217
         certstore.add_certificate(trust_root);
1✔
218

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

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

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

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

242
         return result;
1✔
243
      }
2✔
244

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

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

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

254
         auto ocsp = load_test_OCSP_resp("x509/ocsp/patrickschmidt_ocsp.der");
1✔
255

256
         Botan::Certificate_Store_In_Memory certstore;
1✔
257
         certstore.add_certificate(trust_root);
1✔
258

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

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

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

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

280
         return result;
1✔
281
      }
2✔
282

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

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

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

292
         auto ocsp = load_test_OCSP_resp("x509/ocsp/patrickschmidt_ocsp.der");
1✔
293

294
         Botan::Certificate_Store_In_Memory certstore;
1✔
295
         certstore.add_certificate(trust_root);
1✔
296

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

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

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

315
         return result;
1✔
316
      }
2✔
317

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

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

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

327
         Botan::OCSP::Response ocsp(Botan::Certificate_Status_Code::OCSP_NO_REVOCATION_URL);
1✔
328

329
         Botan::Certificate_Store_In_Memory certstore;
1✔
330
         certstore.add_certificate(trust_root);
1✔
331

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

337
         if(result.test_sz_eq("Expected size of ocsp_status", ocsp_status.size(), 1)) {
1✔
338
            if(result.test_sz_eq("Expected size of ocsp_status[0]", ocsp_status[0].size(), 1)) {
1✔
339
               result.test_sz_gt(
2✔
340
                  "Status warning", ocsp_status[0].count(Botan::Certificate_Status_Code::OCSP_NO_REVOCATION_URL), 0);
1✔
341
            }
342
         }
343

344
         return result;
1✔
345
      }
3✔
346

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

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

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

356
         Botan::Certificate_Store_In_Memory certstore;
1✔
357
         certstore.add_certificate(trust_root);
1✔
358

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

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

373
         return result;
1✔
374
      }
2✔
375
   #endif
376

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

380
         // OCSP response is signed by 3rd party responder certificate that is
381
         // not included in the OCSP response itself
382
         // See `src/scripts/randombit_ocsp_forger.sh` for a helper script to recreate those.
383
         auto ocsp = load_test_OCSP_resp("x509/ocsp/randombit_ocsp_forged_valid_nocerts.der");
1✔
384
         auto responder = load_test_X509_cert("x509/ocsp/randombit_ocsp_forged_responder.pem");
1✔
385
         auto ca = load_test_X509_cert("x509/ocsp/letsencrypt.pem");
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_opt_is_null("cannot find signing certificate without trusted responders",
1✔
391
                                 ocsp.find_signing_certificate(ca));
1✔
392
         result.test_opt_is_null("cannot find signing certificate without additional help",
1✔
393
                                 ocsp.find_signing_certificate(ca, &trusted_responders));
1✔
394

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

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

407
         return result;
1✔
408
      }
1✔
409

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

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

419
         result.test_is_true("Contains NoCheck extension", contains_cert_with_nocheck);
1✔
420

421
         return result;
1✔
422
      }
1✔
423

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

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

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

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

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

452
#endif
453

454
}  // 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