Example #1
0
            //
            // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb".
            //
            private static unsafe CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *EncodeKeyTransRecipientInfo(CmsRecipient recipient, HeapBlockRetainer hb)
            {
                // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers
                // and embed pointers to them in the memory block we return. Yes, this code is scary.
                //
                // (The use of SafeCertContextHandle here is about using a consistent pattern to get the CERT_CONTEXT (rather than the ugly (CERT_CONTEXT*)(recipient.Certificate.Handle) pattern.)
                // It's not about keeping the context alive.)
                using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle())
                {
                    CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext();
                    CERT_INFO *   pCertInfo    = pCertContext->pCertInfo;

                    CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)));

                    pEncodeInfo->cbSize = sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO);

                    CRYPT_ALGORITHM_IDENTIFIER algId = pCertInfo->SubjectPublicKeyInfo.Algorithm;
                    pEncodeInfo->KeyEncryptionAlgorithm = algId;

                    pEncodeInfo->pvKeyEncryptionAuxInfo = IntPtr.Zero;
                    pEncodeInfo->hCryptProv             = IntPtr.Zero;

                    pEncodeInfo->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey;

                    pEncodeInfo->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb);

                    return(pEncodeInfo);
                }
            }
            //
            // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb".
            //
            private static unsafe CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *EncodeKeyTransRecipientInfo(CmsRecipient recipient, HeapBlockRetainer hb)
            {
                // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers
                // and embed pointers to them in the memory block we return. Yes, this code is scary.
                //
                // (The use of SafeCertContextHandle here is about using a consistent pattern to get the CERT_CONTEXT (rather than the ugly (CERT_CONTEXT*)(recipient.Certificate.Handle) pattern.)
                // It's not about keeping the context alive.)
                using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle())
                {
                    CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext();
                    CERT_INFO *   pCertInfo    = pCertContext->pCertInfo;

                    CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)));

                    pEncodeInfo->cbSize = sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO);

                    if (recipient.RSAEncryptionPadding is null)
                    {
                        CRYPT_ALGORITHM_IDENTIFIER algId = pCertInfo->SubjectPublicKeyInfo.Algorithm;
                        pEncodeInfo->KeyEncryptionAlgorithm = algId;
                    }
                    else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.Pkcs1)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.Rsa);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaPkcsParameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaPkcsParameters);
                    }
                    else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA1)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha1Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha1Parameters);
                    }
                    else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA256)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha256Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha256Parameters);
                    }
                    else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA384)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha384Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha384Parameters);
                    }
                    else if (recipient.RSAEncryptionPadding == RSAEncryptionPadding.OaepSHA512)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha512Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha512Parameters);
                    }
                    else
                    {
                        throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException();
                    }

                    pEncodeInfo->pvKeyEncryptionAuxInfo = IntPtr.Zero;
                    pEncodeInfo->hCryptProv             = IntPtr.Zero;

                    pEncodeInfo->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey;

                    pEncodeInfo->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb);

                    return(pEncodeInfo);
                }
            }
Example #3
0
            //
            // This returns an allocated native memory block. Its lifetime (and that of any allocated subblocks it may point to) is that of "hb".
            //
            private static unsafe CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *EncodeKeyTransRecipientInfo(CmsRecipient recipient, HeapBlockRetainer hb)
            {
                // "recipient" is a deep-cloned CmsRecipient object whose lifetime this class controls. Because of this, we can pull out the CERT_CONTEXT* and CERT_INFO* pointers
                // and embed pointers to them in the memory block we return. Yes, this code is scary.
                //
                // (The use of SafeCertContextHandle here is about using a consistent pattern to get the CERT_CONTEXT (rather than the ugly (CERT_CONTEXT*)(recipient.Certificate.Handle) pattern.)
                // It's not about keeping the context alive.)
                using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle())
                {
                    CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext();
                    CERT_INFO *   pCertInfo    = pCertContext->pCertInfo;

                    CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *pEncodeInfo = (CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO)));

                    pEncodeInfo->cbSize = sizeof(CMSG_KEY_TRANS_RECIPIENT_ENCODE_INFO);

                    RSAEncryptionPadding padding = recipient.RSAEncryptionPadding;

                    if (padding is null)
                    {
                        if (recipient.Certificate.GetKeyAlgorithm() == Oids.RsaOaep)
                        {
                            byte[] parameters = recipient.Certificate.GetKeyAlgorithmParameters();

                            if (parameters == null || parameters.Length == 0)
                            {
                                padding = RSAEncryptionPadding.OaepSHA1;
                            }
                            else if (!PkcsHelpers.TryGetRsaOaepEncryptionPadding(parameters, out padding, out _))
                            {
                                throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException();
                            }
                        }
                        else
                        {
                            // gost falls in here
                            padding = RSAEncryptionPadding.Pkcs1;
                        }
                    }

                    if (padding == RSAEncryptionPadding.Pkcs1)
                    {
                        // begin: gost
                        switch (recipient.Certificate.GetKeyAlgorithm())
                        {
                        case Oids.Gost3410:
                        case Oids.Gost3410_2012_256:
                        case Oids.Gost3410_2012_512:
                        {
                            // copy from cert info explicitly
                            pEncodeInfo->KeyEncryptionAlgorithm.pszObjId = hb.AllocAsciiString(recipient.Certificate.GetKeyAlgorithm());

                            // uint, копируем
                            pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData;

                            // копируем из памяти и записываем
                            var pbDataBytes = new byte[pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.cbData];
                            Marshal.Copy(pCertInfo->SubjectPublicKeyInfo.Algorithm.Parameters.pbData, pbDataBytes, 0, pbDataBytes.Length);
                            pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(pbDataBytes);
                            break;
                        }

                        default:
                        {
                            // end: gost
                            pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.Rsa);
                            pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaPkcsParameters.Length;
                            pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaPkcsParameters);
                            break;
                        }
                        }
                    }
                    else if (padding == RSAEncryptionPadding.OaepSHA1)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha1Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha1Parameters);
                    }
                    else if (padding == RSAEncryptionPadding.OaepSHA256)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha256Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha256Parameters);
                    }
                    else if (padding == RSAEncryptionPadding.OaepSHA384)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha384Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha384Parameters);
                    }
                    else if (padding == RSAEncryptionPadding.OaepSHA512)
                    {
                        pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.RsaOaep);
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = (uint)s_rsaOaepSha512Parameters.Length;
                        pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = hb.AllocBytes(s_rsaOaepSha512Parameters);
                    }
                    else
                    {
                        throw ErrorCode.CRYPT_E_UNKNOWN_ALGO.ToCryptographicException();
                    }

                    pEncodeInfo->pvKeyEncryptionAuxInfo = IntPtr.Zero;
                    pEncodeInfo->hCryptProv             = IntPtr.Zero;

                    pEncodeInfo->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey;

                    pEncodeInfo->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb);

                    return(pEncodeInfo);
                }
            }