Created
September 11, 2023 18:43
-
-
Save rfl890/5e2934a5c677d27f8c8c4d6789bf6bcd to your computer and use it in GitHub Desktop.
CNG hash
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <Windows.h> | |
#include <bcrypt.h> | |
#include <ntstatus.h> | |
#include <ntdef.h> | |
typedef struct SHA256State { | |
BCRYPT_ALG_HANDLE algHandle; | |
BCRYPT_HASH_HANDLE hashHandle; | |
DWORD _unused; | |
DWORD hashOutputLength; | |
DWORD hashObjectLength; | |
PBYTE hashObject; | |
} SHA256State; | |
// https://gist.github.com/ian-abbott/732c5b88182a1941a603 | |
DWORD RtlNtStatusToDosError(LONG ntstatus) { | |
DWORD oldError; | |
DWORD result; | |
DWORD br; | |
OVERLAPPED o; | |
o.Internal = ntstatus; | |
o.InternalHigh = 0; | |
o.Offset = 0; | |
o.OffsetHigh = 0; | |
o.hEvent = 0; | |
oldError = GetLastError(); | |
GetOverlappedResult(NULL, &o, &br, FALSE); | |
result = GetLastError(); | |
SetLastError(oldError); | |
return result; | |
} | |
void panicAndPrintError(NTSTATUS status, const char *errorFunction) { | |
DWORD errCode = RtlNtStatusToDosError(status); | |
LPSTR errString = NULL; | |
FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | | |
FORMAT_MESSAGE_IGNORE_INSERTS, | |
NULL, errCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | |
errString, 0, NULL); | |
printf("%s Error %lu: %s\n", errorFunction, errCode, errString); | |
exit(EXIT_FAILURE); | |
} | |
void initHashState(SHA256State *state) { | |
NTSTATUS status = STATUS_UNSUCCESSFUL; | |
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider( | |
&state->algHandle, BCRYPT_SHA256_ALGORITHM, NULL, | |
BCRYPT_HASH_REUSABLE_FLAG))) { | |
panicAndPrintError(status, "BCryptOpenAlgorithmProvider"); | |
} | |
if (!NT_SUCCESS( | |
status = BCryptGetProperty(state->algHandle, BCRYPT_OBJECT_LENGTH, | |
(PBYTE)&state->hashObjectLength, | |
sizeof(DWORD), &state->_unused, 0))) { | |
panicAndPrintError(status, "BCryptGetProperty"); | |
} | |
state->hashObject = malloc(state->hashObjectLength); | |
if (state->hashObject == NULL) { | |
printf("Memory allocation error\n"); | |
exit(EXIT_FAILURE); | |
} | |
if (!NT_SUCCESS(status = BCryptCreateHash( | |
state->algHandle, &state->hashHandle, state->hashObject, | |
state->hashObjectLength, NULL, 0, | |
BCRYPT_HASH_REUSABLE_FLAG))) { | |
panicAndPrintError(status, "BCryptCreateHash"); | |
} | |
if (!NT_SUCCESS(status = | |
BCryptGetProperty(state->algHandle, BCRYPT_HASH_LENGTH, | |
(PBYTE)&state->hashOutputLength, | |
sizeof(DWORD), &state->_unused, 0))) { | |
panicAndPrintError(status, "BCryptGetProperty"); | |
} | |
} | |
void updateHashState(SHA256State *state, void *input, | |
unsigned long inputLength) { | |
NTSTATUS status = STATUS_UNSUCCESSFUL; | |
if (!NT_SUCCESS(status = BCryptHashData(state->hashHandle, (PUCHAR)input, | |
inputLength, 0))) { | |
panicAndPrintError(status, "BCryptHashData"); | |
} | |
} | |
void finishHashState(SHA256State *state, uint8_t *output) { | |
NTSTATUS status = STATUS_UNSUCCESSFUL; | |
if (!NT_SUCCESS(BCryptFinishHash(state->hashHandle, output, | |
state->hashOutputLength, 0))) { | |
panicAndPrintError(status, "BCryptFinishHash"); | |
} | |
} | |
void destroyHashState(SHA256State *state) { | |
if (state->hashObject != NULL) { | |
free(state->hashObject); | |
} | |
if (state->hashHandle != NULL) { | |
BCryptDestroyHash(state->hashHandle); | |
} | |
if (state->algHandle != NULL) { | |
BCryptCloseAlgorithmProvider(state->algHandle, 0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment