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

randombit / botan / 20681212647

03 Jan 2026 06:29PM UTC coverage: 90.425% (+0.002%) from 90.423%
20681212647

push

github

web-flow
Merge pull request #5204 from KaganCanSit/remove-unused-variables

CppCheck - Remove two unused variables

101650 of 112413 relevant lines covered (90.43%)

12885104.13 hits per line

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

90.11
/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/asn1_obj.h>
12
#include <botan/ber_dec.h>
13
#include <botan/data_src.h>
14
#include <botan/pk_keys.h>
15
#include <botan/pkcs8.h>
16
#include <botan/pkix_types.h>
17

18
namespace Botan {
19

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

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

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

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

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

70
   return std::optional<X509_Certificate>();
6✔
71
}
48✔
72

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

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

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

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

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;
14✔
98
}
14✔
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_Certificate> Certificate_Store_In_SQL::find_cert_by_issuer_dn_and_serial_number(
×
111
   const X509_DN& /*issuer_dn*/, std::span<const uint8_t> /*serial_number*/) const {
112
   throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_issuer_dn_and_serial_number");
×
113
}
114

115
std::optional<X509_CRL> Certificate_Store_In_SQL::find_crl_for(const X509_Certificate& subject) const {
2✔
116
   auto all_crls = generate_crls();
2✔
117

118
   for(auto crl : all_crls) {
3✔
119
      if(!crl.get_revoked().empty() && crl.issuer_dn() == subject.issuer_dn()) {
2✔
120
         return crl;
1✔
121
      }
122
   }
2✔
123

124
   return std::optional<X509_CRL>();
1✔
125
}
2✔
126

127
std::vector<X509_DN> Certificate_Store_In_SQL::all_subjects() const {
1✔
128
   std::vector<X509_DN> ret;
1✔
129
   auto stmt = m_database->new_statement("SELECT subject_dn FROM " + m_prefix + "certificates");
3✔
130

131
   while(stmt->step()) {
7✔
132
      auto blob = stmt->get_blob(0);
6✔
133
      BER_Decoder dec(blob.first, blob.second);
6✔
134
      X509_DN dn;
6✔
135

136
      dn.decode_from(dec);
6✔
137

138
      ret.push_back(dn);
6✔
139
   }
6✔
140

141
   return ret;
1✔
142
}
1✔
143

144
bool Certificate_Store_In_SQL::insert_cert(const X509_Certificate& cert) {
29✔
145
   const std::vector<uint8_t> dn_encoding = cert.subject_dn().BER_encode();
29✔
146
   const std::vector<uint8_t> cert_encoding = cert.BER_encode();
29✔
147

148
   auto stmt = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix +
87✔
149
                                         "certificates (\
150
                                         fingerprint,          \
151
                                         subject_dn,           \
152
                                         key_id,               \
153
                                         priv_fingerprint,     \
154
                                         certificate           \
155
                                     ) VALUES ( ?1, ?2, ?3, ?4, ?5 )");
29✔
156

157
   stmt->bind(1, cert.fingerprint("SHA-256"));
29✔
158
   stmt->bind(2, dn_encoding);
29✔
159
   stmt->bind(3, cert.subject_key_id());
29✔
160
   stmt->bind(4, std::vector<uint8_t>());
29✔
161
   stmt->bind(5, cert_encoding);
29✔
162
   stmt->spin();
29✔
163

164
   return true;
58✔
165
}
29✔
166

167
bool Certificate_Store_In_SQL::remove_cert(const X509_Certificate& cert) {
6✔
168
   if(!find_cert(cert.subject_dn(), cert.subject_key_id())) {
12✔
169
      return false;
170
   }
171

172
   auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "certificates WHERE fingerprint == ?1");
18✔
173

174
   stmt->bind(1, cert.fingerprint("SHA-256"));
6✔
175
   stmt->spin();
6✔
176

177
   return true;
6✔
178
}
6✔
179

180
// Private key handling
181
std::shared_ptr<const Private_Key> Certificate_Store_In_SQL::find_key(const X509_Certificate& cert) const {
18✔
182
   auto stmt = m_database->new_statement("SELECT key FROM " + m_prefix +
54✔
183
                                         "keys "
184
                                         "JOIN " +
18✔
185
                                         m_prefix + "certificates ON " + m_prefix + "keys.fingerprint == " + m_prefix +
108✔
186
                                         "certificates.priv_fingerprint "
187
                                         "WHERE " +
36✔
188
                                         m_prefix + "certificates.fingerprint == ?1");
54✔
189
   stmt->bind(1, cert.fingerprint("SHA-256"));
18✔
190

191
   std::shared_ptr<const Private_Key> key;
18✔
192
   while(stmt->step()) {
23✔
193
      auto blob = stmt->get_blob(0);
5✔
194
      DataSource_Memory src(blob.first, blob.second);
5✔
195
      key = PKCS8::load_key(src, m_password);
10✔
196
   }
5✔
197

198
   return key;
18✔
199
}
18✔
200

201
std::vector<X509_Certificate> Certificate_Store_In_SQL::find_certs_for_key(const Private_Key& key) const {
5✔
202
   auto fprint = key.fingerprint_private("SHA-256");
5✔
203
   auto stmt =
5✔
204
      m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE priv_fingerprint == ?1");
15✔
205

206
   stmt->bind(1, fprint);
5✔
207

208
   std::vector<X509_Certificate> certs;
5✔
209
   while(stmt->step()) {
11✔
210
      auto blob = stmt->get_blob(0);
6✔
211
      certs.push_back(X509_Certificate(blob.first, blob.second));
12✔
212
   }
213

214
   return certs;
5✔
215
}
5✔
216

217
bool Certificate_Store_In_SQL::insert_key(const X509_Certificate& cert, const Private_Key& key) {
6✔
218
   insert_cert(cert);
6✔
219

220
   if(find_key(cert)) {
6✔
221
      return false;
222
   }
223

224
   auto pkcs8 = PKCS8::BER_encode(key, m_rng, m_password);
6✔
225
   auto fprint = key.fingerprint_private("SHA-256");
6✔
226

227
   auto stmt1 =
6✔
228
      m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix + "keys ( fingerprint, key ) VALUES ( ?1, ?2 )");
18✔
229

230
   stmt1->bind(1, fprint);
6✔
231
   stmt1->bind(2, pkcs8.data(), pkcs8.size());
6✔
232
   stmt1->spin();
6✔
233

234
   auto stmt2 = m_database->new_statement("UPDATE " + m_prefix +
18✔
235
                                          "certificates SET priv_fingerprint = ?1 WHERE fingerprint == ?2");
6✔
236

237
   stmt2->bind(1, fprint);
6✔
238
   stmt2->bind(2, cert.fingerprint("SHA-256"));
6✔
239
   stmt2->spin();
6✔
240

241
   return true;
6✔
242
}
12✔
243

244
void Certificate_Store_In_SQL::remove_key(const Private_Key& key) {
5✔
245
   auto fprint = key.fingerprint_private("SHA-256");
5✔
246
   auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "keys WHERE fingerprint == ?1");
15✔
247

248
   stmt->bind(1, fprint);
5✔
249
   stmt->spin();
5✔
250
}
5✔
251

252
// Revocation
253
void Certificate_Store_In_SQL::revoke_cert(const X509_Certificate& cert, CRL_Code code, const X509_Time& time) {
×
254
   // TODO(Botan4) require that time be valid
255
   insert_cert(cert);
×
256

257
   auto stmt1 = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix +
×
258
                                          "revoked ( fingerprint, reason, time ) VALUES ( ?1, ?2, ?3 )");
×
259

260
   stmt1->bind(1, cert.fingerprint("SHA-256"));
×
261
   stmt1->bind(2, static_cast<uint32_t>(code));
×
262

263
   if(time.time_is_set()) {
×
264
      stmt1->bind(3, time.BER_encode());
×
265
   } else {
266
      stmt1->bind(3, static_cast<size_t>(-1));
×
267
   }
268

269
   stmt1->spin();
×
270
}
×
271

272
// Revocation
273
void Certificate_Store_In_SQL::revoke_cert(const X509_Certificate& cert, CRL_Code code) {
3✔
274
   insert_cert(cert);
3✔
275

276
   auto stmt1 = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix +
9✔
277
                                          "revoked ( fingerprint, reason, time ) VALUES ( ?1, ?2, ?3 )");
3✔
278

279
   stmt1->bind(1, cert.fingerprint("SHA-256"));
3✔
280
   stmt1->bind(2, static_cast<uint32_t>(code));
3✔
281
   stmt1->bind(3, static_cast<size_t>(-1));
3✔
282

283
   stmt1->spin();
3✔
284
}
3✔
285

286
void Certificate_Store_In_SQL::affirm_cert(const X509_Certificate& cert) {
1✔
287
   auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "revoked WHERE fingerprint == ?1");
3✔
288

289
   stmt->bind(1, cert.fingerprint("SHA-256"));
1✔
290
   stmt->spin();
1✔
291
}
1✔
292

293
std::vector<X509_CRL> Certificate_Store_In_SQL::generate_crls() const {
4✔
294
   auto stmt = m_database->new_statement("SELECT certificate,reason,time FROM " + m_prefix +
12✔
295
                                         "revoked "
296
                                         "JOIN " +
8✔
297
                                         m_prefix + "certificates ON " + m_prefix +
16✔
298
                                         "certificates.fingerprint == " + m_prefix + "revoked.fingerprint");
16✔
299

300
   std::map<X509_DN, std::vector<CRL_Entry>> crls;
4✔
301
   while(stmt->step()) {
9✔
302
      auto blob = stmt->get_blob(0);
5✔
303
      auto cert = X509_Certificate(std::vector<uint8_t>(blob.first, blob.first + blob.second));
5✔
304
      auto code = static_cast<CRL_Code>(stmt->get_size_t(1));
5✔
305
      auto ent = CRL_Entry(cert, code);
5✔
306

307
      auto i = crls.find(cert.issuer_dn());
5✔
308
      if(i == crls.end()) {
5✔
309
         crls.insert(std::make_pair(cert.issuer_dn(), std::vector<CRL_Entry>({ent})));
15✔
310
      } else {
311
         i->second.push_back(ent);
×
312
      }
313
   }
5✔
314

315
   const X509_Time t(std::chrono::system_clock::now());
4✔
316

317
   std::vector<X509_CRL> ret;
4✔
318
   ret.reserve(crls.size());
4✔
319

320
   for(const auto& p : crls) {
9✔
321
      ret.push_back(X509_CRL(p.first, t, t, p.second));
10✔
322
   }
323

324
   return ret;
4✔
325
}
13✔
326

327
}  // namespace Botan
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