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); }
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); }
/// <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 = ¶meters; 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); } }
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; }