aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/x509/certstor_system_windows
diff options
context:
space:
mode:
authorPatrik Fiedler <[email protected]>2019-04-30 16:14:15 +0200
committerTim Oesterreich <[email protected]>2019-05-14 09:11:59 +0200
commit296d41c12a5c8b7ddd28a4c22b5d0482ff3bd5d4 (patch)
tree9c8d4efeeed12862a027ea37d3fe339de65a6c6f /src/lib/x509/certstor_system_windows
parent249edbf41a75285527869c13068aa49d689c716b (diff)
add windows certstore find_cert and find_cert_by_pubkey_sha1 functionality
Signed-off-by: Patrik Fiedler <[email protected]>
Diffstat (limited to 'src/lib/x509/certstor_system_windows')
-rw-r--r--src/lib/x509/certstor_system_windows/certstor_windows.cpp140
-rw-r--r--src/lib/x509/certstor_system_windows/certstor_windows.h74
-rw-r--r--src/lib/x509/certstor_system_windows/info.txt15
3 files changed, 229 insertions, 0 deletions
diff --git a/src/lib/x509/certstor_system_windows/certstor_windows.cpp b/src/lib/x509/certstor_system_windows/certstor_windows.cpp
new file mode 100644
index 000000000..eda8ed17e
--- /dev/null
+++ b/src/lib/x509/certstor_system_windows/certstor_windows.cpp
@@ -0,0 +1,140 @@
+/*
+* Certificate Store
+* (C) 1999-2019 Jack Lloyd
+* (C) 2018-2019 Patrik Fiedler, Tim Oesterreich
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/certstor_windows.h>
+
+#include <Windows.h>
+#include <Wincrypt.h>
+
+namespace Botan {
+
+Certificate_Store_Windows::Certificate_Store_Windows()
+{}
+
+std::vector<X509_DN> Certificate_Store_Windows::all_subjects() const
+ {
+ return {};
+ }
+
+std::shared_ptr<const X509_Certificate>
+Certificate_Store_Windows::find_cert(const Botan::X509_DN & subject_dn,
+ const std::vector<uint8_t> &key_id) const
+{
+ auto commonName = subject_dn.get_attribute("CN");
+
+ if (commonName.empty())
+ {
+ return nullptr; // certificate not found
+ }
+
+ if (commonName.size() != 1)
+ {
+ throw Lookup_Error("ambiguous certificate result");
+ }
+
+ const auto &certName = commonName[0];
+
+ std::vector<std::string> certStoreNames{"MY", "Root", "Trust", "CA"};
+ for (auto &storeName : certStoreNames) {
+ auto windowsCertStore = CertOpenSystemStore(0, storeName.c_str());
+ if (!windowsCertStore) {
+ throw Decoding_Error(
+ "failed to open windows certificate store '" + storeName +
+ "' to find_cert (Error Code: " +
+ std::to_string(::GetLastError()) + ")");
+ }
+
+ PCCERT_CONTEXT pCertContext = CertFindCertificateInStore(
+ windowsCertStore, PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
+ CERT_UNICODE_IS_RDN_ATTRS_FLAG, CERT_FIND_SUBJECT_STR_A,
+ certName.c_str(), nullptr);
+
+ CertCloseStore(windowsCertStore, 0);
+
+ if (pCertContext) {
+ X509_Certificate cert(pCertContext->pbCertEncoded, pCertContext->cbCertEncoded);
+ CertFreeCertificateContext(pCertContext);
+
+ if (cert.subject_dn() == subject_dn) {
+ return std::shared_ptr<X509_Certificate>(&cert);
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+std::vector<std::shared_ptr<const X509_Certificate>> Certificate_Store_Windows::find_all_certs(
+ const X509_DN& subject_dn,
+ const std::vector<uint8_t>& key_id) const
+{
+ BOTAN_UNUSED(subject_dn);
+ BOTAN_UNUSED(key_id);
+ return {};
+}
+std::shared_ptr<const Botan::X509_Certificate>
+Certificate_Store_Windows::find_cert_by_pubkey_sha1(
+ const std::vector<uint8_t> &key_hash) const
+{
+ if(key_hash.size() != 20)
+ {
+ throw Invalid_Argument("Flatfile_Certificate_Store::find_cert_by_pubkey_sha1 invalid hash");
+ }
+
+ // auto internalCerts = _certs.get();
+ // auto lookUp = std::find_if(
+ // internalCerts.begin(), internalCerts.end(),
+ // [&](decltype(internalCerts)::value_type value) {
+ // auto str = value->fingerprint();
+ // str.erase(std::remove(str.begin(), str.end(), ':'), str.end());
+ // return convertTo<ByteBuffer>(str) == key_hash;
+ // });
+ // if (*lookUp != nullptr) {
+ // return *lookUp;
+ // }
+
+ auto windowsCertStore = CertOpenSystemStore(0, TEXT("CA"));
+ if (!windowsCertStore) {
+ throw Decoding_Error(
+ "failed to open windows certificate store 'CA' (Error Code: " + std::to_string(::GetLastError()) + ")");
+ }
+
+ const CRYPT_HASH_BLOB blob {key_hash.size(), const_cast<BYTE*>(key_hash.data())};
+ // dvault::Hash hash = dvault::Hash::fromHex(
+ // HashAlgorithm::SHA1, reinterpret_cast<const char *>(key_hash.data()));
+
+ // blob.pbData = reinterpret_cast<BYTE*>(hash_data);
+ // blob.cbData = key_hash.size();
+ auto certContext = CertFindCertificateInStore(
+ windowsCertStore, (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING), 0,
+ CERT_FIND_SHA1_HASH, &blob, nullptr);
+
+ CertCloseStore(windowsCertStore, 0);
+
+ if (certContext) {
+ X509_Certificate cert(certContext->pbCertEncoded, certContext->cbCertEncoded);
+ CertFreeCertificateContext(certContext);
+ return std::shared_ptr<X509_Certificate>(&cert);
+ }
+
+ return nullptr;
+}
+
+std::shared_ptr<const X509_Certificate>
+Certificate_Store_Windows::find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const
+ {
+ BOTAN_UNUSED(subject_hash);
+ throw Not_Implemented("Certificate_Store_Windows::find_cert_by_raw_subject_dn_sha256");
+ }
+
+std::shared_ptr<const X509_CRL> Certificate_Store_Windows::find_crl_for(const X509_Certificate& subject) const
+ {
+ BOTAN_UNUSED(subject);
+ return {};
+ }
+}
diff --git a/src/lib/x509/certstor_system_windows/certstor_windows.h b/src/lib/x509/certstor_system_windows/certstor_windows.h
new file mode 100644
index 000000000..24d3666e9
--- /dev/null
+++ b/src/lib/x509/certstor_system_windows/certstor_windows.h
@@ -0,0 +1,74 @@
+/*
+* Certificate Store
+* (C) 1999-2019 Jack Lloyd
+* (C) 2019 Patrick Schmidt
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#ifndef BOTAN_CERT_STORE_SYSTEM_WINDOWS_H_
+#define BOTAN_CERT_STORE_SYSTEM_WINDOWS_H_
+
+#include <botan/certstor.h>
+
+#include <vector>
+#include <memory>
+#include <map>
+
+namespace Botan {
+/**
+* Certificate Store that is backed by a file of PEMs of trusted CAs.
+*/
+class BOTAN_PUBLIC_API(2, 11) Certificate_Store_Windows final : public Certificate_Store
+ {
+ public:
+ Certificate_Store_Windows();
+
+ Certificate_Store_Windows(const Certificate_Store_Windows&) = default;
+ Certificate_Store_Windows(Certificate_Store_Windows&&) = default;
+ Certificate_Store_Windows& operator=(const Certificate_Store_Windows&) = default;
+ Certificate_Store_Windows& operator=(Certificate_Store_Windows&&) = default;
+
+ /**
+ * @return DNs for all certificates managed by the store
+ */
+ std::vector<X509_DN> all_subjects() const override;
+
+ /**
+ * Find a certificate by Subject DN and (optionally) key identifier
+ * @return the first certificate that matches
+ */
+ std::shared_ptr<const X509_Certificate> find_cert(
+ const X509_DN& subject_dn,
+ const std::vector<uint8_t>& key_id) const override;
+
+ /**
+ * Find all certificates with a given Subject DN.
+ * Subject DN and even the key identifier might not be unique.
+ */
+ 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;
+
+ /**
+ * Find a certificate by searching for one with a matching SHA-1 hash of
+ * public key.
+ * @return a matching certificate or nullptr otherwise
+ */
+ std::shared_ptr<const X509_Certificate>
+ find_cert_by_pubkey_sha1(const std::vector<uint8_t>& key_hash) const override;
+
+ /**
+ * @throws Botan::Not_Implemented
+ */
+ std::shared_ptr<const X509_Certificate>
+ find_cert_by_raw_subject_dn_sha256(const std::vector<uint8_t>& subject_hash) const override;
+
+ /**
+ * Fetching CRLs is not supported by the keychain on macOS. This will
+ * always return an empty list.
+ */
+ std::shared_ptr<const X509_CRL> find_crl_for(const X509_Certificate& subject) const override;
+ };
+}
+
+#endif
diff --git a/src/lib/x509/certstor_system_windows/info.txt b/src/lib/x509/certstor_system_windows/info.txt
new file mode 100644
index 000000000..8c11db8f8
--- /dev/null
+++ b/src/lib/x509/certstor_system_windows/info.txt
@@ -0,0 +1,15 @@
+<defines>
+CERTSTOR_WINDOWS -> 20190430
+</defines>
+
+<os_features>
+win32
+</os_features>
+
+<header:public>
+certstor_windows.h
+</header:public>
+
+<libs>
+all!windows -> crypto
+</libs> \ No newline at end of file