diff --git a/Sandboxie/common/verify.c b/Sandboxie/common/verify.c
index 11acf8f3..8dd4ee02 100644
--- a/Sandboxie/common/verify.c
+++ b/Sandboxie/common/verify.c
@@ -1,3 +1,21 @@
+/*
+ * Copyright 2021 David Xanatos, xanasoft.com
+ *
+ * Based on the processhacker's CustomSignTool, Copyright 2016 wj32
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
#include
#define WIN32_NO_STATUS
@@ -36,7 +54,7 @@ static UCHAR KphpTrustedPublicKey[] =
#define FILE_BUFFER_SIZE 4096
-NTSTATUS PhCreateFileWin32(_Out_ PHANDLE FileHandle, _In_ PCWSTR FileName, _In_ ACCESS_MASK DesiredAccess,
+static NTSTATUS MyCreateFile(_Out_ PHANDLE FileHandle, _In_ PCWSTR FileName, _In_ ACCESS_MASK DesiredAccess,
_In_opt_ ULONG FileAttributes, _In_ ULONG ShareAccess, _In_ ULONG CreateDisposition, _In_ ULONG CreateOptions)
{
UNICODE_STRING uni;
@@ -50,14 +68,6 @@ NTSTATUS PhCreateFileWin32(_Out_ PHANDLE FileHandle, _In_ PCWSTR FileName, _In_
return NtCreateFile(FileHandle, DesiredAccess, &attr, &Iosb, NULL, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, NULL, 0);
}
-NTSTATUS PhGetFileSize(_In_ HANDLE FileHandle, _Out_ PLARGE_INTEGER Size)
-{
- if (GetFileSizeEx(FileHandle, Size))
- return STATUS_SUCCESS;
- return STATUS_UNSUCCESSFUL;
-}
-
-
static NTSTATUS CstReadFile(
_In_ PWSTR FileName,
_In_ ULONG FileSizeLimit,
@@ -71,13 +81,10 @@ static NTSTATUS CstReadFile(
PVOID buffer;
IO_STATUS_BLOCK iosb;
- if (!NT_SUCCESS(status = PhCreateFileWin32(&fileHandle, FileName, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE)))
+ if (!NT_SUCCESS(status = MyCreateFile(&fileHandle, FileName, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE)))
goto CleanupExit;
- if (!NT_SUCCESS(status = PhGetFileSize(fileHandle, &fileSize)))
- goto CleanupExit;
-
- if (fileSize.QuadPart > FileSizeLimit)
+ if (!GetFileSizeEx(fileHandle, &fileSize) || fileSize.QuadPart > FileSizeLimit)
goto CleanupExit;
buffer = malloc((ULONG)fileSize.QuadPart);
@@ -95,89 +102,79 @@ CleanupExit:
}
typedef struct {
- BCRYPT_ALG_HANDLE hashAlgHandle;
- ULONG hashObjectSize;
- ULONG hashSize;
- PVOID hashObject;
- BCRYPT_HASH_HANDLE hashHandle;
-
-} CST_HASH_OBJ;
+ BCRYPT_ALG_HANDLE algHandle;
+ BCRYPT_HASH_HANDLE handle;
+ PVOID object;
+} MY_HASH_OBJ;
-static VOID CstFreeHash(CST_HASH_OBJ* pHashObj)
+static VOID MyFreeHash(MY_HASH_OBJ* pHashObj)
{
- if (pHashObj->hashHandle)
- BCryptDestroyHash(pHashObj->hashHandle);
- if (pHashObj->hashObject)
- free(pHashObj->hashObject); // must be freed after destroying hash object
- if (pHashObj->hashAlgHandle)
- BCryptCloseAlgorithmProvider(pHashObj->hashAlgHandle, 0);
+ if (pHashObj->handle)
+ BCryptDestroyHash(pHashObj->handle);
+ if (pHashObj->object)
+ free(pHashObj->object);
+ if (pHashObj->algHandle)
+ BCryptCloseAlgorithmProvider(pHashObj->algHandle, 0);
}
-static NTSTATUS CstInitHash(CST_HASH_OBJ* pHashObj)
+static NTSTATUS MyInitHash(MY_HASH_OBJ* pHashObj)
{
NTSTATUS status;
+ ULONG hashObjectSize;
ULONG querySize;
- memset(pHashObj, 0, sizeof(CST_HASH_OBJ));
+ memset(pHashObj, 0, sizeof(MY_HASH_OBJ));
- if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&pHashObj->hashAlgHandle, CST_HASH_ALGORITHM, NULL, 0)))
+ if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&pHashObj->algHandle, CST_HASH_ALGORITHM, NULL, 0)))
goto CleanupExit;
- if (!NT_SUCCESS(status = BCryptGetProperty(pHashObj->hashAlgHandle, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pHashObj->hashObjectSize, sizeof(ULONG), &querySize, 0)))
+ if (!NT_SUCCESS(status = BCryptGetProperty(pHashObj->algHandle, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hashObjectSize, sizeof(ULONG), &querySize, 0)))
goto CleanupExit;
- if (!NT_SUCCESS(status = BCryptGetProperty(pHashObj->hashAlgHandle, BCRYPT_HASH_LENGTH, (PUCHAR)&pHashObj->hashSize, sizeof(ULONG), &querySize, 0)))
- goto CleanupExit;
-
- pHashObj->hashObject = malloc(pHashObj->hashObjectSize);
- if (!pHashObj->hashObject) {
+ pHashObj->object = malloc(hashObjectSize);
+ if (!pHashObj->object) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto CleanupExit;
}
- if (!NT_SUCCESS(status = BCryptCreateHash(pHashObj->hashAlgHandle, &pHashObj->hashHandle, (PUCHAR)pHashObj->hashObject, pHashObj->hashObjectSize, NULL, 0, 0)))
+ if (!NT_SUCCESS(status = BCryptCreateHash(pHashObj->algHandle, &pHashObj->handle, (PUCHAR)pHashObj->object, hashObjectSize, NULL, 0, 0)))
goto CleanupExit;
CleanupExit:
if (!NT_SUCCESS(status))
- CstFreeHash(pHashObj);
+ MyFreeHash(pHashObj);
return status;
}
-static NTSTATUS CstHashData(
- CST_HASH_OBJ* pHashObj,
- _Out_ PVOID Data,
- _Out_ ULONG DataSize
- )
+static NTSTATUS MyHashData(MY_HASH_OBJ* pHashObj, PVOID Data, ULONG DataSize)
{
- return BCryptHashData(pHashObj->hashHandle, (PUCHAR)Data, DataSize, 0);
+ return BCryptHashData(pHashObj->handle, (PUCHAR)Data, DataSize, 0);
}
-static NTSTATUS CstFinishHash(
- CST_HASH_OBJ* pHashObj,
- _Out_ PVOID* Hash,
- _Out_ PULONG HashSize
- )
+static NTSTATUS MyFinishHash(MY_HASH_OBJ* pHashObj, PVOID* Hash, PULONG HashSize)
{
NTSTATUS status;
- PVOID hash;
+ ULONG querySize;
- hash = malloc(pHashObj->hashSize);
- if (!hash) {
+ if (!NT_SUCCESS(status = BCryptGetProperty(pHashObj->algHandle, BCRYPT_HASH_LENGTH, (PUCHAR)HashSize, sizeof(ULONG), &querySize, 0)))
+ goto CleanupExit;
+
+ *Hash = malloc(*HashSize);
+ if (!*Hash) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto CleanupExit;
}
- if (!NT_SUCCESS(status = BCryptFinishHash(pHashObj->hashHandle, (PUCHAR)hash, pHashObj->hashSize, 0)))
+ if (!NT_SUCCESS(status = BCryptFinishHash(pHashObj->handle, (PUCHAR)*Hash, *HashSize, 0)))
goto CleanupExit;
- *HashSize = pHashObj->hashSize;
- *Hash = hash;
return STATUS_SUCCESS;
CleanupExit:
- if (hash)
- free(hash);
+ if (*Hash) {
+ free(*Hash);
+ *Hash = NULL;
+ }
return status;
}
@@ -193,12 +190,12 @@ static NTSTATUS CstHashFile(
HANDLE fileHandle = INVALID_HANDLE_VALUE;
PVOID buffer = NULL;
IO_STATUS_BLOCK iosb;
- CST_HASH_OBJ hashObj;
+ MY_HASH_OBJ hashObj;
- if (!NT_SUCCESS(status = CstInitHash(&hashObj)))
+ if (!NT_SUCCESS(status = MyInitHash(&hashObj)))
goto CleanupExit;
- if (!NT_SUCCESS(status = PhCreateFileWin32(&fileHandle, FileName, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE)))
+ if (!NT_SUCCESS(status = MyCreateFile(&fileHandle, FileName, FILE_GENERIC_READ, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE)))
goto CleanupExit;
buffer = malloc(FILE_BUFFER_SIZE);
@@ -217,11 +214,11 @@ static NTSTATUS CstHashFile(
goto CleanupExit;
}
- if (!NT_SUCCESS(status = CstHashData(&hashObj, buffer, (ULONG)iosb.Information)))
+ if (!NT_SUCCESS(status = MyHashData(&hashObj, buffer, (ULONG)iosb.Information)))
goto CleanupExit;
}
- if (!NT_SUCCESS(status = CstFinishHash(&hashObj, Hash, HashSize)))
+ if (!NT_SUCCESS(status = MyFinishHash(&hashObj, Hash, HashSize)))
goto CleanupExit;
CleanupExit:
@@ -229,39 +226,26 @@ CleanupExit:
free(buffer);
if(fileHandle != INVALID_HANDLE_VALUE)
NtClose(fileHandle);
- CstFreeHash(&hashObj);
+ MyFreeHash(&hashObj);
return status;
}
-static NTSTATUS VerifyHashSignature(
- _In_ PVOID Hash,
- _In_ ULONG HashSize,
- _In_ PVOID Signature,
- _In_ ULONG SignatureSize
- )
+static NTSTATUS VerifyHashSignature(PVOID Hash, ULONG HashSize, PVOID Signature, ULONG SignatureSize)
{
NTSTATUS status;
BCRYPT_ALG_HANDLE signAlgHandle = NULL;
BCRYPT_KEY_HANDLE keyHandle = NULL;
- // Import the trusted public key.
-
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(&signAlgHandle, CST_SIGN_ALGORITHM, NULL, 0)))
goto CleanupExit;
- if (!NT_SUCCESS(status = BCryptImportKeyPair(signAlgHandle, NULL, CST_BLOB_PUBLIC, &keyHandle,
- KphpTrustedPublicKey, sizeof(KphpTrustedPublicKey), 0)))
- {
- goto CleanupExit;
- }
- // Verify the hash.
-
- if (!NT_SUCCESS(status = BCryptVerifySignature(keyHandle, NULL, (PUCHAR)Hash, HashSize, (PUCHAR)Signature,
- SignatureSize, 0)))
- {
+ if (!NT_SUCCESS(status = BCryptImportKeyPair(signAlgHandle, NULL, CST_BLOB_PUBLIC, &keyHandle, KphpTrustedPublicKey, sizeof(KphpTrustedPublicKey), 0)))
+ goto CleanupExit;
+
+
+ if (!NT_SUCCESS(status = BCryptVerifySignature(keyHandle, NULL, (PUCHAR)Hash, HashSize, (PUCHAR)Signature, SignatureSize, 0)))
goto CleanupExit;
- }
CleanupExit:
if (keyHandle != NULL)