/// <inheritdoc/>
        public async Task <X509CRLCollection> EnumerateCRLs(X509Certificate2 issuer, bool validateUpdateTime = true)
        {
            if (issuer == null)
            {
                throw new ArgumentNullException(nameof(issuer));
            }

            var crls = new X509CRLCollection();

            foreach (X509CRL crl in await EnumerateCRLs().ConfigureAwait(false))
            {
                if (!X509Utils.CompareDistinguishedName(crl.IssuerName, issuer.SubjectName))
                {
                    continue;
                }

                if (!crl.VerifySignature(issuer, false))
                {
                    continue;
                }

                if (!validateUpdateTime ||
                    crl.ThisUpdate <= DateTime.UtcNow && (crl.NextUpdate == DateTime.MinValue || crl.NextUpdate >= DateTime.UtcNow))
                {
                    crls.Add(crl);
                }
            }

            return(crls);
        }
        /// <summary>
        /// Revoke the certificates.
        /// </summary>
        /// <remarks>
        /// Merge all existing revoked certificates from CRL list.
        /// Add serialnumbers of new revoked certificates.
        /// The CRL number is increased by one and the new CRL is returned.
        /// </remarks>
        public static X509CRL RevokeCertificate(
            X509Certificate2 issuerCertificate,
            X509CRLCollection issuerCrls,
            X509Certificate2Collection revokedCertificates,
            DateTime thisUpdate,
            DateTime nextUpdate
            )
        {
            if (!issuerCertificate.HasPrivateKey)
            {
                throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer certificate has no private key, cannot revoke certificate.");
            }

            BigInteger crlSerialNumber = 0;
            var        crlRevokedList  = new Dictionary <string, RevokedCertificate>();

            // merge all existing revocation list
            if (issuerCrls != null)
            {
                foreach (X509CRL issuerCrl in issuerCrls)
                {
                    var extension = X509Extensions.FindExtension <X509CrlNumberExtension>(issuerCrl.CrlExtensions);
                    if (extension != null &&
                        extension.CrlNumber > crlSerialNumber)
                    {
                        crlSerialNumber = extension.CrlNumber;
                    }
                    foreach (var revokedCertificate in issuerCrl.RevokedCertificates)
                    {
                        if (!crlRevokedList.ContainsKey(revokedCertificate.SerialNumber))
                        {
                            crlRevokedList[revokedCertificate.SerialNumber] = revokedCertificate;
                        }
                    }
                }
            }

            // add existing serial numbers
            if (revokedCertificates != null)
            {
                foreach (var cert in revokedCertificates)
                {
                    if (!crlRevokedList.ContainsKey(cert.SerialNumber))
                    {
                        var entry = new RevokedCertificate(cert.SerialNumber, CRLReason.PrivilegeWithdrawn);
                        crlRevokedList[cert.SerialNumber] = entry;
                    }
                }
            }

            CrlBuilder crlBuilder = CrlBuilder.Create(issuerCertificate.SubjectName)
                                    .AddRevokedCertificates(crlRevokedList.Values.ToList())
                                    .SetThisUpdate(thisUpdate)
                                    .SetNextUpdate(nextUpdate)
                                    .AddCRLExtension(X509Extensions.BuildAuthorityKeyIdentifier(issuerCertificate))
                                    .AddCRLExtension(X509Extensions.BuildCRLNumber(crlSerialNumber + 1));

            return(new X509CRL(crlBuilder.CreateForRSA(issuerCertificate)));
        }
 /// <summary>
 /// Revoke the certificate.
 /// The CRL number is increased by one and the new CRL is returned.
 /// </summary>
 public static X509CRL RevokeCertificate(
     X509Certificate2 issuerCertificate,
     X509CRLCollection issuerCrls,
     X509Certificate2Collection revokedCertificates
     )
 {
     return(RevokeCertificate(issuerCertificate, issuerCrls, revokedCertificates,
                              DateTime.UtcNow, DateTime.UtcNow.AddMonths(12)));
 }
        /// <inheritdoc/>
        public Task <X509CRLCollection> EnumerateCRLs()
        {
            var crls = new X509CRLCollection();

            // check for CRL.
            DirectoryInfo info = new DirectoryInfo(this.Directory.FullName + Path.DirectorySeparatorChar + "crl");

            if (info.Exists)
            {
                foreach (FileInfo file in info.GetFiles("*.crl"))
                {
                    X509CRL crl = new X509CRL(file.FullName);
                    crls.Add(crl);
                }
            }

            return(Task.FromResult(crls));
        }
示例#5
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);
        }
示例#6
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);
        }
示例#7
0
        private ServiceResult RemoveCertificate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            string thumbprint,
            bool isTrustedCertificate)
        {
            HasSecureWriteAccess(context);

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

                if (String.IsNullOrEmpty(thumbprint))
                {
                    return(StatusCodes.BadInvalidArgument);
                }

                using (ICertificateStore store = CertificateStoreIdentifier.OpenStore(isTrustedCertificate ? m_trustedStorePath : m_issuerStorePath))
                {
                    var certCollection = store.FindByThumbprint(thumbprint).GetAwaiter().GetResult();

                    if (certCollection.Count == 0)
                    {
                        return(StatusCodes.BadInvalidArgument);
                    }

                    // delete all CRLs signed by cert
                    var crlsToDelete = new X509CRLCollection();
                    foreach (var crl in store.EnumerateCRLs().GetAwaiter().GetResult())
                    {
                        foreach (var cert in certCollection)
                        {
                            if (X509Utils.CompareDistinguishedName(cert.Subject, crl.Issuer) &&
                                crl.VerifySignature(cert, false))
                            {
                                crlsToDelete.Add(crl);
                                break;
                            }
                        }
                    }

                    if (!store.Delete(thumbprint).GetAwaiter().GetResult())
                    {
                        return(StatusCodes.BadInvalidArgument);
                    }

                    foreach (var crl in crlsToDelete)
                    {
                        if (!store.DeleteCRL(crl).GetAwaiter().GetResult())
                        {
                            // intentionally ignore errors, try best effort
                            Utils.LogError("RemoveCertificate: Failed to delete CRL {0}.", crl.ToString());
                        }
                    }
                }

                m_node.LastUpdateTime.Value = DateTime.UtcNow;
            }

            return(ServiceResult.Good);
        }
示例#8
0
        private ServiceResult CloseAndUpdate(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            uint fileHandle,
            ref bool restartRequired)
        {
            HasSecureWriteAccess(context);

            ServiceResult result = StatusCodes.Good;

            lock (m_lock)
            {
                if (m_sessionId != context.SessionId)
                {
                    return(StatusCodes.BadUserAccessDenied);
                }

                if (m_fileHandle != fileHandle)
                {
                    return(StatusCodes.BadInvalidArgument);
                }

                try
                {
                    TrustListDataType trustList = DecodeTrustListData(context, m_strm);
                    TrustListMasks    masks     = (TrustListMasks)trustList.SpecifiedLists;

                    X509Certificate2Collection issuerCertificates  = null;
                    X509CRLCollection          issuerCrls          = null;
                    X509Certificate2Collection trustedCertificates = null;
                    X509CRLCollection          trustedCrls         = null;

                    // test integrity of all CRLs
                    if ((masks & TrustListMasks.IssuerCertificates) != 0)
                    {
                        issuerCertificates = new X509Certificate2Collection();
                        foreach (var cert in trustList.IssuerCertificates)
                        {
                            issuerCertificates.Add(new X509Certificate2(cert));
                        }
                    }
                    if ((masks & TrustListMasks.IssuerCrls) != 0)
                    {
                        issuerCrls = new X509CRLCollection();
                        foreach (var crl in trustList.IssuerCrls)
                        {
                            issuerCrls.Add(new X509CRL(crl));
                        }
                    }
                    if ((masks & TrustListMasks.TrustedCertificates) != 0)
                    {
                        trustedCertificates = new X509Certificate2Collection();
                        foreach (var cert in trustList.TrustedCertificates)
                        {
                            trustedCertificates.Add(new X509Certificate2(cert));
                        }
                    }
                    if ((masks & TrustListMasks.TrustedCrls) != 0)
                    {
                        trustedCrls = new X509CRLCollection();
                        foreach (var crl in trustList.TrustedCrls)
                        {
                            trustedCrls.Add(new X509CRL(crl));
                        }
                    }

                    // update store
                    // test integrity of all CRLs
                    TrustListMasks updateMasks = TrustListMasks.None;
                    if ((masks & TrustListMasks.IssuerCertificates) != 0)
                    {
                        if (UpdateStoreCertificates(m_issuerStorePath, issuerCertificates).GetAwaiter().GetResult())
                        {
                            updateMasks |= TrustListMasks.IssuerCertificates;
                        }
                    }
                    if ((masks & TrustListMasks.IssuerCrls) != 0)
                    {
                        if (UpdateStoreCrls(m_issuerStorePath, issuerCrls).GetAwaiter().GetResult())
                        {
                            updateMasks |= TrustListMasks.IssuerCrls;
                        }
                    }
                    if ((masks & TrustListMasks.TrustedCertificates) != 0)
                    {
                        if (UpdateStoreCertificates(m_trustedStorePath, trustedCertificates).GetAwaiter().GetResult())
                        {
                            updateMasks |= TrustListMasks.TrustedCertificates;
                        }
                    }
                    if ((masks & TrustListMasks.TrustedCrls) != 0)
                    {
                        if (UpdateStoreCrls(m_trustedStorePath, trustedCrls).GetAwaiter().GetResult())
                        {
                            updateMasks |= TrustListMasks.TrustedCrls;
                        }
                    }

                    if (masks != updateMasks)
                    {
                        result = StatusCodes.BadCertificateInvalid;
                    }
                }
                catch
                {
                    result = StatusCodes.BadCertificateInvalid;
                }
                finally
                {
                    m_sessionId = null;
                    m_strm      = null;
                    m_node.LastUpdateTime.Value = DateTime.UtcNow;
                    m_node.OpenCount.Value      = 0;
                }
            }

            restartRequired = false;

            return(result);
        }
        public void VerifyCrlCerts(
            KeyHashPair keyHashPair
            )
        {
            int pathLengthConstraint           = (keyHashPair.KeySize / 512) - 3;
            X509Certificate2 issuerCertificate = GetIssuer(keyHashPair);

            Assert.True(X509Utils.VerifySelfSigned(issuerCertificate));

            var otherIssuerCertificate = CertificateFactory.CreateCertificate(issuerCertificate.Subject)
                                         .SetLifeTime(TimeSpan.FromDays(180))
                                         .SetHashAlgorithm(keyHashPair.HashAlgorithmName)
                                         .SetCAConstraint(pathLengthConstraint)
                                         .CreateForRSA();

            Assert.True(X509Utils.VerifySelfSigned(otherIssuerCertificate));

            X509Certificate2Collection revokedCerts = new X509Certificate2Collection();

            for (int i = 0; i < 10; i++)
            {
                var cert = CertificateFactory.CreateCertificate($"CN=Test Cert {i}")
                           .SetIssuer(issuerCertificate)
                           .SetRSAKeySize((ushort)(keyHashPair.KeySize <= 2048 ? keyHashPair.KeySize : 2048))
                           .CreateForRSA();
                revokedCerts.Add(cert);
                Assert.False(X509Utils.VerifySelfSigned(cert));
            }

            Assert.NotNull(issuerCertificate);
            Assert.NotNull(issuerCertificate.RawData);
            Assert.True(issuerCertificate.HasPrivateKey);
            using (var rsa = issuerCertificate.GetRSAPrivateKey())
            {
                Assert.NotNull(rsa);
            }

            using (var plainCert = new X509Certificate2(issuerCertificate.RawData))
            {
                Assert.NotNull(plainCert);
                VerifyCACert(plainCert, issuerCertificate.Subject, pathLengthConstraint);
            }
            Assert.True(X509Utils.VerifySelfSigned(issuerCertificate));
            X509Utils.VerifyRSAKeyPair(issuerCertificate, issuerCertificate, true);

            var crl = CertificateFactory.RevokeCertificate(issuerCertificate, null, null);

            Assert.NotNull(crl);
            Assert.True(crl.VerifySignature(issuerCertificate, true));
            var extension  = crl.CrlExtensions.FindExtension <X509CrlNumberExtension>();
            var crlCounter = new BigInteger(1);

            Assert.AreEqual(crlCounter, extension.CrlNumber);
            var revokedList = new X509CRLCollection {
                crl
            };

            foreach (var cert in revokedCerts)
            {
                Assert.Throws <CryptographicException>(() => crl.VerifySignature(otherIssuerCertificate, true));
                Assert.False(crl.IsRevoked(cert));
                var nextCrl = CertificateFactory.RevokeCertificate(issuerCertificate, revokedList, new X509Certificate2Collection(cert));
                crlCounter++;
                Assert.NotNull(nextCrl);
                Assert.True(nextCrl.IsRevoked(cert));
                extension = nextCrl.CrlExtensions.FindExtension <X509CrlNumberExtension>();
                Assert.AreEqual(crlCounter, extension.CrlNumber);
                Assert.True(crl.VerifySignature(issuerCertificate, true));
                revokedList.Add(nextCrl);
                crl = nextCrl;
            }

            foreach (var cert in revokedCerts)
            {
                Assert.True(crl.IsRevoked(cert));
            }
        }
        public async void Initialize(string trustedStorePath, string issuerStorePath, string rejectedStorePath)
        {
            CertificatesTable.Rows.Clear();

            m_trustedStorePath  = trustedStorePath;
            m_issuerStorePath   = issuerStorePath;
            m_rejectedStorePath = rejectedStorePath;

            if (!String.IsNullOrEmpty(trustedStorePath))
            {
                using (ICertificateStore store = CreateStore(trustedStorePath))
                {
                    X509CertificateCollection certificates = await store.Enumerate();

                    foreach (X509Certificate2 certificate in certificates)
                    {
                        var crls = new X509CRLCollection();

                        if (store.SupportsCRLs)
                        {
                            foreach (X509CRL crl in await store.EnumerateCRLs(certificate))
                            {
                                crls.Add(crl);
                            }
                        }

                        AddCertificate(certificate, Status.Trusted, crls);
                    }
                }
            }

            string path1 = Utils.GetAbsoluteDirectoryPath(trustedStorePath, true, false, false);
            string path2 = Utils.GetAbsoluteDirectoryPath(issuerStorePath, true, false, false);

            if (String.Compare(path1, path2, StringComparison.OrdinalIgnoreCase) != 0)
            {
                if (!String.IsNullOrEmpty(issuerStorePath))
                {
                    using (ICertificateStore store = CreateStore(issuerStorePath))
                    {
                        X509Certificate2Collection certificates = await store.Enumerate();

                        foreach (X509Certificate2 certificate in certificates)
                        {
                            var crls = new X509CRLCollection();

                            if (store.SupportsCRLs)
                            {
                                foreach (X509CRL crl in await store.EnumerateCRLs(certificate))
                                {
                                    crls.Add(crl);
                                }
                            }

                            AddCertificate(certificate, Status.Issuer, crls);
                        }
                    }
                }
            }

            if (!String.IsNullOrEmpty(rejectedStorePath))
            {
                using (ICertificateStore store = CreateStore(rejectedStorePath))
                {
                    X509Certificate2Collection certificates = await store.Enumerate();

                    foreach (X509Certificate2 certificate in certificates)
                    {
                        AddCertificate(certificate, Status.Rejected, null);
                    }
                }
            }

            m_dataset.AcceptChanges();
            NoDataWarningLabel.Visible = CertificatesTable.Rows.Count == 0;
        }
示例#11
0
        private async Task <bool> AddTrustListToStore(SecurityConfiguration config, TrustListDataType trustList)
        {
            TrustListMasks masks = (TrustListMasks)trustList.SpecifiedLists;

            X509Certificate2Collection issuerCertificates  = null;
            X509CRLCollection          issuerCrls          = null;
            X509Certificate2Collection trustedCertificates = null;
            X509CRLCollection          trustedCrls         = null;

            // test integrity of all CRLs
            if ((masks & TrustListMasks.IssuerCertificates) != 0)
            {
                issuerCertificates = new X509Certificate2Collection();
                foreach (var cert in trustList.IssuerCertificates)
                {
                    issuerCertificates.Add(new X509Certificate2(cert));
                }
            }
            if ((masks & TrustListMasks.IssuerCrls) != 0)
            {
                issuerCrls = new X509CRLCollection();
                foreach (var crl in trustList.IssuerCrls)
                {
                    issuerCrls.Add(new X509CRL(crl));
                }
            }
            if ((masks & TrustListMasks.TrustedCertificates) != 0)
            {
                trustedCertificates = new X509Certificate2Collection();
                foreach (var cert in trustList.TrustedCertificates)
                {
                    trustedCertificates.Add(new X509Certificate2(cert));
                }
            }
            if ((masks & TrustListMasks.TrustedCrls) != 0)
            {
                trustedCrls = new X509CRLCollection();
                foreach (var crl in trustList.TrustedCrls)
                {
                    trustedCrls.Add(new X509CRL(crl));
                }
            }

            // update store
            // test integrity of all CRLs
            TrustListMasks updateMasks = TrustListMasks.None;

            if ((masks & TrustListMasks.IssuerCertificates) != 0)
            {
                if (await UpdateStoreCertificates(config.TrustedIssuerCertificates, issuerCertificates).ConfigureAwait(false))
                {
                    updateMasks |= TrustListMasks.IssuerCertificates;
                }
            }
            if ((masks & TrustListMasks.IssuerCrls) != 0)
            {
                if (await UpdateStoreCrls(config.TrustedIssuerCertificates, issuerCrls).ConfigureAwait(false))
                {
                    updateMasks |= TrustListMasks.IssuerCrls;
                }
            }
            if ((masks & TrustListMasks.TrustedCertificates) != 0)
            {
                if (await UpdateStoreCertificates(config.TrustedPeerCertificates, trustedCertificates).ConfigureAwait(false))
                {
                    updateMasks |= TrustListMasks.TrustedCertificates;
                }
            }
            if ((masks & TrustListMasks.TrustedCrls) != 0)
            {
                if (await UpdateStoreCrls(config.TrustedPeerCertificates, trustedCrls).ConfigureAwait(false))
                {
                    updateMasks |= TrustListMasks.TrustedCrls;
                }
            }

            return(masks == updateMasks);
        }