-
Notifications
You must be signed in to change notification settings - Fork 229
/
Copy pathHash.cpp
81 lines (64 loc) · 2.1 KB
/
Hash.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//--------------------------------------------------------------------------------------
// Hash.cpp
//
// Advanced Technology Group (ATG)
// Copyright (C) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include "pch.h"
#include "Hash.h"
#include <bcrypt.h>
#ifndef NT_SUCCESS
#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0)
#endif
class ScopedBCrypHashHandle
{
public:
ScopedBCrypHashHandle() : m_handle(nullptr) { }
ScopedBCrypHashHandle(BCRYPT_HASH_HANDLE h) : m_handle(h) { }
~ScopedBCrypHashHandle() { BCryptDestroyHash(m_handle); }
operator BCRYPT_HASH_HANDLE() { return m_handle; }
BCRYPT_HASH_HANDLE* operator&() { return &m_handle; }
private:
BCRYPT_HASH_HANDLE m_handle;
};
HRESULT MD5Checksum(const void* data, size_t byteCount, uint8_t *digest)
{
if (!data || !digest || byteCount == 0)
return E_INVALIDARG;
memset(digest, 0, MD5_DIGEST_LENGTH);
NTSTATUS status;
// Ensure have the MD5 algorithm ready
static BCRYPT_ALG_HANDLE s_algid = 0;
if (!s_algid)
{
status = BCryptOpenAlgorithmProvider(&s_algid, BCRYPT_MD5_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
if (!NT_SUCCESS(status))
{
return HRESULT_FROM_NT(status);
}
DWORD len = 0, res = 0;
status = BCryptGetProperty(s_algid, BCRYPT_HASH_LENGTH, (PBYTE)&len, sizeof(DWORD), &res, 0);
if (!NT_SUCCESS(status) || res != sizeof(DWORD) || len != MD5_DIGEST_LENGTH)
{
return E_FAIL;
}
}
// Create hash object
ScopedBCrypHashHandle hobj;
status = BCryptCreateHash(s_algid, &hobj, nullptr, 0, nullptr, 0, 0);
if (!NT_SUCCESS(status))
{
return HRESULT_FROM_NT(status);
}
status = BCryptHashData(hobj, (PBYTE)data, (ULONG)byteCount, 0);
if (!NT_SUCCESS(status))
{
return HRESULT_FROM_NT(status);
}
status = BCryptFinishHash(hobj, (PBYTE)digest, MD5_DIGEST_LENGTH, 0);
if (!NT_SUCCESS(status))
{
return HRESULT_FROM_NT(status);
}
return S_OK;
}