117 lines
6.1 KiB
Markdown
117 lines
6.1 KiB
Markdown
# CI validation helpers
|
|
|
|
These additive APIs are declared in `Domito.h` for Windows 10 compile targets.
|
|
They reuse CI for cryptographic verification. They do not implement RSA/ECDSA,
|
|
certificate-chain building or timestamp-signature verification themselves.
|
|
Raw CI declarations and existing digest/legacy helpers are unchanged.
|
|
|
|
## Result lifetime
|
|
|
|
Zero-initialize `DOMITO_CI_VALIDATION_RESULT` before first use. Each validation
|
|
call frees its previous signer/timestamp policies before reuse and resets the
|
|
result. Do not pass uninitialized storage or copy an owning result as a second
|
|
owner. On every exit, including a failed call, release it with
|
|
`DomitoFreeCiValidationResult`. The destructor accepts NULL and empty results.
|
|
All three APIs require PASSIVE_LEVEL. Referenced input objects/buffers must stay
|
|
valid and file bytes must stay stable throughout validation and consumption.
|
|
|
|
On success, `Hash`/`HashSize`/`HashAlgId` describe a known SHA-1/256/384/512 file
|
|
digest with a consistent length. Unused digest bytes are zero. This is not a
|
|
certificate thumbprint. On failure, digest bytes/length/algorithm and signing
|
|
time are zero; policy objects may retain owned diagnostic allocations. Input
|
|
flags/level forwarded to the file-object export remain recorded if it was called.
|
|
Those fields are not CI's final internally normalized policy flags.
|
|
|
|
Check the returned NTSTATUS first. Policy verification status, policy bits,
|
|
certificate identity, timestamps and the application's intended trust policy
|
|
remain separate observations/checks. Returning STATUS_SUCCESS does not pin a
|
|
company signer, reproduce WinVerifyTrust policy or prove driver-load acceptance.
|
|
No helper traverses the private chain layout or matches a certificate for you.
|
|
|
|
## File-object path
|
|
|
|
`DomitoValidateFileObjectEx` takes a referenced FILE_OBJECT, caller-selected
|
|
validation flags, a byte-sized requested signing level and a selection mode.
|
|
It supplies fresh 64-byte hash capacity and initialized policy/time outputs on
|
|
every call. It does not read, duplicate or acquire ownership of the file object.
|
|
|
|
- `DomitoCiSignatureSelectionNative` forwards the caller's flags unchanged.
|
|
This is native policy, not a guarantee of preferred-level selection: the
|
|
caller's other flags may already change the search/exit path.
|
|
- `DomitoCiSignatureSelectionFirstSuccessfulExperimental` additionally sets
|
|
`DOMITO_CI_VALIDATE_FLAG_FIRST_SUCCESS_EXPERIMENTAL` (0x80). On examined x64
|
|
builds this changes a successful-candidate early-exit predicate. It also
|
|
affects other policy/fallback paths. This explicit mode returns
|
|
STATUS_NOT_SUPPORTED on non-x64 builds. No runtime behavior on ARM64 is implied.
|
|
|
|
Neither mode automatically adds `0x20`. Broadening accepted roots is a separate
|
|
caller decision. Neither mode selects an arbitrary signer index or guarantees
|
|
that signature zero succeeds. A rejected primary may still lead to another signer.
|
|
|
|
```c
|
|
DOMITO_CI_VALIDATION_RESULT result = {0};
|
|
NTSTATUS status = DomitoValidateFileObjectEx(
|
|
fileObject,
|
|
DOMITO_CI_VALIDATE_FLAG_BROADEN_ROOT_ACCEPTANCE,
|
|
0,
|
|
DomitoCiSignatureSelectionFirstSuccessfulExperimental,
|
|
&result);
|
|
if (NT_SUCCESS(status)) {
|
|
// Apply your expected-certificate/trust policy to result.PolicyInfo.
|
|
// result.SigningTime belongs to that selected verification result.
|
|
}
|
|
DomitoFreeCiValidationResult(&result);
|
|
```
|
|
|
|
The native kernel experiment on the supplied dual-SHA256 BthPS3 fixture returned
|
|
Microsoft for flags 0x20 and Nefarius for flags 0xA0 on a Windows 11 22631 x64
|
|
TESTSIGNING-enabled machine. It does not establish all older builds, TESTSIGNING-off
|
|
behavior or every side effect of 0x80. See [the flag evidence](ci-validate-file-object.md).
|
|
Do not rename this mode "require our company" or "select primary signature".
|
|
|
|
## Embedded PE-buffer path
|
|
|
|
`DomitoValidatePortableExecutableEmbeddedSignature` accepts a stable PE buffer
|
|
and an explicit CALG_SHA1/CALG_SHA_256/CALG_SHA_384/CALG_SHA_512. It calls
|
|
`DomitoCalculatePortableExecutableDigestEx` and supplies the resulting digest
|
|
and original first WIN_CERTIFICATE to `CiCheckSignedFile`. The digest allocation
|
|
is always freed, and only copied digest bytes/owned CI policies remain in the
|
|
result. Unsupported algorithm/layout and CI errors propagate without trying a
|
|
different algorithm or a catalog. An absent certificate returns
|
|
STATUS_INVALID_IMAGE_HASH; the helper cannot turn an unsigned file into a
|
|
successful catalog verification.
|
|
|
|
```c
|
|
DOMITO_CI_VALIDATION_RESULT result = {0};
|
|
NTSTATUS status = DomitoValidatePortableExecutableEmbeddedSignature(
|
|
stablePeBytes, peSize, CALG_SHA_256, &result);
|
|
if (NT_SUCCESS(status)) {
|
|
// Enforce the expected certificate and intended trust policy here.
|
|
}
|
|
DomitoFreeCiValidationResult(&result);
|
|
```
|
|
|
|
This uses the explicit digest helper's [supported PE layout subset](authenticode-digests.md):
|
|
bounded headers, contiguous nonoverlapping raw sections in file order and an EOF
|
|
certificate table. It is not an arbitrary PE/SIP parser. CI can select nested
|
|
signatures according to its algorithm rules, so the helper is deliberately named
|
|
**embedded**, not **force primary**. The matching SHA-256 request selected the
|
|
company primary in the tested BthPS3 layout; another layout may select another
|
|
signer or fail. General enumeration remains separate work.
|
|
|
|
## Support and validation
|
|
|
|
The functions are C-compatible and compile for x64/ARM64. The experimental
|
|
file-object mode is deliberately gated to x64; native forwarding/embedded code
|
|
compilation does not certify every architecture/build's CI runtime ABI. CI
|
|
imports are static and must exist on the target OS, as described in the
|
|
[availability matrix](ci-api-compatibility.md). Structure/chain interpretation
|
|
remains subject to the [mincrypt contracts](mincrypt-contracts.md).
|
|
|
|
The new host suite checks production code forwarding, hash invariants, failures,
|
|
partial allocations, cleanup, result reuse and the non-x64 conditional branch.
|
|
The existing digest suite independently compares Windows SIP and Crypt32 results.
|
|
Kernel compilation covers the full library, public C clients and layout checks.
|
|
CodeIntegrity-RE probe v2 now calls the new APIs; a further kernel run is needed
|
|
to validate these wrappers rather than merely their previously tested raw calls.
|