• 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

96.51
/src/lib/x509/certstor_sql/certstor_sql.cpp
1
/*
2
* Certificate Store in SQL
3
* (C) 2016 Kai Michaelis, Rohde & Schwarz Cybersecurity
4
* (C) 2018 Jack Lloyd
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#include <botan/certstor_sql.h>
10

11
#include <botan/ber_dec.h>
12
#include <botan/data_src.h>
13
#include <botan/pk_keys.h>
14
#include <botan/pkcs8.h>
15
#include <botan/pkix_types.h>
16

17
namespace Botan {
18

19
Certificate_Store_In_SQL::Certificate_Store_In_SQL(std::shared_ptr<SQL_Database> db,
4✔
20
                                                   std::string_view passwd,
21
                                                   RandomNumberGenerator& rng,
22
                                                   std::string_view table_prefix) :
4✔
23
      m_rng(rng), m_database(std::move(db)), m_prefix(table_prefix), m_password(passwd) {
12✔
24
   m_database->create_table("CREATE TABLE IF NOT EXISTS " + m_prefix +
8✔
25
                            "certificates (                \
26
                                 fingerprint       BLOB PRIMARY KEY,   \
27
                                 subject_dn        BLOB,               \
28
                                 key_id            BLOB,               \
29
                                 priv_fingerprint  BLOB,               \
30
                                 certificate       BLOB UNIQUE NOT NULL\
31
                             )");
32
   m_database->create_table("CREATE TABLE IF NOT EXISTS " + m_prefix +
8✔
33
                            "keys (\
34
                                 fingerprint BLOB PRIMARY KEY,                \
35
                                 key         BLOB UNIQUE NOT NULL             \
36
                             )");
37
   m_database->create_table("CREATE TABLE IF NOT EXISTS " + m_prefix +
8✔
38
                            "revoked (\
39
                                 fingerprint BLOB PRIMARY KEY,                   \
40
                                 reason      BLOB NOT NULL,                      \
41
                                 time        BLOB NOT NULL                       \
42
                            )");
43
}
4✔
44

45
// Certificate handling
46
std::optional<X509_Certificate> Certificate_Store_In_SQL::find_cert(const X509_DN& subject_dn,
24✔
47
                                                                    const std::vector<uint8_t>& key_id) const {
48
   std::shared_ptr<SQL_Database::Statement> stmt;
24✔
49

50
   const std::vector<uint8_t> dn_encoding = subject_dn.BER_encode();
24✔
51

52
   if(key_id.empty()) {
24✔
53
      stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix +
12✔
54
                                       "certificates WHERE subject_dn == ?1 LIMIT 1");
6✔
55
      stmt->bind(1, dn_encoding);
6✔
56
   } else {
57
      stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix +
36✔
58
                                       "certificates WHERE\
59
                                        subject_dn == ?1 AND (key_id == NULL OR key_id == ?2) LIMIT 1");
18✔
60
      stmt->bind(1, dn_encoding);
18✔
61
      stmt->bind(2, key_id);
18✔
62
   }
63

64
   while(stmt->step()) {
24✔
65
      auto blob = stmt->get_blob(0);
18✔
66
      return X509_Certificate(blob.first, blob.second);
36✔
67
   }
68

69
   return std::optional<X509_Certificate>();
24✔
70
}
48✔
71

72
std::vector<X509_Certificate> Certificate_Store_In_SQL::find_all_certs(const X509_DN& subject_dn,
7✔
73
                                                                       const std::vector<uint8_t>& key_id) const {
74
   std::vector<X509_Certificate> certs;
7✔
75

76
   std::shared_ptr<SQL_Database::Statement> stmt;
7✔
77

78
   const std::vector<uint8_t> dn_encoding = subject_dn.BER_encode();
7✔
79

80
   if(key_id.empty()) {
7✔
81
      stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE subject_dn == ?1");
2✔
82
      stmt->bind(1, dn_encoding);
1✔
83
   } else {
84
      stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix +
12✔
85
                                       "certificates WHERE\
86
                                        subject_dn == ?1 AND (key_id == NULL OR key_id == ?2)");
6✔
87
      stmt->bind(1, dn_encoding);
6✔
88
      stmt->bind(2, key_id);
6✔
89
   }
90

91
   std::optional<X509_Certificate> cert;
7✔
92
   while(stmt->step()) {
15✔
93
      auto blob = stmt->get_blob(0);
8✔
94
      certs.push_back(X509_Certificate(blob.first, blob.second));
16✔
95
   }
96

97
   return certs;
7✔
98
}
21✔
99

100
std::optional<X509_Certificate> Certificate_Store_In_SQL::find_cert_by_pubkey_sha1(
×
101
   const std::vector<uint8_t>& /*key_hash*/) const {
102
   throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_pubkey_sha1");
×
103
}
104

105
std::optional<X509_Certificate> Certificate_Store_In_SQL::find_cert_by_raw_subject_dn_sha256(
×
106
   const std::vector<uint8_t>& /*subject_hash*/) const {
107
   throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_raw_subject_dn_sha256");
×
108
}
109

110
std::optional<X509_CRL> Certificate_Store_In_SQL::find_crl_for(const X509_Certificate& subject) const {
2✔
111
   auto all_crls = generate_crls();
2✔
112

113
   for(auto crl : all_crls) {
3✔
114
      if(!crl.get_revoked().empty() && crl.issuer_dn() == subject.issuer_dn())
2✔
115
         return crl;
1✔
116
   }
2✔
117

118
   return std::optional<X509_CRL>();
1✔
119
}
2✔
120

121
std::vector<X509_DN> Certificate_Store_In_SQL::all_subjects() const {
1✔
122
   std::vector<X509_DN> ret;
1✔
123
   auto stmt = m_database->new_statement("SELECT subject_dn FROM " + m_prefix + "certificates");
2✔
124

125
   while(stmt->step()) {
7✔
126
      auto blob = stmt->get_blob(0);
6✔
127
      BER_Decoder dec(blob.first, blob.second);
6✔
128
      X509_DN dn;
6✔
129

130
      dn.decode_from(dec);
6✔
131

132
      ret.push_back(dn);
6✔
133
   }
6✔
134

135
   return ret;
1✔
136
}
1✔
137

138
bool Certificate_Store_In_SQL::insert_cert(const X509_Certificate& cert) {
29✔
139
   const std::vector<uint8_t> dn_encoding = cert.subject_dn().BER_encode();
29✔
140
   const std::vector<uint8_t> cert_encoding = cert.BER_encode();
29✔
141

142
   auto stmt = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix +
58✔
143
                                         "certificates (\
144
                                         fingerprint,          \
145
                                         subject_dn,           \
146
                                         key_id,               \
147
                                         priv_fingerprint,     \
148
                                         certificate           \
149
                                     ) VALUES ( ?1, ?2, ?3, ?4, ?5 )");
29✔
150

151
   stmt->bind(1, cert.fingerprint("SHA-256"));
29✔
152
   stmt->bind(2, dn_encoding);
29✔
153
   stmt->bind(3, cert.subject_key_id());
29✔
154
   stmt->bind(4, std::vector<uint8_t>());
29✔
155
   stmt->bind(5, cert_encoding);
29✔
156
   stmt->spin();
29✔
157

158
   return true;
29✔
159
}
87✔
160

161
bool Certificate_Store_In_SQL::remove_cert(const X509_Certificate& cert) {
6✔
162
   if(!find_cert(cert.subject_dn(), cert.subject_key_id()))
12✔
163
      return false;
164

165
   auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "certificates WHERE fingerprint == ?1");
12✔
166

167
   stmt->bind(1, cert.fingerprint("SHA-256"));
6✔
168
   stmt->spin();
6✔
169

170
   return true;
6✔
171
}
6✔
172

173
// Private key handling
174
std::shared_ptr<const Private_Key> Certificate_Store_In_SQL::find_key(const X509_Certificate& cert) const {
18✔
175
   auto stmt = m_database->new_statement("SELECT key FROM " + m_prefix +
36✔
176
                                         "keys "
177
                                         "JOIN " +
36✔
178
                                         m_prefix + "certificates ON " + m_prefix + "keys.fingerprint == " + m_prefix +
36✔
179
                                         "certificates.priv_fingerprint "
180
                                         "WHERE " +
36✔
181
                                         m_prefix + "certificates.fingerprint == ?1");
54✔
182
   stmt->bind(1, cert.fingerprint("SHA-256"));
18✔
183

184
   std::shared_ptr<const Private_Key> key;
18✔
185
   while(stmt->step()) {
23✔
186
      auto blob = stmt->get_blob(0);
5✔
187
      DataSource_Memory src(blob.first, blob.second);
5✔
188
      key = PKCS8::load_key(src, m_password);
10✔
189
   }
5✔
190

191
   return key;
18✔
192
}
18✔
193

194
std::vector<X509_Certificate> Certificate_Store_In_SQL::find_certs_for_key(const Private_Key& key) const {
5✔
195
   auto fpr = key.fingerprint_private("SHA-256");
5✔
196
   auto stmt =
5✔
197
      m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE priv_fingerprint == ?1");
10✔
198

199
   stmt->bind(1, fpr);
5✔
200

201
   std::vector<X509_Certificate> certs;
5✔
202
   while(stmt->step()) {
11✔
203
      auto blob = stmt->get_blob(0);
6✔
204
      certs.push_back(X509_Certificate(blob.first, blob.second));
12✔
205
   }
206

207
   return certs;
5✔
208
}
10✔
209

210
bool Certificate_Store_In_SQL::insert_key(const X509_Certificate& cert, const Private_Key& key) {
6✔
211
   insert_cert(cert);
6✔
212

213
   if(find_key(cert))
6✔
214
      return false;
215

216
   auto pkcs8 = PKCS8::BER_encode(key, m_rng, m_password);
6✔
217
   auto fpr = key.fingerprint_private("SHA-256");
6✔
218

219
   auto stmt1 =
6✔
220
      m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix + "keys ( fingerprint, key ) VALUES ( ?1, ?2 )");
12✔
221

222
   stmt1->bind(1, fpr);
6✔
223
   stmt1->bind(2, pkcs8.data(), pkcs8.size());
6✔
224
   stmt1->spin();
6✔
225

226
   auto stmt2 = m_database->new_statement("UPDATE " + m_prefix +
12✔
227
                                          "certificates SET priv_fingerprint = ?1 WHERE fingerprint == ?2");
6✔
228

229
   stmt2->bind(1, fpr);
6✔
230
   stmt2->bind(2, cert.fingerprint("SHA-256"));
6✔
231
   stmt2->spin();
6✔
232

233
   return true;
6✔
234
}
24✔
235

236
void Certificate_Store_In_SQL::remove_key(const Private_Key& key) {
5✔
237
   auto fpr = key.fingerprint_private("SHA-256");
5✔
238
   auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "keys WHERE fingerprint == ?1");
10✔
239

240
   stmt->bind(1, fpr);
5✔
241
   stmt->spin();
5✔
242
}
10✔
243

244
// Revocation
245
void Certificate_Store_In_SQL::revoke_cert(const X509_Certificate& cert, CRL_Code code, const X509_Time& time) {
3✔
246
   insert_cert(cert);
3✔
247

248
   auto stmt1 = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix +
6✔
249
                                          "revoked ( fingerprint, reason, time ) VALUES ( ?1, ?2, ?3 )");
3✔
250

251
   stmt1->bind(1, cert.fingerprint("SHA-256"));
3✔
252
   stmt1->bind(2, static_cast<uint32_t>(code));
3✔
253

254
   if(time.time_is_set()) {
3✔
255
      stmt1->bind(3, time.BER_encode());
×
256
   } else {
257
      stmt1->bind(3, static_cast<size_t>(-1));
3✔
258
   }
259

260
   stmt1->spin();
3✔
261
}
3✔
262

263
void Certificate_Store_In_SQL::affirm_cert(const X509_Certificate& cert) {
1✔
264
   auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "revoked WHERE fingerprint == ?1");
2✔
265

266
   stmt->bind(1, cert.fingerprint("SHA-256"));
1✔
267
   stmt->spin();
1✔
268
}
1✔
269

270
std::vector<X509_CRL> Certificate_Store_In_SQL::generate_crls() const {
4✔
271
   auto stmt = m_database->new_statement("SELECT certificate,reason,time FROM " + m_prefix +
8✔
272
                                         "revoked "
273
                                         "JOIN " +
8✔
274
                                         m_prefix + "certificates ON " + m_prefix +
8✔
275
                                         "certificates.fingerprint == " + m_prefix + "revoked.fingerprint");
12✔
276

277
   std::map<X509_DN, std::vector<CRL_Entry>> crls;
4✔
278
   while(stmt->step()) {
9✔
279
      auto blob = stmt->get_blob(0);
5✔
280
      auto cert = X509_Certificate(std::vector<uint8_t>(blob.first, blob.first + blob.second));
5✔
281
      auto code = static_cast<CRL_Code>(stmt->get_size_t(1));
5✔
282
      auto ent = CRL_Entry(cert, code);
5✔
283

284
      auto i = crls.find(cert.issuer_dn());
5✔
285
      if(i == crls.end()) {
5✔
286
         crls.insert(std::make_pair(cert.issuer_dn(), std::vector<CRL_Entry>({ent})));
15✔
287
      } else {
288
         i->second.push_back(ent);
×
289
      }
290
   }
5✔
291

292
   X509_Time t(std::chrono::system_clock::now());
4✔
293

294
   std::vector<X509_CRL> ret;
4✔
295
   ret.reserve(crls.size());
4✔
296

297
   for(const auto& p : crls) {
9✔
298
      ret.push_back(X509_CRL(p.first, t, t, p.second));
10✔
299
   }
300

301
   return ret;
4✔
302
}
12✔
303

304
}
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