private static IEnumerable<RecipientInfo> ToRecipientInfosForThisIndex(SafeHandle pCmsgCmsRecipientInfoMemory, int index) { bool mustRelease = false; pCmsgCmsRecipientInfoMemory.DangerousAddRef(ref mustRelease); try { unsafe { CMSG_CMS_RECIPIENT_INFO* pCMsgCmsRecipientInfo = (CMSG_CMS_RECIPIENT_INFO*)(pCmsgCmsRecipientInfoMemory.DangerousGetHandle()); switch (pCMsgCmsRecipientInfo->dwRecipientChoice) { case CMsgCmsRecipientChoice.CMSG_KEY_TRANS_RECIPIENT: return new KeyTransRecipientInfo[] { new KeyTransRecipientInfo(new KeyTransRecipientInfoPalWindows(pCmsgCmsRecipientInfoMemory, index)) }; case CMsgCmsRecipientChoice.CMSG_KEY_AGREE_RECIPIENT: { CMSG_KEY_AGREE_RECIPIENT_INFO* pCmsKeyAgreeRecipientInfo = pCMsgCmsRecipientInfo->KeyAgree; int numKeys = pCmsKeyAgreeRecipientInfo->cRecipientEncryptedKeys; KeyAgreeRecipientInfo[] recipients = new KeyAgreeRecipientInfo[numKeys]; for (int subIndex = 0; subIndex < numKeys; subIndex++) { recipients[subIndex] = new KeyAgreeRecipientInfo(new KeyAgreeRecipientInfoPalWindows(pCmsgCmsRecipientInfoMemory, index, subIndex)); } return recipients; } default: throw ErrorCode.E_NOTIMPL.ToCryptographicException(); } } } finally { if (mustRelease) { pCmsgCmsRecipientInfoMemory.DangerousRelease(); } } }
private Exception TryDecryptAgree(KeyAgreeRecipientInfo keyAgreeRecipientInfo, SafeProvOrNCryptKeyHandle hKey, CryptKeySpec keySpec, X509Certificate2Collection originatorCerts, X509Certificate2Collection extraStore) { unsafe { KeyAgreeRecipientInfoPalWindows pal = (KeyAgreeRecipientInfoPalWindows)(keyAgreeRecipientInfo.Pal); return pal.WithCmsgCmsRecipientInfo<Exception>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* pKeyAgreeRecipientInfo) { CMSG_CTRL_KEY_AGREE_DECRYPT_PARA decryptPara = default(CMSG_CTRL_KEY_AGREE_DECRYPT_PARA); decryptPara.cbSize = Marshal.SizeOf<CMSG_CTRL_KEY_AGREE_DECRYPT_PARA>(); decryptPara.hProv = hKey; decryptPara.dwKeySpec = keySpec; decryptPara.pKeyAgree = pKeyAgreeRecipientInfo; decryptPara.dwRecipientIndex = pal.Index; decryptPara.dwRecipientEncryptedKeyIndex = pal.SubIndex; CMsgKeyAgreeOriginatorChoice originatorChoice = pKeyAgreeRecipientInfo->dwOriginatorChoice; switch (originatorChoice) { case CMsgKeyAgreeOriginatorChoice.CMSG_KEY_AGREE_ORIGINATOR_CERT: { X509Certificate2Collection candidateCerts = new X509Certificate2Collection(); candidateCerts.AddRange(Helpers.GetStoreCertificates(StoreName.AddressBook, StoreLocation.CurrentUser, openExistingOnly: true)); candidateCerts.AddRange(Helpers.GetStoreCertificates(StoreName.AddressBook, StoreLocation.LocalMachine, openExistingOnly: true)); candidateCerts.AddRange(originatorCerts); candidateCerts.AddRange(extraStore); SubjectIdentifier originatorId = pKeyAgreeRecipientInfo->OriginatorCertId.ToSubjectIdentifier(); using (X509Certificate2 originatorCert = candidateCerts.TryFindMatchingCertificate(originatorId)) { if (originatorCert == null) return ErrorCode.CRYPT_E_NOT_FOUND.ToCryptographicException(); using (SafeCertContextHandle hCertContext = originatorCert.CreateCertContextHandle()) { CERT_CONTEXT* pOriginatorCertContext = hCertContext.DangerousGetCertContext(); decryptPara.OriginatorPublicKey = pOriginatorCertContext->pCertInfo->SubjectPublicKeyInfo.PublicKey; // Do not factor this call out of the switch statement as leaving this "using" block will free up // native memory that decryptPara points to. return TryExecuteDecryptAgree(ref decryptPara); } } } case CMsgKeyAgreeOriginatorChoice.CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY: { decryptPara.OriginatorPublicKey = pKeyAgreeRecipientInfo->OriginatorPublicKeyInfo.PublicKey; return TryExecuteDecryptAgree(ref decryptPara); } default: return new CryptographicException(SR.Format(SR.Cryptography_Cms_Invalid_Originator_Identifier_Choice, originatorChoice)); } }); } }