Ejemplo n.º 1
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);
        }