Skip to content

Instantly share code, notes, and snippets.

@rfl890
Created September 11, 2023 18:43
Show Gist options
  • Save rfl890/5e2934a5c677d27f8c8c4d6789bf6bcd to your computer and use it in GitHub Desktop.
Save rfl890/5e2934a5c677d27f8c8c4d6789bf6bcd to your computer and use it in GitHub Desktop.
CNG hash
#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