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.
This commit is contained in:
nefarius committed 2026-10-27 00:16:42 +01:00
1 parent 1f4d62ae95
commit a491bbd3f8
32 files changed
+5404 -1136

No files matched your search

+140 -33
View File
@@ -2,19 +2,30 @@
#if (NTDDI_VERSION >= NTDDI_WIN10)
static UINT32 DomitoCiDigestSize(ALG_ID Algorithm)
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;
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)
static void
DomitoClearCiDigest(
DOMITO_CI_VALIDATION_RESULT* Result
)
{
RtlZeroMemory(Result->Hash, sizeof(Result->Hash));
Result->HashSize = 0;
@@ -23,27 +34,53 @@ static void DomitoClearCiDigest(DOMITO_CI_VALIDATION_RESULT* Result)
}
_Use_decl_annotations_
void DomitoFreeCiValidationResult(DOMITO_CI_VALIDATION_RESULT* Result)
void
DomitoFreeCiValidationResult(
DOMITO_CI_VALIDATION_RESULT* Result
)
{
PAGED_CODE();
if (!Result) return;
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)
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;
if (!Result)
{
return STATUS_INVALID_PARAMETER;
}
DomitoFreeCiValidationResult(Result);
if (!FileObject) return STATUS_INVALID_PARAMETER;
if (!FileObject)
{
return STATUS_INVALID_PARAMETER;
}
if (Selection != DomitoCiSignatureSelectionNative &&
Selection != DomitoCiSignatureSelectionFirstSuccessfulExperimental)
{
return STATUS_INVALID_PARAMETER;
}
if (Selection == DomitoCiSignatureSelectionFirstSuccessfulExperimental)
{
#if defined(_M_AMD64) || defined(_AMD64_)
@@ -52,48 +89,109 @@ NTSTATUS DomitoValidateFileObjectEx(
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);
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;
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);
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)
NTSTATUS
DomitoValidatePortableExecutableEmbeddedSignature(
const UCHAR* PeBytes,
ULONG PeSize,
ALG_ID HashAlgId,
DOMITO_CI_VALIDATION_RESULT* Result
)
{
PAGED_CODE();
if (!Result) return STATUS_INVALID_PARAMETER;
if (!Result)
{
return STATUS_INVALID_PARAMETER;
}
DomitoFreeCiValidationResult(Result);
if (!PeBytes) return STATUS_INVALID_PARAMETER;
if (!PeBytes)
{
return STATUS_INVALID_PARAMETER;
}
const UINT32 expected = DomitoCiDigestSize(HashAlgId);
if (!expected) return STATUS_NOT_SUPPORTED;
if (!expected)
{
return STATUS_NOT_SUPPORTED;
}
PVOID digest = nullptr;
ULONG digestSize = 0, securitySize = 0;
ULONG digestSize = 0;
ULONG securitySize = 0;
LPWIN_CERTIFICATE certificate = nullptr;
NTSTATUS status = DomitoCalculatePortableExecutableDigestEx(PeBytes, PeSize, HashAlgId,
&digestSize, &digest, &certificate, &securitySize);
NTSTATUS status = DomitoCalculatePortableExecutableDigestEx(
PeBytes, PeSize, HashAlgId, &digestSize, &digest, &certificate, &securitySize
);
if (NT_SUCCESS(status))
{
if (!certificate || !securitySize) status = STATUS_INVALID_IMAGE_HASH;
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);
status = CiCheckSignedFile(
digest,
digestSize,
HashAlgId,
certificate,
securitySize,
&Result->PolicyInfo,
&Result->SigningTime,
&Result->TimeStampPolicyInfo
);
if (NT_SUCCESS(status))
{
RtlCopyMemory(Result->Hash, digest, digestSize);
@@ -102,8 +200,17 @@ NTSTATUS DomitoValidatePortableExecutableEmbeddedSignature(
}
}
}
if (digest) DomitoFreePortableExecutableDigest(digest);
if (!NT_SUCCESS(status)) DomitoClearCiDigest(Result);
if (digest)
{
DomitoFreePortableExecutableDigest(digest);
}
if (!NT_SUCCESS(status))
{
DomitoClearCiDigest(Result);
}
return status;
}
#endif // NTDDI_VERSION >= NTDDI_WIN10