internal static Signature SignFile( SigningOption option, string fileName, X509Certificate2 certificate, string timeStampServerUrl, string hashAlgorithm) { using (SignatureHelper.tracer.TraceMethod("file: {0}, cert: {1}", (object)SignatureHelper.GetStringValue(fileName), (object)SignatureHelper.GetCertName(certificate))) { Signature signature = (Signature)null; IntPtr num = IntPtr.Zero; uint error = 0; string hashAlgorithm1 = (string)null; Utils.CheckArgForNullOrEmpty(SignatureHelper.tracer, fileName, nameof(fileName)); Utils.CheckArgForNull(SignatureHelper.tracer, (object)certificate, nameof(certificate)); if (!string.IsNullOrEmpty(timeStampServerUrl) && (timeStampServerUrl.Length <= 7 || timeStampServerUrl.IndexOf("http://", StringComparison.OrdinalIgnoreCase) != 0)) { throw SignatureHelper.tracer.NewArgumentException(nameof(certificate), "Authenticode", "TimeStampUrlRequired"); } if (!string.IsNullOrEmpty(hashAlgorithm)) { IntPtr oidInfo = System.Management.Automation.Security.NativeMethods.CryptFindOIDInfo(2U, hashAlgorithm, 0U); hashAlgorithm1 = !(oidInfo == IntPtr.Zero) ? ((System.Management.Automation.Security.NativeMethods.CRYPT_OID_INFO)Marshal.PtrToStructure(oidInfo, typeof(System.Management.Automation.Security.NativeMethods.CRYPT_OID_INFO))).pszOID : throw SignatureHelper.tracer.NewArgumentException(nameof(certificate), "Authenticode", "InvalidHashAlgorithm"); } if (!SecuritySupport.CertIsGoodForSigning(certificate)) { throw SignatureHelper.tracer.NewArgumentException(nameof(certificate), "Authenticode", "CertNotGoodForSigning"); } SecuritySupport.CheckIfFileExists(fileName); try { string timeStampServerUrl1 = ""; if (!string.IsNullOrEmpty(timeStampServerUrl)) { timeStampServerUrl1 = timeStampServerUrl; } System.Management.Automation.Security.NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_INFO wizDigitalSignInfo = System.Management.Automation.Security.NativeMethods.InitSignInfoStruct(fileName, certificate, timeStampServerUrl1, hashAlgorithm1, option); num = Marshal.AllocCoTaskMem(Marshal.SizeOf((object)wizDigitalSignInfo)); Marshal.StructureToPtr((object)wizDigitalSignInfo, num, false); bool flag = System.Management.Automation.Security.NativeMethods.CryptUIWizDigitalSign(1U, IntPtr.Zero, IntPtr.Zero, num, IntPtr.Zero); Marshal.DestroyStructure(wizDigitalSignInfo.pSignExtInfo, typeof(System.Management.Automation.Security.NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO)); Marshal.FreeCoTaskMem(wizDigitalSignInfo.pSignExtInfo); if (!flag) { error = SignatureHelper.GetLastWin32Error(); switch (error) { case 2147500037: case 2147942401: flag = true; break; case 2148073480: throw SignatureHelper.tracer.NewArgumentException(nameof(certificate), "Authenticode", "InvalidHashAlgorithm"); default: SignatureHelper.tracer.TraceError("CryptUIWizDigitalSign: failed: {0:x}", (object)error); break; } } signature = !flag ? new Signature(fileName, error) : (string.IsNullOrEmpty(timeStampServerUrl) ? new Signature(fileName, certificate) : SignatureHelper.GetSignature(fileName, (string)null)); } finally { Marshal.DestroyStructure(num, typeof(System.Management.Automation.Security.NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_INFO)); Marshal.FreeCoTaskMem(num); } return(signature); } }
internal static Signature SignFile(SigningOption option, string fileName, X509Certificate2 certificate, string timeStampServerUrl, string hashAlgorithm) { bool result = false; Signature signature = null; IntPtr pSignInfo = IntPtr.Zero; DWORD error = 0; string hashOid = null; Utils.CheckArgForNullOrEmpty(fileName, "fileName"); Utils.CheckArgForNull(certificate, "certificate"); // If given, TimeStamp server URLs must begin with http:// if (!String.IsNullOrEmpty(timeStampServerUrl)) { if ((timeStampServerUrl.Length <= 7) || (timeStampServerUrl.IndexOf("http://", StringComparison.OrdinalIgnoreCase) != 0)) { throw PSTraceSource.NewArgumentException( "certificate", Authenticode.TimeStampUrlRequired); } } // Validate that the hash algorithm is valid if (!String.IsNullOrEmpty(hashAlgorithm)) { IntPtr intptrAlgorithm = Marshal.StringToHGlobalUni(hashAlgorithm); IntPtr oidPtr = NativeMethods.CryptFindOIDInfo(NativeConstants.CRYPT_OID_INFO_NAME_KEY, intptrAlgorithm, 0); // If we couldn't find an OID for the hash // algorithm, it was invalid. if (oidPtr == IntPtr.Zero) { throw PSTraceSource.NewArgumentException( "certificate", Authenticode.InvalidHashAlgorithm); } else { NativeMethods.CRYPT_OID_INFO oidInfo = ClrFacade.PtrToStructure <NativeMethods.CRYPT_OID_INFO>(oidPtr); hashOid = oidInfo.pszOID; } } if (!SecuritySupport.CertIsGoodForSigning(certificate)) { throw PSTraceSource.NewArgumentException( "certificate", Authenticode.CertNotGoodForSigning); } SecuritySupport.CheckIfFileExists(fileName); //SecurityUtils.CheckIfFileSmallerThan4Bytes(fileName); try { // CryptUI is not documented either way, but does not // support empty strings for the timestamp server URL. // It expects null, only. Instead, it randomly AVs if you // try. string timeStampServerUrlForCryptUI = null; if (!String.IsNullOrEmpty(timeStampServerUrl)) { timeStampServerUrlForCryptUI = timeStampServerUrl; } // // first initialize the struct to pass to // CryptUIWizDigitalSign() function // NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_INFO si = NativeMethods.InitSignInfoStruct(fileName, certificate, timeStampServerUrlForCryptUI, hashOid, option); pSignInfo = Marshal.AllocCoTaskMem(Marshal.SizeOf(si)); Marshal.StructureToPtr(si, pSignInfo, false); // // sign the file // // The GetLastWin32Error of this is checked, but PreSharp doesn't seem to be // able to see that. #pragma warning disable 56523 result = NativeMethods.CryptUIWizDigitalSign( (DWORD)NativeMethods.CryptUIFlags.CRYPTUI_WIZ_NO_UI, IntPtr.Zero, IntPtr.Zero, pSignInfo, IntPtr.Zero); #pragma warning enable 56523 if (si.pSignExtInfo != null) { ClrFacade.DestroyStructure <NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO>(si.pSignExtInfo); Marshal.FreeCoTaskMem(si.pSignExtInfo); } if (!result) { error = GetLastWin32Error(); // // ISSUE-2004/05/08-kumarp : there seems to be a bug // in CryptUIWizDigitalSign(). // It returns 80004005 or 80070001 // but it signs the file correctly. Mask this error // till we figure out this odd behavior. // if ((error == 0x80004005) || (error == 0x80070001) || // CryptUIWizDigitalSign introduced a breaking change in Win8 to return this // error code (ERROR_INTERNET_NAME_NOT_RESOLVED) when you provide an invalid // timestamp server. It used to be 0x80070001. // Also masking this out so that we don't introduce a breaking change ourselves. (error == 0x80072EE7) ) { result = true; } else { if (error == Win32Errors.NTE_BAD_ALGID) { throw PSTraceSource.NewArgumentException( "certificate", Authenticode.InvalidHashAlgorithm); } s_tracer.TraceError("CryptUIWizDigitalSign: failed: {0:x}", error); } } if (result) { signature = GetSignature(fileName, null); } else { signature = new Signature(fileName, (DWORD)error); } } finally { ClrFacade.DestroyStructure <NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_INFO>(pSignInfo); Marshal.FreeCoTaskMem(pSignInfo); } return(signature); }
internal static System.Management.Automation.Signature SignFile(SigningOption option, string fileName, X509Certificate2 certificate, string timeStampServerUrl, string hashAlgorithm) { bool flag = false; System.Management.Automation.Signature signature = null; IntPtr zero = IntPtr.Zero; uint error = 0; string pszOID = null; Utils.CheckArgForNullOrEmpty(fileName, "fileName"); Utils.CheckArgForNull(certificate, "certificate"); if (!string.IsNullOrEmpty(timeStampServerUrl) && ((timeStampServerUrl.Length <= 7) || (timeStampServerUrl.IndexOf("http://", StringComparison.OrdinalIgnoreCase) != 0))) { throw PSTraceSource.NewArgumentException("certificate", "Authenticode", "TimeStampUrlRequired", new object[0]); } if (!string.IsNullOrEmpty(hashAlgorithm)) { IntPtr pvKey = Marshal.StringToHGlobalUni(hashAlgorithm); IntPtr ptr = System.Management.Automation.Security.NativeMethods.CryptFindOIDInfo(2, pvKey, 0); if (ptr == IntPtr.Zero) { throw PSTraceSource.NewArgumentException("certificate", "Authenticode", "InvalidHashAlgorithm", new object[0]); } System.Management.Automation.Security.NativeMethods.CRYPT_OID_INFO crypt_oid_info = (System.Management.Automation.Security.NativeMethods.CRYPT_OID_INFO)Marshal.PtrToStructure(ptr, typeof(System.Management.Automation.Security.NativeMethods.CRYPT_OID_INFO)); pszOID = crypt_oid_info.pszOID; } if (!SecuritySupport.CertIsGoodForSigning(certificate)) { throw PSTraceSource.NewArgumentException("certificate", "Authenticode", "CertNotGoodForSigning", new object[0]); } SecuritySupport.CheckIfFileExists(fileName); try { string str2 = null; if (!string.IsNullOrEmpty(timeStampServerUrl)) { str2 = timeStampServerUrl; } System.Management.Automation.Security.NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_INFO structure = System.Management.Automation.Security.NativeMethods.InitSignInfoStruct(fileName, certificate, str2, pszOID, option); zero = Marshal.AllocCoTaskMem(Marshal.SizeOf(structure)); Marshal.StructureToPtr(structure, zero, false); flag = System.Management.Automation.Security.NativeMethods.CryptUIWizDigitalSign(1, IntPtr.Zero, IntPtr.Zero, zero, IntPtr.Zero); Marshal.DestroyStructure(structure.pSignExtInfo, typeof(System.Management.Automation.Security.NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_EXTENDED_INFO)); Marshal.FreeCoTaskMem(structure.pSignExtInfo); if (!flag) { error = GetLastWin32Error(); switch (error) { case 0x80004005: case 0x80070001: case 0x80072ee7: flag = true; goto Label_01CF; case 0x80090008: throw PSTraceSource.NewArgumentException("certificate", "Authenticode", "InvalidHashAlgorithm", new object[0]); } tracer.TraceError("CryptUIWizDigitalSign: failed: {0:x}", new object[] { error }); } Label_01CF: if (flag) { return(GetSignature(fileName, null)); } signature = new System.Management.Automation.Signature(fileName, error); } finally { Marshal.DestroyStructure(zero, typeof(System.Management.Automation.Security.NativeMethods.CRYPTUI_WIZ_DIGITAL_SIGN_INFO)); Marshal.FreeCoTaskMem(zero); } return(signature); }