Botan 3.6.1
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 &)
 Reverses the revokation 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="")
 
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_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 &) 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 &, CRL_Code, const X509_Time &time=X509_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
rngused for encrypting keys
table_prefixoptional prefix for db table names

Definition at line 19 of file certstor_sql.cpp.

22 :
23 m_rng(rng), m_database(std::move(db)), m_prefix(table_prefix), m_password(passwd) {
24 m_database->create_table("CREATE TABLE IF NOT EXISTS " + m_prefix +
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 +
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 +
38 "revoked (\
39 fingerprint BLOB PRIMARY KEY, \
40 reason BLOB NOT NULL, \
41 time BLOB NOT NULL \
42 )");
43}

Member Function Documentation

◆ affirm_cert()

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

Reverses the revokation for "cert".

Definition at line 266 of file certstor_sql.cpp.

266 {
267 auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "revoked WHERE fingerprint == ?1");
268
269 stmt->bind(1, cert.fingerprint("SHA-256"));
270 stmt->spin();
271}

References Botan::X509_Certificate::fingerprint().

◆ 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 122 of file certstor_sql.cpp.

122 {
123 std::vector<X509_DN> ret;
124 auto stmt = m_database->new_statement("SELECT subject_dn FROM " + m_prefix + "certificates");
125
126 while(stmt->step()) {
127 auto blob = stmt->get_blob(0);
128 BER_Decoder dec(blob.first, blob.second);
129 X509_DN dn;
130
131 dn.decode_from(dec);
132
133 ret.push_back(dn);
134 }
135
136 return ret;
137}

References Botan::X509_DN::decode_from().

◆ certificate_known()

bool Botan::Certificate_Store::certificate_known ( const X509_Certificate & cert) const
inlineinherited
Returns
whether the certificate is known
Parameters
certcertififcate to be searched

Definition at line 70 of file certstor.h.

70 {
71 return find_cert(cert.subject_dn(), cert.subject_key_id()).has_value();
72 }
virtual std::optional< X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const
Definition certstor.cpp:20

References Botan::X509_Certificate::subject_dn(), and Botan::X509_Certificate::subject_key_id().

◆ 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 72 of file certstor_sql.cpp.

73 {
74 std::vector<X509_Certificate> certs;
75
76 std::shared_ptr<SQL_Database::Statement> stmt;
77
78 const std::vector<uint8_t> dn_encoding = subject_dn.BER_encode();
79
80 if(key_id.empty()) {
81 stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE subject_dn == ?1");
82 stmt->bind(1, dn_encoding);
83 } else {
84 stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix +
85 "certificates WHERE\
86 subject_dn == ?1 AND (key_id == NULL OR key_id == ?2)");
87 stmt->bind(1, dn_encoding);
88 stmt->bind(2, key_id);
89 }
90
91 std::optional<X509_Certificate> cert;
92 while(stmt->step()) {
93 auto blob = stmt->get_blob(0);
94 certs.push_back(X509_Certificate(blob.first, blob.second));
95 }
96
97 return certs;
98}

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 46 of file certstor_sql.cpp.

47 {
48 std::shared_ptr<SQL_Database::Statement> stmt;
49
50 const std::vector<uint8_t> dn_encoding = subject_dn.BER_encode();
51
52 if(key_id.empty()) {
53 stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix +
54 "certificates WHERE subject_dn == ?1 LIMIT 1");
55 stmt->bind(1, dn_encoding);
56 } else {
57 stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix +
58 "certificates WHERE\
59 subject_dn == ?1 AND (key_id == NULL OR key_id == ?2) LIMIT 1");
60 stmt->bind(1, dn_encoding);
61 stmt->bind(2, key_id);
62 }
63
64 while(stmt->step()) {
65 auto blob = stmt->get_blob(0);
66 return X509_Certificate(blob.first, blob.second);
67 }
68
69 return std::optional<X509_Certificate>();
70}

References Botan::ASN1_Object::BER_encode().

Referenced by remove_cert().

◆ 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 100 of file certstor_sql.cpp.

101 {
102 throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_pubkey_sha1");
103}

◆ 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 105 of file certstor_sql.cpp.

106 {
107 throw Not_Implemented("Certificate_Store_In_SQL::find_cert_by_raw_subject_dn_sha256");
108}

◆ 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 196 of file certstor_sql.cpp.

196 {
197 auto fpr = key.fingerprint_private("SHA-256");
198 auto stmt =
199 m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE priv_fingerprint == ?1");
200
201 stmt->bind(1, fpr);
202
203 std::vector<X509_Certificate> certs;
204 while(stmt->step()) {
205 auto blob = stmt->get_blob(0);
206 certs.push_back(X509_Certificate(blob.first, blob.second));
207 }
208
209 return certs;
210}

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 110 of file certstor_sql.cpp.

110 {
111 auto all_crls = generate_crls();
112
113 for(auto crl : all_crls) {
114 if(!crl.get_revoked().empty() && crl.issuer_dn() == subject.issuer_dn()) {
115 return crl;
116 }
117 }
118
119 return std::optional<X509_CRL>();
120}
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 176 of file certstor_sql.cpp.

176 {
177 auto stmt = m_database->new_statement("SELECT key FROM " + m_prefix +
178 "keys "
179 "JOIN " +
180 m_prefix + "certificates ON " + m_prefix + "keys.fingerprint == " + m_prefix +
181 "certificates.priv_fingerprint "
182 "WHERE " +
183 m_prefix + "certificates.fingerprint == ?1");
184 stmt->bind(1, cert.fingerprint("SHA-256"));
185
186 std::shared_ptr<const Private_Key> key;
187 while(stmt->step()) {
188 auto blob = stmt->get_blob(0);
189 DataSource_Memory src(blob.first, blob.second);
190 key = PKCS8::load_key(src, m_password);
191 }
192
193 return key;
194}
std::unique_ptr< Private_Key > load_key(DataSource &source, const std::function< std::string()> &get_pass)
Definition pkcs8.cpp:316

References Botan::X509_Certificate::fingerprint(), 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 273 of file certstor_sql.cpp.

273 {
274 auto stmt = m_database->new_statement("SELECT certificate,reason,time FROM " + m_prefix +
275 "revoked "
276 "JOIN " +
277 m_prefix + "certificates ON " + m_prefix +
278 "certificates.fingerprint == " + m_prefix + "revoked.fingerprint");
279
280 std::map<X509_DN, std::vector<CRL_Entry>> crls;
281 while(stmt->step()) {
282 auto blob = stmt->get_blob(0);
283 auto cert = X509_Certificate(std::vector<uint8_t>(blob.first, blob.first + blob.second));
284 auto code = static_cast<CRL_Code>(stmt->get_size_t(1));
285 auto ent = CRL_Entry(cert, code);
286
287 auto i = crls.find(cert.issuer_dn());
288 if(i == crls.end()) {
289 crls.insert(std::make_pair(cert.issuer_dn(), std::vector<CRL_Entry>({ent})));
290 } else {
291 i->second.push_back(ent);
292 }
293 }
294
295 X509_Time t(std::chrono::system_clock::now());
296
297 std::vector<X509_CRL> ret;
298 ret.reserve(crls.size());
299
300 for(const auto& p : crls) {
301 ret.push_back(X509_CRL(p.first, t, t, p.second));
302 }
303
304 return ret;
305}
ASN1_Time X509_Time
Definition asn1_obj.h:409

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 139 of file certstor_sql.cpp.

139 {
140 const std::vector<uint8_t> dn_encoding = cert.subject_dn().BER_encode();
141 const std::vector<uint8_t> cert_encoding = cert.BER_encode();
142
143 auto stmt = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix +
144 "certificates (\
145 fingerprint, \
146 subject_dn, \
147 key_id, \
148 priv_fingerprint, \
149 certificate \
150 ) VALUES ( ?1, ?2, ?3, ?4, ?5 )");
151
152 stmt->bind(1, cert.fingerprint("SHA-256"));
153 stmt->bind(2, dn_encoding);
154 stmt->bind(3, cert.subject_key_id());
155 stmt->bind(4, std::vector<uint8_t>());
156 stmt->bind(5, cert_encoding);
157 stmt->spin();
158
159 return true;
160}

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(), 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 212 of file certstor_sql.cpp.

212 {
213 insert_cert(cert);
214
215 if(find_key(cert)) {
216 return false;
217 }
218
219 auto pkcs8 = PKCS8::BER_encode(key, m_rng, m_password);
220 auto fpr = key.fingerprint_private("SHA-256");
221
222 auto stmt1 =
223 m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix + "keys ( fingerprint, key ) VALUES ( ?1, ?2 )");
224
225 stmt1->bind(1, fpr);
226 stmt1->bind(2, pkcs8.data(), pkcs8.size());
227 stmt1->spin();
228
229 auto stmt2 = m_database->new_statement("UPDATE " + m_prefix +
230 "certificates SET priv_fingerprint = ?1 WHERE fingerprint == ?2");
231
232 stmt2->bind(1, fpr);
233 stmt2->bind(2, cert.fingerprint("SHA-256"));
234 stmt2->spin();
235
236 return true;
237}
std::shared_ptr< const Private_Key > find_key(const X509_Certificate &) const
Returns the private key for "cert" or an empty shared_ptr if none was found.
bool insert_cert(const X509_Certificate &cert)
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:163

References Botan::PKCS8::BER_encode(), find_key(), Botan::X509_Certificate::fingerprint(), Botan::Private_Key::fingerprint_private(), 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 162 of file certstor_sql.cpp.

162 {
163 if(!find_cert(cert.subject_dn(), cert.subject_key_id())) {
164 return false;
165 }
166
167 auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "certificates WHERE fingerprint == ?1");
168
169 stmt->bind(1, cert.fingerprint("SHA-256"));
170 stmt->spin();
171
172 return true;
173}
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::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 239 of file certstor_sql.cpp.

239 {
240 auto fpr = key.fingerprint_private("SHA-256");
241 auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "keys WHERE fingerprint == ?1");
242
243 stmt->bind(1, fpr);
244 stmt->spin();
245}

References Botan::Private_Key::fingerprint_private().

◆ revoke_cert()

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

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

Definition at line 248 of file certstor_sql.cpp.

248 {
249 insert_cert(cert);
250
251 auto stmt1 = m_database->new_statement("INSERT OR REPLACE INTO " + m_prefix +
252 "revoked ( fingerprint, reason, time ) VALUES ( ?1, ?2, ?3 )");
253
254 stmt1->bind(1, cert.fingerprint("SHA-256"));
255 stmt1->bind(2, static_cast<uint32_t>(code));
256
257 if(time.time_is_set()) {
258 stmt1->bind(3, time.BER_encode());
259 } else {
260 stmt1->bind(3, static_cast<size_t>(-1));
261 }
262
263 stmt1->spin();
264}

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


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