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

randombit / botan / 17405119897

02 Sep 2025 01:30PM UTC coverage: 90.657% (-0.006%) from 90.663%
17405119897

push

github

Brassinolide
Extend Certificate_Store interface to support searching by issuer DN and serial number

100249 of 110581 relevant lines covered (90.66%)

12245468.93 hits per line

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

77.63
/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/ber_dec.h>
14
   #include <botan/certstor_system.h>
15
   #include <botan/der_enc.h>
16
   #include <botan/hex.h>
17
   #include <algorithm>
18
   #include <memory>
19

20
namespace Botan_Tests {
21

22
namespace {
23

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

27
   try {
1✔
28
      result.start_timer();
1✔
29
      auto cert = certstore.find_cert_by_pubkey_sha1(get_key_id());
1✔
30
      result.end_timer();
1✔
31

32
      if(result.test_not_nullopt("found certificate", cert)) {
1✔
33
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
34
         result.test_is_eq("exactly one CN", cns.size(), size_t(1));
1✔
35
         result.test_eq("CN", cns.front(), get_subject_cn());
2✔
36
      }
1✔
37
   } catch(std::exception& e) {
1✔
38
      result.test_failure(e.what());
×
39
   }
×
40

41
   result.test_throws("on invalid SHA1 hash data", [&] { certstore.find_cert_by_pubkey_sha1({}); });
3✔
42

43
   return result;
1✔
44
}
×
45

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

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

54
   try {
1✔
55
      result.start_timer();
1✔
56
      auto cert = certstore.find_cert_by_pubkey_sha1(get_pubkey_sha1_of_cert_with_different_key_id());
1✔
57
      result.end_timer();
1✔
58

59
      if(result.test_not_nullopt("found certificate", cert)) {
1✔
60
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
61
         result.test_is_eq("exactly one CN", cns.size(), size_t(1));
1✔
62
         result.test_eq("CN", cns.front(), "SecureTrust CA");
2✔
63
      }
1✔
64
   } catch(std::exception& e) {
1✔
65
      result.test_failure(e.what());
×
66
   }
×
67

68
   return result;
69
}
×
70

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

74
   try {
1✔
75
      auto dn = get_dn();
1✔
76

77
      result.start_timer();
1✔
78
      auto cert = certstore.find_cert(dn, std::vector<uint8_t>());
1✔
79
      result.end_timer();
1✔
80

81
      if(result.test_not_nullopt("found certificate", cert)) {
1✔
82
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
83
         result.test_is_eq("exactly one CN", cns.size(), size_t(1));
1✔
84
         result.test_eq("CN", cns.front(), get_subject_cn());
2✔
85
      }
1✔
86
   } catch(std::exception& e) {
1✔
87
      result.test_failure(e.what());
×
88
   }
×
89

90
   return result;
1✔
91
}
×
92

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

96
   try {
1✔
97
      const auto DNs = get_utf8_dn_alternatives();
1✔
98

99
      unsigned int found = 0;
1✔
100

101
      result.start_timer();
1✔
102
      for(const auto& [cn, dn] : DNs) {
6✔
103
         if(auto cert = certstore.find_cert(dn, {})) {
10✔
104
            auto cns = cert->subject_dn().get_attribute("CN");
5✔
105
            result.test_is_eq("exactly one CN", cns.size(), size_t(1));
5✔
106
            result.test_eq("CN", cns.front(), cn);
5✔
107

108
            ++found;
5✔
109
         }
10✔
110
      }
111
      result.end_timer();
1✔
112

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

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

123
      result.test_gte("found at least one certificate", found, 1);
1✔
124
   } catch(std::exception& e) {
1✔
125
      result.test_failure(e.what());
×
126
   }
×
127

128
   return result;
1✔
129
}
×
130

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

134
   try {
1✔
135
      auto dn = get_dn();
1✔
136

137
      result.start_timer();
1✔
138
      auto cert = certstore.find_cert(dn, get_key_id());
1✔
139
      result.end_timer();
1✔
140

141
      if(result.test_not_nullopt("found certificate", cert)) {
1✔
142
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
143
         result.test_is_eq("exactly one CN", cns.size(), size_t(1));
1✔
144
         result.test_eq("CN", cns.front(), get_subject_cn());
2✔
145
      }
1✔
146
   } catch(std::exception& e) {
1✔
147
      result.test_failure(e.what());
×
148
   }
×
149

150
   return result;
1✔
151
}
×
152

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

156
   try {
1✔
157
      auto dn = get_dn();
1✔
158

159
      result.start_timer();
1✔
160
      auto certs = certstore.find_all_certs(dn, get_key_id());
1✔
161
      result.end_timer();
1✔
162

163
      if(result.confirm("result not empty", !certs.empty()) &&
2✔
164
         result.test_eq("exactly one certificate", certs.size(), 1)) {
2✔
165
         auto cns = certs.front().subject_dn().get_attribute("CN");
1✔
166
         result.test_is_eq("exactly one CN", cns.size(), size_t(1));
1✔
167
         result.test_eq("CN", cns.front(), get_subject_cn());
2✔
168
      }
1✔
169
   } catch(std::exception& e) {
1✔
170
      result.test_failure(e.what());
×
171
   }
×
172

173
   return result;
1✔
174
}
×
175

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

179
   try {
1✔
180
      auto dn = get_dn();
1✔
181

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

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

194
      if(result.confirm("result not empty", !certs.empty())) {
2✔
195
         auto cns = certs.front().subject_dn().get_attribute("CN");
1✔
196
         result.test_gte("at least one CN", cns.size(), size_t(1));
1✔
197
         result.test_eq("CN", cns.front(), get_subject_cn());
2✔
198
      }
1✔
199
   } catch(std::exception& e) {
1✔
200
      result.test_failure(e.what());
×
201
   }
×
202

203
   return result;
1✔
204
}
×
205

206
Test::Result find_all_subjects(Botan::Certificate_Store& certstore) {
1✔
207
   Test::Result result("System Certificate Store - Find all Certificate Subjects");
1✔
208

209
   try {
1✔
210
      result.start_timer();
1✔
211
      auto subjects = certstore.all_subjects();
1✔
212
      result.end_timer();
1✔
213

214
      if(result.confirm("result not empty", !subjects.empty())) {
2✔
215
         auto dn = get_dn();
1✔
216
         auto needle = std::find_if(
1✔
217
            subjects.cbegin(), subjects.cend(), [=](const Botan::X509_DN& subject) { return subject == dn; });
88✔
218

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

227
   return result;
1✔
228
}
×
229

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

233
   try {
1✔
234
      result.start_timer();
1✔
235
      auto cert = certstore.find_cert_by_issuer_dn_and_serial_number(get_dn(), get_serial_number());
1✔
236
      result.end_timer();
1✔
237

238
      if(result.test_not_nullopt("found certificate", cert)) {
1✔
239
         auto cns = cert->subject_dn().get_attribute("CN");
1✔
240
         result.test_is_eq("exactly one CN", cns.size(), size_t(1));
1✔
241
         result.test_eq("CN", cns.front(), get_subject_cn());
2✔
242
         result.test_eq("serial number", cert->serial_number(), get_serial_number());
2✔
243
      }
1✔
244
   } catch(std::exception& e) {
1✔
245
      result.test_failure(e.what());
×
246
   }
×
247

248
   return result;
1✔
249
}
×
250

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

254
   try {
1✔
255
      auto dn = get_unknown_dn();
1✔
256
      auto kid = get_unknown_key_id();
1✔
257

258
      result.start_timer();
1✔
259
      auto certs = certstore.find_all_certs(dn, kid);
1✔
260
      auto cert = certstore.find_cert(dn, kid);
1✔
261
      auto pubk_cert = certstore.find_cert_by_pubkey_sha1(kid);
1✔
262
      result.end_timer();
1✔
263

264
      result.confirm("find_all_certs did not find the dummy", certs.empty());
2✔
265
      result.confirm("find_cert did not find the dummy", !cert);
2✔
266
      result.confirm("find_cert_by_pubkey_sha1 did not find the dummy", !pubk_cert);
2✔
267
   } catch(std::exception& e) {
2✔
268
      result.test_failure(e.what());
×
269
   }
×
270

271
   return result;
1✔
272
}
×
273

274
   #if defined(BOTAN_HAS_CERTSTOR_MACOS)
275

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

279
   try {
280
      auto dn = get_skewed_dn();
281

282
      result.start_timer();
283
      auto certs = certstore.find_all_certs(dn, std::vector<uint8_t>());
284
      auto cert = certstore.find_cert(dn, std::vector<uint8_t>());
285
      result.end_timer();
286

287
      if(result.confirm("find_all_certs did find the skewed DN", !certs.empty()) &&
288
         result.confirm("find_cert did find the skewed DN", cert.has_value())) {
289
         result.test_eq(
290
            "it is the correct cert", certs.front().subject_dn().get_first_attribute("CN"), get_subject_cn());
291
         result.test_eq("it is the correct cert", cert->subject_dn().get_first_attribute("CN"), get_subject_cn());
292
      }
293
   } catch(std::exception& e) {
294
      result.test_failure(e.what());
295
   }
296

297
   return result;
298
}
299

300
   #endif
301

302
class Certstor_System_Tests final : public Test {
×
303
   public:
304
      std::vector<Test::Result> run() override {
1✔
305
         Test::Result open_result("System Certificate Store - Open Keychain");
1✔
306

307
         std::unique_ptr<Botan::Certificate_Store> system;
1✔
308

309
         try {
1✔
310
            open_result.start_timer();
1✔
311
            system = std::make_unique<Botan::System_Certificate_Store>();
1✔
312
            open_result.end_timer();
1✔
313
         } catch(Botan::Not_Implemented& e) {
×
314
            BOTAN_UNUSED(e);
×
315
            open_result.test_note("Skipping due to not available in current build");
×
316
            return {open_result};
×
317
         } catch(std::exception& e) {
×
318
            open_result.test_failure(e.what());
×
319
            return {open_result};
×
320
         }
×
321

322
         open_result.test_success();
1✔
323

324
         std::vector<Test::Result> results;
1✔
325
         results.push_back(open_result);
1✔
326

327
         results.push_back(find_certificate_by_pubkey_sha1(*system));
2✔
328
         results.push_back(find_certificate_by_pubkey_sha1_with_unmatching_key_id(*system));
2✔
329
         results.push_back(find_cert_by_subject_dn(*system));
2✔
330
         results.push_back(find_cert_by_subject_dn_and_key_id(*system));
2✔
331
         results.push_back(find_all_certs_by_subject_dn(*system));
2✔
332
         results.push_back(find_certs_by_subject_dn_and_key_id(*system));
2✔
333
         results.push_back(find_all_subjects(*system));
2✔
334
         results.push_back(no_certificate_matches(*system));
2✔
335
         results.push_back(find_cert_by_utf8_subject_dn(*system));
2✔
336
         results.push_back(find_cert_by_issuer_dn_and_serial_number(*system));
2✔
337
   #if defined(BOTAN_HAS_CERTSTOR_MACOS)
338
         results.push_back(certificate_matching_with_dn_normalization(*system));
339
   #endif
340

341
         return results;
1✔
342
      }
2✔
343
};
344

345
BOTAN_REGISTER_TEST("x509", "certstor_system", Certstor_System_Tests);
346

347
}  // namespace
348

349
}  // namespace Botan_Tests
350

351
#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