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)); } } }
internal static DecryptorPalWindows Decode( ReadOnlySpan <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, ref MemoryMarshal.GetReference(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.Value !; contentEncryptionAlgorithmAsn.Parameters = (*pCryptAlgorithmIdentifier).Parameters.ToByteArray(); } } originatorCerts = hCryptMsg.GetOriginatorCerts(); unprotectedAttributes = hCryptMsg.GetUnprotectedAttributes(); RecipientInfoCollection recipientInfos = CreateRecipientInfos(hCryptMsg); return(new DecryptorPalWindows(hCryptMsg, recipientInfos, contentEncryptionAlgorithmAsn)); }
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)); }