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);
                }
            }
Example #2
0
        public static void TestHandle()
        {
            //
            // Ensure that the Handle property returns a valid CER_CONTEXT pointer.
            //
            using (X509Certificate2 c = new X509Certificate2(TestData.MsCertificate))
            {
                IntPtr h = c.Handle;
                unsafe
                {
                    CERT_CONTEXT *pCertContext = (CERT_CONTEXT *)h;

                    // Does the blob data match?
                    int cbCertEncoded = pCertContext->cbCertEncoded;
                    Assert.Equal(TestData.MsCertificate.Length, cbCertEncoded);

                    byte[] pCertEncoded = new byte[cbCertEncoded];
                    Marshal.Copy((IntPtr)(pCertContext->pbCertEncoded), pCertEncoded, 0, cbCertEncoded);
                    Assert.Equal(TestData.MsCertificate, pCertEncoded);

                    // Does the serial number match?
                    CERT_INFO *pCertInfo      = pCertContext->pCertInfo;
                    byte[]     serialNumber   = pCertInfo->SerialNumber.ToByteArray();
                    byte[]     expectedSerial = "b00000000100dd9f3bd08b0aaf11b000000033".HexToByteArray();
                    Assert.Equal(expectedSerial, serialNumber);
                }
            }
        }
Example #3
0
 public unsafe void FindByExtension(string oidValue)
 {
     FindCore(
         delegate(SafeCertContextHandle pCertContext)
     {
         CERT_INFO *pCertInfo           = pCertContext.CertContext->pCertInfo;
         CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(oidValue, pCertInfo->cExtension, pCertInfo->rgExtension);
         GC.KeepAlive(pCertContext);
         return(pCertExtension != null);
     });
 }
Example #4
0
 public unsafe void FindByKeyUsage(X509KeyUsageFlags keyUsage)
 {
     FindCore(
         delegate(SafeCertContextHandle pCertContext)
     {
         CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo;
         X509KeyUsageFlags actual;
         if (!Interop.crypt32.CertGetIntendedKeyUsage(CertEncodingType.All, pCertInfo, out actual, sizeof(X509KeyUsageFlags)))
         {
             return(true);     // no key usage means it is valid for all key usages.
         }
         GC.KeepAlive(pCertContext);
         return((actual & keyUsage) == keyUsage);
     });
 }
Example #5
0
        public unsafe void FindByCertificatePolicy(string oidValue)
        {
            FindCore(
                delegate(SafeCertContextHandle pCertContext)
            {
                CERT_INFO *pCertInfo           = pCertContext.CertContext->pCertInfo;
                CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(Oids.CertPolicies,
                                                                                   pCertInfo->cExtension, pCertInfo->rgExtension);
                if (pCertExtension == null)
                {
                    return(false);
                }

                bool foundMatch         = false;
                byte[] extensionRawData = pCertExtension->Value.ToByteArray();
                if (!extensionRawData.DecodeObjectNoThrow(
                        CryptDecodeObjectStructType.X509_CERT_POLICIES,
                        delegate(void *pvDecoded, int cbDecoded)
                {
                    Debug.Assert(cbDecoded >= sizeof(CERT_POLICIES_INFO));
                    CERT_POLICIES_INFO *pCertPoliciesInfo = (CERT_POLICIES_INFO *)pvDecoded;
                    for (int i = 0; i < pCertPoliciesInfo->cPolicyInfo; i++)
                    {
                        CERT_POLICY_INFO *pCertPolicyInfo = &(pCertPoliciesInfo->rgPolicyInfo[i]);
                        string actual = Marshal.PtrToStringAnsi(pCertPolicyInfo->pszPolicyIdentifier) !;
                        if (oidValue.Equals(actual, StringComparison.OrdinalIgnoreCase))
                        {
                            foundMatch = true;
                            break;
                        }
                    }
                }
                        ))
                {
                    return(false);
                }

                GC.KeepAlive(pCertContext);
                return(foundMatch);
            });
        }
Example #6
0
 internal static unsafe partial bool CertGetIntendedKeyUsage(
     CertEncodingType dwCertEncodingType,
     CERT_INFO *pCertInfo,
     out X509KeyUsageFlags pbKeyUsage,
     int cbKeyUsage);
Example #7
0
        private StorePal CreatedLinkedStoreWithFindResults(X509FindType findType, Object findValue, bool validOnly)
        {
            unsafe
            {
                switch (findType)
                {
                case X509FindType.FindByThumbprint:
                {
                    byte[] thumbPrint = ConfirmedCast <String>(findValue).DecodeHexString();
                    fixed(byte *pThumbPrint = thumbPrint)
                    {
                        CRYPTOAPI_BLOB blob = new CRYPTOAPI_BLOB(thumbPrint.Length, pThumbPrint);

                        return(FindCore(CertFindType.CERT_FIND_HASH, &blob, validOnly));
                    }
                }

                case X509FindType.FindBySubjectName:
                {
                    String subjectName = ConfirmedCast <String>(findValue);
                    fixed(char *pSubjectName = subjectName)
                    {
                        return(FindCore(CertFindType.CERT_FIND_SUBJECT_STR, pSubjectName, validOnly));
                    }
                }

                case X509FindType.FindBySubjectDistinguishedName:
                {
                    String subjectDistinguishedName = ConfirmedCast <String>(findValue);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            String actual = GetCertNameInfo(pCertContext, CertNameType.CERT_NAME_RDN_TYPE, CertNameFlags.None);
                            return subjectDistinguishedName.Equals(actual, StringComparison.OrdinalIgnoreCase);
                        }
                                    ));
                }

                case X509FindType.FindByIssuerName:
                {
                    String issuerName = ConfirmedCast <String>(findValue);
                    fixed(char *pIssuerName = issuerName)
                    {
                        return(FindCore(CertFindType.CERT_FIND_ISSUER_STR, pIssuerName, validOnly));
                    }
                }

                case X509FindType.FindByIssuerDistinguishedName:
                {
                    String issuerDistinguishedName = ConfirmedCast <String>(findValue);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            String actual = GetCertNameInfo(pCertContext, CertNameType.CERT_NAME_RDN_TYPE, CertNameFlags.CERT_NAME_ISSUER_FLAG);
                            return issuerDistinguishedName.Equals(actual, StringComparison.OrdinalIgnoreCase);
                        }
                                    ));
                }

                case X509FindType.FindBySerialNumber:
                {
                    String decimalOrHexString = ConfirmedCast <String>(findValue);

                    // FindBySerialNumber allows the input format to be either in hex or decimal. Since we can't know which one was intended,
                    // it compares against both interpretations and treats a match of either as a successful find.

                    byte[] hexBytes = decimalOrHexString.DecodeHexString();
                    Array.Reverse(hexBytes);           // String is big-endian, BigInteger constructor requires little-endian.
                    BigInteger expected1 = PositiveBigIntegerFromByteArray(hexBytes);

                    BigInteger ten       = new BigInteger(10);
                    BigInteger expected2 = BigInteger.Zero;
                    foreach (char c in decimalOrHexString)
                    {
                        if (c >= '0' && c <= '9')
                        {
                            expected2 = BigInteger.Multiply(expected2, ten);
                            expected2 = BigInteger.Add(expected2, c - '0');
                        }
                    }

                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            byte[] actual = pCertContext.CertContext->pCertInfo->SerialNumber.ToByteArray();
                            BigInteger actualAsBigInteger = PositiveBigIntegerFromByteArray(actual);           // Convert to BigInteger as the comparison must not fail due to spurious leading zeros
                            GC.KeepAlive(pCertContext);
                            return expected1.Equals(actualAsBigInteger) || expected2.Equals(actualAsBigInteger);
                        }
                                    ));
                }

                case X509FindType.FindByTimeValid:
                {
                    DateTime dateTime = ConfirmedCast <DateTime>(findValue);
                    FILETIME fileTime = FILETIME.FromDateTime(dateTime);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            int comparison = Interop.crypt32.CertVerifyTimeValidity(ref fileTime, pCertContext.CertContext->pCertInfo);
                            GC.KeepAlive(pCertContext);
                            return comparison == 0;
                        }
                                    ));
                }

                case X509FindType.FindByTimeNotYetValid:
                {
                    DateTime dateTime = ConfirmedCast <DateTime>(findValue);
                    FILETIME fileTime = FILETIME.FromDateTime(dateTime);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            int comparison = Interop.crypt32.CertVerifyTimeValidity(ref fileTime, pCertContext.CertContext->pCertInfo);
                            GC.KeepAlive(pCertContext);
                            return comparison == -1;
                        }
                                    ));
                }

                case X509FindType.FindByTimeExpired:
                {
                    DateTime dateTime = ConfirmedCast <DateTime>(findValue);
                    FILETIME fileTime = FILETIME.FromDateTime(dateTime);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            int comparison = Interop.crypt32.CertVerifyTimeValidity(ref fileTime, pCertContext.CertContext->pCertInfo);
                            GC.KeepAlive(pCertContext);
                            return comparison == 1;
                        }
                                    ));
                }

                case X509FindType.FindByTemplateName:
                {
                    String expected = ConfirmedCast <String>(findValue);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            // The template name can have 2 different formats: V1 format (<= Win2K) is just a string
                            // V2 format (XP only) can be a friendly name or an OID.
                            // An example of Template Name can be "ClientAuth".

                            bool foundMatch = false;
                            CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo;
                            {
                                CERT_EXTENSION *pV1Template = Interop.crypt32.CertFindExtension(Oids.EnrollCertTypeExtension, pCertInfo->cExtension, pCertInfo->rgExtension);
                                if (pV1Template != null)
                                {
                                    byte[] extensionRawData = pV1Template->Value.ToByteArray();
                                    if (!extensionRawData.DecodeObjectNoThrow(
                                            CryptDecodeObjectStructType.X509_UNICODE_ANY_STRING,
                                            delegate(void *pvDecoded)
                                    {
                                        CERT_NAME_VALUE *pNameValue = (CERT_NAME_VALUE *)pvDecoded;
                                        String actual = Marshal.PtrToStringUni(new IntPtr(pNameValue->Value.pbData));
                                        if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase))
                                        {
                                            foundMatch = true;
                                        }
                                    }))
                                    {
                                        return false;
                                    }
                                }
                            }

                            if (!foundMatch)
                            {
                                CERT_EXTENSION *pV2Template = Interop.crypt32.CertFindExtension(Oids.CertificateTemplate, pCertInfo->cExtension, pCertInfo->rgExtension);
                                if (pV2Template != null)
                                {
                                    byte[] extensionRawData = pV2Template->Value.ToByteArray();
                                    if (!extensionRawData.DecodeObjectNoThrow(
                                            CryptDecodeObjectStructType.X509_CERTIFICATE_TEMPLATE,
                                            delegate(void *pvDecoded)
                                    {
                                        CERT_TEMPLATE_EXT *pTemplateExt = (CERT_TEMPLATE_EXT *)pvDecoded;
                                        String actual = Marshal.PtrToStringAnsi(pTemplateExt->pszObjId);
                                        String expectedOidValue = OidInfo.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_NAME_KEY, expected, OidGroup.Template, fallBackToAllGroups: true).OID;
                                        if (expectedOidValue == null)
                                        {
                                            expectedOidValue = expected;
                                        }
                                        if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase))
                                        {
                                            foundMatch = true;
                                        }
                                    }))
                                    {
                                        return false;
                                    }
                                }
                            }

                            GC.KeepAlive(pCertContext);
                            return foundMatch;
                        }));
                }

                case X509FindType.FindByApplicationPolicy:
                {
                    String expected = ConfirmedOidValue(findValue, OidGroup.Policy);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            int numOids;
                            int cbData = 0;
                            if (!Interop.crypt32.CertGetValidUsages(1, ref pCertContext, out numOids, null, ref cbData))
                            {
                                return false;
                            }

                            // -1 means the certificate is good for all usages.
                            if (numOids == -1)
                            {
                                return true;
                            }

                            fixed(byte *pOidsPointer = new byte[cbData])
                            {
                                if (!Interop.crypt32.CertGetValidUsages(1, ref pCertContext, out numOids, pOidsPointer, ref cbData))
                                {
                                    return false;
                                }

                                IntPtr *pOids = (IntPtr *)pOidsPointer;
                                for (int i = 0; i < numOids; i++)
                                {
                                    String actual = Marshal.PtrToStringAnsi(pOids[i]);
                                    if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase))
                                    {
                                        return true;
                                    }
                                }
                                return false;
                            }
                        }
                                    ));
                }

                case X509FindType.FindByCertificatePolicy:
                {
                    String expected = ConfirmedOidValue(findValue, OidGroup.Policy);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo;
                            CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(Oids.CertPolicies, pCertInfo->cExtension, pCertInfo->rgExtension);
                            if (pCertExtension == null)
                            {
                                return false;
                            }

                            bool foundMatch = false;
                            byte[] extensionRawData = pCertExtension->Value.ToByteArray();
                            if (!extensionRawData.DecodeObjectNoThrow(
                                    CryptDecodeObjectStructType.X509_CERT_POLICIES,
                                    delegate(void *pvDecoded)
                            {
                                CERT_POLICIES_INFO *pCertPoliciesInfo = (CERT_POLICIES_INFO *)pvDecoded;
                                for (int i = 0; i < pCertPoliciesInfo->cPolicyInfo; i++)
                                {
                                    CERT_POLICY_INFO *pCertPolicyInfo = &(pCertPoliciesInfo->rgPolicyInfo[i]);
                                    String actual = Marshal.PtrToStringAnsi(pCertPolicyInfo->pszPolicyIdentifier);
                                    if (expected.Equals(actual, StringComparison.OrdinalIgnoreCase))
                                    {
                                        foundMatch = true;
                                        break;
                                    }
                                }
                            }
                                    ))
                            {
                                return false;
                            }

                            GC.KeepAlive(pCertContext);
                            return foundMatch;
                        }
                                    ));
                }

                case X509FindType.FindByExtension:
                {
                    String oidValue = ConfirmedOidValue(findValue, OidGroup.ExtensionOrAttribute);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo;
                            CERT_EXTENSION *pCertExtension = Interop.crypt32.CertFindExtension(oidValue, pCertInfo->cExtension, pCertInfo->rgExtension);
                            GC.KeepAlive(pCertContext);
                            return pCertExtension != null;
                        }
                                    ));
                }

                case X509FindType.FindByKeyUsage:
                {
                    X509KeyUsageFlags expected = ConfirmedX509KeyUsage(findValue);
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo;
                            X509KeyUsageFlags actual;
                            if (!Interop.crypt32.CertGetIntendedKeyUsage(CertEncodingType.All, pCertInfo, out actual, sizeof(X509KeyUsageFlags)))
                            {
                                return true;          // no key usage means it is valid for all key usages.
                            }
                            GC.KeepAlive(pCertContext);
                            return (actual & expected) == expected;
                        }
                                    ));
                }

                case X509FindType.FindBySubjectKeyIdentifier:
                {
                    byte[] expected = ConfirmedCast <String>(findValue).DecodeHexString();
                    return(FindCore(validOnly,
                                    delegate(SafeCertContextHandle pCertContext)
                        {
                            int cbData = 0;
                            if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_IDENTIFIER_PROP_ID, null, ref cbData))
                            {
                                return false;
                            }

                            byte[] actual = new byte[cbData];
                            if (!Interop.crypt32.CertGetCertificateContextProperty(pCertContext, CertContextPropId.CERT_KEY_IDENTIFIER_PROP_ID, actual, ref cbData))
                            {
                                return false;
                            }

                            return expected.ContentsEqual(actual);
                        }
                                    ));
                }

                default:
                    throw new CryptographicException(SR.Cryptography_X509_InvalidFindType);
                }
            }
        }
Example #8
0
 public static unsafe partial int CertVerifyTimeValidity(ref FILETIME pTimeToVerify, CERT_INFO *pCertInfo);
Example #9
0
 public static extern unsafe bool CertGetIntendedKeyUsage(CertEncodingType dwCertEncodingType, CERT_INFO *pCertInfo, out X509KeyUsageFlags pbKeyUsage, int cbKeyUsage);
Example #10
0
 public static extern unsafe int CertVerifyTimeValidity([In] ref FILETIME pTimeToVerify, [In] CERT_INFO *pCertInfo);
Example #11
0
 public static extern int WTHelperCertIsSelfSigned([NativeTypeName("DWORD")] uint dwEncoding, [NativeTypeName("CERT_INFO *")] CERT_INFO *pCert);
Example #12
0
        public unsafe void FindByTemplateName(string templateName)
        {
            FindCore(
                delegate(SafeCertContextHandle pCertContext)
            {
                // The template name can have 2 different formats: V1 format (<= Win2K) is just a string
                // V2 format (XP only) can be a friendly name or an OID.
                // An example of Template Name can be "ClientAuth".

                bool foundMatch      = false;
                CERT_INFO *pCertInfo = pCertContext.CertContext->pCertInfo;
                {
                    CERT_EXTENSION *pV1Template = Interop.crypt32.CertFindExtension(Oids.EnrollCertTypeExtension,
                                                                                    pCertInfo->cExtension, pCertInfo->rgExtension);
                    if (pV1Template != null)
                    {
                        byte[] extensionRawData = pV1Template->Value.ToByteArray();
                        if (!extensionRawData.DecodeObjectNoThrow(
                                CryptDecodeObjectStructType.X509_UNICODE_ANY_STRING,
                                delegate(void *pvDecoded, int cbDecoded)
                        {
                            Debug.Assert(cbDecoded >= sizeof(CERT_NAME_VALUE));
                            CERT_NAME_VALUE *pNameValue = (CERT_NAME_VALUE *)pvDecoded;
                            string?actual = Marshal.PtrToStringUni(new IntPtr(pNameValue->Value.pbData));
                            if (templateName.Equals(actual, StringComparison.OrdinalIgnoreCase))
                            {
                                foundMatch = true;
                            }
                        }))
                        {
                            return(false);
                        }
                    }
                }

                if (!foundMatch)
                {
                    CERT_EXTENSION *pV2Template = Interop.crypt32.CertFindExtension(Oids.CertificateTemplate,
                                                                                    pCertInfo->cExtension, pCertInfo->rgExtension);
                    if (pV2Template != null)
                    {
                        byte[] extensionRawData = pV2Template->Value.ToByteArray();
                        if (!extensionRawData.DecodeObjectNoThrow(
                                CryptDecodeObjectStructType.X509_CERTIFICATE_TEMPLATE,
                                delegate(void *pvDecoded, int cbDecoded)
                        {
                            Debug.Assert(cbDecoded >= sizeof(CERT_TEMPLATE_EXT));
                            CERT_TEMPLATE_EXT *pTemplateExt = (CERT_TEMPLATE_EXT *)pvDecoded;
                            string?actual = Marshal.PtrToStringAnsi(pTemplateExt->pszObjId);
                            string?expectedOidValue =
                                Interop.Crypt32.FindOidInfo(CryptOidInfoKeyType.CRYPT_OID_INFO_NAME_KEY, templateName,
                                                            OidGroup.Template, fallBackToAllGroups: true).OID;
                            if (expectedOidValue == null)
                            {
                                expectedOidValue = templateName;
                            }
                            if (expectedOidValue.Equals(actual, StringComparison.OrdinalIgnoreCase))
                            {
                                foundMatch = true;
                            }
                        }))
                        {
                            return(false);
                        }
                    }
                }

                GC.KeepAlive(pCertContext);
                return(foundMatch);
            });
        }
Example #13
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 CERT_ID EncodeRecipientId(CmsRecipient recipient, SafeCertContextHandle hCertContext, CERT_CONTEXT *pCertContext, CERT_INFO *pCertInfo, HeapBlockRetainer hb)
            {
                CERT_ID recipientId        = default(CERT_ID);
                SubjectIdentifierType type = recipient.RecipientIdentifierType;

                switch (type)
                {
                case SubjectIdentifierType.IssuerAndSerialNumber:
                {
                    recipientId.dwIdChoice = CertIdChoice.CERT_ID_ISSUER_SERIAL_NUMBER;
                    recipientId.u.IssuerSerialNumber.Issuer       = pCertInfo->Issuer;
                    recipientId.u.IssuerSerialNumber.SerialNumber = pCertInfo->SerialNumber;
                    break;
                }

                case SubjectIdentifierType.SubjectKeyIdentifier:
                {
                    byte[] ski  = hCertContext.GetSubjectKeyIdentifer();
                    IntPtr pSki = hb.AllocBytes(ski);

                    recipientId.dwIdChoice     = CertIdChoice.CERT_ID_KEY_IDENTIFIER;
                    recipientId.u.KeyId.cbData = (uint)(ski.Length);
                    recipientId.u.KeyId.pbData = pSki;
                    break;
                }

                default:
                    // The public contract for CmsRecipient guarantees that SubjectKeyIdentifier and IssuerAndSerialNumber are the only two possibilities.
                    Debug.Fail($"Unexpected SubjectIdentifierType: {type}");
                    throw new NotSupportedException(SR.Format(SR.Cryptography_Cms_Invalid_Subject_Identifier_Type, type));
                }

                return(recipientId);
            }
Example #14
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_AGREE_RECIPIENT_ENCODE_INFO *EncodeKeyAgreeRecipientInfo(CmsRecipient recipient, AlgorithmIdentifier contentEncryptionAlgorithm, 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 without
                // bringing in all the SafeCertContextHandle machinery, and embed pointers to them in the memory block we return. Yes, this code is scary.
                using (SafeCertContextHandle hCertContext = recipient.Certificate.CreateCertContextHandle())
                {
                    CERT_CONTEXT *pCertContext = hCertContext.DangerousGetCertContext();
                    CERT_INFO *   pCertInfo    = pCertContext->pCertInfo;

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

                    pEncodeInfo->cbSize = sizeof(CMSG_KEY_AGREE_RECIPIENT_ENCODE_INFO);

                    pEncodeInfo->KeyEncryptionAlgorithm.pszObjId          = hb.AllocAsciiString(Oids.Esdh);
                    pEncodeInfo->KeyEncryptionAlgorithm.Parameters.cbData = 0;
                    pEncodeInfo->KeyEncryptionAlgorithm.Parameters.pbData = IntPtr.Zero;

                    pEncodeInfo->pvKeyEncryptionAuxInfo = null;

                    string oidValue;
                    AlgId  algId = contentEncryptionAlgorithm.Oid.Value.ToAlgId();
                    if (algId == AlgId.CALG_RC2)
                    {
                        oidValue = Oids.CmsRc2Wrap;
                    }
                    else
                    {
                        oidValue = Oids.Cms3DesWrap;
                    }

                    pEncodeInfo->KeyWrapAlgorithm.pszObjId          = hb.AllocAsciiString(oidValue);
                    pEncodeInfo->KeyWrapAlgorithm.Parameters.cbData = 0;
                    pEncodeInfo->KeyWrapAlgorithm.Parameters.pbData = IntPtr.Zero;

                    pEncodeInfo->pvKeyWrapAuxInfo = GenerateEncryptionAuxInfoIfNeeded(contentEncryptionAlgorithm, hb);

                    pEncodeInfo->hCryptProv             = IntPtr.Zero;
                    pEncodeInfo->dwKeySpec              = 0;
                    pEncodeInfo->dwKeyChoice            = CmsKeyAgreeKeyChoice.CMSG_KEY_AGREE_EPHEMERAL_KEY_CHOICE;
                    pEncodeInfo->pEphemeralAlgorithm    = (CRYPT_ALGORITHM_IDENTIFIER *)(hb.Alloc(sizeof(CRYPT_ALGORITHM_IDENTIFIER)));
                    *(pEncodeInfo->pEphemeralAlgorithm) = pCertInfo->SubjectPublicKeyInfo.Algorithm;

                    pEncodeInfo->UserKeyingMaterial.cbData = 0;
                    pEncodeInfo->UserKeyingMaterial.pbData = IntPtr.Zero;

                    CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *pEncryptedKey = (CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *)(hb.Alloc(sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO)));

                    pEncryptedKey->cbSize             = sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO);
                    pEncryptedKey->RecipientPublicKey = pCertInfo->SubjectPublicKeyInfo.PublicKey;

                    pEncryptedKey->RecipientId = EncodeRecipientId(recipient, hCertContext, pCertContext, pCertInfo, hb);
                    pEncryptedKey->Date        = default(FILETIME);
                    pEncryptedKey->pOtherAttr  = null;

                    CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO **ppEncryptedKey = (CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO **)(hb.Alloc(sizeof(CMSG_RECIPIENT_ENCRYPTED_KEY_ENCODE_INFO *)));
                    ppEncryptedKey[0] = pEncryptedKey;
                    pEncodeInfo->cRecipientEncryptedKeys   = 1;
                    pEncodeInfo->rgpRecipientEncryptedKeys = ppEncryptedKey;

                    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 #16
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);
                }
            }