internal RecipientInfoCollection(SafeCryptMsgHandle safeCryptMsgHandle) { bool flag = PkcsUtils.CmsSupported(); uint num1 = 0U; uint num2 = (uint)Marshal.SizeOf(typeof(uint)); if (flag) { if (!CAPI.CAPISafe.CryptMsgGetParam(safeCryptMsgHandle, 33U, 0U, new IntPtr((void*)&num1), new IntPtr((void*)&num2))) throw new CryptographicException(Marshal.GetLastWin32Error()); } else if (!CAPI.CAPISafe.CryptMsgGetParam(safeCryptMsgHandle, 17U, 0U, new IntPtr((void*)&num1), new IntPtr((void*)&num2))) throw new CryptographicException(Marshal.GetLastWin32Error()); this.m_recipientInfos = new ArrayList(); for (uint index = 0U; index < num1; ++index) { if (flag) { SafeLocalAllocHandle pvData; uint cbData; PkcsUtils.GetParam(safeCryptMsgHandle, 36U, index, out pvData, out cbData); CAPI.CMSG_CMS_RECIPIENT_INFO cmsRecipientInfo = (CAPI.CMSG_CMS_RECIPIENT_INFO)Marshal.PtrToStructure(pvData.DangerousGetHandle(), typeof(CAPI.CMSG_CMS_RECIPIENT_INFO)); switch (cmsRecipientInfo.dwRecipientChoice) { case 1U: CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO keyTrans = (CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO)); this.m_recipientInfos.Add((object)new KeyTransRecipientInfo(pvData, keyTrans, index)); continue; case 2U: CAPI.CMSG_KEY_AGREE_RECIPIENT_INFO agreeRecipientInfo = (CAPI.CMSG_KEY_AGREE_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_INFO)); switch (agreeRecipientInfo.dwOriginatorChoice) { case 1U: CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO certIdRecipient = (CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO)); for (uint subIndex = 0U; subIndex < certIdRecipient.cRecipientEncryptedKeys; ++subIndex) this.m_recipientInfos.Add((object)new KeyAgreeRecipientInfo(pvData, certIdRecipient, index, subIndex)); continue; case 2U: CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO publicKeyRecipient = (CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO)); for (uint subIndex = 0U; subIndex < publicKeyRecipient.cRecipientEncryptedKeys; ++subIndex) this.m_recipientInfos.Add((object)new KeyAgreeRecipientInfo(pvData, publicKeyRecipient, index, subIndex)); continue; default: throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Invalid_Originator_Identifier_Choice"), agreeRecipientInfo.dwOriginatorChoice.ToString((IFormatProvider)CultureInfo.CurrentCulture)); } default: throw new CryptographicException(-2147483647); } } else { SafeLocalAllocHandle pvData; uint cbData; PkcsUtils.GetParam(safeCryptMsgHandle, 19U, index, out pvData, out cbData); CAPI.CERT_INFO certInfo = (CAPI.CERT_INFO)Marshal.PtrToStructure(pvData.DangerousGetHandle(), typeof(CAPI.CERT_INFO)); this.m_recipientInfos.Add((object)new KeyTransRecipientInfo(pvData, certInfo, index)); } } this.m_safeCryptMsgHandle = safeCryptMsgHandle; }
public static extern bool CryptQueryObject( CERT_QUERY_OBJECT dwObjectType, [MarshalAs(UnmanagedType.LPWStr)] string pvObject, CERT_QUERY_CONTENT dwExpectedContentTypeFlags, CERT_QUERY_FORMAT dwExpectedFormatTypeFlags, [In] uint dwFlags, out uint pdwMsgAndCertEncodingType, out uint pdwContentType, out uint pdwFormatType, out SafeCertStoreHandle phCertStore, out SafeCryptMsgHandle phMsg, [In, Out] IntPtr ppvContext);
internal static DecryptorPalWindows Decode( byte[] encodedMessage, out int version, out ContentInfo contentInfo, out AlgorithmIdentifier contentEncryptionAlgorithm, out X509Certificate2Collection originatorCerts, out CryptographicAttributeObjectCollection unprotectedAttributes ) { SafeCryptMsgHandle hCryptMsg = Interop.Crypt32.CryptMsgOpenToDecode(MsgEncodingType.All, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (hCryptMsg == null || hCryptMsg.IsInvalid) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } if (!Interop.Crypt32.CryptMsgUpdate(hCryptMsg, encodedMessage, encodedMessage.Length, fFinal: true)) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } CryptMsgType cryptMsgType = hCryptMsg.GetMessageType(); if (cryptMsgType != CryptMsgType.CMSG_ENVELOPED) { throw ErrorCode.CRYPT_E_INVALID_MSG_TYPE.ToCryptographicException(); } version = hCryptMsg.GetVersion(); contentInfo = hCryptMsg.GetContentInfo(); AlgorithmIdentifierAsn contentEncryptionAlgorithmAsn; using (SafeHandle sh = hCryptMsg.GetMsgParamAsMemory(CryptMsgParamType.CMSG_ENVELOPE_ALGORITHM_PARAM)) { unsafe { CRYPT_ALGORITHM_IDENTIFIER *pCryptAlgorithmIdentifier = (CRYPT_ALGORITHM_IDENTIFIER *)(sh.DangerousGetHandle()); contentEncryptionAlgorithm = (*pCryptAlgorithmIdentifier).ToAlgorithmIdentifier(); contentEncryptionAlgorithmAsn.Algorithm = contentEncryptionAlgorithm.Oid; contentEncryptionAlgorithmAsn.Parameters = (*pCryptAlgorithmIdentifier).Parameters.ToByteArray(); } } originatorCerts = hCryptMsg.GetOriginatorCerts(); unprotectedAttributes = hCryptMsg.GetUnprotectedAttributes(); RecipientInfoCollection recipientInfos = CreateRecipientInfos(hCryptMsg); return(new DecryptorPalWindows(hCryptMsg, recipientInfos, contentEncryptionAlgorithmAsn)); }
public static unsafe extern bool CryptQueryObject( CertQueryObjectType dwObjectType, void* pvObject, ExpectedContentTypeFlags dwExpectedContentTypeFlags, ExpectedFormatTypeFlags dwExpectedFormatTypeFlags, int dwFlags, // reserved - always pass 0 out CertEncodingType pdwMsgAndCertEncodingType, out ContentType pdwContentType, out FormatType pdwFormatType, out SafeCertStoreHandle phCertStore, out SafeCryptMsgHandle phMsg, out SafeCertContextHandle ppvContext );
internal static extern bool CryptQueryObject( /* _In_ DWORD */ [In] CertQueryObject dwObjectType, /* _In_ const void* */ [In] IntPtr pvObject, /* _In_ DWORD */ [In] CertQueryContentFlag dwExpectedContentTypeFlags, /* _In_ DWORD */ [In] CertQueryFormatFlag dwExpectedFormatTypeFlags, /* _In_ DWORD */ [In] int dwFlags, /* _Out_opt_ DWORD* */ [Out] out CertEncoding pdwMsgAndCertEncodingType, /* _Out_opt_ DWORD* */ [Out] out CertQueryContent pdwContentType, /* _Out_opt_ DWORD* */ [Out] out CertQueryFormat pdwFormatType, /* _Out_opt_ HCERTSTORE* */ [Out] out SafeCertStoreHandle phCertStore, /* _Out_opt_ HCRYPTMSG* */ [Out] out SafeCryptMsgHandle phMsg, /* _Outptr_opt_result_maybenull_ const void** */ [Out] out SafeCertContextHandle ppvContext );
internal static unsafe partial bool CryptQueryObject( CertQueryObjectType dwObjectType, void* pvObject, ExpectedContentTypeFlags dwExpectedContentTypeFlags, ExpectedFormatTypeFlags dwExpectedFormatTypeFlags, int dwFlags, // reserved - always pass 0 out CertEncodingType pdwMsgAndCertEncodingType, out ContentType pdwContentType, out FormatType pdwFormatType, out SafeCertStoreHandle phCertStore, out SafeCryptMsgHandle phMsg, out SafeCertContextHandle ppvContext );
public sealed override Oid GetEncodedMessageType(byte[] encodedMessage) { using (SafeCryptMsgHandle hCryptMsg = Interop.Crypt32.CryptMsgOpenToDecode(MsgEncodingType.All, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) { if (hCryptMsg == null || hCryptMsg.IsInvalid) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } if (!Interop.Crypt32.CryptMsgUpdate(hCryptMsg, encodedMessage, encodedMessage.Length, fFinal: true)) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } int msgTypeAsInt; int cbSize = sizeof(int); if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, CryptMsgParamType.CMSG_TYPE_PARAM, 0, out msgTypeAsInt, ref cbSize)) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } CryptMsgType msgType = (CryptMsgType)msgTypeAsInt; switch (msgType) { case CryptMsgType.CMSG_DATA: return(Oid.FromOidValue(Oids.Pkcs7Data, OidGroup.ExtensionOrAttribute)); case CryptMsgType.CMSG_SIGNED: return(Oid.FromOidValue(Oids.Pkcs7Signed, OidGroup.ExtensionOrAttribute)); case CryptMsgType.CMSG_ENVELOPED: return(Oid.FromOidValue(Oids.Pkcs7Enveloped, OidGroup.ExtensionOrAttribute)); case CryptMsgType.CMSG_SIGNED_AND_ENVELOPED: return(Oid.FromOidValue(Oids.Pkcs7SignedEnveloped, OidGroup.ExtensionOrAttribute)); case CryptMsgType.CMSG_HASHED: return(Oid.FromOidValue(Oids.Pkcs7Hashed, OidGroup.ExtensionOrAttribute)); case CryptMsgType.CMSG_ENCRYPTED: return(Oid.FromOidValue(Oids.Pkcs7Encrypted, OidGroup.ExtensionOrAttribute)); default: throw ErrorCode.CRYPT_E_INVALID_MSG_TYPE.ToCryptographicException(); } } }
public sealed unsafe override byte[] Encrypt(CmsRecipientCollection recipients, ContentInfo contentInfo, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes) { using (SafeCryptMsgHandle hCryptMsg = EncodeHelpers.CreateCryptMsgHandleToEncode(recipients, contentInfo.ContentType, contentEncryptionAlgorithm, originatorCerts, unprotectedAttributes)) { byte[] encodedContent; if (contentInfo.ContentType.Value.Equals(Oids.Pkcs7Data, StringComparison.OrdinalIgnoreCase)) { encodedContent = PkcsHelpers.EncodeOctetString(contentInfo.Content); } else { encodedContent = contentInfo.Content; if (encodedContent.Length > 0) { // Windows will throw if it encounters indefinite length encoding. // Let's reencode if that is the case ReencodeIfUsingIndefiniteLengthEncodingOnOuterStructure(ref encodedContent); } } if (encodedContent.Length > 0) { // Pin to avoid copy during heap compaction fixed(byte *pinnedContent = encodedContent) { try { if (!Interop.Crypt32.CryptMsgUpdate(hCryptMsg, encodedContent, encodedContent.Length, fFinal: true)) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } } finally { if (!object.ReferenceEquals(encodedContent, contentInfo.Content)) { Array.Clear(encodedContent, 0, encodedContent.Length); } } } } byte[] encodedMessage = hCryptMsg.GetMsgParamAsByteArray(CryptMsgParamType.CMSG_CONTENT_PARAM); return(encodedMessage); } }
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); }
// Used for binary blobs without internal pointers. public static byte[] GetMsgParamAsByteArray(this SafeCryptMsgHandle hCryptMsg, CryptMsgParamType paramType, int index = 0) { int cbData = 0; if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, null, ref cbData)) { throw Interop.CPError.GetLastWin32Error().ToCryptographicException(); } byte[] pvData = new byte[cbData]; if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, pvData, ref cbData)) { throw Interop.CPError.GetLastWin32Error().ToCryptographicException(); } return(pvData.Resize(cbData)); }
// Used for binary blobs with internal pointers. public static SafeHandle GetMsgParamAsMemory(this SafeCryptMsgHandle hCryptMsg, CryptMsgParamType paramType, int index = 0) { int cbData = 0; if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, null, ref cbData)) { throw Interop.CPError.GetLastWin32Error().ToCryptographicException(); } SafeHandle pvData = SafeHeapAllocHandle.Alloc(cbData); if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, pvData.DangerousGetHandle(), ref cbData)) { throw Interop.CPError.GetLastWin32Error().ToCryptographicException(); } return(pvData); }
internal unsafe SignerInfoCollection(SignedCms signedCms) { uint dwSigners = 0; uint cbCount = (uint)Marshal.SizeOf(typeof(uint)); SafeCryptMsgHandle safeCryptMsgHandle = signedCms.GetCryptMsgHandle(); if (!CAPI.CAPISafe.CryptMsgGetParam(safeCryptMsgHandle, CAPI.CMSG_SIGNER_COUNT_PARAM, 0, new IntPtr(&dwSigners), new IntPtr(&cbCount))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } SignerInfo[] signerInfos = new SignerInfo[dwSigners]; for (int index = 0; index < dwSigners; index++) { uint cbCmsgSignerInfo = 0; if (!CAPI.CAPISafe.CryptMsgGetParam(safeCryptMsgHandle, CAPI.CMSG_SIGNER_INFO_PARAM, (uint)index, IntPtr.Zero, new IntPtr(&cbCmsgSignerInfo))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } SafeLocalAllocHandle pbCmsgSignerInfo = CAPI.LocalAlloc(CAPI.LMEM_FIXED, new IntPtr(cbCmsgSignerInfo)); if (!CAPI.CAPISafe.CryptMsgGetParam(safeCryptMsgHandle, CAPI.CMSG_SIGNER_INFO_PARAM, (uint)index, pbCmsgSignerInfo, new IntPtr(&cbCmsgSignerInfo))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } signerInfos[index] = new SignerInfo(signedCms, pbCmsgSignerInfo); } m_signerInfos = signerInfos; }
public static X509Certificate2Collection GetOriginatorCerts(this SafeCryptMsgHandle hCryptMsg) { int numCertificates = 0; int cbNumCertificates = sizeof(int); if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, CryptMsgParamType.CMSG_CERT_COUNT_PARAM, 0, out numCertificates, ref cbNumCertificates)) { throw Interop.CPError.GetLastWin32Error().ToCryptographicException(); } X509Certificate2Collection certs = new X509Certificate2Collection(); for (int index = 0; index < numCertificates; index++) { byte[] encodedCertificate = hCryptMsg.GetMsgParamAsByteArray(CryptMsgParamType.CMSG_CERT_PARAM, index); X509Certificate2 cert = new X509Certificate2(encodedCertificate); certs.Add(cert); } return(certs); }
// Used for binary blobs with internal pointers. public static SafeHandle GetMsgParamAsMemory(this SafeCryptMsgHandle hCryptMsg, CryptMsgParamType paramType, int index = 0) { int cbData = 0; if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, IntPtr.Zero, ref cbData)) { throw Marshal.GetLastPInvokeError().ToCryptographicException(); } SafeHandle pvData = SafeHeapAllocHandle.Alloc(cbData); if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, pvData.DangerousGetHandle(), ref cbData)) { Exception e = Marshal.GetLastPInvokeError().ToCryptographicException(); pvData.Dispose(); throw e; } return(pvData); }
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); } }
/// <summary> /// Returns the inner content of the CMS. /// /// Special case: If the CMS is an enveloped CMS that has been decrypted and the inner content type is Oids.Pkcs7Data, the returned /// content bytes are the decoded octet bytes, rather than the encoding of those bytes. This is a documented convenience behavior of /// CryptMsgGetParam(CMSG_CONTENT_PARAM) that apparently got baked into the behavior of the managed EnvelopedCms class. /// </summary> public static ContentInfo GetContentInfo(this SafeCryptMsgHandle hCryptMsg) { byte[] oidBytes = hCryptMsg.GetMsgParamAsByteArray(CryptMsgParamType.CMSG_INNER_CONTENT_TYPE_PARAM); // Desktop compat: If we get a null or non-terminated string back from Crypt32, throwing an exception seems more apropros but // for the desktop compat, we throw the result at the ASCII Encoder and let the chips fall where they may. int length = oidBytes.Length; if (length > 0 && oidBytes[length - 1] == 0) { length--; } string oidValue = Encoding.ASCII.GetString(oidBytes, 0, length); Oid contentType = new Oid(oidValue); byte[] content = hCryptMsg.GetMsgParamAsByteArray(CryptMsgParamType.CMSG_CONTENT_PARAM); return(new ContentInfo(contentType, content)); }
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; }
// Used for binary blobs without internal pointers. public static unsafe byte[] GetMsgParamAsByteArray(this SafeCryptMsgHandle hCryptMsg, CryptMsgParamType paramType, int index = 0) { int cbData = 0; if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, IntPtr.Zero, ref cbData)) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } byte[] data = new byte[cbData]; fixed(byte *pvData = data) { if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, paramType, index, pvData, ref cbData)) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } } return(data.Resize(cbData)); }
private static RecipientInfoCollection CreateRecipientInfos(SafeCryptMsgHandle hCryptMsg) { int numRecipients; int cbRecipientsCount = sizeof(int); if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, CryptMsgParamType.CMSG_CMS_RECIPIENT_COUNT_PARAM, 0, out numRecipients, ref cbRecipientsCount)) { throw Marshal.GetLastPInvokeError().ToCryptographicException(); } List <RecipientInfo> recipientInfos = new List <RecipientInfo>(numRecipients); for (int index = 0; index < numRecipients; index++) { // Do not dispose this safehandle. The RecipientInfoPal objects we create hold on to these and they get freed through garbage collection. SafeHandle pCmsgCmsRecipientInfoMemory = hCryptMsg.GetMsgParamAsMemory(CryptMsgParamType.CMSG_CMS_RECIPIENT_INFO_PARAM, index); IEnumerable <RecipientInfo> recipientInfosForThisIndex = ToRecipientInfosForThisIndex(pCmsgCmsRecipientInfoMemory, index); recipientInfos.AddRange(recipientInfosForThisIndex); } return(new RecipientInfoCollection(recipientInfos)); }
public static SafeCryptMsgHandle CreateCryptMsgHandleToEncode(CmsRecipientCollection recipients, Oid innerContentType, AlgorithmIdentifier contentEncryptionAlgorithm, X509Certificate2Collection originatorCerts, CryptographicAttributeObjectCollection unprotectedAttributes) { using (HeapBlockRetainer hb = new HeapBlockRetainer()) { // Deep copy the CmsRecipients (and especially their underlying X509Certificate2 objects). This will prevent malicious callers from altering them or disposing them while we're performing // unsafe memory crawling inside them. recipients = recipients.DeepCopy(); // We must keep all the certificates inside recipients alive until the call to CryptMsgOpenToEncode() finishes. The CMSG_ENVELOPED_ENCODE_INFO* structure we passed to it // contains direct pointers to memory owned by the CERT_INFO memory block whose lifetime is that of the certificate. hb.KeepAlive(recipients); unsafe { CMSG_ENVELOPED_ENCODE_INFO *pEnvelopedEncodeInfo = CreateCmsEnvelopedEncodeInfo(recipients, contentEncryptionAlgorithm, originatorCerts, unprotectedAttributes, hb); SafeCryptMsgHandle hCryptMsg = Interop.Crypt32.CryptMsgOpenToEncode(MsgEncodingType.All, 0, CryptMsgType.CMSG_ENVELOPED, pEnvelopedEncodeInfo, innerContentType.Value, IntPtr.Zero); if (hCryptMsg == null || hCryptMsg.IsInvalid) { throw Marshal.GetLastWin32Error().ToCryptographicException(); } return(hCryptMsg); } } }
internal RecipientInfoCollection() { this.m_safeCryptMsgHandle = SafeCryptMsgHandle.InvalidHandle; this.m_recipientInfos = new ArrayList(); }
private NativeCms(SafeCryptMsgHandle handle, bool detached) { _handle = handle; _detached = detached; }
private static SafeCertContextHandle GetSignerInPKCS7Store(SafeCertStoreHandle hCertStore, SafeCryptMsgHandle hCryptMsg) { // make sure that there is at least one signer of the certificate store int dwSigners; int cbSigners = sizeof(int); if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_COUNT_PARAM, 0, out dwSigners, ref cbSigners)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; if (dwSigners == 0) throw ErrorCode.CRYPT_E_SIGNER_NOT_FOUND.ToCryptographicException(); // get the first signer from the store, and use that as the loaded certificate int cbData = 0; if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_INFO_PARAM, 0, null, ref cbData)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; byte[] cmsgSignerBytes = new byte[cbData]; if (!Interop.crypt32.CryptMsgGetParam(hCryptMsg, CryptMessageParameterType.CMSG_SIGNER_INFO_PARAM, 0, cmsgSignerBytes, ref cbData)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; CERT_INFO certInfo = default(CERT_INFO); unsafe { fixed (byte* pCmsgSignerBytes = cmsgSignerBytes) { CMSG_SIGNER_INFO_Partial* pCmsgSignerInfo = (CMSG_SIGNER_INFO_Partial*)pCmsgSignerBytes; certInfo.Issuer.cbData = pCmsgSignerInfo->Issuer.cbData; certInfo.Issuer.pbData = pCmsgSignerInfo->Issuer.pbData; certInfo.SerialNumber.cbData = pCmsgSignerInfo->SerialNumber.cbData; certInfo.SerialNumber.pbData = pCmsgSignerInfo->SerialNumber.pbData; } SafeCertContextHandle pCertContext = null; if (!Interop.crypt32.CertFindCertificateInStore(hCertStore, CertFindType.CERT_FIND_SUBJECT_CERT, &certInfo, ref pCertContext)) throw Marshal.GetHRForLastWin32Error().ToCryptographicException();; return pCertContext; } }
internal RecipientInfoCollection(RecipientInfo recipientInfo) { this.m_safeCryptMsgHandle = SafeCryptMsgHandle.InvalidHandle; this.m_recipientInfos = new ArrayList(1); this.m_recipientInfos.Add((object)recipientInfo); }
internal RecipientInfoCollection(RecipientInfo recipientInfo) { m_safeCryptMsgHandle = SafeCryptMsgHandle.InvalidHandle; m_recipientInfos = new ArrayList(1); m_recipientInfos.Add(recipientInfo); }
public static partial bool CryptMsgGetParam(SafeCryptMsgHandle hCryptMsg, CryptMessageParameterType dwParamType, int dwIndex, out int pvData, ref int pcbData);
internal unsafe RecipientInfoCollection(SafeCryptMsgHandle safeCryptMsgHandle) { bool cmsSupported = PkcsUtils.CmsSupported(); uint dwRecipients = 0; uint cbCount = (uint)Marshal.SizeOf(typeof(uint)); // Use CMS if supported. if (cmsSupported) { // CMS. if (!CAPI.CAPISafe.CryptMsgGetParam(safeCryptMsgHandle, CAPI.CMSG_CMS_RECIPIENT_COUNT_PARAM, 0, new IntPtr(&dwRecipients), new IntPtr(&cbCount))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } else { // PKCS7. if (!CAPI.CAPISafe.CryptMsgGetParam(safeCryptMsgHandle, CAPI.CMSG_RECIPIENT_COUNT_PARAM, 0, new IntPtr(&dwRecipients), new IntPtr(&cbCount))) { throw new CryptographicException(Marshal.GetLastWin32Error()); } } m_recipientInfos = new ArrayList(); for (uint index = 0; index < dwRecipients; index++) { if (cmsSupported) { uint cbCmsRecipientInfo; SafeLocalAllocHandle pbCmsRecipientInfo; PkcsUtils.GetParam(safeCryptMsgHandle, CAPI.CMSG_CMS_RECIPIENT_INFO_PARAM, index, out pbCmsRecipientInfo, out cbCmsRecipientInfo); CAPI.CMSG_CMS_RECIPIENT_INFO cmsRecipientInfo = (CAPI.CMSG_CMS_RECIPIENT_INFO)Marshal.PtrToStructure(pbCmsRecipientInfo.DangerousGetHandle(), typeof(CAPI.CMSG_CMS_RECIPIENT_INFO)); switch (cmsRecipientInfo.dwRecipientChoice) { case CAPI.CMSG_KEY_TRANS_RECIPIENT: CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO keyTrans = (CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO)); m_recipientInfos.Add(new KeyTransRecipientInfo(pbCmsRecipientInfo, keyTrans, index)); break; case CAPI.CMSG_KEY_AGREE_RECIPIENT: CAPI.CMSG_KEY_AGREE_RECIPIENT_INFO keyAgree = (CAPI.CMSG_KEY_AGREE_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_INFO)); switch (keyAgree.dwOriginatorChoice) { case CAPI.CMSG_KEY_AGREE_ORIGINATOR_CERT: CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO certIdRecipient = (CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO)); for (uint cRecipient = 0; cRecipient < certIdRecipient.cRecipientEncryptedKeys; cRecipient++) { m_recipientInfos.Add(new KeyAgreeRecipientInfo(pbCmsRecipientInfo, certIdRecipient, index, cRecipient)); } break; case CAPI.CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY: CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO publicKeyRecipient = (CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO)Marshal.PtrToStructure(cmsRecipientInfo.pRecipientInfo, typeof(CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO)); for (uint cRecipient = 0; cRecipient < publicKeyRecipient.cRecipientEncryptedKeys; cRecipient++) { m_recipientInfos.Add(new KeyAgreeRecipientInfo(pbCmsRecipientInfo, publicKeyRecipient, index, cRecipient)); } break; default: throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Invalid_Originator_Identifier_Choice"), keyAgree.dwOriginatorChoice.ToString(CultureInfo.CurrentCulture)); } break; default: throw new CryptographicException(CAPI.E_NOTIMPL); } } else { uint cbCertInfo; SafeLocalAllocHandle pbCertInfo; PkcsUtils.GetParam(safeCryptMsgHandle, CAPI.CMSG_RECIPIENT_INFO_PARAM, index, out pbCertInfo, out cbCertInfo); CAPI.CERT_INFO certInfo = (CAPI.CERT_INFO)Marshal.PtrToStructure(pbCertInfo.DangerousGetHandle(), typeof(CAPI.CERT_INFO)); m_recipientInfos.Add(new KeyTransRecipientInfo(pbCertInfo, certInfo, index)); } } m_safeCryptMsgHandle = safeCryptMsgHandle; }
internal static extern bool CryptMsgGetParam(SafeCryptMsgHandle hCryptMsg, CryptMsgParamType dwParamType, int dwIndex, IntPtr pvData, [In, Out] ref int pcbData);
public EnvelopedCms(SubjectIdentifierType recipientIdentifierType, ContentInfo contentInfo, AlgorithmIdentifier encryptionAlgorithm) { if (contentInfo == null) throw new ArgumentNullException("contentInfo"); if (contentInfo.Content == null) throw new ArgumentNullException("contentInfo.Content"); if (encryptionAlgorithm == null) throw new ArgumentNullException("encryptionAlgorithm"); this.m_safeCryptMsgHandle = SafeCryptMsgHandle.InvalidHandle; this.m_version = recipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier ? 2 : 0; this.m_recipientIdentifierType = recipientIdentifierType; this.m_contentInfo = contentInfo; this.m_encryptionAlgorithm = encryptionAlgorithm; this.m_encryptionAlgorithm.Parameters = new byte[0]; this.m_certificates = new X509Certificate2Collection(); this.m_unprotectedAttributes = new CryptographicAttributeObjectCollection(); }
private static ICertificatePal FromBlobOrFile(byte[] rawData, string fileName, SafePasswordHandle password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(rawData != null || fileName != null); Debug.Assert(password != null); bool loadFromFile = (fileName != null); PfxCertStoreFlags pfxCertStoreFlags = MapKeyStorageFlags(keyStorageFlags); bool deleteKeyContainer = false; CertEncodingType msgAndCertEncodingType; ContentType contentType; FormatType formatType; SafeCertStoreHandle hCertStore = null; SafeCryptMsgHandle hCryptMsg = null; SafeCertContextHandle pCertContext = null; try { unsafe { fixed(byte *pRawData = rawData) { fixed(char *pFileName = fileName) { CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(loadFromFile ? 0 : rawData.Length, pRawData); CertQueryObjectType objectType = loadFromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB; void *pvObject = loadFromFile ? (void *)pFileName : (void *)&certBlob; bool success = Interop.crypt32.CryptQueryObject( objectType, pvObject, X509ExpectedContentTypeFlags, X509ExpectedFormatTypeFlags, 0, out msgAndCertEncodingType, out contentType, out formatType, out hCertStore, out hCryptMsg, out pCertContext ); if (!success) { int hr = Interop.CPError.GetHRForLastWin32Error(); throw hr.ToCryptographicException(); } } } if (contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED || contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) { pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg); } else if (contentType == ContentType.CERT_QUERY_CONTENT_PFX) { if (loadFromFile) { rawData = File.ReadAllBytes(fileName); } pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags); // If PersistKeySet is set we don't delete the key, so that it persists. // If EphemeralKeySet is set we don't delete the key, because there's no file, so it's a wasteful call. const X509KeyStorageFlags DeleteUnless = X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.EphemeralKeySet | // begin: gost X509KeyStorageFlags.CspNoPersistKeySet; // end gost deleteKeyContainer = ((keyStorageFlags & DeleteUnless) == 0); } CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer); pCertContext = null; return(pal); } } finally { if (hCertStore != null) { hCertStore.Dispose(); } if (hCryptMsg != null) { hCryptMsg.Dispose(); } if (pCertContext != null) { pCertContext.Dispose(); } } }
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); }
public void Decode(byte[] encodedMessage) { if (encodedMessage == null) throw new ArgumentNullException("encodedMessage"); if (this.m_safeCryptMsgHandle != null && !this.m_safeCryptMsgHandle.IsInvalid) this.m_safeCryptMsgHandle.Dispose(); this.m_safeCryptMsgHandle = SignedCms.OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); if (this.Detached) return; this.m_contentInfo = new ContentInfo(PkcsUtils.GetContentType(this.m_safeCryptMsgHandle), PkcsUtils.GetContent(this.m_safeCryptMsgHandle)); }
private unsafe void Sign(CmsSigner signer, bool silent) { 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 = (byte[])null; try { SafeLocalAllocHandle localAllocHandle = CAPI.LocalAlloc(0U, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)))); try { Marshal.StructureToPtr((object)signerEncodeInfo, localAllocHandle.DangerousGetHandle(), false); X509Certificate2Collection bagOfCertificates = PkcsUtils.CreateBagOfCertificates(signer); SafeLocalAllocHandle encodedCertBlob = PkcsUtils.CreateEncodedCertBlob(bagOfCertificates); signedEncodeInfo.cSigners = 1U; signedEncodeInfo.rgSigners = localAllocHandle.DangerousGetHandle(); signedEncodeInfo.cCertEncoded = (uint)bagOfCertificates.Count; if (bagOfCertificates.Count > 0) signedEncodeInfo.rgCertEncoded = encodedCertBlob.DangerousGetHandle(); SafeCryptMsgHandle safeCryptMsgHandle = string.Compare(this.ContentInfo.ContentType.Value, "1.2.840.113549.1.7.1", StringComparison.OrdinalIgnoreCase) != 0 ? CAPI.CryptMsgOpenToEncode(65537U, this.Detached ? 4U : 0U, 2U, new IntPtr((void*)&signedEncodeInfo), this.ContentInfo.ContentType.Value, IntPtr.Zero) : CAPI.CryptMsgOpenToEncode(65537U, this.Detached ? 4U : 0U, 2U, new IntPtr((void*)&signedEncodeInfo), IntPtr.Zero, IntPtr.Zero); if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); if (this.ContentInfo.Content.Length > 0 && !CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, this.ContentInfo.pContent, (uint)this.ContentInfo.Content.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); encodedMessage = PkcsUtils.GetContent(safeCryptMsgHandle); safeCryptMsgHandle.Dispose(); encodedCertBlob.Dispose(); } finally { Marshal.DestroyStructure(localAllocHandle.DangerousGetHandle(), typeof(CAPI.CMSG_SIGNER_ENCODE_INFO)); localAllocHandle.Dispose(); } } finally { signerEncodeInfo.Dispose(); } SafeCryptMsgHandle safeCryptMsgHandle1 = SignedCms.OpenToDecode(encodedMessage, this.ContentInfo, this.Detached); if (this.m_safeCryptMsgHandle != null && !this.m_safeCryptMsgHandle.IsInvalid) this.m_safeCryptMsgHandle.Dispose(); this.m_safeCryptMsgHandle = safeCryptMsgHandle1; GC.KeepAlive((object)signer); }
internal void ReopenToDecode() { byte[] message = PkcsUtils.GetMessage(this.m_safeCryptMsgHandle); if (this.m_safeCryptMsgHandle != null && !this.m_safeCryptMsgHandle.IsInvalid) this.m_safeCryptMsgHandle.Dispose(); this.m_safeCryptMsgHandle = SignedCms.OpenToDecode(message, this.ContentInfo, this.Detached); }
public NativeCms(IntPtr handle) { _handle = new SafeCryptMsgHandle(handle, ownsHandle: false); }
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); } }
private static ICertificatePal FromBlobOrFile(byte[] rawData, String fileName, String password, X509KeyStorageFlags keyStorageFlags) { Debug.Assert(rawData != null || fileName != null); bool loadFromFile = (fileName != null); PfxCertStoreFlags pfxCertStoreFlags = MapKeyStorageFlags(keyStorageFlags); bool persistKeySet = (0 != (keyStorageFlags & X509KeyStorageFlags.PersistKeySet)); CertEncodingType msgAndCertEncodingType; ContentType contentType; FormatType formatType; SafeCertStoreHandle hCertStore = null; SafeCryptMsgHandle hCryptMsg = null; SafeCertContextHandle pCertContext = null; try { unsafe { fixed(byte *pRawData = rawData) { fixed(char *pFileName = fileName) { CRYPTOAPI_BLOB certBlob = new CRYPTOAPI_BLOB(loadFromFile ? 0 : rawData.Length, pRawData); CertQueryObjectType objectType = loadFromFile ? CertQueryObjectType.CERT_QUERY_OBJECT_FILE : CertQueryObjectType.CERT_QUERY_OBJECT_BLOB; void *pvObject = loadFromFile ? (void *)pFileName : (void *)&certBlob; bool success = Interop.crypt32.CryptQueryObject( objectType, pvObject, X509ExpectedContentTypeFlags, X509ExpectedFormatTypeFlags, 0, out msgAndCertEncodingType, out contentType, out formatType, out hCertStore, out hCryptMsg, out pCertContext ); if (!success) { int hr = Marshal.GetHRForLastWin32Error(); throw hr.ToCryptographicException(); } } } if (contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED || contentType == ContentType.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED) { pCertContext = GetSignerInPKCS7Store(hCertStore, hCryptMsg); } else if (contentType == ContentType.CERT_QUERY_CONTENT_PFX) { if (loadFromFile) { rawData = File.ReadAllBytes(fileName); } pCertContext = FilterPFXStore(rawData, password, pfxCertStoreFlags); } CertificatePal pal = new CertificatePal(pCertContext, deleteKeyContainer: !persistKeySet); pCertContext = null; return(pal); } } finally { if (hCertStore != null) { hCertStore.Dispose(); } if (hCryptMsg != null) { hCryptMsg.Dispose(); } if (pCertContext != null) { pCertContext.Dispose(); } } }
public static Oid GetContentType(byte[] encodedMessage) { if (encodedMessage == null) { throw new ArgumentNullException("encodedMessage"); } SafeCryptMsgHandle safeCryptMsgHandle = CAPI.CAPISafe.CryptMsgOpenToDecode( CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if (!CAPI.CAPISafe.CryptMsgUpdate(safeCryptMsgHandle, encodedMessage, (uint)encodedMessage.Length, true)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } Oid contentType; switch (PkcsUtils.GetMessageType(safeCryptMsgHandle)) { case CAPI.CMSG_DATA: contentType = Oid.FromOidValue(CAPI.szOID_RSA_data, OidGroup.ExtensionOrAttribute); break; case CAPI.CMSG_SIGNED: contentType = Oid.FromOidValue(CAPI.szOID_RSA_signedData, OidGroup.ExtensionOrAttribute); break; case CAPI.CMSG_ENVELOPED: contentType = Oid.FromOidValue(CAPI.szOID_RSA_envelopedData, OidGroup.ExtensionOrAttribute); break; case CAPI.CMSG_SIGNED_AND_ENVELOPED: contentType = Oid.FromOidValue(CAPI.szOID_RSA_signEnvData, OidGroup.ExtensionOrAttribute); break; case CAPI.CMSG_HASHED: contentType = Oid.FromOidValue(CAPI.szOID_RSA_hashedData, OidGroup.ExtensionOrAttribute); break; case CAPI.CMSG_ENCRYPTED: contentType = Oid.FromOidValue(CAPI.szOID_RSA_encryptedData, OidGroup.ExtensionOrAttribute); break; default: throw new CryptographicException(CAPI.CRYPT_E_INVALID_MSG_TYPE); } safeCryptMsgHandle.Dispose(); return(contentType); }
public static extern bool CryptMsgGetParam(SafeCryptMsgHandle hCryptMsg, CryptMessageParameterType dwParamType, int dwIndex, out int pvData, [In, Out] ref int pcbData);
internal static partial bool CryptMsgControl( SafeCryptMsgHandle hCryptMsg, int dwFlags, MsgControlType dwCtrlType, ref CMSG_CTRL_KEY_AGREE_DECRYPT_PARA pvCtrlPara);
private unsafe void EncryptContent(CmsRecipientCollection recipients) { EnvelopedCms.CMSG_ENCRYPT_PARAM encryptParam = new EnvelopedCms.CMSG_ENCRYPT_PARAM(); if (recipients.Count < 1) throw new CryptographicException(-2146889717); foreach (CmsRecipient cmsRecipient in recipients) { if (cmsRecipient.Certificate == null) throw new ArgumentNullException(SecurityResources.GetResourceString("Cryptography_Cms_RecipientCertificateNotFound")); if (PkcsUtils.GetRecipientInfoType(cmsRecipient.Certificate) == RecipientInfoType.KeyAgreement || cmsRecipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier) encryptParam.useCms = true; } if (!encryptParam.useCms && (this.Certificates.Count > 0 || this.UnprotectedAttributes.Count > 0)) encryptParam.useCms = true; if (encryptParam.useCms && !PkcsUtils.CmsSupported()) throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Cms_Not_Supported")); CAPI.CMSG_ENVELOPED_ENCODE_INFO envelopedEncodeInfo = new CAPI.CMSG_ENVELOPED_ENCODE_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO))); SafeLocalAllocHandle localAllocHandle = CAPI.LocalAlloc(64U, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO)))); EnvelopedCms.SetCspParams(this.ContentEncryptionAlgorithm, ref encryptParam); envelopedEncodeInfo.ContentEncryptionAlgorithm.pszObjId = this.ContentEncryptionAlgorithm.Oid.Value; if (encryptParam.pvEncryptionAuxInfo != null && !encryptParam.pvEncryptionAuxInfo.IsInvalid) envelopedEncodeInfo.pvEncryptionAuxInfo = encryptParam.pvEncryptionAuxInfo.DangerousGetHandle(); envelopedEncodeInfo.cRecipients = (uint)recipients.Count; if (encryptParam.useCms) { EnvelopedCms.SetCmsRecipientParams(recipients, this.Certificates, this.UnprotectedAttributes, this.ContentEncryptionAlgorithm, ref encryptParam); envelopedEncodeInfo.rgCmsRecipients = encryptParam.rgpRecipients.DangerousGetHandle(); if (encryptParam.rgCertEncoded != null && !encryptParam.rgCertEncoded.IsInvalid) { envelopedEncodeInfo.cCertEncoded = (uint)this.Certificates.Count; envelopedEncodeInfo.rgCertEncoded = encryptParam.rgCertEncoded.DangerousGetHandle(); } if (encryptParam.rgUnprotectedAttr != null && !encryptParam.rgUnprotectedAttr.IsInvalid) { envelopedEncodeInfo.cUnprotectedAttr = (uint)this.UnprotectedAttributes.Count; envelopedEncodeInfo.rgUnprotectedAttr = encryptParam.rgUnprotectedAttr.DangerousGetHandle(); } } else { EnvelopedCms.SetPkcs7RecipientParams(recipients, ref encryptParam); envelopedEncodeInfo.rgpRecipients = encryptParam.rgpRecipients.DangerousGetHandle(); } Marshal.StructureToPtr((object)envelopedEncodeInfo, localAllocHandle.DangerousGetHandle(), false); try { SafeCryptMsgHandle safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(65537U, 0U, 3U, localAllocHandle.DangerousGetHandle(), this.ContentInfo.ContentType.Value, IntPtr.Zero); if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid) throw new CryptographicException(Marshal.GetLastWin32Error()); if (this.m_safeCryptMsgHandle != null && !this.m_safeCryptMsgHandle.IsInvalid) this.m_safeCryptMsgHandle.Dispose(); this.m_safeCryptMsgHandle = safeCryptMsgHandle; } finally { Marshal.DestroyStructure(localAllocHandle.DangerousGetHandle(), typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO)); localAllocHandle.Dispose(); } byte[] encodedData = new byte[0]; if (string.Compare(this.ContentInfo.ContentType.Value, "1.2.840.113549.1.7.1", StringComparison.OrdinalIgnoreCase) == 0) { byte[] content = this.ContentInfo.Content; fixed (byte* numPtr = content) { if (!CAPI.EncodeObject(new IntPtr(25L), new IntPtr((void*)&new CAPI.CRYPTOAPI_BLOB() { cbData = (uint)content.Length, pbData = new IntPtr((void*)numPtr) }), out encodedData)) throw new CryptographicException(Marshal.GetLastWin32Error()); } } else encodedData = this.ContentInfo.Content; if (encodedData.Length > 0 && !CAPI.CAPISafe.CryptMsgUpdate(this.m_safeCryptMsgHandle, encodedData, (uint)encodedData.Length, true)) throw new CryptographicException(Marshal.GetLastWin32Error()); GC.KeepAlive((object)encryptParam); GC.KeepAlive((object)recipients); }
private DecryptorPalWindows(SafeCryptMsgHandle hCryptMsg, RecipientInfoCollection recipientInfos) : base(recipientInfos) { _hCryptMsg = hCryptMsg; }
public void Decode(byte[] encodedMessage) { if (encodedMessage == null) throw new ArgumentNullException("encodedMessage"); if (this.m_safeCryptMsgHandle != null && !this.m_safeCryptMsgHandle.IsInvalid) this.m_safeCryptMsgHandle.Dispose(); this.m_safeCryptMsgHandle = EnvelopedCms.OpenToDecode(encodedMessage); this.m_version = (int)PkcsUtils.GetVersion(this.m_safeCryptMsgHandle); this.m_contentInfo = new ContentInfo(PkcsUtils.GetContentType(this.m_safeCryptMsgHandle), PkcsUtils.GetContent(this.m_safeCryptMsgHandle)); this.m_encryptionAlgorithm = PkcsUtils.GetAlgorithmIdentifier(this.m_safeCryptMsgHandle); this.m_certificates = PkcsUtils.GetCertificates(this.m_safeCryptMsgHandle); this.m_unprotectedAttributes = PkcsUtils.GetUnprotectedAttributes(this.m_safeCryptMsgHandle); }
public static CryptographicAttributeObjectCollection GetUnprotectedAttributes(this SafeCryptMsgHandle hCryptMsg) { // For some reason, you can't ask how many attributes there are - you have to ask for the attributes and // get a CRYPT_E_ATTRIBUTES_MISSING failure if the count is 0. int cbUnprotectedAttr = 0; if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, CryptMsgParamType.CMSG_UNPROTECTED_ATTR_PARAM, 0, null, ref cbUnprotectedAttr)) { int lastError = Interop.CPError.GetLastWin32Error(); if (lastError == (int)ErrorCode.CRYPT_E_ATTRIBUTES_MISSING) { return(new CryptographicAttributeObjectCollection()); } throw lastError.ToCryptographicException(); } using (SafeHandle sh = hCryptMsg.GetMsgParamAsMemory(CryptMsgParamType.CMSG_UNPROTECTED_ATTR_PARAM)) { unsafe { CRYPT_ATTRIBUTES *pCryptAttributes = (CRYPT_ATTRIBUTES *)(sh.DangerousGetHandle()); return(ToCryptographicAttributeObjectCollection(pCryptAttributes)); } } }
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); }
private static unsafe SafeCertContextHandle GetSignerInPKCS7Store(SafeCertStoreHandle hCertStore, SafeCryptMsgHandle hCryptMsg) { // make sure that there is at least one signer of the certificate store int dwSigners; int cbSigners = sizeof(int); if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, Interop.Crypt32.CryptMsgParamType.CMSG_SIGNER_COUNT_PARAM, 0, out dwSigners, ref cbSigners)) { throw Marshal.GetHRForLastWin32Error().ToCryptographicException(); } if (dwSigners == 0) { throw ErrorCode.CRYPT_E_SIGNER_NOT_FOUND.ToCryptographicException(); } // get the first signer from the store, and use that as the loaded certificate int cbData = 0; if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, Interop.Crypt32.CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, default(byte *), ref cbData)) { throw Marshal.GetHRForLastWin32Error().ToCryptographicException(); fixed(byte *pCmsgSignerBytes = new byte[cbData]) { if (!Interop.Crypt32.CryptMsgGetParam(hCryptMsg, Interop.Crypt32.CryptMsgParamType.CMSG_SIGNER_INFO_PARAM, 0, pCmsgSignerBytes, ref cbData)) { throw Marshal.GetHRForLastWin32Error().ToCryptographicException(); } CMSG_SIGNER_INFO_Partial *pCmsgSignerInfo = (CMSG_SIGNER_INFO_Partial *)pCmsgSignerBytes; Interop.Crypt32.CERT_INFO certInfo = default(Interop.Crypt32.CERT_INFO); certInfo.Issuer.cbData = pCmsgSignerInfo->Issuer.cbData; certInfo.Issuer.pbData = pCmsgSignerInfo->Issuer.pbData; certInfo.SerialNumber.cbData = pCmsgSignerInfo->SerialNumber.cbData; certInfo.SerialNumber.pbData = pCmsgSignerInfo->SerialNumber.pbData; SafeCertContextHandle?pCertContext = null; if (!Interop.crypt32.CertFindCertificateInStore(hCertStore, Interop.Crypt32.CertFindType.CERT_FIND_SUBJECT_CERT, &certInfo, ref pCertContext)) { throw Marshal.GetHRForLastWin32Error().ToCryptographicException(); } return(pCertContext); } }
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))); SafeCryptProvHandle safeCryptProvHandle; CAPI.CMSG_SIGNER_ENCODE_INFO signerEncodeInfo = PkcsUtils.CreateSignerEncodeInfo(signer, silent, out safeCryptProvHandle); 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(); safeCryptProvHandle.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); }