Add CI validation helpers with explicit signature selection and owned results
This commit is contained in:
1 parent
28f284be8f
commit
1f4d62ae95
13 files changed
+596
-3
No files matched your search
@@ -0,0 +1,109 @@
|
||||
#include "Domito.Internal.h"
|
||||
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN10)
|
||||
|
||||
static UINT32 DomitoCiDigestSize(ALG_ID Algorithm)
|
||||
{
|
||||
switch (Algorithm)
|
||||
{
|
||||
case CALG_SHA1: return MINCRYPT_SHA1_LENGTH;
|
||||
case CALG_SHA_256: return MINCRYPT_SHA256_LENGTH;
|
||||
case CALG_SHA_384: return MINCRYPT_SHA384_LENGTH;
|
||||
case CALG_SHA_512: return MINCRYPT_SHA512_LENGTH;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void DomitoClearCiDigest(DOMITO_CI_VALIDATION_RESULT* Result)
|
||||
{
|
||||
RtlZeroMemory(Result->Hash, sizeof(Result->Hash));
|
||||
Result->HashSize = 0;
|
||||
Result->HashAlgId = 0;
|
||||
Result->SigningTime.QuadPart = 0;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
void DomitoFreeCiValidationResult(DOMITO_CI_VALIDATION_RESULT* Result)
|
||||
{
|
||||
PAGED_CODE();
|
||||
if (!Result) return;
|
||||
CiFreePolicyInfo(&Result->PolicyInfo);
|
||||
CiFreePolicyInfo(&Result->TimeStampPolicyInfo);
|
||||
RtlZeroMemory(Result, sizeof(*Result));
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS DomitoValidateFileObjectEx(
|
||||
PFILE_OBJECT FileObject, UINT32 ValidationFlags, UINT8 RequestedSigningLevel,
|
||||
DOMITO_CI_SIGNATURE_SELECTION Selection, DOMITO_CI_VALIDATION_RESULT* Result)
|
||||
{
|
||||
PAGED_CODE();
|
||||
if (!Result) return STATUS_INVALID_PARAMETER;
|
||||
DomitoFreeCiValidationResult(Result);
|
||||
if (!FileObject) return STATUS_INVALID_PARAMETER;
|
||||
if (Selection != DomitoCiSignatureSelectionNative &&
|
||||
Selection != DomitoCiSignatureSelectionFirstSuccessfulExperimental)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (Selection == DomitoCiSignatureSelectionFirstSuccessfulExperimental)
|
||||
{
|
||||
#if defined(_M_AMD64) || defined(_AMD64_)
|
||||
ValidationFlags |= DOMITO_CI_VALIDATE_FLAG_FIRST_SUCCESS_EXPERIMENTAL;
|
||||
#else
|
||||
return STATUS_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
Result->FileObjectValidationFlags = ValidationFlags;
|
||||
Result->RequestedSigningLevel = RequestedSigningLevel;
|
||||
Result->HashSize = sizeof(Result->Hash);
|
||||
NTSTATUS status = CiValidateFileObject(FileObject, ValidationFlags, RequestedSigningLevel,
|
||||
&Result->PolicyInfo, &Result->TimeStampPolicyInfo, &Result->SigningTime,
|
||||
Result->Hash, &Result->HashSize, &Result->HashAlgId);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
const UINT32 expected = DomitoCiDigestSize(Result->HashAlgId);
|
||||
if (!expected) status = STATUS_NOT_SUPPORTED;
|
||||
else if (Result->HashSize != expected || Result->HashSize > sizeof(Result->Hash))
|
||||
status = STATUS_INVALID_BUFFER_SIZE;
|
||||
}
|
||||
if (!NT_SUCCESS(status)) DomitoClearCiDigest(Result);
|
||||
else RtlZeroMemory(Result->Hash + Result->HashSize, sizeof(Result->Hash) - Result->HashSize);
|
||||
return status;
|
||||
}
|
||||
|
||||
_Use_decl_annotations_
|
||||
NTSTATUS DomitoValidatePortableExecutableEmbeddedSignature(
|
||||
const UCHAR* PeBytes, ULONG PeSize, ALG_ID HashAlgId, DOMITO_CI_VALIDATION_RESULT* Result)
|
||||
{
|
||||
PAGED_CODE();
|
||||
if (!Result) return STATUS_INVALID_PARAMETER;
|
||||
DomitoFreeCiValidationResult(Result);
|
||||
if (!PeBytes) return STATUS_INVALID_PARAMETER;
|
||||
const UINT32 expected = DomitoCiDigestSize(HashAlgId);
|
||||
if (!expected) return STATUS_NOT_SUPPORTED;
|
||||
PVOID digest = nullptr;
|
||||
ULONG digestSize = 0, securitySize = 0;
|
||||
LPWIN_CERTIFICATE certificate = nullptr;
|
||||
NTSTATUS status = DomitoCalculatePortableExecutableDigestEx(PeBytes, PeSize, HashAlgId,
|
||||
&digestSize, &digest, &certificate, &securitySize);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
if (!certificate || !securitySize) status = STATUS_INVALID_IMAGE_HASH;
|
||||
else if (!digest || digestSize != expected || digestSize > sizeof(Result->Hash))
|
||||
status = STATUS_INVALID_BUFFER_SIZE;
|
||||
else
|
||||
{
|
||||
status = CiCheckSignedFile(digest, digestSize, HashAlgId, certificate, securitySize,
|
||||
&Result->PolicyInfo, &Result->SigningTime, &Result->TimeStampPolicyInfo);
|
||||
if (NT_SUCCESS(status))
|
||||
{
|
||||
RtlCopyMemory(Result->Hash, digest, digestSize);
|
||||
Result->HashSize = digestSize;
|
||||
Result->HashAlgId = HashAlgId;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (digest) DomitoFreePortableExecutableDigest(digest);
|
||||
if (!NT_SUCCESS(status)) DomitoClearCiDigest(Result);
|
||||
return status;
|
||||
}
|
||||
#endif // NTDDI_VERSION >= NTDDI_WIN10
|
||||
Reference in new issue
Block a user