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

randombit / botan / 5079590438

25 May 2023 12:28PM UTC coverage: 92.228% (+0.5%) from 91.723%
5079590438

Pull #3502

github

Pull Request #3502: Apply clang-format to the codebase

75589 of 81959 relevant lines covered (92.23%)

12139530.51 hits per line

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

79.57
/src/tests/test_certstor.cpp
1
/*
2
* (C) 2016 Kai Michaelis, Rohde & Schwarz Cybersecurity
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include "tests.h"
8
#include <sstream>
9

10
#if defined(BOTAN_HAS_X509_CERTIFICATES)
11
   #include <botan/certstor.h>
12
   #include <botan/pk_keys.h>
13
   #include <botan/pkcs8.h>
14
   #include <botan/pkix_types.h>
15
   #include <botan/x509cert.h>
16
   #include <botan/internal/filesystem.h>
17

18
   #if defined(BOTAN_HAS_CERTSTOR_SQLITE3)
19
      #include <botan/certstor_sqlite.h>
20
      #include <botan/sqlite3.h>
21
   #endif
22
#endif
23

24
namespace Botan_Tests {
25

26
namespace {
27

28
#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_HAS_RSA) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
29

30
struct CertificateAndKey {
13✔
31
      const Botan::X509_Certificate certificate;
32
      const std::shared_ptr<Botan::Private_Key> private_key;
33

34
      bool operator!=(const CertificateAndKey& rhs) const {
12✔
35
         return std::tie(certificate, private_key) != std::tie(rhs.certificate, rhs.private_key);
6✔
36
      }
37
};
38

39
   #if defined(BOTAN_HAS_CERTSTOR_SQLITE3)
40
Test::Result test_certstor_sqlite3_insert_find_remove_test(const std::vector<CertificateAndKey>& certsandkeys) {
1✔
41
   Test::Result result("Certificate Store SQLITE3 - Insert, Find, Remove");
1✔
42

43
   try {
1✔
44
      auto& rng = Test::rng();
1✔
45
      const std::string passwd(reinterpret_cast<const char*>(rng.random_vec(8).data()), 8);
3✔
46
      // Just create a database in memory for testing (https://sqlite.org/inmemorydb.html)
47
      Botan::Certificate_Store_In_SQLite store(":memory:", passwd, rng);
1✔
48

49
      for(const auto& a : certsandkeys) {
7✔
50
         store.insert_key(a.certificate, *a.private_key);
6✔
51
      }
52

53
      for(const auto& certandkey : certsandkeys) {
7✔
54
         const auto cert = certandkey.certificate;
6✔
55
         const auto key = certandkey.private_key;
6✔
56
         const auto wo_keyid = store.find_cert(cert.subject_dn(), {});
6✔
57
         const auto w_keyid = store.find_cert(cert.subject_dn(), cert.subject_key_id());
6✔
58

59
         if(!wo_keyid || !w_keyid) {
6✔
60
            result.test_failure("Can't retrieve certificate");
×
61
            return result;
×
62
         }
63

64
         const auto priv = store.find_key(cert);
6✔
65
         if(!priv && (certsandkeys[1] != certandkey && certsandkeys[0] != certandkey)) {
6✔
66
            result.test_failure("Can't retrieve private key for " + cert.fingerprint("SHA-1"));
×
67
            return result;
×
68
         }
69

70
         result.test_eq("Got wrong certificate", cert.fingerprint(), w_keyid->fingerprint());
18✔
71

72
         if(priv) {
6✔
73
            result.test_eq("Got wrong private key", key->private_key_bits(), priv->private_key_bits());
15✔
74

75
            const auto rev_certs = store.find_certs_for_key(*priv);
5✔
76

77
            if(rev_certs.empty()) {
5✔
78
               result.test_failure("No certificate");
×
79
            } else {
80
               const bool found =
5✔
81
                  std::any_of(rev_certs.begin(), rev_certs.end(), [&](const Botan::X509_Certificate& c) {
5✔
82
                     return c.fingerprint() == cert.fingerprint();
15✔
83
                  });
84

85
               result.test_eq("Got wrong/no certificate", found, true);
10✔
86
            }
87
         }
5✔
88

89
         if(certsandkeys[4] != certandkey && certsandkeys[5] != certandkey) {
6✔
90
            result.test_eq("Got wrong certificate", cert.fingerprint(), wo_keyid->fingerprint());
16✔
91
         }
92

93
         result.test_eq("Can't remove certificate", store.remove_cert(cert), true);
6✔
94
         result.test_eq("Can't remove certificate", !store.find_cert(cert.subject_dn(), cert.subject_key_id()), true);
12✔
95

96
         if(priv) {
6✔
97
            store.remove_key(*key);
5✔
98
         }
99

100
         result.test_eq("Can't remove key", !store.find_key(cert), true);
12✔
101
      }
24✔
102

103
      return result;
104
   } catch(std::exception& e) {
1✔
105
      result.test_failure(e.what());
×
106
      return result;
×
107
   }
×
108
}
×
109

110
Test::Result test_certstor_sqlite3_crl_test(const std::vector<CertificateAndKey>& certsandkeys) {
1✔
111
   Test::Result result("Certificate Store SQLITE3 - CRL");
1✔
112
   try {
1✔
113
      auto& rng = Test::rng();
1✔
114
      const std::string passwd(reinterpret_cast<const char*>(rng.random_vec(8).data()), 8);
3✔
115
      // Just create a database in memory for testing (https://sqlite.org/inmemorydb.html)
116
      Botan::Certificate_Store_In_SQLite store(":memory:", passwd, rng);
1✔
117

118
      for(const auto& a : certsandkeys) {
7✔
119
         store.insert_cert(a.certificate);
6✔
120
      }
121

122
      store.revoke_cert(certsandkeys[0].certificate, Botan::CRL_Code::CaCompromise);
1✔
123
      store.revoke_cert(certsandkeys[3].certificate, Botan::CRL_Code::CaCompromise);
1✔
124
      store.revoke_cert(certsandkeys[3].certificate, Botan::CRL_Code::CaCompromise);
1✔
125

126
      {
1✔
127
         const auto crls = store.generate_crls();
1✔
128

129
         result.test_eq("Can't revoke certificate", crls.size(), 2);
1✔
130
         result.test_eq(
2✔
131
            "Can't revoke certificate",
132
            crls[0].is_revoked(certsandkeys[0].certificate) ^ crls[1].is_revoked(certsandkeys[0].certificate),
1✔
133
            true);
134
         result.test_eq(
2✔
135
            "Can't revoke certificate",
136
            crls[0].is_revoked(certsandkeys[3].certificate) ^ crls[1].is_revoked(certsandkeys[3].certificate),
1✔
137
            true);
138
      }
1✔
139

140
      store.affirm_cert(certsandkeys[3].certificate);
1✔
141

142
      {
1✔
143
         const auto crls = store.generate_crls();
1✔
144

145
         result.test_eq("Can't revoke certificate, wrong crl size", crls.size(), 1);
1✔
146
         result.test_eq(
1✔
147
            "Can't revoke certificate, cert 0 not revoked", crls[0].is_revoked(certsandkeys[0].certificate), true);
1✔
148
      }
1✔
149

150
      const auto cert0_crl = store.find_crl_for(certsandkeys[0].certificate);
1✔
151

152
      result.test_eq("Can't revoke certificate, crl for cert 0", !cert0_crl, false);
1✔
153
      result.test_eq("Can't revoke certificate, crl for cert 0 size check", cert0_crl->get_revoked().size(), 1);
1✔
154
      result.test_eq(
1✔
155
         "Can't revoke certificate, no crl for cert 0", cert0_crl->is_revoked(certsandkeys[0].certificate), true);
1✔
156

157
      const auto cert3_crl = store.find_crl_for(certsandkeys[3].certificate);
1✔
158

159
      result.test_eq("Can't revoke certificate, crl for cert 3", !cert3_crl, true);
1✔
160

161
      return result;
1✔
162
   } catch(std::exception& e) {
2✔
163
      result.test_failure(e.what());
×
164
      return result;
×
165
   }
×
166
}
×
167

168
Test::Result test_certstor_sqlite3_all_subjects_test(const std::vector<CertificateAndKey>& certsandkeys) {
1✔
169
   Test::Result result("Certificate Store SQLITE3 - All subjects");
1✔
170
   try {
1✔
171
      auto& rng = Test::rng();
1✔
172
      const std::string passwd(reinterpret_cast<const char*>(rng.random_vec(8).data()), 8);
3✔
173
      // Just create a database in memory for testing (https://sqlite.org/inmemorydb.html)
174
      Botan::Certificate_Store_In_SQLite store(":memory:", passwd, rng);
×
175

176
      for(const auto& a : certsandkeys) {
7✔
177
         store.insert_cert(a.certificate);
6✔
178
      }
179

180
      const auto subjects = store.all_subjects();
1✔
181

182
      result.test_eq("Check subject list length", subjects.size(), 6);
1✔
183

184
      for(const auto& sub : subjects) {
7✔
185
         std::stringstream ss;
6✔
186

187
         ss << sub;
6✔
188
         result.test_eq(
18✔
189
            "Check subject " + ss.str(),
12✔
190
            certsandkeys[0].certificate.subject_dn() == sub || certsandkeys[1].certificate.subject_dn() == sub ||
15✔
191
               certsandkeys[2].certificate.subject_dn() == sub || certsandkeys[3].certificate.subject_dn() == sub ||
9✔
192
               certsandkeys[4].certificate.subject_dn() == sub || certsandkeys[5].certificate.subject_dn() == sub,
8✔
193
            true);
194
      }
6✔
195
      return result;
1✔
196
   } catch(std::exception& e) {
1✔
197
      result.test_failure(e.what());
×
198
      return result;
×
199
   }
×
200
}
×
201

202
Test::Result test_certstor_sqlite3_find_all_certs_test(const std::vector<CertificateAndKey>& certsandkeys) {
1✔
203
   Test::Result result("Certificate Store SQLITE3 - Find all certs");
1✔
204
   try {
1✔
205
      auto& rng = Test::rng();
1✔
206
      const std::string passwd(reinterpret_cast<const char*>(rng.random_vec(8).data()), 8);
3✔
207
      // Just create a database in memory for testing (https://sqlite.org/inmemorydb.html)
208
      Botan::Certificate_Store_In_SQLite store(":memory:", passwd, rng);
1✔
209

210
      for(const auto& a : certsandkeys) {
7✔
211
         store.insert_cert(a.certificate);
6✔
212
      }
213

214
      for(const auto& a : certsandkeys) {
7✔
215
         auto res_vec = store.find_all_certs(a.certificate.subject_dn(), a.certificate.subject_key_id());
6✔
216
         if(res_vec.size() != 1) {
6✔
217
            result.test_failure("SQLITE all lookup error");
×
218
            return result;
×
219
         } else {
220
            std::stringstream a_ss;
6✔
221
            a_ss << a.certificate.subject_dn();
6✔
222
            std::stringstream res_ss;
6✔
223
            res_ss << res_vec.at(0).subject_dn();
6✔
224
            result.test_eq("Check subject " + a_ss.str(), a_ss.str(), res_ss.str());
12✔
225
         }
6✔
226
      }
6✔
227

228
      Botan::X509_Certificate same_dn_1 =
1✔
229
         Botan::X509_Certificate(Test::data_file("x509/bsi/common_14/common_14_sub_ca.ca.pem.crt"));
2✔
230
      Botan::X509_Certificate same_dn_2 =
1✔
231
         Botan::X509_Certificate(Test::data_file("x509/bsi/common_14/common_14_wrong_sub_ca.ca.pem.crt"));
2✔
232

233
      store.insert_cert(same_dn_1);
1✔
234
      store.insert_cert(same_dn_2);
1✔
235
      auto res_vec = store.find_all_certs(same_dn_1.subject_dn(), {});
1✔
236

237
      if(res_vec.size() != 2) {
1✔
238
         result.test_failure("SQLITE all lookup error (duplicate) " + std::to_string(res_vec.size()));
×
239
         return result;
×
240
      } else {
241
         std::stringstream cert_ss;
1✔
242
         cert_ss << same_dn_1.subject_dn();
1✔
243
         std::stringstream res_ss;
1✔
244
         res_ss << res_vec.at(0).subject_dn();
1✔
245
         result.test_eq("Check subject " + cert_ss.str(), cert_ss.str(), res_ss.str());
3✔
246
         res_ss.str("");
2✔
247
         res_ss << res_vec.at(1).subject_dn();
1✔
248
         result.test_eq("Check subject " + cert_ss.str(), cert_ss.str(), res_ss.str());
3✔
249
      }
1✔
250
   } catch(const std::exception& e) {
1✔
251
      result.test_failure(e.what());
×
252
      return result;
×
253
   }
×
254
   return result;
255
}
×
256

257
   #endif
258

259
Test::Result test_certstor_find_hash_subject(const std::vector<CertificateAndKey>& certsandkeys) {
1✔
260
   Test::Result result("Certificate Store - Find by subject hash");
1✔
261

262
   try {
1✔
263
      Botan::Certificate_Store_In_Memory store;
1✔
264

265
      for(const auto& a : certsandkeys) {
7✔
266
         store.add_certificate(a.certificate);
6✔
267
      }
268

269
      for(const auto& certandkey : certsandkeys) {
7✔
270
         const auto cert = certandkey.certificate;
6✔
271
         const auto hash = cert.raw_subject_dn_sha256();
6✔
272

273
         const auto found = store.find_cert_by_raw_subject_dn_sha256(hash);
6✔
274
         if(!found) {
6✔
275
            result.test_failure("Can't retrieve certificate " + cert.fingerprint("SHA-1"));
×
276
            return result;
×
277
         }
278

279
         result.test_eq("Got wrong certificate", hash, found->raw_subject_dn_sha256());
18✔
280
      }
12✔
281

282
      const auto found = store.find_cert_by_raw_subject_dn_sha256(std::vector<uint8_t>(32, 0));
1✔
283
      if(found) {
1✔
284
         result.test_failure("Certificate found for dummy hash");
×
285
         return result;
×
286
      }
287

288
      return result;
289
   } catch(std::exception& e) {
1✔
290
      result.test_failure(e.what());
×
291
      return result;
×
292
   }
×
293
}
×
294

295
Test::Result test_certstor_load_allcert() {
1✔
296
   Test::Result result("Certificate Store - Load every cert of every files");
1✔
297
   // test_dir_bundled dir should contain only one file with 2 certificates
298
   // concatenated (ValidCert and root)
299
   const std::string test_dir_bundled = Test::data_dir() + "/x509/misc/bundledcertdir";
1✔
300

301
   try {
1✔
302
      result.test_note("load certs from dir: " + test_dir_bundled);
1✔
303
      // Certificate_Store_In_Memory constructor loads every cert of every files of the dir.
304
      Botan::Certificate_Store_In_Memory store(test_dir_bundled);
1✔
305

306
      // X509_Certificate constructor loads only the first certificate found in the file.
307
      Botan::X509_Certificate root_cert(Test::data_dir() + "/x509/x509test/root.pem");
1✔
308
      Botan::X509_Certificate valid_cert(Test::data_dir() + "/x509/x509test/ValidCert.pem");
1✔
309
      std::vector<uint8_t> key_id;
1✔
310
      result.confirm("Root cert found", store.find_cert(root_cert.subject_dn(), key_id) != std::nullopt);
2✔
311
      result.confirm("ValidCert found", store.find_cert(valid_cert.subject_dn(), key_id) != std::nullopt);
2✔
312
      return result;
1✔
313
   } catch(std::exception& e) {
1✔
314
      result.test_failure(e.what());
×
315
      return result;
×
316
   }
×
317
}
1✔
318

319
class Certstor_Tests final : public Test {
×
320
   public:
321
      std::vector<Test::Result> run() override {
1✔
322
         if(Botan::has_filesystem_impl() == false) {
1✔
323
            return {Test::Result::Note("Certificate Store", "Skipping due to missing filesystem access")};
×
324
         }
325

326
         const std::string test_dir = Test::data_dir() + "/x509/certstor";
1✔
327

328
         struct CertificateAndKeyFilenames {
1✔
329
               const std::string certificate;
330
               const std::string private_key;
331
         } const certsandkeys_filenames[]{
332
            {"cert1.crt", "key01.pem"},
333
            {"cert2.crt", "key01.pem"},
334
            {"cert3.crt", "key03.pem"},
335
            {"cert4.crt", "key04.pem"},
336
            {"cert5a.crt", "key05.pem"},
337
            {"cert5b.crt", "key06.pem"},
338
         };
7✔
339

340
         const std::vector<std::string> all_files = Botan::get_files_recursive(test_dir);
1✔
341

342
         if(all_files.empty()) {
1✔
343
            Test::Result result("Certificate Store");
×
344
            result.test_failure("No test files found in " + test_dir);
×
345
            return {result};
×
346
         }
×
347

348
         std::vector<CertificateAndKey> certsandkeys;
1✔
349

350
         for(const auto& certandkey_filenames : certsandkeys_filenames) {
7✔
351
            const Botan::X509_Certificate certificate(test_dir + "/" + certandkey_filenames.certificate);
12✔
352

353
            Botan::DataSource_Stream key_stream(test_dir + "/" + certandkey_filenames.private_key);
12✔
354
            std::shared_ptr<Botan::Private_Key> private_key = Botan::PKCS8::load_key(key_stream);
12✔
355

356
            if(!private_key) {
6✔
357
               Test::Result result("Certificate Store");
×
358
               result.test_failure("Failed to load key from disk at path: " + test_dir + "/" +
×
359
                                   certandkey_filenames.private_key);
360
               return {result};
×
361
            }
×
362

363
            certsandkeys.push_back({certificate, private_key});
12✔
364
         }
6✔
365

366
         std::vector<Test::Result> results;
1✔
367

368
         results.push_back(test_certstor_find_hash_subject(certsandkeys));
2✔
369
         results.push_back(test_certstor_load_allcert());
2✔
370
   #if defined(BOTAN_HAS_CERTSTOR_SQLITE3)
371
         results.push_back(test_certstor_sqlite3_insert_find_remove_test(certsandkeys));
2✔
372
         results.push_back(test_certstor_sqlite3_crl_test(certsandkeys));
2✔
373
         results.push_back(test_certstor_sqlite3_all_subjects_test(certsandkeys));
2✔
374
         results.push_back(test_certstor_sqlite3_find_all_certs_test(certsandkeys));
2✔
375
   #endif
376
         return results;
1✔
377
      }
8✔
378
};
379

380
BOTAN_REGISTER_TEST("x509", "certstor", Certstor_Tests);
381
#endif
382
}
383
}
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