Botan  2.1.0
Crypto and TLS for C++11
Public Member Functions | List of all members
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". More...
 
virtual std::vector< X509_DNall_subjects () const override
 
bool certificate_known (const X509_Certificate &cert) const
 
 Certificate_Store_In_SQL (const std::shared_ptr< SQL_Database > db, const std::string &passwd, RandomNumberGenerator &rng, const std::string &table_prefix="")
 
virtual std::shared_ptr< const X509_Certificatefind_cert (const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
 
std::shared_ptr< const X509_Certificatefind_cert_by_pubkey_sha1 (const std::vector< uint8_t > &key_hash) const override
 
std::shared_ptr< const X509_Certificatefind_cert_by_raw_subject_dn_sha256 (const std::vector< uint8_t > &subject_hash) const override
 
std::vector< std::shared_ptr< const X509_Certificate > > find_certs_for_key (const Private_Key &key) const
 Returns all certificates for private key "key". More...
 
virtual std::shared_ptr< const 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. More...
 
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. More...
 
void revoke_cert (const X509_Certificate &, CRL_Code, const X509_Time &time=X509_Time())
 Marks "cert" as revoked starting from "time". More...
 

Detailed Description

Certificate and private key store backed by an SQL database.

Definition at line 23 of file certstor_sql.h.

Constructor & Destructor Documentation

Botan::Certificate_Store_In_SQL::Certificate_Store_In_SQL ( const std::shared_ptr< SQL_Database db,
const std::string &  passwd,
RandomNumberGenerator rng,
const std::string &  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),
24  m_database(db),
25  m_prefix(table_prefix),
26  m_password(passwd)
27  {
28  m_database->create_table("CREATE TABLE IF NOT EXISTS " +
29  m_prefix + "certificates ( \
30  fingerprint BLOB PRIMARY KEY, \
31  subject_dn BLOB, \
32  key_id BLOB, \
33  priv_fingerprint BLOB, \
34  certificate BLOB UNIQUE NOT NULL\
35  )");
36  m_database->create_table("CREATE TABLE IF NOT EXISTS " + m_prefix + "keys (\
37  fingerprint BLOB PRIMARY KEY, \
38  key BLOB UNIQUE NOT NULL \
39  )");
40  m_database->create_table("CREATE TABLE IF NOT EXISTS " + m_prefix + "revoked (\
41  fingerprint BLOB PRIMARY KEY, \
42  reason BLOB NOT NULL, \
43  time BLOB NOT NULL \
44  )");
45  }

Member Function Documentation

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

Reverses the revokation for "cert".

Definition at line 267 of file certstor_sql.cpp.

References Botan::X509_Certificate::fingerprint().

268  {
269  auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "revoked WHERE fingerprint == ?1");
270 
271  stmt->bind(1,cert.fingerprint("SHA-256"));
272  stmt->spin();
273  }
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 107 of file certstor_sql.cpp.

References Botan::X509_DN::decode_from().

108  {
109  std::vector<X509_DN> ret;
110  auto stmt = m_database->new_statement("SELECT subject_dn FROM " + m_prefix + "certificates");
111 
112  while(stmt->step())
113  {
114  auto blob = stmt->get_blob(0);
115  BER_Decoder dec(blob.first,blob.second);
116  X509_DN dn;
117 
118  dn.decode_from(dec);
119 
120  ret.push_back(dn);
121  }
122 
123  return ret;
124  }
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 62 of file certstor.h.

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

63  {
64  return find_cert(cert.subject_dn(), cert.subject_key_id()) != nullptr;
65  }
virtual std::shared_ptr< const X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const =0
std::shared_ptr< const 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.

Implements Botan::Certificate_Store.

Definition at line 49 of file certstor_sql.cpp.

References Botan::X509_DN::encode_into(), and Botan::DER_Encoder::get_contents_unlocked().

Referenced by insert_cert(), and remove_cert().

50  {
51  DER_Encoder enc;
52  std::shared_ptr<SQL_Database::Statement> stmt;
53 
54  subject_dn.encode_into(enc);
55 
56  if(key_id.empty())
57  {
58  stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE subject_dn == ?1");
59  stmt->bind(1,enc.get_contents_unlocked());
60  }
61  else
62  {
63  stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE\
64  subject_dn == ?1 AND (key_id == NULL OR key_id == ?2)");
65  stmt->bind(1,enc.get_contents_unlocked());
66  stmt->bind(2,key_id);
67  }
68 
69  std::shared_ptr<const X509_Certificate> cert;
70  while(stmt->step())
71  {
72  auto blob = stmt->get_blob(0);
73  cert = std::make_shared<X509_Certificate>(
74  std::vector<uint8_t>(blob.first,blob.first + blob.second));
75 
76  }
77 
78  return cert;
79  }
std::shared_ptr< const 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 nullptr otherwise

Implements Botan::Certificate_Store.

Definition at line 82 of file certstor_sql.cpp.

83  {
84  throw Not_Implemented("TODO!");
85  }
std::shared_ptr< const 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 nullptr otherwise

Implements Botan::Certificate_Store.

Definition at line 88 of file certstor_sql.cpp.

89  {
90  throw Not_Implemented("TODO!");
91  }
std::vector< std::shared_ptr< const 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 189 of file certstor_sql.cpp.

References Botan::Private_Key::fingerprint().

190  {
191  auto fpr = key.fingerprint("SHA-256");
192  auto stmt = m_database->new_statement("SELECT certificate FROM " + m_prefix + "certificates WHERE priv_fingerprint == ?1");
193 
194  stmt->bind(1,fpr);
195 
196  std::vector<std::shared_ptr<const X509_Certificate>> certs;
197  while(stmt->step())
198  {
199  auto blob = stmt->get_blob(0);
200  certs.push_back(std::make_shared<X509_Certificate>(
201  std::vector<uint8_t>(blob.first,blob.first + blob.second)));
202  }
203 
204  return certs;
205  }
std::shared_ptr< const 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 94 of file certstor_sql.cpp.

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

95  {
96  auto all_crls = generate_crls();
97 
98  for(auto crl: all_crls)
99  {
100  if(!crl.get_revoked().empty() && crl.issuer_dn() == subject.issuer_dn())
101  return std::shared_ptr<X509_CRL>(new X509_CRL(crl));
102  }
103 
104  return std::shared_ptr<X509_CRL>();
105  }
std::vector< X509_CRL > generate_crls() const
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 169 of file certstor_sql.cpp.

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

Referenced by insert_key().

170  {
171  auto stmt = m_database->new_statement("SELECT key FROM " + m_prefix + "keys "
172  "JOIN " + m_prefix + "certificates ON " +
173  m_prefix + "keys.fingerprint == " + m_prefix + "certificates.priv_fingerprint "
174  "WHERE " + m_prefix + "certificates.fingerprint == ?1");
175  stmt->bind(1,cert.fingerprint("SHA-256"));
176 
177  std::shared_ptr<const Private_Key> key;
178  while(stmt->step())
179  {
180  auto blob = stmt->get_blob(0);
181  DataSource_Memory src(blob.first,blob.second);
182  key.reset(PKCS8::load_key(src, m_rng, m_password));
183  }
184 
185  return key;
186  }
Private_Key * load_key(DataSource &source, RandomNumberGenerator &rng, std::function< std::string()> get_pass)
Definition: pkcs8.cpp:313
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 275 of file certstor_sql.cpp.

Referenced by find_crl_for().

276  {
277  auto stmt = m_database->new_statement(
278  "SELECT certificate,reason,time FROM " + m_prefix + "revoked "
279  "JOIN " + m_prefix + "certificates ON " +
280  m_prefix + "certificates.fingerprint == " + m_prefix + "revoked.fingerprint");
281 
282  std::map<X509_DN,std::vector<CRL_Entry>> crls;
283  while(stmt->step())
284  {
285  auto blob = stmt->get_blob(0);
286  auto cert = X509_Certificate(
287  std::vector<uint8_t>(blob.first,blob.first + blob.second));
288  auto code = static_cast<CRL_Code>(stmt->get_size_t(1));
289  auto ent = CRL_Entry(cert,code);
290 
291  auto i = crls.find(cert.issuer_dn());
292  if(i == crls.end())
293  {
294  crls.insert(std::make_pair(cert.issuer_dn(),std::vector<CRL_Entry>({ent})));
295  }
296  else
297  {
298  i->second.push_back(ent);
299  }
300  }
301 
302  std::vector<X509_CRL> ret;
303  X509_Time t(std::chrono::system_clock::now());
304 
305  for(auto p: crls)
306  {
307  ret.push_back(X509_CRL(p.first,t,t,p.second));
308  }
309 
310  return ret;
311  }
CRL_Code
Definition: crl_ent.h:20
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 126 of file certstor_sql.cpp.

References Botan::X509_DN::encode_into(), Botan::X509_Object::encode_into(), find_cert(), Botan::X509_Certificate::fingerprint(), Botan::DER_Encoder::get_contents_unlocked(), Botan::X509_Certificate::subject_dn(), and Botan::X509_Certificate::subject_key_id().

Referenced by insert_key(), and revoke_cert().

127  {
128  if(find_cert(cert.subject_dn(),cert.subject_key_id()))
129  return false;
130 
131  DER_Encoder enc;
132  auto stmt = m_database->new_statement("INSERT OR REPLACE INTO " +
133  m_prefix + "certificates (\
134  fingerprint, \
135  subject_dn, \
136  key_id, \
137  priv_fingerprint, \
138  certificate \
139  ) VALUES ( ?1, ?2, ?3, ?4, ?5 )");
140 
141  stmt->bind(1,cert.fingerprint("SHA-256"));
142  cert.subject_dn().encode_into(enc);
143  stmt->bind(2,enc.get_contents_unlocked());
144  stmt->bind(3,cert.subject_key_id());
145  stmt->bind(4,std::vector<uint8_t>());
146  enc = DER_Encoder();
147  cert.encode_into(enc);
148  stmt->bind(5,enc.get_contents_unlocked());
149  stmt->spin();
150 
151  return true;
152  }
virtual std::shared_ptr< const X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
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 207 of file certstor_sql.cpp.

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

207  {
208  insert_cert(cert);
209 
210  if(find_key(cert))
211  return false;
212 
213  auto pkcs8 = PKCS8::BER_encode(key, m_rng, m_password);
214  auto fpr = key.fingerprint("SHA-256");
215 
216  auto stmt1 = m_database->new_statement(
217  "INSERT OR REPLACE INTO " + m_prefix + "keys ( fingerprint, key ) VALUES ( ?1, ?2 )");
218 
219  stmt1->bind(1,fpr);
220  stmt1->bind(2,pkcs8.data(),pkcs8.size());
221  stmt1->spin();
222 
223  auto stmt2 = m_database->new_statement(
224  "UPDATE " + m_prefix + "certificates SET priv_fingerprint = ?1 WHERE fingerprint == ?2");
225 
226  stmt2->bind(1,fpr);
227  stmt2->bind(2,cert.fingerprint("SHA-256"));
228  stmt2->spin();
229 
230  return true;
231  }
bool insert_cert(const X509_Certificate &cert)
secure_vector< uint8_t > BER_encode(const Private_Key &key)
Definition: pkcs8.cpp:130
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 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 155 of file certstor_sql.cpp.

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

156  {
157  if(!find_cert(cert.subject_dn(),cert.subject_key_id()))
158  return false;
159 
160  auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "certificates WHERE fingerprint == ?1");
161 
162  stmt->bind(1,cert.fingerprint("SHA-256"));
163  stmt->spin();
164 
165  return true;
166  }
virtual std::shared_ptr< const X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
void Botan::Certificate_Store_In_SQL::remove_key ( const Private_Key key)

Removes "key" from the store.

Definition at line 233 of file certstor_sql.cpp.

References Botan::Private_Key::fingerprint().

234  {
235  auto fpr = key.fingerprint("SHA-256");
236  auto stmt = m_database->new_statement("DELETE FROM " + m_prefix + "keys WHERE fingerprint == ?1");
237 
238  stmt->bind(1,fpr);
239  stmt->spin();
240  }
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 243 of file certstor_sql.cpp.

References Botan::X509_Time::encode_into(), Botan::X509_Certificate::fingerprint(), Botan::DER_Encoder::get_contents_unlocked(), insert_cert(), and Botan::X509_Time::time_is_set().

244  {
245  insert_cert(cert);
246 
247  auto stmt1 = m_database->new_statement(
248  "INSERT OR REPLACE INTO " + m_prefix + "revoked ( fingerprint, reason, time ) VALUES ( ?1, ?2, ?3 )");
249 
250  stmt1->bind(1,cert.fingerprint("SHA-256"));
251  stmt1->bind(2,code);
252 
253  if(time.time_is_set())
254  {
255  DER_Encoder der;
256  time.encode_into(der);
257  stmt1->bind(3,der.get_contents_unlocked());
258  }
259  else
260  {
261  stmt1->bind(3,-1);
262  }
263 
264  stmt1->spin();
265  }
bool insert_cert(const X509_Certificate &cert)

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