/// <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));
                            }
                        }
                    }
            }
        }
예제 #2
0
        private static CertChainFlags MapRevocationFlags(X509RevocationMode revocationMode, X509RevocationFlag revocationFlag)
        {
            CertChainFlags dwFlags = CertChainFlags.None;

            if (revocationMode == X509RevocationMode.NoCheck)
            {
                return(dwFlags);
            }

            if (revocationMode == X509RevocationMode.Offline)
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
            }

            if (revocationFlag == X509RevocationFlag.EndCertificateOnly)
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_END_CERT;
            }
            else if (revocationFlag == X509RevocationFlag.EntireChain)
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CHAIN;
            }
            else
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
            }

            return(dwFlags);
        }
        private static CertChainFlags MapRevocationFlags(
            X509RevocationMode revocationMode,
            X509RevocationFlag revocationFlag,
            bool disableAia)
        {
            const CertChainFlags AiaDisabledFlags =
                CertChainFlags.CERT_CHAIN_DISABLE_AIA | CertChainFlags.CERT_CHAIN_DISABLE_AUTH_ROOT_AUTO_UPDATE;

            CertChainFlags dwFlags = disableAia ? AiaDisabledFlags : CertChainFlags.None;

            if (revocationMode == X509RevocationMode.NoCheck)
            {
                return(dwFlags);
            }

            if (revocationMode == X509RevocationMode.Offline)
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
            }

            if (revocationFlag == X509RevocationFlag.EndCertificateOnly)
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_END_CERT;
            }
            else if (revocationFlag == X509RevocationFlag.EntireChain)
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CHAIN;
            }
            else
            {
                dwFlags |= CertChainFlags.CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
            }

            return(dwFlags);
        }
예제 #4
0
 internal static unsafe partial bool CertGetCertificateChain(
     IntPtr hChainEngine,
     SafeCertContextHandle pCertContext,
     FILETIME *pTime,
     SafeCertStoreHandle hStore,
     ref CERT_CHAIN_PARA pChainPara,
     CertChainFlags dwFlags,
     IntPtr pvReserved,
     out SafeX509ChainHandle ppChainContext);
예제 #5
0
 public static unsafe bool CertGetCertificateChain(ChainEngine hChainEngine, SafeCertContextHandle pCertContext, FILETIME *pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext)
 {
     return(CertGetCertificateChain((IntPtr)hChainEngine, pCertContext, pTime, hStore, ref pChainPara, dwFlags, pvReserved, out ppChainContext));
 }
예제 #6
0
 private static extern unsafe bool CertGetCertificateChain(IntPtr hChainEngine, SafeCertContextHandle pCertContext, FILETIME* pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext);
예제 #7
0
 public static unsafe bool CertGetCertificateChain(ChainEngine hChainEngine, SafeCertContextHandle pCertContext, FILETIME* pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext)
 {
     return CertGetCertificateChain((IntPtr)hChainEngine, pCertContext, pTime, hStore, ref pChainPara, dwFlags, pvReserved, out ppChainContext);
 }