private static IntPtr GetSubjectInfoPointer(string path) { // target file info var signerFileInfo = new SIGNER_FILE_INFO { pwszFileName = Marshal.StringToHGlobalUni(path), cbSize = (uint)Marshal.SizeOf <SIGNER_FILE_INFO>(), hFile = IntPtr.Zero }; // subject info var signerSubjectInfo = new SIGNER_SUBJECT_INFO { cbSize = (uint)Marshal.SizeOf <SIGNER_SUBJECT_INFO>(), pdwIndex = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint))), dwSubjectChoice = Constants.SIGNER_SUBJECT_FILE, SubjectChoice = new SIGNER_SUBJECT_INFO.SubjectChoiceUnion { pSignerFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf <SIGNER_FILE_INFO>()) } }; Marshal.StructureToPtr(Constants.DONT_CARE, signerSubjectInfo.pdwIndex, false); Marshal.StructureToPtr(signerFileInfo, signerSubjectInfo.SubjectChoice.pSignerFileInfo, false); var subjectHandle = Marshal.AllocHGlobal(Marshal.SizeOf <SIGNER_SUBJECT_INFO>()); Marshal.StructureToPtr(signerSubjectInfo, subjectHandle, false); return(subjectHandle); }
private static IntPtr CreateSignerSubjectInfo(string pathToAssembly) { SIGNER_SUBJECT_INFO info = new SIGNER_SUBJECT_INFO { cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_SUBJECT_INFO)), pdwIndex = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint))) }; var index = 0; Marshal.StructureToPtr(index, info.pdwIndex, false); info.dwSubjectChoice = 0x1; //SIGNER_SUBJECT_FILE IntPtr assemblyFilePtr = Marshal.StringToHGlobalUni(pathToAssembly); SIGNER_FILE_INFO fileInfo = new SIGNER_FILE_INFO { cbSize = (uint)Marshal.SizeOf(typeof(SIGNER_FILE_INFO)), pwszFileName = assemblyFilePtr, hFile = IntPtr.Zero }; info.Union1 = new SIGNER_SUBJECT_INFO.SubjectChoiceUnion { pSignerFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SIGNER_FILE_INFO))) }; Marshal.StructureToPtr(fileInfo, info.Union1.pSignerFileInfo, false); IntPtr pSubjectInfo = Marshal.AllocHGlobal(Marshal.SizeOf(info)); Marshal.StructureToPtr(info, pSubjectInfo, false); return(pSubjectInfo); }
/// <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 CreateSignerSubjectInfo(string pathToAssembly) { var info = new SIGNER_SUBJECT_INFO { cbSize = (uint) Marshal.SizeOf(typeof (SIGNER_SUBJECT_INFO)), pdwIndex = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (uint))) }; const int index = 0; Marshal.StructureToPtr(index, info.pdwIndex, false); info.dwSubjectChoice = 0x1; //SIGNER_SUBJECT_FILE var assemblyFilePtr = Marshal.StringToHGlobalUni(pathToAssembly); var fileInfo = new SIGNER_FILE_INFO { cbSize = (uint) Marshal.SizeOf(typeof (SIGNER_FILE_INFO)), pwszFileName = assemblyFilePtr, hFile = IntPtr.Zero }; info.Union1 = new SIGNER_SUBJECT_INFO.SubjectChoiceUnion { pSignerFileInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof (SIGNER_FILE_INFO))) }; Marshal.StructureToPtr(fileInfo, info.Union1.pSignerFileInfo, false); var pSubjectInfo = Marshal.AllocHGlobal(Marshal.SizeOf(info)); Marshal.StructureToPtr(info, pSubjectInfo, false); return pSubjectInfo; }