From ff50c4a4c9b25abd88cf8a4a47f92c56e0fd4a94 Mon Sep 17 00:00:00 2001 From: David Hall Date: Thu, 7 Sep 2023 14:05:46 -0600 Subject: [PATCH] Updated CryptUI. CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO and CRYPTUI_WIZ_DIGITAL_SIGN_CERT_PVK_INFO and CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT with better ctors and enums. --- PInvoke/Cryptography/CryptUI/Wincrypt.cs | 39 ++++++++++++++++-- UnitTests/PInvoke/Cryptography/CryptUITests.cs | 57 ++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 UnitTests/PInvoke/Cryptography/CryptUITests.cs diff --git a/PInvoke/Cryptography/CryptUI/Wincrypt.cs b/PInvoke/Cryptography/CryptUI/Wincrypt.cs index cfa41135..cdafd815 100644 --- a/PInvoke/Cryptography/CryptUI/Wincrypt.cs +++ b/PInvoke/Cryptography/CryptUI/Wincrypt.cs @@ -1,4 +1,5 @@ -using System; +#nullable enable +using System; using System.Runtime.InteropServices; using Vanara.Extensions; using Vanara.InteropServices; @@ -26,6 +27,17 @@ namespace Vanara.PInvoke [return: MarshalAs(UnmanagedType.Bool)] public delegate bool PFNCFILTERPROC(PCCERT_CONTEXT pCertContext, [MarshalAs(UnmanagedType.Bool)] ref bool pfInitialSelectedCert, IntPtr pvCallbackData); + /// Specifies the type of entity that contains the certificates. + [PInvokeData("cryptuiapi.h", MSDNShortId = "0316ed0b-d4e5-4102-9ab0-637e96c7d9f5")] + public enum CRYPTUI_WIZ_DIGITAL_SIGN_PVK : uint + { + /// The entity is a PVK file. + CRYPTUI_WIZ_DIGITAL_SIGN_PVK_FILE = 1, + + /// The entity is a PVK provider. + CRYPTUI_WIZ_DIGITAL_SIGN_PVK_PROV = 2 + } + /// Flags that can be combined to exclude columns of the display. [PInvokeData("cryptuiapi.h", MSDNShortId = "5774af1c-f2d4-4b1e-a20b-dfb57bf9aa37")] [Flags] @@ -1240,7 +1252,7 @@ namespace Vanara.PInvoke /// /// A pointer to a GUID that contains the GUID that identifies the Session Initiation Protocol (SIP) functions to load. /// - public IntPtr pGuidSubject; + public GuidPtr pGuidSubject; /// The size, in bytes, of the BLOB pointed to by the pbBlob member. public uint cbBlob; @@ -1249,7 +1261,20 @@ namespace Vanara.PInvoke public IntPtr pbBlob; /// A pointer to a null-terminated Unicode string that contains the display name of the BLOB to sign. - [MarshalAs(UnmanagedType.LPWStr)] public string pwszDisplayName; + [MarshalAs(UnmanagedType.LPWStr)] public string? pwszDisplayName; + + /// Initializes a new instance of the struct. + /// The handle of allocated memory with blob data. + /// The display name of the blob. + /// The Session Initiation Protocol (SIP) functions GUID. + public CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO(ISafeMemoryHandle h, string? name = null, GuidPtr subject = default) + { + dwSize = (uint)Marshal.SizeOf(typeof(CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO)); + cbBlob = (uint)h.Size; + pbBlob = h.DangerousGetHandle(); + pwszDisplayName = name; + pGuidSubject = subject; + } } /// @@ -1295,7 +1320,7 @@ namespace Vanara.PInvoke /// /// /// - public uint dwPvkChoice; + public CRYPTUI_WIZ_DIGITAL_SIGN_PVK dwPvkChoice; /// /// A pointer to a CRYPTUI_WIZ_DIGITAL_SIGN_PVK_FILE_INFO structure that contains the PVK file that contains the certificates. @@ -1333,6 +1358,12 @@ namespace Vanara.PInvoke /// A pointer to the signed BLOB. public IntPtr pbBlob; + + /// Creates and instance of from a memory handle. + /// The memory handle. + /// A filled instance of . + public static CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT FromMemHandle(ISafeMemoryHandle h) => + new() { dwSize = (uint)Marshal.SizeOf(typeof(CRYPTUI_WIZ_DIGITAL_SIGN_CONTEXT)), cbBlob = (uint)h.Size, pbBlob = h.DangerousGetHandle() }; } /// diff --git a/UnitTests/PInvoke/Cryptography/CryptUITests.cs b/UnitTests/PInvoke/Cryptography/CryptUITests.cs new file mode 100644 index 00000000..b840a4bd --- /dev/null +++ b/UnitTests/PInvoke/Cryptography/CryptUITests.cs @@ -0,0 +1,57 @@ +using NUnit.Framework; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using Vanara.InteropServices; +using static Vanara.PInvoke.Crypt32; +using static Vanara.PInvoke.CryptUI; + +namespace Vanara.PInvoke.Tests; + +[TestFixture] +public class CryptUITests +{ + [Test] + public void CryptUIWizDigitalSignTest() + { + using var cert = new X509Certificate2(TestCaseSources.TempDirWhack + "test.cer", "~CertPassword~"); + using var pBlob = new SafeHGlobalHandle(System.IO.File.ReadAllBytes(TestCaseSources.ResourceFile)); + using var pBlobInfo = new SafeHGlobalStruct(new CRYPTUI_WIZ_DIGITAL_SIGN_BLOB_INFO(pBlob)); + + CRYPTUI_WIZ_DIGITAL_SIGN_INFO signInfo = new() + { + dwSize = (uint)Marshal.SizeOf(typeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO)), + dwSubjectChoice = CryptUIWizToSign.CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_BLOB, + ToSign = new() { pSignBlobInfo = pBlobInfo }, + dwSigningCertChoice = CryptUIWizSignLoc.CRYPTUI_WIZ_DIGITAL_SIGN_CERT, + pSigningCertObject = cert.Handle, + }; + + Assert.That(CryptUIWizDigitalSign(CryptUIWizFlags.CRYPTUI_WIZ_NO_UI, default, default, signInfo, out _), ResultIs.Successful); + } + + [Test] + public void CryptUIWizDigitalSignFileTest() + { + using var cert = new X509Certificate2(TestCaseSources.TempDirWhack + "test.cer", "~CertPassword~"); + using SafeCoTaskMemString pFile = new(TestCaseSources.ResourceFile); + + var signInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO() + { + dwSize = (uint)Marshal.SizeOf(typeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO)), + dwSubjectChoice = CryptUIWizToSign.CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE, + ToSign = new() { pwszFileName = (System.IntPtr)pFile }, + dwSigningCertChoice = CryptUIWizSignLoc.CRYPTUI_WIZ_DIGITAL_SIGN_CERT, + pSigningCertObject = cert.Handle, + }; + + Assert.That(CryptUIWizDigitalSign(CryptUIWizFlags.CRYPTUI_WIZ_NO_UI, default, default, signInfo, out _), ResultIs.Successful); + } + + [Test] + public void WizTest() + { + var signInfo = new CRYPTUI_WIZ_DIGITAL_SIGN_INFO() { dwSize = (uint)Marshal.SizeOf(typeof(CRYPTUI_WIZ_DIGITAL_SIGN_INFO)), }; + Assert.That(CryptUIWizDigitalSign(0, default, default, signInfo, out _), ResultIs.Successful); + } +} \ No newline at end of file