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:
1 parent
1f4d62ae95
commit
a491bbd3f8
32 files changed
+5404
-1136
No files matched your search
@@ -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
|
||||
Reference in new issue
Block a user