private static SafeChainEngineHandle GetChainEngine(
            X509ChainTrustMode trustMode,
            X509Certificate2Collection?customTrustStore,
            bool useMachineContext)
        {
            SafeChainEngineHandle chainEngineHandle;

            if (trustMode == X509ChainTrustMode.CustomRootTrust)
            {
                // Need to get a valid SafeCertStoreHandle otherwise the default stores will be trusted
                using (SafeCertStoreHandle customTrustStoreHandle = ConvertStoreToSafeHandle(customTrustStore, true))
                {
                    CERT_CHAIN_ENGINE_CONFIG customChainEngine = default;
                    customChainEngine.cbSize         = Marshal.SizeOf <CERT_CHAIN_ENGINE_CONFIG>();
                    customChainEngine.hExclusiveRoot = customTrustStoreHandle.DangerousGetHandle();
                    chainEngineHandle = Interop.crypt32.CertCreateCertificateChainEngine(ref customChainEngine);
                }
            }
            else
            {
                chainEngineHandle = useMachineContext ? SafeChainEngineHandle.MachineChainEngine : SafeChainEngineHandle.UserChainEngine;
            }

            return(chainEngineHandle);
        }
예제 #2
0
        internal static partial IChainPal?BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection?applicationPolicy,
            OidCollection?certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection?customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout,
            bool disableAia)
        {
            var chainPal = new AndroidCertPath();

            try
            {
                chainPal.Initialize(cert, extraStore, customTrustStore, trustMode);
                chainPal.Evaluate(verificationTime, applicationPolicy, certificatePolicy, revocationMode, revocationFlag);
            }
            catch
            {
                chainPal.Dispose();
                throw;
            }

            return(chainPal);
        }
        /// <summary>
        /// Does not throw on error. Returns null ChainPal instead.
        /// </summary>
        public static ChainPal?BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection?applicationPolicy,
            OidCollection?certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection?customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout,
            bool disableAia)
        {
            CertificatePal certificatePal = (CertificatePal)cert;

            unsafe
            {
                using (SafeChainEngineHandle storeHandle = GetChainEngine(trustMode, customTrustStore, useMachineContext))
                    using (SafeCertStoreHandle extraStoreHandle = ConvertStoreToSafeHandle(extraStore))
                    {
                        CERT_CHAIN_PARA chainPara = default;
                        chainPara.cbSize = Marshal.SizeOf <CERT_CHAIN_PARA>();

                        int applicationPolicyCount;
                        using (SafeHandle applicationPolicyOids = applicationPolicy !.ToLpstrArray(out applicationPolicyCount))
                        {
                            if (!applicationPolicyOids.IsInvalid)
                            {
                                chainPara.RequestedUsage.dwType = CertUsageMatchType.USAGE_MATCH_TYPE_AND;
                                chainPara.RequestedUsage.Usage.cUsageIdentifier     = applicationPolicyCount;
                                chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = applicationPolicyOids.DangerousGetHandle();
                            }

                            int certificatePolicyCount;
                            using (SafeHandle certificatePolicyOids = certificatePolicy !.ToLpstrArray(out certificatePolicyCount))
                            {
                                if (!certificatePolicyOids.IsInvalid)
                                {
                                    chainPara.RequestedIssuancePolicy.dwType = CertUsageMatchType.USAGE_MATCH_TYPE_AND;
                                    chainPara.RequestedIssuancePolicy.Usage.cUsageIdentifier     = certificatePolicyCount;
                                    chainPara.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = certificatePolicyOids.DangerousGetHandle();
                                }

                                chainPara.dwUrlRetrievalTimeout = (int)Math.Floor(timeout.TotalMilliseconds);

                                FILETIME            ft    = FILETIME.FromDateTime(verificationTime);
                                CertChainFlags      flags = MapRevocationFlags(revocationMode, revocationFlag, disableAia);
                                SafeX509ChainHandle chain;
                                if (!Interop.crypt32.CertGetCertificateChain(storeHandle.DangerousGetHandle(), certificatePal.CertContext, &ft, extraStoreHandle, ref chainPara, flags, IntPtr.Zero, out chain))
                                {
                                    return(null);
                                }

                                return(new ChainPal(chain));
                            }
                        }
                    }
            }
        }
예제 #4
0
        private SafeCreateHandle PrepareCertsArray(
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            X509Certificate2Collection customTrustStore,
            X509ChainTrustMode trustMode)
        {
            List <SafeHandle> safeHandles = new List <SafeHandle> {
                ((AppleCertificatePal)cert).CertificateHandle
            };

            if (extraStore != null)
            {
                for (int i = 0; i < extraStore.Count; i++)
                {
                    safeHandles.Add(((AppleCertificatePal)extraStore[i].Pal).CertificateHandle);
                }
            }

            if (trustMode == X509ChainTrustMode.CustomRootTrust && customTrustStore != null)
            {
                for (int i = 0; i < customTrustStore.Count; i++)
                {
                    // Only adds non self issued certs to the untrusted certs array. Trusted self signed
                    // certs will be added to the custom certs array.
                    if (!customTrustStore[i].SubjectName.RawData.ContentsEqual(customTrustStore[i].IssuerName.RawData))
                    {
                        safeHandles.Add(((AppleCertificatePal)customTrustStore[i].Pal).CertificateHandle);
                    }
                }
            }

            return(GetCertsArray(safeHandles));
        }
예제 #5
0
 public void Reset()
 {
     _applicationPolicy  = null;
     _certificatePolicy  = null;
     _extraStore         = null;
     _customTrustStore   = null;
     _revocationMode     = X509RevocationMode.Online;
     _revocationFlag     = X509RevocationFlag.ExcludeRoot;
     _verificationFlags  = X509VerificationFlags.NoFlag;
     _trustMode          = X509ChainTrustMode.System;
     VerificationTime    = DateTime.Now;
     UrlRetrievalTimeout = TimeSpan.Zero; // default timeout
 }
예제 #6
0
파일: ChainPal.cs 프로젝트: z77ma/runtime
 internal static partial IChainPal?BuildChain(
     bool useMachineContext,
     ICertificatePal cert,
     X509Certificate2Collection?extraStore,
     OidCollection?applicationPolicy,
     OidCollection?certificatePolicy,
     X509RevocationMode revocationMode,
     X509RevocationFlag revocationFlag,
     X509Certificate2Collection?customTrustStore,
     X509ChainTrustMode trustMode,
     DateTime verificationTime,
     TimeSpan timeout,
     bool disableAia);
예제 #7
0
        public static IChainPal BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection applicationPolicy,
            OidCollection certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout)
        {
            // If the time was given in Universal, it will stay Universal.
            // If the time was given in Local, it will be converted.
            // If the time was given in Unspecified, it will be assumed local, and converted.
            //
            // This matches the "assume Local unless explicitly Universal" implicit contract.
            verificationTime = verificationTime.ToUniversalTime();

            // The Windows (and other-Unix-PAL) behavior is to allow network until network operations
            // have exceeded the specified timeout.  For Apple it's either on (and AIA fetching works),
            // or off (and AIA fetching doesn't work).  And once an SSL policy is used, or revocation is
            // being checked, the value is on anyways.
            const bool       allowNetwork = true;
            SecTrustChainPal chainPal     = new SecTrustChainPal();

            try
            {
                chainPal.OpenTrustHandle(
                    cert,
                    extraStore,
                    revocationMode,
                    customTrustStore,
                    trustMode);

                chainPal.Execute(
                    verificationTime,
                    allowNetwork,
                    applicationPolicy,
                    certificatePolicy,
                    revocationFlag);
            }
            catch
            {
                chainPal.Dispose();
                throw;
            }

            return(chainPal);
        }
예제 #8
0
        internal static OpenSslX509ChainProcessor InitiateChain(
            SafeX509Handle leafHandle,
            X509Certificate2Collection customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan remainingDownloadTime)
        {
            CachedSystemStoreProvider.GetNativeCollections(
                out SafeX509StackHandle systemTrust,
                out SafeX509StackHandle systemIntermediate);

            SafeX509StoreHandle    store     = null;
            SafeX509StackHandle    untrusted = null;
            SafeX509StoreCtxHandle storeCtx  = null;

            try
            {
                untrusted = Interop.Crypto.NewX509Stack();
                Interop.Crypto.X509StackAddMultiple(untrusted, s_userIntermediateStore.GetNativeCollection());
                Interop.Crypto.X509StackAddMultiple(untrusted, s_userPersonalStore.GetNativeCollection());

                store = GetTrustStore(trustMode, customTrustStore, untrusted, systemTrust);

                Interop.Crypto.X509StackAddMultiple(untrusted, systemIntermediate);
                Interop.Crypto.X509StoreSetVerifyTime(store, verificationTime);

                storeCtx = Interop.Crypto.X509StoreCtxCreate();

                if (!Interop.Crypto.X509StoreCtxInit(storeCtx, store, leafHandle, untrusted))
                {
                    throw Interop.Crypto.CreateOpenSslCryptographicException();
                }

                return(new OpenSslX509ChainProcessor(
                           leafHandle,
                           store,
                           untrusted,
                           storeCtx,
                           verificationTime,
                           remainingDownloadTime));
            }
            catch
            {
                store?.Dispose();
                untrusted?.Dispose();
                storeCtx?.Dispose();
                throw;
            }
        }
예제 #9
0
 public static IChainPal BuildChain(
     bool useMachineContext,
     ICertificatePal cert,
     X509Certificate2Collection?extraStore,
     OidCollection applicationPolicy,
     OidCollection certificatePolicy,
     X509RevocationMode revocationMode,
     X509RevocationFlag revocationFlag,
     X509Certificate2Collection customTrustStore,
     X509ChainTrustMode trustMode,
     DateTime verificationTime,
     TimeSpan timeout,
     bool disableAia)
 {
     throw new NotImplementedException(nameof(BuildChain));
 }
예제 #10
0
 internal static partial IChainPal?BuildChain(
     bool useMachineContext,
     ICertificatePal cert,
     X509Certificate2Collection?extraStore,
     OidCollection?applicationPolicy,
     OidCollection?certificatePolicy,
     X509RevocationMode revocationMode,
     X509RevocationFlag revocationFlag,
     X509Certificate2Collection?customTrustStore,
     X509ChainTrustMode trustMode,
     DateTime verificationTime,
     TimeSpan timeout,
     bool disableAia)
 {
     throw new PlatformNotSupportedException(SR.SystemSecurityCryptographyX509Certificates_PlatformNotSupported);
 }
예제 #11
0
        public static IChainPal BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection applicationPolicy,
            OidCollection certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout,
            bool disableAia)
        {
            // If the time was given in Universal, it will stay Universal.
            // If the time was given in Local, it will be converted.
            // If the time was given in Unspecified, it will be assumed local, and converted.
            //
            // This matches the "assume Local unless explicitly Universal" implicit contract.
            verificationTime = verificationTime.ToUniversalTime();

            SecTrustChainPal chainPal = new SecTrustChainPal();

            try
            {
                chainPal.OpenTrustHandle(
                    cert,
                    extraStore,
                    revocationMode,
                    customTrustStore,
                    trustMode);

                chainPal.Execute(
                    verificationTime,
                    !disableAia,
                    applicationPolicy,
                    certificatePolicy,
                    revocationFlag);
            }
            catch
            {
                chainPal.Dispose();
                throw;
            }

            return(chainPal);
        }
예제 #12
0
        internal static partial IChainPal?BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection?applicationPolicy,
            OidCollection?certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection?customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout,
            bool disableAia)
        {
            if (OpenSslX509ChainEventSource.Log.IsEnabled())
            {
                OpenSslX509ChainEventSource.Log.ChainStart();
            }

            try
            {
                return(BuildChainCore(
                           useMachineContext,
                           cert,
                           extraStore,
                           applicationPolicy,
                           certificatePolicy,
                           revocationMode,
                           revocationFlag,
                           customTrustStore,
                           trustMode,
                           verificationTime,
                           timeout,
                           disableAia));
            }
            finally
            {
                if (OpenSslX509ChainEventSource.Log.IsEnabled())
                {
                    OpenSslX509ChainEventSource.Log.ChainStop();
                }
            }
        }
예제 #13
0
        private static SafeX509StoreHandle GetTrustStore(
            X509ChainTrustMode trustMode,
            X509Certificate2Collection customTrustStore,
            SafeX509StackHandle untrusted,
            SafeX509StackHandle systemTrust)
        {
            if (trustMode == X509ChainTrustMode.CustomRootTrust)
            {
                using (SafeX509StackHandle customTrust = Interop.Crypto.NewX509Stack())
                {
                    foreach (X509Certificate2 cert in customTrustStore)
                    {
                        SafeX509StackHandle toAdd = cert.SubjectName.RawData.ContentsEqual(cert.IssuerName.RawData) ? customTrust : untrusted;
                        AddToStackAndUpRef(((OpenSslX509CertificateReader)cert.Pal).SafeHandle, toAdd);
                    }

                    return(Interop.Crypto.X509ChainNew(customTrust, SafeX509StackHandle.InvalidHandle));
                }
            }

            return(Interop.Crypto.X509ChainNew(systemTrust, s_userRootStore.GetNativeCollection()));
        }
예제 #14
0
        public static IChainPal BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection applicationPolicy,
            OidCollection certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout)
        {
            // An input value of 0 on the timeout is "take all the time you need".
            if (timeout == TimeSpan.Zero)
            {
                timeout = TimeSpan.MaxValue;
            }

            // Let Unspecified mean Local, so only convert if the source was UTC.
            //
            // Converge on Local instead of UTC because OpenSSL is going to assume we gave it
            // local time.
            if (verificationTime.Kind == DateTimeKind.Utc)
            {
                verificationTime = verificationTime.ToLocalTime();
            }

            // Until we support the Disallowed store, ensure it's empty (which is done by the ctor)
            using (new X509Store(StoreName.Disallowed, StoreLocation.CurrentUser, OpenFlags.ReadOnly))
            {
            }

            TimeSpan remainingDownloadTime = timeout;

            OpenSslX509ChainProcessor chainPal = OpenSslX509ChainProcessor.InitiateChain(
                ((OpenSslX509CertificateReader)cert).SafeHandle,
                customTrustStore,
                trustMode,
                verificationTime,
                remainingDownloadTime);

            Interop.Crypto.X509VerifyStatusCode status = chainPal.FindFirstChain(extraStore);

            if (!OpenSslX509ChainProcessor.IsCompleteChain(status))
            {
                List <X509Certificate2>?tmp = null;
                status = chainPal.FindChainViaAia(ref tmp);

                if (tmp != null)
                {
                    if (status == Interop.Crypto.X509VerifyStatusCode.X509_V_OK)
                    {
                        SaveIntermediateCertificates(tmp);
                    }

                    foreach (X509Certificate2 downloaded in tmp)
                    {
                        downloaded.Dispose();
                    }
                }
            }

            // In NoCheck+OK then we don't need to build the chain any more, we already
            // know it's error-free.  So skip straight to finish.
            if (status != Interop.Crypto.X509VerifyStatusCode.X509_V_OK ||
                revocationMode != X509RevocationMode.NoCheck)
            {
                if (OpenSslX509ChainProcessor.IsCompleteChain(status))
                {
                    chainPal.CommitToChain();
                    chainPal.ProcessRevocation(revocationMode, revocationFlag);
                }
            }

            chainPal.Finish(applicationPolicy, certificatePolicy);

#if DEBUG
            if (chainPal.ChainElements !.Length > 0)
            {
                X509Certificate2 reportedLeaf = chainPal.ChainElements[0].Certificate;
                Debug.Assert(reportedLeaf != null, "reportedLeaf != null");
                Debug.Assert(!ReferenceEquals(cert, reportedLeaf.Pal), "!ReferenceEquals(cert, reportedLeaf.Pal)");
            }
#endif
            return(chainPal);
        }
예제 #15
0
        internal void OpenTrustHandle(
            ICertificatePal leafCert,
            X509Certificate2Collection?extraStore,
            X509RevocationMode revocationMode,
            X509Certificate2Collection customTrustStore,
            X509ChainTrustMode trustMode)
        {
            _revocationMode = revocationMode;
            SafeCreateHandle policiesArray = PreparePoliciesArray(revocationMode != X509RevocationMode.NoCheck);
            SafeCreateHandle certsArray    = PrepareCertsArray(leafCert, extraStore, customTrustStore, trustMode);

            int osStatus;

            SafeX509ChainHandle chain;
            int ret = Interop.AppleCrypto.AppleCryptoNative_X509ChainCreate(
                certsArray,
                policiesArray,
                out chain,
                out osStatus);

            if (ret == 1)
            {
                if (trustMode == X509ChainTrustMode.CustomRootTrust)
                {
                    SafeCreateHandle customCertsArray = s_emptyArray;
                    if (customTrustStore != null && customTrustStore.Count > 0)
                    {
                        customCertsArray = PrepareCustomCertsArray(customTrustStore);
                    }

                    try
                    {
                        int error = Interop.AppleCrypto.X509ChainSetTrustAnchorCertificates(chain, customCertsArray);
                        if (error != 0)
                        {
                            throw Interop.AppleCrypto.CreateExceptionForOSStatus(error);
                        }
                    }
                    finally
                    {
                        if (customCertsArray != s_emptyArray)
                        {
                            customCertsArray.Dispose();
                        }
                    }
                }

                _chainHandle = chain;
                return;
            }

            chain.Dispose();

            if (ret == 0)
            {
                throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
            }

            Debug.Fail($"AppleCryptoNative_X509ChainCreate returned unexpected return value {ret}");
            throw new CryptographicException();
        }
예제 #16
0
            internal void Initialize(
                ICertificatePal cert,
                X509Certificate2Collection?extraStore,
                X509Certificate2Collection?customTrustStore,
                X509ChainTrustMode trustMode)
            {
                List <SafeHandle> extraCertHandles = new List <SafeHandle>()
                {
                    ((AndroidCertificatePal)cert).SafeHandle
                };

                if (extraStore != null)
                {
                    foreach (X509Certificate2 extraCert in extraStore)
                    {
                        extraCertHandles.Add(((AndroidCertificatePal)extraCert.Pal).SafeHandle);
                    }
                }

                Debug.Assert(
                    trustMode == X509ChainTrustMode.System || trustMode == X509ChainTrustMode.CustomRootTrust,
                    "Unsupported trust mode. Only System and CustomRootTrust are currently handled");

                List <SafeHandle> customTrustCertHandles = new List <SafeHandle>();
                bool useCustomRootTrust = trustMode == X509ChainTrustMode.CustomRootTrust;

                if (useCustomRootTrust && customTrustStore != null)
                {
                    foreach (X509Certificate2 custom in customTrustStore)
                    {
                        SafeHandle certHandle = ((AndroidCertificatePal)custom.Pal).SafeHandle;
                        if (custom.SubjectName.RawData.ContentsEqual(custom.IssuerName.RawData))
                        {
                            // Add self-issued certs to custom root trust cert
                            customTrustCertHandles.Add(certHandle);
                        }
                        else
                        {
                            // Add non-self-issued certs to extra certs
                            extraCertHandles.Add(certHandle);
                        }
                    }
                }

                int extraIdx  = 0;
                int customIdx = 0;

                try
                {
                    IntPtr[] extraCerts = new IntPtr[extraCertHandles.Count];
                    for (extraIdx = 0; extraIdx < extraCertHandles.Count; extraIdx++)
                    {
                        SafeHandle handle   = extraCertHandles[extraIdx];
                        bool       addedRef = false;
                        handle.DangerousAddRef(ref addedRef);
                        extraCerts[extraIdx] = handle.DangerousGetHandle();
                    }

                    _chainContext = Interop.AndroidCrypto.X509ChainCreateContext(
                        ((AndroidCertificatePal)cert).SafeHandle,
                        extraCerts,
                        extraCerts.Length);

                    if (useCustomRootTrust)
                    {
                        // Android does not support an empty set of trust anchors
                        if (customTrustCertHandles.Count == 0)
                        {
                            throw new PlatformNotSupportedException(SR.Chain_EmptyCustomTrustNotSupported);
                        }

                        IntPtr[] customTrustCerts = new IntPtr[customTrustCertHandles.Count];
                        for (customIdx = 0; customIdx < customTrustCertHandles.Count; customIdx++)
                        {
                            SafeHandle handle   = customTrustCertHandles[customIdx];
                            bool       addedRef = false;
                            handle.DangerousAddRef(ref addedRef);
                            customTrustCerts[customIdx] = handle.DangerousGetHandle();
                        }

                        int res = Interop.AndroidCrypto.X509ChainSetCustomTrustStore(_chainContext, customTrustCerts, customTrustCerts.Length);
                        if (res != 1)
                        {
                            throw new CryptographicException();
                        }
                    }
                }
                finally
                {
                    for (extraIdx -= 1; extraIdx >= 0; extraIdx--)
                    {
                        extraCertHandles[extraIdx].DangerousRelease();
                    }

                    for (customIdx -= 1; customIdx >= 0; customIdx--)
                    {
                        customTrustCertHandles[customIdx].DangerousRelease();
                    }
                }
            }
예제 #17
0
        private static IChainPal?BuildChainCore(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection?applicationPolicy,
            OidCollection?certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection?customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout,
            bool disableAia)
        {
            if (timeout == TimeSpan.Zero)
            {
                // An input value of 0 on the timeout is treated as 15 seconds, to match Windows.
                timeout = TimeSpan.FromSeconds(15);
            }
            else if (timeout > s_maxUrlRetrievalTimeout || timeout < TimeSpan.Zero)
            {
                // Windows has a max timeout of 1 minute, so we'll match. Windows also treats
                // the timeout as unsigned, so a negative value gets treated as a large positive
                // value that is also clamped.
                timeout = s_maxUrlRetrievalTimeout;
            }

            // Let Unspecified mean Local, so only convert if the source was UTC.
            //
            // Converge on Local instead of UTC because OpenSSL is going to assume we gave it
            // local time.
            if (verificationTime.Kind == DateTimeKind.Utc)
            {
                verificationTime = verificationTime.ToLocalTime();
            }

            // Until we support the Disallowed store, ensure it's empty (which is done by the ctor)
            using (new X509Store(StoreName.Disallowed, StoreLocation.CurrentUser, OpenFlags.ReadOnly))
            {
            }

            TimeSpan downloadTimeout = timeout;

            OpenSslX509ChainProcessor chainPal = OpenSslX509ChainProcessor.InitiateChain(
                ((OpenSslX509CertificateReader)cert).SafeHandle,
                customTrustStore,
                trustMode,
                verificationTime,
                downloadTimeout);

            Interop.Crypto.X509VerifyStatusCode status = chainPal.FindFirstChain(extraStore);

            if (OpenSslX509ChainEventSource.Log.IsEnabled())
            {
                OpenSslX509ChainEventSource.Log.FindFirstChainFinished(status);
            }

            if (!OpenSslX509ChainProcessor.IsCompleteChain(status))
            {
                if (disableAia)
                {
                    if (OpenSslX509ChainEventSource.Log.IsEnabled())
                    {
                        OpenSslX509ChainEventSource.Log.AiaDisabled();
                    }
                }
                else
                {
                    List <X509Certificate2>?tmp = null;
                    status = chainPal.FindChainViaAia(ref tmp);

                    if (OpenSslX509ChainEventSource.Log.IsEnabled())
                    {
                        OpenSslX509ChainEventSource.Log.FindChainViaAiaFinished(status, tmp?.Count ?? 0);
                    }

                    if (tmp != null)
                    {
                        if (status == Interop.Crypto.X509VerifyStatusCode.X509_V_OK)
                        {
                            SaveIntermediateCertificates(tmp);
                        }

                        foreach (X509Certificate2 downloaded in tmp)
                        {
                            downloaded.Dispose();
                        }
                    }
                }
            }

            if (revocationMode != X509RevocationMode.NoCheck)
            {
                if (OpenSslX509ChainProcessor.IsCompleteChain(status))
                {
                    // Checking the validity period for the certificates in the chain is done after the
                    // check for a trusted root, so accept expired (or not yet valid) as acceptable for
                    // processing revocation.
                    if (status != Interop.Crypto.X509VerifyStatusCode.X509_V_OK &&
                        status != Interop.Crypto.X509VerifyStatusCodeUniversal.X509_V_ERR_CERT_NOT_YET_VALID &&
                        status != Interop.Crypto.X509VerifyStatusCodeUniversal.X509_V_ERR_CERT_HAS_EXPIRED)
                    {
                        if (OpenSslX509ChainEventSource.Log.IsEnabled())
                        {
                            OpenSslX509ChainEventSource.Log.UntrustedChainWithRevocation();
                        }

                        revocationMode = X509RevocationMode.NoCheck;
                    }

                    chainPal.CommitToChain();
                    chainPal.ProcessRevocation(revocationMode, revocationFlag);
                }
            }

            chainPal.Finish(applicationPolicy, certificatePolicy);

#if DEBUG
            if (chainPal.ChainElements !.Length > 0)
            {
                X509Certificate2 reportedLeaf = chainPal.ChainElements[0].Certificate;
                Debug.Assert(reportedLeaf != null, "reportedLeaf != null");
                Debug.Assert(!ReferenceEquals(cert, reportedLeaf.Pal), "!ReferenceEquals(cert, reportedLeaf.Pal)");
            }
#endif
            return(chainPal);
        }
예제 #18
0
        internal static partial IChainPal?BuildChain(
            bool useMachineContext,
            ICertificatePal cert,
            X509Certificate2Collection?extraStore,
            OidCollection?applicationPolicy,
            OidCollection?certificatePolicy,
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            X509Certificate2Collection?customTrustStore,
            X509ChainTrustMode trustMode,
            DateTime verificationTime,
            TimeSpan timeout,
            bool disableAia)
        {
            if (timeout == TimeSpan.Zero)
            {
                // An input value of 0 on the timeout is treated as 15 seconds, to match Windows.
                timeout = TimeSpan.FromSeconds(15);
            }
            else if (timeout > s_maxUrlRetrievalTimeout || timeout < TimeSpan.Zero)
            {
                // Windows has a max timeout of 1 minute, so we'll match. Windows also treats
                // the timeout as unsigned, so a negative value gets treated as a large positive
                // value that is also clamped.
                timeout = s_maxUrlRetrievalTimeout;
            }

            // Let Unspecified mean Local, so only convert if the source was UTC.
            //
            // Converge on Local instead of UTC because OpenSSL is going to assume we gave it
            // local time.
            if (verificationTime.Kind == DateTimeKind.Utc)
            {
                verificationTime = verificationTime.ToLocalTime();
            }

            // Until we support the Disallowed store, ensure it's empty (which is done by the ctor)
            using (new X509Store(StoreName.Disallowed, StoreLocation.CurrentUser, OpenFlags.ReadOnly))
            {
            }

            TimeSpan downloadTimeout = timeout;

            OpenSslX509ChainProcessor chainPal = OpenSslX509ChainProcessor.InitiateChain(
                ((OpenSslX509CertificateReader)cert).SafeHandle,
                customTrustStore,
                trustMode,
                verificationTime,
                downloadTimeout);

            Interop.Crypto.X509VerifyStatusCode status = chainPal.FindFirstChain(extraStore);

            if (!OpenSslX509ChainProcessor.IsCompleteChain(status) && !disableAia)
            {
                List <X509Certificate2>?tmp = null;
                status = chainPal.FindChainViaAia(ref tmp);

                if (tmp != null)
                {
                    if (status == Interop.Crypto.X509VerifyStatusCode.X509_V_OK)
                    {
                        SaveIntermediateCertificates(tmp);
                    }

                    foreach (X509Certificate2 downloaded in tmp)
                    {
                        downloaded.Dispose();
                    }
                }
            }

            // In NoCheck+OK then we don't need to build the chain any more, we already
            // know it's error-free.  So skip straight to finish.
            if (status != Interop.Crypto.X509VerifyStatusCode.X509_V_OK ||
                revocationMode != X509RevocationMode.NoCheck)
            {
                if (OpenSslX509ChainProcessor.IsCompleteChain(status))
                {
                    chainPal.CommitToChain();
                    chainPal.ProcessRevocation(revocationMode, revocationFlag);
                }
            }

            chainPal.Finish(applicationPolicy, certificatePolicy);

#if DEBUG
            if (chainPal.ChainElements !.Length > 0)
            {
                X509Certificate2 reportedLeaf = chainPal.ChainElements[0].Certificate;
                Debug.Assert(reportedLeaf != null, "reportedLeaf != null");
                Debug.Assert(!ReferenceEquals(cert, reportedLeaf.Pal), "!ReferenceEquals(cert, reportedLeaf.Pal)");
            }
#endif
            return(chainPal);
        }