Coverage Report

Created: 2019-12-03 15:21

/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/internal/filesystem.h>
11
#include <botan/hash.h>
12
#include <botan/data_src.h>
13
14
namespace Botan {
15
16
std::shared_ptr<const X509_CRL> Certificate_Store::find_crl_for(const X509_Certificate&) const
17
0
   {
18
0
   return {};
19
0
   }
20
21
void Certificate_Store_In_Memory::add_certificate(const X509_Certificate& cert)
22
0
   {
23
0
   for(const auto& c : m_certs)
24
0
      if(*c == cert)
25
0
         return;
26
0
27
0
   m_certs.push_back(std::make_shared<const X509_Certificate>(cert));
28
0
   }
29
30
void Certificate_Store_In_Memory::add_certificate(std::shared_ptr<const X509_Certificate> cert)
31
876
   {
32
876
   for(const auto& c : m_certs)
33
1.22k
      if(*c == *cert)
34
11
         return;
35
876
36
876
   m_certs.push_back(cert);
37
865
   }
38
39
std::vector<X509_DN> Certificate_Store_In_Memory::all_subjects() const
40
0
   {
41
0
   std::vector<X509_DN> subjects;
42
0
   for(const auto& cert : m_certs)
43
0
      subjects.push_back(cert->subject_dn());
44
0
   return subjects;
45
0
   }
46
47
std::shared_ptr<const X509_Certificate>
48
Certificate_Store_In_Memory::find_cert(const X509_DN& subject_dn,
49
                                       const std::vector<uint8_t>& key_id) const
50
0
   {
51
0
   for(const auto& cert : m_certs)
52
0
      {
53
0
      // Only compare key ids if set in both call and in the cert
54
0
      if(key_id.size())
55
0
         {
56
0
         std::vector<uint8_t> skid = cert->subject_key_id();
57
0
58
0
         if(skid.size() && skid != key_id) // no match
59
0
            continue;
60
0
         }
61
0
62
0
      if(cert->subject_dn() == subject_dn)
63
0
         return cert;
64
0
      }
65
0
66
0
   return nullptr;
67
0
   }
68
69
std::vector<std::shared_ptr<const X509_Certificate>> Certificate_Store_In_Memory::find_all_certs(
70
      const X509_DN& subject_dn,
71
      const std::vector<uint8_t>& key_id) const
72
3.96k
   {
73
3.96k
   std::vector<std::shared_ptr<const X509_Certificate>> matches;
74
3.96k
75
3.96k
   for(const auto& cert : m_certs)
76
13.3k
      {
77
13.3k
      if(key_id.size())
78
6.48k
         {
79
6.48k
         std::vector<uint8_t> skid = cert->subject_key_id();
80
6.48k
81
6.48k
         if(skid.size() && skid != key_id) // no match
82
2.16k
            continue;
83
11.1k
         }
84
11.1k
85
11.1k
      if(cert->subject_dn() == subject_dn)
86
8.53k
         matches.push_back(cert);
87
11.1k
      }
88
3.96k
89
3.96k
   return matches;
90
3.96k
   }
91
92
std::shared_ptr<const X509_Certificate>
93
Certificate_Store_In_Memory::find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const
94
0
   {
95
0
   if(key_hash.size() != 20)
96
0
      throw Invalid_Argument("Certificate_Store_In_Memory::find_cert_by_pubkey_sha1 invalid hash");
97
0
98
0
   std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-1"));
99
0
100
0
   for(const auto& cert : m_certs){
101
0
      hash->update(cert->subject_public_key_bitstring());
102
0
      if(key_hash == hash->final_stdvec()) //final_stdvec also clears the hash to initial state
103
0
         return cert;
104
0
   }
105
0
106
0
   return nullptr;
107
0
   }
108
109
std::shared_ptr<const X509_Certificate>
110
Certificate_Store_In_Memory::find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const
111
0
   {
112
0
   if(subject_hash.size() != 32)
113
0
      throw Invalid_Argument("Certificate_Store_In_Memory::find_cert_by_raw_subject_dn_sha256 invalid hash");
114
0
115
0
   std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-256"));
116
0
117
0
   for(const auto& cert : m_certs){
118
0
      hash->update(cert->raw_subject_dn());
119
0
      if(subject_hash == hash->final_stdvec()) //final_stdvec also clears the hash to initial state
120
0
         return cert;
121
0
   }
122
0
123
0
   return nullptr;
124
0
   }
125
126
void Certificate_Store_In_Memory::add_crl(const X509_CRL& crl)
127
0
   {
128
0
   std::shared_ptr<const X509_CRL> crl_s = std::make_shared<const X509_CRL>(crl);
129
0
   return add_crl(crl_s);
130
0
   }
131
132
void Certificate_Store_In_Memory::add_crl(std::shared_ptr<const X509_CRL> crl)
133
0
   {
134
0
   X509_DN crl_issuer = crl->issuer_dn();
135
0
136
0
   for(auto& c : m_crls)
137
0
      {
138
0
      // Found an update of a previously existing one; replace it
139
0
      if(c->issuer_dn() == crl_issuer)
140
0
         {
141
0
         if(c->this_update() <= crl->this_update())
142
0
            c = crl;
143
0
         return;
144
0
         }
145
0
      }
146
0
147
0
   // Totally new CRL, add to the list
148
0
   m_crls.push_back(crl);
149
0
   }
150
151
std::shared_ptr<const X509_CRL> Certificate_Store_In_Memory::find_crl_for(const X509_Certificate& subject) const
152
0
   {
153
0
   const std::vector<uint8_t>& key_id = subject.authority_key_id();
154
0
155
0
   for(const auto& c : m_crls)
156
0
      {
157
0
      // Only compare key ids if set in both call and in the CRL
158
0
      if(key_id.size())
159
0
         {
160
0
         std::vector<uint8_t> akid = c->authority_key_id();
161
0
162
0
         if(akid.size() && akid != key_id) // no match
163
0
            continue;
164
0
         }
165
0
166
0
      if(c->issuer_dn() == subject.issuer_dn())
167
0
         return c;
168
0
      }
169
0
170
0
   return {};
171
0
   }
172
173
Certificate_Store_In_Memory::Certificate_Store_In_Memory(const X509_Certificate& cert)
174
0
   {
175
0
   add_certificate(cert);
176
0
   }
177
178
#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
179
Certificate_Store_In_Memory::Certificate_Store_In_Memory(const std::string& dir)
180
0
   {
181
0
   if(dir.empty())
182
0
      return;
183
0
184
0
   std::vector<std::string> maybe_certs = get_files_recursive(dir);
185
0
186
0
   if(maybe_certs.empty())
187
0
      {
188
0
      maybe_certs.push_back(dir);
189
0
      }
190
0
191
0
   for(auto&& cert_file : maybe_certs)
192
0
      {
193
0
      try
194
0
         {
195
0
         DataSource_Stream src(cert_file, true);
196
0
         while(!src.end_of_data())
197
0
            {
198
0
            try
199
0
               {
200
0
               m_certs.push_back(std::make_shared<X509_Certificate>(src));
201
0
               }
202
0
            catch(std::exception&)
203
0
               {
204
0
               // stop searching for other certificate at first exception
205
0
               break;
206
0
               }
207
0
            }
208
0
         }
209
0
      catch(std::exception&)
210
0
         {
211
0
         }
212
0
      }
213
0
   }
214
#endif
215
216
}