private static IntPtr CreateSignerCert(string thumbPrint)
        {
            SIGNER_CERT signerCert = new SIGNER_CERT
            {
                cbSize       = (uint)Marshal.SizeOf(typeof(SIGNER_CERT)),
                dwCertChoice = 0x2,
                Union1       = new SIGNER_CERT.SignerCertUnion
                {
                    pCertStoreInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIGNER_CERT_STORE_INFO)))
                },
                hwnd = IntPtr.Zero
            };
            const int        X509_ASN_ENCODING   = 0x00000001;
            const int        PKCS_7_ASN_ENCODING = 0x00010000;
            X509Certificate2 cert         = FindCertByThumbPrint(thumbPrint);
            IntPtr           pCertContext = CertCreateCertificateContext(
                X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                cert.GetRawCertData(),
                cert.GetRawCertData().Length);
            SIGNER_CERT_STORE_INFO certStoreInfo = new SIGNER_CERT_STORE_INFO
            {
                cbSize       = (uint)Marshal.SizeOf(typeof(SIGNER_CERT_STORE_INFO)),
                pSigningCert = pCertContext,
                dwCertPolicy = 0x2,     // SIGNER_CERT_POLICY_CHAIN
                hCertStore   = IntPtr.Zero
            };

            Marshal.StructureToPtr(certStoreInfo, signerCert.Union1.pCertStoreInfo, false);
            IntPtr pSignerCert = Marshal.AllocHGlobal(Marshal.SizeOf(signerCert));

            Marshal.StructureToPtr(signerCert, pSignerCert, false);
            return(pSignerCert);
        }
Example #2
0
        private static IntPtr GetSignerCertificatePointer(IntPtr certificate)
        {
            // cert store info
            var certStoreInfo = new SIGNER_CERT_STORE_INFO
            {
                cbSize       = (uint)Marshal.SizeOf <SIGNER_CERT_STORE_INFO>(),
                dwCertPolicy = Constants.SIGNER_CERT_POLICY_CHAIN_NO_ROOT,
                pSigningCert = certificate,
                hCertStore   = IntPtr.Zero
            };

            // signer cert info
            var signerCertInfo = new SIGNER_CERT
            {
                cbSize           = (uint)Marshal.SizeOf <SIGNER_CERT>(),
                dwCertChoice     = Constants.SIGNER_CERT_STORE,
                SignerCertSource = new SIGNER_CERT.SignerCertSourceUnion
                {
                    pCertStoreInfo = Marshal.AllocHGlobal(Marshal.SizeOf <SIGNER_CERT_STORE_INFO>())
                }
            };

            var certHandle = Marshal.AllocHGlobal(Marshal.SizeOf <SIGNER_CERT>());

            Marshal.StructureToPtr(signerCertInfo, certHandle, false);

            Marshal.StructureToPtr(certStoreInfo, signerCertInfo.SignerCertSource.pCertStoreInfo, false);
            return(certHandle);
        }
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 CreateSignerCertificate(X509Certificate2 certificate)
        {
            var signerCertificate = new SIGNER_CERT
            {
                cbSize = (uint) Marshal.SizeOf(typeof (SIGNER_CERT)),
                dwCertChoice = 0x2,
                Union1 = new SIGNER_CERT.SignerCertUnion
                {
                    pCertStoreInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (SIGNER_CERT_STORE_INFO)))
                },
                hwnd = IntPtr.Zero
            };

            const int X509_ASN_ENCODING = 0x00000001;
            const int PKCS_7_ASN_ENCODING = 0x00010000;

            var pCertContext = CertCreateCertificateContext(
                X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                certificate.GetRawCertData(),
                certificate.GetRawCertData()
                           .Length);

            var certStoreInfo = new SIGNER_CERT_STORE_INFO
            {
                cbSize = (uint) Marshal.SizeOf(typeof (SIGNER_CERT_STORE_INFO)),
                pSigningCert = pCertContext,
                dwCertPolicy = 0x2,
                hCertStore = IntPtr.Zero
            };

            Marshal.StructureToPtr(certStoreInfo, signerCertificate.Union1.pCertStoreInfo, false);

            var pSignerCert = Marshal.AllocHGlobal(Marshal.SizeOf(signerCertificate));
            Marshal.StructureToPtr(signerCertificate, pSignerCert, false);

            return pSignerCert;
        }