diff options
author | Patrik Fiedler <[email protected]> | 2019-04-30 16:14:15 +0200 |
---|---|---|
committer | Tim Oesterreich <[email protected]> | 2019-05-14 09:11:59 +0200 |
commit | 296d41c12a5c8b7ddd28a4c22b5d0482ff3bd5d4 (patch) | |
tree | 9c8d4efeeed12862a027ea37d3fe339de65a6c6f /src/lib/x509/certstor_system_windows | |
parent | 249edbf41a75285527869c13068aa49d689c716b (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.cpp | 140 | ||||
-rw-r--r-- | src/lib/x509/certstor_system_windows/certstor_windows.h | 74 | ||||
-rw-r--r-- | src/lib/x509/certstor_system_windows/info.txt | 15 |
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 |