Skip to content

Commit

Permalink
key loading uses new cng wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
Aidan63 committed Aug 17, 2024
1 parent bdb8337 commit 38c8b18
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 142 deletions.
36 changes: 22 additions & 14 deletions src/hx/libs/ssl/windows/Cng.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ namespace hx
{
BCRYPT_HANDLE handle;

virtual ~CngObject() = 0;

CngObject(BCRYPT_HANDLE inHandle) : handle(inHandle) {}

template<class T>
Expand All @@ -38,9 +36,19 @@ namespace hx
return buffer;
}

void setProperty(const wchar_t* prop) const
void setProperty(const wchar_t* prop, PUCHAR input, const ULONG length) const
{
hx::EnterGCFreeZone();

auto result = DWORD{ 0 };

if (!BCRYPT_SUCCESS(result = BCryptSetProperty(handle, prop, input, length, 0)))
{
hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

hx::ExitGCFreeZone();
}
};

Expand Down Expand Up @@ -124,25 +132,25 @@ namespace hx

struct CngAlgorithm : CngObject
{
CngAlgorithm(BCRYPT_ALG_HANDLE inHandle) : CngObject(inHandle) {}
ULONG flags;

public:
BCRYPT_ALG_HANDLE handle;
CngAlgorithm(BCRYPT_ALG_HANDLE inHandle, ULONG inFlags) : CngObject(inHandle), flags(inFlags) {}

public:
~CngAlgorithm()
{
BCryptCloseAlgorithmProvider(handle, 0);
}

std::unique_ptr<CngHash> hash() const
{
hx::EnterGCFreeZone();

auto result = DWORD{ 0 };
auto hHash = BCRYPT_HASH_HANDLE();
auto object = std::make_unique<std::vector<uint8_t>>(getProperty<DWORD>(BCRYPT_OBJECT_LENGTH));

if (!BCRYPT_SUCCESS(result = BCryptCreateHash(handle, &hHash, object->data(), object->size(), nullptr, 0, BCRYPT_HASH_REUSABLE_FLAG)))
hx::EnterGCFreeZone();

if (!BCRYPT_SUCCESS(result = BCryptCreateHash(handle, &hHash, object->data(), object->size(), nullptr, 0, flags)))
{
hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failed to create hash object : ") + hx::ssl::windows::utils::NTStatusErrorToString(result));
Expand All @@ -153,22 +161,22 @@ namespace hx
return std::make_unique<CngHash>(hHash, std::move(object));
}

static std::unique_ptr<CngAlgorithm> create(const wchar_t* algId)
static std::unique_ptr<CngAlgorithm> create(const wchar_t* algId, ULONG flags)
{
hx::EnterGCFreeZone();

auto result = DWORD{ 0 };
auto handle = BCRYPT_ALG_HANDLE();

if (!BCRYPT_SUCCESS(result = BCryptOpenAlgorithmProvider(&handle, algId, nullptr, BCRYPT_HASH_REUSABLE_FLAG)))
hx::EnterGCFreeZone();

if (!BCRYPT_SUCCESS(result = BCryptOpenAlgorithmProvider(&handle, algId, nullptr, flags)))
{
hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failed to open algorithm provider : ") + hx::ssl::windows::utils::NTStatusErrorToString(result));
}

hx::ExitGCFreeZone();

return std::make_unique<CngAlgorithm>(handle);
return std::make_unique<CngAlgorithm>(handle, flags);
}
};
}
Expand Down
6 changes: 3 additions & 3 deletions src/hx/libs/ssl/windows/Digest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Array<unsigned char> _hx_ssl_dgst_make(Array<unsigned char> buffer, String algId
{
hx::strbuf buf;

auto algorithm = hx::ssl::windows::CngAlgorithm::create(algId.wchar_str(&buf));
auto algorithm = hx::ssl::windows::CngAlgorithm::create(algId.wchar_str(&buf), 0);
auto hash = algorithm->hash();

hash->hash(buffer);
Expand All @@ -22,7 +22,7 @@ Array<unsigned char> _hx_ssl_dgst_sign(Array<unsigned char> buffer, Dynamic hpke

auto key = hpkey.Cast<hx::ssl::windows::Key>();
auto algorithm = algId.wchar_str(&buf);
auto alg = hx::ssl::windows::CngAlgorithm::create(algorithm);
auto alg = hx::ssl::windows::CngAlgorithm::create(algorithm, 0);
auto hash = alg->hash();
auto hashed = std::vector<uint8_t>(hash->getProperty<DWORD>(BCRYPT_HASH_LENGTH));

Expand Down Expand Up @@ -61,7 +61,7 @@ bool _hx_ssl_dgst_verify(Array<unsigned char> buffer, Array<unsigned char> sign,

auto key = hpkey.Cast<hx::ssl::windows::Key>();
auto algorithm = algId.wchar_str(&buf);
auto alg = hx::ssl::windows::CngAlgorithm::create(algorithm);
auto alg = hx::ssl::windows::CngAlgorithm::create(algorithm, 0);
auto hash = alg->hash();
auto hashed = std::vector<uint8_t>(hash->getProperty<DWORD>(BCRYPT_HASH_LENGTH));

Expand Down
142 changes: 17 additions & 125 deletions src/hx/libs/ssl/windows/Key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include <iostream>

#include "SSL.h"
#include "Utils.h"
#include "Cng.h"

namespace
{
Expand Down Expand Up @@ -105,33 +105,12 @@ namespace
hx::Throw(HX_CSTRING("Failure"));
}

auto md5 = BCRYPT_ALG_HANDLE();
if (!BCRYPT_SUCCESS(result = BCryptOpenAlgorithmProvider(&md5, BCRYPT_MD5_ALGORITHM, nullptr, BCRYPT_HASH_REUSABLE_FLAG)))
{
hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

auto objectLength = DWORD{ 0 };
if (!BCRYPT_SUCCESS(result = BCryptGetProperty(md5, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PUCHAR>(&objectLength), sizeof(DWORD), &cb, 0)))
{
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

auto object = std::vector<uint8_t>(objectLength);
auto hash = BCRYPT_HASH_HANDLE();
if (!BCRYPT_SUCCESS(result = BCryptCreateHash(md5, &hash, object.data(), object.size(), nullptr, 0, BCRYPT_HASH_REUSABLE_FLAG)))
{
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}
hx::ExitGCFreeZone();

auto concat = std::vector<uint8_t>();
auto md5 = hx::ssl::windows::CngAlgorithm::create(BCRYPT_MD5_ALGORITHM, BCRYPT_HASH_REUSABLE_FLAG);
auto hash = md5->hash();
auto concat = std::vector<UCHAR>();
auto digest = std::vector<UCHAR>(hash->getProperty<DWORD>(BCRYPT_HASH_LENGTH));

hx::strbuf passbuffer;

Expand All @@ -142,115 +121,35 @@ namespace
{
if (!concat.empty())
{
if (!BCRYPT_SUCCESS(result = BCryptHashData(hash, reinterpret_cast<PUCHAR>(concat.data()), concat.size(), 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}
hash->hash(concat.data(), concat.size());
}

if (!BCRYPT_SUCCESS(result = BCryptHashData(hash, reinterpret_cast<PUCHAR>(const_cast<char*>(password)), passlength, 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}
if (!BCRYPT_SUCCESS(result = BCryptHashData(hash, reinterpret_cast<PUCHAR>(iv.data()), 8, 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

auto hashLength = DWORD{ 0 };
if (!BCRYPT_SUCCESS(result = BCryptGetProperty(hash, BCRYPT_HASH_LENGTH, reinterpret_cast<PUCHAR>(&hashLength), sizeof(DWORD), &cb, 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

auto digest = std::vector<uint8_t>(hashLength);
if (!BCRYPT_SUCCESS(result = BCryptFinishHash(hash, digest.data(), digest.size(), 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}
hash->hash(reinterpret_cast<PUCHAR>(const_cast<char*>(password)), passlength);
hash->hash(reinterpret_cast<PUCHAR>(iv.data()), 8);
hash->finish(digest.data(), digest.size());

hx::EnterGCFreeZone();
concat.insert(concat.end(), digest.begin(), digest.end());
}

auto aes = BCRYPT_ALG_HANDLE();
if (!BCRYPT_SUCCESS(result = BCryptOpenAlgorithmProvider(&aes, algorithm, nullptr, 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

if (!BCRYPT_SUCCESS(result = BCryptGetProperty(aes, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PUCHAR>(&size), sizeof(DWORD), &cb, 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);
BCryptCloseAlgorithmProvider(aes, 0);
auto aes = hx::ssl::windows::CngAlgorithm::create(algorithm, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}
aes->setProperty(BCRYPT_CHAINING_MODE, reinterpret_cast<PUCHAR>(BCRYPT_CHAIN_MODE_CBC), wcslen(BCRYPT_CHAIN_MODE_CBC));

auto aeskey = std::vector<uint8_t>(size);
auto aeskey = std::vector<uint8_t>(aes->getProperty<DWORD>(BCRYPT_OBJECT_LENGTH));

auto blockLength = DWORD{ 0 };
if (!BCRYPT_SUCCESS(result = BCryptGetProperty(aes, BCRYPT_BLOCK_LENGTH, reinterpret_cast<PUCHAR>(&blockLength), sizeof(DWORD), &cb, 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);
BCryptCloseAlgorithmProvider(aes, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

if (!BCRYPT_SUCCESS(result = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, reinterpret_cast<PUCHAR>(BCRYPT_CHAIN_MODE_CBC), wcslen(BCRYPT_CHAIN_MODE_CBC), 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);
BCryptCloseAlgorithmProvider(aes, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}
hx::EnterGCFreeZone();

auto outputkey = BCRYPT_KEY_HANDLE();
if (!BCRYPT_SUCCESS(result = BCryptGenerateSymmetricKey(aes, &outputkey, aeskey.data(), aeskey.size(), concat.data(), keySize, 0)))
if (!BCRYPT_SUCCESS(result = BCryptGenerateSymmetricKey(aes->handle, &outputkey, aeskey.data(), aeskey.size(), concat.data(), keySize, 0)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);
BCryptCloseAlgorithmProvider(aes, 0);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failure"));
}

if (!BCRYPT_SUCCESS(result = BCryptDecrypt(outputkey, encrypted.data(), encrypted.size(), nullptr, iv.data(), iv.size(), nullptr, 0, &size, BCRYPT_PAD_PKCS1)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);
BCryptCloseAlgorithmProvider(aes, 0);
BCryptDestroyKey(outputkey);

hx::ExitGCFreeZone();
Expand All @@ -260,18 +159,12 @@ namespace
auto decrypted = std::vector<uint8_t>(size);
if (!BCRYPT_SUCCESS(result = BCryptDecrypt(outputkey, encrypted.data(), encrypted.size(), nullptr, iv.data(), iv.size(), decrypted.data(), decrypted.size(), &size, BCRYPT_PAD_PKCS1)))
{
BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);
BCryptCloseAlgorithmProvider(aes, 0);
BCryptDestroyKey(outputkey);

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Failed to decrypt key : ") + hx::ssl::windows::utils::NTStatusErrorToString(result));
}

BCryptDestroyHash(hash);
BCryptCloseAlgorithmProvider(md5, 0);
BCryptCloseAlgorithmProvider(aes, 0);
BCryptDestroyKey(outputkey);

return DecodePrivateRsaKey(decrypted.data(), decrypted.size());
Expand Down Expand Up @@ -563,8 +456,7 @@ Dynamic _hx_ssl_key_from_pem(String pem, bool pub, String pass)
return DecodePublicPkcs8Key(derKey.data(), derKeyLength);
}

hx::ExitGCFreeZone();
hx::Throw(HX_CSTRING("Unsupported public key type in PEM"));
return null();
}
else
{
Expand Down

0 comments on commit 38c8b18

Please sign in to comment.