Exemple #1
0
        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);
        }