private static void SetPkcs7RecipientParams(CmsRecipientCollection recipients, ref CMSG_ENCRYPT_PARAM encryptParam, out List<System.Security.Cryptography.SafeCertContextHandle> certContexts)
 {
     int num = 0;
     int count = recipients.Count;
     certContexts = new List<System.Security.Cryptography.SafeCertContextHandle>();
     uint num3 = (uint) (count * Marshal.SizeOf(typeof(IntPtr)));
     encryptParam.rgpRecipients = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr((long) num3));
     IntPtr ptr = encryptParam.rgpRecipients.DangerousGetHandle();
     for (num = 0; num < count; num++)
     {
         System.Security.Cryptography.SafeCertContextHandle certContext = System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(recipients[num].Certificate);
         certContexts.Add(certContext);
         System.Security.Cryptography.CAPI.CERT_CONTEXT cert_context = (System.Security.Cryptography.CAPI.CERT_CONTEXT) Marshal.PtrToStructure(certContext.DangerousGetHandle(), typeof(System.Security.Cryptography.CAPI.CERT_CONTEXT));
         Marshal.WriteIntPtr(ptr, cert_context.pCertInfo);
         ptr = new IntPtr(((long) ptr) + Marshal.SizeOf(typeof(IntPtr)));
     }
 }
 private static unsafe void SetCmsRecipientParams(CmsRecipientCollection recipients, X509Certificate2Collection certificates, CryptographicAttributeObjectCollection unprotectedAttributes, AlgorithmIdentifier contentEncryptionAlgorithm, ref CMSG_ENCRYPT_PARAM encryptParam)
 {
     int index = 0;
     uint[] numArray = new uint[recipients.Count];
     int num2 = 0;
     int num3 = recipients.Count * Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCODE_INFO));
     int num4 = num3;
     for (index = 0; index < recipients.Count; index++)
     {
         numArray[index] = (uint) PkcsUtils.GetRecipientInfoType(recipients[index].Certificate);
         if (numArray[index] == 1)
         {
             num4 += Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO));
         }
         else
         {
             if (numArray[index] != 2)
             {
                 throw new CryptographicException(-2146889726);
             }
             num2++;
             num4 += Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO));
         }
     }
     encryptParam.rgpRecipients = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(num4));
     encryptParam.rgCertEncoded = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle;
     encryptParam.rgUnprotectedAttr = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle;
     encryptParam.rgSubjectKeyIdentifier = new System.Security.Cryptography.SafeLocalAllocHandle[recipients.Count];
     encryptParam.rgszObjId = new System.Security.Cryptography.SafeLocalAllocHandle[recipients.Count];
     if (num2 > 0)
     {
         encryptParam.rgszKeyWrapObjId = new System.Security.Cryptography.SafeLocalAllocHandle[num2];
         encryptParam.rgKeyWrapAuxInfo = new System.Security.Cryptography.SafeLocalAllocHandle[num2];
         encryptParam.rgEphemeralIdentifier = new System.Security.Cryptography.SafeLocalAllocHandle[num2];
         encryptParam.rgszEphemeralObjId = new System.Security.Cryptography.SafeLocalAllocHandle[num2];
         encryptParam.rgUserKeyingMaterial = new System.Security.Cryptography.SafeLocalAllocHandle[num2];
         encryptParam.prgpEncryptedKey = new System.Security.Cryptography.SafeLocalAllocHandle[num2];
         encryptParam.rgpEncryptedKey = new System.Security.Cryptography.SafeLocalAllocHandle[num2];
     }
     if (certificates.Count > 0)
     {
         encryptParam.rgCertEncoded = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(certificates.Count * Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB))));
         for (index = 0; index < certificates.Count; index++)
         {
             System.Security.Cryptography.CAPI.CERT_CONTEXT cert_context = (System.Security.Cryptography.CAPI.CERT_CONTEXT) Marshal.PtrToStructure(System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(certificates[index]).DangerousGetHandle(), typeof(System.Security.Cryptography.CAPI.CERT_CONTEXT));
             System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB* cryptoapi_blobPtr = (System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB*) new IntPtr(((long) encryptParam.rgCertEncoded.DangerousGetHandle()) + (index * Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB))));
             cryptoapi_blobPtr->cbData = cert_context.cbCertEncoded;
             cryptoapi_blobPtr->pbData = cert_context.pbCertEncoded;
         }
     }
     if (unprotectedAttributes.Count > 0)
     {
         encryptParam.rgUnprotectedAttr = new System.Security.Cryptography.SafeLocalAllocHandle(PkcsUtils.CreateCryptAttributes(unprotectedAttributes));
     }
     num2 = 0;
     IntPtr ptr = new IntPtr(((long) encryptParam.rgpRecipients.DangerousGetHandle()) + num3);
     for (index = 0; index < recipients.Count; index++)
     {
         CmsRecipient recipient = recipients[index];
         X509Certificate2 certificate = recipient.Certificate;
         System.Security.Cryptography.CAPI.CERT_CONTEXT cert_context2 = (System.Security.Cryptography.CAPI.CERT_CONTEXT) Marshal.PtrToStructure(System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(certificate).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_context2.pCertInfo, typeof(System.Security.Cryptography.CAPI.CERT_INFO));
         System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCODE_INFO* cmsg_recipient_encode_infoPtr = (System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCODE_INFO*) new IntPtr(((long) encryptParam.rgpRecipients.DangerousGetHandle()) + (index * Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCODE_INFO))));
         cmsg_recipient_encode_infoPtr->dwRecipientChoice = numArray[index];
         cmsg_recipient_encode_infoPtr->pRecipientInfo = ptr;
         if (numArray[index] == 1)
         {
             IntPtr ptr2 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "cbSize")));
             Marshal.WriteInt32(ptr2, Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)));
             IntPtr ptr3 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "KeyEncryptionAlgorithm")));
             byte[] bytes = Encoding.ASCII.GetBytes(cert_info.SubjectPublicKeyInfo.Algorithm.pszObjId);
             encryptParam.rgszObjId[index] = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(bytes.Length + 1));
             Marshal.Copy(bytes, 0, encryptParam.rgszObjId[index].DangerousGetHandle(), bytes.Length);
             IntPtr ptr4 = new IntPtr(((long) ptr3) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId")));
             Marshal.WriteIntPtr(ptr4, encryptParam.rgszObjId[index].DangerousGetHandle());
             IntPtr ptr5 = new IntPtr(((long) ptr3) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_ALGORITHM_IDENTIFIER), "Parameters")));
             IntPtr ptr6 = new IntPtr(((long) ptr5) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
             Marshal.WriteInt32(ptr6, (int) cert_info.SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
             IntPtr ptr7 = new IntPtr(((long) ptr5) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
             Marshal.WriteIntPtr(ptr7, cert_info.SubjectPublicKeyInfo.Algorithm.Parameters.pbData);
             IntPtr ptr8 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "RecipientPublicKey")));
             ptr6 = new IntPtr(((long) ptr8) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_BIT_BLOB), "cbData")));
             Marshal.WriteInt32(ptr6, (int) cert_info.SubjectPublicKeyInfo.PublicKey.cbData);
             ptr7 = new IntPtr(((long) ptr8) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_BIT_BLOB), "pbData")));
             Marshal.WriteIntPtr(ptr7, cert_info.SubjectPublicKeyInfo.PublicKey.pbData);
             IntPtr ptr9 = new IntPtr(((long) ptr8) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_BIT_BLOB), "cUnusedBits")));
             Marshal.WriteInt32(ptr9, (int) cert_info.SubjectPublicKeyInfo.PublicKey.cUnusedBits);
             IntPtr ptr10 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "RecipientId")));
             if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)
             {
                 uint pcbData = 0;
                 System.Security.Cryptography.SafeLocalAllocHandle invalidHandle = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle;
                 if (!System.Security.Cryptography.CAPI.CAPISafe.CertGetCertificateContextProperty(System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(certificate), 20, invalidHandle, ref pcbData))
                 {
                     throw new CryptographicException(Marshal.GetLastWin32Error());
                 }
                 invalidHandle = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr((long) pcbData));
                 if (!System.Security.Cryptography.CAPI.CAPISafe.CertGetCertificateContextProperty(System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(certificate), 20, invalidHandle, ref pcbData))
                 {
                     throw new CryptographicException(Marshal.GetLastWin32Error());
                 }
                 encryptParam.rgSubjectKeyIdentifier[index] = invalidHandle;
                 IntPtr ptr11 = new IntPtr(((long) ptr10) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ID), "dwIdChoice")));
                 Marshal.WriteInt32(ptr11, 2);
                 IntPtr ptr12 = new IntPtr(((long) ptr10) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ID), "Value")));
                 ptr6 = new IntPtr(((long) ptr12) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
                 Marshal.WriteInt32(ptr6, (int) pcbData);
                 ptr7 = new IntPtr(((long) ptr12) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
                 Marshal.WriteIntPtr(ptr7, invalidHandle.DangerousGetHandle());
             }
             else
             {
                 IntPtr ptr13 = new IntPtr(((long) ptr10) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ID), "dwIdChoice")));
                 Marshal.WriteInt32(ptr13, 1);
                 IntPtr ptr14 = new IntPtr(((long) ptr10) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ID), "Value")));
                 IntPtr ptr15 = new IntPtr(((long) ptr14) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ISSUER_SERIAL_NUMBER), "Issuer")));
                 ptr6 = new IntPtr(((long) ptr15) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
                 Marshal.WriteInt32(ptr6, (int) cert_info.Issuer.cbData);
                 ptr7 = new IntPtr(((long) ptr15) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
                 Marshal.WriteIntPtr(ptr7, cert_info.Issuer.pbData);
                 IntPtr ptr16 = new IntPtr(((long) ptr14) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ISSUER_SERIAL_NUMBER), "SerialNumber")));
                 ptr6 = new IntPtr(((long) ptr16) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
                 Marshal.WriteInt32(ptr6, (int) cert_info.SerialNumber.cbData);
                 ptr7 = new IntPtr(((long) ptr16) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
                 Marshal.WriteIntPtr(ptr7, cert_info.SerialNumber.pbData);
             }
             ptr = new IntPtr(((long) ptr) + Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)));
         }
         else if (numArray[index] == 2)
         {
             IntPtr ptr17 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "cbSize")));
             Marshal.WriteInt32(ptr17, Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO)));
             IntPtr ptr18 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "KeyEncryptionAlgorithm")));
             byte[] source = Encoding.ASCII.GetBytes("1.2.840.113549.1.9.16.3.5");
             encryptParam.rgszObjId[index] = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(source.Length + 1));
             Marshal.Copy(source, 0, encryptParam.rgszObjId[index].DangerousGetHandle(), source.Length);
             IntPtr ptr19 = new IntPtr(((long) ptr18) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId")));
             Marshal.WriteIntPtr(ptr19, encryptParam.rgszObjId[index].DangerousGetHandle());
             IntPtr ptr20 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "KeyWrapAlgorithm")));
             uint num6 = System.Security.Cryptography.X509Certificates.X509Utils.OidToAlgId(contentEncryptionAlgorithm.Oid.Value);
             if (num6 == 0x6602)
             {
                 source = Encoding.ASCII.GetBytes("1.2.840.113549.1.9.16.3.7");
             }
             else
             {
                 source = Encoding.ASCII.GetBytes("1.2.840.113549.1.9.16.3.6");
             }
             encryptParam.rgszKeyWrapObjId[num2] = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(source.Length + 1));
             Marshal.Copy(source, 0, encryptParam.rgszKeyWrapObjId[num2].DangerousGetHandle(), source.Length);
             ptr19 = new IntPtr(((long) ptr20) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId")));
             Marshal.WriteIntPtr(ptr19, encryptParam.rgszKeyWrapObjId[num2].DangerousGetHandle());
             if (num6 == 0x6602)
             {
                 IntPtr ptr21 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "pvKeyWrapAuxInfo")));
                 Marshal.WriteIntPtr(ptr21, encryptParam.pvEncryptionAuxInfo.DangerousGetHandle());
             }
             IntPtr ptr22 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "dwKeyChoice")));
             Marshal.WriteInt32(ptr22, 1);
             IntPtr ptr23 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "pEphemeralAlgorithmOrSenderId")));
             encryptParam.rgEphemeralIdentifier[num2] = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CRYPT_ALGORITHM_IDENTIFIER))));
             Marshal.WriteIntPtr(ptr23, encryptParam.rgEphemeralIdentifier[num2].DangerousGetHandle());
             source = Encoding.ASCII.GetBytes(cert_info.SubjectPublicKeyInfo.Algorithm.pszObjId);
             encryptParam.rgszEphemeralObjId[num2] = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(source.Length + 1));
             Marshal.Copy(source, 0, encryptParam.rgszEphemeralObjId[num2].DangerousGetHandle(), source.Length);
             ptr19 = new IntPtr(((long) encryptParam.rgEphemeralIdentifier[num2].DangerousGetHandle()) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId")));
             Marshal.WriteIntPtr(ptr19, encryptParam.rgszEphemeralObjId[num2].DangerousGetHandle());
             IntPtr ptr24 = new IntPtr(((long) encryptParam.rgEphemeralIdentifier[num2].DangerousGetHandle()) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_ALGORITHM_IDENTIFIER), "Parameters")));
             IntPtr ptr25 = new IntPtr(((long) ptr24) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
             Marshal.WriteInt32(ptr25, (int) cert_info.SubjectPublicKeyInfo.Algorithm.Parameters.cbData);
             IntPtr ptr26 = new IntPtr(((long) ptr24) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
             Marshal.WriteIntPtr(ptr26, cert_info.SubjectPublicKeyInfo.Algorithm.Parameters.pbData);
             IntPtr ptr27 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "cRecipientEncryptedKeys")));
             Marshal.WriteInt32(ptr27, 1);
             encryptParam.prgpEncryptedKey[num2] = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(Marshal.SizeOf(typeof(IntPtr))));
             IntPtr ptr28 = new IntPtr(((long) ptr) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "rgpRecipientEncryptedKeys")));
             Marshal.WriteIntPtr(ptr28, encryptParam.prgpEncryptedKey[num2].DangerousGetHandle());
             encryptParam.rgpEncryptedKey[num2] = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO))));
             Marshal.WriteIntPtr(encryptParam.prgpEncryptedKey[num2].DangerousGetHandle(), encryptParam.rgpEncryptedKey[num2].DangerousGetHandle());
             ptr17 = new IntPtr(((long) encryptParam.rgpEncryptedKey[num2].DangerousGetHandle()) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO), "cbSize")));
             Marshal.WriteInt32(ptr17, Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO)));
             IntPtr ptr29 = new IntPtr(((long) encryptParam.rgpEncryptedKey[num2].DangerousGetHandle()) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO), "RecipientPublicKey")));
             ptr25 = new IntPtr(((long) ptr29) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_BIT_BLOB), "cbData")));
             Marshal.WriteInt32(ptr25, (int) cert_info.SubjectPublicKeyInfo.PublicKey.cbData);
             ptr26 = new IntPtr(((long) ptr29) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_BIT_BLOB), "pbData")));
             Marshal.WriteIntPtr(ptr26, cert_info.SubjectPublicKeyInfo.PublicKey.pbData);
             IntPtr ptr30 = new IntPtr(((long) ptr29) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPT_BIT_BLOB), "cUnusedBits")));
             Marshal.WriteInt32(ptr30, (int) cert_info.SubjectPublicKeyInfo.PublicKey.cUnusedBits);
             IntPtr ptr31 = new IntPtr(((long) encryptParam.rgpEncryptedKey[num2].DangerousGetHandle()) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO), "RecipientId")));
             IntPtr ptr32 = new IntPtr(((long) ptr31) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ID), "dwIdChoice")));
             if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier)
             {
                 Marshal.WriteInt32(ptr32, 2);
                 IntPtr ptr33 = new IntPtr(((long) ptr31) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ID), "Value")));
                 uint num7 = 0;
                 System.Security.Cryptography.SafeLocalAllocHandle pvData = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle;
                 if (!System.Security.Cryptography.CAPI.CAPISafe.CertGetCertificateContextProperty(System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(certificate), 20, pvData, ref num7))
                 {
                     throw new CryptographicException(Marshal.GetLastWin32Error());
                 }
                 pvData = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr((long) num7));
                 if (!System.Security.Cryptography.CAPI.CAPISafe.CertGetCertificateContextProperty(System.Security.Cryptography.X509Certificates.X509Utils.GetCertContext(certificate), 20, pvData, ref num7))
                 {
                     throw new CryptographicException(Marshal.GetLastWin32Error());
                 }
                 encryptParam.rgSubjectKeyIdentifier[num2] = pvData;
                 ptr25 = new IntPtr(((long) ptr33) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
                 Marshal.WriteInt32(ptr25, (int) num7);
                 ptr26 = new IntPtr(((long) ptr33) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
                 Marshal.WriteIntPtr(ptr26, pvData.DangerousGetHandle());
             }
             else
             {
                 Marshal.WriteInt32(ptr32, 1);
                 IntPtr ptr34 = new IntPtr(((long) ptr31) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ID), "Value")));
                 IntPtr ptr35 = new IntPtr(((long) ptr34) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ISSUER_SERIAL_NUMBER), "Issuer")));
                 ptr25 = new IntPtr(((long) ptr35) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
                 Marshal.WriteInt32(ptr25, (int) cert_info.Issuer.cbData);
                 ptr26 = new IntPtr(((long) ptr35) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
                 Marshal.WriteIntPtr(ptr26, cert_info.Issuer.pbData);
                 IntPtr ptr36 = new IntPtr(((long) ptr34) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CERT_ISSUER_SERIAL_NUMBER), "SerialNumber")));
                 ptr25 = new IntPtr(((long) ptr36) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "cbData")));
                 Marshal.WriteInt32(ptr25, (int) cert_info.SerialNumber.cbData);
                 ptr26 = new IntPtr(((long) ptr36) + ((long) Marshal.OffsetOf(typeof(System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB), "pbData")));
                 Marshal.WriteIntPtr(ptr26, cert_info.SerialNumber.pbData);
             }
             num2++;
             ptr = new IntPtr(((long) ptr) + Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO)));
         }
     }
 }
 private static void SetCspParams(AlgorithmIdentifier contentEncryptionAlgorithm, ref CMSG_ENCRYPT_PARAM encryptParam)
 {
     encryptParam.safeCryptProvHandle = System.Security.Cryptography.SafeCryptProvHandle.InvalidHandle;
     encryptParam.pvEncryptionAuxInfo = System.Security.Cryptography.SafeLocalAllocHandle.InvalidHandle;
     System.Security.Cryptography.SafeCryptProvHandle invalidHandle = System.Security.Cryptography.SafeCryptProvHandle.InvalidHandle;
     if (!System.Security.Cryptography.CAPI.CryptAcquireContext(ref invalidHandle, IntPtr.Zero, IntPtr.Zero, 1, 0xf0000000))
     {
         throw new CryptographicException(Marshal.GetLastWin32Error());
     }
     uint algId = System.Security.Cryptography.X509Certificates.X509Utils.OidToAlgId(contentEncryptionAlgorithm.Oid.Value);
     switch (algId)
     {
         case 0x6602:
         case 0x6801:
         {
             System.Security.Cryptography.CAPI.CMSG_RC2_AUX_INFO structure = new System.Security.Cryptography.CAPI.CMSG_RC2_AUX_INFO(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_RC2_AUX_INFO)));
             uint keyLength = (uint) contentEncryptionAlgorithm.KeyLength;
             if (keyLength == 0)
             {
                 keyLength = (uint) PkcsUtils.GetMaxKeyLength(invalidHandle, algId);
             }
             structure.dwBitLen = keyLength;
             System.Security.Cryptography.SafeLocalAllocHandle handle2 = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_RC2_AUX_INFO))));
             Marshal.StructureToPtr(structure, handle2.DangerousGetHandle(), false);
             encryptParam.pvEncryptionAuxInfo = handle2;
             break;
         }
     }
     encryptParam.safeCryptProvHandle = invalidHandle;
 }
 private unsafe void EncryptContent(CmsRecipientCollection recipients)
 {
     CMSG_ENCRYPT_PARAM encryptParam = new CMSG_ENCRYPT_PARAM();
     if (recipients.Count < 1)
     {
         throw new CryptographicException(-2146889717);
     }
     CmsRecipientEnumerator enumerator = recipients.GetEnumerator();
     while (enumerator.MoveNext())
     {
         CmsRecipient current = enumerator.Current;
         if (current.Certificate == null)
         {
             throw new ArgumentNullException(SecurityResources.GetResourceString("Cryptography_Cms_RecipientCertificateNotFound"));
         }
         if ((PkcsUtils.GetRecipientInfoType(current.Certificate) == RecipientInfoType.KeyAgreement) || (current.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"));
     }
     System.Security.Cryptography.CAPI.CMSG_ENVELOPED_ENCODE_INFO structure = new System.Security.Cryptography.CAPI.CMSG_ENVELOPED_ENCODE_INFO(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_ENVELOPED_ENCODE_INFO)));
     System.Security.Cryptography.SafeLocalAllocHandle handle = System.Security.Cryptography.CAPI.LocalAlloc(0x40, new IntPtr(Marshal.SizeOf(typeof(System.Security.Cryptography.CAPI.CMSG_ENVELOPED_ENCODE_INFO))));
     SetCspParams(this.ContentEncryptionAlgorithm, ref encryptParam);
     structure.ContentEncryptionAlgorithm.pszObjId = this.ContentEncryptionAlgorithm.Oid.Value;
     if ((encryptParam.pvEncryptionAuxInfo != null) && !encryptParam.pvEncryptionAuxInfo.IsInvalid)
     {
         structure.pvEncryptionAuxInfo = encryptParam.pvEncryptionAuxInfo.DangerousGetHandle();
     }
     structure.cRecipients = (uint) recipients.Count;
     List<System.Security.Cryptography.SafeCertContextHandle> certContexts = null;
     if (encryptParam.useCms)
     {
         SetCmsRecipientParams(recipients, this.Certificates, this.UnprotectedAttributes, this.ContentEncryptionAlgorithm, ref encryptParam);
         structure.rgCmsRecipients = encryptParam.rgpRecipients.DangerousGetHandle();
         if ((encryptParam.rgCertEncoded != null) && !encryptParam.rgCertEncoded.IsInvalid)
         {
             structure.cCertEncoded = (uint) this.Certificates.Count;
             structure.rgCertEncoded = encryptParam.rgCertEncoded.DangerousGetHandle();
         }
         if ((encryptParam.rgUnprotectedAttr != null) && !encryptParam.rgUnprotectedAttr.IsInvalid)
         {
             structure.cUnprotectedAttr = (uint) this.UnprotectedAttributes.Count;
             structure.rgUnprotectedAttr = encryptParam.rgUnprotectedAttr.DangerousGetHandle();
         }
     }
     else
     {
         SetPkcs7RecipientParams(recipients, ref encryptParam, out certContexts);
         structure.rgpRecipients = encryptParam.rgpRecipients.DangerousGetHandle();
     }
     Marshal.StructureToPtr(structure, handle.DangerousGetHandle(), false);
     try
     {
         System.Security.Cryptography.SafeCryptMsgHandle handle2 = System.Security.Cryptography.CAPI.CryptMsgOpenToEncode(0x10001, 0, 3, handle.DangerousGetHandle(), this.ContentInfo.ContentType.Value, IntPtr.Zero);
         if ((handle2 == null) || handle2.IsInvalid)
         {
             throw new CryptographicException(Marshal.GetLastWin32Error());
         }
         if ((this.m_safeCryptMsgHandle != null) && !this.m_safeCryptMsgHandle.IsInvalid)
         {
             this.m_safeCryptMsgHandle.Dispose();
         }
         this.m_safeCryptMsgHandle = handle2;
     }
     finally
     {
         Marshal.DestroyStructure(handle.DangerousGetHandle(), typeof(System.Security.Cryptography.CAPI.CMSG_ENVELOPED_ENCODE_INFO));
         handle.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* numRef = content)
         {
             System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB cryptoapi_blob = new System.Security.Cryptography.CAPI.CRYPTOAPI_BLOB {
                 cbData = (uint) content.Length,
                 pbData = new IntPtr((void*) numRef)
             };
             if (!System.Security.Cryptography.CAPI.EncodeObject(new IntPtr(0x19L), new IntPtr((void*) &cryptoapi_blob), out encodedData))
             {
                 throw new CryptographicException(Marshal.GetLastWin32Error());
             }
         }
     }
     else
     {
         encodedData = this.ContentInfo.Content;
     }
     if ((encodedData.Length > 0) && !System.Security.Cryptography.CAPI.CAPISafe.CryptMsgUpdate(this.m_safeCryptMsgHandle, encodedData, (uint) encodedData.Length, true))
     {
         throw new CryptographicException(Marshal.GetLastWin32Error());
     }
     GC.KeepAlive(encryptParam);
     GC.KeepAlive(recipients);
     GC.KeepAlive(certContexts);
 }
Exemple #5
0
        private static unsafe void SetCmsRecipientParams(CmsRecipientCollection           recipients, 
                                                         X509Certificate2Collection      certificates, 
                                                         CryptographicAttributeObjectCollection unprotectedAttributes,
                                                         AlgorithmIdentifier              contentEncryptionAlgorithm,
                                                         ref CMSG_ENCRYPT_PARAM           encryptParam) {
            checked {
                recipients = recipients.DeepCopy();
                certificates = new X509Certificate2Collection(certificates);

                int index = 0;
                uint[] recipientInfoTypes = new uint[recipients.Count];
                int cKeyAgree = 0;
                int reiSize = recipients.Count * Marshal.SizeOf(typeof(CAPI.CMSG_RECIPIENT_ENCODE_INFO));
                int totalSize = reiSize;

                for (index = 0; index < recipients.Count; index++) {
                    recipientInfoTypes[index] = (uint) PkcsUtils.GetRecipientInfoType(recipients[index].Certificate);

                    if (recipientInfoTypes[index] == CAPI.CMSG_KEY_TRANS_RECIPIENT) {
                        totalSize += Marshal.SizeOf(typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO));
                    }
                    else if (recipientInfoTypes[index] == CAPI.CMSG_KEY_AGREE_RECIPIENT) {
                        cKeyAgree++;
                        totalSize += Marshal.SizeOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO));
                    }
                    else {
                        throw new CryptographicException(CAPI.CRYPT_E_UNKNOWN_ALGO);
                    }
                }

                encryptParam.rgpRecipients = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(totalSize));
                encryptParam.rgCertEncoded = SafeLocalAllocHandle.InvalidHandle;
                encryptParam.rgUnprotectedAttr = SafeLocalAllocHandle.InvalidHandle;
                encryptParam.rgSubjectKeyIdentifier = new SafeLocalAllocHandle[recipients.Count];
                encryptParam.rgszObjId = new SafeLocalAllocHandle[recipients.Count];

                if (cKeyAgree > 0) {
                    encryptParam.rgszKeyWrapObjId = new SafeLocalAllocHandle[cKeyAgree];
                    encryptParam.rgKeyWrapAuxInfo = new SafeLocalAllocHandle[cKeyAgree];
                    encryptParam.rgEphemeralIdentifier = new SafeLocalAllocHandle[cKeyAgree];
                    encryptParam.rgszEphemeralObjId = new SafeLocalAllocHandle[cKeyAgree];
                    encryptParam.rgUserKeyingMaterial = new SafeLocalAllocHandle[cKeyAgree];
                    encryptParam.prgpEncryptedKey = new SafeLocalAllocHandle[cKeyAgree];
                    encryptParam.rgpEncryptedKey = new SafeLocalAllocHandle[cKeyAgree];
                }

                // Create encode certs array.
                if (certificates.Count > 0) {
                    encryptParam.rgCertEncoded = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(certificates.Count * Marshal.SizeOf(typeof(CAPI.CRYPTOAPI_BLOB))));
                    for (index = 0; index < certificates.Count; index++) {
                        CAPI.CERT_CONTEXT pCertContext = (CAPI.CERT_CONTEXT) Marshal.PtrToStructure(X509Utils.GetCertContext(certificates[index]).DangerousGetHandle(), typeof(CAPI.CERT_CONTEXT));
                        CAPI.CRYPTOAPI_BLOB * pBlob = (CAPI.CRYPTOAPI_BLOB *) new IntPtr((long) encryptParam.rgCertEncoded.DangerousGetHandle() + 
                                                                                            (index * Marshal.SizeOf(typeof(CAPI.CRYPTOAPI_BLOB))));
                        pBlob->cbData = pCertContext.cbCertEncoded;
                        pBlob->pbData = pCertContext.pbCertEncoded;
                    }
                }

                // Create unprotected attributes array.
                if (unprotectedAttributes.Count > 0) {
                    encryptParam.rgUnprotectedAttr = new SafeLocalAllocHandle(PkcsUtils.CreateCryptAttributes(unprotectedAttributes));
                }

                // pKeyInfo = CMSG_ENVELOPED_ENCODE_INFO.rgCmsRecipients
                cKeyAgree = 0;
                IntPtr pKeyInfo = new IntPtr((long) encryptParam.rgpRecipients.DangerousGetHandle() + reiSize);
                for (index = 0; index < recipients.Count; index++) {
                    CmsRecipient recipient = recipients[index];
                    X509Certificate2 certificate = recipient.Certificate;
                    CAPI.CERT_CONTEXT pCertContext = (CAPI.CERT_CONTEXT) Marshal.PtrToStructure(X509Utils.GetCertContext(certificate).DangerousGetHandle(), typeof(CAPI.CERT_CONTEXT));
                    CAPI.CERT_INFO certInfo = (CAPI.CERT_INFO) Marshal.PtrToStructure(pCertContext.pCertInfo, typeof(CAPI.CERT_INFO));

                    CAPI.CMSG_RECIPIENT_ENCODE_INFO * pEncodeInfo = (CAPI.CMSG_RECIPIENT_ENCODE_INFO *) new IntPtr((long) encryptParam.rgpRecipients.DangerousGetHandle() + 
                                                                                                                    (index * Marshal.SizeOf(typeof(CAPI.CMSG_RECIPIENT_ENCODE_INFO))));
                    // CMSG_RECIPIENT_ENCODE_INFO.dwRecipientChoice
                    pEncodeInfo->dwRecipientChoice = (uint) recipientInfoTypes[index];

                    // CMSG_RECIPIENT_ENCODE_INFO.pRecipientInfo (pKeyTrans or pKeyAgree)
                    pEncodeInfo->pRecipientInfo = pKeyInfo;

                    if (recipientInfoTypes[index] == CAPI.CMSG_KEY_TRANS_RECIPIENT) {
                        // Fill in CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO.

                        // cbSize
                        IntPtr pcbSize = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "cbSize"));
                        Marshal.WriteInt32(pcbSize, Marshal.SizeOf(typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)));

                        // KeyEncryptionAlgorithm
                        IntPtr pKeyEncryptionAlgorithm = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "KeyEncryptionAlgorithm"));

                        byte[] objId = Encoding.ASCII.GetBytes(certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId);
                        encryptParam.rgszObjId[index] = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(objId.Length + 1));
                        Marshal.Copy(objId, 0, encryptParam.rgszObjId[index].DangerousGetHandle(), objId.Length);

                        // KeyEncryptionAlgorithm.pszObjId
                        IntPtr pszObjId = new IntPtr((long) pKeyEncryptionAlgorithm + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId"));
                        Marshal.WriteIntPtr(pszObjId, encryptParam.rgszObjId[index].DangerousGetHandle());

                        // KeyEncryptionAlgorithm.Parameters
                        IntPtr pParameters = new IntPtr((long) pKeyEncryptionAlgorithm + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "Parameters"));

                        // KeyEncryptionAlgorithm.Parameters.cbData
                        IntPtr pcbData = new IntPtr((long) pParameters + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                        Marshal.WriteInt32(pcbData, (int) certInfo.SubjectPublicKeyInfo.Algorithm.Parameters.cbData);

                        // KeyEncryptionAlgorithm.Parameters.pbData
                        IntPtr ppbData = new IntPtr((long) pParameters + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                        Marshal.WriteIntPtr(ppbData, certInfo.SubjectPublicKeyInfo.Algorithm.Parameters.pbData);

                        // Skip pvKeyEncryptionAuxInfo
                        // Skip hCryptProv

                        // RecipientPublicKey
                        IntPtr pRecipientPublicKey = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "RecipientPublicKey"));

                        // RecipientPublicKey.cbData
                        pcbData = new IntPtr((long) pRecipientPublicKey + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_BIT_BLOB), "cbData"));
                        Marshal.WriteInt32(pcbData, (int) certInfo.SubjectPublicKeyInfo.PublicKey.cbData);

                        // RecipientPublicKey.pbData
                        ppbData = new IntPtr((long) pRecipientPublicKey + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_BIT_BLOB), "pbData"));
                        Marshal.WriteIntPtr(ppbData, certInfo.SubjectPublicKeyInfo.PublicKey.pbData);

                        // RecipientPublicKey.cUnusedBits
                        IntPtr pcUnusedBIts = new IntPtr((long) pRecipientPublicKey + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_BIT_BLOB), "cUnusedBits"));
                        Marshal.WriteInt32(pcUnusedBIts, (int) certInfo.SubjectPublicKeyInfo.PublicKey.cUnusedBits);

                        // RecipientId
                        IntPtr pRecipientId = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO), "RecipientId"));
                        if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier) {
                            uint cbData = 0;
                            SafeLocalAllocHandle pbData = SafeLocalAllocHandle.InvalidHandle;
                            if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate),
                                                                                    CAPI.CERT_KEY_IDENTIFIER_PROP_ID,
                                                                                    pbData,
                                                                                    ref cbData))
                                throw new CryptographicException(Marshal.GetLastWin32Error());

                            pbData = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(cbData));

                            if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate),
                                                                                    CAPI.CERT_KEY_IDENTIFIER_PROP_ID,
                                                                                    pbData,
                                                                                    ref cbData))
                                throw new CryptographicException(Marshal.GetLastWin32Error());

                            encryptParam.rgSubjectKeyIdentifier[index] = pbData;

                            // RecipientId.dwIdChoice
                            IntPtr pdwIdChoice = new IntPtr((long) pRecipientId + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ID), "dwIdChoice"));
                            Marshal.WriteInt32(pdwIdChoice, (int) CAPI.CERT_ID_KEY_IDENTIFIER);

                            // RecipientId.KeyId
                            IntPtr pKeyId = new IntPtr((long) pRecipientId + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ID), "Value"));

                            // RecipientId.KeyId.cbData
                            pcbData = new IntPtr((long) pKeyId + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                            Marshal.WriteInt32(pcbData, (int) cbData);

                            // RecipientId.KeyId.pbData
                            ppbData = new IntPtr((long) pKeyId + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                            Marshal.WriteIntPtr(ppbData, pbData.DangerousGetHandle());
                        }
                        else {
                            // RecipientId.dwIdChoice
                            IntPtr pdwIdChoice = new IntPtr((long) pRecipientId + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ID), "dwIdChoice"));
                            Marshal.WriteInt32(pdwIdChoice, (int) CAPI.CERT_ID_ISSUER_SERIAL_NUMBER);

                            // RecipientId.IssuerSerialNumber
                            IntPtr pIssuerSerialNumber = new IntPtr((long) pRecipientId + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ID), "Value"));

                            // RecipientId.IssuerSerialNumber.Issuer
                            IntPtr pIssuer = new IntPtr((long) pIssuerSerialNumber + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ISSUER_SERIAL_NUMBER), "Issuer"));

                            // RecipientId.IssuerSerialNumber.Issuer.cbData
                            pcbData = new IntPtr((long) pIssuer + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                            Marshal.WriteInt32(pcbData, (int) certInfo.Issuer.cbData);

                            // RecipientId.IssuerSerialNumber.Issuer.pbData
                            ppbData = new IntPtr((long) pIssuer + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                            Marshal.WriteIntPtr(ppbData, certInfo.Issuer.pbData);

                            // RecipientId.IssuerSerialNumber.SerialNumber
                            IntPtr pSerialNumber = new IntPtr((long) pIssuerSerialNumber + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ISSUER_SERIAL_NUMBER), "SerialNumber"));

                            // RecipientId.IssuerSerialNumber.SerialNumber.cbData
                            pcbData = new IntPtr((long) pSerialNumber + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                            Marshal.WriteInt32(pcbData, (int) certInfo.SerialNumber.cbData);

                            // RecipientId.IssuerSerialNumber.SerialNumber.pbData
                            ppbData = new IntPtr((long) pSerialNumber + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                            Marshal.WriteIntPtr(ppbData, certInfo.SerialNumber.pbData);
                        }
                        pKeyInfo = new IntPtr((long) pKeyInfo + Marshal.SizeOf(typeof(CAPI.CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)));
                    }
                    else if (recipientInfoTypes[index] == CAPI.CMSG_KEY_AGREE_RECIPIENT) {
                        // Fill in CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO.

                        // cbSize
                        IntPtr pcbSize = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "cbSize"));
                        Marshal.WriteInt32(pcbSize, Marshal.SizeOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO)));

                        // KeyEncryptionAlgorithm
                        IntPtr pKeyEncryptionAlgorithm = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "KeyEncryptionAlgorithm"));

                        byte[] objId = Encoding.ASCII.GetBytes(CAPI.szOID_RSA_SMIMEalgESDH);
                        encryptParam.rgszObjId[index] = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(objId.Length + 1));
                        Marshal.Copy(objId, 0, encryptParam.rgszObjId[index].DangerousGetHandle(), objId.Length);

                        // KeyEncryptionAlgorithm.pszObjId
                        IntPtr pszObjId = new IntPtr((long) pKeyEncryptionAlgorithm + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId"));
                        Marshal.WriteIntPtr(pszObjId, encryptParam.rgszObjId[index].DangerousGetHandle());

                        // Skip KeyEncryptionAlgorithm.Parameters
                        // Skip pvKeyEncryptionAuxInfo

                        // KeyWrapAlgorithm
                        IntPtr pKeyWrapAlgorithm = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "KeyWrapAlgorithm"));

                        uint algId = X509Utils.OidToAlgId(contentEncryptionAlgorithm.Oid.Value);
                        if (algId == CAPI.CALG_RC2) {
                            objId = Encoding.ASCII.GetBytes(CAPI.szOID_RSA_SMIMEalgCMSRC2wrap);
                        }
                        else {
                            objId = Encoding.ASCII.GetBytes(CAPI.szOID_RSA_SMIMEalgCMS3DESwrap);
                        }
                        encryptParam.rgszKeyWrapObjId[cKeyAgree] = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(objId.Length + 1));
                        Marshal.Copy(objId, 0, encryptParam.rgszKeyWrapObjId[cKeyAgree].DangerousGetHandle(), objId.Length);

                        // KeyWrapAlgorithm.pszObjId
                        pszObjId = new IntPtr((long) pKeyWrapAlgorithm + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId"));
                        Marshal.WriteIntPtr(pszObjId, encryptParam.rgszKeyWrapObjId[cKeyAgree].DangerousGetHandle());

                        // Skip KeyWrapAlgorithm.Parameters

                        // Fill in pvKeyWrapAuxInfo for RC2.
                        if (algId == CAPI.CALG_RC2) {
                            IntPtr pKeyWrapAuxInfo = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "pvKeyWrapAuxInfo"));
                            Marshal.WriteIntPtr(pKeyWrapAuxInfo, encryptParam.pvEncryptionAuxInfo.DangerousGetHandle());
                        }

                        // Skip hCryptProv
                        // Skip dwKeySpec

                        // dwKeyChoice
                        IntPtr pdwKeyChoice = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "dwKeyChoice"));
                        Marshal.WriteInt32(pdwKeyChoice, (int) CAPI.CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE);

                        // pEphemeralAlgorithm
                        IntPtr pEphemeralAlgorithm = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "pEphemeralAlgorithmOrSenderId"));
                        encryptParam.rgEphemeralIdentifier[cKeyAgree] = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER))));
                        Marshal.WriteIntPtr(pEphemeralAlgorithm, encryptParam.rgEphemeralIdentifier[cKeyAgree].DangerousGetHandle());

                        // pEphemeralAlgorithm.pszObjId
                        objId = Encoding.ASCII.GetBytes(certInfo.SubjectPublicKeyInfo.Algorithm.pszObjId);
                        encryptParam.rgszEphemeralObjId[cKeyAgree] = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(objId.Length + 1));
                        Marshal.Copy(objId, 0, encryptParam.rgszEphemeralObjId[cKeyAgree].DangerousGetHandle(), objId.Length);

                        pszObjId = new IntPtr((long) encryptParam.rgEphemeralIdentifier[cKeyAgree].DangerousGetHandle() + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "pszObjId"));
                        Marshal.WriteIntPtr(pszObjId, encryptParam.rgszEphemeralObjId[cKeyAgree].DangerousGetHandle());

                        // pEphemeralAlgorithm.Parameters
                        IntPtr pParameters = new IntPtr((long) encryptParam.rgEphemeralIdentifier[cKeyAgree].DangerousGetHandle() + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_ALGORITHM_IDENTIFIER), "Parameters"));

                        // pEphemeralAlgorithm.Parameters.cbData
                        IntPtr pcbData = new IntPtr((long) pParameters + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                        Marshal.WriteInt32(pcbData, (int) certInfo.SubjectPublicKeyInfo.Algorithm.Parameters.cbData);

                        // pEphemeralAlgorithm.Parameters.pbData
                        IntPtr ppbData = new IntPtr((long) pParameters + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                        Marshal.WriteIntPtr(ppbData, certInfo.SubjectPublicKeyInfo.Algorithm.Parameters.pbData);

                        // Skip UserKeyingMaterial

                        // cRecipientEncryptedKeys
                        IntPtr pcRecipientEncryptedKeys = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "cRecipientEncryptedKeys"));
                        Marshal.WriteInt32(pcRecipientEncryptedKeys, 1);

                        // rgpRecipientEncryptedKeys
                        encryptParam.prgpEncryptedKey[cKeyAgree] = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(IntPtr))));
                        IntPtr prgpRecipientEncryptedKeys = new IntPtr((long) pKeyInfo + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO), "rgpRecipientEncryptedKeys"));
                        Marshal.WriteIntPtr(prgpRecipientEncryptedKeys, encryptParam.prgpEncryptedKey[cKeyAgree].DangerousGetHandle());
                        encryptParam.rgpEncryptedKey[cKeyAgree] = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO))));
                        Marshal.WriteIntPtr(encryptParam.prgpEncryptedKey[cKeyAgree].DangerousGetHandle(), encryptParam.rgpEncryptedKey[cKeyAgree].DangerousGetHandle());

                        // rgpRecipientEncryptedKeys.cbSize
                        pcbSize = new IntPtr((long) encryptParam.rgpEncryptedKey[cKeyAgree].DangerousGetHandle() + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO), "cbSize"));
                        Marshal.WriteInt32(pcbSize, Marshal.SizeOf(typeof(CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO)));

                        // rgpRecipientEncryptedKeys.RecipientPublicKey
                        IntPtr pRecipientPublicKey = new IntPtr((long) encryptParam.rgpEncryptedKey[cKeyAgree].DangerousGetHandle() + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO), "RecipientPublicKey"));

                        // rgpRecipientEncryptedKeys.RecipientPublicKey.cbData
                        pcbData = new IntPtr((long) pRecipientPublicKey + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_BIT_BLOB), "cbData"));
                        Marshal.WriteInt32(pcbData, (int) certInfo.SubjectPublicKeyInfo.PublicKey.cbData);

                        // rgpRecipientEncryptedKeys.RecipientPublicKey.pbData
                        ppbData = new IntPtr((long) pRecipientPublicKey + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_BIT_BLOB), "pbData"));
                        Marshal.WriteIntPtr(ppbData, certInfo.SubjectPublicKeyInfo.PublicKey.pbData);

                        // rgpRecipientEncryptedKeys.RecipientPublicKey.cUnusedBits
                        IntPtr pcUnusedBits = new IntPtr((long) pRecipientPublicKey + (long) Marshal.OffsetOf(typeof(CAPI.CRYPT_BIT_BLOB), "cUnusedBits"));
                        Marshal.WriteInt32(pcUnusedBits, (int) certInfo.SubjectPublicKeyInfo.PublicKey.cUnusedBits);                    

                        // rgpRecipientEncryptedKeys.RecipientId
                        IntPtr pRecipientId = new IntPtr((long) encryptParam.rgpEncryptedKey[cKeyAgree].DangerousGetHandle() + (long) Marshal.OffsetOf(typeof(CAPI.CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO), "RecipientId"));

                        // rgpRecipientEncryptedKeys.RecipientId.dwIdChoice
                        IntPtr pdwIdChoice = new IntPtr((long) pRecipientId + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ID), "dwIdChoice"));

                        if (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier) {
                            Marshal.WriteInt32(pdwIdChoice, (int) CAPI.CERT_ID_KEY_IDENTIFIER);

                            // rgpRecipientEncryptedKeys.RecipientId.KeyId
                            IntPtr pKeyId = new IntPtr((long) pRecipientId + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ID), "Value"));

                            uint cbKeyId = 0;
                            SafeLocalAllocHandle pbKeyId = SafeLocalAllocHandle.InvalidHandle;
                            if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate),
                                                                                    CAPI.CERT_KEY_IDENTIFIER_PROP_ID,
                                                                                    pbKeyId,
                                                                                    ref cbKeyId))
                                throw new CryptographicException(Marshal.GetLastWin32Error());

                            pbKeyId = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(cbKeyId));
                            if (!CAPI.CAPISafe.CertGetCertificateContextProperty(X509Utils.GetCertContext(certificate),
                                                                                    CAPI.CERT_KEY_IDENTIFIER_PROP_ID,
                                                                                    pbKeyId,
                                                                                    ref cbKeyId))
                                throw new CryptographicException(Marshal.GetLastWin32Error());

                            encryptParam.rgSubjectKeyIdentifier[cKeyAgree] = pbKeyId;

                            // rgpRecipientEncryptedKeys.RecipientId.KeyId.cbData
                            pcbData = new IntPtr((long) pKeyId + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                            Marshal.WriteInt32(pcbData, (int) cbKeyId);

                            // rgpRecipientEncryptedKeys.RecipientId.KeyId.pbData
                            ppbData = new IntPtr((long) pKeyId + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                            Marshal.WriteIntPtr(ppbData, pbKeyId.DangerousGetHandle());
                        }
                        else {
                            Marshal.WriteInt32(pdwIdChoice, (int) CAPI.CERT_ID_ISSUER_SERIAL_NUMBER);

                            // rgpRecipientEncryptedKeys.RecipientId.IssuerSerialNumber
                            IntPtr pIssuerSerial = new IntPtr((long) pRecipientId + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ID), "Value"));

                            // rgpRecipientEncryptedKeys.RecipientId.IssuerSerialNumber.Issuer
                            IntPtr pIssuer = new IntPtr((long) pIssuerSerial + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ISSUER_SERIAL_NUMBER), "Issuer"));

                            // rgpRecipientEncryptedKeys.RecipientId.IssuerSerialNumber.Issuer.cbData
                            pcbData = new IntPtr((long) pIssuer + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                            Marshal.WriteInt32(pcbData, (int) certInfo.Issuer.cbData);

                            // rgpRecipientEncryptedKeys.RecipientId.IssuerSerialNumber.Issuer.pbData
                            ppbData = new IntPtr((long) pIssuer + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                            Marshal.WriteIntPtr(ppbData, certInfo.Issuer.pbData);

                            // rgpRecipientEncryptedKeys.RecipientId.IssuerSerialNumber.SerialNumber
                            IntPtr pSerialNumber = new IntPtr((long) pIssuerSerial + (long) Marshal.OffsetOf(typeof(CAPI.CERT_ISSUER_SERIAL_NUMBER), "SerialNumber"));

                            // rgpRecipientEncryptedKeys.RecipientId.IssuerSerialNumber.SerialNumber.cbData
                            pcbData = new IntPtr((long) pSerialNumber + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "cbData"));
                            Marshal.WriteInt32(pcbData, (int) certInfo.SerialNumber.cbData);

                            // rgpRecipientEncryptedKeys.RecipientId.IssuerSerialNumber.SerialNumber.pbData
                            ppbData = new IntPtr((long) pSerialNumber + (long) Marshal.OffsetOf(typeof(CAPI.CRYPTOAPI_BLOB), "pbData"));
                            Marshal.WriteIntPtr(ppbData, certInfo.SerialNumber.pbData);
                        }

                        // Bump key agree count.
                        cKeyAgree++;
                        pKeyInfo = new IntPtr((long) pKeyInfo + Marshal.SizeOf(typeof(CAPI.CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO)));
                    }
                    else {
                        // Should never get here!
                        Debug.Assert(false);
                    }
                }
            }
        }
Exemple #6
0
        private static void SetCspParams (AlgorithmIdentifier contentEncryptionAlgorithm, ref CMSG_ENCRYPT_PARAM encryptParam) {

            encryptParam.safeCryptProvHandle = SafeCryptProvHandle.InvalidHandle;
            encryptParam.pvEncryptionAuxInfo = SafeLocalAllocHandle.InvalidHandle;

            // Try with CRYPT_VERIFYCONTEXT
            SafeCryptProvHandle hCryptProv = SafeCryptProvHandle.InvalidHandle;
            if (!CAPI.CryptAcquireContext(ref hCryptProv, IntPtr.Zero, IntPtr.Zero, CAPI.PROV_RSA_FULL, CAPI.CRYPT_VERIFYCONTEXT)) {
                throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            uint algId = X509Utils.OidToAlgId(contentEncryptionAlgorithm.Oid.Value);
            if (algId == CAPI.CALG_RC2 || algId == CAPI.CALG_RC4) {
                CAPI.CMSG_RC2_AUX_INFO auxInfo = new CAPI.CMSG_RC2_AUX_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_RC2_AUX_INFO)));
                uint keyLength = (uint) contentEncryptionAlgorithm.KeyLength;
                if (keyLength == 0) {
                    keyLength = (uint) PkcsUtils.GetMaxKeyLength(hCryptProv, algId);
                }
                auxInfo.dwBitLen = keyLength;
                SafeLocalAllocHandle pvAuxInfo = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_RC2_AUX_INFO))));
                Marshal.StructureToPtr(auxInfo, pvAuxInfo.DangerousGetHandle(), false);
                encryptParam.pvEncryptionAuxInfo = pvAuxInfo;
            }

            encryptParam.safeCryptProvHandle = hCryptProv;
        }
Exemple #7
0
        private unsafe void EncryptContent (CmsRecipientCollection recipients) {
            CMSG_ENCRYPT_PARAM encryptParam = new CMSG_ENCRYPT_PARAM();

            if (recipients.Count < 1)
                throw new CryptographicException(CAPI.CRYPT_E_RECIPIENT_NOT_FOUND);

            foreach (CmsRecipient recipient in recipients) {
                if (recipient.Certificate == null)
                    throw new ArgumentNullException(SecurityResources.GetResourceString("Cryptography_Cms_RecipientCertificateNotFound"));

                if ((PkcsUtils.GetRecipientInfoType(recipient.Certificate) == RecipientInfoType.KeyAgreement) ||
                    (recipient.RecipientIdentifierType == SubjectIdentifierType.SubjectKeyIdentifier))
                    encryptParam.useCms = true;
            }

            if (!encryptParam.useCms) {
                if (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 encodeInfo = new CAPI.CMSG_ENVELOPED_ENCODE_INFO(Marshal.SizeOf(typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO)));
            SafeLocalAllocHandle ceei = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(Marshal.SizeOf(typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO))));

            SetCspParams(this.ContentEncryptionAlgorithm, ref encryptParam);
            encodeInfo.ContentEncryptionAlgorithm.pszObjId = this.ContentEncryptionAlgorithm.Oid.Value;
            //encodeInfo.hCryptProv = encryptParam.safeCryptProvHandle.DangerousGetHandle(); 
            if (encryptParam.pvEncryptionAuxInfo != null && !encryptParam.pvEncryptionAuxInfo.IsInvalid) {
                encodeInfo.pvEncryptionAuxInfo = encryptParam.pvEncryptionAuxInfo.DangerousGetHandle();
            }

            encodeInfo.cRecipients = (uint) recipients.Count;

            List<SafeCertContextHandle> certContexts = null;
            if (encryptParam.useCms) {
                SetCmsRecipientParams(recipients, this.Certificates, this.UnprotectedAttributes, this.ContentEncryptionAlgorithm, ref encryptParam);
                encodeInfo.rgCmsRecipients = encryptParam.rgpRecipients.DangerousGetHandle();
                if (encryptParam.rgCertEncoded != null && !encryptParam.rgCertEncoded.IsInvalid) {
                    encodeInfo.cCertEncoded = (uint) this.Certificates.Count;
                    encodeInfo.rgCertEncoded = encryptParam.rgCertEncoded.DangerousGetHandle();
                }
                if (encryptParam.rgUnprotectedAttr != null && !encryptParam.rgUnprotectedAttr.IsInvalid) {
                    encodeInfo.cUnprotectedAttr = (uint) this.UnprotectedAttributes.Count;
                    encodeInfo.rgUnprotectedAttr = encryptParam.rgUnprotectedAttr.DangerousGetHandle();
                }
            }
            else {
                SetPkcs7RecipientParams(recipients, ref encryptParam, out certContexts);
                encodeInfo.rgpRecipients = encryptParam.rgpRecipients.DangerousGetHandle();
            }

            Marshal.StructureToPtr(encodeInfo, ceei.DangerousGetHandle(), false);

            try {
                SafeCryptMsgHandle safeCryptMsgHandle = CAPI.CryptMsgOpenToEncode(CAPI.X509_ASN_ENCODING | CAPI.PKCS_7_ASN_ENCODING,
                                                                                  0,
                                                                                  CAPI.CMSG_ENVELOPED,
                                                                                  ceei.DangerousGetHandle(),
                                                                                  this.ContentInfo.ContentType.Value,
                                                                                  IntPtr.Zero);
                if (safeCryptMsgHandle == null || safeCryptMsgHandle.IsInvalid)
                    throw new CryptographicException(Marshal.GetLastWin32Error());

                if (m_safeCryptMsgHandle != null && !m_safeCryptMsgHandle.IsInvalid) {
                    m_safeCryptMsgHandle.Dispose();
                }

                m_safeCryptMsgHandle = safeCryptMsgHandle;
            }
            finally {
                Marshal.DestroyStructure(ceei.DangerousGetHandle(), typeof(CAPI.CMSG_ENVELOPED_ENCODE_INFO));
                ceei.Dispose();
            }

            byte[] encodedContent = new byte[0];
            if (String.Compare(this.ContentInfo.ContentType.Value, CAPI.szOID_RSA_data, StringComparison.OrdinalIgnoreCase) == 0) {
                byte[] content = this.ContentInfo.Content;
                fixed (byte * pbContent = content) {
                    CAPI.CRYPTOAPI_BLOB dataBlob = new CAPI.CRYPTOAPI_BLOB();
                    dataBlob.cbData = (uint) content.Length;
                    dataBlob.pbData = new IntPtr(pbContent);
                    if (!CAPI.EncodeObject(new IntPtr(CAPI.X509_OCTET_STRING), new IntPtr(&dataBlob), out encodedContent))
                        throw new CryptographicException(Marshal.GetLastWin32Error());
                }
            }
            else {
                encodedContent = this.ContentInfo.Content;
            }
            if (encodedContent.Length > 0) {
                if (!CAPI.CAPISafe.CryptMsgUpdate(m_safeCryptMsgHandle, encodedContent, (uint) encodedContent.Length, true))
                    throw new CryptographicException(Marshal.GetLastWin32Error());
            }

            // Keep alive
            GC.KeepAlive(encryptParam);
            GC.KeepAlive(recipients);
            GC.KeepAlive(certContexts);
        }
Exemple #8
0
        private static unsafe void SetPkcs7RecipientParams (CmsRecipientCollection recipients,
                                                            ref CMSG_ENCRYPT_PARAM encryptParam,
                                                            out List<SafeCertContextHandle> certContexts) {
            int index = 0;

            // Must read recipients.Count only once to avoid a security issue where another thread
            // could add objects to recipients after we allocate the native buffer, but while we're
            // iterating. That could lead to a buffer overflow
            int numRecipients = recipients.Count;

            certContexts = new List<SafeCertContextHandle>();

            checked {
                uint totalSize = (uint)numRecipients * (uint)Marshal.SizeOf(typeof(IntPtr));
                encryptParam.rgpRecipients = CAPI.LocalAlloc(CAPI.LPTR, new IntPtr(totalSize));

                IntPtr pCertInfo = encryptParam.rgpRecipients.DangerousGetHandle();

                for (index = 0; index < numRecipients; index++) {
                    SafeCertContextHandle certContext = X509Utils.GetCertContext(recipients[index].Certificate);
                    certContexts.Add(certContext);
                    IntPtr dangerousCertContextHandle = certContext.DangerousGetHandle();
                    CAPI.CERT_CONTEXT pCertContext = (CAPI.CERT_CONTEXT) Marshal.PtrToStructure(dangerousCertContextHandle, typeof(CAPI.CERT_CONTEXT));

                    Marshal.WriteIntPtr(pCertInfo, pCertContext.pCertInfo);
                    pCertInfo = new IntPtr((long) pCertInfo + Marshal.SizeOf(typeof(IntPtr)));
                }
                Debug.Assert(index == totalSize / (uint)Marshal.SizeOf(typeof(IntPtr)));
            }
        }