From 175542dbaada3e91c574f281bfc21b8675925add Mon Sep 17 00:00:00 2001 From: Jan Vratislav Date: Sat, 9 Nov 2019 16:51:25 +0100 Subject: [PATCH] Adding source code --- src/MSBuildCode/IClrStrongName.cs | 98 +++++++ src/MSBuildCode/IClrStrongNameUsingIntPtr.cs | 98 +++++++ src/MSBuildCode/ResolveKeySourceTask.cs | 110 ++++++++ src/MSBuildCode/StrongNameHelpers.cs | 268 +++++++++++++++++++ src/SnInstallPfx.cs | 79 ++++++ src/SnInstallPfx.csproj | 12 + src/SnInstallPfx.sln | 25 ++ 7 files changed, 690 insertions(+) create mode 100644 src/MSBuildCode/IClrStrongName.cs create mode 100644 src/MSBuildCode/IClrStrongNameUsingIntPtr.cs create mode 100644 src/MSBuildCode/ResolveKeySourceTask.cs create mode 100644 src/MSBuildCode/StrongNameHelpers.cs create mode 100644 src/SnInstallPfx.cs create mode 100644 src/SnInstallPfx.csproj create mode 100644 src/SnInstallPfx.sln diff --git a/src/MSBuildCode/IClrStrongName.cs b/src/MSBuildCode/IClrStrongName.cs new file mode 100644 index 0000000..c2c0e98 --- /dev/null +++ b/src/MSBuildCode/IClrStrongName.cs @@ -0,0 +1,98 @@ +namespace MSBuildCode +{ + using System; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Security; + + /// + /// Exported using ILSpy from Microsoft.Build.Tasks.Core.dll + /// + [ComImport] + [SecurityCritical] + [ComConversionLoss] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D")] + internal interface IClrStrongName + { + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromAssemblyFile([In] [MarshalAs(UnmanagedType.LPStr)] string pszFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromAssemblyFileW([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromBlob([In] IntPtr pbBlob, [In] [MarshalAs(UnmanagedType.U4)] int cchBlob, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromFile([In] [MarshalAs(UnmanagedType.LPStr)] string pszFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromFileW([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromHandle([In] IntPtr hFile, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameCompareAssemblies([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzAssembly1, [In] [MarshalAs(UnmanagedType.LPWStr)] string pwzAssembly2, [MarshalAs(UnmanagedType.U4)] out int dwResult); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameFreeBuffer([In] IntPtr pbMemory); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameGetBlob([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pbBlob, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int pcbBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameGetBlobFromImage([In] IntPtr pbBase, [In] [MarshalAs(UnmanagedType.U4)] int dwLength, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbBlob, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int pcbBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameGetPublicKey([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob, out IntPtr ppbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbPublicKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameHashSize([In] [MarshalAs(UnmanagedType.U4)] int ulHashAlg, [MarshalAs(UnmanagedType.U4)] out int cbSize); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyDelete([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyGen([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] [MarshalAs(UnmanagedType.U4)] int dwFlags, out IntPtr ppbKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyGenEx([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] [MarshalAs(UnmanagedType.U4)] int dwFlags, [In] [MarshalAs(UnmanagedType.U4)] int dwKeySize, out IntPtr ppbKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyInstall([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameSignatureGeneration([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob, [In] [Out] IntPtr ppbSignatureBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSignatureBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameSignatureGenerationEx([In] [MarshalAs(UnmanagedType.LPWStr)] string wszFilePath, [In] [MarshalAs(UnmanagedType.LPWStr)] string wszKeyContainer, [In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob, [In] [Out] IntPtr ppbSignatureBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSignatureBlob, [In] [MarshalAs(UnmanagedType.U4)] int dwFlags); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameSignatureSize([In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pbPublicKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSize); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameSignatureVerification([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [MarshalAs(UnmanagedType.U4)] int dwInFlags, [MarshalAs(UnmanagedType.U4)] out int dwOutFlags); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameSignatureVerificationEx([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [MarshalAs(UnmanagedType.I1)] bool fForceVerification, [MarshalAs(UnmanagedType.I1)] out bool fWasVerified); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameSignatureVerificationFromImage([In] IntPtr pbBase, [In] [MarshalAs(UnmanagedType.U4)] int dwLength, [In] [MarshalAs(UnmanagedType.U4)] int dwInFlags, [MarshalAs(UnmanagedType.U4)] out int dwOutFlags); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameTokenFromAssembly([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameTokenFromAssemblyEx([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken, out IntPtr ppbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbPublicKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameTokenFromPublicKey([In] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] byte[] pbPublicKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbPublicKeyBlob, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken); + } +} \ No newline at end of file diff --git a/src/MSBuildCode/IClrStrongNameUsingIntPtr.cs b/src/MSBuildCode/IClrStrongNameUsingIntPtr.cs new file mode 100644 index 0000000..f9a2553 --- /dev/null +++ b/src/MSBuildCode/IClrStrongNameUsingIntPtr.cs @@ -0,0 +1,98 @@ +namespace MSBuildCode +{ + using System; + using System.Runtime.CompilerServices; + using System.Runtime.InteropServices; + using System.Security; + + /// + /// Exported using ILSpy from Microsoft.Build.Tasks.Core.dll + /// + [ComImport] + [SecurityCritical] + [ComConversionLoss] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D")] + internal interface IClrStrongNameUsingIntPtr + { + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromAssemblyFile([In] [MarshalAs(UnmanagedType.LPStr)] string pszFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromAssemblyFileW([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromBlob([In] IntPtr pbBlob, [In] [MarshalAs(UnmanagedType.U4)] int cchBlob, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromFile([In] [MarshalAs(UnmanagedType.LPStr)] string pszFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromFileW([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int GetHashFromHandle([In] IntPtr hFile, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int piHashAlg, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbHash, [In] [MarshalAs(UnmanagedType.U4)] int cchHash, [MarshalAs(UnmanagedType.U4)] out int pchHash); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameCompareAssemblies([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzAssembly1, [In] [MarshalAs(UnmanagedType.LPWStr)] string pwzAssembly2, [MarshalAs(UnmanagedType.U4)] out int dwResult); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameFreeBuffer([In] IntPtr pbMemory); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameGetBlob([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] pbBlob, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int pcbBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameGetBlobFromImage([In] IntPtr pbBase, [In] [MarshalAs(UnmanagedType.U4)] int dwLength, [Out] [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] pbBlob, [In] [Out] [MarshalAs(UnmanagedType.U4)] ref int pcbBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameGetPublicKey([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] IntPtr pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob, out IntPtr ppbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbPublicKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameHashSize([In] [MarshalAs(UnmanagedType.U4)] int ulHashAlg, [MarshalAs(UnmanagedType.U4)] out int cbSize); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyDelete([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyGen([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] [MarshalAs(UnmanagedType.U4)] int dwFlags, out IntPtr ppbKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyGenEx([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] [MarshalAs(UnmanagedType.U4)] int dwFlags, [In] [MarshalAs(UnmanagedType.U4)] int dwKeySize, out IntPtr ppbKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameKeyInstall([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] IntPtr pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameSignatureGeneration([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [MarshalAs(UnmanagedType.LPWStr)] string pwzKeyContainer, [In] IntPtr pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob, [In] [Out] IntPtr ppbSignatureBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSignatureBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameSignatureGenerationEx([In] [MarshalAs(UnmanagedType.LPWStr)] string wszFilePath, [In] [MarshalAs(UnmanagedType.LPWStr)] string wszKeyContainer, [In] IntPtr pbKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbKeyBlob, [In] [Out] IntPtr ppbSignatureBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSignatureBlob, [In] [MarshalAs(UnmanagedType.U4)] int dwFlags); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameSignatureSize([In] IntPtr pbPublicKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbSize); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameSignatureVerification([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [MarshalAs(UnmanagedType.U4)] int dwInFlags, [MarshalAs(UnmanagedType.U4)] out int dwOutFlags); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameSignatureVerificationEx([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, [In] [MarshalAs(UnmanagedType.I1)] bool fForceVerification, [MarshalAs(UnmanagedType.I1)] out bool fWasVerified); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + [return: MarshalAs(UnmanagedType.U4)] + int StrongNameSignatureVerificationFromImage([In] IntPtr pbBase, [In] [MarshalAs(UnmanagedType.U4)] int dwLength, [In] [MarshalAs(UnmanagedType.U4)] int dwInFlags, [MarshalAs(UnmanagedType.U4)] out int dwOutFlags); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameTokenFromAssembly([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameTokenFromAssemblyEx([In] [MarshalAs(UnmanagedType.LPWStr)] string pwzFilePath, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken, out IntPtr ppbPublicKeyBlob, [MarshalAs(UnmanagedType.U4)] out int pcbPublicKeyBlob); + + [MethodImpl(MethodImplOptions.PreserveSig | MethodImplOptions.InternalCall)] + int StrongNameTokenFromPublicKey([In] IntPtr pbPublicKeyBlob, [In] [MarshalAs(UnmanagedType.U4)] int cbPublicKeyBlob, out IntPtr ppbStrongNameToken, [MarshalAs(UnmanagedType.U4)] out int pcbStrongNameToken); + } +} \ No newline at end of file diff --git a/src/MSBuildCode/ResolveKeySourceTask.cs b/src/MSBuildCode/ResolveKeySourceTask.cs new file mode 100644 index 0000000..737e1a2 --- /dev/null +++ b/src/MSBuildCode/ResolveKeySourceTask.cs @@ -0,0 +1,110 @@ +using System; +using System.Globalization; +using System.IO; + +namespace MSBuildCode +{ + /// + /// Adjusted MSBuild source from https://github.com/microsoft/msbuild/blob/master/src/Tasks/ResolveKeySource.cs + /// + public static class ResolveKeySourceTask + { + private const string pfxFileExtension = ".pfx"; + private const string pfxFileContainerPrefix = "VS_KEY_"; + + // This is was originally a msbuild task method. Only its first half is used. + public static string ResolveAssemblyKey(string KeyFile) + { + if (string.IsNullOrEmpty(KeyFile)) + { + throw new ArgumentException("KeyFile cannot be empty"); + } + + string keyFileExtension = String.Empty; + try + { + keyFileExtension = Path.GetExtension(KeyFile); + } + catch (ArgumentException ex) + { + var message = string.Format("MSB3324: Invalid key file name \"{0}\". {1}", KeyFile, ex.Message); + throw new ApplicationException(message); + } + + if (0 != String.Compare(keyFileExtension, pfxFileExtension, StringComparison.OrdinalIgnoreCase)) + { + throw new ApplicationException($"This implementation only works with {pfxFileExtension} keys."); + } + + // it is .pfx file. It is being imported into key container with name = "VS_KEY_" + FileStream fs = null; + try + { + string currentUserName = Environment.UserDomainName + "\\" + Environment.UserName; + // we use the curent user name to randomize the associated container name, i.e different user on the same machine will export to different keys + // this is because SNAPI by default will create keys in "per-machine" crypto store (visible for all the user) but will set the permission such only + // creator will be able to use it. This will make imposible for other user both to sign or export the key again (since they also can not delete that key). + // Now different users will use different container name. We use ToLower(invariant) because this is what the native equivalent of this function (Create new key, or VC++ import-er). + // use as well and we want to keep the hash (and key container name the same) otherwise user could be prompt for a password twice. + byte[] userNameBytes = + System.Text.Encoding.Unicode.GetBytes( + currentUserName.ToLower(CultureInfo.InvariantCulture)); + fs = File.OpenRead(KeyFile); + int fileLength = (int)fs.Length; + var keyBytes = new byte[fileLength]; + fs.Read(keyBytes, 0, fileLength); + + UInt64 hash = HashFromBlob(keyBytes); + hash ^= HashFromBlob( + userNameBytes); // modify it with the username hash, so each user would get different hash for the same key + + string hashedContainerName = + pfxFileContainerPrefix + hash.ToString("X016", CultureInfo.InvariantCulture); + + return hashedContainerName; + } + finally + { + fs?.Close(); + } + } + + public static bool IsContainerInstalled(string hashedContainerName) + { + + if (StrongNameHelpers.StrongNameGetPublicKey(hashedContainerName, IntPtr.Zero, 0, out IntPtr publicKeyBlob, out _) && publicKeyBlob != IntPtr.Zero) + { + StrongNameHelpers.StrongNameFreeBuffer(publicKeyBlob); + return true; + } + + return false; + } + + // We we use hash the contens of .pfx file so we can establish relationship file <-> container name, whithout + // need to prompt for password. Note this is not used for any security reasons. With the departure from standard MD5 algoritm + // we need as simple hash function for replacement. The data blobs we use (.pfx files) are + // encrypted meaning they have high entropy, so in all practical pupose even a simpliest + // hash would give good enough results. This code needs to be kept in sync with the code in compsvcpkgs + // to prevent double prompt for newly created keys. The magic numbers here are just random primes + // in the range 10m/20m. + private static UInt64 HashFromBlob(byte[] data) + { + UInt32 dw1 = 17339221; + UInt32 dw2 = 19619429; + UInt32 pos = 10803503; + + foreach (byte b in data) + { + UInt32 value = b ^ pos; + pos *= 10803503; + dw1 += ((value ^ dw2) * 15816943) + 17368321; + dw2 ^= ((value + dw1) * 14984549) ^ 11746499; + } + UInt64 result = dw1; + result <<= 32; + result |= dw2; + return result; + } + } +} \ No newline at end of file diff --git a/src/MSBuildCode/StrongNameHelpers.cs b/src/MSBuildCode/StrongNameHelpers.cs new file mode 100644 index 0000000..8d0bf44 --- /dev/null +++ b/src/MSBuildCode/StrongNameHelpers.cs @@ -0,0 +1,268 @@ +using System; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Security; + +namespace MSBuildCode +{ + /// + /// Adjusted MSBuild source from https://github.com/microsoft/msbuild/blob/e70a3159d64f9ed6ec3b60253ef863fa883a99b1/src/Shared/StrongNameHelpers.cs + /// + internal static class StrongNameHelpers + { + [ThreadStatic] + private static int t_ts_LastStrongNameHR; + + [SecurityCritical] + [ThreadStatic] + private static MSBuildCode.IClrStrongName s_StrongName; + + [ThreadStatic] + private static MethodInfo s_GetRuntimeInterfaceAsObjectMethod; + + private static MSBuildCode.IClrStrongName StrongName + { + [SecurityCritical] + get + { + if (s_StrongName == null) + { + if (s_GetRuntimeInterfaceAsObjectMethod == null) + { + s_GetRuntimeInterfaceAsObjectMethod = typeof(RuntimeEnvironment).GetMethod("GetRuntimeInterfaceAsObject"); + } + if (s_GetRuntimeInterfaceAsObjectMethod != null) + { + s_StrongName = (MSBuildCode.IClrStrongName)s_GetRuntimeInterfaceAsObjectMethod.Invoke(null, new object[2] + { + new Guid("B79B0ACD-F5CD-409b-B5A5-A16244610B92"), + new Guid("9FD93CCF-3280-4391-B3A9-96E1CDE77C8D") + }); + } + } + return s_StrongName; + } + } + + private static MSBuildCode.IClrStrongNameUsingIntPtr StrongNameUsingIntPtr + { + [SecurityCritical] + get + { + return (MSBuildCode.IClrStrongNameUsingIntPtr)StrongName; + } + } + + [SecurityCritical] + public static int StrongNameErrorInfo() + { + return t_ts_LastStrongNameHR; + } + + [SecurityCritical] + public static void StrongNameFreeBuffer(IntPtr pbMemory) + { + StrongNameUsingIntPtr.StrongNameFreeBuffer(pbMemory); + } + + [SecurityCritical] + public static bool StrongNameGetPublicKey(string pwzKeyContainer, IntPtr pbKeyBlob, int cbKeyBlob, out IntPtr ppbPublicKeyBlob, out int pcbPublicKeyBlob) + { + int num = StrongNameUsingIntPtr.StrongNameGetPublicKey(pwzKeyContainer, pbKeyBlob, cbKeyBlob, out ppbPublicKeyBlob, out pcbPublicKeyBlob); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + ppbPublicKeyBlob = IntPtr.Zero; + pcbPublicKeyBlob = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameKeyDelete(string pwzKeyContainer) + { + int num = StrongName.StrongNameKeyDelete(pwzKeyContainer); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameKeyGen(string pwzKeyContainer, int dwFlags, out IntPtr ppbKeyBlob, out int pcbKeyBlob) + { + int num = StrongName.StrongNameKeyGen(pwzKeyContainer, dwFlags, out ppbKeyBlob, out pcbKeyBlob); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + ppbKeyBlob = IntPtr.Zero; + pcbKeyBlob = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameKeyInstall(string pwzKeyContainer, IntPtr pbKeyBlob, int cbKeyBlob) + { + int num = StrongNameUsingIntPtr.StrongNameKeyInstall(pwzKeyContainer, pbKeyBlob, cbKeyBlob); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameSignatureGeneration(string pwzFilePath, string pwzKeyContainer, IntPtr pbKeyBlob, int cbKeyBlob) + { + IntPtr ppbSignatureBlob = IntPtr.Zero; + int pcbSignatureBlob = 0; + return StrongNameSignatureGeneration(pwzFilePath, pwzKeyContainer, pbKeyBlob, cbKeyBlob, ref ppbSignatureBlob, out pcbSignatureBlob); + } + + [SecurityCritical] + public static bool StrongNameSignatureGeneration(string pwzFilePath, string pwzKeyContainer, IntPtr pbKeyBlob, int cbKeyBlob, ref IntPtr ppbSignatureBlob, out int pcbSignatureBlob) + { + int num = StrongNameUsingIntPtr.StrongNameSignatureGeneration(pwzFilePath, pwzKeyContainer, pbKeyBlob, cbKeyBlob, ppbSignatureBlob, out pcbSignatureBlob); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + pcbSignatureBlob = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameSignatureSize(IntPtr pbPublicKeyBlob, int cbPublicKeyBlob, out int pcbSize) + { + int num = StrongNameUsingIntPtr.StrongNameSignatureSize(pbPublicKeyBlob, cbPublicKeyBlob, out pcbSize); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + pcbSize = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameSignatureVerification(string pwzFilePath, int dwInFlags, out int pdwOutFlags) + { + int num = StrongName.StrongNameSignatureVerification(pwzFilePath, dwInFlags, out pdwOutFlags); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + pdwOutFlags = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameSignatureVerificationEx(string pwzFilePath, bool fForceVerification, out bool pfWasVerified) + { + int num = StrongName.StrongNameSignatureVerificationEx(pwzFilePath, fForceVerification, out pfWasVerified); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + pfWasVerified = false; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameTokenFromPublicKey(IntPtr pbPublicKeyBlob, int cbPublicKeyBlob, out IntPtr ppbStrongNameToken, out int pcbStrongNameToken) + { + int num = StrongNameUsingIntPtr.StrongNameTokenFromPublicKey(pbPublicKeyBlob, cbPublicKeyBlob, out ppbStrongNameToken, out pcbStrongNameToken); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + ppbStrongNameToken = IntPtr.Zero; + pcbStrongNameToken = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameSignatureSize(byte[] bPublicKeyBlob, int cbPublicKeyBlob, out int pcbSize) + { + int num = StrongName.StrongNameSignatureSize(bPublicKeyBlob, cbPublicKeyBlob, out pcbSize); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + pcbSize = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameTokenFromPublicKey(byte[] bPublicKeyBlob, int cbPublicKeyBlob, out IntPtr ppbStrongNameToken, out int pcbStrongNameToken) + { + int num = StrongName.StrongNameTokenFromPublicKey(bPublicKeyBlob, cbPublicKeyBlob, out ppbStrongNameToken, out pcbStrongNameToken); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + ppbStrongNameToken = IntPtr.Zero; + pcbStrongNameToken = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameGetPublicKey(string pwzKeyContainer, byte[] bKeyBlob, int cbKeyBlob, out IntPtr ppbPublicKeyBlob, out int pcbPublicKeyBlob) + { + int num = StrongName.StrongNameGetPublicKey(pwzKeyContainer, bKeyBlob, cbKeyBlob, out ppbPublicKeyBlob, out pcbPublicKeyBlob); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + ppbPublicKeyBlob = IntPtr.Zero; + pcbPublicKeyBlob = 0; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameKeyInstall(string pwzKeyContainer, byte[] bKeyBlob, int cbKeyBlob) + { + int num = StrongName.StrongNameKeyInstall(pwzKeyContainer, bKeyBlob, cbKeyBlob); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + return false; + } + return true; + } + + [SecurityCritical] + public static bool StrongNameSignatureGeneration(string pwzFilePath, string pwzKeyContainer, byte[] bKeyBlob, int cbKeyBlob) + { + IntPtr ppbSignatureBlob = IntPtr.Zero; + int pcbSignatureBlob = 0; + return StrongNameSignatureGeneration(pwzFilePath, pwzKeyContainer, bKeyBlob, cbKeyBlob, ref ppbSignatureBlob, out pcbSignatureBlob); + } + + [SecurityCritical] + public static bool StrongNameSignatureGeneration(string pwzFilePath, string pwzKeyContainer, byte[] bKeyBlob, int cbKeyBlob, ref IntPtr ppbSignatureBlob, out int pcbSignatureBlob) + { + int num = StrongName.StrongNameSignatureGeneration(pwzFilePath, pwzKeyContainer, bKeyBlob, cbKeyBlob, ppbSignatureBlob, out pcbSignatureBlob); + if (num < 0) + { + t_ts_LastStrongNameHR = num; + pcbSignatureBlob = 0; + return false; + } + return true; + } + } +} \ No newline at end of file diff --git a/src/SnInstallPfx.cs b/src/SnInstallPfx.cs new file mode 100644 index 0000000..bf212a0 --- /dev/null +++ b/src/SnInstallPfx.cs @@ -0,0 +1,79 @@ +using System; +using System.Reflection; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using MSBuildCode; + +namespace SnInstallPfx +{ + // Utility to replace the sn.exe -i command that does not accepts password. + public static class SnInstallPfx + { + static int Main(string[] args) + { + // params and usage + if (args.Length == 0 || args[0] == "?" || args[0] == "-?" || args.Length != 2) + { + Console.WriteLine("By Honzajscz at 2019"); + Console.WriteLine("Installs key pair from into a key container compatible for MSBuild."); + Console.WriteLine("This utility is an alternative for command sn.exe -i ."); + Console.WriteLine("It accepts password from command line and automatically generates a container for ."); + Console.WriteLine(); + Console.WriteLine($"Usage: {Assembly.GetEntryAssembly().GetName().Name}.exe "); + Console.WriteLine(); + + return -1; + } + + string pfxPath = args[0]; + string pfxPassword = args[1]; + + var pfxContainer = ResolveKeySourceTask.ResolveAssemblyKey(pfxPath); + if (ResolveKeySourceTask.IsContainerInstalled(pfxContainer)) + { + //Installs from infile in the specified key container. The key container resides in the strong name CSP. + Console.Error.WriteLine($"The key pair is already installed in the strong name CSP key container '{pfxContainer}'."); + Console.Error.WriteLine("To delete the key container run following command from the Developer Command Prompt:"); + Console.Error.WriteLine($"sn.exe -d {pfxContainer}"); + Console.Error.WriteLine(); + Console.Error.WriteLine($"To list all installed key containers run following command:"); + Console.Error.WriteLine($"certutil -csp \"Microsoft Strong Cryptographic Provider\" -key"); + return -2; + } + + // open pfx and export its private key + var pfxCert = new X509Certificate2(pfxPath, pfxPassword, X509KeyStorageFlags.Exportable); + var pfxPrivateKey = pfxCert.PrivateKey as RSACryptoServiceProvider; + var pfxCspBlob = pfxPrivateKey.ExportCspBlob(true); + + + // create cryptographic service provider (CSP) and machine-wide persistent key container + // more at https://stackoverflow.com/questions/2528186/what-exactly-is-a-key-container + // and https://www.sysadmins.lv/blog-en/certutil-tips-and-tricks-query-cryptographic-service-providers-csp-and-ksp.aspx + const string DotNetStrongSigningCSP = "Microsoft Strong Cryptographic Provider"; + var cspParameters = new CspParameters(1, DotNetStrongSigningCSP, pfxContainer) + { + KeyNumber = (int)KeyNumber.Signature, // container used for signing + Flags = CspProviderFlags.UseMachineKeyStore | CspProviderFlags.UseNonExportableKey + }; + + using (var rsaCSP = new RSACryptoServiceProvider(cspParameters)) + { + rsaCSP.PersistKeyInCsp = true; + rsaCSP.ImportCspBlob(pfxCspBlob); + }; + + // output + // This not an actual error - just avoiding output pollution. + Console.Error.WriteLine($"The key pair has been installed into the strong name CSP key container '{pfxContainer}'."); + // Write the container to the output + Console.WriteLine(pfxContainer); + return 0; + + } + } + + +} + + diff --git a/src/SnInstallPfx.csproj b/src/SnInstallPfx.csproj new file mode 100644 index 0000000..96a3147 --- /dev/null +++ b/src/SnInstallPfx.csproj @@ -0,0 +1,12 @@ + + + + net461 + Pfx Strong Name Signing Importer + Utility to replace the sn.exe -i command that does not accepts password. Created by Honzajscz + DevOps + Exe + 0.1.0 + + + \ No newline at end of file diff --git a/src/SnInstallPfx.sln b/src/SnInstallPfx.sln new file mode 100644 index 0000000..09ab78b --- /dev/null +++ b/src/SnInstallPfx.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.645 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SnInstallPfx", "SnInstallPfx.csproj", "{091C867A-2142-4318-AC06-91376C79CFA5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {091C867A-2142-4318-AC06-91376C79CFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {091C867A-2142-4318-AC06-91376C79CFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {091C867A-2142-4318-AC06-91376C79CFA5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {091C867A-2142-4318-AC06-91376C79CFA5}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {11CE5D1E-B142-422C-81AB-508FA8FDEDDA} + EndGlobalSection +EndGlobal