Files
meeting-assistant/docs/wine-sdk-trust.md
T
dh 728e66dd72
PR and Push Build/Test / windows-build-and-test (push) Failing after 38m25s
PR and Push Build/Test / portable-build-and-test (push) Successful in 8m9s
PR and Push Build/Test / macos-native-full (push) Skipped
ci: consolidate platform pipelines and test prerequisites on macOS support
2026-10-06 09:02:19 +02:00

4.7 KiB

Wine SDK certificate trust

scripts/wine-sdk-trust.cs is a .NET 10 file-based helper for validating the public root-certificate bundles distributed with the Microsoft SDK and importing them into a disposable Wine prefix's Windows CurrentUser Root store. It does not disable NuGet signature verification or certificate checks and does not import private keys.

dotnet publish scripts/wine-sdk-trust.cs -c Release -p:UseAppHost=false -p:PublishAot=false -o artifacts/wine-sdk-trust
dotnet artifacts/wine-sdk-trust/WineSdkTrust.dll --validate /path/to/sdk/trustedroots/codesignctl.pem /path/to/sdk/trustedroots/timestampctl.pem

Validation is read-only on every OS. Both files must exist and contain public PEM certificates. Explicit non-CA certificates are rejected. Historical self-issued SDK roots without BasicConstraints remain valid; certificate expiry is not filtered because trusted bundles also support historical signatures. The helper logs each bundle's certificate count and SHA-256, then the unique certificate count. Use bundles from the verified Microsoft SDK archive and retain those hashes with the SDK provenance.

For the Windows SDK installed inside a disposable Wine prefix, invoke the published DLL with --import and the two authoritative Linux SDK bundle paths. From the repository root after installing the matching Windows SDK, for example:

export WINEPREFIX="${RUNNER_TEMP}/meeting-assistant-wine"
SDK_VERSION="$(dotnet --version)"
"${WINE_BIN}" "${WIN_DOTNET_DIR}/dotnet.exe" "Z:${PWD}/artifacts/wine-sdk-trust/WineSdkTrust.dll" --import \
  "Z:${DOTNET_ROOT}/sdk/${SDK_VERSION}/trustedroots/codesignctl.pem" \
  "Z:${DOTNET_ROOT}/sdk/${SDK_VERSION}/trustedroots/timestampctl.pem"

The import mode first requires OperatingSystem.IsWindows() and the Wine-specific wine_get_version export from ntdll.dll, located with NativeLibrary.TryLoad and TryGetExport. Native Windows is rejected as well as macOS/Linux. Only after both bundles validate does it open CurrentUser Root for writing and call AddRange. It closes the store, reopens it read-only and asserts that every imported thumbprint is present. There is no localized shell command, interactive prompt or GUI automation. Missing/unknown arguments and import attempts outside Wine return 2; validation/import failures return 1; successful validation or verified import returns 0.

The write side effect is confined to the selected Wine prefix's current-user root store. Repeated imports are safe. Run it only against the disposable CI prefix. Native validation never opens any certificate store, and native import attempts are rejected before parsing bundles or constructing a store. The normal PR workflow publishes this DLL and imports the bundles before restoring/building both projects for net10.0-windows10.0.19041.0. It retains helper-build and import/readback logs in artifacts/tests/windows/, alongside Windows discovery, TRX and verifier results. Trust-helper success does not replace a passing actual Windows test run; the Windows .NET SDK must build, discover and execute the Windows TFM, as described in platform test verification.

Microsoft documents that these SDK bundles originate from its Trusted Root Program and provide code-signing and timestamping roots. The Windows NuGet restore remains responsible for checking actual package signatures; this helper populates the Wine store used for those checks.

Local qualification on 2026-10-03 used SDK 10.0.203 to publish the DLL and the authoritative bundles from SDK 10.0.401 to validate it on macOS/.NET 10.0.7. Both bundles passed: codesign contained 307 certificates including seven historical roots without constraints; timestamp contained 327 including two such roots; the union contained 372 unique thumbprints. Their SHA-256 hashes were AAB671F52E5229906B2100727370007EF4B6D2E360B23F2CF12A6D87773BE611 and 5CCB03367B52F047099F07E1653160E8578A83711CB18560C979FEBB65F8CB5D, respectively. A native --import invocation with those same paths returned 2 before parsing bundles or opening a store; unknown arguments returned 2, and an empty input returned 1. No local store import was performed. This is helper qualification, not a passing Wine/NuGet result.

Gitea run 4154 on 2026-10-03 subsequently imported and read back all 372 thumbprints under Wine 11 and completed Windows desktop restore without suppressing NuGet signature verification. Its later MakePRI build failure and the direct core-package correction are recorded in Windows builds under Wine. That historical restore result does not prove the current Windows test target or application build.