9#include <botan/certstor_sql.h>
11#include <botan/asn1_obj.h>
12#include <botan/asn1_time.h>
13#include <botan/ber_dec.h>
14#include <botan/data_src.h>
15#include <botan/pk_keys.h>
16#include <botan/pkcs8.h>
17#include <botan/pkix_types.h>
22 std::string_view passwd,
24 std::string_view table_prefix) :
25 m_rng(rng), m_database(std::move(db)), m_prefix(table_prefix), m_password(passwd) {
26 m_database->create_table(
"CREATE TABLE IF NOT EXISTS " + m_prefix +
28 fingerprint BLOB PRIMARY KEY, \
31 priv_fingerprint BLOB, \
32 certificate BLOB UNIQUE NOT NULL\
34 m_database->create_table(
"CREATE TABLE IF NOT EXISTS " + m_prefix +
36 fingerprint BLOB PRIMARY KEY, \
37 key BLOB UNIQUE NOT NULL \
39 m_database->create_table(
"CREATE TABLE IF NOT EXISTS " + m_prefix +
41 fingerprint BLOB PRIMARY KEY, \
42 reason BLOB NOT NULL, \
49 const std::vector<uint8_t>& key_id)
const {
50 std::shared_ptr<SQL_Database::Statement> stmt;
52 const std::vector<uint8_t> dn_encoding = subject_dn.
BER_encode();
55 stmt = m_database->new_statement(
"SELECT certificate FROM " + m_prefix +
56 "certificates WHERE subject_dn == ?1 LIMIT 1");
57 stmt->bind(1, dn_encoding);
59 stmt = m_database->new_statement(
"SELECT certificate FROM " + m_prefix +
61 subject_dn == ?1 AND (key_id IS NULL OR key_id == ?2) LIMIT 1");
62 stmt->bind(1, dn_encoding);
63 stmt->bind(2, key_id);
67 auto blob = stmt->get_blob(0);
71 return std::optional<X509_Certificate>();
75 const std::vector<uint8_t>& key_id)
const {
76 std::vector<X509_Certificate> certs;
78 std::shared_ptr<SQL_Database::Statement> stmt;
80 const std::vector<uint8_t> dn_encoding = subject_dn.
BER_encode();
83 stmt = m_database->new_statement(
"SELECT certificate FROM " + m_prefix +
"certificates WHERE subject_dn == ?1");
84 stmt->bind(1, dn_encoding);
86 stmt = m_database->new_statement(
"SELECT certificate FROM " + m_prefix +
88 subject_dn == ?1 AND (key_id IS NULL OR key_id == ?2)");
89 stmt->bind(1, dn_encoding);
90 stmt->bind(2, key_id);
94 auto blob = stmt->get_blob(0);
102 const std::vector<uint8_t>& )
const {
103 throw Not_Implemented(
"Certificate_Store_In_SQL::find_cert_by_pubkey_sha1");
107 const std::vector<uint8_t>& )
const {
108 throw Not_Implemented(
"Certificate_Store_In_SQL::find_cert_by_raw_subject_dn_sha256");
112 const X509_DN& , std::span<const uint8_t> )
const {
113 throw Not_Implemented(
"Certificate_Store_In_SQL::find_cert_by_issuer_dn_and_serial_number");
119 for(
const auto& crl : all_crls) {
120 if(!crl.get_revoked().empty() && crl.issuer_dn() == subject.
issuer_dn()) {
125 return std::optional<X509_CRL>();
129 std::vector<X509_DN> ret;
130 auto stmt = m_database->new_statement(
"SELECT subject_dn FROM " + m_prefix +
"certificates");
132 while(stmt->step()) {
133 auto blob = stmt->get_blob(0);
147 const std::vector<uint8_t> cert_encoding = cert.
BER_encode();
149 auto stmt = m_database->new_statement(
"INSERT OR REPLACE INTO " + m_prefix +
156 ) VALUES ( ?1, ?2, ?3, ?4, ?5 )");
159 stmt->bind(2, dn_encoding);
161 stmt->bind(4, std::vector<uint8_t>());
162 stmt->bind(5, cert_encoding);
169 auto stmt = m_database->new_statement(
"SELECT 1 FROM " + m_prefix +
"certificates WHERE fingerprint == ?1");
179 auto stmt = m_database->new_statement(
"DELETE FROM " + m_prefix +
"certificates WHERE fingerprint == ?1");
189 auto stmt = m_database->new_statement(
"SELECT key FROM " + m_prefix +
192 m_prefix +
"certificates ON " + m_prefix +
"keys.fingerprint == " + m_prefix +
193 "certificates.priv_fingerprint "
195 m_prefix +
"certificates.fingerprint == ?1");
198 std::shared_ptr<const Private_Key> key;
199 while(stmt->step()) {
200 auto blob = stmt->get_blob(0);
211 m_database->new_statement(
"SELECT certificate FROM " + m_prefix +
"certificates WHERE priv_fingerprint == ?1");
213 stmt->bind(1, fprint);
215 std::vector<X509_Certificate> certs;
216 while(stmt->step()) {
217 auto blob = stmt->get_blob(0);
235 m_database->new_statement(
"INSERT OR REPLACE INTO " + m_prefix +
"keys ( fingerprint, key ) VALUES ( ?1, ?2 )");
237 stmt1->bind(1, fprint);
238 stmt1->bind(2, pkcs8.data(), pkcs8.size());
241 auto stmt2 = m_database->new_statement(
"UPDATE " + m_prefix +
242 "certificates SET priv_fingerprint = ?1 WHERE fingerprint == ?2");
244 stmt2->bind(1, fprint);
253 auto stmt = m_database->new_statement(
"DELETE FROM " + m_prefix +
"keys WHERE fingerprint == ?1");
255 stmt->bind(1, fprint);
264 auto stmt1 = m_database->new_statement(
"INSERT OR REPLACE INTO " + m_prefix +
265 "revoked ( fingerprint, reason, time ) VALUES ( ?1, ?2, ?3 )");
268 stmt1->bind(2,
static_cast<uint32_t
>(code));
273 stmt1->bind(3,
static_cast<size_t>(-1));
283 auto stmt1 = m_database->new_statement(
"INSERT OR REPLACE INTO " + m_prefix +
284 "revoked ( fingerprint, reason, time ) VALUES ( ?1, ?2, ?3 )");
287 stmt1->bind(2,
static_cast<uint32_t
>(code));
288 stmt1->bind(3,
static_cast<size_t>(-1));
294 auto stmt = m_database->new_statement(
"DELETE FROM " + m_prefix +
"revoked WHERE fingerprint == ?1");
301 auto stmt = m_database->new_statement(
"SELECT certificate,reason,time FROM " + m_prefix +
304 m_prefix +
"certificates ON " + m_prefix +
305 "certificates.fingerprint == " + m_prefix +
"revoked.fingerprint");
307 std::map<X509_DN, std::vector<CRL_Entry>> crls;
308 while(stmt->step()) {
309 auto blob = stmt->get_blob(0);
310 auto cert =
X509_Certificate(std::vector<uint8_t>(blob.first, blob.first + blob.second));
311 auto code =
static_cast<CRL_Code>(stmt->get_size_t(1));
314 auto i = crls.find(cert.issuer_dn());
315 if(i == crls.end()) {
316 crls.insert(std::make_pair(cert.issuer_dn(), std::vector<CRL_Entry>({ent})));
318 i->second.push_back(ent);
322 const X509_Time t(std::chrono::system_clock::now());
324 std::vector<X509_CRL> ret;
325 ret.reserve(crls.size());
327 for(
const auto& p : crls) {
328 ret.push_back(
X509_CRL(p.first, t, t, p.second));
std::vector< uint8_t > BER_encode() const
bool time_is_set() const
Return if the time has been set somehow.
std::optional< X509_Certificate > find_cert_by_issuer_dn_and_serial_number(const X509_DN &issuer_dn, std::span< const uint8_t > serial_number) const override
std::vector< X509_DN > all_subjects() const override
bool insert_cert(const X509_Certificate &cert)
std::vector< X509_Certificate > find_all_certs(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
std::optional< X509_Certificate > find_cert_by_raw_subject_dn_sha256(const std::vector< uint8_t > &subject_hash) const override
bool contains(const X509_Certificate &cert) const override
void revoke_cert(const X509_Certificate &cert, CRL_Code reason, const X509_Time &time)
Marks "cert" as revoked starting from "time".
std::optional< X509_CRL > find_crl_for(const X509_Certificate &issuer) const override
Certificate_Store_In_SQL(std::shared_ptr< SQL_Database > db, std::string_view passwd, RandomNumberGenerator &rng, std::string_view table_prefix="")
std::vector< X509_Certificate > find_certs_for_key(const Private_Key &key) const
Returns all certificates for private key "key".
void affirm_cert(const X509_Certificate &cert)
Reverses the revocation for "cert".
bool remove_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::optional< X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
void remove_key(const Private_Key &key)
Removes "key" from the store.
bool insert_key(const X509_Certificate &cert, const Private_Key &key)
std::optional< X509_Certificate > find_cert_by_pubkey_sha1(const std::vector< uint8_t > &key_hash) const override
std::vector< X509_CRL > generate_crls() const
std::string fingerprint_private(std::string_view alg) const
std::string fingerprint(std::string_view hash_name="SHA-1") const
const X509_DN & subject_dn() const
const std::vector< uint8_t > & subject_key_id() const
const X509_DN & issuer_dn() const
void decode_from(BER_Decoder &from) override
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)
std::unique_ptr< Private_Key > load_key(DataSource &source, const std::function< std::string()> &get_pass)