/// <summary> /// Creates the objects used to validate the user identity tokens supported by the server. /// </summary> private void CreateUserIdentityValidators(ApplicationConfiguration configuration) { for (int ii = 0; ii < configuration.ServerConfiguration.UserTokenPolicies.Count; ii++) { UserTokenPolicy policy = configuration.ServerConfiguration.UserTokenPolicies[ii]; // create a validator for a certificate token policy. if (policy.TokenType == UserTokenType.Certificate) { // the name of the element in the configuration file. XmlQualifiedName qname = new XmlQualifiedName(policy.PolicyId, Opc.Ua.Namespaces.OpcUa); // find the location of the trusted issuers. CertificateTrustList trustedIssuers = configuration.ParseExtension <CertificateTrustList>(qname); if (trustedIssuers == null) { Utils.Trace( (int)Utils.TraceMasks.Error, "Could not load CertificateTrustList for UserTokenPolicy {0}", policy.PolicyId); continue; } // trusts any certificate in the trusted people store. m_certificateValidator = X509CertificateValidator.PeerTrust; } } }
internal static async Task <CertificateTrustList> CreateTrustListAsync( string storePath, X509Certificate2Collection certCollection, IList <X509CRL> crlCollection) { var certTrustList = new CertificateTrustList(); certTrustList.StoreType = CertificateStoreType.Directory; certTrustList.StorePath = storePath; using (var store = certTrustList.OpenStore()) { foreach (var cert in certCollection) { await store.Add(cert); } if (store.SupportsCRLs) { foreach (var crl in crlCollection) { store.AddCRL(crl); } } } return(certTrustList); }
internal static async Task <CertificateTrustList> CreateTrustListAsync( string storePath, X509Certificate2Collection certCollection, IEnumerable <Crl> crlCollection) { var certTrustList = new CertificateTrustList { StoreType = CertificateStoreType.Directory, StorePath = storePath }; using (var store = certTrustList.OpenStore()) { foreach (var cert in certCollection) { await store.Add(cert); } if (store.SupportsCRLs) { foreach (var crl in crlCollection) { using (var x509crl = new X509CRL(crl.RawData)) { store.AddCRL(x509crl); } } } } return(certTrustList); }
/// <summary> /// Creates the objects used to validate the user identity tokens supported by the server. /// </summary> private void CreateUserIdentityValidators(ApplicationConfiguration configuration) { for (int ii = 0; ii < configuration.ServerConfiguration.UserTokenPolicies.Count; ii++) { UserTokenPolicy policy = configuration.ServerConfiguration.UserTokenPolicies[ii]; // ignore policies without an explicit id. if (String.IsNullOrEmpty(policy.PolicyId)) { continue; } // create a validator for an issued token policy. if (policy.TokenType == UserTokenType.IssuedToken) { // the name of the element in the configuration file. XmlQualifiedName qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa); // find the id for the issuer certificate. CertificateIdentifier id = configuration.ParseExtension <CertificateIdentifier>(qname); if (id == null) { Utils.Trace( (int)Utils.TraceMasks.Error, "Could not load CertificateIdentifier for UserTokenPolicy {0}", policy.PolicyId); continue; } m_tokenResolver = CreateSecurityTokenResolver(id); m_tokenSerializer = WSSecurityTokenSerializer.DefaultInstance; } // create a validator for a certificate token policy. if (policy.TokenType == UserTokenType.Certificate) { // the name of the element in the configuration file. XmlQualifiedName qname = new XmlQualifiedName(policy.PolicyId, Namespaces.OpcUa); // find the location of the trusted issuers. CertificateTrustList trustedIssuers = configuration.ParseExtension <CertificateTrustList>(qname); if (trustedIssuers == null) { Utils.Trace( (int)Utils.TraceMasks.Error, "Could not load CertificateTrustList for UserTokenPolicy {0}", policy.PolicyId); continue; } // trusts any certificate in the trusted people store. m_certificateValidator = X509CertificateValidator.PeerTrust; } } }
private string GetCtlDisplayName(CertificateTrustList ctl) { if (!string.IsNullOrEmpty(ctl.FriendlyName)) { return(ctl.FriendlyName); } return("Trust List"); }
/// <summary> /// Create trust list /// </summary> /// <param name="certificateStore"></param> /// <returns></returns> public static CertificateTrustList ToCertificateTrustList(this CertificateStore certificateStore) { var certificateTrustList = new CertificateTrustList { StoreType = certificateStore.StoreType, StorePath = certificateStore.StorePath }; return(certificateTrustList); }
public static X509Object Create(CertificateTrustList ctl, string storeName, StoreLocation storeLocation) { if (ctl == null) { throw new ArgumentNullException("ctl"); } return(new X509Object(storeName, storeLocation) { Value = ctl, Data = ctl.RawData }); }
public static void VerifyApplicationCertIntegrity( X509Certificate2 newCert, byte[] privateKey, string privateKeyPassword, string privateKeyFormat, X509Certificate2Collection issuerCertificates) { Assert.NotNull(newCert); if (privateKey != null) { X509Certificate2 newPrivateKeyCert = null; if (privateKeyFormat == "PFX") { newPrivateKeyCert = CertificateFactory.CreateCertificateFromPKCS12(privateKey, privateKeyPassword); } else if (privateKeyFormat == "PEM") { newPrivateKeyCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, privateKeyPassword); } else { Assert.True(false, "Invalid private key format"); } Assert.NotNull(newPrivateKeyCert); // verify the public cert matches the private key Assert.True(CertificateFactory.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true)); Assert.True(CertificateFactory.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true)); } CertificateIdentifierCollection issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in issuerCertificates) { issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert)); } // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateTrustList trustedStore = new CertificateTrustList(); trustedStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(trustedStore, issuerStore, null); Assert.Throws <Opc.Ua.ServiceResultException>(() => { certValidator.Validate(newCert); }); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(newCert); }
private CertificateValidator InitValidatorWithStores() { CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerTrustList = new CertificateTrustList(); issuerTrustList.StoreType = "Directory"; issuerTrustList.StorePath = _issuerStore.Directory.FullName; CertificateTrustList trustedTrustList = new CertificateTrustList(); trustedTrustList.StoreType = "Directory"; trustedTrustList.StorePath = _trustedStore.Directory.FullName; certValidator.Update(issuerTrustList, trustedTrustList, null); return(certValidator); }
private CertificateValidator InitValidatorWithStores() { var certValidator = new CertificateValidator(); var issuerTrustList = new CertificateTrustList { StoreType = "Directory", StorePath = m_issuerStore.Directory.FullName }; var trustedTrustList = new CertificateTrustList { StoreType = "Directory", StorePath = m_trustedStore.Directory.FullName }; certValidator.Update(issuerTrustList, trustedTrustList, null); return(certValidator); }
public static void VerifyApplicationCertIntegrity(byte[] certificate, byte[] privateKey, string privateKeyPassword, string privateKeyFormat, byte[][] issuerCertificates) { X509Certificate2 newCert = new X509Certificate2(certificate); Assert.IsNotNull(newCert); X509Certificate2 newPrivateKeyCert = null; if (privateKeyFormat == "PFX") { newPrivateKeyCert = X509Utils.CreateCertificateFromPKCS12(privateKey, privateKeyPassword); } else if (privateKeyFormat == "PEM") { newPrivateKeyCert = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, privateKeyPassword); } else { Assert.Fail("Invalid private key format"); } Assert.IsNotNull(newPrivateKeyCert); // verify the public cert matches the private key Assert.IsTrue(X509Utils.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true)); Assert.IsTrue(X509Utils.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true)); CertificateIdentifierCollection issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var issuer in issuerCertificates) { var issuerCert = new X509Certificate2(issuer); Assert.IsNotNull(issuerCert); issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert)); } // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateTrustList trustedStore = new CertificateTrustList(); trustedStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(trustedStore, issuerStore, null); Assert.That(() => { certValidator.Validate(newCert); }, Throws.Exception); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(newCert); }
/// <summary> /// Apply the configured settings provided via a CertificateStore to a CertificateTrustList. /// </summary> public static void ApplyLocalConfig( this CertificateTrustList certificateTrustList, CertificateStore certificateStore) { if (certificateTrustList == null) { throw new ArgumentNullException(nameof(certificateTrustList)); } if (certificateStore == null) { throw new ArgumentNullException(nameof(certificateStore)); } if (certificateTrustList.StorePath != certificateStore.StorePath) { certificateTrustList.StoreType = certificateStore.StoreType; certificateTrustList.StorePath = certificateStore.StorePath; } }
public static void VerifyApplicationCertIntegrity( X509Certificate2 newCert, Key privateKey, X509Certificate2Collection issuerCertificates) { Assert.NotNull(newCert); Assert.True(privateKey.HasPrivateKey()); if (privateKey != null) { using (var newPrivateKeyCert = new X509Certificate2(newCert.RawData) { PrivateKey = privateKey.ToRSA() }) { Assert.True(newPrivateKeyCert.HasPrivateKey); Assert.NotNull(newPrivateKeyCert); Assert.True(newPrivateKeyCert.HasPrivateKey); // verify the public cert matches the private key Assert.True(CertificateFactory.VerifyRSAKeyPair(newCert, newPrivateKeyCert, true)); Assert.True(CertificateFactory.VerifyRSAKeyPair(newPrivateKeyCert, newPrivateKeyCert, true)); } } var issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in issuerCertificates) { issuerCertIdCollection.Add(new CertificateIdentifier(issuerCert)); } // verify cert with issuer chain var certValidator = new CertificateValidator(); var issuerStore = new CertificateTrustList(); var trustedStore = new CertificateTrustList { TrustedCertificates = issuerCertIdCollection }; certValidator.Update(trustedStore, issuerStore, null); Assert.Throws <ServiceResultException>(() => certValidator.Validate(newCert)); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(newCert); }
private async Task <bool> UpdateStoreCertificates( CertificateTrustList trustList, X509Certificate2Collection updatedCerts) { bool result = true; ICertificateStore store = null; try { store = trustList.OpenStore(); var storeCerts = await store.Enumerate().ConfigureAwait(false); foreach (var cert in storeCerts) { if (!updatedCerts.Contains(cert)) { if (!store.Delete(cert.Thumbprint).Result) { result = false; } } else { updatedCerts.Remove(cert); } } foreach (var cert in updatedCerts) { await store.Add(cert).ConfigureAwait(false); } } catch { result = false; } finally { store?.Close(); } return(result); }
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); }
/// <summary> /// Creates the validator using the issuer and trusted store. /// </summary> public CertificateValidator Update() { var certValidator = new CertificateValidator(); var issuerTrustList = new CertificateTrustList { StoreType = "Directory", StorePath = m_issuerStore.Directory.FullName }; var trustedTrustList = new CertificateTrustList { StoreType = "Directory", StorePath = m_trustedStore.Directory.FullName }; CertificateStoreIdentifier rejectedList = null; if (m_rejectedStore != null) { rejectedList = new CertificateStoreIdentifier { StoreType = "Directory", StorePath = m_rejectedStore.Directory.FullName }; } certValidator.Update(issuerTrustList, trustedTrustList, rejectedList); m_certificateValidator = certValidator; return(certValidator); }
/// <summary> /// hardcoded application configuration of the collector server/client /// </summary> /// <returns>application configuration of the collector server/client</returns> public static ApplicationConfiguration getConfiguration() { //not fully implemented ApplicationConfiguration config = new ApplicationConfiguration(); config.ApplicationName = "Collector Server"; //config.ApplicationType = null; config.ApplicationUri = @"urn:localhost:UA:InformationModelServer"; //config.CertificateValidator = null; //config.ClientConfiguration = null; //config.DisableHiResClock = null; //config.DiscoveryServerConfiguration = null; #region Extensions List <XmlElement> config_extensions = new List <XmlElement>(); #endregion config.Extensions = new XmlElementCollection(); //config.MessageContext = null; config.ProductUri = @"http://opcfoundation.org/UA/InformationModelServer"; //config.Properties = null; //config.PropertiesLock = null; #region Security Configuration SecurityConfiguration config_security = new SecurityConfiguration(); CertificateIdentifier config_security_certificate = new CertificateIdentifier(); config_security_certificate.StoreType = "Directory"; config_security_certificate.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\own"; config_security_certificate.SubjectName = @"CN = Demo Server, C = US, S = Arizona, O = OPC Foundation, DC = localhost"; config_security.ApplicationCertificate = config_security_certificate; CertificateTrustList config_trustedIssuer = new CertificateTrustList(); config_trustedIssuer.StoreType = "Directory"; config_trustedIssuer.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\issuer"; config_security.TrustedIssuerCertificates = config_trustedIssuer; CertificateTrustList config_security_trustedPeer = new CertificateTrustList(); config_security_trustedPeer.StoreType = "Directory"; config_security_trustedPeer.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\trusted"; config_security.TrustedPeerCertificates = config_security_trustedPeer; CertificateStoreIdentifier config_security_rejected = new CertificateStoreIdentifier(); config_security_rejected.StoreType = "Directory"; config_security_rejected.StorePath = @"%CommonApplicationData%\OPC Foundation\pki\rejected"; config_security.RejectedCertificateStore = config_security_rejected; #endregion config.SecurityConfiguration = config_security; //config_security.ApplicationCertificate = null; #region ServerConfiguration ServerConfiguration config_server = new ServerConfiguration(); List <string> config_server_baseAdress = new List <string>(); config_server_baseAdress.Add(@"https://*****:*****@"opc.tcp://localhost:51210/CollectorServer"); config_server.BaseAddresses = new StringCollection(config_server_baseAdress); List <ServerSecurityPolicy> config_server_policies = new List <ServerSecurityPolicy>(); ServerSecurityPolicy tmp_pol1 = new ServerSecurityPolicy(); tmp_pol1.SecurityMode = MessageSecurityMode.SignAndEncrypt; tmp_pol1.SecurityPolicyUri = @"http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"; config_server_policies.Add(tmp_pol1); ServerSecurityPolicy tmp_pol2 = new ServerSecurityPolicy(); tmp_pol2.SecurityMode = MessageSecurityMode.None; tmp_pol2.SecurityPolicyUri = @"http://opcfoundation.org/UA/SecurityPolicy#None"; config_server_policies.Add(tmp_pol2); ServerSecurityPolicy tmp_pol3 = new ServerSecurityPolicy(); tmp_pol3.SecurityMode = MessageSecurityMode.Sign; tmp_pol3.SecurityPolicyUri = @""; config_server_policies.Add(tmp_pol3); ServerSecurityPolicy tmp_pol4 = new ServerSecurityPolicy(); tmp_pol4.SecurityMode = MessageSecurityMode.SignAndEncrypt; tmp_pol4.SecurityPolicyUri = @""; ServerSecurityPolicyCollection config_server_policy = new ServerSecurityPolicyCollection(config_server_policies); config_server.SecurityPolicies = config_server_policy; List <UserTokenPolicy> config_server_userTokenPolicies = new List <UserTokenPolicy>(); config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Anonymous)); config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.UserName)); config_server_userTokenPolicies.Add(new UserTokenPolicy(UserTokenType.Certificate)); config_server.UserTokenPolicies = new UserTokenPolicyCollection(config_server_userTokenPolicies); config_server.DiagnosticsEnabled = false; config_server.MaxSessionCount = 100; config_server.MinSessionTimeout = 10000; config_server.MaxSessionTimeout = 3600000; config_server.MaxBrowseContinuationPoints = 10; config_server.MaxQueryContinuationPoints = 10; config_server.MaxHistoryContinuationPoints = 100; config_server.MaxRequestAge = 600000; config_server.MinPublishingInterval = 100; config_server.MaxPublishingInterval = 3600000; config_server.PublishingResolution = 50; config_server.MaxSubscriptionLifetime = 3600000; config_server.MaxMessageQueueSize = 10; config_server.MaxNotificationQueueSize = 100; config_server.MaxNotificationsPerPublish = 1000; config_server.MinMetadataSamplingInterval = 1000; List <SamplingRateGroup> config_server_samplingRateGroups = new List <SamplingRateGroup>(); config_server_samplingRateGroups.Add(new SamplingRateGroup(5, 5, 20)); config_server_samplingRateGroups.Add(new SamplingRateGroup(100, 100, 4)); config_server_samplingRateGroups.Add(new SamplingRateGroup(500, 250, 2)); config_server_samplingRateGroups.Add(new SamplingRateGroup(1000, 500, 20)); config_server.AvailableSamplingRates = new SamplingRateGroupCollection(config_server_samplingRateGroups); config_server.MaxRegistrationInterval = 30000; #endregion config.ServerConfiguration = config_server; //config.SourceFilePath = null; #region TraceConfiguration TraceConfiguration config_traceConfiguration = new TraceConfiguration(); config_traceConfiguration.OutputFilePath = @"Logs\Quickstarts.BoilerServer.log.txt"; config_traceConfiguration.DeleteOnLoad = true; config_traceConfiguration.TraceMasks = 515; #endregion config.TraceConfiguration = config_traceConfiguration; config.TransportConfigurations = new TransportConfigurationCollection(); #region TransportQuotas TransportQuotas config_transportQuotas = new TransportQuotas(); config_transportQuotas.OperationTimeout = 600000; config_transportQuotas.MaxStringLength = 1048576; config_transportQuotas.MaxByteStringLength = 1048576; config_transportQuotas.MaxArrayLength = 65535; config_transportQuotas.ChannelLifetime = 300000; config_transportQuotas.SecurityTokenLifetime = 3600000; #endregion config.TransportQuotas = config_transportQuotas; return(config); }
private ServiceResult UpdateCertificate( ISystemContext context, MethodState method, NodeId objectId, NodeId certificateGroupId, NodeId certificateTypeId, byte[] certificate, byte[][] issuerCertificates, string privateKeyFormat, byte[] privateKey, ref bool applyChangesRequired) { HasApplicationSecureAdminAccess(context); if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } privateKeyFormat = privateKeyFormat?.ToUpper(); if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX")) { throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported."); } ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId); certificateGroup.UpdateCertificate = null; X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection(); X509Certificate2 newCert; try { // build issuer chain if (issuerCertificates != null) { foreach (byte[] issuerRawCert in issuerCertificates) { var newIssuerCert = new X509Certificate2(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } newCert = new X509Certificate2(certificate); } catch { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid."); } // load existing application cert and private key if (!Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application."); } // self signed bool selfSigned = Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer); if (selfSigned && newIssuerCollection.Count != 0) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate."); } if (!selfSigned) { try { // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in newIssuerCollection) { issuerCollection.Add(new CertificateIdentifier(issuerCert)); } issuerStore.TrustedCertificates = issuerCollection; certValidator.Update(issuerStore, issuerStore, null); certValidator.Validate(newCert); } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list."); } } var updateCertificate = new UpdateCertificateData(); try { string password = String.Empty; switch (privateKeyFormat) { case null: case "": { X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKey(password).Result; updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PFX": { X509Certificate2 certWithPrivateKey = CertificateFactory.CreateCertificateFromPKCS12(privateKey, password); updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PEM": { updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, password); break; } } updateCertificate.IssuerCollection = newIssuerCollection; updateCertificate.SessionId = context.SessionId; } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key."); } certificateGroup.UpdateCertificate = updateCertificate; applyChangesRequired = true; return(ServiceResult.Good); }
public static void VerifySignedApplicationCert(ApplicationTestData testApp, X509Certificate2 signedCert, X509Certificate2Collection issuerCerts) { var issuerCert = issuerCerts[0]; var signedCertO = signedCert.ToCertificate(); Assert.NotNull(signedCertO); Assert.False(signedCert.HasPrivateKey); Assert.True(Utils.CompareDistinguishedName(testApp.Subject, signedCert.Subject)); Assert.False(Utils.CompareDistinguishedName(signedCert.Issuer, signedCert.Subject)); Assert.True(Utils.CompareDistinguishedName(signedCert.Issuer, issuerCert.Subject)); // test basic constraints var constraints = signedCertO.GetBasicConstraintsExtension(); Assert.NotNull(constraints); Assert.True(constraints.Critical); Assert.False(constraints.CertificateAuthority); Assert.False(constraints.HasPathLengthConstraint); // key usage var keyUsage = signedCertO.GetKeyUsageExtension(); Assert.NotNull(keyUsage); Assert.True(keyUsage.Critical); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.CrlSign) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DataEncipherment) == X509KeyUsageFlags.DataEncipherment); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DecipherOnly) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) == X509KeyUsageFlags.DigitalSignature); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.EncipherOnly) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyAgreement) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyCertSign) == 0); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.KeyEncipherment) == X509KeyUsageFlags.KeyEncipherment); Assert.True((keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) == X509KeyUsageFlags.NonRepudiation); // enhanced key usage var enhancedKeyUsage = signedCertO.GetEnhancedKeyUsageExtension(); Assert.NotNull(enhancedKeyUsage); Assert.True(enhancedKeyUsage.Critical); // test for authority key var authority = signedCertO.GetAuthorityKeyIdentifierExtension(); Assert.NotNull(authority); Assert.NotNull(authority.SerialNumber); Assert.NotNull(authority.KeyId); Assert.NotNull(authority.AuthorityNames); // verify authority key in signed cert var subjectKeyId = signedCertO.GetSubjectKeyIdentifierExtension(); Assert.Equal(subjectKeyId.SubjectKeyIdentifier, authority.KeyId); Assert.Equal(issuerCert.SerialNumber, authority.SerialNumber.ToString()); var subjectAlternateName = signedCertO.GetSubjectAltNameExtension(); Assert.NotNull(subjectAlternateName); Assert.False(subjectAlternateName.Critical); var domainNames = Utils.GetDomainsFromCertficate(signedCert); foreach (var domainName in testApp.DomainNames) { Assert.Contains(domainName, domainNames, StringComparer.OrdinalIgnoreCase); } Assert.True(subjectAlternateName.Uris.Count == 1); var applicationUri = Utils.GetApplicationUriFromCertificate(signedCert); Assert.True(testApp.ApplicationRecord.ApplicationUri == applicationUri); var issuerCertIdCollection = new CertificateIdentifierCollection(); foreach (var cert in issuerCerts) { issuerCertIdCollection.Add(new CertificateIdentifier(cert)); } // verify cert with issuer chain var certValidator = new CertificateValidator(); var issuerStore = new CertificateTrustList(); var trustedStore = new CertificateTrustList { TrustedCertificates = issuerCertIdCollection }; certValidator.Update(trustedStore, issuerStore, null); Assert.Throws <ServiceResultException>(() => certValidator.Validate(signedCert)); issuerStore.TrustedCertificates = issuerCertIdCollection; certValidator.Update(issuerStore, trustedStore, null); certValidator.Validate(signedCert); }
private ServiceResult UpdateCertificate( ISystemContext context, MethodState method, NodeId objectId, NodeId certificateGroupId, NodeId certificateTypeId, byte[] certificate, byte[][] issuerCertificates, string privateKeyFormat, byte[] privateKey, ref bool applyChangesRequired) { HasApplicationSecureAdminAccess(context); if (certificate == null) { throw new ArgumentNullException(nameof(certificate)); } privateKeyFormat = privateKeyFormat?.ToUpper(); if (!(String.IsNullOrEmpty(privateKeyFormat) || privateKeyFormat == "PEM" || privateKeyFormat == "PFX")) { throw new ServiceResultException(StatusCodes.BadNotSupported, "The private key format is not supported."); } ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId); certificateGroup.UpdateCertificate = null; X509Certificate2Collection newIssuerCollection = new X509Certificate2Collection(); X509Certificate2 newCert; try { // build issuer chain if (issuerCertificates != null) { foreach (byte[] issuerRawCert in issuerCertificates) { var newIssuerCert = new X509Certificate2(issuerRawCert); newIssuerCollection.Add(newIssuerCert); } } newCert = new X509Certificate2(certificate); } catch { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Certificate data is invalid."); } // validate new subject matches the previous subject if (!X509Utils.CompareDistinguishedName(certificateGroup.ApplicationCertificate.SubjectName, newCert.SubjectName.Name)) { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Subject Name of new certificate doesn't match the application."); } // self signed bool selfSigned = X509Utils.CompareDistinguishedName(newCert.Subject, newCert.Issuer); if (selfSigned && newIssuerCollection.Count != 0) { throw new ServiceResultException(StatusCodes.BadCertificateInvalid, "Issuer list not empty for self signed certificate."); } if (!selfSigned) { try { // verify cert with issuer chain CertificateValidator certValidator = new CertificateValidator(); CertificateTrustList issuerStore = new CertificateTrustList(); CertificateIdentifierCollection issuerCollection = new CertificateIdentifierCollection(); foreach (var issuerCert in newIssuerCollection) { issuerCollection.Add(new CertificateIdentifier(issuerCert)); } issuerStore.TrustedCertificates = issuerCollection; certValidator.Update(issuerStore, issuerStore, null); certValidator.Validate(newCert); } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the issuer list."); } } var updateCertificate = new UpdateCertificateData(); try { var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; switch (privateKeyFormat) { case null: case "": { X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKeyEx(passwordProvider).Result; updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PFX": { X509Certificate2 certWithPrivateKey = X509Utils.CreateCertificateFromPKCS12(privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPrivateKey(newCert, certWithPrivateKey); break; } case "PEM": { updateCertificate.CertificateWithPrivateKey = CertificateFactory.CreateCertificateWithPEMPrivateKey(newCert, privateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)); break; } } updateCertificate.IssuerCollection = newIssuerCollection; updateCertificate.SessionId = context.SessionId; } catch { throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to verify integrity of the new certificate and the private key."); } certificateGroup.UpdateCertificate = updateCertificate; applyChangesRequired = true; if (updateCertificate != null) { try { using (ICertificateStore appStore = certificateGroup.ApplicationCertificate.OpenStore()) { Utils.LogCertificate(Utils.TraceMasks.Security, "Delete application certificate: ", certificateGroup.ApplicationCertificate.Certificate); appStore.Delete(certificateGroup.ApplicationCertificate.Thumbprint).Wait(); Utils.LogCertificate(Utils.TraceMasks.Security, "Add new application certificate: ", updateCertificate.CertificateWithPrivateKey); var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider; appStore.Add(updateCertificate.CertificateWithPrivateKey, passwordProvider?.GetPassword(certificateGroup.ApplicationCertificate)).Wait(); // keep only track of cert without private key var certOnly = new X509Certificate2(updateCertificate.CertificateWithPrivateKey.RawData); updateCertificate.CertificateWithPrivateKey.Dispose(); updateCertificate.CertificateWithPrivateKey = certOnly; } using (ICertificateStore issuerStore = CertificateStoreIdentifier.OpenStore(certificateGroup.IssuerStorePath)) { foreach (var issuer in updateCertificate.IssuerCollection) { try { Utils.LogCertificate(Utils.TraceMasks.Security, "Add new issuer certificate: ", issuer); issuerStore.Add(issuer).Wait(); } catch (ArgumentException) { // ignore error if issuer cert already exists } } } } catch (Exception ex) { Utils.LogError(Utils.TraceMasks.Security, ServiceResult.BuildExceptionTrace(ex)); throw new ServiceResultException(StatusCodes.BadSecurityChecksFailed, "Failed to update certificate.", ex); } } return(ServiceResult.Good); }
public CapiCtlWrapper(CertificateTrustList certificateTrustList) { ctl = certificateTrustList; }