Coverage Report

Created: 2021-02-21 07:20

/src/botan/src/lib/x509/certstor.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
* Certificate Store
3
* (C) 1999-2010,2013 Jack Lloyd
4
* (C) 2017 Fabian Weissberg, Rohde & Schwarz Cybersecurity
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8
9
#include <botan/certstor.h>
10
#include <botan/pkix_types.h>
11
#include <botan/internal/filesystem.h>
12
#include <botan/hash.h>
13
#include <botan/data_src.h>
14
15
namespace Botan {
16
17
574
Certificate_Store::~Certificate_Store() {}
18
19
std::optional<X509_Certificate>
20
Certificate_Store::find_cert(const X509_DN& subject_dn, const std::vector<uint8_t>& key_id) const
21
0
   {
22
0
   const auto certs = find_all_certs(subject_dn, key_id);
23
24
0
   if(certs.empty())
25
0
      {
26
0
      return std::nullopt;
27
0
      }
28
29
   // `count` might be greater than 1, but we'll just select the first match
30
0
   return certs.front();
31
0
   }
32
33
std::optional<X509_CRL> Certificate_Store::find_crl_for(const X509_Certificate&) const
34
0
   {
35
0
   return std::nullopt;
36
0
   }
37
38
void Certificate_Store_In_Memory::add_certificate(const X509_Certificate& cert)
39
643
   {
40
643
   for(const auto& c : m_certs)
41
944
      if(c == cert)
42
11
         return;
43
44
632
   m_certs.push_back(cert);
45
632
   }
46
47
std::vector<X509_DN> Certificate_Store_In_Memory::all_subjects() const
48
0
   {
49
0
   std::vector<X509_DN> subjects;
50
0
   for(const auto& cert : m_certs)
51
0
      subjects.push_back(cert.subject_dn());
52
0
   return subjects;
53
0
   }
54
55
std::optional<X509_Certificate>
56
Certificate_Store_In_Memory::find_cert(const X509_DN& subject_dn,
57
                                       const std::vector<uint8_t>& key_id) const
58
0
   {
59
0
   for(const auto& cert : m_certs)
60
0
      {
61
      // Only compare key ids if set in both call and in the cert
62
0
      if(key_id.size())
63
0
         {
64
0
         std::vector<uint8_t> skid = cert.subject_key_id();
65
66
0
         if(skid.size() && skid != key_id) // no match
67
0
            continue;
68
0
         }
69
70
0
      if(cert.subject_dn() == subject_dn)
71
0
         return cert;
72
0
      }
73
74
0
   return std::nullopt;
75
0
   }
76
77
std::vector<X509_Certificate> Certificate_Store_In_Memory::find_all_certs(
78
      const X509_DN& subject_dn,
79
      const std::vector<uint8_t>& key_id) const
80
3.13k
   {
81
3.13k
   std::vector<X509_Certificate> matches;
82
83
3.13k
   for(const auto& cert : m_certs)
84
10.8k
      {
85
10.8k
      if(key_id.size())
86
5.00k
         {
87
5.00k
         std::vector<uint8_t> skid = cert.subject_key_id();
88
89
5.00k
         if(skid.size() && skid != key_id) // no match
90
1.32k
            continue;
91
9.49k
         }
92
93
9.49k
      if(cert.subject_dn() == subject_dn)
94
7.04k
         matches.push_back(cert);
95
9.49k
      }
96
97
3.13k
   return matches;
98
3.13k
   }
99
100
std::optional<X509_Certificate>
101
Certificate_Store_In_Memory::find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const
102
0
   {
103
0
   if(key_hash.size() != 20)
104
0
      throw Invalid_Argument("Certificate_Store_In_Memory::find_cert_by_pubkey_sha1 invalid hash");
105
106
0
   std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-1"));
107
108
0
   for(const auto& cert : m_certs){
109
0
      hash->update(cert.subject_public_key_bitstring());
110
0
      if(key_hash == hash->final_stdvec()) //final_stdvec also clears the hash to initial state
111
0
         return cert;
112
0
   }
113
114
0
   return std::nullopt;
115
0
   }
116
117
std::optional<X509_Certificate>
118
Certificate_Store_In_Memory::find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const
119
0
   {
120
0
   if(subject_hash.size() != 32)
121
0
      throw Invalid_Argument("Certificate_Store_In_Memory::find_cert_by_raw_subject_dn_sha256 invalid hash");
122
123
0
   std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-256"));
124
125
0
   for(const auto& cert : m_certs){
126
0
      hash->update(cert.raw_subject_dn());
127
0
      if(subject_hash == hash->final_stdvec()) //final_stdvec also clears the hash to initial state
128
0
         return cert;
129
0
   }
130
131
0
   return std::nullopt;
132
0
   }
133
134
void Certificate_Store_In_Memory::add_crl(const X509_CRL& crl)
135
0
   {
136
0
   X509_DN crl_issuer = crl.issuer_dn();
137
138
0
   for(auto& c : m_crls)
139
0
      {
140
      // Found an update of a previously existing one; replace it
141
0
      if(c.issuer_dn() == crl_issuer)
142
0
         {
143
0
         if(c.this_update() <= crl.this_update())
144
0
            c = crl;
145
0
         return;
146
0
         }
147
0
      }
148
149
   // Totally new CRL, add to the list
150
0
   m_crls.push_back(crl);
151
0
   }
152
153
std::optional<X509_CRL> Certificate_Store_In_Memory::find_crl_for(const X509_Certificate& subject) const
154
0
   {
155
0
   const std::vector<uint8_t>& key_id = subject.authority_key_id();
156
157
0
   for(const auto& c : m_crls)
158
0
      {
159
      // Only compare key ids if set in both call and in the CRL
160
0
      if(key_id.size())
161
0
         {
162
0
         std::vector<uint8_t> akid = c.authority_key_id();
163
164
0
         if(akid.size() && akid != key_id) // no match
165
0
            continue;
166
0
         }
167
168
0
      if(c.issuer_dn() == subject.issuer_dn())
169
0
         return c;
170
0
      }
171
172
0
   return {};
173
0
   }
174
175
Certificate_Store_In_Memory::Certificate_Store_In_Memory(const X509_Certificate& cert)
176
0
   {
177
0
   add_certificate(cert);
178
0
   }
179
180
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
181
Certificate_Store_In_Memory::Certificate_Store_In_Memory(const std::string& dir)
182
0
   {
183
0
   if(dir.empty())
184
0
      return;
185
186
0
   std::vector<std::string> maybe_certs = get_files_recursive(dir);
187
188
0
   if(maybe_certs.empty())
189
0
      {
190
0
      maybe_certs.push_back(dir);
191
0
      }
192
193
0
   for(auto&& cert_file : maybe_certs)
194
0
      {
195
0
      try
196
0
         {
197
0
         DataSource_Stream src(cert_file, true);
198
0
         while(!src.end_of_data())
199
0
            {
200
0
            try
201
0
               {
202
0
               X509_Certificate cert(src);
203
0
               m_certs.push_back(cert);
204
0
               }
205
0
            catch(std::exception&)
206
0
               {
207
               // stop searching for other certificate at first exception
208
0
               break;
209
0
               }
210
0
            }
211
0
         }
212
0
      catch(std::exception&)
213
0
         {
214
0
         }
215
0
      }
216
0
   }
217
#endif
218
219
}