99#include < botan/certstor.h>
1010
1111#include < botan/asn1_time.h>
12+ #include < botan/assert.h>
1213#include < botan/data_src.h>
13- #include < botan/hash.h>
1414#include < botan/pkix_types.h>
1515#include < botan/internal/filesystem.h>
1616#include < algorithm>
@@ -19,7 +19,11 @@ namespace Botan {
1919
2020Certificate_Store::~Certificate_Store () = default ;
2121
22- bool Certificate_Store::certificate_known (const X509_Certificate& searching) const {
22+ bool Certificate_Store::certificate_known (const X509_Certificate& cert) const {
23+ return contains (cert);
24+ }
25+
26+ bool Certificate_Store::contains (const X509_Certificate& searching) const {
2327 for (const auto & cert : find_all_certs (searching.subject_dn (), searching.subject_key_id ())) {
2428 if (cert == searching) {
2529 return true ;
@@ -46,13 +50,13 @@ std::optional<X509_CRL> Certificate_Store::find_crl_for(const X509_Certificate&
4650}
4751
4852void Certificate_Store_In_Memory::add_certificate (const X509_Certificate& cert) {
49- for (const auto & c : m_certs) {
50- if (c == cert) {
51- return ;
52- }
53+ const auto tag = cert.tag ();
54+ if (!m_cert_tags.contains (tag)) {
55+ m_cert_tags.insert (tag);
56+ const size_t idx = m_certs.size ();
57+ m_certs.push_back (cert);
58+ m_dn_to_indices[cert.subject_dn ()].push_back (idx);
5359 }
54-
55- m_certs.push_back (cert);
5660}
5761
5862std::vector<X509_DN> Certificate_Store_In_Memory::all_subjects () const {
@@ -66,19 +70,23 @@ std::vector<X509_DN> Certificate_Store_In_Memory::all_subjects() const {
6670
6771std::optional<X509_Certificate> Certificate_Store_In_Memory::find_cert (const X509_DN& subject_dn,
6872 const std::vector<uint8_t >& key_id) const {
69- for (const auto & cert : m_certs) {
70- // Only compare key ids if set in both call and in the cert
73+ const auto it = m_dn_to_indices.find (subject_dn);
74+ if (it == m_dn_to_indices.end ()) {
75+ return std::nullopt ;
76+ }
77+
78+ for (const size_t idx : it->second ) {
79+ const auto & cert = m_certs[idx];
80+ BOTAN_ASSERT_NOMSG (cert.subject_dn () == subject_dn);
81+
7182 if (!key_id.empty ()) {
7283 const std::vector<uint8_t >& skid = cert.subject_key_id ();
73-
7484 if (!skid.empty () && skid != key_id) { // no match
7585 continue ;
7686 }
7787 }
7888
79- if (cert.subject_dn () == subject_dn) {
80- return cert;
81- }
89+ return cert;
8290 }
8391
8492 return std::nullopt ;
@@ -88,18 +96,23 @@ std::vector<X509_Certificate> Certificate_Store_In_Memory::find_all_certs(const
8896 const std::vector<uint8_t >& key_id) const {
8997 std::vector<X509_Certificate> matches;
9098
91- for (const auto & cert : m_certs) {
99+ const auto it = m_dn_to_indices.find (subject_dn);
100+ if (it == m_dn_to_indices.end ()) {
101+ return matches;
102+ }
103+
104+ for (const size_t idx : it->second ) {
105+ const auto & cert = m_certs[idx];
106+ BOTAN_ASSERT_NOMSG (cert.subject_dn () == subject_dn);
107+
92108 if (!key_id.empty ()) {
93109 const std::vector<uint8_t >& skid = cert.subject_key_id ();
94-
95110 if (!skid.empty () && skid != key_id) { // no match
96111 continue ;
97112 }
98113 }
99114
100- if (cert.subject_dn () == subject_dn) {
101- matches.push_back (cert);
102- }
115+ matches.push_back (cert);
103116 }
104117
105118 return matches;
@@ -111,11 +124,8 @@ std::optional<X509_Certificate> Certificate_Store_In_Memory::find_cert_by_pubkey
111124 throw Invalid_Argument (" Certificate_Store_In_Memory::find_cert_by_pubkey_sha1 invalid hash" );
112125 }
113126
114- auto hash = HashFunction::create_or_throw (" SHA-1" );
115-
116127 for (const auto & cert : m_certs) {
117- hash->update (cert.subject_public_key_bitstring ());
118- if (key_hash == hash->final_stdvec ()) { // final_stdvec also clears the hash to initial state
128+ if (key_hash == cert.subject_public_key_bitstring_sha1 ()) {
119129 return cert;
120130 }
121131 }
@@ -129,11 +139,8 @@ std::optional<X509_Certificate> Certificate_Store_In_Memory::find_cert_by_raw_su
129139 throw Invalid_Argument (" Certificate_Store_In_Memory::find_cert_by_raw_subject_dn_sha256 invalid hash" );
130140 }
131141
132- auto hash = HashFunction::create_or_throw (" SHA-256" );
133-
134142 for (const auto & cert : m_certs) {
135- hash->update (cert.raw_subject_dn ());
136- if (subject_hash == hash->final_stdvec ()) { // final_stdvec also clears the hash to initial state
143+ if (subject_hash == cert.raw_subject_dn_sha256 ()) {
137144 return cert;
138145 }
139146 }
@@ -190,6 +197,10 @@ std::optional<X509_CRL> Certificate_Store_In_Memory::find_crl_for(const X509_Cer
190197 return {};
191198}
192199
200+ bool Certificate_Store_In_Memory::contains (const X509_Certificate& cert) const {
201+ return m_cert_tags.contains (cert.tag ());
202+ }
203+
193204Certificate_Store_In_Memory::Certificate_Store_In_Memory (const X509_Certificate& cert) {
194205 add_certificate (cert);
195206}
@@ -216,8 +227,7 @@ Certificate_Store_In_Memory::Certificate_Store_In_Memory(std::string_view dir) {
216227 DataSource_Stream src (cert_file, true );
217228 while (!src.end_of_data ()) {
218229 try {
219- const X509_Certificate cert (src);
220- m_certs.push_back (cert);
230+ add_certificate (X509_Certificate (src));
221231 } catch (std::exception&) {
222232 // stop searching for other certificate at first exception
223233 break ;
0 commit comments