Exemplo n.º 1
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);
                }
            }
        }