| File: Internal\Cryptography\Pal\Windows\KeyAgreeRecipientInfoPalWindows.cs | Web Access |
| Project: src\runtime\src\libraries\System.Security.Cryptography.Pkcs\src\System.Security.Cryptography.Pkcs.csproj (System.Security.Cryptography.Pkcs) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Security.Cryptography.Pkcs; using Microsoft.Win32.SafeHandles; using static Interop.Crypt32; namespace Internal.Cryptography.Pal.Windows { internal sealed class KeyAgreeRecipientInfoPalWindows : KeyAgreeRecipientInfoPal { internal KeyAgreeRecipientInfoPalWindows(SafeHandle pCmsgCmsRecipientInfoMemory, int index, int subIndex) : base() { _pCmsgCmsRecipientInfoMemory = pCmsgCmsRecipientInfoMemory; Index = index; SubIndex = subIndex; } public sealed override int Version { get { unsafe { return WithCmsgCmsRecipientInfo<int>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* recipient) { return recipient->dwVersion; }); } } } public sealed override SubjectIdentifier RecipientIdentifier { get { unsafe { return WithCmsgCmsRecipientInfo<SubjectIdentifier>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* recipient) { CMSG_RECIPIENT_ENCRYPTED_KEY_INFO* pEncryptedKeyInfo = recipient->rgpRecipientEncryptedKeys[SubIndex]; return pEncryptedKeyInfo->RecipientId.ToSubjectIdentifier(); }); } } } public sealed override AlgorithmIdentifier KeyEncryptionAlgorithm { get { unsafe { return WithCmsgCmsRecipientInfo<AlgorithmIdentifier>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* recipient) { return recipient->KeyEncryptionAlgorithm.ToAlgorithmIdentifier(); }); } } } public sealed override byte[] EncryptedKey { get { unsafe { return WithCmsgCmsRecipientInfo<byte[]>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* recipient) { CMSG_RECIPIENT_ENCRYPTED_KEY_INFO* pEncryptedKeyInfo = recipient->rgpRecipientEncryptedKeys[SubIndex]; return pEncryptedKeyInfo->EncryptedKey.ToByteArray(); }); } } } public sealed override SubjectIdentifierOrKey OriginatorIdentifierOrKey { get { unsafe { return WithCmsgCmsRecipientInfo<SubjectIdentifierOrKey>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* recipient) { CMsgKeyAgreeOriginatorChoice originatorChoice = recipient->dwOriginatorChoice; return originatorChoice switch { CMsgKeyAgreeOriginatorChoice.CMSG_KEY_AGREE_ORIGINATOR_CERT => recipient->OriginatorCertId.ToSubjectIdentifierOrKey(), CMsgKeyAgreeOriginatorChoice.CMSG_KEY_AGREE_ORIGINATOR_PUBLIC_KEY => recipient->OriginatorPublicKeyInfo.ToSubjectIdentifierOrKey(), _ => throw new CryptographicException(SR.Format(SR.Cryptography_Cms_Invalid_Originator_Identifier_Choice, originatorChoice)), }; }); } } } public sealed override DateTime Date { get { if (RecipientIdentifier.Type != SubjectIdentifierType.SubjectKeyIdentifier) throw new InvalidOperationException(SR.Cryptography_Cms_Key_Agree_Date_Not_Available); unsafe { return WithCmsgCmsRecipientInfo<DateTime>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* recipient) { CMSG_RECIPIENT_ENCRYPTED_KEY_INFO* pEncryptedKeyInfo = recipient->rgpRecipientEncryptedKeys[SubIndex]; long date = (((long)pEncryptedKeyInfo->Date.ftTimeHigh) << 32) | ((long)pEncryptedKeyInfo->Date.ftTimeLow); DateTime dateTime = DateTime.FromFileTimeUtc(date); return dateTime; }); } } } public sealed override CryptographicAttributeObject? OtherKeyAttribute { get { if (RecipientIdentifier.Type != SubjectIdentifierType.SubjectKeyIdentifier) throw new InvalidOperationException(SR.Cryptography_Cms_Key_Agree_Date_Not_Available); unsafe { return WithCmsgCmsRecipientInfo<CryptographicAttributeObject?>( delegate (CMSG_KEY_AGREE_RECIPIENT_INFO* recipient) { CMSG_RECIPIENT_ENCRYPTED_KEY_INFO* pEncryptedKeyInfo = recipient->rgpRecipientEncryptedKeys[SubIndex]; CRYPT_ATTRIBUTE_TYPE_VALUE* pCryptAttributeTypeValue = pEncryptedKeyInfo->pOtherAttr; if (pCryptAttributeTypeValue == null) return null; string oidValue = pCryptAttributeTypeValue->pszObjId.ToStringAnsi(); Oid oid = Oid.FromOidValue(oidValue, OidGroup.All); byte[] rawData = pCryptAttributeTypeValue->Value.ToByteArray(); Pkcs9AttributeObject pkcs9AttributeObject = new Pkcs9AttributeObject(oid, rawData); AsnEncodedDataCollection values = new AsnEncodedDataCollection(pkcs9AttributeObject); return new CryptographicAttributeObject(oid, values); }); } } } internal int Index { get; } internal int SubIndex { get; } // Provides access to the native CMSG_KEY_TRANS_RECIPIENT_INFO* structure. This helper is structured as taking a delegate to // help avoid the easy trap of forgetting to prevent the underlying memory block from being GC'd early. internal T WithCmsgCmsRecipientInfo<T>(KeyAgreeReceiver<T> receiver) { unsafe { CMSG_CMS_RECIPIENT_INFO* pRecipientInfo = (CMSG_CMS_RECIPIENT_INFO*)(_pCmsgCmsRecipientInfoMemory.DangerousGetHandle()); CMSG_KEY_AGREE_RECIPIENT_INFO* pKeyAgree = pRecipientInfo->KeyAgree; T value = receiver(pKeyAgree); GC.KeepAlive(_pCmsgCmsRecipientInfoMemory); return value; } } internal unsafe delegate T KeyAgreeReceiver<T>(CMSG_KEY_AGREE_RECIPIENT_INFO* recipient); // This is the backing store for the CMSG_CMS_RECIPIENT_INFO* structure for this RecipientInfo. CMSG_CMS_RECIPIENT_INFO is full of interior // pointers so we store in a native heap block to keep it pinned. private readonly SafeHandle _pCmsgCmsRecipientInfoMemory; } }