Files
Domito/src/Domito.CodeIntegrity.Validation.cpp
T
nefarius a491bbd3f8 Add reusable certificate and file validation helpers
Fix process-name ownership and module lookup outputs, add explicit SPKI hashing and bounded chain access, and improve WDM integration. Deprecate superseded entry points with migration guidance and align branch code and tests with the library style.
2026-10-27 00:16:42 +01:00

217 lines
4.7 KiB
C++

#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;
ULONG 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