Example #1
0
        private static SIGNER_SIGN_EX2_PARAMS GetSignerSignEx2ParametersPointer(string timestampUrl, SignMode type,
                                                                                IntPtr subjectInfo, IntPtr signerCertificate, IntPtr provider, out GCHandle?signerSignHandle, string timestampAlgorithmOid)
        {
            // signature info
            var signatureInfo = new SIGNER_SIGNATURE_INFO
            {
                cbSize            = (uint)Marshal.SizeOf <SIGNER_SIGNATURE_INFO>(),
                algidHash         = Constants.CALG_SHA_256,
                dwAttrChoice      = Constants.DONT_CARE,
                pAttrAuthCode     = IntPtr.Zero,
                psAuthenticated   = IntPtr.Zero,
                psUnauthenticated = IntPtr.Zero,
            };

            var signatureHandle = Marshal.AllocHGlobal(Marshal.SizeOf <SIGNER_SIGNATURE_INFO>());

            Marshal.StructureToPtr(signatureInfo, signatureHandle, false);

            // signer sign ex params
            var signerSignEx2Params = new SIGNER_SIGN_EX2_PARAMS
            {
                dwFlags        = Constants.DONT_CARE,
                pSubjectInfo   = subjectInfo,
                pSigningCert   = signerCertificate,
                pSignatureInfo = signatureHandle,
                pProviderInfo  = provider,
            };

            if (!string.IsNullOrEmpty(timestampUrl))
            {
                signerSignEx2Params.pwszTimestampURL = Marshal.StringToHGlobalUni(timestampUrl);
                if (string.IsNullOrEmpty(timestampAlgorithmOid))
                {
                    signerSignEx2Params.dwTimestampFlags = Constants.SIGNER_TIMESTAMP_AUTHENTICODE;
                }
                else
                {
                    signerSignEx2Params.dwTimestampFlags = Constants.SIGNER_TIMESTAMP_RFC3161;
                    signerSignEx2Params.pszAlgorithmOid  = Marshal.StringToHGlobalAnsi(timestampAlgorithmOid);
                }
            }

            signerSignHandle = null;
            if (type == SignMode.APPX)
            {
                var sipData = new APPX_SIP_CLIENT_DATA();
                signerSignHandle = GCHandle.Alloc(signerSignEx2Params, GCHandleType.Pinned);

                sipData.pSignerParams = signerSignHandle.Value.AddrOfPinnedObject();

                var sipHandle = Marshal.AllocHGlobal(Marshal.SizeOf <APPX_SIP_CLIENT_DATA>());
                Marshal.StructureToPtr(sipData, sipHandle, false);

                signerSignEx2Params.pSipData = sipHandle;
            }

            return(signerSignEx2Params);
        }
        private static IntPtr CreateSignerSignatureInfo()
        {
            SIGNER_SIGNATURE_INFO signatureInfo = new SIGNER_SIGNATURE_INFO
            {
                cbSize            = (uint)Marshal.SizeOf(typeof(SIGNER_SIGNATURE_INFO)),
                algidHash         = 0x00008004, // CALG_SHA1
                dwAttrChoice      = 0x0,        // SIGNER_NO_ATTR
                pAttrAuthCode     = IntPtr.Zero,
                psAuthenticated   = IntPtr.Zero,
                psUnauthenticated = IntPtr.Zero
            };
            IntPtr pSignatureInfo = Marshal.AllocHGlobal(Marshal.SizeOf(signatureInfo));

            Marshal.StructureToPtr(signatureInfo, pSignatureInfo, false);
            return(pSignatureInfo);
        }
Example #3
0
        /// <summary>Authenticode signs a file.</summary>
        /// <param name="pageHashing">True if the signing process should try to include page hashing, otherwise false.
        /// Use <c>null</c> to use the operating system default. Note that page hashing still may be disabled if the
        /// Subject Interface Package does not support page hashing.</param>
        /// <param name="descriptionUrl">A URL describing the signature or the signer.</param>
        /// <param name="description">The description to apply to the signature.</param>
        /// <param name="path">The path to the file to signed.</param>
        /// <param name="logger">An optional logger to capture signing operations.</param>
        /// <returns>A HRESULT indicating the result of the signing operation. S_OK, or zero, is returned if the signing
        /// operation completed successfully.</returns>
        public unsafe int SignFile(ReadOnlySpan <char> path, ReadOnlySpan <char> description, ReadOnlySpan <char> descriptionUrl, bool?pageHashing, ILogger logger = null)
        {
            void CopyAndNullTerminate(ReadOnlySpan <char> str, Span <char> destination)
            {
                str.CopyTo(destination);
                destination[destination.Length - 1] = '\0';
            }

            var flags = SignerSignEx3Flags.SIGN_CALLBACK_UNDOCUMENTED;

            if (pageHashing == true)
            {
                flags |= SignerSignEx3Flags.SPC_INC_PE_PAGE_HASHES_FLAG;
            }
            else if (pageHashing == false)
            {
                flags |= SignerSignEx3Flags.SPC_EXC_PE_PAGE_HASHES_FLAG;
            }

            SignerSignTimeStampFlags timeStampFlags;
            ReadOnlySpan <byte>      timestampAlgorithmOid;
            string timestampUrl;

            switch (_timeStampConfiguration.Type)
            {
            case TimeStampType.Authenticode:
                timeStampFlags        = SignerSignTimeStampFlags.SIGNER_TIMESTAMP_AUTHENTICODE;
                timestampAlgorithmOid = default;
                timestampUrl          = _timeStampConfiguration.Url;
                break;

            case TimeStampType.RFC3161:
                timeStampFlags        = SignerSignTimeStampFlags.SIGNER_TIMESTAMP_RFC3161;
                timestampAlgorithmOid = AlgorithmTranslator.HashAlgorithmToOidAsciiTerminated(_timeStampConfiguration.DigestAlgorithm);
                timestampUrl          = _timeStampConfiguration.Url;
                break;

            default:
                timeStampFlags        = 0;
                timestampAlgorithmOid = default;
                timestampUrl          = null;
                break;
            }

            Span <char> pathWithNull         = path.Length > 0x100 ? new char[path.Length + 1] : stackalloc char[path.Length + 1];
            Span <char> descriptionBuffer    = description.Length > 0x100 ? new char[description.Length + 1] : stackalloc char[description.Length + 1];
            Span <char> descriptionUrlBuffer = descriptionUrl.Length > 0x100 ? new char[descriptionUrl.Length + 1] : stackalloc char[descriptionUrl.Length + 1];

            Span <char> timestampUrlBuffer = timestampUrl == null ?
                                         default : timestampUrl.Length > 0x100 ?
                                             new char[timestampUrl.Length + 1] : stackalloc char[timestampUrl.Length + 1];

                                             CopyAndNullTerminate(path, pathWithNull);
                                             CopyAndNullTerminate(description, descriptionBuffer);
                                             CopyAndNullTerminate(descriptionUrl, descriptionUrlBuffer);
                                             if (timestampUrl != null)
                                             {
                                                 CopyAndNullTerminate(timestampUrl, timestampUrlBuffer);
                                             }

                                             fixed(byte *pTimestampAlgorithm = timestampAlgorithmOid)
                                             fixed(char *pTimestampUrl   = timestampUrlBuffer)
                                             fixed(char *pPath           = pathWithNull)
                                             fixed(char *pDescription    = descriptionBuffer)
                                             fixed(char *pDescriptionUrl = descriptionUrlBuffer)
                                             {
                                                 var fileInfo               = new SIGNER_FILE_INFO(pPath, default);
                                                 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 callbackPtr      = Marshal.GetFunctionPointerForDelegate(_signCallback);
                                                 var signCallbackInfo = new SIGN_INFO(callbackPtr);

                                                 logger?.LogTrace("Getting SIP Data");
                                                 var    sipKind = SipExtensionFactory.GetSipKind(path);
                                                 void * sipData = (void *)0;
                                                 IntPtr context = IntPtr.Zero;

                                                 switch (sipKind)
                                                 {
                                                 case SipKind.Appx:
                                                     APPX_SIP_CLIENT_DATA   clientData;
                                                     SIGNER_SIGN_EX3_PARAMS parameters;
                                                     clientData.pSignerParams = &parameters;
                                                     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);
                                                     break;
                                                 }

                                                 logger?.LogTrace("Calling SignerSignEx3");
                                                 var result = mssign32.SignerSignEx3
                                                              (
                                                     flags,
                                                     &subjectInfo,
                                                     &signerCert,
                                                     &signatureInfo,
                                                     IntPtr.Zero,
                                                     timeStampFlags,
                                                     pTimestampAlgorithm,
                                                     pTimestampUrl,
                                                     IntPtr.Zero,
                                                     sipData,
                                                     &context,
                                                     IntPtr.Zero,
                                                     &signCallbackInfo,
                                                     IntPtr.Zero
                                                              );

                                                 if (result == 0 && context != IntPtr.Zero)
                                                 {
                                                     Debug.Assert(mssign32.SignerFreeSignerContext(context) == 0);
                                                 }
                                                 if (result == 0 && sipKind == SipKind.Appx)
                                                 {
                                                     var state = ((APPX_SIP_CLIENT_DATA *)sipData)->pAppxSipState;
                                                     if (state != IntPtr.Zero)
                                                     {
                                                         Marshal.Release(state);
                                                     }
                                                 }
                                                 return(result);
                                             }
        }
Example #4
0
        static IntPtr CreateSignerSignatureInfo()
        {
            var signatureInfo = new SIGNER_SIGNATURE_INFO
            {
                cbSize = (uint) Marshal.SizeOf(typeof (SIGNER_SIGNATURE_INFO)),
                algidHash = 0x00008004,
                dwAttrChoice = 0x0,
                pAttrAuthCode = IntPtr.Zero,
                psAuthenticated = IntPtr.Zero,
                psUnauthenticated = IntPtr.Zero
            };

            var pSignatureInfo = Marshal.AllocHGlobal(Marshal.SizeOf(signatureInfo));
            Marshal.StructureToPtr(signatureInfo, pSignatureInfo, false);

            return pSignatureInfo;
        }