Beispiel #1
0
        /// <summary>
        /// Verifies if the ETK contains a token that is still valid and can be trusted.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method checks if the certificate in the ETK is issued by a trusted party.  Trust means
        /// the root certificate is trusted by the computer it is running on and all
        /// validation checks, including revocation, are successful.  Root
        /// certificates are trusted by the computer if present in the
        /// <see cref="StoreName.Root"/> store.
        /// </para>
        /// <para>
        /// This method no longer validates the signer of the ETK token due lack of signing time in the ETK.
        /// The encryption certificate inside the ETK is still completely verified, this means there isn't a reduction in
        /// security compared to the previous implementation.
        /// </para>
        /// </remarks>
        /// <param name="checkRevocation"><c>true</c>to check if the certificates that issued the encryption cert aren't revoked</param>
        /// <returns>Detailed information about the encryption certificate status</returns>
        public CertificateSecurityInformation Verify(bool checkRevocation)
        {
            IList <CertificateList>   crls;
            IList <BasicOcspResponse> ocps;

            //Get encryption cert
            BC::X509Certificate encCert = DotNetUtilities.FromX509Certificate(ToCertificate());

            trace.TraceEvent(TraceEventType.Information, 0, "Verifying ETK: {0}", encCert.SubjectDN.ToString());

            //Check the certificate
            IX509Store certs = raw.GetCertificates("COLLECTION");

            if (checkRevocation)
            {
                crls = new List <CertificateList>();
                ocps = new List <BasicOcspResponse>();
            }
            else
            {
                crls = null;
                ocps = null;
            }
            CertificateSecurityInformation certInfo = encCert.Verify(DateTime.UtcNow, new int[] { 2, 3 }, EteeActiveConfig.Unseal.MinimumEncryptionKeySize.AsymmerticRecipientKey, certs, ref crls, ref ocps);

            if (!(encCert.GetPublicKey() is RsaKeyParameters))
            {
                certInfo.securityViolations.Add(CertSecurityViolation.NotValidKeyType);
                trace.TraceEvent(TraceEventType.Warning, 0, "Only RSA keys can be used for sealing");
            }
            return(certInfo);
        }
Beispiel #2
0
        public void InvalidEncKeyUsage()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/invalid_encrkey_usage.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.None, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Invalid, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.NotValidForUsage));
        }
Beispiel #3
0
        public void ExpiredEnc()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/expired_encr.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.Unsure, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Invalid, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.NotTimeValid));
        }
Beispiel #4
0
        public void Bob2()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/Bob2_public_key.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.Unsure, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Valid, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.IssuerTrustUnknown));
            Assert.IsTrue(info.IssuerInfo.SecurityViolations.Contains(CertSecurityViolation.RevocationStatusUnknown));
        }
Beispiel #5
0
        public void MixedKeyAlgorithm()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/invalid_key_algorithm.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.None, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Valid, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.UntrustedIssuer));
            Assert.IsTrue(info.IssuerInfo.SecurityViolations.Contains(CertSecurityViolation.NotValidKeySize));
        }
Beispiel #6
0
        public void NotYetAuth()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/not_yet_auth.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.None, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Valid, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.UntrustedIssuer));
            Assert.IsTrue(info.IssuerInfo.SecurityViolations.Contains(CertSecurityViolation.NotTimeValid));
        }
Beispiel #7
0
        public void DifferentDN()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/auth_and_encr_not_same_DN.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.None, info.TrustStatus);
            //Assert.AreEqual(ValidationStatus.Unsure, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.UntrustedIssuer));
            Assert.IsTrue(info.IssuerInfo.SecurityViolations.Contains(CertSecurityViolation.InvalidBasicConstraints));
        }
Beispiel #8
0
        public void ValidButScrambledDN()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/valid_but_scrambledDN.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.None, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Valid, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.UntrustedIssuer));
            Assert.IsTrue(info.IssuerInfo.SecurityViolations.Contains(CertSecurityViolation.NotValidForUsage));
        }
Beispiel #9
0
        public void InvalidKeySize()
        {
            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/invalid_key_size.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.None, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Invalid, info.ValidationStatus);

            Assert.IsTrue(info.SecurityViolations.Contains(CertSecurityViolation.NotValidKeySize));
            //This is no longer the case because we allow eID with 1024 bit keys.
            //Assert.IsTrue(info.IssuerInfo.SecurityViolations.Contains(CertSecurityViolation.NotValidKeySize));
        }
Beispiel #10
0
        public void kgss()
        {
            if (DateTime.Now > new DateTime(2015, 4, 22))
            {
                Assert.Inconclusive("KGSS token must be updated");
            }

            EncryptionToken receiver            = new EncryptionToken(Utils.ReadFully(GetAbsoluteTestFilePath("etk/kgss.etk")));
            CertificateSecurityInformation info = receiver.Verify();

            Console.WriteLine(info.ToString());

            Assert.IsNotNull(info.ToString());
            Assert.AreEqual(ETEE::Status.TrustStatus.Full, info.TrustStatus);
            Assert.AreEqual(ValidationStatus.Valid, info.ValidationStatus);
        }
Beispiel #11
0
        public static CertificateSecurityInformation VerifyEnc(Org.BouncyCastle.X509.X509Certificate encCert, Org.BouncyCastle.X509.X509Certificate authCert, DateTime date, IX509Store certs, bool checkRevocation)
        {
            CertificateSecurityInformation result = new CertificateSecurityInformation();

            result.Certificate = new X509Certificate2(encCert.GetEncoded());

            //check validity
            try
            {
                encCert.CheckValidity(date);
            }
            catch (CertificateExpiredException)
            {
                result.securityViolations.Add(CertSecurityViolation.NotTimeValid);
            }
            catch (CertificateNotYetValidException)
            {
                result.securityViolations.Add(CertSecurityViolation.NotTimeValid);
            }

            //check key usage
            int[] keyUsageIndexes = new int[] { 2, 3 };
            foreach (int i in keyUsageIndexes)
            {
                if (!encCert.GetKeyUsage()[i])
                {
                    result.securityViolations.Add(CertSecurityViolation.NotValidForUsage);
                    trace.TraceEvent(TraceEventType.Warning, 0, "The key usage did not have the correct usage flag set");
                }
            }

            //check issuer/subject
            if (!encCert.IssuerDN.Equivalent(encCert.SubjectDN, false)) result.securityViolations.Add(CertSecurityViolation.HasNotPermittedNameConstraint);

            //check key size
            if (!VerifyKeySize(encCert.GetPublicKey(), EteeActiveConfig.Unseal.MinimumEncryptionKeySize.AsymmerticRecipientKey)) result.securityViolations.Add(CertSecurityViolation.NotValidKeySize);

            //check key type
            if (!(encCert.GetPublicKey() is RsaKeyParameters)) result.securityViolations.Add(CertSecurityViolation.NotValidKeyType);

            if (authCert != null)
            {
                //check signature
                try
                {
                    encCert.Verify(authCert.GetPublicKey());
                }
                catch (InvalidKeyException)
                {
                    result.securityViolations.Add(CertSecurityViolation.NotSignatureValid);
                }

                //Validate
                result.IssuerInfo = VerifyBoth(authCert, date, certs, new List<CertificateList>(0), new List<BasicOcspResponse>(0), checkRevocation, false);
            }
            else
            {
                //We assume that we have the authCert in case it's of a 3rd person, we don't care if its or own encryption cert (we only care for the validity)
            }

            return result;
        }
Beispiel #12
0
        private static CertificateSecurityInformation Verify(Org.BouncyCastle.X509.X509Certificate cert, DateTime date, IX509Store certs, IList<CertificateList> crls, IList<BasicOcspResponse> ocsps, bool checkRevocation, bool checkTime)
        {
            CertificateSecurityInformation result = new CertificateSecurityInformation();

            AsymmetricKeyParameter key = cert.GetPublicKey();

            //check key type
            if (!(key is RsaKeyParameters))
            {
                result.securityViolations.Add(CertSecurityViolation.NotValidKeyType);
                trace.TraceEvent(TraceEventType.Warning, 0, "The key should be RSA but was {0}", key.GetType());
            }

            //check key size
            if (!VerifyKeySize(key, EteeActiveConfig.Unseal.MinimumSignatureKeySize))
            {
                result.securityViolations.Add(CertSecurityViolation.NotValidKeySize);
                trace.TraceEvent(TraceEventType.Warning, 0, "The key was smaller then {0}", EteeActiveConfig.Unseal.MinimumSignatureKeySize);
            }

            X509Certificate2Collection extraStore = new X509Certificate2Collection();
            foreach (Org.BouncyCastle.X509.X509Certificate obj in certs.GetMatches(null))
            {
                extraStore.Add(new X509Certificate2(obj.GetEncoded()));
            }
            Chain chain;
            if (checkRevocation)
                chain = new X509Certificate2(cert.GetEncoded()).BuildChain(date, extraStore, ref crls, ref ocsps, checkTime ? DateTime.UtcNow : date);
            else
                chain = new X509Certificate2(cert.GetEncoded()).BuildBasicChain(date, extraStore);

            CertificateSecurityInformation dest = null;
            foreach (ChainElement ce in chain.ChainElements)
            {
                if (dest == null) {
                    dest = result;
                }
                else
                {
                    dest.IssuerInfo = new CertificateSecurityInformation();
                    dest = dest.IssuerInfo;
                }

                dest.Certificate = ce.Certificate;
                foreach (X509ChainStatus status in ce.ChainElementStatus.Where(x => x.Status != X509ChainStatusFlags.NoError))
                {
                    dest.securityViolations.Add((CertSecurityViolation)Enum.Parse(typeof(CertSecurityViolation), Enum.GetName(typeof(X509ChainStatusFlags), status.Status)));
                }
            }
            if (chain.ChainStatus.Count(x => x.Status == X509ChainStatusFlags.PartialChain) > 0)
            {
                result.securityViolations.Add(CertSecurityViolation.IssuerTrustUnknown);
            }

            trace.TraceEvent(TraceEventType.Verbose, 0, "Verified certificate {0} for date {1}", cert.SubjectDN.ToString(), date);
            return result;
        }
Beispiel #13
0
        public static CertificateSecurityInformation Verify(this Org.BouncyCastle.X509.X509Certificate cert, DateTime date, int[] keyUsageIndexes, int minimumKeySize, IX509Store certs, ref IList <CertificateList> crls, ref IList <BasicOcspResponse> ocsps)
        {
            CertificateSecurityInformation result = new CertificateSecurityInformation();

            result.Certificate = new X509Certificate2(cert.GetEncoded());

            //check key size
            AsymmetricKeyParameter key = cert.GetPublicKey();

            if (!VerifyKeySize(key, minimumKeySize))
            {
                result.securityViolations.Add(CertSecurityViolation.NotValidKeySize);
                trace.TraceEvent(TraceEventType.Warning, 0, "The key was smaller then {0}", minimumKeySize);
            }

            //check key usages
            foreach (int i in keyUsageIndexes)
            {
                if (!cert.GetKeyUsage()[i])
                {
                    result.securityViolations.Add(CertSecurityViolation.NotValidForUsage);
                    trace.TraceEvent(TraceEventType.Warning, 0, "The key usage did not have the correct usage flag {0} set", i);
                }
            }

            //build extra store
            X509Certificate2Collection extraStore = new X509Certificate2Collection();

            foreach (Org.BouncyCastle.X509.X509Certificate obj in certs.GetMatches(null))
            {
                extraStore.Add(new X509Certificate2(obj.GetEncoded()));
            }

            CertificateSecurityInformation dest     = result;
            CertificateSecurityInformation previous = null;

            Org.BouncyCastle.X509.X509Certificate issuer = cert.ValidateAndGetDerivedIssuer(certs);
            if (issuer != null)
            {
                trace.TraceEvent(TraceEventType.Verbose, 0, "Detected eHealth variant of proxy certificate");

                //check proxy certificate, is it still valid?
                if (!cert.IsValid(date))
                {
                    dest.securityViolations.Add(CertSecurityViolation.NotTimeValid);
                    trace.TraceEvent(TraceEventType.Warning, 0, "The proxy certificate is expired or not yet valid, {0} not between {1}-{2}",
                                     date, cert.NotBefore, cert.NotAfter);
                }

                //The issuer signature of the proxy certificate is already checked...

                //check issuer
                previous         = dest;
                dest             = new CertificateSecurityInformation();
                dest.Certificate = new X509Certificate2(issuer.GetEncoded());

                //check key size of the issuer
                key = issuer.GetPublicKey();
                if (!VerifyKeySize(key, minimumKeySize))
                {
                    dest.securityViolations.Add(CertSecurityViolation.NotValidKeySize);
                    trace.TraceEvent(TraceEventType.Warning, 0, "The key of the issuer was smaller then {0}", minimumKeySize);
                }

                //check key usage of the issuer
                foreach (int i in new int[] { 0, 1 })
                {
                    if (!issuer.GetKeyUsage()[i])
                    {
                        dest.securityViolations.Add(CertSecurityViolation.NotValidForUsage);
                        trace.TraceEvent(TraceEventType.Warning, 0, "The key usage of the issuer did not have the correct usage flag set");
                    }
                }
            }


            //check the chain
            Chain chain;

            if (crls != null || ocsps != null)
            {
                chain = dest.Certificate.BuildChain(date, extraStore, crls, ocsps);
            }
            else
            {
                chain = dest.Certificate.BuildChain(date, extraStore);
            }

            //process the chain
            foreach (ChainElement ce in chain.ChainElements)
            {
                //connect the prepared link
                if (previous != null)
                {
                    previous.IssuerInfo = dest;
                }

                //update the link
                dest.Certificate = ce.Certificate;
                foreach (X509ChainStatus status in ce.ChainElementStatus.Where(x => x.Status != X509ChainStatusFlags.NoError))
                {
                    dest.securityViolations.Add((CertSecurityViolation)Enum.Parse(typeof(CertSecurityViolation), Enum.GetName(typeof(X509ChainStatusFlags), status.Status)));
                }

                //prepare the next link
                previous = dest;
                dest     = new CertificateSecurityInformation();
            }

            if (chain.ChainStatus.Count(x => x.Status == X509ChainStatusFlags.PartialChain) > 0)
            {
                result.securityViolations.Add(CertSecurityViolation.IssuerTrustUnknown);
            }


            trace.TraceEvent(TraceEventType.Verbose, 0, "Verified certificate {0} for date {1}", cert.SubjectDN.ToString(), date);
            return(result);
        }