/// <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); } } } } }
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}"); }
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); } } } }
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; }
// 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); } }
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); } } } } } }
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); }
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); }
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); }
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); } }
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); } }