9#include <botan/certstor_windows.h>
10#include <botan/pkix_types.h>
11#include <botan/der_enc.h>
21#define WINCRYPT_UNUSED_PARAM 0
26using Cert_Pointer = std::shared_ptr<const Botan::X509_Certificate>;
27using Cert_Vector = std::vector<Cert_Pointer>;
28const std::array<const char*, 2> cert_store_names{
"Root",
"CA"};
41 Handle_Guard(
T context)
46 Handle_Guard(
const Handle_Guard<T>& rhs) =
delete;
47 Handle_Guard(Handle_Guard<T>&& rhs) :
48 m_context(std::move(rhs.m_context))
50 rhs.m_context =
nullptr;
60 return m_context !=
nullptr;
63 bool assign(
T context)
66 return m_context !=
nullptr;
85 template<
class T2 = T>
86 typename std::enable_if<std::is_same<T2, PCCERT_CONTEXT>::value>
::type close()
90 CertFreeCertificateContext(m_context);
94 template<
class T2 = T>
95 typename std::enable_if<std::is_same<T2, HCERTSTORE>::value>
::type close()
102 CertCloseStore(m_context, 0);
109HCERTSTORE open_cert_store(
const char* cert_store_name)
115 "failed to open windows certificate store '" + std::string(cert_store_name) +
122Cert_Vector search_cert_stores(
const _CRYPTOAPI_BLOB& blob,
const DWORD& find_type,
123 std::function<
bool(
const Cert_Vector& certs, Cert_Pointer cert)> filter,
124 bool return_on_first_found)
127 for(
const auto store_name : cert_store_names)
129 Handle_Guard<HCERTSTORE> windows_cert_store = open_cert_store(store_name);
130 Handle_Guard<PCCERT_CONTEXT> cert_context =
nullptr;
131 while(cert_context.assign(CertFindCertificateInStore(
132 windows_cert_store.get(), PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
134 &blob, cert_context.get())))
136 auto cert = std::make_shared<X509_Certificate>(cert_context->pbCertEncoded, cert_context->cbCertEncoded);
137 if(filter(certs, cert))
139 if(return_on_first_found)
143 certs.push_back(cert);
151bool already_contains_certificate(
const Cert_Vector& certs, Cert_Pointer cert)
153 return std::any_of(certs.begin(), certs.end(), [&](std::shared_ptr<const Botan::X509_Certificate> c)
159Cert_Vector find_cert_by_dn_and_key_id(
const Botan::X509_DN& subject_dn,
160 const std::vector<uint8_t>& key_id,
161 bool return_on_first_found)
163 _CRYPTOAPI_BLOB blob;
165 std::vector<uint8_t> dn_data;
170 find_type = CERT_FIND_SUBJECT_NAME;
171 DER_Encoder encoder(dn_data);
173 blob.cbData =
static_cast<DWORD
>(dn_data.size());
174 blob.pbData =
reinterpret_cast<BYTE*
>(dn_data.data());
178 find_type = CERT_FIND_KEY_IDENTIFIER;
179 blob.cbData =
static_cast<DWORD
>(key_id.size());
180 blob.pbData =
const_cast<BYTE*
>(key_id.data());
183 auto filter = [&](
const Cert_Vector& certs, Cert_Pointer cert)
185 return !already_contains_certificate(certs, cert) && (key_id.empty() || cert->subject_dn() == subject_dn);
188 return search_cert_stores(blob, find_type, filter, return_on_first_found);
196 std::vector<X509_DN> subject_dns;
197 for(
const auto store_name : cert_store_names)
199 Handle_Guard<HCERTSTORE> windows_cert_store = open_cert_store(store_name);
200 Handle_Guard<PCCERT_CONTEXT> cert_context =
nullptr;
204 while(cert_context.assign(CertEnumCertificatesInStore(windows_cert_store.get(), cert_context.get())))
206 X509_Certificate cert(cert_context->pbCertEncoded, cert_context->cbCertEncoded);
215 const std::vector<uint8_t>& key_id)
const
217 const auto certs = find_cert_by_dn_and_key_id(subject_dn, key_id,
true);
218 return certs.empty() ? nullptr : certs.front();
223 const std::vector<uint8_t>& key_id)
const
225 return find_cert_by_dn_and_key_id(subject_dn, key_id,
false);
230 if(key_hash.size() != 20)
232 throw Invalid_Argument(
"Certificate_Store_Windows::find_cert_by_pubkey_sha1 invalid hash");
235 CRYPT_HASH_BLOB blob;
236 blob.cbData =
static_cast<DWORD
>(key_hash.size());
237 blob.pbData =
const_cast<BYTE*
>(key_hash.data());
239 auto filter = [](
const Cert_Vector&, Cert_Pointer) {
return true; };
241 const auto certs = search_cert_stores(blob, CERT_FIND_KEY_IDENTIFIER, filter,
true);
242 return certs.empty() ? nullptr : certs.front();
246 const std::vector<uint8_t>& subject_hash)
const
249 throw Not_Implemented(
"Certificate_Store_Windows::find_cert_by_raw_subject_dn_sha256");
#define BOTAN_UNUSED(...)
#define WINCRYPT_UNUSED_PARAM
Certificate_Store_Windows()
std::vector< std::shared_ptr< const X509_Certificate > > find_all_certs(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
std::vector< X509_DN > all_subjects() const override
std::shared_ptr< const X509_Certificate > find_cert_by_raw_subject_dn_sha256(const std::vector< uint8_t > &subject_hash) const override
std::shared_ptr< const X509_Certificate > find_cert(const X509_DN &subject_dn, const std::vector< uint8_t > &key_id) const override
std::shared_ptr< const X509_CRL > find_crl_for(const X509_Certificate &subject) const override
std::shared_ptr< const X509_Certificate > find_cert_by_pubkey_sha1(const std::vector< uint8_t > &key_hash) const override
const X509_DN & subject_dn() const
void encode_into(DER_Encoder &) const override
std::string to_string(const BER_Object &obj)