#:property PublishAot=false #:property UseAppHost=false #:property AssemblyName=WineSdkTrust using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; if (args.Length != 3 || (args[0] != "--validate" && args[0] != "--import")) { Console.Error.WriteLine("Usage: WineSdkTrust <--validate|--import> "); return 2; } var import = args[0] == "--import"; if (import && (!OperatingSystem.IsWindows() || !IsWine())) { Console.Error.WriteLine("REFUSED: --import requires Windows under Wine (ntdll.dll!wine_get_version). No certificate store was opened."); return 2; } Console.WriteLine($"OS: {RuntimeInformation.OSDescription}"); Console.WriteLine($"Runtime: {RuntimeInformation.FrameworkDescription}"); Console.WriteLine($"Mode: {args[0]}"); var certificates = new X509Certificate2Collection(); try { foreach (var path in args.Skip(1)) { if (!File.Exists(path) || new FileInfo(path).Length == 0) { throw new InvalidDataException($"The SDK certificate bundle is missing or empty: {path}"); } var bundle = new X509Certificate2Collection(); try { bundle.ImportFromPemFile(path); if (bundle.Count == 0) { throw new InvalidDataException($"The SDK bundle contains no PEM certificates: {path}"); } var legacyRoots = 0; foreach (var certificate in bundle) { if (certificate.HasPrivateKey) { throw new InvalidDataException($"The SDK bundle must contain public certificates only: {certificate.Thumbprint}"); } var constraints = certificate.Extensions.OfType().SingleOrDefault(); if (constraints is { CertificateAuthority: false }) { throw new InvalidDataException($"The SDK bundle contains a non-CA certificate: {certificate.Thumbprint}"); } if (constraints is null) { // Microsoft also ships historical roots without the BasicConstraints extension. if (!certificate.SubjectName.RawData.AsSpan().SequenceEqual(certificate.IssuerName.RawData)) { throw new InvalidDataException($"A certificate without CA constraints is not self-issued: {certificate.Thumbprint}"); } legacyRoots++; } } Console.WriteLine($"Bundle: {Path.GetFullPath(path)}"); Console.WriteLine($" SHA256: {Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))}"); Console.WriteLine($" Certificates: {bundle.Count}; historical self-issued roots without BasicConstraints: {legacyRoots}"); certificates.AddRange(bundle); bundle.Clear(); } finally { foreach (var certificate in bundle) { certificate.Dispose(); } } } var thumbprints = certificates.Select(certificate => certificate.Thumbprint).ToHashSet(StringComparer.OrdinalIgnoreCase); Console.WriteLine($"Unique SDK certificate thumbprints: {thumbprints.Count}"); if (!import) { Console.WriteLine("PASS: both SDK bundles validated; no certificate store was opened."); return 0; } using (var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) { store.Open(OpenFlags.ReadWrite); store.AddRange(certificates); } using (var store = new X509Store(StoreName.Root, StoreLocation.CurrentUser)) { store.Open(OpenFlags.ReadOnly); var installed = store.Certificates; try { var installedThumbprints = installed.Select(certificate => certificate.Thumbprint).ToHashSet(StringComparer.OrdinalIgnoreCase); var missing = thumbprints.Except(installedThumbprints).ToArray(); if (missing.Length != 0) { throw new CryptographicException($"SDK certificates missing after import: {string.Join(", ", missing)}"); } } finally { foreach (var certificate in installed) { certificate.Dispose(); } } } Console.WriteLine($"PASS: all {thumbprints.Count} SDK certificate thumbprints verified in CurrentUser Root."); return 0; } catch (Exception exception) { Console.Error.WriteLine($"FAIL: {exception.GetType().Name}: {exception.Message}"); return 1; } finally { foreach (var certificate in certificates) { certificate.Dispose(); } } static bool IsWine() { if (!NativeLibrary.TryLoad("ntdll.dll", out var library)) { return false; } try { return NativeLibrary.TryGetExport(library, "wine_get_version", out _); } finally { NativeLibrary.Free(library); } }