Add explicit Authenticode workflows and correct CI helper contracts

This commit is contained in:
nefarius committed 2026-10-26 17:55:58 +01:00
1 parent 1026c48324
commit 7aa23f50be
18 files changed
+1952 -185

No files matched your search

+68 -33
View File
@@ -277,6 +277,8 @@ MINCRYPT_DIGEST_BLOB, * PMINCRYPT_DIGEST_BLOB,
MINCRYPT_DER_BLOB, * PMINCRYPT_DER_BLOB,
MINCRYPT_ATTR_BLOB, * PMINCRYPT_ATTR_BLOB;
// Encoded, length-delimited name bytes; not necessarily ANSI or NUL-terminated.
// The observed 26100 x64 string tag occupies padding; see the opt-in version header.
typedef struct _MINCRYPT_NAME_BLOB
{
_Field_size_bytes_(Size) PCHAR Data;
@@ -287,6 +289,8 @@ typedef struct _MINCRYPT_NAME_BLOB
#define MINCRYPT_MAX_HASH_LENGTH (64)
#define MINCRYPT_SHA1_LENGTH (160/8)
#define MINCRYPT_SHA256_LENGTH (256/8)
#define MINCRYPT_SHA384_LENGTH (384/8)
#define MINCRYPT_SHA512_LENGTH (512/8)
typedef struct _MINCRYPT_CHAIN_ELEMENT
{
@@ -301,9 +305,11 @@ typedef struct _MINCRYPT_CHAIN_ELEMENT
}MINCRYPT_CHAIN_ELEMENT, * PMINCRYPT_CHAIN_ELEMENT;
// CI owns one chain allocation; nested pointers borrow that allocation.
// Do not free child blobs separately or use memcpy to create a second owner.
typedef struct _MINCRYPT_CHAIN_INFO
{
UINT32 Size;
UINT32 Size; // Observed 26100 x64: total allocation bytes, including trailing data.
MINCERT_BLOB* PublicKeys;
UINT32 NumberOfPublicKeys;
@@ -319,7 +325,9 @@ typedef struct _MINCRYPT_CHAIN_INFO
// ASN.1 blob of authenticated attributes - spcSpOpusInfo, contentType, etc.
MINCRYPT_ATTR_BLOB AuthenticodeAttributes;
// UINT8 Hash[32];
// Observed 26100 x64 adds RootId at +0x34 and a 32-byte platform-manifest
// binary ID at +0x48. These are exposed only by Domito.MinCrypt.26100.h.
// Do not infer their availability solely from NTDDI_VERSION or Size.
#endif // NTDDI_VERSION >= NTDDI_WIN10
@@ -338,7 +346,7 @@ typedef struct _MINCRYPT_CHAIN_INFO
typedef struct _MINCRYPT_POLICY_INFO
{
UINT32 Size;
UINT32 VerificationStatus;
NTSTATUS VerificationStatus; // Check API return status separately.
UINT32 PolicyBits;
MINCRYPT_CHAIN_INFO* ChainInfo;
@@ -347,8 +355,8 @@ typedef struct _MINCRYPT_POLICY_INFO
#if (NTDDI_VERSION >= NTDDI_WIN10)
LARGE_INTEGER NotBefore; // The certificate is not valid before this time
LARGE_INTEGER NotAfter; // The certificate is not valid after this time
LARGE_INTEGER NotBefore; // Observed: signer certificate validity start.
LARGE_INTEGER NotAfter; // Observed: signer certificate validity end.
#endif // NTDDI_VERSION >= NTDDI_WIN10
@@ -358,12 +366,16 @@ typedef struct _MINCRYPT_POLICY_INFO
/**
* Resets a PolicyInfo struct - frees the dynamically allocated buffer in PolicyInfo (ChainInfo) if not null.
* Zeros the entire PolicyInfo struct.
* Release a known initialized policy's owned ChainInfo allocation and reset it.
* Zero-initialize policy objects before first use. Release both signer and TSA
* policies after use, including failures, and before reusing output storage.
* Borrowed child pointers become invalid when the owner is released. Never clear
* Size while a chain is still owned. Size does not negotiate the runtime layout.
*
* @param PolicyInfo - the struct to reset.
* @param PolicyInfo - initialized policy, not arbitrary uninitialized storage.
*
* @return the struct which was reset.
* Ignore the return value. The legacy PVOID declaration is retained for source
* compatibility; observed 26100 x64 code provides no defined pointer return.
*/
_IRQL_requires_max_(PASSIVE_LEVEL)
MINCRYPTAPI
@@ -375,18 +387,23 @@ CiFreePolicyInfo(
/**
* Win7SP1-Win8.1 only (KB3033929 installed). Use CiValidateFileObject on Win10!
* Digest-based workflow, also implemented on observed Windows 11 build 26100.
* Prefer the file-object workflow when its policy fits. Older-build ABI and
* KB3033929 requirements need a separately verified compatibility matrix.
*
* Given a file digest and signature of a file, verify the signature and provide information regarding
* the certificates that was used for signing (the entire certificate chain)
*
* @param Hash - buffer containing the digest
* @param Hash[in] - caller-computed file digest; CI does not recompute the file bytes
*
* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256
*
* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C)
*
* @param SecurityDirectory - pointer to the start of the security directory
* @param SecurityDirectory - WIN_CERTIFICATE header, not the PKCS#7 payload.
* Observed 26100 x64 checks 4-byte pointer alignment, revision 0x200,
* type 2, supplied size >=12 and 8 < dwLength <= supplied size.
* This wrapper selects the first entry; it does not enumerate the table.
*
* @param SizeOfSecurityDirectory - size the security directory
*
@@ -396,9 +413,12 @@ CiFreePolicyInfo(
*
* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain
*
* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified.
* @return Overall verification NTSTATUS. A successful policy VerificationStatus
* does not replace this return value: the final file-digest comparison
* can still fail. Both policy outputs may carry diagnostics on failure.
* See docs/mincrypt-contracts.md for ownership and policy limits.
* Various error values otherwise, for example:
* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature
* STATUS_INVALID_IMAGE_HASH - digest/signature or selected CI policy rejected
* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked
* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired
*/
@@ -407,10 +427,10 @@ MINCRYPTAPI
NTSTATUS
NTAPI
CiCheckSignedFile(
_In_ PVOID Hash,
_In_reads_bytes_(HashSize) PVOID Hash,
_In_ UINT32 HashSize,
_In_ ALG_ID HashAlgId,
_In_ PVOID SecurityDirectory,
_In_reads_bytes_(SizeOfSecurityDirectory) PVOID SecurityDirectory,
_In_ UINT32 SizeOfSecurityDirectory,
_Out_ MINCRYPT_POLICY_INFO* PolicyInfo,
_Out_ LARGE_INTEGER* SigningTime,
@@ -418,36 +438,51 @@ CiCheckSignedFile(
);
// Existing Domito compatibility filter, not a universal trusted-root policy.
// Includes test/DMD categories and a diagnostic bit; select policy deliberately.
#define DOMITO_CI_LEGACY_CATALOG_POLICY_BITS 0x0002007FUL
/**
* Win7SP1-Win8.1 only (KB3033929 installed). Use CiValidateFileObject on Win10!
* Digest-based workflow, also implemented on observed Windows 11 build 26100.
* Prefer the file-object workflow when its policy fits. Older-build ABI and
* KB3033929 requirements need a separately verified compatibility matrix.
*
* Checks if the SHA-1 message digest is contained within a verified system catalog
* Finds a caller-computed file digest in an accepted installed catalog.
* Observed 26100 x64 file-hash lookup supports SHA-1 and SHA-256.
*
* @note must be attached to the PsInitialSystemProcess first!
*
* @param Hash - buffer containing the digest
* @param Hash[in] - caller-computed file digest; CI does not recompute the file bytes
*
* @param HashSize - size of the digest, e.g. 0x14(160bit) for SHA1, 0x20(256bit) for SHA256
*
* @param HashAlgId - digest algorithm identifier, e.g. CALG_SHA1(0x8004), CALG_SHA_256(0x800C)
*
* @param IsReloadCatalogs - is reload catalogs cache.
* @param ReloadCatalogs - request catalog-store reload; process/silo and cache state matter.
*
* @param Always0 - this is for IsReloadCatalogs, Always0 != 0 ? 16 : 24;
* @param RequireTrustedCatalog - nonzero requires the observed catalog TRUSTED
* extension marker. This does not itself establish Microsoft signer trust.
*
* @param Always2007F - unknown, always 0x2007F, maybe a mask.
* @param AcceptedCatalogPolicyBits - candidate catalog policy-bit filter.
* Observed 26100 x64 requires ANY overlap with catalog PolicyBits, not
* every requested bit. This is not a flags-to-enable input.
*
* @param PolicyInfo[out] - PolicyInfo containing information about the signer certificate chain.
*
* @param CatalogName[out option] - catalog file name.
* @param CatalogName[out option] - initialize empty; observed 26100 x64 returns
* a separate duplicated string allocation. Release a returned Buffer
* with RtlFreeUnicodeString, separately from both policy outputs.
*
* @param SigningTime[out] - when the file was signed (FILETIME format)
*
* @param TimeStampPolicyInfo[out] - PolicyInfo containing information about the timestamping authority (TSA) certificate chain.
*
* @return STATUS_SUCCESS if the file digest in the signature matches the given digest and the signer cetificate is verified.
* @return Overall verification NTSTATUS. A successful policy VerificationStatus
* does not replace this return value. Catalog selection and the
* selected policy still apply. Outputs may carry diagnostics on failure.
* See docs/mincrypt-contracts.md for ownership and policy limits.
* Various error values otherwise, for example:
* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature
* STATUS_INVALID_IMAGE_HASH - digest/signature or selected CI policy rejected
* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked
* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired
*/
@@ -456,12 +491,12 @@ MINCRYPTAPI
NTSTATUS
NTAPI
CiVerifyHashInCatalog(
_In_ PVOID Hash,
_In_reads_bytes_(HashSize) PVOID Hash,
_In_ UINT32 HashSize,
_In_ ALG_ID HashAlgId,
_In_ BOOLEAN IsReloadCatalogs,
_In_ UINT32 Always0,
_In_ UINT32 Always2007F,
_In_ BOOLEAN ReloadCatalogs,
_In_ UINT32 RequireTrustedCatalog,
_In_ UINT32 AcceptedCatalogPolicyBits,
_Out_ MINCRYPT_POLICY_INFO* PolicyInfo,
_Out_opt_ UNICODE_STRING* CatalogName,
_Out_ LARGE_INTEGER* SigningTime,
@@ -552,7 +587,7 @@ CiSetTrustedOriginClaimId(
* @return STATUS_SUCCESS when verification succeeds under the selected CI policy.
* This does not by itself establish the application's signer trust policy.
* Various error values otherwise, for example:
* STATUS_INVALID_IMAGE_HASH - the digest does not match the digest in the signature
* STATUS_INVALID_IMAGE_HASH - digest/signature or selected CI policy rejected
* STATUS_IMAGE_CERT_REVOKED - the certificate used for signing the file is revoked
* STATUS_IMAGE_CERT_EXPIRED - the certificate used for signing the file has expired
*/
@@ -562,12 +597,12 @@ NTSTATUS
NTAPI
CiValidateFileObject(
_In_ FILE_OBJECT* FileObject,
_In_opt_ UINT32 ValidationFlags,
_In_opt_ UINT32 RequestedSigningLevel,
_In_ UINT32 ValidationFlags,
_In_ UINT32 RequestedSigningLevel,
_Out_ MINCRYPT_POLICY_INFO* PolicyInfo,
_Out_ MINCRYPT_POLICY_INFO* TimeStampPolicyInfo,
_Out_ LARGE_INTEGER* SigningTime,
_Out_ UINT8* Hash,
_Out_writes_bytes_(*HashSize) UINT8* Hash,
_Inout_ UINT32* HashSize,
_Out_ ALG_ID* HashAlgId
);