From ff8345101e7d7364b3fda68094e537ca1f7a9f50 Mon Sep 17 00:00:00 2001 From: Andrei Kurushin Date: Sat, 7 Jan 2017 09:53:39 +0300 Subject: [PATCH] consolidate windows crypto provider implementation into single header (#1495) consolidate windows crypto provider into single header --- include/libtorrent/Makefile.am | 1 + .../libtorrent/aux_/win_crypto_provider.hpp | 165 ++++++++++++++++++ include/libtorrent/hasher.hpp | 5 +- include/libtorrent/hasher512.hpp | 5 +- src/hasher.cpp | 99 +---------- src/hasher512.cpp | 99 +---------- src/random.cpp | 41 +---- 7 files changed, 180 insertions(+), 235 deletions(-) create mode 100644 include/libtorrent/aux_/win_crypto_provider.hpp diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 09700219b..2107ea120 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -184,6 +184,7 @@ nobase_include_HEADERS = \ aux_/has_block.hpp \ aux_/scope_end.hpp \ aux_/vector.hpp \ + aux_/win_crypto_provider.hpp \ aux_/win_util.hpp \ aux_/non_owning_handle.hpp \ \ diff --git a/include/libtorrent/aux_/win_crypto_provider.hpp b/include/libtorrent/aux_/win_crypto_provider.hpp new file mode 100644 index 000000000..79935dfe0 --- /dev/null +++ b/include/libtorrent/aux_/win_crypto_provider.hpp @@ -0,0 +1,165 @@ +/* + +Copyright (c) 2016, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_WIN_CRYPTO_PROVIDER_HPP +#define TORRENT_WIN_CRYPTO_PROVIDER_HPP + +#include "libtorrent/config.hpp" +#include "libtorrent/error_code.hpp" + +#include +#include + +namespace libtorrent { namespace aux +{ + + inline HCRYPTPROV crypt_acquire_provider(DWORD provider_type) + { + HCRYPTPROV ret; + if (CryptAcquireContext(&ret, nullptr, nullptr, provider_type + , CRYPT_VERIFYCONTEXT) == false) + { +#ifndef BOOST_NO_EXCEPTIONS + throw system_error(error_code(GetLastError(), system_category())); +#else + std::terminate(); +#endif + } + return ret; + } + + inline void crypt_gen_random(span buffer) + { + static HCRYPTPROV provider = crypt_acquire_provider(PROV_RSA_FULL); + if (!CryptGenRandom(provider, int(buffer.size()) + , reinterpret_cast(buffer.data()))) + { +#ifndef BOOST_NO_EXCEPTIONS + throw system_error(error_code(GetLastError(), system_category())); +#else + std::terminate(); +#endif + } + } + + template + struct crypt_hash + { + crypt_hash() { m_hash = create(); } + crypt_hash(crypt_hash const& h) { m_hash = duplicate(h); } + ~crypt_hash() { CryptDestroyHash(m_hash); } + + crypt_hash& crypt_hash::operator=(crypt_hash const& h) + { + if (this == &h) return *this; + HCRYPTHASH temp = duplicate(h); + CryptDestroyHash(m_hash); + m_hash = temp; + return *this; + } + + void reset() + { + HCRYPTHASH temp = create(); + CryptDestroyHash(m_hash); + m_hash = temp; + } + + void update(span data) + { + if (CryptHashData(m_hash, reinterpret_cast(data.data()), int(data.size()), 0) == false) + { +#ifndef BOOST_NO_EXCEPTIONS + throw system_error(error_code(GetLastError(), system_category())); +#else + std::terminate(); +#endif + } + } + + void get_hash(char *digest, size_t digest_size) + { + DWORD size = DWORD(digest_size); + if (CryptGetHashParam(m_hash, HP_HASHVAL + , reinterpret_cast(digest), &size, 0) == false) + { +#ifndef BOOST_NO_EXCEPTIONS + throw system_error(error_code(GetLastError(), system_category())); +#else + std::terminate(); +#endif + } + TORRENT_ASSERT(size == DWORD(digest_size)); + } + private: + HCRYPTHASH create() + { + HCRYPTHASH ret; + if (CryptCreateHash(get_provider(), AlgId, 0, 0, &ret) == false) + { +#ifndef BOOST_NO_EXCEPTIONS + throw system_error(error_code(GetLastError(), system_category())); +#else + std::terminate(); +#endif + } + return ret; + } + + HCRYPTHASH duplicate(crypt_hash const& h) + { + HCRYPTHASH ret; + if (CryptDuplicateHash(h.m_hash, 0, 0, &ret) == false) + { +#ifndef BOOST_NO_EXCEPTIONS + throw system_error(error_code(GetLastError(), system_category())); +#else + std::terminate(); +#endif + } + return ret; + } + + HCRYPTPROV get_provider() + { + static HCRYPTPROV provider = crypt_acquire_provider(ProviderType); + return provider; + } + + HCRYPTHASH m_hash; + }; + +} // namespace aux +} // namespace libtorrent + +#endif + diff --git a/include/libtorrent/hasher.hpp b/include/libtorrent/hasher.hpp index 88d770c4e..102600d99 100644 --- a/include/libtorrent/hasher.hpp +++ b/include/libtorrent/hasher.hpp @@ -47,8 +47,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #elif TORRENT_USE_CRYPTOAPI -#include -#include +#include "libtorrent/aux_/win_crypto_provider.hpp" #elif defined TORRENT_USE_LIBCRYPTO @@ -114,7 +113,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA1_CTX m_context; #elif TORRENT_USE_CRYPTOAPI - HCRYPTHASH m_context; + aux::crypt_hash m_context; #elif defined TORRENT_USE_LIBCRYPTO SHA_CTX m_context; #else diff --git a/include/libtorrent/hasher512.hpp b/include/libtorrent/hasher512.hpp index 672380804..8e5aea80b 100644 --- a/include/libtorrent/hasher512.hpp +++ b/include/libtorrent/hasher512.hpp @@ -47,8 +47,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #elif TORRENT_USE_CRYPTOAPI_SHA_512 -#include -#include +#include "libtorrent/aux_/win_crypto_provider.hpp" #elif defined TORRENT_USE_LIBCRYPTO @@ -114,7 +113,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA512_CTX m_context; #elif TORRENT_USE_CRYPTOAPI_SHA_512 - HCRYPTHASH m_context; + aux::crypt_hash m_context; #elif defined TORRENT_USE_LIBCRYPTO SHA512_CTX m_context; #else diff --git a/src/hasher.cpp b/src/hasher.cpp index 73809e684..d9e309ced 100644 --- a/src/hasher.cpp +++ b/src/hasher.cpp @@ -35,34 +35,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/assert.hpp" #include "libtorrent/aux_/openssl.hpp" -#if TORRENT_USE_CRYPTOAPI -namespace -{ - HCRYPTPROV make_crypt_provider() - { - using namespace libtorrent; - - HCRYPTPROV ret; - if (CryptAcquireContext(&ret, nullptr, nullptr, PROV_RSA_FULL - , CRYPT_VERIFYCONTEXT) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - return ret; - } - - HCRYPTPROV get_crypt_provider() - { - static HCRYPTPROV prov = make_crypt_provider(); - return prov; - } -} -#endif - namespace libtorrent { #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO @@ -77,14 +49,6 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA1_Init(&m_context); #elif TORRENT_USE_CRYPTOAPI - if (CryptCreateHash(get_crypt_provider(), CALG_SHA1, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } #elif defined TORRENT_USE_LIBCRYPTO SHA1_Init(&m_context); #else @@ -118,33 +82,6 @@ namespace libtorrent gcry_md_copy(&m_context, h.m_context); return *this; } -#elif TORRENT_USE_CRYPTOAPI - hasher::hasher(hasher const& h) - { - if (CryptDuplicateHash(h.m_context, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - } - - hasher& hasher::operator=(hasher const& h) - { - if (this == &h) return *this; - CryptDestroyHash(m_context); - if (CryptDuplicateHash(h.m_context, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - return *this; - } #else hasher::hasher(hasher const&) = default; hasher& hasher::operator=(hasher const&) = default; @@ -163,14 +100,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA1_Update(&m_context, reinterpret_cast(data.data()), CC_LONG(data.size())); #elif TORRENT_USE_CRYPTOAPI - if (CryptHashData(m_context, reinterpret_cast(data.data()), int(data.size()), 0) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } + m_context.update(data); #elif defined TORRENT_USE_LIBCRYPTO SHA1_Update(&m_context, reinterpret_cast(data.data()), data.size()); #else @@ -188,18 +118,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA1_Final(reinterpret_cast(digest.data()), &m_context); #elif TORRENT_USE_CRYPTOAPI - - DWORD size = DWORD(digest.size()); - if (CryptGetHashParam(m_context, HP_HASHVAL - , reinterpret_cast(digest.data()), &size, 0) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - TORRENT_ASSERT(size == digest.size()); + m_context.get_hash(digest.data(), digest.size()); #elif defined TORRENT_USE_LIBCRYPTO SHA1_Final(reinterpret_cast(digest.data()), &m_context); #else @@ -215,15 +134,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA1_Init(&m_context); #elif TORRENT_USE_CRYPTOAPI - CryptDestroyHash(m_context); - if (CryptCreateHash(get_crypt_provider(), CALG_SHA1, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } + m_context.reset(); #elif defined TORRENT_USE_LIBCRYPTO SHA1_Init(&m_context); #else @@ -233,9 +144,7 @@ namespace libtorrent hasher::~hasher() { -#if TORRENT_USE_CRYPTOAPI - CryptDestroyHash(m_context); -#elif defined TORRENT_USE_LIBGCRYPT +#if defined TORRENT_USE_LIBGCRYPT gcry_md_close(m_context); #endif } diff --git a/src/hasher512.cpp b/src/hasher512.cpp index 9dfc905e0..977a22be0 100644 --- a/src/hasher512.cpp +++ b/src/hasher512.cpp @@ -35,34 +35,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/assert.hpp" #include "libtorrent/aux_/openssl.hpp" -#if TORRENT_USE_CRYPTOAPI_SHA_512 -namespace -{ - HCRYPTPROV make_crypt_provider() - { - using namespace libtorrent; - - HCRYPTPROV ret; - if (CryptAcquireContext(&ret, nullptr, nullptr, PROV_RSA_AES - , CRYPT_VERIFYCONTEXT) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - return ret; - } - - HCRYPTPROV get_crypt_provider() - { - static HCRYPTPROV prov = make_crypt_provider(); - return prov; - } -} -#endif - namespace libtorrent { #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO @@ -77,14 +49,6 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA512_Init(&m_context); #elif TORRENT_USE_CRYPTOAPI_SHA_512 - if (CryptCreateHash(get_crypt_provider(), CALG_SHA_512, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } #elif defined TORRENT_USE_LIBCRYPTO SHA512_Init(&m_context); #else @@ -111,33 +75,6 @@ namespace libtorrent gcry_md_copy(&m_context, h.m_context); return *this; } -#elif TORRENT_USE_CRYPTOAPI_SHA_512 - hasher512::hasher512(hasher512 const& h) - { - if (CryptDuplicateHash(h.m_context, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - } - - hasher512& hasher512::operator=(hasher512 const& h) - { - if (this == &h) return *this; - CryptDestroyHash(m_context); - if (CryptDuplicateHash(h.m_context, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - return *this; - } #else hasher512::hasher512(hasher512 const&) = default; hasher512& hasher512::operator=(hasher512 const&) = default; @@ -151,14 +88,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA512_Update(&m_context, reinterpret_cast(data.data()), CC_LONG(data.size())); #elif TORRENT_USE_CRYPTOAPI_SHA_512 - if (CryptHashData(m_context, reinterpret_cast(data.data()), int(data.size()), 0) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } + m_context.update(data); #elif defined TORRENT_USE_LIBCRYPTO SHA512_Update(&m_context, reinterpret_cast(data.data()), data.size()); #else @@ -176,18 +106,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA512_Final(reinterpret_cast(digest.data()), &m_context); #elif TORRENT_USE_CRYPTOAPI_SHA_512 - - DWORD size = DWORD(digest.size()); - if (CryptGetHashParam(m_context, HP_HASHVAL - , reinterpret_cast(digest.data()), &size, 0) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - TORRENT_ASSERT(size == digest.size()); + m_context.get_hash(digest.data(), digest.size()); #elif defined TORRENT_USE_LIBCRYPTO SHA512_Final(reinterpret_cast(digest.data()), &m_context); #else @@ -203,15 +122,7 @@ namespace libtorrent #elif TORRENT_USE_COMMONCRYPTO CC_SHA512_Init(&m_context); #elif TORRENT_USE_CRYPTOAPI_SHA_512 - CryptDestroyHash(m_context); - if (CryptCreateHash(get_crypt_provider(), CALG_SHA_512, 0, 0, &m_context) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } + m_context.reset(); #elif defined TORRENT_USE_LIBCRYPTO SHA512_Init(&m_context); #else @@ -221,9 +132,7 @@ namespace libtorrent hasher512::~hasher512() { -#if TORRENT_USE_CRYPTOAPI_SHA_512 - CryptDestroyHash(m_context); -#elif defined TORRENT_USE_LIBGCRYPT +#if defined TORRENT_USE_LIBGCRYPT gcry_md_close(m_context); #endif } diff --git a/src/random.cpp b/src/random.cpp index cd4cc28e3..eab5dfcb4 100644 --- a/src/random.cpp +++ b/src/random.cpp @@ -38,8 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/disable_warnings_push.hpp" #if TORRENT_USE_CRYPTOAPI -#include -#include +#include "libtorrent/aux_/win_crypto_provider.hpp" #elif defined TORRENT_USE_LIBCRYPTO extern "C" { @@ -51,34 +50,6 @@ extern "C" { #include "libtorrent/aux_/disable_warnings_pop.hpp" -#if TORRENT_USE_CRYPTOAPI -namespace -{ - HCRYPTPROV make_crypt_provider() - { - using namespace libtorrent; - - HCRYPTPROV ret; - if (CryptAcquireContext(&ret, nullptr, nullptr, PROV_RSA_FULL - , CRYPT_VERIFYCONTEXT) == false) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } - return ret; - } - - HCRYPTPROV get_crypt_provider() - { - static HCRYPTPROV prov = make_crypt_provider(); - return prov; - } -} -#endif - namespace libtorrent { namespace aux @@ -98,15 +69,7 @@ namespace libtorrent void random_bytes(span buffer) { #if TORRENT_USE_CRYPTOAPI - if (!CryptGenRandom(get_crypt_provider(), int(buffer.size()) - , reinterpret_cast(buffer.data()))) - { -#ifndef BOOST_NO_EXCEPTIONS - throw system_error(error_code(GetLastError(), system_category())); -#else - std::terminate(); -#endif - } + aux::crypt_gen_random(buffer); #elif defined TORRENT_USE_LIBCRYPTO #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO