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

randombit / botan / 13215274653

08 Feb 2025 11:38AM UTC coverage: 91.655% (-0.009%) from 91.664%
13215274653

Pull #4650

github

web-flow
Merge 107f31833 into bc555cd3c
Pull Request #4650: Reorganize code and reduce header dependencies

94836 of 103471 relevant lines covered (91.65%)

11230958.94 hits per line

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

77.11
/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)) {
3✔
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)) {
3✔
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)) {
3✔
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)) {
3✔
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 no_certificate_matches(Botan::Certificate_Store& certstore) {
1✔
231
   Test::Result result("System Certificate Store - can deal with no matches (regression test)");
1✔
232

233
   try {
1✔
234
      auto dn = get_unknown_dn();
1✔
235
      auto kid = get_unknown_key_id();
1✔
236

237
      result.start_timer();
1✔
238
      auto certs = certstore.find_all_certs(dn, kid);
1✔
239
      auto cert = certstore.find_cert(dn, kid);
1✔
240
      auto pubk_cert = certstore.find_cert_by_pubkey_sha1(kid);
1✔
241
      result.end_timer();
1✔
242

243
      result.confirm("find_all_certs did not find the dummy", certs.empty());
2✔
244
      result.confirm("find_cert did not find the dummy", !cert);
2✔
245
      result.confirm("find_cert_by_pubkey_sha1 did not find the dummy", !pubk_cert);
2✔
246
   } catch(std::exception& e) {
2✔
247
      result.test_failure(e.what());
×
248
   }
×
249

250
   return result;
1✔
251
}
×
252

253
   #if defined(BOTAN_HAS_CERTSTOR_MACOS)
254

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

258
   try {
259
      auto dn = get_skewed_dn();
260

261
      result.start_timer();
262
      auto certs = certstore.find_all_certs(dn, std::vector<uint8_t>());
263
      auto cert = certstore.find_cert(dn, std::vector<uint8_t>());
264
      result.end_timer();
265

266
      if(result.confirm("find_all_certs did find the skewed DN", !certs.empty()) &&
267
         result.confirm("find_cert did find the skewed DN", cert.has_value())) {
268
         result.test_eq(
269
            "it is the correct cert", certs.front().subject_dn().get_first_attribute("CN"), get_subject_cn());
270
         result.test_eq("it is the correct cert", cert->subject_dn().get_first_attribute("CN"), get_subject_cn());
271
      }
272
   } catch(std::exception& e) {
273
      result.test_failure(e.what());
274
   }
275

276
   return result;
277
}
278

279
   #endif
280

281
class Certstor_System_Tests final : public Test {
×
282
   public:
283
      std::vector<Test::Result> run() override {
1✔
284
         Test::Result open_result("System Certificate Store - Open Keychain");
1✔
285

286
         std::unique_ptr<Botan::Certificate_Store> system;
1✔
287

288
         try {
1✔
289
            open_result.start_timer();
1✔
290
            system = std::make_unique<Botan::System_Certificate_Store>();
1✔
291
            open_result.end_timer();
1✔
292
         } catch(Botan::Not_Implemented& e) {
×
293
            BOTAN_UNUSED(e);
×
294
            open_result.test_note("Skipping due to not available in current build");
×
295
            return {open_result};
×
296
         } catch(std::exception& e) {
×
297
            open_result.test_failure(e.what());
×
298
            return {open_result};
×
299
         }
×
300

301
         open_result.test_success();
1✔
302

303
         std::vector<Test::Result> results;
1✔
304
         results.push_back(open_result);
1✔
305

306
         results.push_back(find_certificate_by_pubkey_sha1(*system));
2✔
307
         results.push_back(find_certificate_by_pubkey_sha1_with_unmatching_key_id(*system));
2✔
308
         results.push_back(find_cert_by_subject_dn(*system));
2✔
309
         results.push_back(find_cert_by_subject_dn_and_key_id(*system));
2✔
310
         results.push_back(find_all_certs_by_subject_dn(*system));
2✔
311
         results.push_back(find_certs_by_subject_dn_and_key_id(*system));
2✔
312
         results.push_back(find_all_subjects(*system));
2✔
313
         results.push_back(no_certificate_matches(*system));
2✔
314
         results.push_back(find_cert_by_utf8_subject_dn(*system));
2✔
315
   #if defined(BOTAN_HAS_CERTSTOR_MACOS)
316
         results.push_back(certificate_matching_with_dn_normalization(*system));
317
   #endif
318

319
         return results;
1✔
320
      }
2✔
321
};
322

323
BOTAN_REGISTER_TEST("x509", "certstor_system", Certstor_System_Tests);
324

325
}  // namespace
326

327
}  // namespace Botan_Tests
328

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

© 2025 Coveralls, Inc