mirror of https://github.com/OpenRCT2/OpenRCT2.git
Only reuse CNG object if Windows 8+
This commit is contained in:
parent
320b149b58
commit
ea22c672d0
|
@ -15,6 +15,7 @@
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#include "Hash.h"
|
#include "Hash.h"
|
||||||
|
#include "../platform/Platform2.h"
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ private:
|
||||||
BCRYPT_ALG_HANDLE _hAlg{};
|
BCRYPT_ALG_HANDLE _hAlg{};
|
||||||
BCRYPT_HASH_HANDLE _hHash{};
|
BCRYPT_HASH_HANDLE _hHash{};
|
||||||
PBYTE _pbHashObject{};
|
PBYTE _pbHashObject{};
|
||||||
|
bool _reusable{};
|
||||||
#else
|
#else
|
||||||
EVP_MD_CTX * _ctx{};
|
EVP_MD_CTX * _ctx{};
|
||||||
#endif
|
#endif
|
||||||
|
@ -48,63 +50,30 @@ public:
|
||||||
Sha1Algorithm()
|
Sha1Algorithm()
|
||||||
{
|
{
|
||||||
#ifdef __USE_CNG__
|
#ifdef __USE_CNG__
|
||||||
// TODO BCRYPT_HASH_REUSABLE_FLAG only available from Windows 8
|
// BCRYPT_HASH_REUSABLE_FLAG only available from Windows 8
|
||||||
auto status = BCryptOpenAlgorithmProvider(&_hAlg, BCRYPT_SHA1_ALGORITHM, nullptr, BCRYPT_HASH_REUSABLE_FLAG);
|
_reusable = Platform::IsOSVersionAtLeast(6, 2, 0);
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
throw std::runtime_error("BCryptOpenAlgorithmProvider failed: " + std::to_string(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the size of the buffer to hold the hash object
|
|
||||||
DWORD cbHashObject{};
|
|
||||||
DWORD cbData{};
|
|
||||||
status = BCryptGetProperty(_hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0);
|
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
throw std::runtime_error("BCryptGetProperty failed: " + std::to_string(status));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a hash
|
|
||||||
_pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
|
|
||||||
if (_pbHashObject == nullptr)
|
|
||||||
{
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
status = BCryptCreateHash(_hAlg, &_hHash, _pbHashObject, cbHashObject, nullptr, 0, 0);
|
|
||||||
if (!NT_SUCCESS(status))
|
|
||||||
{
|
|
||||||
throw std::runtime_error("BCryptCreateHash failed: " + std::to_string(status));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
_ctx = EVP_MD_CTX_create();
|
|
||||||
if (_ctx == nullptr)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("EVP_MD_CTX_create failed");
|
|
||||||
}
|
|
||||||
if (EVP_DigestInit_ex(_ctx, EVP_sha1(), nullptr) <= 0)
|
|
||||||
{
|
|
||||||
EVP_MD_CTX_destroy(_ctx);
|
|
||||||
throw std::runtime_error("EVP_DigestInit_ex failed");
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
Initialise();
|
||||||
}
|
}
|
||||||
|
|
||||||
~Sha1Algorithm()
|
~Sha1Algorithm()
|
||||||
{
|
{
|
||||||
#ifdef __USE_CNG__
|
Dispose();
|
||||||
BCryptCloseAlgorithmProvider(_hAlg, 0);
|
|
||||||
BCryptDestroyHash(_hHash);
|
|
||||||
HeapFree(GetProcessHeap(), 0, _pbHashObject);
|
|
||||||
#else
|
|
||||||
EVP_MD_CTX_destroy(_ctx);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear() override
|
void Clear() override
|
||||||
{
|
{
|
||||||
#ifdef __USE_CNG__
|
#ifdef __USE_CNG__
|
||||||
// Finishing the current digest clears the state ready for a new digest
|
if (_reusable)
|
||||||
Finish();
|
{
|
||||||
|
// Finishing the current digest clears the state ready for a new digest
|
||||||
|
Finish();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
Initialise();
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (EVP_DigestInit_ex(_ctx, EVP_sha1(), nullptr) <= 0)
|
if (EVP_DigestInit_ex(_ctx, EVP_sha1(), nullptr) <= 0)
|
||||||
{
|
{
|
||||||
|
@ -154,6 +123,67 @@ public:
|
||||||
return result;
|
return result;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Initialise()
|
||||||
|
{
|
||||||
|
#ifdef __USE_CNG__
|
||||||
|
auto flags = _reusable ? BCRYPT_HASH_REUSABLE_FLAG : 0;
|
||||||
|
auto status = BCryptOpenAlgorithmProvider(&_hAlg, BCRYPT_SHA1_ALGORITHM, nullptr, flags);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("BCryptOpenAlgorithmProvider failed: " + std::to_string(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the size of the buffer to hold the hash object
|
||||||
|
DWORD cbHashObject{};
|
||||||
|
DWORD cbData{};
|
||||||
|
status = BCryptGetProperty(_hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("BCryptGetProperty failed: " + std::to_string(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a hash
|
||||||
|
_pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
|
||||||
|
if (_pbHashObject == nullptr)
|
||||||
|
{
|
||||||
|
throw std::bad_alloc();
|
||||||
|
}
|
||||||
|
status = BCryptCreateHash(_hAlg, &_hHash, _pbHashObject, cbHashObject, nullptr, 0, 0);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("BCryptCreateHash failed: " + std::to_string(status));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
_ctx = EVP_MD_CTX_create();
|
||||||
|
if (_ctx == nullptr)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("EVP_MD_CTX_create failed");
|
||||||
|
}
|
||||||
|
if (EVP_DigestInit_ex(_ctx, EVP_sha1(), nullptr) <= 0)
|
||||||
|
{
|
||||||
|
EVP_MD_CTX_destroy(_ctx);
|
||||||
|
throw std::runtime_error("EVP_DigestInit_ex failed");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dispose()
|
||||||
|
{
|
||||||
|
#ifdef __USE_CNG__
|
||||||
|
BCryptCloseAlgorithmProvider(_hAlg, 0);
|
||||||
|
BCryptDestroyHash(_hHash);
|
||||||
|
HeapFree(GetProcessHeap(), 0, _pbHashObject);
|
||||||
|
|
||||||
|
_hAlg = {};
|
||||||
|
_hHash = {};
|
||||||
|
_pbHashObject = {};
|
||||||
|
#else
|
||||||
|
EVP_MD_CTX_destroy(_ctx);
|
||||||
|
_ctx = {};
|
||||||
|
#endif
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Hash
|
namespace Hash
|
||||||
|
|
|
@ -197,15 +197,10 @@ namespace Platform
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
bool IsOSVersionAtLeast(uint32 major, uint32 minor, uint32 build)
|
||||||
* Checks if the current version of Windows supports ANSI colour codes.
|
|
||||||
* From Windows 10, build 10586 ANSI escape colour codes can be used on stdout.
|
|
||||||
*/
|
|
||||||
static bool HasANSIColourSupport()
|
|
||||||
{
|
{
|
||||||
const DWORD MINV_MAJOR = 10, MINV_MINOR = 0, MINV_BUILD = 10586;
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
HMODULE hModule = GetModuleHandleA("ntdll.dll");
|
auto hModule = GetModuleHandleA("ntdll.dll");
|
||||||
if (hModule != nullptr)
|
if (hModule != nullptr)
|
||||||
{
|
{
|
||||||
using RtlGetVersionPtr = NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW);
|
using RtlGetVersionPtr = NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW);
|
||||||
|
@ -216,11 +211,11 @@ namespace Platform
|
||||||
rovi.dwOSVersionInfoSize = sizeof(rovi);
|
rovi.dwOSVersionInfoSize = sizeof(rovi);
|
||||||
if (fn(&rovi) == 0)
|
if (fn(&rovi) == 0)
|
||||||
{
|
{
|
||||||
if (rovi.dwMajorVersion > MINV_MAJOR ||
|
if (rovi.dwMajorVersion > major ||
|
||||||
(rovi.dwMajorVersion == MINV_MAJOR &&
|
(rovi.dwMajorVersion == major &&
|
||||||
(rovi.dwMinorVersion > MINV_MINOR ||
|
(rovi.dwMinorVersion > minor ||
|
||||||
(rovi.dwMinorVersion == MINV_MINOR &&
|
(rovi.dwMinorVersion == minor &&
|
||||||
rovi.dwBuildNumber >= MINV_BUILD))))
|
rovi.dwBuildNumber >= build))))
|
||||||
{
|
{
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
@ -230,6 +225,15 @@ namespace Platform
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current version of Windows supports ANSI colour codes.
|
||||||
|
* From Windows 10, build 10586 ANSI escape colour codes can be used on stdout.
|
||||||
|
*/
|
||||||
|
static bool HasANSIColourSupport()
|
||||||
|
{
|
||||||
|
return IsOSVersionAtLeast(10, 0, 10586);
|
||||||
|
}
|
||||||
|
|
||||||
static void EnableANSIConsole()
|
static void EnableANSIConsole()
|
||||||
{
|
{
|
||||||
if (HasANSIColourSupport())
|
if (HasANSIColourSupport())
|
||||||
|
|
|
@ -45,5 +45,9 @@ namespace Platform
|
||||||
std::string FormatShortDate(std::time_t timestamp);
|
std::string FormatShortDate(std::time_t timestamp);
|
||||||
std::string FormatTime(std::time_t timestamp);
|
std::string FormatTime(std::time_t timestamp);
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
bool IsOSVersionAtLeast(uint32 major, uint32 minor, uint32 build);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool IsColourTerminalSupported();
|
bool IsColourTerminalSupported();
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
Loading…
Reference in New Issue