reapack

Package manager for REAPER
Log | Files | Refs | Submodules | README | LICENSE

commit 258058688c09a819fd67761000ca6975d83598a6
parent 4594e1fe2021e5e506c0a881b9921c585f72f75b
Author: cfillion <cfillion@users.noreply.github.com>
Date:   Wed,  5 Dec 2018 18:32:38 -0800

implement SHA256 on Windows

https://docs.microsoft.com/en-us/windows/desktop/seccng/creating-a-hash-with-cng

Diffstat:
Msrc/hash.cpp | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Msrc/hash.hpp | 3++-
Mwin32.tup | 2+-
3 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/src/hash.cpp b/src/hash.cpp @@ -3,35 +3,103 @@ #include <cstdio> #include <vector> -#ifdef __APPLE__ -# include <CommonCrypto/CommonDigest.h> -# define CC(s) CC_##s -#else -# include <openssl/sha.h> -# define CC(s) s -#endif +#ifdef _WIN32 + +# include <windows.h> + +class Hash::CNGContext : public Hash::Context { +public: + CNGContext(const Algorithm algo) : m_algo(), m_hash(), m_hashLength() { + const wchar_t *algoName; + + switch(algo) { + case SHA256: + algoName = BCRYPT_SHA256_ALGORITHM; + break; + default: + return; + } + + BCryptOpenAlgorithmProvider(&m_algo, algoName, + MS_PRIMITIVE_PROVIDER, 0); + + unsigned long bytesWritten; + BCryptGetProperty(m_algo, BCRYPT_HASH_LENGTH, + reinterpret_cast<PUCHAR>(&m_hashLength), sizeof(m_hashLength), + &bytesWritten, 0); + + BCryptCreateHash(m_algo, &m_hash, nullptr, 0, nullptr, 0, 0); + } + + ~CNGContext() override { + if(m_algo) + BCryptCloseAlgorithmProvider(m_algo, 0); + if(m_hash) + BCryptDestroyHash(m_hash); + } + + size_t hashSize() const override { return m_hashLength; } + + void addData(const char *data, const size_t len) override { + BCryptHashData(m_hash, + reinterpret_cast<unsigned char *>(const_cast<char *>(data)), + static_cast<unsigned long>(len), 0); + } + + void getHash(unsigned char *out) { + BCryptFinishHash(m_hash, out, m_hashLength, 0); + } + +private: + BCRYPT_ALG_HANDLE m_algo; + BCRYPT_HASH_HANDLE m_hash; + unsigned long m_hashLength; +}; + +#else // Unix systems + +# ifdef __APPLE__ +# include <CommonCrypto/CommonDigest.h> +# define CC(s) CC_##s +# else +# include <openssl/sha.h> +# define CC(s) s +# endif class Hash::SHA256Context : public Hash::Context { public: SHA256Context() { CC(SHA256_Init)(&m_context); } - size_t hashSize() const { return CC(SHA256_DIGEST_LENGTH); } - void addData(const char *data, const size_t len) { + + size_t hashSize() const override { + return CC(SHA256_DIGEST_LENGTH); + } + + void addData(const char *data, const size_t len) override { CC(SHA256_Update)(&m_context, data, len); } - void getHash(unsigned char *out) { CC(SHA256_Final)(out, &m_context); } + + void getHash(unsigned char *out) override { + CC(SHA256_Final)(out, &m_context); + } private: CC(SHA256_CTX) m_context; }; +#endif + Hash::Hash(const Algorithm algo) : m_algo(algo) { +#ifdef _WIN32 + m_context = std::make_unique<CNGContext>(algo); +#else switch(algo) { case SHA256: m_context = std::make_unique<SHA256Context>(); break; } +#endif } void Hash::write(const char *data, const size_t len) @@ -45,11 +113,13 @@ const std::string &Hash::digest() if(!m_context || !m_value.empty()) return m_value; + // Assuming m_algo and hashSize can fit in one byte. We'll need to implement + // multihash's varint if we need larger values in the future. const size_t hashSize = m_context->hashSize(); std::vector<unsigned char> multihash(2 + hashSize); multihash[0] = m_algo; - multihash[1] = hashSize; + multihash[1] = static_cast<unsigned char>(hashSize); m_context->getHash(&multihash[2]); m_value.resize(multihash.size() * 2); diff --git a/src/hash.hpp b/src/hash.hpp @@ -19,10 +19,11 @@ private: public: virtual ~Context() = default; virtual size_t hashSize() const = 0; - virtual void addData(const char *data, const size_t len) = 0; + virtual void addData(const char *data, size_t len) = 0; virtual void getHash(unsigned char *out) = 0; }; + class CNGContext; class SHA256Context; Algorithm m_algo; diff --git a/win32.tup b/win32.tup @@ -15,7 +15,7 @@ CXXFLAGS += /DWDL_NO_DEFINE_MINMAX /DCURL_STATICLIB /DUNICODE /DNDEBUG CXXFLAGS += /DREAPACK_FILE#\"$(REAPACK_FILE).dll\" LD := $(WRAP) link -LDFLAGS := /nologo User32.lib Shell32.lib Gdi32.lib Comdlg32.lib Comctl32.lib +LDFLAGS := /nologo User32.lib Shell32.lib Gdi32.lib Comdlg32.lib Comctl32.lib Bcrypt.lib LDFLAGS += $(VCPKG)/lib/libcurl.lib Ws2_32.lib Crypt32.lib Advapi32.lib LDFLAGS += $(VCPKG)/lib/sqlite3.lib $(VCPKG)/lib/zlib.lib LDFLAGS += $(TUP_VARIANTDIR)/src/resource.res