Beispiel #1
0
        /// <summary>
        /// Updates the certificate authority certificate and CRL in the trusted list.
        /// </summary>
        private async Task UpdateAuthorityCertInTrustedList()
        {
            string trustedListStorePath = Configuration.TrustedListPath;

            if (!String.IsNullOrEmpty(Configuration.TrustedListPath))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(trustedListStorePath))
                {
                    X509Certificate2Collection certs = await store.FindByThumbprint(Certificate.Thumbprint);

                    if (certs.Count == 0)
                    {
                        await store.Add(Certificate);
                    }

                    // delete existing CRL in trusted list
                    foreach (var crl in store.EnumerateCRLs(Certificate, false))
                    {
                        if (crl.VerifySignature(Certificate, false))
                        {
                            store.DeleteCRL(crl);
                        }
                    }

                    // copy latest CRL to trusted list
                    using (ICertificateStore storeAuthority = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath))
                    {
                        foreach (var crl in storeAuthority.EnumerateCRLs(Certificate, true))
                        {
                            store.AddCRL(crl);
                        }
                    }
                }
            }
        }
Beispiel #2
0
        public async Task VerifyAppChainsOneTrusted()
        {
            var stopWatch = new Stopwatch();

            stopWatch.Start();
            // verify cert with issuer chain
            for (int v = 0; v < kCaChainCount; v++)
            {
                long start = stopWatch.ElapsedMilliseconds;
                TestContext.Out.WriteLine($"Chain Number {v}, Total Elapsed: {start}");
                CleanupValidatorAndStores();
                TestContext.Out.WriteLine($"Cleanup: {stopWatch.ElapsedMilliseconds-start}");
                for (int i = 0; i < kCaChainCount; i++)
                {
                    ICertificateStore store = i == v ? m_trustedStore : m_issuerStore;
                    await store.Add(m_caChain[i]);

                    store.AddCRL(m_crlChain[i]);
                }
                TestContext.Out.WriteLine($"AddChains: {stopWatch.ElapsedMilliseconds - start}");
                var certValidator = InitValidatorWithStores();
                TestContext.Out.WriteLine($"InitValidator: {stopWatch.ElapsedMilliseconds - start}");
                foreach (var app in m_goodApplicationTestSet)
                {
                    certValidator.Validate(new X509Certificate2(app.Certificate));
                }
                TestContext.Out.WriteLine($"Validation: {stopWatch.ElapsedMilliseconds - start}");
            }
            TestContext.Out.WriteLine($"Total: {stopWatch.ElapsedMilliseconds}");
        }
Beispiel #3
0
        protected async Task UpdateGroupStore(string storePath, X509Certificate2Collection certs, IList <Opc.Ua.X509CRL> crls)
        {
            if (!String.IsNullOrEmpty(storePath))
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    X509Certificate2Collection oldCertificates = await store.Enumerate();

                    foreach (var cert in oldCertificates)
                    {
                        await store.Delete(cert.Thumbprint);
                    }
                    foreach (var crl in store.EnumerateCRLs())
                    {
                        store.DeleteCRL(crl);
                    }
                    foreach (var cert in certs)
                    {
                        await store.Add(cert);
                    }
                    foreach (var crl in crls)
                    {
                        store.AddCRL(crl);
                    }
                }
            }
        }
Beispiel #4
0
        private ServiceResult AddCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            byte[] certificate,
            bool isTrustedCertificate)
        {
            HasSecureWriteAccess(context);

            lock (m_lock)
            {

                if (m_sessionId != null)
                {
                    return StatusCodes.BadInvalidState;
                }

                if (certificate == null)
                {
                    return StatusCodes.BadInvalidArgument;
                }

                X509Certificate2 cert = null;
                X509CRL crl = null;
                try
                {
                    cert = new X509Certificate2(certificate);
                }
                catch
                {
                    try
                    {
                        crl = new X509CRL(certificate);
                    }
                    catch
                    {
                        return StatusCodes.BadCertificateInvalid;
                    }
                }

                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath))
                {
                    if (cert != null)
                    {
                        store.Add(cert).Wait();
                    }
                    if (crl != null)
                    {
                        store.AddCRL(crl);
                    }
                }

                m_node.LastUpdateTime.Value = DateTime.UtcNow;
            }

            return ServiceResult.Good;
        }
Beispiel #5
0
 // Create an empty CRL
 static void CreateCACRL(string storePath, X509Certificate2 caCert)
 {
     Console.WriteLine("Creating an empty certificate revocation list (CRL) for the CA");
     using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
     {
         List <X509CRL> caCRL      = store.EnumerateCRLs(caCert, false);
         X509CRL        updatedCRL = CertificateFactory.RevokeCertificate(caCert, caCRL, null);
         store.AddCRL(updatedCRL);
     }
 }
Beispiel #6
0
        public async Task VerifyAppChainsWithGoodAndInvalidChain()
        {
            // verify cert with issuer chain
            for (int v = 0; v < kCaChainCount; v++)
            {
                CleanupValidatorAndStores();
                for (int i = 0; i < kCaChainCount; i++)
                {
                    ICertificateStore store = i == v ? m_trustedStore : m_issuerStore;
                    await store.Add(m_caChain[i]);

                    store.AddCRL(m_crlChain[i]);
                    await store.Add(m_caDupeChain[i]);

                    store.AddCRL(m_crlDupeChain[i]);
                }
                var certValidator = InitValidatorWithStores();
                foreach (var app in m_goodApplicationTestSet)
                {
                    certValidator.Validate(new X509Certificate2(app.Certificate));
                }
            }
        }
        /// <summary>
        /// Updates the certificate authority certificate and CRL in the trusted list.
        /// </summary>
        protected async Task UpdateAuthorityCertInTrustedList()
        {
            string trustedListStorePath = Configuration.TrustedListPath;

            if (!String.IsNullOrEmpty(Configuration.TrustedListPath))
            {
                using (ICertificateStore authorityStore = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath))
                    using (ICertificateStore trustedStore = CertificateStoreIdentifier.OpenStore(trustedListStorePath))
                    {
                        X509Certificate2Collection certificates = await authorityStore.Enumerate();

                        foreach (var certificate in certificates)
                        {
                            if (Utils.CompareDistinguishedName(certificate.Subject, m_subjectName))
                            {
                                X509Certificate2Collection certs = await trustedStore.FindByThumbprint(certificate.Thumbprint);

                                if (certs.Count == 0)
                                {
                                    await trustedStore.Add(new X509Certificate2(certificate.RawData));
                                }

                                // delete existing CRL in trusted list
                                foreach (var crl in trustedStore.EnumerateCRLs(certificate, false))
                                {
                                    if (crl.VerifySignature(certificate, false))
                                    {
                                        trustedStore.DeleteCRL(crl);
                                    }
                                }

                                // copy latest CRL to trusted list
                                foreach (var crl in authorityStore.EnumerateCRLs(certificate, true))
                                {
                                    trustedStore.AddCRL(crl);
                                }
                            }
                        }
                    }
            }
        }
Beispiel #8
0
        private async Task <bool> UpdateStoreCrls(
            CertificateTrustList trustList,
            X509CRLCollection updatedCrls)
        {
            bool result             = true;
            ICertificateStore store = null;

            try
            {
                store = trustList.OpenStore();
                var storeCrls = await store.EnumerateCRLs().ConfigureAwait(false);

                foreach (var crl in storeCrls)
                {
                    if (!updatedCrls.Contains(crl))
                    {
                        if (!await store.DeleteCRL(crl).ConfigureAwait(false))
                        {
                            result = false;
                        }
                    }
                    else
                    {
                        updatedCrls.Remove(crl);
                    }
                }
                foreach (var crl in updatedCrls)
                {
                    await store.AddCRL(crl).ConfigureAwait(false);
                }
            }
            catch
            {
                result = false;
            }
            finally
            {
                store?.Close();
            }
            return(result);
        }
Beispiel #9
0
        private async Task <bool> UpdateStoreCrls(
            string storePath,
            X509CRLCollection updatedCrls)
        {
            bool result = true;

            try
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    var storeCrls = await store.EnumerateCRLs().ConfigureAwait(false);

                    foreach (var crl in storeCrls)
                    {
                        if (!updatedCrls.Contains(crl))
                        {
                            if (!await store.DeleteCRL(crl).ConfigureAwait(false))
                            {
                                result = false;
                            }
                        }
                        else
                        {
                            updatedCrls.Remove(crl);
                        }
                    }
                    foreach (var crl in updatedCrls)
                    {
                        await store.AddCRL(crl).ConfigureAwait(false);
                    }
                }
            }
            catch
            {
                result = false;
            }
            return(result);
        }
Beispiel #10
0
        private bool UpdateStoreCrls(
            string storePath,
            IList <X509CRL> updatedCrls)
        {
            bool result = true;

            try
            {
                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
                {
                    var storeCrls = store.EnumerateCRLs();
                    foreach (var crl in storeCrls)
                    {
                        if (!updatedCrls.Contains(crl))
                        {
                            if (!store.DeleteCRL(crl))
                            {
                                result = false;
                            }
                        }
                        else
                        {
                            updatedCrls.Remove(crl);
                        }
                    }
                    foreach (var crl in updatedCrls)
                    {
                        store.AddCRL(crl);
                    }
                }
            }
            catch
            {
                result = false;
            }
            return(result);
        }
    /// <summary>
    /// Revoke the CA signed certificate.
    /// The issuer CA public key, the private key and the crl reside in the storepath.
    /// The CRL number is increased by one and existing CRL for the issuer are deleted from the store.
    /// </summary>
    public static async Task <X509CRL> RevokeCertificateAsync(
        string storePath,
        X509Certificate2 certificate,
        string issuerKeyFilePassword = null
        )
    {
        X509CRL updatedCRL = null;

        try
        {
            string subjectName  = certificate.IssuerName.Name;
            string keyId        = null;
            string serialNumber = null;

            // caller may want to create empty CRL using the CA cert itself
            bool isCACert = IsCertificateAuthority(certificate);

            // find the authority key identifier.
            X509AuthorityKeyIdentifierExtension authority = FindAuthorityKeyIdentifier(certificate);

            if (authority != null)
            {
                keyId        = authority.KeyId;
                serialNumber = authority.SerialNumber;
            }
            else
            {
                throw new ArgumentException("Certificate does not contain an Authority Key");
            }

            if (!isCACert)
            {
                if (serialNumber == certificate.SerialNumber ||
                    Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer))
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot revoke self signed certificates");
                }
            }

            X509Certificate2 certCA = null;
            using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
            {
                if (store == null)
                {
                    throw new ArgumentException("Invalid store path/type");
                }
                certCA = await FindIssuerCABySerialNumberAsync(store, certificate.Issuer, serialNumber);

                if (certCA == null)
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot find issuer certificate in store.");
                }

                if (!certCA.HasPrivateKey)
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer certificate has no private key, cannot revoke certificate.");
                }

                CertificateIdentifier certCAIdentifier = new CertificateIdentifier(certCA);
                certCAIdentifier.StorePath = storePath;
                certCAIdentifier.StoreType = CertificateStoreIdentifier.DetermineStoreType(storePath);
                X509Certificate2 certCAWithPrivateKey = await certCAIdentifier.LoadPrivateKey(issuerKeyFilePassword);

                if (certCAWithPrivateKey == null)
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Failed to load issuer private key. Is the password correct?");
                }

                List <X509CRL> certCACrl = store.EnumerateCRLs(certCA, false);

                using (var cfrg = new CertificateFactoryRandomGenerator())
                {
                    // cert generators
                    SecureRandom random          = new SecureRandom(cfrg);
                    BigInteger   crlSerialNumber = BigInteger.Zero;

                    Org.BouncyCastle.X509.X509Certificate bcCertCA = new X509CertificateParser().ReadCertificate(certCA.RawData);
                    AsymmetricKeyParameter signingKey = GetPrivateKeyParameter(certCAWithPrivateKey);

                    ISignatureFactory signatureFactory =
                        new Asn1SignatureFactory(GetRSAHashAlgorithm(defaultHashSize), signingKey, random);

                    X509V2CrlGenerator crlGen = new X509V2CrlGenerator();
                    crlGen.SetIssuerDN(bcCertCA.IssuerDN);
                    crlGen.SetThisUpdate(DateTime.UtcNow);
                    crlGen.SetNextUpdate(DateTime.UtcNow.AddMonths(12));

                    // merge all existing revocation list
                    X509CrlParser parser = new X509CrlParser();
                    foreach (X509CRL caCrl in certCACrl)
                    {
                        X509Crl crl = parser.ReadCrl(caCrl.RawData);
                        crlGen.AddCrl(crl);
                        var crlVersion = GetCrlNumber(crl);
                        if (crlVersion.IntValue > crlSerialNumber.IntValue)
                        {
                            crlSerialNumber = crlVersion;
                        }
                    }

                    if (isCACert)
                    {
                        // add a dummy revoked cert
                        crlGen.AddCrlEntry(BigInteger.One, DateTime.UtcNow, CrlReason.Superseded);
                    }
                    else
                    {
                        // add the revoked cert
                        crlGen.AddCrlEntry(GetSerialNumber(certificate), DateTime.UtcNow, CrlReason.PrivilegeWithdrawn);
                    }

                    crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier,
                                        false,
                                        new AuthorityKeyIdentifierStructure(bcCertCA));

                    // set new serial number
                    crlSerialNumber = crlSerialNumber.Add(BigInteger.One);
                    crlGen.AddExtension(X509Extensions.CrlNumber,
                                        false,
                                        new CrlNumber(crlSerialNumber));

                    // generate updated CRL
                    X509Crl updatedCrl = crlGen.Generate(signatureFactory);

                    // add updated CRL to store
                    updatedCRL = new X509CRL(updatedCrl.GetEncoded());
                    store.AddCRL(updatedCRL);

                    // delete outdated CRLs from store
                    foreach (X509CRL caCrl in certCACrl)
                    {
                        store.DeleteCRL(caCrl);
                    }
                }
                store.Close();
            }
        }
        catch (Exception e)
        {
            throw e;
        }
        return(updatedCRL);
    }
        /// <summary>
        /// Revoke the CA signed certificate.
        /// The issuer CA public key, the private key and the crl reside in the storepath.
        /// The CRL number is increased by one and existing CRL for the issuer are deleted from the store.
        /// </summary>
        public static async Task <X509CRL> RevokeCertificateAsync(
            string storePath,
            X509Certificate2 certificate,
            string issuerKeyFilePassword = null
            )
        {
            X509CRL updatedCRL   = null;
            string  subjectName  = certificate.IssuerName.Name;
            string  keyId        = null;
            string  serialNumber = null;

            // caller may want to create empty CRL using the CA cert itself
            bool isCACert = X509Utils.IsCertificateAuthority(certificate);

            // find the authority key identifier.
            X509AuthorityKeyIdentifierExtension authority = X509Extensions.FindExtension <X509AuthorityKeyIdentifierExtension>(certificate);

            if (authority != null)
            {
                keyId        = authority.KeyIdentifier;
                serialNumber = authority.SerialNumber;
            }
            else
            {
                throw new ArgumentException("Certificate does not contain an Authority Key");
            }

            if (!isCACert)
            {
                if (serialNumber == certificate.SerialNumber ||
                    X509Utils.CompareDistinguishedName(certificate.Subject, certificate.Issuer))
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot revoke self signed certificates");
                }
            }

            X509Certificate2 certCA = null;

            using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(storePath))
            {
                if (store == null)
                {
                    throw new ArgumentException("Invalid store path/type");
                }
                certCA = await X509Utils.FindIssuerCABySerialNumberAsync(store, certificate.Issuer, serialNumber).ConfigureAwait(false);

                if (certCA == null)
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Cannot find issuer certificate in store.");
                }

                if (!certCA.HasPrivateKey)
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer certificate has no private key, cannot revoke certificate.");
                }

                CertificateIdentifier certCAIdentifier = new CertificateIdentifier(certCA)
                {
                    StorePath = storePath,
                    StoreType = CertificateStoreIdentifier.DetermineStoreType(storePath)
                };
                X509Certificate2 certCAWithPrivateKey = await certCAIdentifier.LoadPrivateKey(issuerKeyFilePassword).ConfigureAwait(false);

                if (certCAWithPrivateKey == null)
                {
                    throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Failed to load issuer private key. Is the password correct?");
                }

                List <X509CRL> certCACrl = store.EnumerateCRLs(certCA, false);

                var certificateCollection = new X509Certificate2Collection()
                {
                };
                if (!isCACert)
                {
                    certificateCollection.Add(certificate);
                }
                updatedCRL = CertificateFactory.RevokeCertificate(certCAWithPrivateKey, certCACrl, certificateCollection);

                store.AddCRL(updatedCRL);

                // delete outdated CRLs from store
                foreach (X509CRL caCrl in certCACrl)
                {
                    store.DeleteCRL(caCrl);
                }
                store.Close();
            }
            return(updatedCRL);
        }
Beispiel #13
0
        private void PullFromGds(bool deleteBeforeAdd)
        {
            try
            {
                NodeId trustListId = m_gds.GetTrustList(m_application.ApplicationId, null);

                if (trustListId == null)
                {
                    CertificateStoreControl.Initialize(null, null, null);
                    return;
                }

                var trustList = m_gds.ReadTrustList(trustListId);

                if (m_application.RegistrationType == RegistrationType.ServerPush)
                {
                    CertificateStoreControl.Initialize(trustList, null, deleteBeforeAdd);

                    MessageBox.Show(
                        Parent,
                        "The trust list (include CRLs) was downloaded from the GDS. It now has to be pushed to the Server.",
                        Parent.Text,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information);

                    return;
                }

                if (!String.IsNullOrEmpty(m_trustListStorePath))
                {
                    if (deleteBeforeAdd)
                    {
                        DeleteExistingFromStore(m_trustListStorePath).Wait();
                        DeleteExistingFromStore(m_issuerListStorePath).Wait();;
                    }
                }

                if (!String.IsNullOrEmpty(m_trustListStorePath))
                {
                    using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_trustListStorePath))
                    {
                        if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.TrustedCertificates) != 0)
                        {
                            foreach (var certificate in trustList.TrustedCertificates)
                            {
                                var x509 = new X509Certificate2(certificate);

                                X509Certificate2Collection certs = store.FindByThumbprint(x509.Thumbprint).Result;
                                if (certs.Count == 0)
                                {
                                    store.Add(x509).Wait();
                                }
                            }
                        }

                        if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.TrustedCrls) != 0)
                        {
                            foreach (var crl in trustList.TrustedCrls)
                            {
                                store.AddCRL(new X509CRL(crl));
                            }
                        }
                    }
                }

                if (!String.IsNullOrEmpty(m_application.IssuerListStorePath))
                {
                    using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_application.IssuerListStorePath))
                    {
                        if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.IssuerCertificates) != 0)
                        {
                            foreach (var certificate in trustList.IssuerCertificates)
                            {
                                var x509 = new X509Certificate2(certificate);

                                X509Certificate2Collection certs = store.FindByThumbprint(x509.Thumbprint).Result;
                                if (certs.Count == 0)
                                {
                                    store.Add(x509).Wait();
                                }
                            }
                        }

                        if ((trustList.SpecifiedLists & (uint)Opc.Ua.TrustListMasks.IssuerCrls) != 0)
                        {
                            foreach (var crl in trustList.IssuerCrls)
                            {
                                store.AddCRL(new X509CRL(crl));
                            }
                        }
                    }
                }

                CertificateStoreControl.Initialize(m_trustListStorePath, m_issuerListStorePath, null);

                MessageBox.Show(
                    Parent,
                    "The trust list (include CRLs) was downloaded from the GDS and saved locally.",
                    Parent.Text,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information);
            }
            catch (Exception exception)
            {
                MessageBox.Show(Parent.Text + ": " + exception.Message);
            }
        }
Beispiel #14
0
        public override async Task Init()
        {
            Utils.Trace(Utils.TraceMasks.Information, "InitializeCertificateGroup: {0}", m_subjectName);

            X509Certificate2Collection rootCACertificateChain;
            IList <Opc.Ua.X509CRL>     rootCACrlChain;

            try
            {
                // read root CA chain for certificate group
                rootCACertificateChain = await _opcVaultHandler.GetCACertificateChainAsync(Configuration.Id).ConfigureAwait(false);

                rootCACrlChain = await _opcVaultHandler.GetCACrlChainAsync(Configuration.Id).ConfigureAwait(false);

                var rootCaCert = rootCACertificateChain[0];
                var rootCaCrl  = rootCACrlChain[0];

                if (Utils.CompareDistinguishedName(rootCaCert.Subject, m_subjectName))
                {
                    Certificate = rootCaCert;
                    rootCaCrl.VerifySignature(rootCaCert, true);
                }
                else
                {
                    throw new ServiceResultException("Key Vault certificate subject(" + rootCaCert.Subject + ") does not match cert group subject " + m_subjectName);
                }
            }
            catch (Exception ex)
            {
                Utils.Trace("Failed to load CA certificate " + Configuration.Id + " from key Vault ");
                Utils.Trace(ex.Message);
                throw ex;
            }

            // add all existing cert versions to trust list

            // erase old certs
            using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(m_authoritiesStorePath))
            {
                try
                {
                    X509Certificate2Collection certificates = await store.Enumerate();

                    foreach (var certificate in certificates)
                    {
                        // TODO: Subject may have changed over time
                        if (Utils.CompareDistinguishedName(certificate.Subject, m_subjectName))
                        {
                            var certs = rootCACertificateChain.Find(X509FindType.FindByThumbprint, certificate.Thumbprint, false);
                            if (certs == null || certs.Count == 0)
                            {
                                Utils.Trace("Delete CA certificate from authority store: " + certificate.Thumbprint);

                                // delete existing CRL in trusted list
                                foreach (var crl in store.EnumerateCRLs(certificate, false))
                                {
                                    if (crl.VerifySignature(certificate, false))
                                    {
                                        store.DeleteCRL(crl);
                                    }
                                }

                                await store.Delete(certificate.Thumbprint);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    Utils.Trace("Failed to Delete existing certificates from authority store: " + ex.Message);
                }

                foreach (var rootCACertificate in rootCACertificateChain)
                {
                    X509Certificate2Collection certs = await store.FindByThumbprint(rootCACertificate.Thumbprint);

                    if (certs.Count == 0)
                    {
                        await store.Add(rootCACertificate);

                        Utils.Trace("Added CA certificate to authority store: " + rootCACertificate.Thumbprint);
                    }
                    else
                    {
                        Utils.Trace("CA certificate already exists in authority store: " + rootCACertificate.Thumbprint);
                    }

                    foreach (var rootCACrl in rootCACrlChain)
                    {
                        if (rootCACrl.VerifySignature(rootCACertificate, false))
                        {
                            // delete existing CRL in trusted list
                            foreach (var crl in store.EnumerateCRLs(rootCACertificate, false))
                            {
                                if (crl.VerifySignature(rootCACertificate, false))
                                {
                                    store.DeleteCRL(crl);
                                }
                            }

                            store.AddCRL(rootCACrl);
                        }
                    }
                }

                // load trust list from server
                var trustList = await _opcVaultHandler.GetTrustListAsync(Configuration.Id).ConfigureAwait(false);
                await UpdateTrustList(trustList);
            }
        }