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

randombit / botan / 24872040145

24 Apr 2026 01:10AM UTC coverage: 89.401% (-0.07%) from 89.474%
24872040145

push

github

web-flow
Merge pull request #5539 from randombit/jack/cert-cache

Refactor and optimize Windows certificate store

106671 of 119318 relevant lines covered (89.4%)

11479699.69 hits per line

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

78.83
/src/tests/test_certstor_system.cpp
1
/*
2
* (C) 1999-2021 Jack Lloyd
3
* (C) 2019,2021 René Meusel
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_CERTSTOR_SYSTEM)
11

12
   #include "test_certstor_utils.h"
13
   #include <botan/certstor_system.h>
14
   #include <algorithm>
15
   #include <memory>
16

17
namespace Botan_Tests {
18

19
namespace {
20

21
Test::Result find_certificate_by_pubkey_sha1(Botan::Certificate_Store& certstore) {
1✔
22
   Test::Result result("System Certificate Store - Find Certificate by SHA1(pubkey)");
1✔
23

24
   try {
1✔
25
      result.start_timer();
1✔
26
      auto cert = certstore.find_cert_by_pubkey_sha1(get_key_id());
1✔
27
      result.end_timer();
1✔
28

29
      if(result.test_opt_not_null("found certificate", cert)) {
1✔
30
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
31
         result.test_sz_eq("exactly one CN", cns.size(), 1);
1✔
32
         result.test_str_eq("CN", cns.front(), get_subject_cn());
1✔
33
      }
1✔
34
   } catch(std::exception& e) {
1✔
35
      result.test_failure(e.what());
×
36
   }
×
37

38
   result.test_throws("on invalid SHA1 hash data", [&] { certstore.find_cert_by_pubkey_sha1({}); });
2✔
39

40
   return result;
1✔
41
}
×
42

43
Test::Result find_certificate_by_pubkey_sha1_with_unmatching_key_id(Botan::Certificate_Store& certstore) {
1✔
44
   Test::Result result("System Certificate Store - Find Certificate by SHA1(pubkey) - regression test for GH #2779");
1✔
45

46
   if(!certstore.find_cert(get_dn_of_cert_with_different_key_id(), {}).has_value()) {
3✔
47
      result.note_missing("OS does not trust the certificate used for this regression test, skipping");
×
48
      return result;
×
49
   }
50

51
   try {
1✔
52
      result.start_timer();
1✔
53
      auto cert = certstore.find_cert_by_pubkey_sha1(get_pubkey_sha1_of_cert_with_different_key_id());
1✔
54
      result.end_timer();
1✔
55

56
      if(result.test_opt_not_null("found certificate", cert)) {
1✔
57
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
58
         result.test_sz_eq("exactly one CN", cns.size(), 1);
1✔
59
         result.test_str_eq("CN", cns.front(), "SecureTrust CA");
1✔
60
      }
1✔
61
   } catch(std::exception& e) {
1✔
62
      result.test_failure(e.what());
×
63
   }
×
64

65
   return result;
66
}
×
67

68
Test::Result find_cert_by_subject_dn(Botan::Certificate_Store& certstore) {
1✔
69
   Test::Result result("System Certificate Store - Find Certificate by subject DN");
1✔
70

71
   try {
1✔
72
      auto dn = get_dn();
1✔
73

74
      result.start_timer();
1✔
75
      auto cert = certstore.find_cert(dn, std::vector<uint8_t>());
1✔
76
      result.end_timer();
1✔
77

78
      if(result.test_opt_not_null("found certificate", cert)) {
1✔
79
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
80
         result.test_sz_eq("exactly one CN", cns.size(), 1);
1✔
81
         result.test_str_eq("CN", cns.front(), get_subject_cn());
1✔
82
      }
1✔
83
   } catch(std::exception& e) {
2✔
84
      result.test_failure(e.what());
×
85
   }
×
86

87
   return result;
1✔
88
}
×
89

90
Test::Result find_cert_by_utf8_subject_dn(Botan::Certificate_Store& certstore) {
1✔
91
   Test::Result result("System Certificate Store - Find Certificate by UTF8 subject DN");
1✔
92

93
   try {
1✔
94
      const auto DNs = get_utf8_dn_alternatives();
1✔
95

96
      unsigned int found = 0;
1✔
97

98
      result.start_timer();
1✔
99
      for(const auto& [cn, dn] : DNs) {
6✔
100
         if(auto cert = certstore.find_cert(dn, {})) {
5✔
101
            auto cns = cert->subject_dn().get_attribute("CN");
5✔
102
            result.test_sz_eq("exactly one CN", cns.size(), 1);
5✔
103
            result.test_str_eq("CN", cns.front(), cn);
5✔
104

105
            ++found;
5✔
106
         }
10✔
107
      }
108
      result.end_timer();
1✔
109

110
      if(found == 0) {
1✔
111
         std::string tried_cns;
×
112
         for(const auto& [cn, dn] : DNs) {
×
113
            tried_cns += cn + ", ";
×
114
         }
115

116
         result.test_note("Tried to find any of those CNs: " + tried_cns);
×
117
         result.test_failure("Did not find any certificate via an UTF-8 encoded DN");
×
118
      }
×
119

120
      result.test_sz_gte("found at least one certificate", found, 1);
1✔
121
   } catch(std::exception& e) {
1✔
122
      result.test_failure(e.what());
×
123
   }
×
124

125
   return result;
1✔
126
}
×
127

128
Test::Result find_cert_by_subject_dn_and_key_id(Botan::Certificate_Store& certstore) {
1✔
129
   Test::Result result("System Certificate Store - Find Certificate by subject DN and key ID");
1✔
130

131
   try {
1✔
132
      auto dn = get_dn();
1✔
133

134
      result.start_timer();
1✔
135
      auto cert = certstore.find_cert(dn, get_key_id());
1✔
136
      result.end_timer();
1✔
137

138
      if(result.test_opt_not_null("found certificate", cert)) {
1✔
139
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
140
         result.test_sz_eq("exactly one CN", cns.size(), 1);
1✔
141
         result.test_str_eq("CN", cns.front(), get_subject_cn());
1✔
142
      }
1✔
143
   } catch(std::exception& e) {
2✔
144
      result.test_failure(e.what());
×
145
   }
×
146

147
   return result;
1✔
148
}
×
149

150
Test::Result find_certs_by_subject_dn_and_key_id(Botan::Certificate_Store& certstore) {
1✔
151
   Test::Result result("System Certificate Store - Find Certificates by subject DN and key ID");
1✔
152

153
   try {
1✔
154
      auto dn = get_dn();
1✔
155

156
      result.start_timer();
1✔
157
      auto certs = certstore.find_all_certs(dn, get_key_id());
1✔
158
      result.end_timer();
1✔
159

160
      if(result.test_is_true("result not empty", !certs.empty()) &&
2✔
161
         result.test_sz_eq("exactly one certificate", certs.size(), 1)) {
1✔
162
         auto cns = certs.front().subject_dn().get_attribute("CN");
1✔
163
         result.test_sz_eq("exactly one CN", cns.size(), 1);
1✔
164
         result.test_str_eq("CN", cns.front(), get_subject_cn());
1✔
165
         result.test_is_true("returned cert is considered contained", certstore.contains(certs.front()));
1✔
166
      }
1✔
167
   } catch(std::exception& e) {
2✔
168
      result.test_failure(e.what());
×
169
   }
×
170

171
   return result;
1✔
172
}
×
173

174
Test::Result find_all_certs_by_subject_dn(Botan::Certificate_Store& certstore) {
1✔
175
   Test::Result result("System Certificate Store - Find all Certificates by subject DN");
1✔
176

177
   try {
1✔
178
      auto dn = get_dn();
1✔
179

180
      result.start_timer();
1✔
181
      auto certs = certstore.find_all_certs(dn, std::vector<uint8_t>());
1✔
182
      result.end_timer();
1✔
183

184
      // check for duplications
185
      sort(certs.begin(), certs.end());
1✔
186
      for(size_t i = 1; i < certs.size(); ++i) {
1✔
187
         if(certs[i - 1] == certs[i]) {
×
188
            result.test_failure("find_all_certs produced duplicated result");
×
189
         }
190
      }
191

192
      // check all returned certs are considered contained
193
      for(const auto& cert : certs) {
2✔
194
         result.test_is_true("contains returns true", certstore.contains(cert));
1✔
195
      }
196

197
      if(result.test_is_true("result not empty", !certs.empty())) {
1✔
198
         auto cns = certs.front().subject_dn().get_attribute("CN");
1✔
199
         result.test_sz_gte("at least one CN", cns.size(), size_t(1));
1✔
200
         result.test_str_eq("CN", cns.front(), get_subject_cn());
1✔
201
      }
1✔
202
   } catch(std::exception& e) {
2✔
203
      result.test_failure(e.what());
×
204
   }
×
205

206
   return result;
1✔
207
}
×
208

209
Test::Result find_all_subjects(Botan::Certificate_Store& certstore) {
1✔
210
   Test::Result result("System Certificate Store - Find all Certificate Subjects");
1✔
211

212
   try {
1✔
213
      result.start_timer();
1✔
214
      auto subjects = certstore.all_subjects();
1✔
215
      result.end_timer();
1✔
216

217
      if(result.test_is_true("result not empty", !subjects.empty())) {
1✔
218
         auto dn = get_dn();
1✔
219
         auto needle = std::find_if(
1✔
220
            subjects.cbegin(), subjects.cend(), [=](const Botan::X509_DN& subject) { return subject == dn; });
91✔
221

222
         if(result.test_is_true("found expected certificate", needle != subjects.end())) {
1✔
223
            result.test_is_true("expected certificate", *needle == dn);
1✔
224
         }
225
      }
1✔
226
   } catch(std::exception& e) {
1✔
227
      result.test_failure(e.what());
×
228
   }
×
229

230
   return result;
1✔
231
}
×
232

233
Test::Result find_cert_by_issuer_dn_and_serial_number(Botan::Certificate_Store& certstore) {
1✔
234
   Test::Result result("System Certificate Store - Find Certificate by issuer DN and serial number");
1✔
235

236
   try {
1✔
237
      result.start_timer();
1✔
238
      auto cert = certstore.find_cert_by_issuer_dn_and_serial_number(get_dn(), get_serial_number());
2✔
239
      result.end_timer();
1✔
240

241
      if(result.test_opt_not_null("found certificate", cert)) {
1✔
242
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
243
         result.test_sz_eq("exactly one CN", cns.size(), 1);
1✔
244
         result.test_str_eq("CN", cns.front(), get_subject_cn());
1✔
245
         result.test_bin_eq("serial number", cert->serial_number(), get_serial_number());
1✔
246
         result.test_is_true("returned cert is considered contained", certstore.contains(cert.value()));
1✔
247
      }
1✔
248
   } catch(std::exception& e) {
1✔
249
      result.test_failure(e.what());
×
250
   }
×
251

252
   return result;
1✔
253
}
×
254

255
Test::Result no_certificate_matches(Botan::Certificate_Store& certstore) {
1✔
256
   Test::Result result("System Certificate Store - can deal with no matches (regression test)");
1✔
257

258
   try {
1✔
259
      auto dn = get_unknown_dn();
1✔
260
      auto kid = get_unknown_key_id();
1✔
261

262
      result.start_timer();
1✔
263
      auto certs = certstore.find_all_certs(dn, kid);
1✔
264
      auto cert = certstore.find_cert(dn, kid);
1✔
265
      auto pubk_cert = certstore.find_cert_by_pubkey_sha1(kid);
1✔
266
      result.end_timer();
1✔
267

268
      result.test_is_true("find_all_certs did not find the dummy", certs.empty());
1✔
269
      result.test_is_true("find_cert did not find the dummy", !cert);
1✔
270
      result.test_is_true("find_cert_by_pubkey_sha1 did not find the dummy", !pubk_cert);
1✔
271
   } catch(std::exception& e) {
2✔
272
      result.test_failure(e.what());
×
273
   }
×
274

275
   return result;
1✔
276
}
×
277

278
   #if defined(BOTAN_HAS_CERTSTOR_MACOS)
279

280
Test::Result certificate_matching_with_dn_normalization(Botan::Certificate_Store& certstore) {
281
   Test::Result result("System Certificate Store - normalization of X.509 DN (regression test)");
282

283
   try {
284
      auto dn = get_skewed_dn();
285

286
      result.start_timer();
287
      auto certs = certstore.find_all_certs(dn, std::vector<uint8_t>());
288
      auto cert = certstore.find_cert(dn, std::vector<uint8_t>());
289
      result.end_timer();
290

291
      if(result.test_is_true("find_all_certs did find the skewed DN", !certs.empty()) &&
292
         result.test_is_true("find_cert did find the skewed DN", cert.has_value())) {
293
         result.test_str_eq(
294
            "it is the correct cert", certs.front().subject_dn().get_first_attribute("CN"), get_subject_cn());
295
         result.test_str_eq("it is the correct cert", cert->subject_dn().get_first_attribute("CN"), get_subject_cn());
296
      }
297

298
      // check all returned certs are considered contained
299
      for(const auto& ret : certs) {
300
         result.test_is_true("contains returns true", certstore.contains(ret));
301
      }
302
   } catch(std::exception& e) {
303
      result.test_failure(e.what());
304
   }
305

306
   return result;
307
}
308

309
   #endif
310

311
class Certstor_System_Tests final : public Test {
1✔
312
   public:
313
      std::vector<Test::Result> run() override {
1✔
314
         Test::Result open_result("System Certificate Store - Open Keychain");
1✔
315

316
         std::unique_ptr<Botan::Certificate_Store> system;
1✔
317

318
         try {
1✔
319
            open_result.start_timer();
1✔
320
            system = std::make_unique<Botan::System_Certificate_Store>();
1✔
321
            open_result.end_timer();
1✔
322
         } catch(Botan::Not_Implemented&) {
×
323
            open_result.test_note("Skipping due to not available in current build");
×
324
            return {open_result};
×
325
         } catch(std::exception& e) {
×
326
            open_result.test_failure(e.what());
×
327
            return {open_result};
×
328
         }
×
329

330
         open_result.test_success();
1✔
331

332
         std::vector<Test::Result> results;
1✔
333
         results.push_back(open_result);
1✔
334

335
         results.push_back(find_certificate_by_pubkey_sha1(*system));
2✔
336
         results.push_back(find_certificate_by_pubkey_sha1_with_unmatching_key_id(*system));
2✔
337
         results.push_back(find_cert_by_subject_dn(*system));
2✔
338
         results.push_back(find_cert_by_subject_dn_and_key_id(*system));
2✔
339
         results.push_back(find_all_certs_by_subject_dn(*system));
2✔
340
         results.push_back(find_certs_by_subject_dn_and_key_id(*system));
2✔
341
         results.push_back(find_all_subjects(*system));
2✔
342
         results.push_back(no_certificate_matches(*system));
2✔
343
         results.push_back(find_cert_by_utf8_subject_dn(*system));
2✔
344
         results.push_back(find_cert_by_issuer_dn_and_serial_number(*system));
2✔
345
   #if defined(BOTAN_HAS_CERTSTOR_MACOS)
346
         results.push_back(certificate_matching_with_dn_normalization(*system));
347
   #endif
348

349
         return results;
1✔
350
      }
2✔
351
};
352

353
BOTAN_REGISTER_TEST("x509", "certstor_system", Certstor_System_Tests);
354

355
}  // namespace
356

357
}  // namespace Botan_Tests
358

359
#endif
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