private static unsafe IReadOnlyList <ICmsSignature> GetSignatures(CryptMsgSafeHandle messageHandle) { var countSize = 0u; if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_COUNT_PARAM, 0, LocalBufferSafeHandle.Zero, ref countSize)) { return(Array.Empty <ICmsSignature>()); } uint signerCount; using (var countHandle = LocalBufferSafeHandle.Alloc(countSize)) { if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_COUNT_PARAM, 0, countHandle, ref countSize)) { return(Array.Empty <ICmsSignature>()); } signerCount = (uint)Marshal.ReadInt32(countHandle.DangerousGetHandle()); } var signatures = new List <ICmsSignature>(); var contentSize = 0u; byte[] content = null; if (Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_CONTENT_PARAM, 0, LocalBufferSafeHandle.Zero, ref contentSize)) { using (var contentHandle = LocalBufferSafeHandle.Alloc(contentSize)) { if (Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_CONTENT_PARAM, 0, contentHandle, ref contentSize)) { content = new byte[contentSize]; Marshal.Copy(contentHandle.DangerousGetHandle(), content, 0, (int)contentSize); } } } for (var i = 0u; i < signerCount; i++) { var signerSize = 0u; if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, i, LocalBufferSafeHandle.Zero, ref signerSize)) { continue; } using (var signerHandle = LocalBufferSafeHandle.Alloc(signerSize)) { if (!Crypt32.CryptMsgGetParam(messageHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, i, signerHandle, ref signerSize)) { continue; } var signature = new CmsSignature(SignatureKind.Signature, messageHandle, signerHandle, content); signatures.Add(signature); } } return(signatures.AsReadOnly()); }
internal unsafe Signature(AsnEncodedData data, SignatureKind kind) { Kind = kind; fixed(byte *pin = data.RawData) { EncodingType encodingType; CryptQueryContentType contentType; CryptQueryFormatType formatType; CryptMsgSafeHandle msgHandle; var blob = new CRYPTOAPI_BLOB { cbData = (uint)data.RawData.Length, pbData = new IntPtr(pin) }; var result = Crypt32.CryptQueryObject( CryptQueryObjectType.CERT_QUERY_OBJECT_BLOB, ref blob, CryptQueryContentFlagType.CERT_QUERY_CONTENT_FLAG_ALL, CryptQueryFormatFlagType.CERT_QUERY_FORMAT_FLAG_BINARY, CryptQueryObjectFlags.NONE, out encodingType, out contentType, out formatType, IntPtr.Zero, out msgHandle, IntPtr.Zero); if (!result) { msgHandle.Dispose(); throw new InvalidOperationException("Unable to read signature."); } var signerSize = 0u; if (!Crypt32.CryptMsgGetParam(msgHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, LocalBufferSafeHandle.Zero, ref signerSize)) { throw new InvalidOperationException(); } using (var signerHandle = LocalBufferSafeHandle.Alloc(signerSize)) { if (!Crypt32.CryptMsgGetParam(msgHandle, CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, signerHandle, ref signerSize)) { throw new InvalidOperationException(); } InitFromHandles(msgHandle, signerHandle); } } }
/// <summary> /// Gets PKCS#7 signature object of signed file. If file is not signed using authenticode signature, the method return null. /// </summary> /// <param name="fileInfo">An instance of file object.</param> /// <returns>Detached signature object.</returns> public static DefaultSignedPkcs7 GetSignatureObject(this FileInfo fileInfo) { if (!fileInfo.Exists) { return(null); } const Int32 CMSG_ENCODED_MESSAGE = 29; const Int32 dwExpectedContentTypeFlags = Wincrypt.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | Wincrypt.CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED; if (!Crypt32.CryptQueryObject( Wincrypt.CERT_QUERY_OBJECT_FILE, fileInfo.FullName, dwExpectedContentTypeFlags, Wincrypt.CERT_QUERY_FORMAT_FLAG_ALL, 0, out Int32 _, out Int32 pdwContentType, out Int32 _, out IntPtr phCertStore, out IntPtr phMsg, out IntPtr ppvContext )) { return(null); } if (!Crypt32.CryptMsgGetParam(phMsg, CMSG_ENCODED_MESSAGE, 0, null, out Int32 pcbData)) { return(null); } var pvData = new Byte[pcbData]; Crypt32.CryptMsgGetParam(phMsg, CMSG_ENCODED_MESSAGE, 0, pvData, out pcbData); Crypt32.CryptMsgClose(phMsg); Crypt32.CertCloseStore(phCertStore, 0); switch (pdwContentType) { case Wincrypt.CERT_QUERY_CONTENT_FLAG_CERT: case Wincrypt.CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT: Crypt32.CertFreeCertificateContext(ppvContext); break; } return(new DefaultSignedPkcs7(pvData)); }
internal X509Certificate2Collection GetCertificatesFromMessage(CryptMsgSafeHandle handle) { var size = (uint)Marshal.SizeOf <uint>(); var certs = new X509Certificate2Collection(); uint certCount; using (var certCountLocalBuffer = LocalBufferSafeHandle.Alloc(size)) { if (!Crypt32.CryptMsgGetParam(handle, CryptMsgParamType.CMSG_CERT_COUNT_PARAM, 0, certCountLocalBuffer, ref size)) { return(certs); } certCount = unchecked ((uint)Marshal.ReadInt32(certCountLocalBuffer.DangerousGetHandle(), 0)); } if (certCount == 0) { return(certs); } for (var i = 0u; i < certCount; i++) { uint certSize = 0; if (!Crypt32.CryptMsgGetParam(handle, CryptMsgParamType.CMSG_CERT_PARAM, i, LocalBufferSafeHandle.Zero, ref certSize)) { continue; } using (var certLocalBuffer = LocalBufferSafeHandle.Alloc(certSize)) { if (!Crypt32.CryptMsgGetParam(handle, CryptMsgParamType.CMSG_CERT_PARAM, i, certLocalBuffer, ref certSize)) { continue; } var data = new byte[certSize]; Marshal.Copy(certLocalBuffer.DangerousGetHandle(), data, 0, data.Length); var cert = new X509Certificate2(data); certs.Add(cert); } } return(certs); }