Botan 3.13.0
Crypto and TLS for C&
Botan::Certificate_Store_In_SQL Class Reference

#include <certstor_sql.h>

Inheritance diagram for Botan::Certificate_Store_In_SQL:
Botan::Certificate_Store Botan::Certificate_Store_In_SQLite

Public Member Functions

void affirm_cert (const X509_Certificate &cert)
 Reverses the revocation for "cert".
std::vector< X509_DNall_subjects () const override
bool certificate_known (const X509_Certificate &cert) const
 Certificate_Store_In_SQL (std::shared_ptr< SQL_Database > db, std::string_view passwd, RandomNumberGenerator &rng, std::string_view table_prefix="")
bool contains (const X509_Certificate &cert) const override
std::vector< X509_Certificatefind_all_certs (const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
std::optional< X509_Certificatefind_cert (const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
std::optional< X509_Certificatefind_cert_by_issuer_dn_and_serial_number (const X509_DN &issuer_dn, std::span< const uint8_t > serial_number) const override
std::optional< X509_Certificatefind_cert_by_pubkey_sha1 (const std::vector< uint8_t > &key_hash) const override
std::optional< X509_Certificatefind_cert_by_raw_subject_dn_sha256 (const std::vector< uint8_t > &subject_hash) const override
std::vector< X509_Certificatefind_certs_for_key (const Private_Key &key) const
 Returns all certificates for private key "key".
std::optional< X509_CRLfind_crl_for (const X509_Certificate &issuer) const override
std::shared_ptr< const Private_Keyfind_key (const X509_Certificate &cert) const
 Returns the private key for "cert" or an empty shared_ptr if none was found.
std::vector< X509_CRLgenerate_crls () const
bool insert_cert (const X509_Certificate &cert)
bool insert_key (const X509_Certificate &cert, const Private_Key &key)
bool remove_cert (const X509_Certificate &cert)
void remove_key (const Private_Key &key)
 Removes "key" from the store.
void revoke_cert (const X509_Certificate &cert, CRL_Code reason)
 Marks "cert" as revoked with no time specified.
void revoke_cert (const X509_Certificate &cert, CRL_Code reason, const X509_Time &time)
 Marks "cert" as revoked starting from "time".

Detailed Description

Certificate and private key store backed by an SQL database.

Definition at line 24 of file certstor_sql.h.

Constructor & Destructor Documentation

◆ Certificate_Store_In_SQL()

Botan::Certificate_Store_In_SQL::Certificate_Store_In_SQL ( std::shared_ptr< SQL_Database > db,
std::string_view passwd,
RandomNumberGenerator & rng,
std::string_view table_prefix = "" )
explicit

Create/open a certificate store.

Parameters
dbunderlying database storage
passwdpassword to encrypt private keys in the database
Random Number Generatorsused for encrypting keys
table_prefixoptional prefix for db table names

Definition at line 23 of file certstor_sql.cpp.

26 :
27 m_rng(rng),
28 m_database(std::move(db)),
29 m_db_cert_table(fmt("{}certificates", table_prefix)),
30 m_db_keys_table(fmt("{}keys", table_prefix)),
31 m_db_crls_table(fmt("{}revoked", table_prefix)),
32 m_password(passwd) {
33 using DB = SQL_Database;
34 const auto blob = DB::Column_Type::Blob;
35 const auto integer = DB::Column_Type::Integer;
36
37 BOTAN_ARG_CHECK(m_database->is_valid_table_name(m_db_cert_table), "Invalid table name");
38 BOTAN_ARG_CHECK(m_database->is_valid_table_name(m_db_keys_table), "Invalid table name");
39 BOTAN_ARG_CHECK(m_database->is_valid_table_name(m_db_crls_table), "Invalid table name");
40
41 m_database->create_table(DB::Table_Schema(m_db_cert_table,
42 {
43 DB::Column("fingerprint", blob).primary_key(),
44 DB::Column("subject_dn", blob),
45 DB::Column("key_id", blob),
46 DB::Column("priv_fingerprint", blob),
47 DB::Column("certificate", blob).not_null(),
48 })
49 .if_not_exists());
50
51 m_database->create_table(DB::Table_Schema(m_db_keys_table,
52 {
53 DB::Column("fingerprint", blob).primary_key(),
54 DB::Column("key", blob).not_null(),
55 })
56 .if_not_exists());
57
58 m_database->create_table(DB::Table_Schema(m_db_crls_table,
59 {
60 DB::Column("fingerprint", blob).primary_key(),
61 DB::Column("reason", integer).not_null(),
62 DB::Column("time", integer),
63 })
64 .if_not_exists());
65}
#define BOTAN_ARG_CHECK(expr, msg)
Definition assert.h:33
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53

References BOTAN_ARG_CHECK, and Botan::fmt().

Referenced by Botan::Certificate_Store_In_SQLite::Certificate_Store_In_SQLite().

Member Function Documentation

◆ affirm_cert()

void Botan::Certificate_Store_In_SQL::affirm_cert ( const X509_Certificate & cert)

Reverses the revocation for "cert".

Definition at line 295 of file certstor_sql.cpp.

295 {
296 auto stmt = m_database->new_statement(fmt("DELETE FROM {} WHERE fingerprint = ?1", m_db_crls_table));
297
298 stmt->bind(1, cert.fingerprint("SHA-256"));
299 stmt->spin();
300}

References Botan::X509_Certificate::fingerprint(), and Botan::fmt().

◆ all_subjects()

std::vector< X509_DN > Botan::Certificate_Store_In_SQL::all_subjects ( ) const
overridevirtual

Returns all subject DNs known to the store instance.

Implements Botan::Certificate_Store.

Definition at line 142 of file certstor_sql.cpp.

142 {
143 std::vector<X509_DN> ret;
144 auto stmt = m_database->select("subject_dn", m_db_cert_table);
145
146 while(stmt->step()) {
147 BER_Decoder dec(stmt->get_blob(0), BER_Decoder::Limits::DER());
148 X509_DN dn;
149
150 dn.decode_from(dec);
151
152 ret.push_back(dn);
153 }
154
155 return ret;
156}
static Limits DER()
Definition ber_dec.h:42

References Botan::X509_DN::decode_from(), and Botan::BER_Decoder::Limits::DER().

◆ certificate_known()

bool Botan::Certificate_Store::certificate_known ( const X509_Certificate & cert) const
inherited

Old version of contains

Definition at line 24 of file certstor.cpp.

24 {
25 return contains(cert);
26}
virtual bool contains(const X509_Certificate &cert) const
Definition certstor.cpp:28

References contains().

Referenced by find_cert_by_issuer_dn_and_serial_number().

◆ contains()

bool Botan::Certificate_Store_In_SQL::contains ( const X509_Certificate & cert) const
overridevirtual
Returns
whether this certificate is contained within the store
Parameters
certcertificate to be searched

Default implementation uses find_all_certs

Reimplemented from Botan::Certificate_Store.

Definition at line 175 of file certstor_sql.cpp.

175 {
176 auto stmt = m_database->select("1", m_db_cert_table, "fingerprint = ?1");
177 stmt->bind(1, cert.fingerprint("SHA-256"));
178 return stmt->step();
179}

References Botan::X509_Certificate::fingerprint().

◆ find_all_certs()

std::vector< X509_Certificate > Botan::Certificate_Store_In_SQL::find_all_certs ( const X509_DN & subject_dn,
const std::vector< uint8_t > & key_id ) const
overridevirtual

Find all certificates with a given Subject DN. Subject DN and even the key identifier might not be unique.

Implements Botan::Certificate_Store.

Definition at line 91 of file certstor_sql.cpp.

92 {
93 std::vector<X509_Certificate> certs;
94
95 std::shared_ptr<SQL_Database::Statement> stmt;
96
97 const std::vector<uint8_t> dn_encoding = subject_dn.BER_encode();
98
99 if(key_id.empty()) {
100 stmt = m_database->select("certificate", m_db_cert_table, "subject_dn = ?1");
101 stmt->bind(1, dn_encoding);
102 } else {
103 stmt = m_database->select("certificate", m_db_cert_table, "subject_dn = ?1 AND (key_id IS NULL OR key_id = ?2)");
104 stmt->bind(1, dn_encoding);
105 stmt->bind(2, key_id);
106 }
107
108 while(stmt->step()) {
109 certs.push_back(X509_Certificate(stmt->get_blob(0)));
110 }
111
112 return certs;
113}

References Botan::ASN1_Object::BER_encode().

◆ find_cert()

std::optional< X509_Certificate > Botan::Certificate_Store_In_SQL::find_cert ( const X509_DN & subject_dn,
const std::vector< uint8_t > & key_id ) const
overridevirtual

Returns the first certificate with matching subject DN and optional key ID.

Reimplemented from Botan::Certificate_Store.

Definition at line 68 of file certstor_sql.cpp.

69 {
70 std::shared_ptr<SQL_Database::Statement> stmt;
71
72 const std::vector<uint8_t> dn_encoding = subject_dn.BER_encode();
73
74 if(key_id.empty()) {
75 stmt = m_database->select("certificate", m_db_cert_table, "subject_dn = ?1", 1);
76 stmt->bind(1, dn_encoding);
77 } else {
78 stmt =
79 m_database->select("certificate", m_db_cert_table, "subject_dn = ?1 AND (key_id IS NULL OR key_id = ?2)", 1);
80 stmt->bind(1, dn_encoding);
81 stmt->bind(2, key_id);
82 }
83
84 while(stmt->step()) {
85 return X509_Certificate(stmt->get_blob(0));
86 }
87
88 return std::optional<X509_Certificate>();
89}

References Botan::ASN1_Object::BER_encode().

Referenced by remove_cert().

◆ find_cert_by_issuer_dn_and_serial_number()

std::optional< X509_Certificate > Botan::Certificate_Store_In_SQL::find_cert_by_issuer_dn_and_serial_number ( const X509_DN & issuer_dn,
std::span< const uint8_t > serial_number ) const
overridevirtual

Find a certificate by searching for one with a matching issuer DN and serial number. Used for CMS or PKCS#7.

Parameters
issuer_dnthe distinguished name of the issuer
serial_numberthe certificate's serial number
Returns
a matching certificate or nullopt otherwise

TODO(Botan4) change this to use X509_Serial_Number

Implements Botan::Certificate_Store.

Definition at line 125 of file certstor_sql.cpp.

126 {
127 throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_issuer_dn_and_serial_number");
128}

◆ find_cert_by_pubkey_sha1()

std::optional< X509_Certificate > Botan::Certificate_Store_In_SQL::find_cert_by_pubkey_sha1 ( const std::vector< uint8_t > & key_hash) const
overridevirtual

Find a certificate by searching for one with a matching SHA-1 hash of public key. Used for OCSP.

Parameters
key_hashSHA-1 hash of the subject's public key
Returns
a matching certificate or nullopt otherwise

Implements Botan::Certificate_Store.

Definition at line 115 of file certstor_sql.cpp.

116 {
117 throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_pubkey_sha1");
118}

◆ find_cert_by_raw_subject_dn_sha256()

std::optional< X509_Certificate > Botan::Certificate_Store_In_SQL::find_cert_by_raw_subject_dn_sha256 ( const std::vector< uint8_t > & subject_hash) const
overridevirtual

Find a certificate by searching for one with a matching SHA-256 hash of raw subject name. Used for OCSP.

Parameters
subject_hashSHA-256 hash of the subject's raw name
Returns
a matching certificate or nullopt otherwise

Implements Botan::Certificate_Store.

Definition at line 120 of file certstor_sql.cpp.

121 {
122 throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_raw_subject_dn_sha256");
123}

◆ find_certs_for_key()

std::vector< X509_Certificate > Botan::Certificate_Store_In_SQL::find_certs_for_key ( const Private_Key & key) const

Returns all certificates for private key "key".

Definition at line 215 of file certstor_sql.cpp.

215 {
216 auto fprint = key.fingerprint_private("SHA-256");
217 auto stmt = m_database->select("certificate", m_db_cert_table, "priv_fingerprint = ?1");
218
219 stmt->bind(1, fprint);
220
221 std::vector<X509_Certificate> certs;
222 while(stmt->step()) {
223 certs.push_back(X509_Certificate(stmt->get_blob(0)));
224 }
225
226 return certs;
227}

References Botan::Private_Key::fingerprint_private().

◆ find_crl_for()

std::optional< X509_CRL > Botan::Certificate_Store_In_SQL::find_crl_for ( const X509_Certificate & issuer) const
overridevirtual

Generates a CRL for all certificates issued by the given issuer.

Reimplemented from Botan::Certificate_Store.

Definition at line 130 of file certstor_sql.cpp.

130 {
131 const auto all_crls = generate_crls();
132
133 for(const auto& crl : all_crls) {
134 if(!crl.get_revoked().empty() && crl.issuer_dn() == subject.issuer_dn()) {
135 return crl;
136 }
137 }
138
139 return std::optional<X509_CRL>();
140}
std::vector< X509_CRL > generate_crls() const

References generate_crls(), and Botan::X509_Certificate::issuer_dn().

◆ find_key()

std::shared_ptr< const Private_Key > Botan::Certificate_Store_In_SQL::find_key ( const X509_Certificate & cert) const

Returns the private key for "cert" or an empty shared_ptr if none was found.

Definition at line 195 of file certstor_sql.cpp.

195 {
196 auto stmt =
197 m_database->new_statement(fmt("SELECT key FROM {} JOIN {} ON {}.fingerprint = {}.priv_fingerprint "
198 "WHERE {}.fingerprint = ?1",
199 m_db_keys_table,
200 m_db_cert_table,
201 m_db_keys_table,
202 m_db_cert_table,
203 m_db_cert_table));
204 stmt->bind(1, cert.fingerprint("SHA-256"));
205
206 std::shared_ptr<const Private_Key> key;
207 while(stmt->step()) {
208 DataSource_Memory src(stmt->get_blob(0));
209 key = PKCS8::load_key(src, m_password);
210 }
211
212 return key;
213}
std::unique_ptr< Private_Key > load_key(DataSource &source, const std::function< std::string()> &get_pass)
Definition pkcs8.cpp:319

References Botan::X509_Certificate::fingerprint(), Botan::fmt(), and Botan::PKCS8::load_key().

Referenced by insert_key().

◆ generate_crls()

std::vector< X509_CRL > Botan::Certificate_Store_In_SQL::generate_crls ( ) const

Generates Certificate Revocation Lists for all certificates marked as revoked. A CRL is returned for each unique issuer DN.

Definition at line 302 of file certstor_sql.cpp.

302 {
303 auto stmt =
304 m_database->new_statement(fmt("SELECT certificate,reason,time FROM {} JOIN {} ON {}.fingerprint = "
305 "{}.fingerprint",
306 m_db_crls_table,
307 m_db_cert_table,
308 m_db_cert_table,
309 m_db_crls_table));
310
311 std::map<X509_DN, std::vector<CRL_Entry>> crls;
312 while(stmt->step()) {
313 auto cert = X509_Certificate(stmt->get_blob(0));
314 auto code = static_cast<CRL_Code>(stmt->get_size_t(1));
315 auto ent = CRL_Entry(cert, code);
316
317 auto i = crls.find(cert.issuer_dn());
318 if(i == crls.end()) {
319 crls.insert(std::make_pair(cert.issuer_dn(), std::vector<CRL_Entry>({ent})));
320 } else {
321 i->second.push_back(ent);
322 }
323 }
324
325 const X509_Time t(std::chrono::system_clock::now());
326
327 std::vector<X509_CRL> ret;
328 ret.reserve(crls.size());
329
330 for(const auto& p : crls) {
331 ret.push_back(X509_CRL(p.first, t, t, p.second));
332 }
333
334 return ret;
335}
ASN1_Time X509_Time
Definition asn1_obj.h:27

References Botan::CRL_Entry, and Botan::fmt().

Referenced by find_crl_for().

◆ insert_cert()

bool Botan::Certificate_Store_In_SQL::insert_cert ( const X509_Certificate & cert)

Inserts "cert" into the store, returns false if the certificate is already known and true if insertion was successful.

Definition at line 158 of file certstor_sql.cpp.

158 {
159 const std::vector<uint8_t> dn_encoding = cert.subject_dn().BER_encode();
160 const std::vector<uint8_t> cert_encoding = cert.BER_encode();
161
162 auto stmt =
163 m_database->upsert(m_db_cert_table, {"fingerprint", "subject_dn", "key_id", "priv_fingerprint", "certificate"});
164
165 stmt->bind(1, cert.fingerprint("SHA-256"));
166 stmt->bind(2, dn_encoding);
167 stmt->bind(3, cert.subject_key_id());
168 stmt->bind(4, std::vector<uint8_t>());
169 stmt->bind(5, cert_encoding);
170 stmt->spin();
171
172 return true;
173}

References Botan::ASN1_Object::BER_encode(), Botan::X509_Certificate::fingerprint(), Botan::X509_Certificate::subject_dn(), and Botan::X509_Certificate::subject_key_id().

Referenced by insert_key(), revoke_cert(), and revoke_cert().

◆ insert_key()

bool Botan::Certificate_Store_In_SQL::insert_key ( const X509_Certificate & cert,
const Private_Key & key )

Inserts "key" for "cert" into the store, returns false if the key is already known and true if insertion was successful.

Definition at line 229 of file certstor_sql.cpp.

229 {
230 insert_cert(cert);
231
232 if(find_key(cert)) {
233 return false;
234 }
235
236 auto pkcs8 = PKCS8::BER_encode(key, m_rng, m_password);
237 auto fprint = key.fingerprint_private("SHA-256");
238
239 auto stmt1 = m_database->upsert(m_db_keys_table, {"fingerprint", "key"});
240
241 stmt1->bind(1, fprint);
242 stmt1->bind(2, pkcs8.data(), pkcs8.size());
243 stmt1->spin();
244
245 auto stmt2 =
246 m_database->new_statement(fmt("UPDATE {} SET priv_fingerprint = ?1 WHERE fingerprint = ?2", m_db_cert_table));
247
248 stmt2->bind(1, fprint);
249 stmt2->bind(2, cert.fingerprint("SHA-256"));
250 stmt2->spin();
251
252 return true;
253}
bool insert_cert(const X509_Certificate &cert)
std::shared_ptr< const Private_Key > find_key(const X509_Certificate &cert) const
Returns the private key for "cert" or an empty shared_ptr if none was found.
std::vector< uint8_t > BER_encode(const Private_Key &key, RandomNumberGenerator &rng, std::string_view pass, std::chrono::milliseconds msec, std::string_view pbe_algo)
Definition pkcs8.cpp:167

References Botan::PKCS8::BER_encode(), find_key(), Botan::X509_Certificate::fingerprint(), Botan::Private_Key::fingerprint_private(), Botan::fmt(), and insert_cert().

◆ remove_cert()

bool Botan::Certificate_Store_In_SQL::remove_cert ( const X509_Certificate & cert)

Removes "cert" from the store. Returns false if the certificate could not be found and true if removal was successful.

Definition at line 181 of file certstor_sql.cpp.

181 {
182 if(!find_cert(cert.subject_dn(), cert.subject_key_id())) {
183 return false;
184 }
185
186 auto stmt = m_database->new_statement(fmt("DELETE FROM {} WHERE fingerprint = ?1", m_db_cert_table));
187
188 stmt->bind(1, cert.fingerprint("SHA-256"));
189 stmt->spin();
190
191 return true;
192}
std::optional< X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override

References find_cert(), Botan::X509_Certificate::fingerprint(), Botan::fmt(), Botan::X509_Certificate::subject_dn(), and Botan::X509_Certificate::subject_key_id().

◆ remove_key()

void Botan::Certificate_Store_In_SQL::remove_key ( const Private_Key & key)

Removes "key" from the store.

Definition at line 255 of file certstor_sql.cpp.

255 {
256 auto fprint = key.fingerprint_private("SHA-256");
257 auto stmt = m_database->new_statement(fmt("DELETE FROM {} WHERE fingerprint = ?1", m_db_keys_table));
258
259 stmt->bind(1, fprint);
260 stmt->spin();
261}

References Botan::Private_Key::fingerprint_private(), and Botan::fmt().

◆ revoke_cert() [1/2]

void Botan::Certificate_Store_In_SQL::revoke_cert ( const X509_Certificate & cert,
CRL_Code reason )

Marks "cert" as revoked with no time specified.

Definition at line 283 of file certstor_sql.cpp.

283 {
284 insert_cert(cert);
285
286 auto stmt1 = m_database->upsert(m_db_crls_table, {"fingerprint", "reason", "time"});
287
288 stmt1->bind(1, cert.fingerprint("SHA-256"));
289 stmt1->bind(2, static_cast<uint32_t>(code));
290 stmt1->bind_null(3);
291
292 stmt1->spin();
293}

References Botan::X509_Certificate::fingerprint(), and insert_cert().

◆ revoke_cert() [2/2]

void Botan::Certificate_Store_In_SQL::revoke_cert ( const X509_Certificate & cert,
CRL_Code reason,
const X509_Time & time )

Marks "cert" as revoked starting from "time".

Definition at line 264 of file certstor_sql.cpp.

264 {
265 // TODO(Botan4) require that time be valid
266 insert_cert(cert);
267
268 auto stmt1 = m_database->upsert(m_db_crls_table, {"fingerprint", "reason", "time"});
269
270 stmt1->bind(1, cert.fingerprint("SHA-256"));
271 stmt1->bind(2, static_cast<uint32_t>(code));
272
273 if(time.time_is_set()) {
274 stmt1->bind(3, time.to_std_timepoint());
275 } else {
276 stmt1->bind_null(3);
277 }
278
279 stmt1->spin();
280}

References Botan::X509_Certificate::fingerprint(), insert_cert(), Botan::ASN1_Time::time_is_set(), and Botan::ASN1_Time::to_std_timepoint().


The documentation for this class was generated from the following files: