static int aes_ctr_init(archive_crypto_ctx *ctx, const uint8_t *key, size_t key_len) { BCRYPT_ALG_HANDLE hAlg; BCRYPT_KEY_HANDLE hKey; DWORD keyObj_len, aes_key_len; PBYTE keyObj; ULONG result; NTSTATUS status; BCRYPT_KEY_LENGTHS_STRUCT key_lengths; ctx->hAlg = NULL; ctx->hKey = NULL; ctx->keyObj = NULL; switch (key_len) { case 16: aes_key_len = 128; break; case 24: aes_key_len = 192; break; case 32: aes_key_len = 256; break; default: return -1; } status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_AES_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); if (!BCRYPT_SUCCESS(status)) return -1; status = BCryptGetProperty(hAlg, BCRYPT_KEY_LENGTHS, (PUCHAR)&key_lengths, sizeof(key_lengths), &result, 0); if (!BCRYPT_SUCCESS(status)) { BCryptCloseAlgorithmProvider(hAlg, 0); return -1; } if (key_lengths.dwMinLength > aes_key_len || key_lengths.dwMaxLength < aes_key_len) { BCryptCloseAlgorithmProvider(hAlg, 0); return -1; } status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&keyObj_len, sizeof(keyObj_len), &result, 0); if (!BCRYPT_SUCCESS(status)) { BCryptCloseAlgorithmProvider(hAlg, 0); return -1; } keyObj = (PBYTE)HeapAlloc(GetProcessHeap(), 0, keyObj_len); if (keyObj == NULL) { BCryptCloseAlgorithmProvider(hAlg, 0); return -1; } status = BCryptSetProperty(hAlg, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0); if (!BCRYPT_SUCCESS(status)) { BCryptCloseAlgorithmProvider(hAlg, 0); HeapFree(GetProcessHeap(), 0, keyObj); return -1; } status = BCryptGenerateSymmetricKey(hAlg, &hKey, keyObj, keyObj_len, (PUCHAR)(uintptr_t)key, (ULONG)key_len, 0); if (!BCRYPT_SUCCESS(status)) { BCryptCloseAlgorithmProvider(hAlg, 0); HeapFree(GetProcessHeap(), 0, keyObj); return -1; } ctx->hAlg = hAlg; ctx->hKey = hKey; ctx->keyObj = keyObj; ctx->keyObj_len = keyObj_len; ctx->encr_pos = AES_BLOCK_SIZE; return 0; }
int _libssh2_wincng_hash_init(_libssh2_wincng_hash_ctx *ctx, BCRYPT_ALG_HANDLE hAlg, unsigned long hashlen, unsigned char *key, unsigned long keylen) { BCRYPT_HASH_HANDLE hHash; unsigned char *pbHashObject; unsigned long dwHashObject, dwHash, cbData; int ret; ret = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (unsigned char *)&dwHash, sizeof(dwHash), &cbData, 0); if ((!BCRYPT_SUCCESS(ret)) || dwHash != hashlen) { return -1; } ret = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (unsigned char *)&dwHashObject, sizeof(dwHashObject), &cbData, 0); if (!BCRYPT_SUCCESS(ret)) { return -1; } pbHashObject = malloc(dwHashObject); if (!pbHashObject) { return -1; } ret = BCryptCreateHash(hAlg, &hHash, pbHashObject, dwHashObject, key, keylen, 0); if (!BCRYPT_SUCCESS(ret)) { free(pbHashObject); return -1; } ctx->hHash = hHash; ctx->pbHashObject = pbHashObject; ctx->dwHashObject = dwHashObject; ctx->cbHash = dwHash; return 0; }
BCryptHashImpl::BCryptHashImpl(LPCWSTR algorithmName, bool isHMAC) : m_algorithmHandle(nullptr), m_hashBufferLength(0), m_hashBuffer(nullptr), m_hashObjectLength(0), m_hashObject(nullptr), m_algorithmMutex() { NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algorithmHandle, algorithmName, MS_PRIMITIVE_PROVIDER, isHMAC ? BCRYPT_ALG_HANDLE_HMAC_FLAG : 0); if (!NT_SUCCESS(status)) { AWS_LOG_ERROR(BCRYPT_LOG_TAG, "Failed initializing BCryptOpenAlgorithmProvider for ", algorithmName); return; } DWORD resultLength = 0; status = BCryptGetProperty(m_algorithmHandle, BCRYPT_HASH_LENGTH, (PBYTE)&m_hashBufferLength, sizeof(m_hashBufferLength), &resultLength, 0); if (!NT_SUCCESS(status) || m_hashBufferLength <= 0) { AWS_LOG_ERROR(BCRYPT_LOG_TAG, "Error computing hash buffer length."); return; } m_hashBuffer = Aws::NewArray<BYTE>(m_hashBufferLength, BCRYPT_LOG_TAG); if (!m_hashBuffer) { AWS_LOG_ERROR(BCRYPT_LOG_TAG, "Error allocating hash buffer."); return; } resultLength = 0; status = BCryptGetProperty(m_algorithmHandle, BCRYPT_OBJECT_LENGTH, (PBYTE)&m_hashObjectLength, sizeof(m_hashObjectLength), &resultLength, 0); if (!NT_SUCCESS(status) || m_hashObjectLength <= 0) { AWS_LOG_ERROR(BCRYPT_LOG_TAG, "Error computing hash object length."); return; } m_hashObject = Aws::NewArray<BYTE>(m_hashObjectLength, BCRYPT_LOG_TAG); if (!m_hashObject) { AWS_LOG_ERROR(BCRYPT_LOG_TAG, "Error allocating hash object."); return; } }
static void _test_hash_length(unsigned line, void *handle, ULONG exlen) { ULONG len = 0xdeadbeef, size = 0xdeadbeef; NTSTATUS status; status = BCryptGetProperty(handle, BCRYPT_HASH_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok_(__FILE__,line)(status == STATUS_SUCCESS, "BCryptGetProperty failed: %08x\n", status); ok_(__FILE__,line)(size == sizeof(len), "got %u\n", size); ok_(__FILE__,line)(len == exlen, "len = %u, expected %u\n", len, exlen); }
static void _test_alg_name(unsigned line, void *handle, const char *exname) { ULONG size = 0xdeadbeef; UCHAR buf[256]; const WCHAR *name = (const WCHAR*)buf; NTSTATUS status; status = BCryptGetProperty(handle, BCRYPT_ALGORITHM_NAME, buf, sizeof(buf), &size, 0); ok_(__FILE__,line)(status == STATUS_SUCCESS, "BCryptGetProperty failed: %08x\n", status); ok_(__FILE__,line)(size == (strlen(exname)+1)*sizeof(WCHAR), "got %u\n", size); ok_(__FILE__,line)(!strcmp_wa(name, exname), "alg name = %s, expected %s\n", wine_dbgstr_w(name), exname); }
NTSTATUS _init() { DWORD cbHashObject; DWORD cbResult; RETURN_IF_NTSTATUS_FAILED_LOG(BCryptOpenAlgorithmProvider(&_hAlg, _algorithm, NULL, 0)); RETURN_IF_NTSTATUS_FAILED_LOG( BCryptGetProperty(_hAlg, BCRYPT_OBJECT_LENGTH, reinterpret_cast<PBYTE>(&cbHashObject), sizeof(DWORD), &cbResult, 0)); _pHashObject = new BYTE[cbHashObject]; if (_pHashObject == nullptr) { RETURN_IF_NTSTATUS_FAILED_MSG(STATUS_NO_MEMORY, "CC_Digest_State Unable to allocate Hash object"); } RETURN_IF_NTSTATUS_FAILED_LOG(BCryptCreateHash(_hAlg, &_hHash, _pHashObject, cbHashObject, NULL, 0, 0)); return 0; }
static int __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) { #pragma GCC diagnostic ignored "-Wcast-qual" BCRYPT_ALG_HANDLE hAlg; BCRYPT_HASH_HANDLE hHash; DWORD hash_len; PBYTE hash; ULONG result; NTSTATUS status; ctx->hAlg = NULL; status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); if (!BCRYPT_SUCCESS(status)) return -1; status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len, sizeof(hash_len), &result, 0); if (!BCRYPT_SUCCESS(status)) { BCryptCloseAlgorithmProvider(hAlg, 0); return -1; } hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len); if (hash == NULL) { BCryptCloseAlgorithmProvider(hAlg, 0); return -1; } status = BCryptCreateHash(hAlg, &hHash, NULL, 0, (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG); if (!BCRYPT_SUCCESS(status)) { BCryptCloseAlgorithmProvider(hAlg, 0); HeapFree(GetProcessHeap(), 0, hash); return -1; } ctx->hAlg = hAlg; ctx->hHash = hHash; ctx->hash_len = hash_len; ctx->hash = hash; return 0; }
static void test_md5(void) { static const char expected[] = "e2a3e68d23ce348b8f68b3079de3d4c9"; static const char expected_hmac[] = "7bda029b93fa8d817fcc9e13d6bdf092"; BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], buf_hmac[1024], md5[16], md5_hmac[16]; ULONG size, len; char str[65]; NTSTATUS ret; alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); len = size = 0xdeadbeef; ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ok(len == 0xdeadbeef, "got %u\n", len); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(len != 0xdeadbeef, "len not set\n"); ok(size == sizeof(len), "got %u\n", size); test_hash_length(alg, 16); test_alg_name(alg, "MD5"); hash = NULL; len = sizeof(buf); ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 16); test_alg_name(hash, "MD5"); memset(md5, 0, sizeof(md5)); ret = BCryptFinishHash(hash, md5, sizeof(md5), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( md5, sizeof(md5), str ); ok(!strcmp(str, expected), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); hash = NULL; len = sizeof(buf_hmac); ret = BCryptCreateHash(alg, &hash, buf_hmac, len, (UCHAR *)"key", sizeof("key"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 16); test_alg_name(hash, "MD5"); memset(md5_hmac, 0, sizeof(md5_hmac)); ret = BCryptFinishHash(hash, md5_hmac, sizeof(md5_hmac), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( md5_hmac, sizeof(md5_hmac), str ); ok(!strcmp(str, expected_hmac), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); }
static void test_sha512(void) { static const char expected[] = "d55ced17163bf5386f2cd9ff21d6fd7fe576a915065c24744d09cfae4ec84ee1e" "f6ef11bfbc5acce3639bab725b50a1fe2c204f8c820d6d7db0df0ecbc49c5ca"; static const char expected_hmac[] = "415fb6b10018ca03b38a1b1399c42ac0be5e8aceddb9a73103f5e543bf2d888f2" "eecf91373941f9315dd730a77937fa92444450fbece86f409d9cb5ec48c6513"; BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], buf_hmac[1024], sha512[64], sha512_hmac[64]; ULONG size, len; char str[129]; NTSTATUS ret; alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA512_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); len = size = 0xdeadbeef; ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ok(len == 0xdeadbeef, "got %u\n", len); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(len != 0xdeadbeef, "len not set\n"); ok(size == sizeof(len), "got %u\n", size); test_hash_length(alg, 64); test_alg_name(alg, "SHA512"); hash = NULL; len = sizeof(buf); ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 64); test_alg_name(hash, "SHA512"); memset(sha512, 0, sizeof(sha512)); ret = BCryptFinishHash(hash, sha512, sizeof(sha512), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( sha512, sizeof(sha512), str ); ok(!strcmp(str, expected), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA512_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); hash = NULL; len = sizeof(buf_hmac); ret = BCryptCreateHash(alg, &hash, buf_hmac, len, (UCHAR *)"key", sizeof("key"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 64); test_alg_name(hash, "SHA512"); memset(sha512_hmac, 0, sizeof(sha512_hmac)); ret = BCryptFinishHash(hash, sha512_hmac, sizeof(sha512_hmac), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( sha512_hmac, sizeof(sha512_hmac), str ); ok(!strcmp(str, expected_hmac), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); }
static void test_sha384(void) { static const char expected[] = "62b21e90c9022b101671ba1f808f8631a8149f0f12904055839a35c1ca78ae5363eed1e743a692d70e0504b0cfd12ef9"; BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], sha384[48]; ULONG size, len; char str[97]; NTSTATUS ret; alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA384_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); len = size = 0xdeadbeef; ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ok(len == 0xdeadbeef, "got %u\n", len); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(len != 0xdeadbeef, "len not set\n"); ok(size == sizeof(len), "got %u\n", size); test_hash_length(alg, 48); test_alg_name(alg, "SHA384"); hash = NULL; len = sizeof(buf); ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 48); test_alg_name(hash, "SHA384"); memset(sha384, 0, sizeof(sha384)); ret = BCryptFinishHash(hash, sha384, sizeof(sha384), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( sha384, sizeof(sha384), str ); ok(!strcmp(str, expected), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); }
NTSTATUS KphHashFile( __in PUNICODE_STRING FileName, __out PVOID *Hash, __out PULONG HashSize ) { NTSTATUS status; BCRYPT_ALG_HANDLE hashAlgHandle = NULL; ULONG querySize; ULONG hashObjectSize; ULONG hashSize; PVOID hashObject = NULL; PVOID hash = NULL; BCRYPT_HASH_HANDLE hashHandle = NULL; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK iosb; HANDLE fileHandle = NULL; FILE_STANDARD_INFORMATION standardInfo; ULONG remainingBytes; ULONG bytesToRead; PVOID buffer = NULL; PAGED_CODE(); // Open the hash algorithm and allocate memory for the hash object. if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hashAlgHandle, KPH_HASH_ALGORITHM, NULL, 0))) goto CleanupExit; if (!NT_SUCCESS(status = BCryptGetProperty(hashAlgHandle, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hashObjectSize, sizeof(ULONG), &querySize, 0))) { goto CleanupExit; } if (!NT_SUCCESS(status = BCryptGetProperty(hashAlgHandle, BCRYPT_HASH_LENGTH, (PUCHAR)&hashSize, sizeof(ULONG), &querySize, 0))) { goto CleanupExit; } if (!(hashObject = ExAllocatePoolWithTag(PagedPool, hashObjectSize, 'vhpK'))) { status = STATUS_INSUFFICIENT_RESOURCES; goto CleanupExit; } if (!(hash = ExAllocatePoolWithTag(PagedPool, hashSize, 'vhpK'))) { status = STATUS_INSUFFICIENT_RESOURCES; goto CleanupExit; } if (!NT_SUCCESS(status = BCryptCreateHash(hashAlgHandle, &hashHandle, hashObject, hashObjectSize, NULL, 0, 0))) { goto CleanupExit; } // Open the file and compute the hash. InitializeObjectAttributes(&objectAttributes, FileName, OBJ_KERNEL_HANDLE, NULL, NULL); if (!NT_SUCCESS(status = ZwCreateFile(&fileHandle, FILE_GENERIC_READ, &objectAttributes, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0))) { goto CleanupExit; } if (!NT_SUCCESS(status = ZwQueryInformationFile(fileHandle, &iosb, &standardInfo, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation))) { goto CleanupExit; } if (standardInfo.EndOfFile.QuadPart <= 0) { status = STATUS_UNSUCCESSFUL; goto CleanupExit; } if (standardInfo.EndOfFile.QuadPart > FILE_MAX_SIZE) { status = STATUS_FILE_TOO_LARGE; goto CleanupExit; } if (!(buffer = ExAllocatePoolWithTag(PagedPool, FILE_BUFFER_SIZE, 'vhpK'))) { status = STATUS_INSUFFICIENT_RESOURCES; goto CleanupExit; } remainingBytes = (ULONG)standardInfo.EndOfFile.QuadPart; while (remainingBytes != 0) { bytesToRead = FILE_BUFFER_SIZE; if (bytesToRead > remainingBytes) bytesToRead = remainingBytes; if (!NT_SUCCESS(status = ZwReadFile(fileHandle, NULL, NULL, NULL, &iosb, buffer, bytesToRead, NULL, NULL))) { goto CleanupExit; } if ((ULONG)iosb.Information != bytesToRead) { status = STATUS_INTERNAL_ERROR; goto CleanupExit; } if (!NT_SUCCESS(status = BCryptHashData(hashHandle, buffer, bytesToRead, 0))) goto CleanupExit; remainingBytes -= bytesToRead; } if (!NT_SUCCESS(status = BCryptFinishHash(hashHandle, hash, hashSize, 0))) goto CleanupExit; if (NT_SUCCESS(status)) { *Hash = hash; *HashSize = hashSize; hash = NULL; // Don't free this in the cleanup section } CleanupExit: if (buffer) ExFreePoolWithTag(buffer, 'vhpK'); if (fileHandle) ZwClose(fileHandle); if (hashHandle) BCryptDestroyHash(hashHandle); if (hash) ExFreePoolWithTag(hash, 'vhpK'); if (hashObject) ExFreePoolWithTag(hashObject, 'vhpK'); if (hashAlgHandle) BCryptCloseAlgorithmProvider(hashAlgHandle, 0); return status; }
bool _mongoc_crypto_cng_hmac_or_hash (BCRYPT_ALG_HANDLE algorithm, void *key, size_t key_length, void *data, size_t data_length, void *output) { char *hash_object_buffer = 0; ULONG hash_object_length = 0; BCRYPT_HASH_HANDLE hash = 0; ULONG mac_length = 0; NTSTATUS status = STATUS_UNSUCCESSFUL; bool retval = false; ULONG noop = 0; status = BCryptGetProperty (algorithm, BCRYPT_OBJECT_LENGTH, (char *) &hash_object_length, sizeof hash_object_length, &noop, 0); if (!NT_SUCCESS (status)) { MONGOC_ERROR ("BCryptGetProperty(): OBJECT_LENGTH %x", status); return false; } status = BCryptGetProperty (algorithm, BCRYPT_HASH_LENGTH, (char *) &mac_length, sizeof mac_length, &noop, 0); if (!NT_SUCCESS (status)) { MONGOC_ERROR ("BCryptGetProperty(): HASH_LENGTH %x", status); return false; } hash_object_buffer = bson_malloc (hash_object_length); status = BCryptCreateHash (algorithm, &hash, hash_object_buffer, hash_object_length, key, (ULONG) key_length, 0); if (!NT_SUCCESS (status)) { MONGOC_ERROR ("BCryptCreateHash(): %x", status); goto cleanup; } status = BCryptHashData (hash, data, (ULONG) data_length, 0); if (!NT_SUCCESS (status)) { MONGOC_ERROR ("BCryptHashData(): %x", status); goto cleanup; } status = BCryptFinishHash (hash, output, mac_length, 0); if (!NT_SUCCESS (status)) { MONGOC_ERROR ("BCryptFinishHash(): %x", status); goto cleanup; } retval = true; cleanup: if (hash) { (void) BCryptDestroyHash (hash); } bson_free (hash_object_buffer); return retval; }
int _libssh2_wincng_cipher_init(_libssh2_cipher_ctx *ctx, _libssh2_cipher_type(type), unsigned char *iv, unsigned char *secret, int encrypt) { BCRYPT_KEY_HANDLE hKey; BCRYPT_KEY_DATA_BLOB_HEADER *header; unsigned char *pbKeyObject, *pbIV, *key; unsigned long dwKeyObject, dwIV, dwBlockLength, cbData, keylen; int ret; (void)encrypt; ret = BCryptGetProperty(*type.phAlg, BCRYPT_OBJECT_LENGTH, (unsigned char *)&dwKeyObject, sizeof(dwKeyObject), &cbData, 0); if (!BCRYPT_SUCCESS(ret)) { return -1; } ret = BCryptGetProperty(*type.phAlg, BCRYPT_BLOCK_LENGTH, (unsigned char *)&dwBlockLength, sizeof(dwBlockLength), &cbData, 0); if (!BCRYPT_SUCCESS(ret)) { return -1; } pbKeyObject = malloc(dwKeyObject); if (!pbKeyObject) { return -1; } keylen = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + type.dwKeyLength; key = malloc(keylen); if (!key) { free(pbKeyObject); return -1; } header = (BCRYPT_KEY_DATA_BLOB_HEADER *)key; header->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC; header->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1; header->cbKeyData = type.dwKeyLength; memcpy(key + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER), secret, type.dwKeyLength); ret = BCryptImportKey(*type.phAlg, NULL, BCRYPT_KEY_DATA_BLOB, &hKey, pbKeyObject, dwKeyObject, key, keylen, 0); free(key); if (!BCRYPT_SUCCESS(ret)) { free(pbKeyObject); return -1; } if (type.dwUseIV) { pbIV = malloc(dwBlockLength); if (!pbIV) { BCryptDestroyKey(hKey); free(pbKeyObject); return -1; } dwIV = dwBlockLength; memcpy(pbIV, iv, dwIV); } else { pbIV = NULL; dwIV = 0; } ctx->hKey = hKey; ctx->pbKeyObject = pbKeyObject; ctx->pbIV = pbIV; ctx->dwKeyObject = dwKeyObject; ctx->dwIV = dwIV; ctx->dwBlockLength = dwBlockLength; return 0; }
// // Generate MD5 hash from the given string // std::wstring FlickrUploader::CalculateMD5Hash(const std::wstring& buffer) { #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) // Convert wstring to string std::string byteString(buffer.begin(), buffer.end()); // Open an algorithm handle BCRYPT_ALG_HANDLE algorithm = nullptr; NTSTATUS status = BCryptOpenAlgorithmProvider(&algorithm, BCRYPT_MD5_ALGORITHM, nullptr, 0); // Calculate the size of the buffer to hold the hash object unsigned long dataSize = 0; unsigned long hashObjectSize = 0; if (NT_SUCCESS(status)) { status = BCryptGetProperty(algorithm, BCRYPT_OBJECT_LENGTH, (unsigned char*)&hashObjectSize, sizeof(unsigned long), &dataSize, 0); } // Allocate the hash object on the heap unsigned char* hashObject = nullptr; if (NT_SUCCESS(status)) { hashObject = (unsigned char*) HeapAlloc(GetProcessHeap (), 0, hashObjectSize); if (nullptr == hashObject) { status = STATUS_UNSUCCESSFUL; } } // Calculate the length of the hash unsigned long hashSize = 0; if (NT_SUCCESS(status)) { status = BCryptGetProperty(algorithm, BCRYPT_HASH_LENGTH, (unsigned char*)&hashSize, sizeof(unsigned long), &dataSize, 0); } // Allocate the hash buffer on the heap unsigned char* hash = nullptr; if (NT_SUCCESS(status)) { hash = (unsigned char*)HeapAlloc (GetProcessHeap(), 0, hashSize); if (nullptr == hash) { status = STATUS_UNSUCCESSFUL; } } // Create a hash BCRYPT_HASH_HANDLE cryptHash = nullptr; if (NT_SUCCESS(status)) { status = BCryptCreateHash(algorithm, &cryptHash, hashObject, hashObjectSize, nullptr, 0, 0); } // Hash data if (NT_SUCCESS(status)) { status = BCryptHashData(cryptHash, (unsigned char*)byteString.c_str(), static_cast<unsigned long>(byteString.length()), 0); } // Close the hash and get hash data if (NT_SUCCESS(status)) { status = BCryptFinishHash(cryptHash, hash, hashSize, 0); } std::wstring resultString; // If no issues, then copy the bytes to the output string if (NT_SUCCESS(status)) { std::wostringstream hexString; for (unsigned short i = 0; i < hashSize; i++) { hexString << std::setfill(L'0') << std::setw(2) << std::hex << hash[i]; } resultString = hexString.str(); } // Cleanup if(algorithm) { BCryptCloseAlgorithmProvider(algorithm, 0); } if (cryptHash) { BCryptDestroyHash(cryptHash); } if(hashObject) { HeapFree(GetProcessHeap(), 0, hashObject); } if(hash) { HeapFree(GetProcessHeap(), 0, hash); } return resultString; }
static void test_sha1(void) { static const char expected[] = "961fa64958818f767707072755d7018dcd278e94"; BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], sha1[20]; ULONG size, len; char str[41]; NTSTATUS ret; alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA1_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); len = size = 0xdeadbeef; ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ok(len == 0xdeadbeef, "got %u\n", len); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(len != 0xdeadbeef, "len not set\n"); ok(size == sizeof(len), "got %u\n", size); test_hash_length(alg, 20); test_alg_name(alg, "SHA1"); hash = NULL; len = sizeof(buf); ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 20); test_alg_name(hash, "SHA1"); memset(sha1, 0, sizeof(sha1)); ret = BCryptFinishHash(hash, sha1, sizeof(sha1), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( sha1, sizeof(sha1), str ); ok(!strcmp(str, expected), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); }
static void test_sha256(void) { static const char expected[] = "ceb73749c899693706ede1e30c9929b3fd5dd926163831c2fb8bd41e6efb1126"; BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], sha256[32]; ULONG size, len; char str[65]; NTSTATUS ret; alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA256_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); len = size = 0xdeadbeef; ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ok(len == 0xdeadbeef, "got %u\n", len); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(len != 0xdeadbeef, "len not set\n"); ok(size == sizeof(len), "got %u\n", size); test_hash_length(alg, 32); test_alg_name(alg, "SHA256"); hash = NULL; len = sizeof(buf); ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 32); test_alg_name(hash, "SHA256"); memset(sha256, 0, sizeof(sha256)); ret = BCryptFinishHash(hash, sha256, sizeof(sha256), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( sha256, sizeof(sha256), str ); ok(!strcmp(str, expected), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); }
static int xmlSecMSCngSignatureExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { xmlSecMSCngSignatureCtxPtr ctx; xmlSecSize inSize; xmlSecSize outSize; NTSTATUS status; DWORD cbData = 0; DWORD cbHashObject = 0; int ret; xmlSecAssert2(xmlSecMSCngSignatureCheckId(transform), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecMSCngSignatureSize), -1); xmlSecAssert2(transformCtx != NULL, -1); ctx = xmlSecMSCngSignatureGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->pszHashAlgId != NULL, -1); inSize = xmlSecBufferGetSize(&transform->inBuf); outSize = xmlSecBufferGetSize(&transform->outBuf); if(transform->status == xmlSecTransformStatusNone) { xmlSecAssert2(outSize == 0, -1); /* open an algorithm handle */ status = BCryptOpenAlgorithmProvider( &ctx->hHashAlg, ctx->pszHashAlgId, NULL, 0); if(status != STATUS_SUCCESS) { xmlSecMSCngNtError("BCryptOpenAlgorithmProvider", xmlSecTransformGetName(transform), status); return(-1); } /* calculate the size of the buffer to hold the hash object */ status = BCryptGetProperty( ctx->hHashAlg, BCRYPT_OBJECT_LENGTH, (PBYTE)&cbHashObject, sizeof(DWORD), &cbData, 0); if(status != STATUS_SUCCESS) { xmlSecMSCngNtError("BCryptGetProperty", xmlSecTransformGetName(transform), status); return(-1); } /* allocate the hash object on the heap */ ctx->pbHashObject = (PBYTE)xmlMalloc(cbHashObject); if(ctx->pbHashObject == NULL) { xmlSecMallocError(cbHashObject, NULL); return(-1); } /* calculate the length of the hash */ status = BCryptGetProperty( ctx->hHashAlg, BCRYPT_HASH_LENGTH, (PBYTE)&ctx->cbHash, sizeof(DWORD), &cbData, 0); if(status != STATUS_SUCCESS) { xmlSecMSCngNtError("BCryptGetProperty", xmlSecTransformGetName(transform), status); return(-1); } /* allocate the hash buffer on the heap */ ctx->pbHash = (PBYTE)xmlMalloc(ctx->cbHash); if(ctx->pbHash == NULL) { xmlSecMallocError(ctx->cbHash, NULL); return(-1); } /* create the hash */ status = BCryptCreateHash( ctx->hHashAlg, &ctx->hHash, ctx->pbHashObject, cbHashObject, NULL, 0, 0); if(status != STATUS_SUCCESS) { xmlSecMSCngNtError("BCryptCreateHash", xmlSecTransformGetName(transform), status); return(-1); } transform->status = xmlSecTransformStatusWorking; } if((transform->status == xmlSecTransformStatusWorking)) { if(inSize > 0) { xmlSecAssert2(outSize == 0, -1); /* hash some data */ status = BCryptHashData( ctx->hHash, (PBYTE)xmlSecBufferGetData(&transform->inBuf), inSize, 0); if(status != STATUS_SUCCESS) { xmlSecMSCngNtError("BCryptHashData", xmlSecTransformGetName(transform), status); return(-1); } ret = xmlSecBufferRemoveHead(&transform->inBuf, inSize); if(ret < 0) { xmlSecInternalError("xmlSecBufferRemoveHead", xmlSecTransformGetName(transform)); return(-1); } } if(last != 0) { /* close the hash */ status = BCryptFinishHash( ctx->hHash, ctx->pbHash, ctx->cbHash, 0); if(status != STATUS_SUCCESS) { xmlSecMSCngNtError("BCryptFinishHash", xmlSecTransformGetName(transform), status); return(-1); } xmlSecAssert2(ctx->cbHash > 0, -1); if(transform->operation == xmlSecTransformOperationSign) { xmlSecNotImplementedError(NULL); return(-1); } transform->status = xmlSecTransformStatusFinished; } } if((transform->status == xmlSecTransformStatusWorking) || (transform->status == xmlSecTransformStatusFinished)) { xmlSecAssert2(xmlSecBufferGetSize(&transform->inBuf) == 0, -1); } else { xmlSecInvalidTransfromStatusError(transform); return(-1); } return(0); }
static void test_sha512(void) { static const char expected[] = "d55ced17163bf5386f2cd9ff21d6fd7fe576a915065c24744d09cfae4ec84ee1e" "f6ef11bfbc5acce3639bab725b50a1fe2c204f8c820d6d7db0df0ecbc49c5ca"; BCRYPT_ALG_HANDLE alg; BCRYPT_HASH_HANDLE hash; UCHAR buf[512], sha512[64]; ULONG size, len; char str[129]; NTSTATUS ret; alg = NULL; ret = BCryptOpenAlgorithmProvider(&alg, BCRYPT_SHA512_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(alg != NULL, "alg not set\n"); len = size = 0xdeadbeef; ret = BCryptGetProperty(NULL, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_HANDLE, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, NULL, (UCHAR *)&len, sizeof(len), &size, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, sizeof(len), NULL, 0); ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, NULL, sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len, 0, &size, 0); ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret); ok(len == 0xdeadbeef, "got %u\n", len); ok(size == sizeof(len), "got %u\n", size); len = size = 0xdeadbeef; ret = BCryptGetProperty(alg, BCRYPT_OBJECT_LENGTH, (UCHAR *)&len , sizeof(len), &size, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(len != 0xdeadbeef, "len not set\n"); ok(size == sizeof(len), "got %u\n", size); test_hash_length(alg, 64); test_alg_name(alg, "SHA512"); hash = NULL; len = sizeof(buf); ret = BCryptCreateHash(alg, &hash, buf, len, NULL, 0, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(hash != NULL, "hash not set\n"); ret = BCryptHashData(hash, (UCHAR *)"test", sizeof("test"), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); test_hash_length(hash, 64); test_alg_name(hash, "SHA512"); memset(sha512, 0, sizeof(sha512)); ret = BCryptFinishHash(hash, sha512, sizeof(sha512), 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); format_hash( sha512, sizeof(sha512), str ); ok(!strcmp(str, expected), "got %s\n", str); ret = BCryptDestroyHash(hash); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ret = BCryptCloseAlgorithmProvider(alg, 0); ok(ret == STATUS_SUCCESS, "got %08x\n", ret); }
bool aes_decrypt_check(m0_kdbx_header_entry_t *hdr, uint8_t *masterkey, m0_kdbx_payload_t *payload) { bool res = false; BCRYPT_ALG_HANDLE aes = NULL; BCRYPT_KEY_HANDLE ctx = NULL; NTSTATUS status = 0; DWORD len_ciphertext = 0, tmp_len = 0, key_objectlen = 0; PBYTE key_object = NULL; uint8_t plaintext[32] = {0}; uint8_t iv[256] = {0}; uint8_t ivlen = hdr[ENCRYPTIONIV].len & 0xFF; // we need to create a local copy of IV, as it is modified during decryption. memcpy(&iv, hdr[ENCRYPTIONIV].data, ivlen); // Open an algorithm handle. status = BCryptOpenAlgorithmProvider( &aes, BCRYPT_AES_ALGORITHM, NULL, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); goto cleanup; } // Calculate the size of the buffer to hold the Key Object. status = BCryptGetProperty( aes, BCRYPT_OBJECT_LENGTH, (PBYTE)&key_objectlen, sizeof(DWORD), &tmp_len, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptGetProperty\n", status); goto cleanup; } // We should use preallocated memory for better performance... key_object = (PBYTE)HeapAlloc(GetProcessHeap(), 0, key_objectlen); if(NULL == key_object) { printf("[!] memory allocation failed\n"); goto cleanup; } status = BCryptSetProperty( aes, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptSetProperty\n", status); goto cleanup; } // Generate the key from supplied input key bytes. status = BCryptGenerateSymmetricKey( aes, &ctx, key_object, key_objectlen, masterkey, 32, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptGenerateSymmetricKey\n", status); goto cleanup; } status = BCryptDecrypt( ctx, payload->encrypted, hdr[STREAMSTARTBYTES].len, NULL, iv, ivlen, plaintext, sizeof(plaintext), &tmp_len, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptDecrypt\n", status); goto cleanup; } // success! if (0 == memcmp(plaintext, hdr[STREAMSTARTBYTES].data, hdr[STREAMSTARTBYTES].len)) { res = true; payload->decrypted = malloc(hdr[STREAMSTARTBYTES].len); memcpy(payload->decrypted, plaintext, hdr[STREAMSTARTBYTES].len); } cleanup: if(aes) { BCryptCloseAlgorithmProvider(aes,0); } if (ctx) { BCryptDestroyKey(ctx); } if(key_object) { HeapFree(GetProcessHeap(), 0, key_object); } return res; }
int aes_transformkey(m0_kdbx_header_entry_t *hdr, uint8_t *tkey, size_t tkeylen) { BCRYPT_ALG_HANDLE aes = NULL; BCRYPT_KEY_HANDLE key = NULL; NTSTATUS status = 0; DWORD len_ciphertext = 0, tmp_len = 0, key_objectlen = 0; PBYTE key_object = NULL; uint64_t rounds = 0; // Open an algorithm handle. status = BCryptOpenAlgorithmProvider( &aes, BCRYPT_AES_ALGORITHM, NULL, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptOpenAlgorithmProvider\n", status); goto cleanup; } // Calculate the size of the buffer to hold the KeyObject. status = BCryptGetProperty( aes, BCRYPT_OBJECT_LENGTH, (PBYTE)&key_objectlen, sizeof(DWORD), &tmp_len, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptGetProperty\n", status); goto cleanup; } // Allocate the key object on the heap. key_object = (PBYTE)HeapAlloc(GetProcessHeap(), 0, key_objectlen); if(NULL == key_object) { printf("[!] memory allocation failed\n"); goto cleanup; } status = BCryptSetProperty( aes, BCRYPT_CHAINING_MODE, (PBYTE)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptSetProperty\n", status); goto cleanup; } // Generate the key from supplied input key bytes. status = BCryptGenerateSymmetricKey( aes, &key, key_object, key_objectlen, hdr[TRANSFORMSEED].data, hdr[TRANSFORMSEED].len, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptGenerateSymmetricKey\n", status); goto cleanup; } status = BCryptEncrypt( key, tkey, tkeylen, NULL, NULL, 0, NULL, 0, &len_ciphertext, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptEncrypt (calculate)\n", status); goto cleanup; } for(rounds = 0; rounds < hdr[TRANSFORMROUNDS].qw; rounds++) { status = BCryptEncrypt( key, tkey, tkeylen, NULL, NULL, 0, tkey, tkeylen, &tmp_len, 0); if(!NT_SUCCESS(status)) { printf("[!] Error 0x%x returned by BCryptEncrypt (encrypt)\n", status); goto cleanup; } } cleanup: if(aes) { BCryptCloseAlgorithmProvider(aes,0); } if (key) { BCryptDestroyKey(key); } if(key_object) { HeapFree(GetProcessHeap(), 0, key_object); } return status; }
UINT SfDecryptPayload( LPWSTR lpParameter ) { BOOL cond = FALSE, bSuccess = FALSE; PBYTE cng_object, hashdata, decrypted, enc_data, extracted; ULONG obj_sz, rlen, hdatasz, enc_data_size; BCRYPT_ALG_HANDLE h_alg = NULL; BCRYPT_HASH_HANDLE h_hash = NULL; BCRYPT_KEY_HANDLE h_rc4key = NULL; NTSTATUS status; HANDLE pheap = NULL; PIMAGE_FILE_HEADER fheader; PVOID pdll = NULL; WCHAR InputFile[MAX_PATH + 1], OutputFile[MAX_PATH + 1]; rlen = 0; RtlSecureZeroMemory(InputFile, sizeof(InputFile)); GetCommandLineParam(lpParameter, 1, InputFile, MAX_PATH, &rlen); if (rlen == 0) { SfcuiPrintText(g_ConOut, T_SFDECRYPTUSAGE, g_ConsoleOutput, FALSE); return (UINT)-1; } do { rlen = 0; GetCommandLineParam(lpParameter, 2, OutputFile, MAX_PATH, &rlen); if (rlen == 0) _strcpy(OutputFile, TEXT("out.bin")); pdll = SfuCreateFileMappingNoExec(InputFile); if (pdll == NULL) break; enc_data_size = 0; enc_data = SfuQueryResourceData(2, pdll, &enc_data_size); if (enc_data == NULL) break; fheader = &(RtlImageNtHeader(pdll)->FileHeader); status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_MD5_ALGORITHM, NULL, 0); if (!NT_SUCCESS(status)) break; obj_sz = 0; rlen = 0; status = BCryptGetProperty(h_alg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&obj_sz, sizeof(obj_sz), &rlen, 0); if (!NT_SUCCESS(status)) break; hdatasz = 0; rlen = 0; status = BCryptGetProperty(h_alg, BCRYPT_HASH_LENGTH, (PUCHAR)&hdatasz, sizeof(hdatasz), &rlen, 0); if (!NT_SUCCESS(status)) break; pheap = HeapCreate(0, 0, 0); if (pheap == NULL) break; cng_object = HeapAlloc(pheap, HEAP_ZERO_MEMORY, obj_sz); if (cng_object == NULL) break; hashdata = HeapAlloc(pheap, HEAP_ZERO_MEMORY, hdatasz); if (hashdata == NULL) break; status = BCryptCreateHash(h_alg, &h_hash, cng_object, obj_sz, NULL, 0, 0); if (!NT_SUCCESS(status)) break; status = BCryptHashData(h_hash, (PUCHAR)fheader, sizeof(IMAGE_FILE_HEADER), 0); if (!NT_SUCCESS(status)) break; status = BCryptFinishHash(h_hash, hashdata, hdatasz, 0); if (!NT_SUCCESS(status)) break; BCryptDestroyHash(h_hash); BCryptCloseAlgorithmProvider(h_alg, 0); HeapFree(pheap, 0, cng_object); h_alg = NULL; h_hash = NULL; status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_RC4_ALGORITHM, NULL, 0); if (!NT_SUCCESS(status)) break; obj_sz = 0; rlen = 0; status = BCryptGetProperty(h_alg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&obj_sz, sizeof(obj_sz), &rlen, 0); if (!NT_SUCCESS(status)) break; cng_object = HeapAlloc(pheap, HEAP_ZERO_MEMORY, obj_sz); if (cng_object == NULL) break; status = BCryptGenerateSymmetricKey(h_alg, &h_rc4key, cng_object, obj_sz, hashdata, hdatasz, 0); if (!NT_SUCCESS(status)) break; decrypted = HeapAlloc(pheap, HEAP_ZERO_MEMORY, enc_data_size); if (decrypted == NULL) break; rlen = 0; status = BCryptEncrypt(h_rc4key, enc_data, enc_data_size, NULL, NULL, 0, decrypted, enc_data_size, &rlen, 0); if (!NT_SUCCESS(status)) break; bSuccess = FALSE; enc_data_size = rlen; rlen = 0; extracted = SfcabExtractMemory(decrypted, enc_data_size, &rlen); if (extracted) { if (SfuWriteBufferToFile(OutputFile, extracted, rlen, FALSE, FALSE) == rlen) { bSuccess = TRUE; } LocalFree(extracted); } else { //failed to extract, drop cab as is if (SfuWriteBufferToFile(OutputFile, decrypted, enc_data_size, FALSE, FALSE) == enc_data_size) { bSuccess = TRUE; } } if (bSuccess) { SfcuiPrintText(g_ConOut, T_SFDECRYPTED, g_ConsoleOutput, FALSE); SfcuiPrintText(g_ConOut, OutputFile, g_ConsoleOutput, FALSE); } } while (cond); if (bSuccess == FALSE) { SfcuiPrintText(g_ConOut, T_SFDECRYPTFAIL, g_ConsoleOutput, FALSE); } if (h_rc4key != NULL) BCryptDestroyKey(h_rc4key); if (h_hash != NULL) BCryptDestroyHash(h_hash); if (h_alg != NULL) BCryptCloseAlgorithmProvider(h_alg, 0); if (pheap != NULL) HeapDestroy(pheap); if (pdll != 0) NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)pdll); return 0; }