If you know which certificates can be root and intermediate certificates for certificate verification, you can load the public keys of the root and intermediate certificates in the ChainPolicy.ExtraStore collection of the ChainPolicy.ExtraStore object.
My task was also to write a Windows Forms application to install the certificate only if it was released depending on the famous "National Root Certificate" of my government. There is also a limited number of CAs that are allowed to issue certificates for authenticating connections to national web services, so I had a limited set of certificates that might be in the chain and might not be on the target machine. I collected all of the CA public keys and government root certificates in the "cert" subdirectory of the application: 
In Visual Studio, I added a directory certificate to the solution and marked all the files in this directory as an embedded resource. This allowed me to list the collection of "trusted" certificates in my C # library code to create a chain for certificate verification, even if the issuer certificate is not installed. For this purpose, I created a wrapper class for X509Chain:
private class X509TestChain : X509Chain, IDisposable { public X509TestChain(X509Certificate2 oCert) : base(false) { try { ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; if (!Build(oCert) || (ChainElements.Count <= 1)) { Trace.WriteLine("X509Chain.Build failed with installed certificates."); Assembly asmExe = System.Reflection.Assembly.GetEntryAssembly(); if (asmExe != null) { string[] asResources = asmExe.GetManifestResourceNames(); foreach (string sResource in asResources) { if (sResource.IndexOf(".cert.") >= 0) { try { using (Stream str = asmExe.GetManifestResourceStream(sResource)) using (BinaryReader br = new BinaryReader(str)) { byte[] abResCert = new byte[str.Length]; br.Read(abResCert, 0, abResCert.Length); X509Certificate2 oResCert = new X509Certificate2(abResCert); Trace.WriteLine("Adding extra certificate: " + oResCert.Subject); ChainPolicy.ExtraStore.Add(oResCert); } } catch (Exception ex) { Trace.Write(ex); } } } } if (Build(oCert) && (ChainElements.Count > 1)) Trace.WriteLine("X509Chain.Build succeeded with extra certificates."); else Trace.WriteLine("X509Chain.Build still fails with extra certificates."); } } catch (Exception ex) { Trace.Write(ex); } } public void Dispose() { try { Trace.WriteLine(string.Format("Dispose: remove {0} extra certificates.", ChainPolicy.ExtraStore.Count)); ChainPolicy.ExtraStore.Clear(); } catch (Exception ex) { Trace.Write(ex); } } }
In the calling function, I could now successfully verify that an unknown certificate was received from the national root certificate:
bool bChainOK = false; using (X509TestChain oChain = new X509TestChain(oCert)) { if ((oChain.ChainElements.Count > 0) && IsPKIOverheidRootCert(oChain.ChainElements[oChain.ChainElements.Count - 1].Certificate)) bChainOK = true; if (!bChainOK) { TraceChain(oChain); sMessage = "Root certificate not present or not PKI Overheid (Staat der Nederlanden)"; return false; } } return true;
To complete the image: check the root certificate (which is usually installed because it is included in Windows Update, but theoretically may also be missing), I compare the friendly name and fingerprint with the published values:
private static bool IsPKIOverheidRootCert(X509Certificate2 oCert) { if (oCert != null) { string sFriendlyName = oCert.FriendlyName; if ((sFriendlyName.IndexOf("Staat der Nederlanden") >= 0) && (sFriendlyName.IndexOf(" Root CA") >= 0)) { switch (oCert.Thumbprint) { case "101DFA3FD50BCBBB9BB5600C1955A41AF4733A04": // Staat der Nederlanden Root CA - G1 case "59AF82799186C7B47507CBCF035746EB04DDB716": // Staat der Nederlanden Root CA - G2 case "76E27EC14FDB82C1C0A675B505BE3D29B4EDDBBB": // Staat der Nederlanden EV Root CA return true; } } } return false; }
I'm not sure this check is completely safe, but in my case the Windows Forms application operator is sure that you have access to a valid certificate that will be installed. The purpose of the software is simply to filter the list of certificates to help it install only the correct certificate in the computer's computer storage (the software also installs the public keys of the intermediate and root certificate to ensure that the behavior of the runtime client is a web service).