mirror of https://github.com/OpenRCT2/OpenRCT2.git
Change Windows builds to use CNG API
This commit is contained in:
parent
966032a047
commit
320b149b58
|
@ -61,7 +61,7 @@
|
||||||
<AdditionalOptions>/utf-8 /std:c++latest /permissive- /Zc:externConstexpr</AdditionalOptions>
|
<AdditionalOptions>/utf-8 /std:c++latest /permissive- /Zc:externConstexpr</AdditionalOptions>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalDependencies>imm32.lib;version.lib;winmm.lib;crypt32.lib;wldap32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>imm32.lib;version.lib;winmm.lib;crypt32.lib;wldap32.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalOptions>/OPT:NOLBR /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
<AdditionalOptions>/OPT:NOLBR /ignore:4099 %(AdditionalOptions)</AdditionalOptions>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
|
@ -18,12 +18,17 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// #define __USE_WINSSL__
|
#if defined(_WIN32) && !defined(__USE_OPENSSL__)
|
||||||
|
#define __USE_CNG__
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __USE_WINSSL__
|
#ifdef __USE_CNG__
|
||||||
|
// CNG: Cryptography API: Next Generation (CNG)
|
||||||
|
// available in Windows Vista onwards.
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <wincrypt.h>
|
#include <bcrypt.h>
|
||||||
|
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
|
||||||
#else
|
#else
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +36,10 @@
|
||||||
class Sha1Algorithm final : public HashAlgorithm<20>
|
class Sha1Algorithm final : public HashAlgorithm<20>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
#ifdef __USE_WINSSL__
|
#ifdef __USE_CNG__
|
||||||
HCRYPTPROV _hProv{};
|
BCRYPT_ALG_HANDLE _hAlg{};
|
||||||
HCRYPTHASH _hHash{};
|
BCRYPT_HASH_HANDLE _hHash{};
|
||||||
|
PBYTE _pbHashObject{};
|
||||||
#else
|
#else
|
||||||
EVP_MD_CTX * _ctx{};
|
EVP_MD_CTX * _ctx{};
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,18 +47,33 @@ private:
|
||||||
public:
|
public:
|
||||||
Sha1Algorithm()
|
Sha1Algorithm()
|
||||||
{
|
{
|
||||||
#ifdef __USE_WINSSL__
|
#ifdef __USE_CNG__
|
||||||
if (!CryptAcquireContextW(&_hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
|
// TODO BCRYPT_HASH_REUSABLE_FLAG only available from Windows 8
|
||||||
|
auto status = BCryptOpenAlgorithmProvider(&_hAlg, BCRYPT_SHA1_ALGORITHM, nullptr, BCRYPT_HASH_REUSABLE_FLAG);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
auto dwStatus = GetLastError();
|
throw std::runtime_error("BCryptOpenAlgorithmProvider failed: " + std::to_string(status));
|
||||||
throw std::runtime_error("CryptAcquireContext failed : " + std::to_string(dwStatus));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CryptCreateHash(_hProv, CALG_SHA1, 0, 0, &_hHash))
|
// 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))
|
||||||
{
|
{
|
||||||
auto dwStatus = GetLastError();
|
throw std::runtime_error("BCryptGetProperty failed: " + std::to_string(status));
|
||||||
CryptReleaseContext(_hProv, 0);
|
}
|
||||||
throw std::runtime_error("CryptCreateHash failed : " + std::to_string(dwStatus));
|
|
||||||
|
// 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
|
#else
|
||||||
_ctx = EVP_MD_CTX_create();
|
_ctx = EVP_MD_CTX_create();
|
||||||
|
@ -70,9 +91,10 @@ public:
|
||||||
|
|
||||||
~Sha1Algorithm()
|
~Sha1Algorithm()
|
||||||
{
|
{
|
||||||
#ifdef __USE_WINSSL__
|
#ifdef __USE_CNG__
|
||||||
CryptDestroyHash(_hHash);
|
BCryptCloseAlgorithmProvider(_hAlg, 0);
|
||||||
CryptReleaseContext(_hProv, 0);
|
BCryptDestroyHash(_hHash);
|
||||||
|
HeapFree(GetProcessHeap(), 0, _pbHashObject);
|
||||||
#else
|
#else
|
||||||
EVP_MD_CTX_destroy(_ctx);
|
EVP_MD_CTX_destroy(_ctx);
|
||||||
#endif
|
#endif
|
||||||
|
@ -80,13 +102,9 @@ public:
|
||||||
|
|
||||||
void Clear() override
|
void Clear() override
|
||||||
{
|
{
|
||||||
#ifdef __USE_WINSSL__
|
#ifdef __USE_CNG__
|
||||||
CryptDestroyHash(_hHash);
|
// Finishing the current digest clears the state ready for a new digest
|
||||||
if (!CryptCreateHash(_hProv, CALG_SHA1, 0, 0, &_hHash))
|
Finish();
|
||||||
{
|
|
||||||
auto dwStatus = GetLastError();
|
|
||||||
throw std::runtime_error("CryptCreateHash failed : " + std::to_string(dwStatus));
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
if (EVP_DigestInit_ex(_ctx, EVP_sha1(), nullptr) <= 0)
|
if (EVP_DigestInit_ex(_ctx, EVP_sha1(), nullptr) <= 0)
|
||||||
{
|
{
|
||||||
|
@ -97,11 +115,11 @@ public:
|
||||||
|
|
||||||
void Update(const void * data, size_t dataLen) override
|
void Update(const void * data, size_t dataLen) override
|
||||||
{
|
{
|
||||||
#ifdef __USE_WINSSL__
|
#ifdef __USE_CNG__
|
||||||
if (!CryptHashData(_hHash, (const BYTE *)data, (DWORD)dataLen, 0))
|
auto status = BCryptHashData(_hHash, (PBYTE)data, (ULONG)dataLen, 0);
|
||||||
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
auto dwStatus = GetLastError();
|
throw std::runtime_error("BCryptHashData failed: " + std::to_string(status));
|
||||||
throw std::runtime_error("CryptHashData failed: " + std::to_string(dwStatus));
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (EVP_DigestUpdate(_ctx, data, dataLen) <= 0)
|
if (EVP_DigestUpdate(_ctx, data, dataLen) <= 0)
|
||||||
|
@ -113,13 +131,12 @@ public:
|
||||||
|
|
||||||
std::array<uint8_t, 20> Finish() override
|
std::array<uint8_t, 20> Finish() override
|
||||||
{
|
{
|
||||||
#ifdef __USE_WINSSL__
|
#ifdef __USE_CNG__
|
||||||
std::array<uint8_t, 20> result;
|
std::array<uint8_t, 20> result;
|
||||||
auto cbHash = (DWORD)result.size();
|
auto status = BCryptFinishHash(_hHash, result.data(), (ULONG)result.size(), 0);
|
||||||
if (!CryptGetHashParam(_hHash, HP_HASHVAL, result.data(), &cbHash, 0))
|
if (!NT_SUCCESS(status))
|
||||||
{
|
{
|
||||||
auto dwStatus = GetLastError();
|
throw std::runtime_error("BCryptFinishHash failed: " + std::to_string(status));
|
||||||
throw std::runtime_error("CryptGetHashParam failed: " + std::to_string(dwStatus));
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
#else
|
#else
|
||||||
|
|
Loading…
Reference in New Issue