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); }
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)); } } } } }
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)); }
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 }
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);
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); }
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; } }
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)); }
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); }
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); }
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(); } } }
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())); }
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); }
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(); }
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(); } } }
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); }
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); }