diff --git a/src/hx/libs/ssl/windows/Cng.h b/src/hx/libs/ssl/windows/Cng.h index 21c485826..c912ab7a1 100644 --- a/src/hx/libs/ssl/windows/Cng.h +++ b/src/hx/libs/ssl/windows/Cng.h @@ -14,8 +14,6 @@ namespace hx { BCRYPT_HANDLE handle; - virtual ~CngObject() = 0; - CngObject(BCRYPT_HANDLE inHandle) : handle(inHandle) {} template @@ -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(); } }; @@ -124,11 +132,11 @@ 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); @@ -136,13 +144,13 @@ namespace hx std::unique_ptr hash() const { - hx::EnterGCFreeZone(); - auto result = DWORD{ 0 }; auto hHash = BCRYPT_HASH_HANDLE(); auto object = std::make_unique>(getProperty(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)); @@ -153,14 +161,14 @@ namespace hx return std::make_unique(hHash, std::move(object)); } - static std::unique_ptr create(const wchar_t* algId) + static std::unique_ptr 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)); @@ -168,7 +176,7 @@ namespace hx hx::ExitGCFreeZone(); - return std::make_unique(handle); + return std::make_unique(handle, flags); } }; } diff --git a/src/hx/libs/ssl/windows/Digest.cpp b/src/hx/libs/ssl/windows/Digest.cpp index c08ec09f5..9f7e8066a 100644 --- a/src/hx/libs/ssl/windows/Digest.cpp +++ b/src/hx/libs/ssl/windows/Digest.cpp @@ -8,7 +8,7 @@ Array _hx_ssl_dgst_make(Array 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); @@ -22,7 +22,7 @@ Array _hx_ssl_dgst_sign(Array buffer, Dynamic hpke auto key = hpkey.Cast(); 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(hash->getProperty(BCRYPT_HASH_LENGTH)); @@ -61,7 +61,7 @@ bool _hx_ssl_dgst_verify(Array buffer, Array sign, auto key = hpkey.Cast(); 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(hash->getProperty(BCRYPT_HASH_LENGTH)); diff --git a/src/hx/libs/ssl/windows/Key.cpp b/src/hx/libs/ssl/windows/Key.cpp index f3137d8da..df338b391 100644 --- a/src/hx/libs/ssl/windows/Key.cpp +++ b/src/hx/libs/ssl/windows/Key.cpp @@ -4,7 +4,7 @@ #include #include "SSL.h" -#include "Utils.h" +#include "Cng.h" namespace { @@ -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(&objectLength), sizeof(DWORD), &cb, 0))) - { - BCryptCloseAlgorithmProvider(md5, 0); - - hx::ExitGCFreeZone(); - hx::Throw(HX_CSTRING("Failure")); - } - - auto object = std::vector(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(); + auto md5 = hx::ssl::windows::CngAlgorithm::create(BCRYPT_MD5_ALGORITHM, BCRYPT_HASH_REUSABLE_FLAG); + auto hash = md5->hash(); + auto concat = std::vector(); + auto digest = std::vector(hash->getProperty(BCRYPT_HASH_LENGTH)); hx::strbuf passbuffer; @@ -142,115 +121,35 @@ namespace { if (!concat.empty()) { - if (!BCRYPT_SUCCESS(result = BCryptHashData(hash, reinterpret_cast(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(const_cast(password)), passlength, 0))) - { - BCryptDestroyHash(hash); - BCryptCloseAlgorithmProvider(md5, 0); - - hx::ExitGCFreeZone(); - hx::Throw(HX_CSTRING("Failure")); - } - if (!BCRYPT_SUCCESS(result = BCryptHashData(hash, reinterpret_cast(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(&hashLength), sizeof(DWORD), &cb, 0))) - { - BCryptDestroyHash(hash); - BCryptCloseAlgorithmProvider(md5, 0); - - hx::ExitGCFreeZone(); - hx::Throw(HX_CSTRING("Failure")); - } - - auto digest = std::vector(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(const_cast(password)), passlength); + hash->hash(reinterpret_cast(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(&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(BCRYPT_CHAIN_MODE_CBC), wcslen(BCRYPT_CHAIN_MODE_CBC)); - auto aeskey = std::vector(size); + auto aeskey = std::vector(aes->getProperty(BCRYPT_OBJECT_LENGTH)); - auto blockLength = DWORD{ 0 }; - if (!BCRYPT_SUCCESS(result = BCryptGetProperty(aes, BCRYPT_BLOCK_LENGTH, reinterpret_cast(&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(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(); @@ -260,18 +159,12 @@ namespace auto decrypted = std::vector(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()); @@ -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 {