/// <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 (X509Utils.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);
                                }
                            }
                        }
                    }
            }
        }
Example #2
0
        // Encrypts the given element with the certificate specified. The certificate is added as
        // an X509Data KeyInfo to an EncryptedKey (AES session key) generated randomly.
        public EncryptedData Encrypt(XmlElement inputElement, X509Certificate2 certificate)
        {
            if (inputElement == null)
            {
                throw new ArgumentNullException("inputElement");
            }
            if (certificate == null)
            {
                throw new ArgumentNullException("certificate");
            }

            if (X509Utils.OidToAlgId(certificate.PublicKey.Oid.Value) != CAPI.CALG_RSA_KEYX)
            {
                throw new NotSupportedException(SecurityResources.GetResourceString("NotSupported_KeyAlgorithm"));
            }

            // Create the EncryptedData object, using an AES-256 session key by default.
            EncryptedData ed = new EncryptedData();

            ed.Type             = EncryptedXml.XmlEncElementUrl;
            ed.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncAES256Url);

            // Include the certificate in the EncryptedKey KeyInfo.
            EncryptedKey ek = new EncryptedKey();

            ek.EncryptionMethod = new EncryptionMethod(EncryptedXml.XmlEncRSA15Url);
            ek.KeyInfo.AddClause(new KeyInfoX509Data(certificate));

            // Create a random AES session key and encrypt it with the public key associated with the certificate.
            RijndaelManaged rijn = new RijndaelManaged();

            ek.CipherData.CipherValue = EncryptedXml.EncryptKey(rijn.Key, certificate.PublicKey.Key as RSA, false);

            // Encrypt the input element with the random session key that we've created above.
            KeyInfoEncryptedKey kek = new KeyInfoEncryptedKey(ek);

            ed.KeyInfo.AddClause(kek);
            ed.CipherData.CipherValue = EncryptData(inputElement, rijn, false);

            return(ed);
        }
Example #3
0
 public void UpdateCertificateSelfSignedNoPrivateKey()
 {
     ConnectPushClient(true);
     using (X509Certificate2 invalidCert = CertificateFactory.CreateCertificate(null, null, null, "uri:x:y:z", "TestApp", "CN=Push Server Test", null, 2048, DateTime.UtcNow, 1, 256))
         using (X509Certificate2 serverCert = new X509Certificate2(_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate))
         {
             if (!X509Utils.CompareDistinguishedName(serverCert.Subject, serverCert.Issuer))
             {
                 Assert.Ignore("Server has no self signed cert in use.");
             }
             byte[] invalidRawCert = { 0xba, 0xd0, 0xbe, 0xef, 3 };
             // negative test all parameter combinations
             NodeId invalidCertGroup = new NodeId(333);
             NodeId invalidCertType  = new NodeId(Guid.NewGuid());
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, null, null, null, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(invalidCertGroup, null, serverCert.RawData, null, null, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, invalidCertType, serverCert.RawData, null, null, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(invalidCertGroup, invalidCertType, serverCert.RawData, null, null, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, invalidRawCert, null, null, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, invalidCert.RawData, null, null, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, serverCert.RawData, "XYZ", null, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, serverCert.RawData, "XYZ", invalidCert.RawData, null); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, invalidCert.RawData, null, null, new byte[][] { serverCert.RawData, invalidCert.RawData }); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, null, null, null, new byte[][] { serverCert.RawData, invalidCert.RawData }); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, invalidRawCert, null, null, new byte[][] { serverCert.RawData, invalidCert.RawData }); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, serverCert.RawData, null, null, new byte[][] { serverCert.RawData, invalidRawCert }); }, Throws.Exception);
             Assert.That(() => { _pushClient.PushClient.UpdateCertificate(null, null, serverCert.RawData, null, null, null); }, Throws.Exception);
             var success = _pushClient.PushClient.UpdateCertificate(
                 null,
                 _pushClient.PushClient.ApplicationCertificateType,
                 serverCert.RawData,
                 null,
                 null,
                 null);
             if (success)
             {
                 _pushClient.PushClient.ApplyChanges();
             }
             VerifyNewPushServerCert(serverCert.RawData);
         }
 }
        public void CreateSelfSignedForRSACustomHashDefaultKey(
            KeyHashPair keyHashPair
            )
        {
            // default cert with custom HashAlgorithm
            var cert = CertificateBuilder.Create(Subject)
                       .SetHashAlgorithm(keyHashPair.HashAlgorithmName)
                       .CreateForRSA();

            Assert.NotNull(cert);
            WriteCertificate(cert, $"Default RSA {keyHashPair.HashAlgorithmName} cert");
            Assert.AreEqual(Subject, cert.Subject);
            Assert.AreEqual(X509Defaults.RSAKeySize, cert.GetRSAPublicKey().KeySize);
            Assert.AreEqual(keyHashPair.HashAlgorithmName, Oids.GetHashAlgorithmName(cert.SignatureAlgorithm.Value));
            var basicConstraintsExtension = X509Extensions.FindExtension <X509BasicConstraintsExtension>(cert.Extensions);

            Assert.NotNull(basicConstraintsExtension);
            Assert.True(basicConstraintsExtension.CertificateAuthority);
            X509Utils.VerifyRSAKeyPair(cert, cert, true);
            Assert.True(X509Utils.VerifySelfSigned(cert));
        }
Example #5
0
        public void CreateSelfSignedForRSAAllFields(
            KeyHashPair keyHashPair
            )
        {
            // set dates and extension
            var applicationUri = "urn:opcfoundation.org:mypc";
            var domains        = new string[] { "mypc", "mypc.opcfoundation.org", "192.168.1.100" };
            var cert           = CertificateBuilder.Create(Subject)
                                 .SetNotBefore(DateTime.Today.AddYears(-1))
                                 .SetNotAfter(DateTime.Today.AddYears(25))
                                 .AddExtension(new X509SubjectAltNameExtension(applicationUri, domains))
                                 .SetHashAlgorithm(keyHashPair.HashAlgorithmName)
                                 .SetRSAKeySize(keyHashPair.KeySize)
                                 .CreateForRSA();

            Assert.NotNull(cert);
            WriteCertificate(cert, $"Default cert RSA {keyHashPair.KeySize} with modified lifetime and alt name extension");
            Assert.AreEqual(Subject, cert.Subject);
            using (var privateKey = cert.GetRSAPrivateKey())
            {
                Assert.NotNull(privateKey);
                privateKey.ExportParameters(false);
                privateKey.ExportParameters(true);
            }
            using (var publicKey = cert.GetRSAPublicKey())
            {
                Assert.NotNull(publicKey);
                publicKey.ExportParameters(false);
            }
            Assert.AreEqual(keyHashPair.KeySize, cert.GetRSAPublicKey().KeySize);
            Assert.AreEqual(keyHashPair.HashAlgorithmName, Oids.GetHashAlgorithmName(cert.SignatureAlgorithm.Value));
            var basicConstraintsExtension = X509Extensions.FindExtension <X509BasicConstraintsExtension>(cert.Extensions);

            Assert.NotNull(basicConstraintsExtension);
            Assert.True(basicConstraintsExtension.CertificateAuthority);
            X509Utils.VerifyRSAKeyPair(cert, cert, true);
            Assert.True(X509Utils.VerifySelfSigned(cert));
            CheckPEMWriter(cert);
        }
        public void CreateSelfSignedForRSADefaultTest()
        {
            // default cert
            X509Certificate2 cert = CertificateBuilder.Create(Subject).CreateForRSA();

            Assert.NotNull(cert);
            WriteCertificate(cert, "Default RSA cert");
            Assert.NotNull(cert.GetRSAPrivateKey());
            var publicKey = cert.GetRSAPublicKey();

            Assert.NotNull(publicKey);
            Assert.AreEqual(X509Defaults.RSAKeySize, publicKey.KeySize);
            Assert.AreEqual(X509Defaults.HashAlgorithmName, Oids.GetHashAlgorithmName(cert.SignatureAlgorithm.Value));
            Assert.AreEqual(DateTime.UtcNow.AddDays(-1).Date, cert.NotBefore.ToUniversalTime());
            Assert.AreEqual(cert.NotBefore.ToUniversalTime().AddMonths(X509Defaults.LifeTime), cert.NotAfter.ToUniversalTime());
            var basicConstraintsExtension = X509Extensions.FindExtension <X509BasicConstraintsExtension>(cert.Extensions);

            Assert.NotNull(basicConstraintsExtension);
            Assert.True(basicConstraintsExtension.CertificateAuthority);
            X509Utils.VerifyRSAKeyPair(cert, cert);
            X509Utils.VerifySelfSigned(cert);
        }
Example #7
0
        private static unsafe int VerifyCertificate(X509Certificate2 certificate,
                                                    X509Certificate2Collection extraStore)
        {
            int dwErrorStatus;
            int hr = X509Utils.VerifyCertificate(X509Utils.GetCertContext(certificate),
                                                 null,
                                                 null,
                                                 X509RevocationMode.Online,
                                                 X509RevocationFlag.ExcludeRoot,
                                                 DateTime.Now,
                                                 new TimeSpan(0, 0, 0),
                                                 extraStore,
                                                 new IntPtr(CAPI.CERT_CHAIN_POLICY_BASE),
                                                 new IntPtr(&dwErrorStatus));

            if (hr != CAPI.S_OK)
            {
                return(dwErrorStatus);
            }

            // Check key usages to make sure it is good for signing.
            foreach (X509Extension extension in certificate.Extensions)
            {
                if (String.Compare(extension.Oid.Value, CAPI.szOID_KEY_USAGE, StringComparison.OrdinalIgnoreCase) == 0)
                {
                    X509KeyUsageExtension keyUsage = new X509KeyUsageExtension();
                    keyUsage.CopyFrom(extension);
                    if ((keyUsage.KeyUsages & X509KeyUsageFlags.DigitalSignature) == 0 &&
                        (keyUsage.KeyUsages & X509KeyUsageFlags.NonRepudiation) == 0)
                    {
                        hr = CAPI.CERT_E_WRONG_USAGE;
                        break;
                    }
                }
            }

            return(hr);
        }
        public void CreateCACertForECDsa(
            ECCurveHashPair ecCurveHashPair
            )
        {
            // create a CA cert
            var cert = CertificateBuilder.Create(Subject)
                       .SetCAConstraint()
                       .SetHashAlgorithm(ecCurveHashPair.HashAlgorithmName)
                       .AddExtension(X509Extensions.BuildX509CRLDistributionPoints("http://myca/mycert.crl"))
                       .SetECCurve(ecCurveHashPair.Curve)
                       .CreateForECDsa();

            Assert.NotNull(cert);
            WriteCertificate(cert, "Default cert with RSA {keyHashPair.KeySize} {keyHashPair.HashAlgorithmName} and CRL distribution points");
            Assert.AreEqual(ecCurveHashPair.HashAlgorithmName, Oids.GetHashAlgorithmName(cert.SignatureAlgorithm.Value));
            var basicConstraintsExtension = X509Extensions.FindExtension <X509BasicConstraintsExtension>(cert.Extensions);

            Assert.NotNull(basicConstraintsExtension);
            Assert.True(basicConstraintsExtension.CertificateAuthority);
            Assert.False(basicConstraintsExtension.HasPathLengthConstraint);
            X509PfxUtils.VerifyECDsaKeyPair(cert, cert, true);
            Assert.True(X509Utils.VerifySelfSigned(cert));
        }
        public void VerifyOneSelfSignedAppCertForAll()
        {
            var builder = CertificateBuilder.Create(Subject)
                          .SetNotBefore(DateTime.Today.AddYears(-1))
                          .SetNotAfter(DateTime.Today.AddYears(25))
                          .AddExtension(new X509SubjectAltNameExtension("urn:opcfoundation.org:mypc", new string[] { "mypc", "mypc.opcfoundation.org", "192.168.1.100" }));

            byte[] previousSerialNumber = null;
            foreach (var keyHash in KeyHashPairs)
            {
                var cert = builder
                           .SetHashAlgorithm(keyHash.HashAlgorithmName)
                           .SetRSAKeySize(keyHash.KeySize)
                           .CreateForRSA();
                Assert.NotNull(cert);
                WriteCertificate(cert, $"Default cert with RSA {keyHash.KeySize} {keyHash.HashAlgorithmName} signature.");
                Assert.AreEqual(keyHash.HashAlgorithmName, Oids.GetHashAlgorithmName(cert.SignatureAlgorithm.Value));
                // ensure serial numbers are different
                Assert.AreNotEqual(previousSerialNumber, cert.GetSerialNumber());
                X509PfxUtils.VerifyRSAKeyPair(cert, cert, true);
                Assert.True(X509Utils.VerifySelfSigned(cert));
            }
        }
Example #10
0
 public void UpdateCertificateSelfSignedNoPrivateKey()
 {
     ConnectPushClient(true);
     using (X509Certificate2 serverCert = new X509Certificate2(m_pushClient.PushClient.Session.ConfiguredEndpoint.Description.ServerCertificate))
     {
         if (!X509Utils.CompareDistinguishedName(serverCert.Subject, serverCert.Issuer))
         {
             Assert.Ignore("Server has no self signed cert in use.");
         }
         var success = m_pushClient.PushClient.UpdateCertificate(
             null,
             m_pushClient.PushClient.ApplicationCertificateType,
             serverCert.RawData,
             null,
             null,
             null);
         if (success)
         {
             m_pushClient.PushClient.ApplyChanges();
         }
         VerifyNewPushServerCert(serverCert.RawData);
     }
 }
Example #11
0
            /// <summary>
            /// Verifies that a certificate user token is trusted.
            /// </summary>
            private bool VerifyCertificate(X509Certificate2 certificate)
            {
                try {
                    if (_certificateValidator != null)
                    {
                        _certificateValidator.Validate(certificate);
                    }
                    else
                    {
                        CertificateValidator.Validate(certificate);
                    }

                    // determine if self-signed.
                    var isSelfSigned = X509Utils.CompareDistinguishedName(
                        certificate.Subject, certificate.Issuer);

                    // do not allow self signed application certs as user token
                    if (isSelfSigned && X509Utils.HasApplicationURN(certificate))
                    {
                        throw new ServiceResultException(StatusCodes.BadCertificateUseNotAllowed);
                    }
                    return(false);
                }
                catch (Exception e) {
                    TranslationInfo info;
                    StatusCode      result = StatusCodes.BadIdentityTokenRejected;
                    if (e is ServiceResultException se &&
                        se.StatusCode == StatusCodes.BadCertificateUseNotAllowed)
                    {
                        info = new TranslationInfo(
                            "InvalidCertificate",
                            "en-US",
                            "'{0}' is an invalid user certificate.",
                            certificate.Subject);

                        result = StatusCodes.BadIdentityTokenInvalid;
                    }
        /// <summary>
        /// Create OPC UA client configuration
        /// </summary>
        /// <returns></returns>
        /// <param name="clientName"></param>
        /// <param name="configPath"></param>
        /// <exception cref="ArgumentNullException"></exception>
        public async Task <ApplicationConfiguration> CreateOpcUaConfiguration(string clientName,
                                                                              string configPath)
        {
            if (string.IsNullOrWhiteSpace(clientName))
            {
                throw new ArgumentNullException(nameof(clientName));
            }
            if (string.IsNullOrWhiteSpace(configPath))
            {
                throw new ArgumentNullException(nameof(configPath));
            }

            var application = new ApplicationInstance
            {
                ApplicationName   = clientName,
                ApplicationType   = ApplicationType.Client,
                ConfigSectionName = clientName,
            };

            var clientApplicationConfig = await application.LoadApplicationConfiguration(filePath : configPath,
                                                                                         silent : false);

            var haveAppCertificate = await application.CheckApplicationInstanceCertificate(silent : false,
                                                                                           minimumKeySize : 0);

            if (!haveAppCertificate)
            {
                throw new Exception(Text.InvalidCertificate);
            }

            clientApplicationConfig.ApplicationUri = X509Utils.GetApplicationUriFromCertificate(certificate: clientApplicationConfig.SecurityConfiguration.ApplicationCertificate.Certificate);

            clientApplicationConfig.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(this.SessionAutoAcceptCertificate_Event);

            return(clientApplicationConfig);
        }
        public void VerifyCACerts(
            KeyHashPair keyHashPair
            )
        {
            var subject = "CN=CA Test Cert";
            int pathLengthConstraint = (keyHashPair.KeySize / 512) - 3;
            var cert = CertificateFactory.CreateCertificate(subject)
                       .SetLifeTime(25 * 12)
                       .SetHashAlgorithm(keyHashPair.HashAlgorithmName)
                       .SetCAConstraint(pathLengthConstraint)
                       .SetRSAKeySize(keyHashPair.KeySize)
                       .CreateForRSA();

            Assert.NotNull(cert);
            Assert.NotNull(cert.RawData);
            Assert.True(cert.HasPrivateKey);
            var plainCert = new X509Certificate2(cert.RawData);

            Assert.NotNull(plainCert);
            VerifyCACert(plainCert, subject, pathLengthConstraint);
            X509Utils.VerifyRSAKeyPair(cert, cert, true);
            Assert.True(X509Utils.VerifySelfSigned(cert));
            m_rootCACertificate[keyHashPair.KeySize] = cert;
        }
        void NewKeyStore(object o)
        {
            var passwordBoxes = (object[])o;

            var errors = ValidateInputs(passwordBoxes);

            if (!errors.ToString().IsNullOrEmpty())
            {
                MessageBoxContent = new MessageBoxViewModel(CloseMessageBox,
                                                            MessageBoxModel.Error("Errors generating Certificate - " +
                                                                                  Environment.NewLine +
                                                                                  errors.ToString()));
                IsMessageBoxVisible = true;
                return;
            }
            var password = ((PasswordBox)passwordBoxes[0]).Password.ToCharArray();
            var keygen   = KeyPairUtils.CreateGenerator(Repository.Srand, Model.KeyPairGenerator, Model.KeyStrength);
            var keypair  = keygen.GenerateKeyPair();
            var repo     = Repository.Instance;

            repo.NewCertificateAuthority(Model.CARepositoryPath, password);
            repo.KeyPairType = Model.KeyPairType;
            var cert = X509Utils.GenerateCACertificate(Model.X509Name,
                                                       Model.Validity,
                                                       keypair.Public,
                                                       keypair.Private,
                                                       Model.SignatureAlgorithm,
                                                       KeyUsageUtils.GetKeyUsage(Model.KeyUsages),
                                                       Model.ExtendedKeyUsages == null ? null : new ExtendedKeyUsage(KeyUsageUtils.GetExtendedKeyUsages(Model.ExtendedKeyUsages)),
                                                       Model.PathLenContraint);

            X509Utils.ExportPKCS12(Repository.Instance.CAKeyStore, /*Model.CommonName*/ "ca", keypair.Private, password, cert);
            File.WriteAllText(Repository.CaPfxFilename, PemUtilities.Encode(cert));
            _newCaCompletedAction.Invoke(new KeyStoreViewModel(password, Model.CARepositoryPath));
            //KeyStoreViewModelEx.Instance.Load(password);
        }
        /// <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);
        }
Example #16
0
        internal static X509Certificate2Collection BuildBagOfCerts(KeyInfoX509Data keyInfoX509Data, CertUsageType certUsageType)
        {
            X509Certificate2Collection collection = new X509Certificate2Collection();
            ArrayList decryptionIssuerSerials     = (certUsageType == CertUsageType.Decryption ? new ArrayList() : null);

            if (keyInfoX509Data.Certificates != null)
            {
                foreach (X509Certificate2 certificate in keyInfoX509Data.Certificates)
                {
                    switch (certUsageType)
                    {
                    case CertUsageType.Verification:
                        collection.Add(certificate);
                        break;

                    case CertUsageType.Decryption:
                        decryptionIssuerSerials.Add(new X509IssuerSerial(certificate.IssuerName.Name, certificate.SerialNumber));
                        break;
                    }
                }
            }

            if (keyInfoX509Data.SubjectNames == null && keyInfoX509Data.IssuerSerials == null &&
                keyInfoX509Data.SubjectKeyIds == null && decryptionIssuerSerials == null)
            {
                return(collection);
            }

            // Open LocalMachine and CurrentUser "Other People"/"My" stores.

            // Assert OpenStore since we are not giving back any certificates to the user.
            StorePermission sp = new StorePermission(StorePermissionFlags.OpenStore);

            sp.Assert();

            X509Store[] stores    = new X509Store[2];
            string      storeName = (certUsageType == CertUsageType.Verification ? "AddressBook" : "My");

            stores[0] = new X509Store(storeName, StoreLocation.CurrentUser);
            stores[1] = new X509Store(storeName, StoreLocation.LocalMachine);

            for (int index = 0; index < stores.Length; index++)
            {
                if (stores[index] != null)
                {
                    X509Certificate2Collection filters = null;
                    // We don't care if we can't open the store.
                    try {
                        stores[index].Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
                        filters = stores[index].Certificates;
                        stores[index].Close();
                        if (keyInfoX509Data.SubjectNames != null)
                        {
                            foreach (string subjectName in keyInfoX509Data.SubjectNames)
                            {
                                filters = filters.Find(X509FindType.FindBySubjectDistinguishedName, subjectName, false);
                            }
                        }
                        if (keyInfoX509Data.IssuerSerials != null)
                        {
                            foreach (X509IssuerSerial issuerSerial in keyInfoX509Data.IssuerSerials)
                            {
                                filters = filters.Find(X509FindType.FindByIssuerDistinguishedName, issuerSerial.IssuerName, false);
                                filters = filters.Find(X509FindType.FindBySerialNumber, issuerSerial.SerialNumber, false);
                            }
                        }
                        if (keyInfoX509Data.SubjectKeyIds != null)
                        {
                            foreach (byte[] ski in keyInfoX509Data.SubjectKeyIds)
                            {
                                string hex = X509Utils.EncodeHexString(ski);
                                filters = filters.Find(X509FindType.FindBySubjectKeyIdentifier, hex, false);
                            }
                        }
                        if (decryptionIssuerSerials != null)
                        {
                            foreach (X509IssuerSerial issuerSerial in decryptionIssuerSerials)
                            {
                                filters = filters.Find(X509FindType.FindByIssuerDistinguishedName, issuerSerial.IssuerName, false);
                                filters = filters.Find(X509FindType.FindBySerialNumber, issuerSerial.SerialNumber, false);
                            }
                        }
                    }
                    catch (CryptographicException) {}

                    if (filters != null)
                    {
                        collection.AddRange(filters);
                    }
                }
            }

            return(collection);
        }
Example #17
0
        /// <summary>
        /// Adds the certificate to the Trusted Certificate Store
        /// </summary>
        /// <param name="configuration">The application's configuration which specifies the location of the TrustedStore.</param>
        /// <param name="certificate">The certificate to register.</param>
        private static async Task AddToTrustedStore(ApplicationConfiguration configuration, X509Certificate2 certificate)
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }

            string storePath = null;

            if (configuration != null && configuration.SecurityConfiguration != null && configuration.SecurityConfiguration.TrustedPeerCertificates != null)
            {
                storePath = configuration.SecurityConfiguration.TrustedPeerCertificates.StorePath;
            }

            if (String.IsNullOrEmpty(storePath))
            {
                Utils.Trace(Utils.TraceMasks.Information, "WARNING: Trusted peer store not specified.");
                return;
            }

            try
            {
                ICertificateStore store = configuration.SecurityConfiguration.TrustedPeerCertificates.OpenStore();

                if (store == null)
                {
                    Utils.Trace("Could not open trusted peer store. StorePath={0}", storePath);
                    return;
                }

                try
                {
                    // check if it already exists.
                    X509Certificate2Collection existingCertificates = await store.FindByThumbprint(certificate.Thumbprint);

                    if (existingCertificates.Count > 0)
                    {
                        return;
                    }

                    Utils.Trace(Utils.TraceMasks.Information, "Adding certificate to trusted peer store. StorePath={0}", storePath);

                    List <string> subjectName = X509Utils.ParseDistinguishedName(certificate.Subject);

                    // check for old certificate.
                    X509Certificate2Collection certificates = await store.Enumerate();

                    for (int ii = 0; ii < certificates.Count; ii++)
                    {
                        if (X509Utils.CompareDistinguishedName(certificates[ii], subjectName))
                        {
                            if (certificates[ii].Thumbprint == certificate.Thumbprint)
                            {
                                return;
                            }

                            await store.Delete(certificates[ii].Thumbprint);

                            break;
                        }
                    }

                    // add new certificate.
                    X509Certificate2 publicKey = new X509Certificate2(certificate.RawData);
                    await store.Add(publicKey);
                }
                finally
                {
                    store.Close();
                }
            }
            catch (Exception e)
            {
                Utils.Trace(e, "Could not add certificate to trusted peer store. StorePath={0}", storePath);
            }
        }
Example #18
0
        /// <summary>
        /// Checks that the domains in the server addresses match the domains in the certificates.
        /// </summary>
        private static async Task <bool> CheckDomainsInCertificate(
            ApplicationConfiguration configuration,
            X509Certificate2 certificate,
            bool silent)
        {
            Utils.Trace(Utils.TraceMasks.Information, "Checking domains in certificate. {0}", certificate.Subject);

            bool           valid                  = true;
            IList <string> serverDomainNames      = configuration.GetServerDomainNames();
            IList <string> certificateDomainNames = X509Utils.GetDomainsFromCertficate(certificate);

            // get computer name.
            string computerName = Utils.GetHostName();

            // get IP addresses.
            IPAddress[] addresses = null;

            for (int ii = 0; ii < serverDomainNames.Count; ii++)
            {
                if (Utils.FindStringIgnoreCase(certificateDomainNames, serverDomainNames[ii]))
                {
                    continue;
                }

                if (String.Compare(serverDomainNames[ii], "localhost", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (Utils.FindStringIgnoreCase(certificateDomainNames, computerName))
                    {
                        continue;
                    }

                    // check for aliases.
                    bool found = false;

                    // get IP addresses only if necessary.
                    if (addresses == null)
                    {
                        addresses = await Utils.GetHostAddressesAsync(computerName);
                    }

                    // check for ip addresses.
                    for (int jj = 0; jj < addresses.Length; jj++)
                    {
                        if (Utils.FindStringIgnoreCase(certificateDomainNames, addresses[jj].ToString()))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        continue;
                    }
                }

                string message = Utils.Format(
                    "The server is configured to use domain '{0}' which does not appear in the certificate. Use certificate?",
                    serverDomainNames[ii]);

                valid = false;

                if (await ApproveMessage(message, silent))
                {
                    valid = true;
                    continue;
                }

                break;
            }

            return(valid);
        }
Example #19
0
        /// <summary>
        /// Creates an application instance certificate if one does not already exist.
        /// </summary>
        private static async Task <bool> CheckApplicationInstanceCertificate(
            ApplicationConfiguration configuration,
            X509Certificate2 certificate,
            bool silent,
            ushort minimumKeySize)
        {
            if (certificate == null)
            {
                return(false);
            }

            Utils.Trace(Utils.TraceMasks.Information, "Checking application instance certificate. {0}", certificate.Subject);

            try
            {
                // validate certificate.
                configuration.CertificateValidator.Validate(certificate);
            }
            catch (Exception ex)
            {
                string message = Utils.Format(
                    "Error validating certificate. Exception: {0}. Use certificate anyway?", ex.Message);
                if (!await ApproveMessage(message, silent))
                {
                    return(false);
                }
            }

            // check key size.
            int keySize = X509Utils.GetRSAPublicKeySize(certificate);

            if (minimumKeySize > keySize)
            {
                string message = Utils.Format(
                    "The key size ({0}) in the certificate is less than the minimum provided ({1}). Use certificate anyway?",
                    keySize,
                    minimumKeySize);

                if (!await ApproveMessage(message, silent))
                {
                    return(false);
                }
            }

            // check domains.
            if (configuration.ApplicationType != ApplicationType.Client)
            {
                if (!await CheckDomainsInCertificate(configuration, certificate, silent))
                {
                    return(false);
                }
            }

            // check uri.
            string applicationUri = X509Utils.GetApplicationUriFromCertificate(certificate);

            if (String.IsNullOrEmpty(applicationUri))
            {
                string message = "The Application URI could not be read from the certificate. Use certificate anyway?";
                if (!await ApproveMessage(message, silent))
                {
                    return(false);
                }
            }
            else
            {
                configuration.ApplicationUri = applicationUri;
            }

            // update configuration.
            configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate;

            return(true);
        }
Example #20
0
            private async Task ConsoleClient()
            {
                Log(conn_name + " - " + "Create an Application Configuration...");
                exitCode = ExitCode.ErrorCreateApplication;

                ApplicationInstance application = new ApplicationInstance
                {
                    ApplicationName   = "JSON-SCADA OPC-UA Client",
                    ApplicationType   = ApplicationType.Client,
                    ConfigSectionName = "",
                };

                bool haveAppCertificate         = false;
                ApplicationConfiguration config = null;

                try
                {
                    // load the application configuration.
                    Log(conn_name + " - " + "Load config from " + OPCUA_conn.configFileName);
                    config = await application.LoadApplicationConfiguration(OPCUA_conn.configFileName, false);

                    // config.SecurityConfiguration.AutoAcceptUntrustedCertificates = true;

                    // check the application certificate.
                    haveAppCertificate = await application.CheckApplicationInstanceCertificate(false, 0);

                    if (!haveAppCertificate)
                    {
                        Log(conn_name + " - " + "FATAL: Application instance certificate invalid!", LogLevelNoLog);
                        Environment.Exit(1);
                    }

                    if (haveAppCertificate)
                    {
                        config.ApplicationUri = X509Utils.GetApplicationUriFromCertificate(config.SecurityConfiguration.ApplicationCertificate.Certificate);
                        if (config.SecurityConfiguration.AutoAcceptUntrustedCertificates)
                        {
                            autoAccept = true;
                        }
                        config.CertificateValidator.CertificateValidation += new CertificateValidationEventHandler(CertificateValidator_CertificateValidation);
                    }
                    else
                    {
                        Log(conn_name + " - " + "WARN: missing application certificate, using unsecure connection.");
                    }
                }
                catch (Exception e)
                {
                    Log(conn_name + " - WARN: " + e.Message);
                }

                if (config == null)
                {
                    Log(conn_name + " - " + "FATAL: error in XML config file!", LogLevelNoLog);
                    Environment.Exit(1);
                }

                try
                {
                    Log(conn_name + " - " + "Discover endpoints of " + OPCUA_conn.endpointURLs[0]);
                    exitCode = ExitCode.ErrorDiscoverEndpoints;
                    var selectedEndpoint = CoreClientUtils.SelectEndpoint(OPCUA_conn.endpointURLs[0], haveAppCertificate && OPCUA_conn.useSecurity, 15000);
                    Log(conn_name + " - " + "Selected endpoint uses: " +
                        selectedEndpoint.SecurityPolicyUri.Substring(selectedEndpoint.SecurityPolicyUri.LastIndexOf('#') + 1));

                    Log(conn_name + " - " + "Create a session with OPC UA server.");
                    exitCode = ExitCode.ErrorCreateSession;
                    var endpointConfiguration = EndpointConfiguration.Create(config);
                    var endpoint = new ConfiguredEndpoint(null, selectedEndpoint, endpointConfiguration);

                    await Task.Delay(50);

                    session = await Session.Create(config, endpoint, false, "OPC UA Console Client", 60000, new UserIdentity(new AnonymousIdentityToken()), null);

                    // Log("" + session.KeepAliveInterval); // default is 5000
                    session.KeepAliveInterval = System.Convert.ToInt32(OPCUA_conn.timeoutMs);

                    // register keep alive handler
                    session.KeepAlive += Client_KeepAlive;
                }
                catch (Exception e)
                {
                    Log(conn_name + " - WARN: " + e.Message);
                }

                if (session == null)
                {
                    Log(conn_name + " - " + "FATAL: error creating session!", LogLevelNoLog);
                    Environment.Exit(1);
                }

                Log(conn_name + " - " + "Browsing the OPC UA server namespace.");
                exitCode = ExitCode.ErrorBrowseNamespace;

                await FindObjects(session, ObjectIds.ObjectsFolder);

                await Task.Delay(50);

                Log(conn_name + " - " + "Add a list of items (server current time and status) to the subscription.");
                exitCode = ExitCode.ErrorMonitoredItem;
                ListMon.ForEach(i => i.Notification += OnNotification);
                //ListMon.ForEach(i => i.SamplingInterval = System.Convert.ToInt32(System.Convert.ToDouble(OPCUA_conn.autoCreateTagSamplingInterval) * 1000);
                // ListMon.ForEach(i => Log(conn_name + " - " + i.DisplayName));
                Log(conn_name + " - " + ListMon.Count + " Objects found");

                Log(conn_name + " - " + "Create a subscription with publishing interval of " + System.Convert.ToDouble(OPCUA_conn.autoCreateTagPublishingInterval) + "seconds");
                exitCode = ExitCode.ErrorCreateSubscription;
                var subscription =
                    new Subscription(session.DefaultSubscription)
                {
                    PublishingInterval = System.Convert.ToInt32(System.Convert.ToDouble(OPCUA_conn.autoCreateTagPublishingInterval) * 1000),
                    PublishingEnabled  = true
                };

                await Task.Delay(50);

                subscription.AddItems(ListMon);

                await Task.Delay(50);

                Log(conn_name + " - " + "Add the subscription to the session.");
                Log(conn_name + " - " + subscription.MonitoredItemCount + " Monitored items");
                exitCode = ExitCode.ErrorAddSubscription;
                session.AddSubscription(subscription);
                subscription.Create();

                subscription.ApplyChanges();

                Log(conn_name + " - " + "Running...");
                exitCode = ExitCode.ErrorRunning;
            }
Example #21
0
        private ServiceResult CreateSigningRequest(
            ISystemContext context,
            MethodState method,
            NodeId objectId,
            NodeId certificateGroupId,
            NodeId certificateTypeId,
            string subjectName,
            bool regeneratePrivateKey,
            byte[] nonce,
            ref byte[] certificateRequest)
        {
            HasApplicationSecureAdminAccess(context);

            ServerCertificateGroup certificateGroup = VerifyGroupAndTypeId(certificateGroupId, certificateTypeId);

            if (!String.IsNullOrEmpty(subjectName))
            {
                throw new ArgumentNullException(nameof(subjectName));
            }

            // TODO: implement regeneratePrivateKey
            // TODO: use nonce for generating the private key

            var passwordProvider = m_configuration.SecurityConfiguration.CertificatePasswordProvider;
            X509Certificate2 certWithPrivateKey = certificateGroup.ApplicationCertificate.LoadPrivateKeyEx(passwordProvider).Result;

            Utils.LogCertificate(Utils.TraceMasks.Security, "Create signing request: ", certWithPrivateKey);
            certificateRequest = CertificateFactory.CreateSigningRequest(certWithPrivateKey, X509Utils.GetDomainsFromCertficate(certWithPrivateKey));
            return(ServiceResult.Good);
        }
        /// <summary>
        /// Create the RSA certificate as Pfx byte array with a private key.
        /// </summary>
        /// <returns>
        /// Returns the Pfx with certificate and private key.
        /// </returns>
        private byte[] CreatePfxForRSA(string passcode, ISignatureFactory signatureFactory = null)
        {
            // Cases locked out by API flow
            Debug.Assert(m_rsaPublicKey == null, "A public key is not supported for the certificate.");

            if (signatureFactory != null && IssuerCAKeyCert == null)
            {
                throw new NotSupportedException("Need an issuer certificate for a signature generator.");
            }

            if (IssuerCAKeyCert != null &&
                (!IssuerCAKeyCert.HasPrivateKey && signatureFactory == null))
            {
                throw new NotSupportedException("Need an issuer certificate with a private key or a signature generator.");
            }

            using (var cfrg = new CertificateFactoryRandomGenerator())
            {
                // cert generators
                SecureRandom random = new SecureRandom(cfrg);

                CreateDefaults(cfrg);

                X509V3CertificateGenerator cg = new X509V3CertificateGenerator();
                CreateMandatoryFields(cg);

                // create Private/Public Keypair
                AsymmetricKeyParameter subjectPublicKey  = null;
                AsymmetricKeyParameter subjectPrivateKey = null;
                using (var rsa = new RSACryptoServiceProvider(m_keySize == 0 ? X509Defaults.RSAKeySize : m_keySize))
                {
                    subjectPublicKey  = X509Utils.GetPublicKeyParameter(rsa);
                    subjectPrivateKey = X509Utils.GetPrivateKeyParameter(rsa);
                }

                cg.SetPublicKey(subjectPublicKey);
                CreateExtensions(cg, subjectPublicKey);

                // sign certificate
                if (signatureFactory == null)
                {
                    AsymmetricKeyParameter signingKey;
                    if (IssuerCAKeyCert != null)
                    {
                        // signed by issuer
                        signingKey = X509Utils.GetPrivateKeyParameter(IssuerCAKeyCert);
                    }
                    else
                    {
                        // self signed
                        signingKey = subjectPrivateKey;
                    }
                    signatureFactory = new Asn1SignatureFactory(
                        X509Utils.GetRSAHashAlgorithm(HashAlgorithmName), signingKey, random);
                }
                Org.BouncyCastle.X509.X509Certificate x509 = cg.Generate(signatureFactory);

                // note: this Pfx has a private key!
                return(X509Utils.CreatePfxWithPrivateKey(x509, null, subjectPrivateKey, passcode, random));
            }
        }
        /// <summary>
        /// Creates a certificate signing request from an
        /// existing certificate with a private key.
        /// </summary>
        public static byte[] CreateSigningRequest(
            X509Certificate2 certificate,
            IList <String> domainNames = null
            )
        {
            if (certificate == null)
            {
                throw new ArgumentNullException(nameof(certificate));
            }
            using (var cfrg = new CertificateFactoryRandomGenerator())
            {
                SecureRandom random = new SecureRandom(cfrg);

                // try to get signing/private key from certificate passed in
                AsymmetricKeyParameter signingKey = X509Utils.GetPrivateKeyParameter(certificate);
                RsaKeyParameters       publicKey  = X509Utils.GetPublicKeyParameter(certificate);

                ISignatureFactory signatureFactory =
                    new Asn1SignatureFactory(X509Utils.GetRSAHashAlgorithm(X509Defaults.HashAlgorithmName), signingKey, random);

                Asn1Set attributes = null;
                var     san        = X509Extensions.FindExtension <X509SubjectAltNameExtension>(certificate);
                X509SubjectAltNameExtension alternateName = new X509SubjectAltNameExtension(san, san.Critical);

                string applicationUri = null;
                domainNames = domainNames ?? new List <String>();
                if (alternateName != null)
                {
                    if (alternateName.Uris.Count > 0)
                    {
                        applicationUri = alternateName.Uris[0];
                    }
                    foreach (var name in alternateName.DomainNames)
                    {
                        if (!domainNames.Any(s => s.Equals(name, StringComparison.OrdinalIgnoreCase)))
                        {
                            domainNames.Add(name);
                        }
                    }
                    foreach (var ipAddress in alternateName.IPAddresses)
                    {
                        if (!domainNames.Any(s => s.Equals(ipAddress, StringComparison.OrdinalIgnoreCase)))
                        {
                            domainNames.Add(ipAddress);
                        }
                    }
                }

                // build CSR extensions
                var generalNames = new List <GeneralName>();

                if (applicationUri != null)
                {
                    generalNames.Add(new GeneralName(GeneralName.UniformResourceIdentifier, applicationUri));
                }

                if (domainNames.Count > 0)
                {
                    generalNames.AddRange(BouncyCastle.X509Extensions.CreateSubjectAlternateNameDomains(domainNames));
                }

                if (generalNames.Count > 0)
                {
                    IList oids   = new ArrayList();
                    IList values = new ArrayList();
                    oids.Add(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName);
                    values.Add(new Org.BouncyCastle.Asn1.X509.X509Extension(false,
                                                                            new DerOctetString(new GeneralNames(generalNames.ToArray()).GetDerEncoded())));
                    var attribute = new Org.BouncyCastle.Asn1.Pkcs.AttributePkcs(Org.BouncyCastle.Asn1.Pkcs.PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
                                                                                 new DerSet(new Org.BouncyCastle.Asn1.X509.X509Extensions(oids, values)));
                    attributes = new DerSet(attribute);
                }

                var pkcs10CertificationRequest = new Pkcs10CertificationRequest(
                    signatureFactory,
                    new CertificateFactoryX509Name(false, certificate.Subject),
                    publicKey,
                    attributes);

                return(pkcs10CertificationRequest.GetEncoded());
            }
        }
        public virtual async Task <X509Certificate2> SigningRequestAsync(
            ApplicationRecordDataType application,
            string[] domainNames,
            byte[] certificateRequest)
        {
            try
            {
                var pkcs10CertificationRequest = new Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest(certificateRequest);

                if (!pkcs10CertificationRequest.Verify())
                {
                    throw new ServiceResultException(StatusCodes.BadInvalidArgument, "CSR signature invalid.");
                }

                var info             = pkcs10CertificationRequest.GetCertificationRequestInfo();
                var altNameExtension = GetAltNameExtensionFromCSRInfo(info);
                if (altNameExtension != null)
                {
                    if (altNameExtension.Uris.Count > 0)
                    {
                        if (!altNameExtension.Uris.Contains(application.ApplicationUri))
                        {
                            throw new ServiceResultException(StatusCodes.BadCertificateUriInvalid,
                                                             "CSR AltNameExtension does not match " + application.ApplicationUri);
                        }
                    }

                    if (altNameExtension.IPAddresses.Count > 0 || altNameExtension.DomainNames.Count > 0)
                    {
                        var domainNameList = new List <string>();
                        domainNameList.AddRange(altNameExtension.DomainNames);
                        domainNameList.AddRange(altNameExtension.IPAddresses);
                        domainNames = domainNameList.ToArray();
                    }
                }

                DateTime yesterday = DateTime.Today.AddDays(-1);
                using (var signingKey = await LoadSigningKeyAsync(Certificate, string.Empty).ConfigureAwait(false))
                {
                    return(CertificateFactory.CreateCertificate(
                               application.ApplicationUri,
                               null,
                               info.Subject.ToString(),
                               domainNames)
                           .SetNotBefore(yesterday)
                           .SetLifeTime(Configuration.DefaultCertificateLifetime)
                           .SetHashAlgorithm(X509Utils.GetRSAHashAlgorithmName(Configuration.DefaultCertificateHashSize))
                           .SetIssuer(signingKey)
                           .SetRSAPublicKey(info.SubjectPublicKeyInfo.GetEncoded())
                           .CreateForRSA());
                }
            }
            catch (Exception ex)
            {
                if (ex is ServiceResultException)
                {
                    throw ex as ServiceResultException;
                }
                throw new ServiceResultException(StatusCodes.BadInvalidArgument, ex.Message);
            }
        }
        /// <summary>
        /// Create the extensions.
        /// </summary>
        /// <param name="cg">The cert generator.</param>
        /// <param name="subjectPublicKey">The public key to use for the extensions.</param>
        private void CreateExtensions(X509V3CertificateGenerator cg, AsymmetricKeyParameter subjectPublicKey)
        {
            // Subject key identifier
            cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectKeyIdentifier.Id, false,
                            new SubjectKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(subjectPublicKey)));

            // Basic constraints
            BasicConstraints basicConstraints = new BasicConstraints(m_isCA);

            if (m_isCA && m_pathLengthConstraint >= 0)
            {
                basicConstraints = new BasicConstraints(m_pathLengthConstraint);
            }
            else if (!m_isCA && IssuerCAKeyCert == null)
            {   // self-signed
                basicConstraints = new BasicConstraints(0);
            }
            cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.BasicConstraints.Id, true, basicConstraints);

            // Authority Key identifier references the issuer cert or itself when self signed
            AsymmetricKeyParameter issuerPublicKey;
            BigInteger             issuerSerialNumber;

            if (IssuerCAKeyCert != null)
            {
                issuerPublicKey    = X509Utils.GetPublicKeyParameter(IssuerCAKeyCert);
                issuerSerialNumber = X509Utils.GetSerialNumber(IssuerCAKeyCert);
            }
            else
            {
                issuerPublicKey    = subjectPublicKey;
                issuerSerialNumber = new BigInteger(1, m_serialNumber.Reverse().ToArray());
            }

            cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier.Id, false,
                            new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerPublicKey),
                                                       new GeneralNames(new GeneralName(m_issuerDN)), issuerSerialNumber));

            if (!m_isCA)
            {
                // Key usage
                var keyUsage = KeyUsage.DataEncipherment | KeyUsage.DigitalSignature |
                               KeyUsage.NonRepudiation | KeyUsage.KeyEncipherment;
                if (IssuerCAKeyCert == null)
                {   // only self signed certs need KeyCertSign flag.
                    keyUsage |= KeyUsage.KeyCertSign;
                }
                cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage, true,
                                new KeyUsage(keyUsage));

                // Extended Key usage
                cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage, true,
                                new ExtendedKeyUsage(new List <DerObjectIdentifier>()
                {
                    new DerObjectIdentifier(Oids.ServerAuthentication), // server auth
                    new DerObjectIdentifier(Oids.ClientAuthentication), // client auth
                }));
            }
            else
            {
                // Key usage CA
                cg.AddExtension(Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage, true,
                                new KeyUsage(KeyUsage.CrlSign | KeyUsage.DigitalSignature | KeyUsage.KeyCertSign));
            }

            foreach (var extension in m_extensions)
            {
                cg.AddExtension(extension.Oid.Value, extension.Critical, Asn1Object.FromByteArray(extension.RawData));
            }
        }
Example #26
0
        /// <summary>
        /// Creates an application instance certificate if one does not already exist.
        /// </summary>
        private async Task <bool> CheckApplicationInstanceCertificate(
            ApplicationConfiguration configuration,
            X509Certificate2 certificate,
            bool silent,
            ushort minimumKeySize)
        {
            if (certificate == null)
            {
                return(false);
            }

            // set suppressible errors
            var certValidator = new CertValidationSuppressibleStatusCodes(
                new StatusCode[] {
                StatusCodes.BadCertificateUntrusted,
                StatusCodes.BadCertificateTimeInvalid,
                StatusCodes.BadCertificateHostNameInvalid,
                StatusCodes.BadCertificateRevocationUnknown,
                StatusCodes.BadCertificateIssuerRevocationUnknown,
            });

            Utils.LogCertificate("Check application instance certificate.", certificate);

            try
            {
                // validate certificate.
                configuration.CertificateValidator.CertificateValidation += certValidator.OnCertificateValidation;
                configuration.CertificateValidator.Validate(certificate.HasPrivateKey ? new X509Certificate2(certificate.RawData) : certificate);
            }
            catch (Exception ex)
            {
                string message = Utils.Format(
                    "Error validating certificate. Exception: {0}. Use certificate anyway?", ex.Message);
                if (!await ApproveMessage(message, silent).ConfigureAwait(false))
                {
                    return(false);
                }
            }
            finally
            {
                configuration.CertificateValidator.CertificateValidation -= certValidator.OnCertificateValidation;
            }

            // check key size.
            int keySize = X509Utils.GetRSAPublicKeySize(certificate);

            if (minimumKeySize > keySize)
            {
                string message = Utils.Format(
                    "The key size ({0}) in the certificate is less than the minimum allowed ({1}). Use certificate anyway?",
                    keySize,
                    minimumKeySize);

                if (!await ApproveMessage(message, silent).ConfigureAwait(false))
                {
                    return(false);
                }
            }

            // check domains.
            if (configuration.ApplicationType != ApplicationType.Client)
            {
                if (!await CheckDomainsInCertificate(configuration, certificate, silent).ConfigureAwait(false))
                {
                    return(false);
                }
            }

            // check uri.
            string applicationUri = X509Utils.GetApplicationUriFromCertificate(certificate);

            if (String.IsNullOrEmpty(applicationUri))
            {
                string message = "The Application URI could not be read from the certificate. Use certificate anyway?";
                if (!await ApproveMessage(message, silent).ConfigureAwait(false))
                {
                    return(false);
                }
            }
            else if (!configuration.ApplicationUri.Equals(applicationUri, StringComparison.InvariantCulture))
            {
                Utils.LogInfo("Updated the ApplicationUri: {0} --> {1}", configuration.ApplicationUri, applicationUri);
                configuration.ApplicationUri = applicationUri;
            }

            Utils.LogInfo("Using the ApplicationUri: {0}", applicationUri);

            // update configuration.
            configuration.SecurityConfiguration.ApplicationCertificate.Certificate = certificate;

            return(true);
        }
Example #27
0
        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);
        }
Example #28
0
        public static void VerifySignedApplicationCert(ApplicationTestData testApp, byte[] rawSignedCert, byte[][] rawIssuerCerts)
        {
            X509Certificate2 signedCert = new X509Certificate2(rawSignedCert);
            X509Certificate2 issuerCert = new X509Certificate2(rawIssuerCerts[0]);

            TestContext.Out.WriteLine($"Signed cert: {signedCert}");
            TestContext.Out.WriteLine($"Issuer cert: {issuerCert}");

            Assert.NotNull(signedCert);
            Assert.False(signedCert.HasPrivateKey);
            Assert.True(X509Utils.CompareDistinguishedName(testApp.Subject, signedCert.Subject));
            Assert.False(X509Utils.CompareDistinguishedName(signedCert.Issuer, signedCert.Subject));
            Assert.True(X509Utils.CompareDistinguishedName(signedCert.Issuer, issuerCert.Subject));
            TestContext.Out.WriteLine($"Signed Subject: {signedCert.Subject}");
            TestContext.Out.WriteLine($"Issuer Subject: {issuerCert.Subject}");

            // test basic constraints
            X509BasicConstraintsExtension constraints = X509Extensions.FindExtension <X509BasicConstraintsExtension>(signedCert);

            Assert.NotNull(constraints);
            TestContext.Out.WriteLine($"Constraints: {constraints.Format(true)}");
            Assert.True(constraints.Critical);
            Assert.False(constraints.CertificateAuthority);
            Assert.False(constraints.HasPathLengthConstraint);

            // key usage
            X509KeyUsageExtension keyUsage = X509Extensions.FindExtension <X509KeyUsageExtension>(signedCert);

            Assert.NotNull(keyUsage);
            TestContext.Out.WriteLine($"KeyUsage: {keyUsage.Format(true)}");
            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
            X509EnhancedKeyUsageExtension enhancedKeyUsage = X509Extensions.FindExtension <X509EnhancedKeyUsageExtension>(signedCert);

            Assert.NotNull(enhancedKeyUsage);
            TestContext.Out.WriteLine($"Enhanced Key Usage: {enhancedKeyUsage.Format(true)}");
            Assert.True(enhancedKeyUsage.Critical);

            // test for authority key
            X509AuthorityKeyIdentifierExtension authority = X509Extensions.FindExtension <X509AuthorityKeyIdentifierExtension>(signedCert);

            Assert.NotNull(authority);
            TestContext.Out.WriteLine($"Authority Key Identifier: {authority.Format(true)}");
            Assert.NotNull(authority.SerialNumber);
            Assert.NotNull(authority.KeyIdentifier);
            Assert.NotNull(authority.Issuer);
            Assert.AreEqual(issuerCert.SubjectName.RawData, authority.Issuer.RawData);
            Assert.AreEqual(issuerCert.SubjectName.RawData, authority.Issuer.RawData);

            // verify authority key in signed cert
            X509SubjectKeyIdentifierExtension subjectKeyId = X509Extensions.FindExtension <X509SubjectKeyIdentifierExtension>(issuerCert);

            TestContext.Out.WriteLine($"Issuer Subject Key Identifier: {subjectKeyId}");
            Assert.AreEqual(subjectKeyId.SubjectKeyIdentifier, authority.KeyIdentifier);
            Assert.AreEqual(issuerCert.SerialNumber, authority.SerialNumber);

            X509SubjectAltNameExtension subjectAlternateName = X509Extensions.FindExtension <X509SubjectAltNameExtension>(signedCert);

            Assert.NotNull(subjectAlternateName);
            TestContext.Out.WriteLine($"Issuer Subject Alternate Name: {subjectAlternateName}");
            Assert.False(subjectAlternateName.Critical);
            var domainNames = X509Utils.GetDomainsFromCertficate(signedCert);

            foreach (var domainName in testApp.DomainNames)
            {
                Assert.True(domainNames.Contains(domainName, StringComparer.OrdinalIgnoreCase));
            }
            Assert.True(subjectAlternateName.Uris.Count == 1);
            var applicationUri = X509Utils.GetApplicationUriFromCertificate(signedCert);

            Assert.True(testApp.ApplicationRecord.ApplicationUri == applicationUri);
        }
Example #29
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).Result;

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

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

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

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

                m_node.LastUpdateTime.Value = DateTime.UtcNow;
            }

            return(ServiceResult.Good);
        }
Example #30
0
        public async Task VerifyAppCertDirectoryStore()
        {
            var appCertificate = GetTestCert();

            Assert.NotNull(appCertificate);
            Assert.True(appCertificate.HasPrivateKey);

            string password = Guid.NewGuid().ToString();

            // pki directory root for app cert
            var pkiRoot   = Path.GetTempPath() + Path.GetRandomFileName() + Path.DirectorySeparatorChar;
            var storePath = pkiRoot + "own";
            var storeType = CertificateStoreType.Directory;

            appCertificate.AddToStore(
                storeType, storePath, password
                );

            using (var publicKey = new X509Certificate2(appCertificate.RawData))
            {
                Assert.NotNull(publicKey);
                Assert.False(publicKey.HasPrivateKey);

                var id = new CertificateIdentifier()
                {
                    Thumbprint = publicKey.Thumbprint,
                    StorePath  = storePath,
                    StoreType  = storeType
                };

                {
                    // check no password fails to load
                    var nullKey = await id.LoadPrivateKey(null).ConfigureAwait(false);

                    Assert.IsNull(nullKey);
                }

                {
                    // check invalid password fails to load
                    var nullKey = await id.LoadPrivateKey("123").ConfigureAwait(false);

                    Assert.IsNull(nullKey);
                }

                {
                    // check invalid password fails to load
                    var nullKey = await id.LoadPrivateKeyEx(new CertificatePasswordProvider("123")).ConfigureAwait(false);

                    Assert.IsNull(nullKey);
                }

                var privateKey = await id.LoadPrivateKeyEx(new CertificatePasswordProvider(password)).ConfigureAwait(false);

                Assert.NotNull(privateKey);
                Assert.True(privateKey.HasPrivateKey);

                X509Utils.VerifyRSAKeyPair(publicKey, privateKey, true);

                using (ICertificateStore store = Opc.Ua.CertificateStoreIdentifier.CreateStore(storeType))
                {
                    store.Open(storePath);
                    await store.Delete(publicKey.Thumbprint).ConfigureAwait(false);
                }
            }
        }