9#include <botan/certstor_sql.h>
11#include <botan/asn1_obj.h>
12#include <botan/asn1_time.h>
13#include <botan/assert.h>
14#include <botan/ber_dec.h>
15#include <botan/data_src.h>
16#include <botan/pk_keys.h>
17#include <botan/pkcs8.h>
18#include <botan/pkix_types.h>
19#include <botan/internal/fmt.h>
24 std::string_view passwd,
26 std::string_view table_prefix) :
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)),
34 const auto blob = DB::Column_Type::Blob;
35 const auto integer = DB::Column_Type::Integer;
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");
41 m_database->create_table(DB::Table_Schema(m_db_cert_table,
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(),
51 m_database->create_table(DB::Table_Schema(m_db_keys_table,
53 DB::Column(
"fingerprint", blob).primary_key(),
54 DB::Column(
"key", blob).not_null(),
58 m_database->create_table(DB::Table_Schema(m_db_crls_table,
60 DB::Column(
"fingerprint", blob).primary_key(),
61 DB::Column(
"reason", integer).not_null(),
62 DB::Column(
"time", integer),
69 const std::vector<uint8_t>& key_id)
const {
70 std::shared_ptr<SQL_Database::Statement> stmt;
72 const std::vector<uint8_t> dn_encoding = subject_dn.
BER_encode();
75 stmt = m_database->select(
"certificate", m_db_cert_table,
"subject_dn = ?1", 1);
76 stmt->bind(1, dn_encoding);
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);
88 return std::optional<X509_Certificate>();
92 const std::vector<uint8_t>& key_id)
const {
93 std::vector<X509_Certificate> certs;
95 std::shared_ptr<SQL_Database::Statement> stmt;
97 const std::vector<uint8_t> dn_encoding = subject_dn.
BER_encode();
100 stmt = m_database->select(
"certificate", m_db_cert_table,
"subject_dn = ?1");
101 stmt->bind(1, dn_encoding);
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);
108 while(stmt->step()) {
116 const std::vector<uint8_t>& )
const {
117 throw Not_Implemented(
"Certificate_Store_In_SQL::find_cert_by_pubkey_sha1");
121 const std::vector<uint8_t>& )
const {
122 throw Not_Implemented(
"Certificate_Store_In_SQL::find_cert_by_raw_subject_dn_sha256");
126 const X509_DN& , std::span<const uint8_t> )
const {
127 throw Not_Implemented(
"Certificate_Store_In_SQL::find_cert_by_issuer_dn_and_serial_number");
133 for(
const auto& crl : all_crls) {
134 if(!crl.get_revoked().empty() && crl.issuer_dn() == subject.
issuer_dn()) {
139 return std::optional<X509_CRL>();
143 std::vector<X509_DN> ret;
144 auto stmt = m_database->select(
"subject_dn", m_db_cert_table);
146 while(stmt->step()) {
160 const std::vector<uint8_t> cert_encoding = cert.
BER_encode();
163 m_database->upsert(m_db_cert_table, {
"fingerprint",
"subject_dn",
"key_id",
"priv_fingerprint",
"certificate"});
166 stmt->bind(2, dn_encoding);
168 stmt->bind(4, std::vector<uint8_t>());
169 stmt->bind(5, cert_encoding);
176 auto stmt = m_database->select(
"1", m_db_cert_table,
"fingerprint = ?1");
186 auto stmt = m_database->new_statement(
fmt(
"DELETE FROM {} WHERE fingerprint = ?1", m_db_cert_table));
197 m_database->new_statement(
fmt(
"SELECT key FROM {} JOIN {} ON {}.fingerprint = {}.priv_fingerprint "
198 "WHERE {}.fingerprint = ?1",
206 std::shared_ptr<const Private_Key> key;
207 while(stmt->step()) {
217 auto stmt = m_database->select(
"certificate", m_db_cert_table,
"priv_fingerprint = ?1");
219 stmt->bind(1, fprint);
221 std::vector<X509_Certificate> certs;
222 while(stmt->step()) {
239 auto stmt1 = m_database->upsert(m_db_keys_table, {
"fingerprint",
"key"});
241 stmt1->bind(1, fprint);
242 stmt1->bind(2, pkcs8.data(), pkcs8.size());
246 m_database->new_statement(
fmt(
"UPDATE {} SET priv_fingerprint = ?1 WHERE fingerprint = ?2", m_db_cert_table));
248 stmt2->bind(1, fprint);
257 auto stmt = m_database->new_statement(
fmt(
"DELETE FROM {} WHERE fingerprint = ?1", m_db_keys_table));
259 stmt->bind(1, fprint);
268 auto stmt1 = m_database->upsert(m_db_crls_table, {
"fingerprint",
"reason",
"time"});
271 stmt1->bind(2,
static_cast<uint32_t
>(code));
286 auto stmt1 = m_database->upsert(m_db_crls_table, {
"fingerprint",
"reason",
"time"});
289 stmt1->bind(2,
static_cast<uint32_t
>(code));
296 auto stmt = m_database->new_statement(
fmt(
"DELETE FROM {} WHERE fingerprint = ?1", m_db_crls_table));
304 m_database->new_statement(
fmt(
"SELECT certificate,reason,time FROM {} JOIN {} ON {}.fingerprint = "
311 std::map<X509_DN, std::vector<CRL_Entry>> crls;
312 while(stmt->step()) {
314 auto code =
static_cast<CRL_Code>(stmt->get_size_t(1));
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})));
321 i->second.push_back(ent);
325 const X509_Time t(std::chrono::system_clock::now());
327 std::vector<X509_CRL> ret;
328 ret.reserve(crls.size());
330 for(
const auto& p : crls) {
331 ret.push_back(
X509_CRL(p.first, t, t, p.second));
#define BOTAN_ARG_CHECK(expr, msg)
std::vector< uint8_t > BER_encode() const
std::chrono::system_clock::time_point to_std_timepoint() const
Returns a STL timepoint object.
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)
std::string fmt(std::string_view format, const T &... args)