diff --git a/src/AzureSign.Core/AlgorithmTranslator.cs b/src/AzureSign.Core/AlgorithmTranslator.cs index 0ff06d9..0c2c718 100644 --- a/src/AzureSign.Core/AlgorithmTranslator.cs +++ b/src/AzureSign.Core/AlgorithmTranslator.cs @@ -18,20 +18,16 @@ public static uint HashAlgorithmToAlgId(HashAlgorithmName hashAlgorithmName) throw new NotSupportedException("The algorithm specified is not supported."); } - public static ReadOnlySpan HashAlgorithmToOidAsciiTerminated(HashAlgorithmName hashAlgorithmName) + public static string HashAlgorithmToOidAsciiTerminated(HashAlgorithmName hashAlgorithmName) { if (hashAlgorithmName.Name == HashAlgorithmName.SHA1.Name) - //1.3.14.3.2.26 - return new byte[] { 0x31, 0x2e, 0x33, 0x2e, 0x31, 0x34, 0x2e, 0x33, 0x2e, 0x32, 0x2e, 0x32, 0x36, 0x00 }; + return "1.3.14.3.2.26\0"; if (hashAlgorithmName.Name == HashAlgorithmName.SHA256.Name) - //2.16.840.1.101.3.4.2.1 - return new byte[] { 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x31, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x2e, 0x31, 0x00 }; + return "2.16.840.1.101.3.4.2.1\0"; if (hashAlgorithmName.Name == HashAlgorithmName.SHA384.Name) - //2.16.840.1.101.3.4.2.2 - return new byte[] { 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x31, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x2e, 0x32, 0x00 }; + return "2.16.840.1.101.3.4.2.2\0"; if (hashAlgorithmName.Name == HashAlgorithmName.SHA512.Name) - //2.16.840.1.101.3.4.2.3 - return new byte[] { 0x32, 0x2e, 0x31, 0x36, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x2e, 0x31, 0x30, 0x31, 0x2e, 0x33, 0x2e, 0x34, 0x2e, 0x32, 0x2e, 0x33, 0x00 }; + return "2.16.840.1.101.3.4.2.3\0"; throw new NotSupportedException("The algorithm specified is not supported."); } } diff --git a/src/AzureSign.Core/AuthenticodeKeyVaultSigner.cs b/src/AzureSign.Core/AuthenticodeKeyVaultSigner.cs index d36df3f..ed845e1 100644 --- a/src/AzureSign.Core/AuthenticodeKeyVaultSigner.cs +++ b/src/AzureSign.Core/AuthenticodeKeyVaultSigner.cs @@ -1,11 +1,14 @@ -using AzureSign.Core.Interop; +using static Windows.Win32.PInvoke; +using Windows.Win32.Security.Cryptography; +using AzureSign.Core.Interop; using Microsoft.Extensions.Logging; using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; - +using Windows.Win32.Foundation; + namespace AzureSign.Core { /// @@ -85,74 +88,114 @@ static char[] NullTerminate(ReadOnlySpan str) return result; } - SignerSignEx3Flags flags = SignerSignEx3Flags.SIGN_CALLBACK_UNDOCUMENTED; + SIGNER_SIGN_FLAGS flags = SIGNER_SIGN_FLAGS.SPC_DIGEST_SIGN_FLAG; if (pageHashing == true) { - flags |= SignerSignEx3Flags.SPC_INC_PE_PAGE_HASHES_FLAG; + flags |= SIGNER_SIGN_FLAGS.SPC_INC_PE_PAGE_HASHES_FLAG; } else if (pageHashing == false) { - flags |= SignerSignEx3Flags.SPC_EXC_PE_PAGE_HASHES_FLAG; + flags |= SIGNER_SIGN_FLAGS.SPC_EXC_PE_PAGE_HASHES_FLAG; } - SignerSignTimeStampFlags timeStampFlags; - ReadOnlySpan timestampAlgorithmOid; + SIGNER_TIMESTAMP_FLAGS timeStampFlags; + string? timestampAlgorithmOid = null; string? timestampUrl; switch (_timeStampConfiguration.Type) { case TimeStampType.Authenticode: - timeStampFlags = SignerSignTimeStampFlags.SIGNER_TIMESTAMP_AUTHENTICODE; - timestampAlgorithmOid = default; + timeStampFlags = SIGNER_TIMESTAMP_FLAGS.SIGNER_TIMESTAMP_AUTHENTICODE; timestampUrl = _timeStampConfiguration.Url; break; case TimeStampType.RFC3161: - timeStampFlags = SignerSignTimeStampFlags.SIGNER_TIMESTAMP_RFC3161; + timeStampFlags = SIGNER_TIMESTAMP_FLAGS.SIGNER_TIMESTAMP_RFC3161; timestampAlgorithmOid = AlgorithmTranslator.HashAlgorithmToOidAsciiTerminated(_timeStampConfiguration.DigestAlgorithm); timestampUrl = _timeStampConfiguration.Url; break; default: timeStampFlags = default; - timestampAlgorithmOid = default; timestampUrl = null; break; } - fixed (byte* pTimestampAlgorithm = timestampAlgorithmOid) fixed (char* pTimestampUrl = timestampUrl) fixed (char* pPath = NullTerminate(path)) fixed (char* pDescription = NullTerminate(description)) fixed (char* pDescriptionUrl = NullTerminate(descriptionUrl)) { - var fileInfo = new SIGNER_FILE_INFO(pPath, default); + var fileInfo = new SIGNER_FILE_INFO() + { + cbSize = (uint)Marshal.SizeOf(), + hFile = default, + pwszFileName = pPath, + }; var subjectIndex = 0u; - var signerSubjectInfoUnion = new SIGNER_SUBJECT_INFO_UNION(&fileInfo); - var subjectInfo = new SIGNER_SUBJECT_INFO(&subjectIndex, SignerSubjectInfoUnionChoice.SIGNER_SUBJECT_FILE, signerSubjectInfoUnion); - var authCodeStructure = new SIGNER_ATTR_AUTHCODE(pDescription, pDescriptionUrl); - var storeInfo = new SIGNER_CERT_STORE_INFO( - dwCertPolicy: SignerCertStoreInfoFlags.SIGNER_CERT_POLICY_CHAIN, - hCertStore: _certificateStore.Handle, - pSigningCert: _signingCertificate.Handle - ); - var signerCert = new SIGNER_CERT( - dwCertChoice: SignerCertChoice.SIGNER_CERT_STORE, - union: new SIGNER_CERT_UNION(&storeInfo) - ); - var signatureInfo = new SIGNER_SIGNATURE_INFO( - algidHash: AlgorithmTranslator.HashAlgorithmToAlgId(_fileDigestAlgorithm), - psAuthenticated: IntPtr.Zero, - psUnauthenticated: IntPtr.Zero, - dwAttrChoice: SignerSignatureInfoAttrChoice.SIGNER_AUTHCODE_ATTR, - attrAuthUnion: new SIGNER_SIGNATURE_INFO_UNION(&authCodeStructure) - ); + var subjectInfo = new SIGNER_SUBJECT_INFO + { + cbSize = (uint)Marshal.SizeOf(), + pdwIndex = &subjectIndex, + dwSubjectChoice = SIGNER_SUBJECT_CHOICE.SIGNER_SUBJECT_FILE, + Anonymous = new() { pSignerFileInfo = &fileInfo } + }; + var authCodeStructure = new SIGNER_ATTR_AUTHCODE + { + cbSize = (uint)Marshal.SizeOf(), + fCommercial = false, + fIndividual = false, + pwszName = pDescription, + pwszInfo = pDescriptionUrl, + + }; + + var storeInfo = new SIGNER_CERT_STORE_INFO + { + cbSize = (uint)Marshal.SizeOf(), + dwCertPolicy = SIGNER_CERT_POLICY.SIGNER_CERT_POLICY_CHAIN, + hCertStore = _certificateStore.Handle, + pSigningCert = (CERT_CONTEXT*)_signingCertificate.Handle + }; + + var signerCert = new SIGNER_CERT() + { + cbSize = (uint)Marshal.SizeOf(), + dwCertChoice = SIGNER_CERT_CHOICE.SIGNER_CERT_STORE, + Anonymous = new() { pCertStoreInfo = &storeInfo }, + }; + + var signatureInfo = new SIGNER_SIGNATURE_INFO + { + cbSize = (uint)Marshal.SizeOf(), + algidHash = AlgorithmTranslator.HashAlgorithmToAlgId(_fileDigestAlgorithm), + psAuthenticated = null, + psUnauthenticated = null, + dwAttrChoice = SIGNER_SIGNATURE_ATTRIBUTE_CHOICE.SIGNER_AUTHCODE_ATTR, + Anonymous = new() { pAttrAuthcode = &authCodeStructure } + }; + var callbackPtr = Marshal.GetFunctionPointerForDelegate(_signCallback); - var signCallbackInfo = new SIGN_INFO(callbackPtr); + var signCallbackInfo = new SIGNER_DIGEST_SIGN_INFO + { + cbSize = 24, + Anonymous = new() + { + pfnAuthenticodeDigestSign = + (delegate* unmanaged[Stdcall]< + CERT_CONTEXT*, + CRYPT_INTEGER_BLOB*, + uint, + byte*, + uint, + CRYPT_INTEGER_BLOB*, HRESULT>) + callbackPtr + }, + }; logger?.LogTrace("Getting SIP Data"); var sipKind = SipExtensionFactory.GetSipKind(path); void* sipData = (void*)0; - IntPtr context = IntPtr.Zero; + SIGNER_CONTEXT* pContext = null; switch (sipKind) { @@ -161,35 +204,34 @@ static char[] NullTerminate(ReadOnlySpan str) SIGNER_SIGN_EX3_PARAMS parameters; clientData.pSignerParams = ¶meters; sipData = &clientData; - flags &= ~SignerSignEx3Flags.SPC_INC_PE_PAGE_HASHES_FLAG; - flags |= SignerSignEx3Flags.SPC_EXC_PE_PAGE_HASHES_FLAG; - FillAppxExtension(ref clientData, flags, timeStampFlags, &subjectInfo, &signerCert, &signatureInfo, &context, pTimestampUrl, pTimestampAlgorithm, &signCallbackInfo); + flags &= ~SIGNER_SIGN_FLAGS.SPC_INC_PE_PAGE_HASHES_FLAG; + flags |= SIGNER_SIGN_FLAGS.SPC_EXC_PE_PAGE_HASHES_FLAG; + FillAppxExtension(ref clientData, flags, timeStampFlags, &subjectInfo, &signerCert, &signatureInfo, pContext, pTimestampUrl, timestampAlgorithmOid, &signCallbackInfo); break; } - logger?.LogTrace("Calling SignerSignEx3"); - var result = mssign32.SignerSignEx3 + logger?.LogTrace("Calling SignerSignEx3"); + var result = SignerSignEx3 ( flags, - &subjectInfo, - &signerCert, - &signatureInfo, - IntPtr.Zero, + subjectInfo, + signerCert, + signatureInfo, + null, timeStampFlags, - pTimestampAlgorithm, - pTimestampUrl, - IntPtr.Zero, + timestampAlgorithmOid, + timestampUrl, + null, sipData, - &context, - IntPtr.Zero, - &signCallbackInfo, - IntPtr.Zero + out pContext, + null, + signCallbackInfo ); - if (result == 0 && context != IntPtr.Zero) + if (result == HRESULT.S_OK && pContext != null) { - Debug.Assert(mssign32.SignerFreeSignerContext(context) == 0); + Debug.Assert(SignerFreeSignerContext(pContext) == HRESULT.S_OK); } - if (result == 0 && sipKind == SipKind.Appx) + if (result == HRESULT.S_OK && sipKind == SipKind.Appx) { var state = ((APPX_SIP_CLIENT_DATA*)sipData)->pAppxSipState; if (state != IntPtr.Zero) @@ -208,7 +250,7 @@ public void Dispose() { _chain.Dispose(); _certificateStore.Close(); - } + } private unsafe int SignCallback( IntPtr pCertContext, @@ -216,10 +258,9 @@ private unsafe int SignCallback( uint algId, byte[] pDigestToSign, uint dwDigestToSign, - ref CRYPTOAPI_BLOB blob + ref CRYPT_INTEGER_BLOB blob ) { - const int E_INVALIDARG = unchecked((int)0x80070057); byte[] digest; switch (_signingAlgorithm) { @@ -230,26 +271,26 @@ ref CRYPTOAPI_BLOB blob digest = ecdsa.SignHash(pDigestToSign); break; default: - return E_INVALIDARG; + return HRESULT.E_INVALIDARG; } var resultPtr = Marshal.AllocHGlobal(digest.Length); Marshal.Copy(digest, 0, resultPtr, digest.Length); - blob.pbData = resultPtr; + blob.pbData = (byte*)resultPtr; blob.cbData = (uint)digest.Length; - return 0; + return HRESULT.S_OK; } private static unsafe void FillAppxExtension( ref APPX_SIP_CLIENT_DATA clientData, - SignerSignEx3Flags flags, - SignerSignTimeStampFlags timestampFlags, + SIGNER_SIGN_FLAGS flags, + SIGNER_TIMESTAMP_FLAGS timestampFlags, SIGNER_SUBJECT_INFO* signerSubjectInfo, SIGNER_CERT* signerCert, SIGNER_SIGNATURE_INFO* signatureInfo, - IntPtr* signerContext, + SIGNER_CONTEXT* signerContext, char* timestampUrl, - byte* timestampOid, - SIGN_INFO* signInfo + string? timestampOid, + SIGNER_DIGEST_SIGN_INFO* signInfo ) { clientData.pSignerParams->dwFlags = flags; diff --git a/src/AzureSign.Core/AzureSign.Core.csproj b/src/AzureSign.Core/AzureSign.Core.csproj index 841af99..faaf263 100644 --- a/src/AzureSign.Core/AzureSign.Core.csproj +++ b/src/AzureSign.Core/AzureSign.Core.csproj @@ -12,6 +12,8 @@ + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/AzureSign.Core/Interop/crypt32.cs b/src/AzureSign.Core/Interop/crypt32.cs deleted file mode 100644 index 08e68f3..0000000 --- a/src/AzureSign.Core/Interop/crypt32.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace AzureSign.Core.Interop -{ - internal static class crypt32 - { - [return: MarshalAs(UnmanagedType.Bool)] - [method: DllImport(nameof(crypt32), CallingConvention = CallingConvention.Winapi, SetLastError = true)] - public static extern bool CertCloseStore - ( - [In, MarshalAs(UnmanagedType.SysInt)] IntPtr hCertStore, - [In, MarshalAs(UnmanagedType.U4)] CertCloreStoreFlags dwFlags - ); - - [return: MarshalAs(UnmanagedType.SysInt)] - [method: DllImport(nameof(crypt32), CallingConvention = CallingConvention.Winapi, SetLastError = true)] - public static extern IntPtr CertOpenStore - ( - [In, MarshalAs(UnmanagedType.LPStr)] string lpszStoreProvider, - [In, MarshalAs(UnmanagedType.U4)] CertEncodingType CertEncodingType, - [In, MarshalAs(UnmanagedType.SysInt)] IntPtr hCryptProv, - [In, MarshalAs(UnmanagedType.U4)] CertOpenStoreFlags dwFlags, - [In, MarshalAs(UnmanagedType.SysInt)] IntPtr pvPara - ); - } - - [type: StructLayout(LayoutKind.Sequential)] - internal struct SIGNER_CERT_STORE_INFO - { - public uint cbSize; - public IntPtr pSigningCert; - public SignerCertStoreInfoFlags dwCertPolicy; - public IntPtr hCertStore; - - public SIGNER_CERT_STORE_INFO(IntPtr pSigningCert, SignerCertStoreInfoFlags dwCertPolicy, IntPtr hCertStore) - { - this.cbSize = (uint)Marshal.SizeOf(); - this.pSigningCert = pSigningCert; - this.dwCertPolicy = dwCertPolicy; - this.hCertStore = hCertStore; - } - } - - [type: Flags] - internal enum SignerCertStoreInfoFlags - { - - SIGNER_CERT_POLICY_CHAIN = 0x02, - SIGNER_CERT_POLICY_CHAIN_NO_ROOT = 0x08, - SIGNER_CERT_POLICY_STORE = 0x01 - } - - [type: Flags] - internal enum CertOpenStoreFlags : uint - { - NONE = 0, - CERT_STORE_NO_CRYPT_RELEASE_FLAG = 0x00000001, - CERT_STORE_SET_LOCALIZED_NAME_FLAG = 0x00000002, - CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG = 0x00000004, - CERT_STORE_DELETE_FLAG = 0x00000010, - CERT_STORE_UNSAFE_PHYSICAL_FLAG = 0x00000020, - CERT_STORE_SHARE_STORE_FLAG = 0x00000040, - CERT_STORE_SHARE_CONTEXT_FLAG = 0x00000080, - CERT_STORE_MANIFOLD_FLAG = 0x00000100, - CERT_STORE_ENUM_ARCHIVED_FLAG = 0x00000200, - CERT_STORE_UPDATE_KEYID_FLAG = 0x00000400, - CERT_STORE_BACKUP_RESTORE_FLAG = 0x00000800, - CERT_STORE_READONLY_FLAG = 0x00008000, - CERT_STORE_OPEN_EXISTING_FLAG = 0x00004000, - CERT_STORE_CREATE_NEW_FLAG = 0x00002000, - CERT_STORE_MAXIMUM_ALLOWED_FLAG = 0x00001000, - } - - [type: Flags] - internal enum CertCloreStoreFlags : uint - { - NONE = 0, - CERT_CLOSE_STORE_FORCE_FLAG = 0x00000001, - CERT_CLOSE_STORE_CHECK_FLAG = 0x00000002, - } - - internal enum CertEncodingType : uint - { - NONE = 0, - X509_ASN_ENCODING = 0x1, - PKCS_7_ASN_ENCODING = 0x10000 - } -} diff --git a/src/AzureSign.Core/Interop/mssign32.cs b/src/AzureSign.Core/Interop/mssign32.cs index 196121e..4b1880e 100644 --- a/src/AzureSign.Core/Interop/mssign32.cs +++ b/src/AzureSign.Core/Interop/mssign32.cs @@ -1,244 +1,24 @@ using System; using System.Runtime.InteropServices; +using Windows.Win32.Security.Cryptography; namespace AzureSign.Core.Interop { - internal static class mssign32 - { - [method: DllImport(nameof(mssign32), EntryPoint = "SignerSignEx3", CallingConvention = CallingConvention.Winapi)] - public static unsafe extern int SignerSignEx3 - ( - [param: In, MarshalAs(UnmanagedType.U4)] SignerSignEx3Flags dwFlags, - [param: In] SIGNER_SUBJECT_INFO* pSubjectInfo, - [param: In] SIGNER_CERT* pSignerCert, - [param: In] SIGNER_SIGNATURE_INFO* pSignatureInfo, - [param: In] IntPtr pProviderInfo, - [param: In] SignerSignTimeStampFlags dwTimestampFlags, - [param: In] byte* pszTimestampAlgorithmOid, - [param: In] char* pwszHttpTimeStamp, - [param: In] IntPtr psRequest, - [param: In] void* pSipData, - [param: In] IntPtr* ppSignerContext, - [param: In] IntPtr pCryptoPolicy, - [param: In] SIGN_INFO* pSignInfo, - [param: In] IntPtr pReserved - ); - - [method: DllImport(nameof(mssign32), CallingConvention = CallingConvention.Winapi)] - public static extern int SignerFreeSignerContext( - [param: In] IntPtr pSignerContext - ); - } - - [type: StructLayout(LayoutKind.Sequential)] - internal struct SIGNER_SIGNATURE_INFO - { - public uint cbSize; - public uint algidHash; - public SignerSignatureInfoAttrChoice dwAttrChoice; - public SIGNER_SIGNATURE_INFO_UNION attrAuthUnion; - public IntPtr psAuthenticated; - public IntPtr psUnauthenticated; - - public SIGNER_SIGNATURE_INFO(uint algidHash, - SignerSignatureInfoAttrChoice dwAttrChoice, - SIGNER_SIGNATURE_INFO_UNION attrAuthUnion, - IntPtr psAuthenticated, - IntPtr psUnauthenticated - ) - { - cbSize = (uint)Marshal.SizeOf(); - this.algidHash = algidHash; - this.dwAttrChoice = dwAttrChoice; - this.attrAuthUnion = attrAuthUnion; - this.psAuthenticated = psAuthenticated; - this.psUnauthenticated = psUnauthenticated; - } - } - - [type: StructLayout(LayoutKind.Explicit)] - internal unsafe struct SIGNER_SIGNATURE_INFO_UNION - { - public SIGNER_SIGNATURE_INFO_UNION(SIGNER_ATTR_AUTHCODE* pAttrAuthcode) - { - this.pAttrAuthcode = pAttrAuthcode; - } - - [field: FieldOffset(0)] - public SIGNER_ATTR_AUTHCODE* pAttrAuthcode; - } - - internal enum SignerSignTimeStampFlags : uint - { - SIGNER_TIMESTAMP_AUTHENTICODE = 1, - SIGNER_TIMESTAMP_RFC3161 = 2, - } - - internal enum SignerSignatureInfoAttrChoice : uint - { - SIGNER_AUTHCODE_ATTR = 1, - SIGNER_NO_ATTR = 0 - } - - - [type: StructLayout(LayoutKind.Sequential)] - internal struct SIGNER_CERT - { - public uint cbSize; - public SignerCertChoice dwCertChoice; - public SIGNER_CERT_UNION union; - public IntPtr hwnd; - - public SIGNER_CERT(SignerCertChoice dwCertChoice, SIGNER_CERT_UNION union) - { - this.dwCertChoice = dwCertChoice; - this.union = union; - hwnd = default; - cbSize = (uint)Marshal.SizeOf(); - } - } - - [type: StructLayout(LayoutKind.Explicit)] - internal unsafe struct SIGNER_CERT_UNION - { - public SIGNER_CERT_UNION(SIGNER_CERT_STORE_INFO* certStoreInfo) - { - pSpcChainInfo = certStoreInfo; - } - - [field: FieldOffset(0)] - public SIGNER_CERT_STORE_INFO* pSpcChainInfo; - } - - internal enum SignerCertChoice : uint - { - SIGNER_CERT_SPC_FILE = 1, - SIGNER_CERT_STORE = 2, - SIGNER_CERT_SPC_CHAIN = 3 - } - - [type: Flags] - internal enum SignerSignEx3Flags : uint - { - NONE = 0x0, - SPC_EXC_PE_PAGE_HASHES_FLAG = 0x010, - SPC_INC_PE_IMPORT_ADDR_TABLE_FLAG = 0x020, - SPC_INC_PE_DEBUG_INFO_FLAG = 0x040, - SPC_INC_PE_RESOURCES_FLAG = 0x080, - SPC_INC_PE_PAGE_HASHES_FLAG = 0x100, - SIGN_CALLBACK_UNDOCUMENTED = 0X400, - SIG_APPEND = 0x1000 - } - - [type: StructLayout(LayoutKind.Sequential)] - internal unsafe struct SIGNER_SUBJECT_INFO - { - public uint cbSize; - public uint* pdwIndex; - public SignerSubjectInfoUnionChoice dwSubjectChoice; - public SIGNER_SUBJECT_INFO_UNION unionInfo; - - public SIGNER_SUBJECT_INFO(uint* pdwIndex, SignerSubjectInfoUnionChoice dwSubjectChoice, SIGNER_SUBJECT_INFO_UNION unionInfo) - { - cbSize = (uint)Marshal.SizeOf(); - this.pdwIndex = pdwIndex; - this.dwSubjectChoice = dwSubjectChoice; - this.unionInfo = unionInfo; - } - } - - [type: StructLayout(LayoutKind.Explicit)] - internal unsafe struct SIGNER_SUBJECT_INFO_UNION - { - [FieldOffset(0)] - public SIGNER_FILE_INFO* file; - - public SIGNER_SUBJECT_INFO_UNION(SIGNER_FILE_INFO* file) - { - this.file = file; - } - } - - [type: StructLayout(LayoutKind.Sequential)] - internal unsafe struct SIGNER_FILE_INFO - { - public uint cbSize; - public char* pwszFileName; - public IntPtr hFile; - - public SIGNER_FILE_INFO(char* pwszFileName, IntPtr hFile) - { - cbSize = (uint)Marshal.SizeOf(); - this.pwszFileName = pwszFileName; - this.hFile = hFile; - } - } - - internal enum SignerSubjectInfoUnionChoice : uint - { - SIGNER_SUBJECT_BLOB = 0x02, - SIGNER_SUBJECT_FILE = 0x01 - } - - [type: StructLayout(LayoutKind.Sequential)] - internal struct SIGN_INFO - { - public uint cbSize; - - public IntPtr callback; - - public IntPtr pvOpaque; - - public SIGN_INFO(IntPtr callback) - { - cbSize = (uint)Marshal.SizeOf(); - this.callback = callback; - pvOpaque = default; - } - } - - - [type: StructLayout(LayoutKind.Sequential)] - internal struct CRYPTOAPI_BLOB - { - public uint cbData; - public IntPtr pbData; - } - - [type: StructLayout(LayoutKind.Sequential)] - internal unsafe struct SIGNER_ATTR_AUTHCODE - { - public uint cbSize; - public uint fCommercial; - public uint fIndividual; - - public char* pwszName; - public char* pwszInfo; - - public SIGNER_ATTR_AUTHCODE(char* pwszName, char* pwszInfo) - { - cbSize = (uint)Marshal.SizeOf(); - fCommercial = 0; - fIndividual = 0; - this.pwszName = pwszName; - this.pwszInfo = pwszInfo; - } - } - + [type: StructLayout(LayoutKind.Sequential)] internal unsafe struct SIGNER_SIGN_EX3_PARAMS { - public SignerSignEx3Flags dwFlags; + public SIGNER_SIGN_FLAGS dwFlags; public SIGNER_SUBJECT_INFO* pSubjectInfo; public SIGNER_CERT* pSignerCert; public SIGNER_SIGNATURE_INFO* pSignatureInfo; public IntPtr pProviderInfo; - public SignerSignTimeStampFlags dwTimestampFlags; - public byte* pszTimestampAlgorithmOid; + public SIGNER_TIMESTAMP_FLAGS dwTimestampFlags; + public string? pszTimestampAlgorithmOid; public char* pwszHttpTimeStamp; public IntPtr psRequest; - public SIGN_INFO* pSignCallBack; - public IntPtr* ppSignerContext; + public SIGNER_DIGEST_SIGN_INFO* pSignCallBack; + public SIGNER_CONTEXT* ppSignerContext; public IntPtr pCryptoPolicy; public IntPtr pReserved; } @@ -258,6 +38,6 @@ internal delegate int SignCallback( [param: In, MarshalAs(UnmanagedType.U4)] uint algId, [param: In, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 4)] byte[] pDigestToSign, [param: In, MarshalAs(UnmanagedType.U4)] uint dwDigestToSign, - [param: In, Out] ref CRYPTOAPI_BLOB blob + [param: In, Out] ref CRYPT_INTEGER_BLOB blob ); } diff --git a/src/AzureSign.Core/MemoryCertificateStore.cs b/src/AzureSign.Core/MemoryCertificateStore.cs index d7330dc..8aae918 100644 --- a/src/AzureSign.Core/MemoryCertificateStore.cs +++ b/src/AzureSign.Core/MemoryCertificateStore.cs @@ -1,4 +1,5 @@ -using AzureSign.Core.Interop; +using static Windows.Win32.PInvoke; +using Windows.Win32.Security.Cryptography; using System; using System.Diagnostics; using System.Security.Cryptography.X509Certificates; @@ -27,22 +28,22 @@ private MemoryCertificateStore(IntPtr handle) } } - public static MemoryCertificateStore Create() + public unsafe static MemoryCertificateStore Create() { const string STORE_TYPE = "Memory"; - var handle = crypt32.CertOpenStore(STORE_TYPE, CertEncodingType.NONE, IntPtr.Zero, CertOpenStoreFlags.NONE, IntPtr.Zero); - if (handle == IntPtr.Zero) + var handle = CertOpenStore(STORE_TYPE, 0, (HCRYPTPROV_LEGACY)0, 0, (void*)IntPtr.Zero); + if (handle == (void*)IntPtr.Zero) { throw new InvalidOperationException("Failed to create a memory certificate store."); } - return new MemoryCertificateStore(handle); + return new MemoryCertificateStore((IntPtr)(void*)handle); } public void Close() => Dispose(true); void IDisposable.Dispose() => Dispose(true); ~MemoryCertificateStore() => Dispose(false); - public IntPtr Handle => _store.StoreHandle; + public unsafe HCERTSTORE Handle => (HCERTSTORE)(void*)_store.StoreHandle; public void Add(X509Certificate2 certificate) => _store.Add(certificate); public void Add(X509Certificate2Collection collection) => _store.AddRange(collection); public X509Certificate2Collection Certificates => _store.Certificates; @@ -59,11 +60,11 @@ private void Dispose(bool disposing) FreeHandle(); } - private void FreeHandle() + private unsafe void FreeHandle() { if (_handle != IntPtr.Zero) { - var closed = crypt32.CertCloseStore(_handle, CertCloreStoreFlags.NONE); + var closed = CertCloseStore((HCERTSTORE)(void *)_handle, 0); _handle = IntPtr.Zero; Debug.Assert(closed); } diff --git a/src/AzureSign.Core/NativeMethods.txt b/src/AzureSign.Core/NativeMethods.txt new file mode 100644 index 0000000..20f540a --- /dev/null +++ b/src/AzureSign.Core/NativeMethods.txt @@ -0,0 +1,13 @@ +CertOpenStore +CertCloseStore +SignerSignEx +SignerFreeSignerContext +SignerSignEx3 +PFN_AUTHENTICODE_DIGEST_SIGN +E_INVALIDARG +S_OK + +// Not yet documented: + +// APPX_SIP_CLIENT_DATA +// SIGNER_SIGN_EX3_PARAMS diff --git a/test/AzureSign.Core.Tests/AlgorithmTranslatorTests.cs b/test/AzureSign.Core.Tests/AlgorithmTranslatorTests.cs index 67bd81e..4dd29a7 100644 --- a/test/AzureSign.Core.Tests/AlgorithmTranslatorTests.cs +++ b/test/AzureSign.Core.Tests/AlgorithmTranslatorTests.cs @@ -23,7 +23,7 @@ public void ShouldTranslateNameToAsciiEncodedNullTerminatedOID(HashAlgorithmName expectedBytes.Fill(0); Encoding.ASCII.GetBytes(oid, expectedBytes); var actualBytes = AlgorithmTranslator.HashAlgorithmToOidAsciiTerminated(name); - Assert.True(expectedBytes.SequenceEqual(actualBytes), "ExpectedBytes do not equal actual bytes."); + Assert.True(expectedBytes.SequenceEqual(Encoding.ASCII.GetBytes(actualBytes)), "ExpectedBytes do not equal actual bytes."); } [Fact] diff --git a/test/AzureSign.Core.Tests/MemoryCertificateStoreTests.cs b/test/AzureSign.Core.Tests/MemoryCertificateStoreTests.cs index 3ce379c..d9480ba 100644 --- a/test/AzureSign.Core.Tests/MemoryCertificateStoreTests.cs +++ b/test/AzureSign.Core.Tests/MemoryCertificateStoreTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Security.Cryptography.X509Certificates; using Xunit; using AzureSign.Core; @@ -11,7 +11,7 @@ public class MemoryCertificateStoreTests public void ShouldCreateAndDisposeAMemoryCertificateStore() { var store = MemoryCertificateStore.Create(); - Assert.NotEqual(IntPtr.Zero, store.Handle); + Assert.NotEqual(default, store.Handle); Assert.Empty(store.Certificates); store.Close(); }