# Code Integrity and mincrypt contracts The default header retains the existing structure layouts and calling shapes. Parameter names and ownership comments now distinguish the known controls from the verification result. `VerificationStatus` is an `NTSTATUS` with the same 32-bit storage. The additional `Domito.MinCrypt.26100.h` header is an **opt-in description of ci.dll 10.0.26100.8328 x64**. It neither adds imports nor extends the default structures on every Windows target. The evidence is static REA/Ghidra analysis of SHA-256 `c7d23814f3202c51fb23e3ca3d4328855787383cee5d14c4a986a13ec2aeda0b`, with Microsoft ci.pdb GUID `1CAE574B-CF1F-3564-5F74-49567A128629`, age 1 supplying the address/name map. The companion CodeIntegrity-RE repository retains the full records and readable `evidence/` files. These observations do not establish older-Windows or ARM64 ABI compatibility. Compile-target `NTDDI_VERSION` is not runtime layout negotiation. ## Results and trust policy Check the API's returned `NTSTATUS` first. `PolicyInfo.VerificationStatus`, `PolicyBits`, signer details, and timestamps supply additional observations. Successful chain processing does not imply that the caller's file digest matched the signed digest; the comparison can occur afterward. Diagnostic policy data may exist on failure. An extracted publisher name is display information and does not establish publisher identity or signer trust. Define the policy the application needs: embedded signature validation, membership in an accepted installed catalog, an expected publisher/key, or a Windows signing scenario. Preserve which path produced a result. A nonzero `PolicyBits` value is not automatically failure, and any one root bit is not a complete trust decision. File bytes and object identity must remain tied to the bytes the application will subsequently use. The [file-object flag document](ci-validate-file-object.md) covers `0x20`, hash capacity, signing level, and its pending VM experiment. Other observed flag effects on this build are: - `0x1` selects hash scenario 5. - Otherwise `0x2` selects scenario 4 for signing levels <=4; higher levels use the level mapping. - Otherwise `0x80000000` selects scenario 5 for levels <=4; higher levels use the level mapping. It takes precedence over `0x4`. - Otherwise `0x4` selects scenario 1; without these choices the signing level maps to a scenario. - `0x00400000` suppresses accepted-root bit `0x8` when the relevant helper mode is enabled; CI can add this flag internally. Bits `0x2` and `0x8` also affect later signing-level/EKU restrictions. The scenarios resolve through initialized signing-policy state. Static defaults are not a guarantee of a running system's algorithm, and the flags should not be named as universal fixed SHA selectors. Unknown bits remain unknown. Evidence: `CipGetHashAlgorithmForLegacyScenario`, `CipGetAcceptedRootKeys`, and `CipMinCryptToSigningLevel` in the research bundle. ## Ownership and initialization Zero-initialize both `MINCRYPT_POLICY_INFO` output objects before their first use. Free both with `CiFreePolicyInfo` after use and before reuse, including failure paths. Never call the destructor on arbitrary uninitialized stack data. Do not clear a nonzero `Size` while a chain is still owned: the observed cleanup helper skips an object whose `Size` is zero. `ChainInfo` owns one allocation. Public-key blobs, names, encoded certificates, EKUs, attributes, and chain elements are borrowed views into it. Do not free children separately or retain them after releasing the owner. Copying the policy structure with `memcpy` creates two aliases to one allocation, not independent ownership. CI's internal deep-copy helper uses the total allocation size and rebases interior pointers; Domito does not expose that helper. The default `CiFreePolicyInfo` declaration retains its legacy `PVOID` return to avoid a broad source compatibility change. **Ignore that value**: observed x64 assembly provides no defined pointer result. The opt-in build-specific function pointer type uses `VOID`. `CatalogName` is a separate `RtlDuplicateUnicodeString` allocation in the observed catalog export. Initialize it empty, release a returned buffer with `RtlFreeUnicodeString`, and release both policies separately. Publisher-name storage is allocated through the caller's callback and must be released with that allocator's matching free operation, including an allocated buffer on a later conversion failure. It is not owned by either policy object. Evidence: `MincryptFreePolicyInfo`, `MincryptCopyPolicyInfo`, `I_MincryptAddChainInfo`, `CiVerifyHashInCatalog`, and `CiGetCertPublisherName`. ## Digest-based verification inputs `CiCheckSignedFile` consumes a caller-computed file digest. It does not reopen the file or compute its Authenticode hash. On the observed build it accepts SHA-1/256/384/512 with exactly 20/32/48/64 bytes respectively. A wrong algorithm, length, or digest fails the final comparison. Its signature input points to a `WIN_CERTIFICATE` header. The observed wrapper requires 4-byte pointer alignment, supplied size >=12, revision `0x200`, type 2, and `8 < dwLength <= supplied size`. The PKCS#7 payload begins at header+8. The wrapper selects the first certificate-table entry. Multiple table entries and nested signatures are separate concepts; this is not a complete signature enumeration interface. These exports remain implemented on the analyzed Windows 11 build. The older header's “Win7–8.1 only” comments described a workflow, not verified export availability. Exact first-available builds and pre/post-KB3033929 ABI changes still require matching historical binaries. Import-library symbol names and stdcall stack-byte counts alone do not settle parameter semantics. ## Catalog controls `ReloadCatalogs` controls catalog-store reload and related context setup. `RequireTrustedCatalog` is a nonzero gate requiring an observed catalog extension marker: its matching bytes include `PE`, integer `0x10001`, and `TRUSTED`. The marker is an additional catalog condition, not proof of a Microsoft signer. `AcceptedCatalogPolicyBits` accepts a candidate when `(RequestedMask & Catalog.PolicyInfo.PolicyBits) != 0`: **any overlap** is enough. It neither enables policy flags nor requires every requested bit. The existing Domito compatibility value is named `DOMITO_CI_LEGACY_CATALOG_POLICY_BITS` (`0x2007F`). It includes test/DMD categories and diagnostic bit `0x20000`, while omitting other categories. It is retained as an existing behavior, not promoted as a universally safe trust mask. Establish and test the application's accepted signer policy before changing it. Observed file-hash lookup supports SHA-1 and SHA-256; the internal path has no SHA-384/512 file-hash case. Embedded-signature algorithm support and catalog lookup support are different capabilities. Catalog-only files need an explicit, tested algorithm strategy rather than assuming SHA-1 from an absent embedded table. Catalog stores, caches, silo/process context, and signing policy affect results. The new `DomitoValidateFileLegacyModeEx` forwards a caller-selected mask and marker gate and reports embedded/catalog origin. Its compatibility wrapper retains the existing mask. See [digest and workflow details](authenticode-digests.md). Domito's older-Windows helper keeps its system-process attachment until historical runtime evidence supports changing it. Evidence: `I_FindFileOrHeaderHashInLoadedCatalogs` and its assembly `ev_c42e7ee76099d55e7cf7cdd3d9f79e99030ba637680365612afb4906694ae3a8`, `I_ParseCatalog`, and marker matcher `ev_a1d3a5844a2b6be6c16175e307956c9819d0b64a4fe70216f292c12e4ea38d82`. ## Opt-in x64 26100 structure observations The version header has distinct type names and 14 compile-time layout assertions. Use it only after independently establishing the matching runtime build and architecture. A large `ChainInfo->Size` alone does not identify the header: it includes variable trailing data, so an older allocation could also be large. Only after layout identity is established may a size check protect a field read. - `DOMITO_CI26100_NAME_BLOB`: pointer at +0, byte length at +8, ASN.1 string tag at +10. Names are not necessarily NUL-terminated. Observed conversion handles UTF8String tag `0x0C` and BMPString `0x1E`; `PCHAR` in the default declaration must not be read as a guarantee of ANSI encoding. - `DOMITO_CI26100_CHAIN_INFO`: `Size` is total allocation bytes; fixed header is 104 bytes. Root ID at +0x34 is an opaque integer, not policy bits. The 32 bytes at +0x48 are a platform-manifest binary ID from an authenticated attribute, not a file digest or certificate thumbprint. Zero/nonzero does not by itself prove trust. Require the matching layout and `Size >=104` before reading it. - `DOMITO_CI26100_POLICY_INFO`: 48 bytes; `NotBefore`/`NotAfter` come from the signer certificate validity fields, not an intersection of the whole chain. Interpret `RevocationTime` only with the relevant result. A zero signing time is not a real timestamp to display as a signing date. Construction/copy evidence: `ev_d7110cfc711074a4af1874b5c8e701c13bcc3dc58a1596c64dca4ca98966c79e`, `ev_858afecf2170484325379b6a8bc307fb72dad2f9a5a765169192c7363a3386af`, `ev_f82cbee977715399323bb398781c125a9d19b4ea29acd05063ec55b711cfc670`. ## Partial policy-bit dictionary Names in the opt-in header are Domito descriptions of observed 26100 branches, not official Microsoft constants or a universal trusted-root enumeration. Root/provenance categories include `0x1` self-issued terminal path, `0x2` selected built-in Microsoft roots, `0x4` test roots, `0x8` the built-in root associated with embedded picroot handling, `0x10` tolerated partial/unresolved chain, `0x20` DMD, `0x40` DMD test, `0x80` another built-in Microsoft root, `0x400` flight root, `0x2000` third-party marketplace, `0x4000` explicit supplied certificate/key acceptance, and `0x8000` Microsoft Identity Root 2020. `0x800` and `0x1000` are additional discriminators on some root entries; their independent meanings remain unresolved. These categories do not establish a full trust result. Observed diagnostic branches set `0x20000` chain failure, `0x40000` invalid cryptographic/signature data, `0x80000` unmet EKU, `0x100000` page-hash failure, `0x200000` revocation, `0x400000` certificate validity failure (including not-yet-valid), `0x08000000` path-length constraints, `0x10000000` generic fallback, and `0x20000000` CA/BasicConstraints failure. `0x04000000` marks a no-usable- timestamp branch during revoked-certificate recovery, not universal timestamp absence. `0x50000` and `0x60000` are observed composites; do not infer a unique meaning for every constituent bit. Timestamp-before-revocation processing can clear a revocation bit. Internal checks of high bits are not a replacement for the API status and application policy. ## Remaining runtime and API coverage The missing page-hash exports have recovered argument shapes in the research report. Their normalized allocation uses a 24-byte x64 header and 24-byte entries even for stronger source algorithms. Field meaning, truncation intent, source terminal-entry handling, and a supported destructor remain open. `CiFreePolicyInfo` is not a demonstrated destructor for that allocation. No universal page-hash SDK or static import is added until those ownership and cross-version contracts can be tested. `CiGetPEInformation` is a protected-media dispatcher, not a general PE parser. `CiInitialize` is initialization machinery. `CiSetTrustedOriginClaimId` writes a CI global; it is not an ordinary per-file trust selector. Ordinal-only exports and other initialization interfaces require their own evidence and callers. Still required: historical/ARM64 layout and parameter verification, real CI output lifetimes and retry behavior under failures, timestamp propagation, revocation freshness/network policy, weak-crypto selection, multiple/nested signatures, catalog-only algorithms, and extension of the bounded digest subset to additional PE layouts. The explicit digest helper now has local Windows SIP and real embedded-digest comparisons; this does not close those historical or unusual-layout cases. Run the prepared probes in disposable VMs with exact OS, CI binary, configuration, and fixture identities. Compilation and host mocks do not close those runtime questions.