private static unsafe int GetCspParams(RecipientInfo recipientInfo, X509Certificate2Collection extraStore, ref CMSG_DECRYPT_PARAM cmsgDecryptParam) { int num = -2146889717; System.Security.Cryptography.SafeCertContextHandle invalidHandle = System.Security.Cryptography.SafeCertContextHandle.InvalidHandle; System.Security.Cryptography.SafeCertStoreHandle hCertStore = BuildDecryptorStore(extraStore); switch (recipientInfo.Type) { case RecipientInfoType.KeyTransport: if (recipientInfo.SubType != RecipientSubType.Pkcs7KeyTransport) { System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO cmsgRecipientInfo = (System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO) recipientInfo.CmsgRecipientInfo; invalidHandle = System.Security.Cryptography.CAPI.CertFindCertificateInStore(hCertStore, 0x10001, 0, 0x100000, new IntPtr((void*) &cmsgRecipientInfo.RecipientId), System.Security.Cryptography.SafeCertContextHandle.InvalidHandle); break; } invalidHandle = System.Security.Cryptography.CAPI.CertFindCertificateInStore(hCertStore, 0x10001, 0, 0xb0000, recipientInfo.pCmsgRecipientInfo.DangerousGetHandle(), System.Security.Cryptography.SafeCertContextHandle.InvalidHandle); break; case RecipientInfoType.KeyAgreement: { KeyAgreeRecipientInfo info = (KeyAgreeRecipientInfo) recipientInfo; System.Security.Cryptography.CAPI.CERT_ID recipientId = info.RecipientId; invalidHandle = System.Security.Cryptography.CAPI.CertFindCertificateInStore(hCertStore, 0x10001, 0, 0x100000, new IntPtr((void*) &recipientId), System.Security.Cryptography.SafeCertContextHandle.InvalidHandle); break; } default: num = -2147483647; break; } if ((invalidHandle == null) || invalidHandle.IsInvalid) { return num; } System.Security.Cryptography.SafeCryptProvHandle hCryptProv = System.Security.Cryptography.SafeCryptProvHandle.InvalidHandle; uint pdwKeySpec = 0; bool pfCallerFreeProv = false; CspParameters parameters = new CspParameters(); if (!System.Security.Cryptography.X509Certificates.X509Utils.GetPrivateKeyInfo(invalidHandle, ref parameters)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } if ((string.Compare(parameters.ProviderName, "Microsoft Base Cryptographic Provider v1.0", StringComparison.OrdinalIgnoreCase) == 0) && (System.Security.Cryptography.CAPI.CryptAcquireContext(ref hCryptProv, parameters.KeyContainerName, "Microsoft Enhanced Cryptographic Provider v1.0", 1, 0) || System.Security.Cryptography.CAPI.CryptAcquireContext(ref hCryptProv, parameters.KeyContainerName, "Microsoft Strong Cryptographic Provider", 1, 0))) { cmsgDecryptParam.safeCryptProvHandle = hCryptProv; } cmsgDecryptParam.safeCertContextHandle = invalidHandle; cmsgDecryptParam.keySpec = (uint) parameters.KeyNumber; num = 0; if ((hCryptProv != null) && !hCryptProv.IsInvalid) { return num; } if (System.Security.Cryptography.CAPI.CAPISafe.CryptAcquireCertificatePrivateKey(invalidHandle, 6, IntPtr.Zero, ref hCryptProv, ref pdwKeySpec, ref pfCallerFreeProv)) { if (!pfCallerFreeProv) { GC.SuppressFinalize(hCryptProv); } cmsgDecryptParam.safeCryptProvHandle = hCryptProv; return num; } return Marshal.GetHRForLastWin32Error(); }
private unsafe static int /* HRESULT */ GetCspParams (RecipientInfo recipientInfo, X509Certificate2Collection extraStore, ref CMSG_DECRYPT_PARAM cmsgDecryptParam) { int hr = CAPI.CRYPT_E_RECIPIENT_NOT_FOUND; SafeCertContextHandle safeCertContextHandle = SafeCertContextHandle.InvalidHandle; SafeCertStoreHandle safeCertStoreHandle = BuildDecryptorStore(extraStore); switch (recipientInfo.Type) { case RecipientInfoType.KeyTransport: if (recipientInfo.SubType == RecipientSubType.Pkcs7KeyTransport) { safeCertContextHandle = CAPI.CertFindCertificateInStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, CAPI.CERT_FIND_SUBJECT_CERT, recipientInfo.pCmsgRecipientInfo.DangerousGetHandle(), SafeCertContextHandle.InvalidHandle); } else { CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO keyTrans = (CAPI.CMSG_KEY_TRANS_RECIPIENT_INFO) recipientInfo.CmsgRecipientInfo; safeCertContextHandle = CAPI.CertFindCertificateInStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, CAPI.CERT_FIND_CERT_ID, new IntPtr((byte *) &keyTrans.RecipientId), SafeCertContextHandle.InvalidHandle); } break; case RecipientInfoType.KeyAgreement: KeyAgreeRecipientInfo keyAgree = (KeyAgreeRecipientInfo) recipientInfo; CAPI.CERT_ID recipientId = keyAgree.RecipientId; safeCertContextHandle = CAPI.CertFindCertificateInStore(safeCertStoreHandle, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, CAPI.CERT_FIND_CERT_ID, new IntPtr(&recipientId), SafeCertContextHandle.InvalidHandle); break; default: // Others not supported. hr = CAPI.E_NOTIMPL; break; } // Acquire CSP if the recipient's cert is found. if (safeCertContextHandle != null && !safeCertContextHandle.IsInvalid) { SafeCryptProvHandle safeCryptProvHandle = SafeCryptProvHandle.InvalidHandle; uint keySpec = 0; bool freeCsp = false; // Check to see if KEY_PROV_INFO contains "MS Base ..." // If so, acquire "MS Enhanced..." or "MS Strong". // if failed, then use CryptAcquireCertificatePrivateKey CspParameters parameters = new CspParameters(); if (X509Utils.GetPrivateKeyInfo(safeCertContextHandle, ref parameters) == false) throw new CryptographicException(Marshal.GetLastWin32Error()); if (String.Compare(parameters.ProviderName, CAPI.MS_DEF_PROV, StringComparison.OrdinalIgnoreCase) == 0) { if (CAPI.CryptAcquireContext(ref safeCryptProvHandle, parameters.KeyContainerName, CAPI.MS_ENHANCED_PROV, CAPI.PROV_RSA_FULL, 0) || CAPI.CryptAcquireContext(ref safeCryptProvHandle, parameters.KeyContainerName, CAPI.MS_STRONG_PROV, CAPI.PROV_RSA_FULL, 0)) { cmsgDecryptParam.safeCryptProvHandle = safeCryptProvHandle; } } cmsgDecryptParam.safeCertContextHandle = safeCertContextHandle; cmsgDecryptParam.keySpec = (uint)parameters.KeyNumber; hr = CAPI.S_OK; if ((safeCryptProvHandle == null) || (safeCryptProvHandle.IsInvalid)) { if (CAPI.CAPISafe.CryptAcquireCertificatePrivateKey(safeCertContextHandle, CAPI.CRYPT_ACQUIRE_COMPARE_KEY_FLAG | CAPI.CRYPT_ACQUIRE_USE_PROV_INFO_FLAG, IntPtr.Zero, ref safeCryptProvHandle, ref keySpec, ref freeCsp)) { if (!freeCsp) { GC.SuppressFinalize(safeCryptProvHandle); } cmsgDecryptParam.safeCryptProvHandle = safeCryptProvHandle; } else { hr = Marshal.GetHRForLastWin32Error(); } } } return hr; }
private unsafe void DecryptContent(RecipientInfoCollection recipientInfos, X509Certificate2Collection extraStore) { int hr = -2146889717; if ((this.m_safeCryptMsgHandle == null) || this.m_safeCryptMsgHandle.IsInvalid) { throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_NoEncryptedMessageToEncode")); } for (int i = 0; i < recipientInfos.Count; i++) { System.Security.Cryptography.SafeCertContextHandle invalidHandle; KeyAgreeRecipientInfo info2; System.Security.Cryptography.CAPI.CMSG_CTRL_KEY_AGREE_DECRYPT_PARA cmsg_ctrl_key_agree_decrypt_para; System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO cmsg_key_agree_public_key_recipient_info; RecipientInfo recipientInfo = recipientInfos[i]; CMSG_DECRYPT_PARAM cmsgDecryptParam = new CMSG_DECRYPT_PARAM(); int num3 = GetCspParams(recipientInfo, extraStore, ref cmsgDecryptParam); if (num3 != 0) { goto Label_02F1; } CspParameters parameters = new CspParameters(); if (!System.Security.Cryptography.X509Certificates.X509Utils.GetPrivateKeyInfo(cmsgDecryptParam.safeCertContextHandle, ref parameters)) { throw new CryptographicException(Marshal.GetLastWin32Error()); } KeyContainerPermission permission = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry accessEntry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Decrypt | KeyContainerPermissionFlags.Open); permission.AccessEntries.Add(accessEntry); permission.Demand(); switch (recipientInfo.Type) { case RecipientInfoType.KeyTransport: { System.Security.Cryptography.CAPI.CMSG_CTRL_DECRYPT_PARA cmsg_ctrl_decrypt_para = new System.Security.Cryptography.CAPI.CMSG_CTRL_DECRYPT_PARA(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_CTRL_DECRYPT_PARA))) { hCryptProv = cmsgDecryptParam.safeCryptProvHandle.DangerousGetHandle(), dwKeySpec = cmsgDecryptParam.keySpec, dwRecipientIndex = recipientInfo.Index }; if (!System.Security.Cryptography.CAPI.CryptMsgControl(this.m_safeCryptMsgHandle, 0, 2, new IntPtr((void*) &cmsg_ctrl_decrypt_para))) { num3 = Marshal.GetHRForLastWin32Error(); } GC.KeepAlive(cmsg_ctrl_decrypt_para); goto Label_02E6; } case RecipientInfoType.KeyAgreement: { invalidHandle = System.Security.Cryptography.SafeCertContextHandle.InvalidHandle; info2 = (KeyAgreeRecipientInfo) recipientInfo; System.Security.Cryptography.CAPI.CMSG_CMS_RECIPIENT_INFO cmsg_cms_recipient_info = (System.Security.Cryptography.CAPI.CMSG_CMS_RECIPIENT_INFO) Marshal.PtrToStructure(info2.pCmsgRecipientInfo.DangerousGetHandle(), typeof(System.Security.Cryptography.CAPI.CMSG_CMS_RECIPIENT_INFO)); cmsg_ctrl_key_agree_decrypt_para = new System.Security.Cryptography.CAPI.CMSG_CTRL_KEY_AGREE_DECRYPT_PARA(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_CTRL_KEY_AGREE_DECRYPT_PARA))) { hCryptProv = cmsgDecryptParam.safeCryptProvHandle.DangerousGetHandle(), dwKeySpec = cmsgDecryptParam.keySpec, pKeyAgree = cmsg_cms_recipient_info.pRecipientInfo, dwRecipientIndex = info2.Index, dwRecipientEncryptedKeyIndex = info2.SubIndex }; if (info2.SubType != RecipientSubType.CertIdKeyAgreement) { goto Label_0286; } System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO cmsgRecipientInfo = (System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO) info2.CmsgRecipientInfo; invalidHandle = System.Security.Cryptography.CAPI.CertFindCertificateInStore(BuildOriginatorStore(this.Certificates, extraStore), 0x10001, 0, 0x100000, new IntPtr((void*) &cmsgRecipientInfo.OriginatorCertId), System.Security.Cryptography.SafeCertContextHandle.InvalidHandle); if ((invalidHandle != null) && !invalidHandle.IsInvalid) { break; } num3 = -2146885628; goto Label_02E6; } default: throw new CryptographicException(-2147483647); } System.Security.Cryptography.CAPI.CERT_CONTEXT cert_context = (System.Security.Cryptography.CAPI.CERT_CONTEXT) Marshal.PtrToStructure(invalidHandle.DangerousGetHandle(), typeof(System.Security.Cryptography.CAPI.CERT_CONTEXT)); System.Security.Cryptography.CAPI.CERT_INFO cert_info = (System.Security.Cryptography.CAPI.CERT_INFO) Marshal.PtrToStructure(cert_context.pCertInfo, typeof(System.Security.Cryptography.CAPI.CERT_INFO)); cmsg_ctrl_key_agree_decrypt_para.OriginatorPublicKey = cert_info.SubjectPublicKeyInfo.PublicKey; goto Label_02A7; Label_0286: cmsg_key_agree_public_key_recipient_info = (System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO) info2.CmsgRecipientInfo; cmsg_ctrl_key_agree_decrypt_para.OriginatorPublicKey = cmsg_key_agree_public_key_recipient_info.OriginatorPublicKeyInfo.PublicKey; Label_02A7: if (!System.Security.Cryptography.CAPI.CryptMsgControl(this.m_safeCryptMsgHandle, 0, 0x11, new IntPtr((void*) &cmsg_ctrl_key_agree_decrypt_para))) { num3 = Marshal.GetHRForLastWin32Error(); } GC.KeepAlive(cmsg_ctrl_key_agree_decrypt_para); GC.KeepAlive(invalidHandle); Label_02E6: GC.KeepAlive(cmsgDecryptParam); Label_02F1: if (num3 == 0) { uint cbData = 0; System.Security.Cryptography.SafeLocalAllocHandle pvData = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle; PkcsUtils.GetParam(this.m_safeCryptMsgHandle, 2, 0, out pvData, out cbData); if (cbData > 0) { Oid contentType = PkcsUtils.GetContentType(this.m_safeCryptMsgHandle); byte[] destination = new byte[cbData]; Marshal.Copy(pvData.DangerousGetHandle(), destination, 0, (int) cbData); this.m_contentInfo = new System.Security.Cryptography.Pkcs.ContentInfo(contentType, destination); } pvData.Dispose(); hr = 0; break; } hr = num3; } if (hr != 0) { throw new CryptographicException(hr); } }
private unsafe void DecryptContent (RecipientInfoCollection recipientInfos, X509Certificate2Collection extraStore) { int hr = CAPI.CRYPT_E_RECIPIENT_NOT_FOUND; if (m_safeCryptMsgHandle == null || m_safeCryptMsgHandle.IsInvalid) throw new InvalidOperationException(SecurityResources.GetResourceString("Cryptography_Cms_NoEncryptedMessageToEncode")); for (int index = 0; index < recipientInfos.Count; index++) { RecipientInfo recipientInfo = recipientInfos[index]; CMSG_DECRYPT_PARAM cmsgDecryptParam = new CMSG_DECRYPT_PARAM(); // Get CSP parameters int hr2 = GetCspParams(recipientInfo, extraStore, ref cmsgDecryptParam); if (hr2 == CAPI.S_OK) { // CspParameters parameters = new CspParameters(); if (X509Utils.GetPrivateKeyInfo(cmsgDecryptParam.safeCertContextHandle, ref parameters) == false) throw new CryptographicException(Marshal.GetLastWin32Error()); KeyContainerPermission kp = new KeyContainerPermission(KeyContainerPermissionFlags.NoFlags); KeyContainerPermissionAccessEntry entry = new KeyContainerPermissionAccessEntry(parameters, KeyContainerPermissionFlags.Open | KeyContainerPermissionFlags.Decrypt); kp.AccessEntries.Add(entry); kp.Demand(); // Decrypt the content. switch (recipientInfo.Type) { case RecipientInfoType.KeyTransport: CAPI.CMSG_CTRL_DECRYPT_PARA ctrlDecryptPara = new CAPI.CMSG_CTRL_DECRYPT_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_DECRYPT_PARA))); ctrlDecryptPara.hCryptProv = cmsgDecryptParam.safeCryptProvHandle.DangerousGetHandle(); ctrlDecryptPara.dwKeySpec = cmsgDecryptParam.keySpec; ctrlDecryptPara.dwRecipientIndex = (uint) recipientInfo.Index; if (!CAPI.CryptMsgControl(m_safeCryptMsgHandle, 0, CAPI.CMSG_CTRL_DECRYPT, new IntPtr(&ctrlDecryptPara))) hr2 = Marshal.GetHRForLastWin32Error(); GC.KeepAlive(ctrlDecryptPara); break; case RecipientInfoType.KeyAgreement: SafeCertContextHandle pOriginatorCert = SafeCertContextHandle.InvalidHandle; KeyAgreeRecipientInfo keyAgree = (KeyAgreeRecipientInfo) recipientInfo; CAPI.CMSG_CMS_RECIPIENT_INFO cmsRecipientInfo = (CAPI.CMSG_CMS_RECIPIENT_INFO) Marshal.PtrToStructure(keyAgree.pCmsgRecipientInfo.DangerousGetHandle(), typeof(CAPI.CMSG_CMS_RECIPIENT_INFO)); CAPI.CMSG_CTRL_KEY_AGREE_DECRYPT_PARA keyAgreeDecryptPara = new CAPI.CMSG_CTRL_KEY_AGREE_DECRYPT_PARA(Marshal.SizeOf(typeof(CAPI.CMSG_CTRL_KEY_AGREE_DECRYPT_PARA))); keyAgreeDecryptPara.hCryptProv = cmsgDecryptParam.safeCryptProvHandle.DangerousGetHandle(); keyAgreeDecryptPara.dwKeySpec = cmsgDecryptParam.keySpec; keyAgreeDecryptPara.pKeyAgree = cmsRecipientInfo.pRecipientInfo; keyAgreeDecryptPara.dwRecipientIndex = keyAgree.Index; keyAgreeDecryptPara.dwRecipientEncryptedKeyIndex = keyAgree.SubIndex; if (keyAgree.SubType == RecipientSubType.CertIdKeyAgreement) { CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO certIdKeyAgree = (CAPI.CMSG_KEY_AGREE_CERT_ID_RECIPIENT_INFO) keyAgree.CmsgRecipientInfo; SafeCertStoreHandle hCertStore = BuildOriginatorStore(this.Certificates, extraStore); pOriginatorCert = CAPI.CertFindCertificateInStore(hCertStore, CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING, 0, CAPI.CERT_FIND_CERT_ID, new IntPtr(&certIdKeyAgree.OriginatorCertId), SafeCertContextHandle.InvalidHandle); if (pOriginatorCert == null || pOriginatorCert.IsInvalid) { hr2 = CAPI.CRYPT_E_NOT_FOUND; break; } CAPI.CERT_CONTEXT pCertContext = (CAPI.CERT_CONTEXT) Marshal.PtrToStructure(pOriginatorCert.DangerousGetHandle(), typeof(CAPI.CERT_CONTEXT)); CAPI.CERT_INFO certInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO)); keyAgreeDecryptPara.OriginatorPublicKey = certInfo.SubjectPublicKeyInfo.PublicKey; } else { CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO publicKeyAgree = (CAPI.CMSG_KEY_AGREE_PUBLIC_KEY_RECIPIENT_INFO) keyAgree.CmsgRecipientInfo; keyAgreeDecryptPara.OriginatorPublicKey = publicKeyAgree.OriginatorPublicKeyInfo.PublicKey; } if (!CAPI.CryptMsgControl(m_safeCryptMsgHandle, 0, CAPI.CMSG_CTRL_KEY_AGREE_DECRYPT, new IntPtr(&keyAgreeDecryptPara))) hr2 = Marshal.GetHRForLastWin32Error(); GC.KeepAlive(keyAgreeDecryptPara); GC.KeepAlive(pOriginatorCert); break; default: throw new CryptographicException(CAPI.E_NOTIMPL); } GC.KeepAlive(cmsgDecryptParam); } // Content decrypted? if (hr2 == CAPI.S_OK) { // Yes, so retrieve it. uint cbContent = 0; SafeLocalAllocHandle pbContent = SafeLocalAllocHandle.InvalidHandle; PkcsUtils.GetParam(m_safeCryptMsgHandle, CAPI.CMSG_CONTENT_PARAM, 0, out pbContent, out cbContent); if (cbContent > 0) { Oid contentType = PkcsUtils.GetContentType(m_safeCryptMsgHandle); byte[] content = new byte[cbContent]; Marshal.Copy(pbContent.DangerousGetHandle(), content, 0, (int) cbContent); m_contentInfo = new ContentInfo(contentType, content); } pbContent.Dispose(); hr = CAPI.S_OK; break; } else { // Try next recipient. hr = hr2; } } if (hr != CAPI.S_OK) throw new CryptographicException(hr); return; }