Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / ManagedLibraries / Security / System / Security / Cryptography / Pkcs / SignedPkcs7.cs / 1305376 / SignedPkcs7.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // SignedPkcs7.cs // namespace System.Security.Cryptography.Pkcs { using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.Xml; using System.Security.Permissions; using System.Text; using System.Threading; [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public sealed class SignedCms { [SecurityCritical] private SafeCryptMsgHandle m_safeCryptMsgHandle; private int m_version; private SubjectIdentifierType m_signerIdentifierType; private ContentInfo m_contentInfo; private bool m_detached; // // Constructors. // public SignedCms () : this(SubjectIdentifierType.IssuerAndSerialNumber, new ContentInfo(new Oid(CAPI.szOID_RSA_data), new byte[0]), false) {} public SignedCms (SubjectIdentifierType signerIdentifierType) : this(signerIdentifierType, new ContentInfo(new Oid(CAPI.szOID_RSA_data), new byte[0]), false) {} public SignedCms (ContentInfo contentInfo) : this(SubjectIdentifierType.IssuerAndSerialNumber, contentInfo, false) {} public SignedCms (SubjectIdentifierType signerIdentifierType, ContentInfo contentInfo) : this(signerIdentifierType, contentInfo, false) {} public SignedCms (ContentInfo contentInfo, bool detached) : this(SubjectIdentifierType.IssuerAndSerialNumber, contentInfo, detached) {} [SecuritySafeCritical] public SignedCms (SubjectIdentifierType signerIdentifierType, ContentInfo contentInfo, bool detached) { if (contentInfo == null) throw new ArgumentNullException("contentInfo"); if (contentInfo.Content == null) throw new ArgumentNullException("contentInfo.Content"); // Reset all states. if (signerIdentifierType != SubjectIdentifierType.SubjectKeyIdentifier && signerIdentifierType != SubjectIdentifierType.IssuerAndSerialNumber && signerIdentifierType != SubjectIdentifierType.NoSignature) { signerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber; } m_safeCryptMsgHandle = SafeCryptMsgHandle.InvalidHandle; m_signerIdentifierType = signerIdentifierType; m_version = 0; m_contentInfo = contentInfo; m_detached = detached; } // // Public APIs. // public int Version { [SecuritySafeCritical] get { // SignedData version can change based on user's operation, so // return the value passed in to the constructor if no message handle is // available. Otherwise, query the version from the handle if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) return m_version; return (int) PkcsUtils.GetVersion(m_safeCryptMsgHandle); } } public ContentInfo ContentInfo { get { return m_contentInfo; } } public bool Detached { get { return m_detached; } } public X509Certificate2Collection Certificates { [SecuritySafeCritical] get { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) { return new X509Certificate2Collection(); } return PkcsUtils.GetCertificates(m_safeCryptMsgHandle); } } public SignerInfoCollection SignerInfos { [SecuritySafeCritical] get { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) { return new SignerInfoCollection(); } return new SignerInfoCollection(this); } } [SecuritySafeCritical] public byte[] Encode () { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); return PkcsUtils.GetMessage(m_safeCryptMsgHandle); } [SecuritySafeCritical] public void Decode (byte[] encodedMessage) { if (encodedMessage == null) throw new ArgumentNullException("encodedMessage"); if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) { m_safeCryptMsgHandle.Dispose(); } m_safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); if (!this.Detached) { Oid contentType = PkcsUtils.GetContentType(m_safeCryptMsgHandle); byte[] content = PkcsUtils.GetContent(m_safeCryptMsgHandle); m_contentInfo = new ContentInfo(contentType, content); } } public void ComputeSignature () { ComputeSignature(new CmsSigner(m_signerIdentifierType), true); } public void ComputeSignature (CmsSigner signer) { ComputeSignature(signer, true); } [SecuritySafeCritical] private static int SafeGetLastWin32Error() { return Marshal.GetLastWin32Error(); } [SecuritySafeCritical] public void ComputeSignature (CmsSigner signer, bool silent) { if (signer == null) throw new ArgumentNullException("signer"); if (ContentInfo.Content.Length == 0) throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Sign_Empty_Content")); if (SubjectIdentifierType.NoSignature == signer.SignerIdentifierType) { if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Sign_No_Signature_First_Signer")); // First signer. Sign(signer, silent); return; } if (signer.Certificate == null) { if (silent) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_RecipientCertificateNotFound")); else signer.Certificate = PkcsUtils.SelectSignerCertificate(); } if (!signer.Certificate.HasPrivateKey) throw new CryptographicException(CAPI.NTE_NO_KEY); // CspParameters parameters = new CspParameters(); if (X509Utils.GetPrivateKeyInfo(X509Utils.GetCertContext(signer.Certificate), ref parameters) == false) throw new CryptographicException(SafeGetLastWin32Error()); KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Open | KeyContainerPermissionFlags.Sign); kp.AccessEntries.Add(entry); kp.Demand(); if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) { // First signer. Sign(signer, silent); } else { // Co-signing. CoSign(signer, silent); } } [SecuritySafeCritical] public void RemoveSignature (int index) { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); unsafe { uint dwSigners = 0; uint cbCount = (uint) Marshal.SizeOf(typeof(uint)); if (!CAPI.CAPISafe.CryptMsgGetParam(m_safeCryptMsgHandle, CAPI.CMSG_SIGNER_COUNT_PARAM, 0, new IntPtr(&dwSigners), new IntPtr(&cbCount))) throw new CryptographicException(Marshal.GetLastWin32Error()); if (index < 0 || index >= (int) dwSigners) throw new ArgumentOutOfRangeException("index", SecurityResources.GetResourceString("ArgumentOutOfRange_Index")); if (!CAPI.CryptMsgControl(m_safeCryptMsgHandle, 0, CAPI.CMSG_CTRL_DEL_SIGNER, new IntPtr(&index))) throw new CryptographicException(Marshal.GetLastWin32Error()); } } [SecuritySafeCritical] public void RemoveSignature (SignerInfo signerInfo) { if (signerInfo == null) throw new ArgumentNullException("signerInfo"); RemoveSignature(PkcsUtils.GetSignerIndex(m_safeCryptMsgHandle, signerInfo, 0)); } public void CheckSignature (bool verifySignatureOnly) { CheckSignature(new X509Certificate2Collection(), verifySignatureOnly); } [SecuritySafeCritical] public void CheckSignature (X509Certificate2Collection extraStore, bool verifySignatureOnly) { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); if (extraStore == null) throw new ArgumentNullException("extraStore"); CheckSignatures(this.SignerInfos, extraStore, verifySignatureOnly); } [SecuritySafeCritical] public void CheckHash () { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException( SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); CheckHashes(this.SignerInfos); } // // Internal methods. // [SecurityCritical] internal SafeCryptMsgHandle GetCryptMsgHandle() { return m_safeCryptMsgHandle; } [SecuritySafeCritical] internal void ReopenToDecode () { byte[] encodedMessage = PkcsUtils.GetMessage(m_safeCryptMsgHandle); if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) { m_safeCryptMsgHandle.Dispose(); } m_safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); } [SecuritySafeCritical] private unsafe void Sign (CmsSigner signer, bool silent) { SafeCryptMsgHandle safeCryptMsgHandle = null; CAPI.CMSG_SIGNED_ENCODE_INFO signedEncodeInfo = new CAPI.CMSG_SIGNED_ENCODE_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNED_ENCODE_INFO))); CAPI.CMSG_SIGNER_ENCODE_INFO signerEncodeInfo = PkcsUtils.CreateSignerEncodeInfo(signer, silent); byte[] encodedMessage = null; try { SafeLocalAllocHandle pSignerEncodeInfo = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)))); try { Marshal.StructureToPtr(signerEncodeInfo, pSignerEncodeInfo.DangerousGetHandle(), false); X509Certificate2Collection bagOfCerts = PkcsUtils.CreateBagOfCertificates(signer); SafeLocalAllocHandle pEncodedBagOfCerts = PkcsUtils.CreateEncodedCertBlob(bagOfCerts); signedEncodeInfo.cSigners = 1; signedEncodeInfo.rgSigners = pSignerEncodeInfo.DangerousGetHandle(); signedEncodeInfo.cCertEncoded = (uint) bagOfCerts.Count; if (bagOfCerts.Count > 0) signedEncodeInfo.rgCertEncoded = pEncodedBagOfCerts.DangerousGetHandle(); // Because of the way CAPI treats inner content OID, we should pass NULL // for data type, otherwise detached will not work. if (String.Compare(this.ContentInfo.ContentType.Value, CAPI.szOID_RSA_data, StringComparison.OrdinalIgnoreCase) == 0) { safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, Detached ? CAPI.CMSG_DETACHED_FLAG : 0, CAPI.CMSG_SIGNED, new IntPtr(&signedEncodeInfo), IntPtr.Zero, IntPtr.Zero); } else { safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, Detached ? CAPI.CMSG_DETACHED_FLAG : 0, CAPI.CMSG_SIGNED, new IntPtr(&signedEncodeInfo), this.ContentInfo.ContentType.Value, IntPtr.Zero); } if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); if (this.ContentInfo.Content.Length > 0) { if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, this.ContentInfo.pContent, (uint) this.ContentInfo.Content.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); } // Retrieve encoded message. encodedMessage = PkcsUtils.GetContent(safeCryptMsgHandle); safeCryptMsgHandle.Dispose(); pEncodedBagOfCerts.Dispose(); } finally { Marshal.DestroyStructure(pSignerEncodeInfo.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)); pSignerEncodeInfo.Dispose(); } } finally { // Don't forget to free all the resource still held inside signerEncodeInfo. signerEncodeInfo.Dispose(); } // Re-open to decode. safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) { m_safeCryptMsgHandle.Dispose(); } m_safeCryptMsgHandle = safeCryptMsgHandle; GC.KeepAlive(signer); } [SecuritySafeCritical] private void CoSign (CmsSigner signer, bool silent) { CAPI.CMSG_SIGNER_ENCODE_INFO signerEncodeInfo = PkcsUtils.CreateSignerEncodeInfo(signer, silent); try { SafeLocalAllocHandle pSignerEncodeInfo = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)))); try { // Marshal to unmanaged memory. Marshal.StructureToPtr(signerEncodeInfo, pSignerEncodeInfo.DangerousGetHandle(), false); // Add the signature. if (!CAPI.CryptMsgControl(m_safeCryptMsgHandle, 0, CAPI.CMSG_CTRL_ADD_SIGNER, pSignerEncodeInfo.DangerousGetHandle())) throw new CryptographicException(Marshal.GetLastWin32Error()); } finally { Marshal.DestroyStructure(pSignerEncodeInfo.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)); pSignerEncodeInfo.Dispose(); } } finally { // and don't forget to dispose of resources allocated for the structure. signerEncodeInfo.Dispose(); } // Finally, add certs to bag of certs. PkcsUtils.AddCertsToMessage(m_safeCryptMsgHandle, Certificates, PkcsUtils.CreateBagOfCertificates(signer)); } // // Private static methods. // [SecuritySafeCritical] private static SafeCryptMsgHandle OpenToDecode (byte[] encodedMessage, ContentInfo contentInfo, bool detached) { // Open the message for decode. SafeCryptMsgHandle safeCryptMsgHandle = CAPI.CAPISafe.CryptMsgOpenToDecode( CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, detached ? CAPI.CMSG_DETACHED_FLAG : 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); // ---- the message. if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, encodedMessage, (uint) encodedMessage.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); // Make sure this is PKCS7 SignedData type. if (CAPI.CMSG_SIGNED != PkcsUtils.GetMessageType(safeCryptMsgHandle)) throw new CryptographicException(CAPI.CRYPT_E_INVALID_MSG_TYPE); // If detached, then update message with content if available. if (detached) { byte[] content = contentInfo.Content; if (content != null && content.Length > 0) { if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, content, (uint) content.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); } } return safeCryptMsgHandle; } private static void CheckSignatures (SignerInfoCollection signers, X509Certificate2Collection extraStore, bool verifySignatureOnly) { if (signers == null || signers.Count < 1) throw new CryptographicException(CAPI.CRYPT_E_NO_SIGNER); foreach (SignerInfo signer in signers) { signer.CheckSignature(extraStore, verifySignatureOnly); if (signer.CounterSignerInfos.Count > 0) CheckSignatures(signer.CounterSignerInfos, extraStore, verifySignatureOnly); } } private static void CheckHashes (SignerInfoCollection signers) { if (signers == null || signers.Count < 1) throw new CryptographicException(CAPI.CRYPT_E_NO_SIGNER); foreach (SignerInfo signer in signers) { if (signer.SignerIdentifier.Type == SubjectIdentifierType.NoSignature) signer.CheckHash(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // // SignedPkcs7.cs // namespace System.Security.Cryptography.Pkcs { using System.Diagnostics; using System.Globalization; using System.IO; using System.Runtime.InteropServices; using System.Security; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.Xml; using System.Security.Permissions; using System.Text; using System.Threading; [System.Security.Permissions.HostProtection(MayLeakOnAbort = true)] public sealed class SignedCms { [SecurityCritical] private SafeCryptMsgHandle m_safeCryptMsgHandle; private int m_version; private SubjectIdentifierType m_signerIdentifierType; private ContentInfo m_contentInfo; private bool m_detached; // // Constructors. // public SignedCms () : this(SubjectIdentifierType.IssuerAndSerialNumber, new ContentInfo(new Oid(CAPI.szOID_RSA_data), new byte[0]), false) {} public SignedCms (SubjectIdentifierType signerIdentifierType) : this(signerIdentifierType, new ContentInfo(new Oid(CAPI.szOID_RSA_data), new byte[0]), false) {} public SignedCms (ContentInfo contentInfo) : this(SubjectIdentifierType.IssuerAndSerialNumber, contentInfo, false) {} public SignedCms (SubjectIdentifierType signerIdentifierType, ContentInfo contentInfo) : this(signerIdentifierType, contentInfo, false) {} public SignedCms (ContentInfo contentInfo, bool detached) : this(SubjectIdentifierType.IssuerAndSerialNumber, contentInfo, detached) {} [SecuritySafeCritical] public SignedCms (SubjectIdentifierType signerIdentifierType, ContentInfo contentInfo, bool detached) { if (contentInfo == null) throw new ArgumentNullException("contentInfo"); if (contentInfo.Content == null) throw new ArgumentNullException("contentInfo.Content"); // Reset all states. if (signerIdentifierType != SubjectIdentifierType.SubjectKeyIdentifier && signerIdentifierType != SubjectIdentifierType.IssuerAndSerialNumber && signerIdentifierType != SubjectIdentifierType.NoSignature) { signerIdentifierType = SubjectIdentifierType.IssuerAndSerialNumber; } m_safeCryptMsgHandle = SafeCryptMsgHandle.InvalidHandle; m_signerIdentifierType = signerIdentifierType; m_version = 0; m_contentInfo = contentInfo; m_detached = detached; } // // Public APIs. // public int Version { [SecuritySafeCritical] get { // SignedData version can change based on user's operation, so // return the value passed in to the constructor if no message handle is // available. Otherwise, query the version from the handle if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) return m_version; return (int) PkcsUtils.GetVersion(m_safeCryptMsgHandle); } } public ContentInfo ContentInfo { get { return m_contentInfo; } } public bool Detached { get { return m_detached; } } public X509Certificate2Collection Certificates { [SecuritySafeCritical] get { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) { return new X509Certificate2Collection(); } return PkcsUtils.GetCertificates(m_safeCryptMsgHandle); } } public SignerInfoCollection SignerInfos { [SecuritySafeCritical] get { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) { return new SignerInfoCollection(); } return new SignerInfoCollection(this); } } [SecuritySafeCritical] public byte[] Encode () { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); return PkcsUtils.GetMessage(m_safeCryptMsgHandle); } [SecuritySafeCritical] public void Decode (byte[] encodedMessage) { if (encodedMessage == null) throw new ArgumentNullException("encodedMessage"); if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) { m_safeCryptMsgHandle.Dispose(); } m_safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); if (!this.Detached) { Oid contentType = PkcsUtils.GetContentType(m_safeCryptMsgHandle); byte[] content = PkcsUtils.GetContent(m_safeCryptMsgHandle); m_contentInfo = new ContentInfo(contentType, content); } } public void ComputeSignature () { ComputeSignature(new CmsSigner(m_signerIdentifierType), true); } public void ComputeSignature (CmsSigner signer) { ComputeSignature(signer, true); } [SecuritySafeCritical] private static int SafeGetLastWin32Error() { return Marshal.GetLastWin32Error(); } [SecuritySafeCritical] public void ComputeSignature (CmsSigner signer, bool silent) { if (signer == null) throw new ArgumentNullException("signer"); if (ContentInfo.Content.Length == 0) throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Sign_Empty_Content")); if (SubjectIdentifierType.NoSignature == signer.SignerIdentifierType) { if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Sign_No_Signature_First_Signer")); // First signer. Sign(signer, silent); return; } if (signer.Certificate == null) { if (silent) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_RecipientCertificateNotFound")); else signer.Certificate = PkcsUtils.SelectSignerCertificate(); } if (!signer.Certificate.HasPrivateKey) throw new CryptographicException(CAPI.NTE_NO_KEY); // CspParameters parameters = new CspParameters(); if (X509Utils.GetPrivateKeyInfo(X509Utils.GetCertContext(signer.Certificate), ref parameters) == false) throw new CryptographicException(SafeGetLastWin32Error()); KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Open | KeyContainerPermissionFlags.Sign); kp.AccessEntries.Add(entry); kp.Demand(); if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) { // First signer. Sign(signer, silent); } else { // Co-signing. CoSign(signer, silent); } } [SecuritySafeCritical] public void RemoveSignature (int index) { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); unsafe { uint dwSigners = 0; uint cbCount = (uint) Marshal.SizeOf(typeof(uint)); if (!CAPI.CAPISafe.CryptMsgGetParam(m_safeCryptMsgHandle, CAPI.CMSG_SIGNER_COUNT_PARAM, 0, new IntPtr(&dwSigners), new IntPtr(&cbCount))) throw new CryptographicException(Marshal.GetLastWin32Error()); if (index < 0 || index >= (int) dwSigners) throw new ArgumentOutOfRangeException("index", SecurityResources.GetResourceString("ArgumentOutOfRange_Index")); if (!CAPI.CryptMsgControl(m_safeCryptMsgHandle, 0, CAPI.CMSG_CTRL_DEL_SIGNER, new IntPtr(&index))) throw new CryptographicException(Marshal.GetLastWin32Error()); } } [SecuritySafeCritical] public void RemoveSignature (SignerInfo signerInfo) { if (signerInfo == null) throw new ArgumentNullException("signerInfo"); RemoveSignature(PkcsUtils.GetSignerIndex(m_safeCryptMsgHandle, signerInfo, 0)); } public void CheckSignature (bool verifySignatureOnly) { CheckSignature(new X509Certificate2Collection(), verifySignatureOnly); } [SecuritySafeCritical] public void CheckSignature (X509Certificate2Collection extraStore, bool verifySignatureOnly) { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); if (extraStore == null) throw new ArgumentNullException("extraStore"); CheckSignatures(this.SignerInfos, extraStore, verifySignatureOnly); } [SecuritySafeCritical] public void CheckHash () { if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException( SecurityResources.GetResourceString("Cryptography_Cms_MessageNotSigned")); CheckHashes(this.SignerInfos); } // // Internal methods. // [SecurityCritical] internal SafeCryptMsgHandle GetCryptMsgHandle() { return m_safeCryptMsgHandle; } [SecuritySafeCritical] internal void ReopenToDecode () { byte[] encodedMessage = PkcsUtils.GetMessage(m_safeCryptMsgHandle); if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) { m_safeCryptMsgHandle.Dispose(); } m_safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); } [SecuritySafeCritical] private unsafe void Sign (CmsSigner signer, bool silent) { SafeCryptMsgHandle safeCryptMsgHandle = null; CAPI.CMSG_SIGNED_ENCODE_INFO signedEncodeInfo = new CAPI.CMSG_SIGNED_ENCODE_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNED_ENCODE_INFO))); CAPI.CMSG_SIGNER_ENCODE_INFO signerEncodeInfo = PkcsUtils.CreateSignerEncodeInfo(signer, silent); byte[] encodedMessage = null; try { SafeLocalAllocHandle pSignerEncodeInfo = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)))); try { Marshal.StructureToPtr(signerEncodeInfo, pSignerEncodeInfo.DangerousGetHandle(), false); X509Certificate2Collection bagOfCerts = PkcsUtils.CreateBagOfCertificates(signer); SafeLocalAllocHandle pEncodedBagOfCerts = PkcsUtils.CreateEncodedCertBlob(bagOfCerts); signedEncodeInfo.cSigners = 1; signedEncodeInfo.rgSigners = pSignerEncodeInfo.DangerousGetHandle(); signedEncodeInfo.cCertEncoded = (uint) bagOfCerts.Count; if (bagOfCerts.Count > 0) signedEncodeInfo.rgCertEncoded = pEncodedBagOfCerts.DangerousGetHandle(); // Because of the way CAPI treats inner content OID, we should pass NULL // for data type, otherwise detached will not work. if (String.Compare(this.ContentInfo.ContentType.Value, CAPI.szOID_RSA_data, StringComparison.OrdinalIgnoreCase) == 0) { safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, Detached ? CAPI.CMSG_DETACHED_FLAG : 0, CAPI.CMSG_SIGNED, new IntPtr(&signedEncodeInfo), IntPtr.Zero, IntPtr.Zero); } else { safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, Detached ? CAPI.CMSG_DETACHED_FLAG : 0, CAPI.CMSG_SIGNED, new IntPtr(&signedEncodeInfo), this.ContentInfo.ContentType.Value, IntPtr.Zero); } if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); if (this.ContentInfo.Content.Length > 0) { if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, this.ContentInfo.pContent, (uint) this.ContentInfo.Content.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); } // Retrieve encoded message. encodedMessage = PkcsUtils.GetContent(safeCryptMsgHandle); safeCryptMsgHandle.Dispose(); pEncodedBagOfCerts.Dispose(); } finally { Marshal.DestroyStructure(pSignerEncodeInfo.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)); pSignerEncodeInfo.Dispose(); } } finally { // Don't forget to free all the resource still held inside signerEncodeInfo. signerEncodeInfo.Dispose(); } // Re-open to decode. safeCryptMsgHandle = OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) { m_safeCryptMsgHandle.Dispose(); } m_safeCryptMsgHandle = safeCryptMsgHandle; GC.KeepAlive(signer); } [SecuritySafeCritical] private void CoSign (CmsSigner signer, bool silent) { CAPI.CMSG_SIGNER_ENCODE_INFO signerEncodeInfo = PkcsUtils.CreateSignerEncodeInfo(signer, silent); try { SafeLocalAllocHandle pSignerEncodeInfo = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)))); try { // Marshal to unmanaged memory. Marshal.StructureToPtr(signerEncodeInfo, pSignerEncodeInfo.DangerousGetHandle(), false); // Add the signature. if (!CAPI.CryptMsgControl(m_safeCryptMsgHandle, 0, CAPI.CMSG_CTRL_ADD_SIGNER, pSignerEncodeInfo.DangerousGetHandle())) throw new CryptographicException(Marshal.GetLastWin32Error()); } finally { Marshal.DestroyStructure(pSignerEncodeInfo.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)); pSignerEncodeInfo.Dispose(); } } finally { // and don't forget to dispose of resources allocated for the structure. signerEncodeInfo.Dispose(); } // Finally, add certs to bag of certs. PkcsUtils.AddCertsToMessage(m_safeCryptMsgHandle, Certificates, PkcsUtils.CreateBagOfCertificates(signer)); } // // Private static methods. // [SecuritySafeCritical] private static SafeCryptMsgHandle OpenToDecode (byte[] encodedMessage, ContentInfo contentInfo, bool detached) { // Open the message for decode. SafeCryptMsgHandle safeCryptMsgHandle = CAPI.CAPISafe.CryptMsgOpenToDecode( CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, detached ? CAPI.CMSG_DETACHED_FLAG : 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); // ---- the message. if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, encodedMessage, (uint) encodedMessage.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); // Make sure this is PKCS7 SignedData type. if (CAPI.CMSG_SIGNED != PkcsUtils.GetMessageType(safeCryptMsgHandle)) throw new CryptographicException(CAPI.CRYPT_E_INVALID_MSG_TYPE); // If detached, then update message with content if available. if (detached) { byte[] content = contentInfo.Content; if (content != null && content.Length > 0) { if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, content, (uint) content.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); } } return safeCryptMsgHandle; } private static void CheckSignatures (SignerInfoCollection signers, X509Certificate2Collection extraStore, bool verifySignatureOnly) { if (signers == null || signers.Count < 1) throw new CryptographicException(CAPI.CRYPT_E_NO_SIGNER); foreach (SignerInfo signer in signers) { signer.CheckSignature(extraStore, verifySignatureOnly); if (signer.CounterSignerInfos.Count > 0) CheckSignatures(signer.CounterSignerInfos, extraStore, verifySignatureOnly); } } private static void CheckHashes (SignerInfoCollection signers) { if (signers == null || signers.Count < 1) throw new CryptographicException(CAPI.CRYPT_E_NO_SIGNER); foreach (SignerInfo signer in signers) { if (signer.SignerIdentifier.Type == SubjectIdentifierType.NoSignature) signer.CheckHash(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DbException.cs
- COM2ComponentEditor.cs
- odbcmetadatafactory.cs
- SectionVisual.cs
- AppDomainProtocolHandler.cs
- MailAddressCollection.cs
- WindowsTitleBar.cs
- XmlDataDocument.cs
- entityreference_tresulttype.cs
- PerformanceCounterManager.cs
- IgnoreSectionHandler.cs
- BaseAppDomainProtocolHandler.cs
- PropertyInfoSet.cs
- XmlSchemaSimpleType.cs
- ParameterReplacerVisitor.cs
- BoolLiteral.cs
- Evaluator.cs
- IPipelineRuntime.cs
- AppSettingsReader.cs
- DetailsViewPageEventArgs.cs
- TextServicesCompartmentContext.cs
- GenericRootAutomationPeer.cs
- BackgroundWorker.cs
- ControllableStoryboardAction.cs
- QueryContinueDragEvent.cs
- FreezableCollection.cs
- DataGridLengthConverter.cs
- TextElementAutomationPeer.cs
- MethodCallExpression.cs
- Label.cs
- __ConsoleStream.cs
- DivideByZeroException.cs
- SqlConnectionHelper.cs
- CodeFieldReferenceExpression.cs
- ListViewItem.cs
- LinqDataSource.cs
- SecurityProtocolCorrelationState.cs
- Image.cs
- MultiPageTextView.cs
- SqlRowUpdatedEvent.cs
- ServiceReference.cs
- KeyConstraint.cs
- TextReader.cs
- ReadingWritingEntityEventArgs.cs
- DesignerUtility.cs
- GetTokenRequest.cs
- XmlSchemaAttributeGroupRef.cs
- WrapperSecurityCommunicationObject.cs
- ComponentCollection.cs
- SqlLiftWhereClauses.cs
- XmlNamespaceManager.cs
- PageContentCollection.cs
- CodeNamespace.cs
- WebPageTraceListener.cs
- InkCollectionBehavior.cs
- ExternalException.cs
- DiagnosticsConfiguration.cs
- ConsoleTraceListener.cs
- RemotingSurrogateSelector.cs
- DataGridSortCommandEventArgs.cs
- InstanceOwnerException.cs
- SessionPageStatePersister.cs
- RoleManagerSection.cs
- FlowDocument.cs
- ValueConversionAttribute.cs
- DataGridViewCellCollection.cs
- UnsafeNativeMethods.cs
- DocobjHost.cs
- SqlMultiplexer.cs
- UrlPropertyAttribute.cs
- ThreadPool.cs
- MSAAEventDispatcher.cs
- SafeRightsManagementPubHandle.cs
- SplitContainer.cs
- MessageEnumerator.cs
- TranslateTransform.cs
- DesignerActionHeaderItem.cs
- RequestStatusBarUpdateEventArgs.cs
- LogicalChannel.cs
- BindingNavigator.cs
- XmlCharacterData.cs
- WebPartTransformerAttribute.cs
- SiteMapPathDesigner.cs
- HtmlGenericControl.cs
- ListenerElementsCollection.cs
- IndentTextWriter.cs
- Debug.cs
- KeyBinding.cs
- XmlSerializer.cs
- QilCloneVisitor.cs
- SoapServerProtocol.cs
- LicenseException.cs
- Semaphore.cs
- ContentFilePart.cs
- CommandSet.cs
- ClientConfigurationHost.cs
- CommandConverter.cs
- TemplateBindingExtensionConverter.cs
- SystemTcpStatistics.cs
- MemoryPressure.cs