Rfc3280CertPathUtilities.cs :  » PDF » iTextSharp » Org » BouncyCastle » Pkix » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » PDF » iTextSharp 
iTextSharp » Org » BouncyCastle » Pkix » Rfc3280CertPathUtilities.cs
using System;
using System.Collections;
using System.Globalization;
using System.IO;

using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Security.Certificates;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.Collections;
using Org.BouncyCastle.Utilities.Date;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Store;

namespace Org.BouncyCastle.Pkix{
  public class Rfc3280CertPathUtilities
  {
    internal static readonly string ANY_POLICY = "2.5.29.32.0";

    // key usage bits
    internal static readonly int KEY_CERT_SIGN = 5;
    internal static readonly int CRL_SIGN = 6;

    /**
    * If the complete CRL includes an issuing distribution point (IDP) CRL
    * extension check the following:
    * <p>
    * (i) If the distribution point name is present in the IDP CRL extension
    * and the distribution field is present in the DP, then verify that one of
    * the names in the IDP matches one of the names in the DP. If the
    * distribution point name is present in the IDP CRL extension and the
    * distribution field is omitted from the DP, then verify that one of the
    * names in the IDP matches one of the names in the cRLIssuer field of the
    * DP.
    * </p>
    * <p>
    * (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL
    * extension, verify that the certificate does not include the basic
    * constraints extension with the cA boolean asserted.
    * </p>
    * <p>
    * (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL
    * extension, verify that the certificate includes the basic constraints
    * extension with the cA boolean asserted.
    * </p>
    * <p>
    * (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted.
    * </p>
    *
    * @param dp   The distribution point.
    * @param cert The certificate.
    * @param crl  The CRL.
    * @throws AnnotatedException if one of the conditions is not met or an error occurs.
    */
    internal static void ProcessCrlB2(
      DistributionPoint  dp,
      object        cert,
      X509Crl        crl)
    {
      IssuingDistributionPoint idp = null;
      try
      {
        idp = IssuingDistributionPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.IssuingDistributionPoint));
      }
      catch (Exception e)
      {
        throw new Exception("0 Issuing distribution point extension could not be decoded.", e);
      }
      // (b) (2) (i)
      // distribution point name is present
      if (idp != null)
      {
        if (idp.DistributionPoint != null)
        {
          // make list of names
          DistributionPointName dpName = IssuingDistributionPoint.GetInstance(idp).DistributionPoint;
          IList names = new ArrayList();

          if (dpName.PointType == DistributionPointName.FullName)
          {
            GeneralName[] genNames = GeneralNames.GetInstance(dpName.Name).GetNames();
            for (int j = 0; j < genNames.Length; j++)
            {
              names.Add(genNames[j]);
            }
          }
          if (dpName.PointType == DistributionPointName.NameRelativeToCrlIssuer)
          {
            Asn1EncodableVector vec = new Asn1EncodableVector();
            try
            {
              IEnumerator e = Asn1Sequence.GetInstance(
                Asn1Sequence.FromByteArray(crl.IssuerDN.GetEncoded())).GetEnumerator();
              while (e.MoveNext())
              {
                vec.Add((Asn1Encodable)e.Current);
              }
            }
            catch (IOException e)
            {
              throw new Exception("Could not read CRL issuer.", e);
            }
            vec.Add(dpName.Name);
            names.Add(new GeneralName(X509Name.GetInstance(new DerSequence(vec))));
          }
          bool matches = false;
          // verify that one of the names in the IDP matches one
          // of the names in the DP.
          if (dp.DistributionPointName != null)
          {
            dpName = dp.DistributionPointName;
            GeneralName[] genNames = null;
            if (dpName.PointType == DistributionPointName.FullName)
            {
              genNames = GeneralNames.GetInstance(dpName.Name).GetNames();
            }
            if (dpName.PointType == DistributionPointName.NameRelativeToCrlIssuer)
            {
              if (dp.CrlIssuer != null)
              {
                genNames = dp.CrlIssuer.GetNames();
              }
              else
              {
                genNames = new GeneralName[1];
                try
                {
                  genNames[0] = new GeneralName(
                    PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert));
                }
                catch (IOException e)
                {
                  throw new Exception("Could not read certificate issuer.", e);
                }
              }
              for (int j = 0; j < genNames.Length; j++)
              {
                IEnumerator e = Asn1Sequence.GetInstance(genNames[j].Name.ToAsn1Object()).GetEnumerator();
                Asn1EncodableVector vec = new Asn1EncodableVector();
                while (e.MoveNext())
                {
                  vec.Add((Asn1Encodable)e.Current);
                }
                vec.Add(dpName.Name);
                genNames[j] = new GeneralName(X509Name.GetInstance(new DerSequence(vec)));
              }
            }
            if (genNames != null)
            {
              for (int j = 0; j < genNames.Length; j++)
              {
                if (names.Contains(genNames[j]))
                {
                  matches = true;
                  break;
                }
              }
            }
            if (!matches)   
            {
              throw new Exception(
                "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
            }
          }
            // verify that one of the names in
            // the IDP matches one of the names in the cRLIssuer field of
            // the DP
          else
          {
            if (dp.CrlIssuer == null)
            {
              throw new Exception("Either the cRLIssuer or the distributionPoint field must "
                + "be contained in DistributionPoint.");
            }
            GeneralName[] genNames = dp.CrlIssuer.GetNames();
            for (int j = 0; j < genNames.Length; j++)
            {
              if (names.Contains(genNames[j]))
              {
                matches = true;
                break;
              }
            }
            if (!matches)
            {
              throw new Exception(
                "No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
            }
          }
        }
        BasicConstraints bc = null;
        try
        {
          bc = BasicConstraints.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(
            (IX509Extension)cert, X509Extensions.BasicConstraints));
        }
        catch (Exception e)
        {
          throw new Exception("Basic constraints extension could not be decoded.", e);
        }

        //if (cert is X509Certificate)
        {
          // (b) (2) (ii)
          if (idp.OnlyContainsUserCerts && ((bc != null) && bc.IsCA()))
          {
            throw new Exception("CA Cert CRL only contains user certificates.");
          }

          // (b) (2) (iii)
          if (idp.OnlyContainsCACerts && (bc == null || !bc.IsCA()))
          {
            throw new Exception("End CRL only contains CA certificates.");
          }
        }

        // (b) (2) (iv)
        if (idp.OnlyContainsAttributeCerts)
        {
          throw new Exception("onlyContainsAttributeCerts boolean is asserted.");
        }
      }
    }

    internal static void ProcessCertBC(
      PkixCertPath        certPath,
      int              index,
      PkixNameConstraintValidator  nameConstraintValidator)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      int n = certs.Count;
      // i as defined in the algorithm description
      int i = n - index;
      //
      // (b), (c) permitted and excluded subtree checking.
      //
      if (!(PkixCertPathValidatorUtilities.IsSelfIssued(cert) && (i < n)))
      {
        X509Name principal = cert.SubjectDN;
        Asn1InputStream aIn = new Asn1InputStream(principal.GetEncoded());
        Asn1Sequence dns;

        try
        {
          dns = DerSequence.GetInstance(aIn.ReadObject());
        }
        catch (Exception e)
        {
          throw new PkixCertPathValidatorException(
            "Exception extracting subject name when checking subtrees.", e, certPath, index);
        }

        try
        {
          nameConstraintValidator.CheckPermittedDN(dns);
          nameConstraintValidator.CheckExcludedDN(dns);
        }
        catch (PkixNameConstraintValidatorException e)
        {
          throw new PkixCertPathValidatorException(
            "Subtree check for certificate subject failed.", e, certPath, index);
        }

        GeneralNames altName = null;
        try
        {
          altName = GeneralNames.GetInstance(
            PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.SubjectAlternativeName));
        }
        catch (Exception e)
        {
          throw new PkixCertPathValidatorException(
            "Subject alternative name extension could not be decoded.", e, certPath, index);
        }
              
        ArrayList emails = X509Name.GetInstance(dns).GetValues(X509Name.EmailAddress);
        foreach (string email in emails)
        {
          GeneralName emailAsGeneralName = new GeneralName(GeneralName.Rfc822Name, email);
          try
          {
            nameConstraintValidator.checkPermitted(emailAsGeneralName);
            nameConstraintValidator.checkExcluded(emailAsGeneralName);
          }
          catch (PkixNameConstraintValidatorException ex)
          {
            throw new PkixCertPathValidatorException(
              "Subtree check for certificate subject alternative email failed.", ex, certPath, index);
          }
        }
        if (altName != null)
        {
          GeneralName[] genNames = null;
          try
          {
            genNames = altName.GetNames();
          }
          catch (Exception e)
          {
            throw new PkixCertPathValidatorException(
              "Subject alternative name contents could not be decoded.", e, certPath, index);
          }
          foreach (GeneralName genName in genNames)
          {
            try
            {
              nameConstraintValidator.checkPermitted(genName);
              nameConstraintValidator.checkExcluded(genName);
            }
            catch (PkixNameConstraintValidatorException e)
            {
              throw new PkixCertPathValidatorException(
                "Subtree check for certificate subject alternative name failed.", e, certPath, index);
            }
          }
        }
      }
    }

    internal static void PrepareNextCertA(
      PkixCertPath  certPath,
      int        index)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      //
      //
      // (a) check the policy mappings
      //
      Asn1Sequence pm = null;
      try
      {
        pm = Asn1Sequence.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyMappings));
      }
      catch (Exception ex)
      {
        throw new PkixCertPathValidatorException(
          "Policy mappings extension could not be decoded.", ex, certPath, index);
      }
      if (pm != null)
      {
        Asn1Sequence mappings = pm;

        for (int j = 0; j < mappings.Count; j++)
        {
          DerObjectIdentifier issuerDomainPolicy = null;
          DerObjectIdentifier subjectDomainPolicy = null;
          try
          {
            Asn1Sequence mapping = DerSequence.GetInstance(mappings[j]);

            issuerDomainPolicy = DerObjectIdentifier.GetInstance(mapping[0]);
            subjectDomainPolicy = DerObjectIdentifier.GetInstance(mapping[1]);
          }
          catch (Exception e)
          {
            throw new PkixCertPathValidatorException(
              "Policy mappings extension contents could not be decoded.", e, certPath, index);
          }

          if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(issuerDomainPolicy.Id))
            throw new PkixCertPathValidatorException(
              "IssuerDomainPolicy is anyPolicy", null, certPath, index);

          if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(subjectDomainPolicy.Id))
            throw new PkixCertPathValidatorException(
              "SubjectDomainPolicy is anyPolicy,", null, certPath, index);
        }
      }
    }

    internal static PkixPolicyNode ProcessCertD(
      PkixCertPath  certPath,
      int        index,
      ISet      acceptablePolicies,
      PkixPolicyNode  validPolicyTree,
      IList[]      policyNodes,
      int        inhibitAnyPolicy)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      int n = certs.Count;
      // i as defined in the algorithm description
      int i = n - index;
      //
      // (d) policy Information checking against initial policy and
      // policy mapping
      //
      Asn1Sequence certPolicies = null;
      try
      {
        certPolicies = DerSequence.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CertificatePolicies)); 
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException(
          "Could not read certificate policies extension from certificate.", e, certPath, index);
      }
      if (certPolicies != null && validPolicyTree != null)
      {
        //
        // (d) (1)
        //
        ISet pols = new HashSet();

        foreach (Asn1Encodable ae in certPolicies)
        {
          PolicyInformation pInfo = PolicyInformation.GetInstance(ae.ToAsn1Object());
          DerObjectIdentifier pOid = pInfo.PolicyIdentifier;

          pols.Add(pOid.Id);

          if (!Rfc3280CertPathUtilities.ANY_POLICY.Equals(pOid.Id))
          {
            ISet pq = null;
            try
            {
              pq = PkixCertPathValidatorUtilities.GetQualifierSet(pInfo.PolicyQualifiers);
            }
            catch (PkixCertPathValidatorException ex)
            {
              throw new PkixCertPathValidatorException(
                "Policy qualifier info set could not be build.", ex, certPath, index);
            }

            bool match = PkixCertPathValidatorUtilities.ProcessCertD1i(i, policyNodes, pOid, pq);

            if (!match)
            {
              PkixCertPathValidatorUtilities.ProcessCertD1ii(i, policyNodes, pOid, pq);
            }
          }
        }

        if (acceptablePolicies.IsEmpty || acceptablePolicies.Contains(Rfc3280CertPathUtilities.ANY_POLICY))
        {
          acceptablePolicies.Clear();
          acceptablePolicies.AddAll(pols);
        }
        else
        {
          ISet t1 = new HashSet();

          foreach (object o in acceptablePolicies)
          {
            if (pols.Contains(o))
            {
              t1.Add(o);
            }
          }
          acceptablePolicies.Clear();
          acceptablePolicies.AddAll(t1);
        }

        //
        // (d) (2)
        //
        if ((inhibitAnyPolicy > 0) || ((i < n) && PkixCertPathValidatorUtilities.IsSelfIssued(cert)))
        {
          foreach (Asn1Encodable ae in certPolicies)
          {
            PolicyInformation pInfo = PolicyInformation.GetInstance(ae.ToAsn1Object());
            if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(pInfo.PolicyIdentifier.Id))
            {
              ISet _apq = PkixCertPathValidatorUtilities.GetQualifierSet(pInfo.PolicyQualifiers);
              IList _nodes = policyNodes[i - 1];

              for (int k = 0; k < _nodes.Count; k++)
              {
                PkixPolicyNode _node = (PkixPolicyNode)_nodes[k];

                IEnumerator  _policySetIter = _node.ExpectedPolicies.GetEnumerator();
                while (_policySetIter.MoveNext())
                {
                  object _tmp = _policySetIter.Current;

                  string _policy;
                  if (_tmp is string)
                  {
                    _policy = (string)_tmp;
                  }
                  else if (_tmp is DerObjectIdentifier)
                  {
                    _policy = ((DerObjectIdentifier)_tmp).Id;
                  }
                  else
                  {
                    continue;
                  }

                  bool _found = false;

                  foreach (PkixPolicyNode _child in _node.Children)
                  {
                    if (_policy.Equals(_child.ValidPolicy))
                    {
                      _found = true;
                    }
                  }

                  if (!_found)
                  {
                    ISet _newChildExpectedPolicies = new HashSet();
                    _newChildExpectedPolicies.Add(_policy);

                    PkixPolicyNode _newChild = new PkixPolicyNode(new ArrayList(), i,
                      _newChildExpectedPolicies, _node, _apq, _policy, false);
                    _node.AddChild(_newChild);
                    policyNodes[i].Add(_newChild);
                  }
                }
              }
              break;
            }
          }
        }

        PkixPolicyNode _validPolicyTree = validPolicyTree;
        //
        // (d) (3)
        //
        for (int j = (i - 1); j >= 0; j--)
        {
          IList nodes = policyNodes[j];

          for (int k = 0; k < nodes.Count; k++)
          {
            PkixPolicyNode node = (PkixPolicyNode)nodes[k];
            if (!node.HasChildren)
            {
              _validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(_validPolicyTree, policyNodes,
                node);
              if (_validPolicyTree == null)
              {
                break;
              }
            }
          }
        }

        //
        // d (4)
        //
        ISet criticalExtensionOids = cert.GetCriticalExtensionOids();

        if (criticalExtensionOids != null)
        {
          bool critical = criticalExtensionOids.Contains(X509Extensions.CertificatePolicies.Id);

          IList nodes = policyNodes[i];
          for (int j = 0; j < nodes.Count; j++)
          {
            PkixPolicyNode node = (PkixPolicyNode)nodes[j];
            node.IsCritical = critical;
          }
        }
        return _validPolicyTree;
      }
      return null;
    }

    /**
    * If the DP includes cRLIssuer, then verify that the issuer field in the
    * complete CRL matches cRLIssuer in the DP and that the complete CRL
    * contains an 
    *      g distribution point extension with the indirectCRL
    * boolean asserted. Otherwise, verify that the CRL issuer matches the
    * certificate issuer.
    *
    * @param dp   The distribution point.
    * @param cert The certificate ot attribute certificate.
    * @param crl  The CRL for <code>cert</code>.
    * @throws AnnotatedException if one of the above conditions does not apply or an error
    *                            occurs.
    */
    internal static void ProcessCrlB1(
      DistributionPoint  dp,
      object        cert,
      X509Crl        crl)
    {
      Asn1Object idp = PkixCertPathValidatorUtilities.GetExtensionValue(
        crl, X509Extensions.IssuingDistributionPoint);

      bool isIndirect = false;
      if (idp != null)
      {
        if (IssuingDistributionPoint.GetInstance(idp).IsIndirectCrl)
        {
          isIndirect = true;
        }
      }
      byte[] issuerBytes = crl.IssuerDN.GetEncoded();

      bool matchIssuer = false;
      if (dp.CrlIssuer != null)
      {
        GeneralName[] genNames = dp.CrlIssuer.GetNames();
        for (int j = 0; j < genNames.Length; j++)
        {
          if (genNames[j].TagNo == GeneralName.DirectoryName)
          {
            try
            {
              if (Org.BouncyCastle.Utilities.Arrays.AreEqual(genNames[j].Name.ToAsn1Object().GetEncoded(), issuerBytes))
              {
                matchIssuer = true;
              }
            }
            catch (IOException e)
            {
              throw new Exception(
                "CRL issuer information from distribution point cannot be decoded.", e);
            }
          }
        }
        if (matchIssuer && !isIndirect)
        {
          throw new Exception("Distribution point contains cRLIssuer field but CRL is not indirect.");
        }
        if (!matchIssuer)
        {
          throw new Exception("CRL issuer of CRL does not match CRL issuer of distribution point.");
        }
      }
      else
      {
        if (crl.IssuerDN.Equivalent(PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert), true))
        {
          matchIssuer = true;
        }
      }
      if (!matchIssuer)
      {
        throw new Exception("Cannot find matching CRL issuer for certificate.");
      }
    }

    internal static ReasonsMask ProcessCrlD(
      X509Crl        crl,
      DistributionPoint  dp)
      //throws AnnotatedException
    {
      IssuingDistributionPoint idp = null;
      try
      {
        idp = IssuingDistributionPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.IssuingDistributionPoint));
      }
      catch (Exception e)
      {
        throw new Exception("issuing distribution point extension could not be decoded.", e);
      }

      // (d) (1)
      if (idp != null && idp.OnlySomeReasons != null && dp.Reasons != null)
      {
        return new ReasonsMask(dp.Reasons.IntValue).Intersect(new ReasonsMask(idp.OnlySomeReasons
          .IntValue));
      }
      // (d) (4)
      if ((idp == null || idp.OnlySomeReasons == null) && dp.Reasons == null)
      {
        return ReasonsMask.AllReasons;
      }

      // (d) (2) and (d)(3)

      ReasonsMask dpReasons = null;

      if (dp.Reasons == null)
      {
        dpReasons = ReasonsMask.AllReasons;
      }
      else
      {
        dpReasons = new ReasonsMask(dp.Reasons.IntValue);
      }

      ReasonsMask idpReasons = null;

      if (idp == null)
      {
        idpReasons = ReasonsMask.AllReasons;
      }
      else
      {
        idpReasons = new ReasonsMask(idp.OnlySomeReasons.IntValue);
      }

      return dpReasons.Intersect(idpReasons);
    }

    /**
    * Obtain and validate the certification path for the complete CRL issuer.
    * If a key usage extension is present in the CRL issuer's certificate,
    * verify that the cRLSign bit is set.
    *
    * @param crl                CRL which contains revocation information for the certificate
    *                           <code>cert</code>.
    * @param cert               The attribute certificate or certificate to check if it is
    *                           revoked.
    * @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
    * @param defaultCRLSignKey  The public key of the issuer certificate
    *                           <code>defaultCRLSignCert</code>.
    * @param paramsPKIX         paramsPKIX PKIX parameters.
    * @param certPathCerts      The certificates on the certification path.
    * @return A <code>Set</code> with all keys of possible CRL issuer
    *         certificates.
    * @throws AnnotatedException if the CRL is not valid or the status cannot be checked or
    *                            some error occurs.
    */
    internal static ISet ProcessCrlF(
      X509Crl          crl,
      object          cert,
      X509Certificate      defaultCRLSignCert,
      AsymmetricKeyParameter  defaultCRLSignKey,
      PkixParameters      paramsPKIX,
      IList          certPathCerts)
    {
      // (f)

      // get issuer from CRL
      X509CertStoreSelector selector = new X509CertStoreSelector();
      try
      {
        selector.Subject = crl.IssuerDN;
      }
      catch (IOException e)
      {
        throw new Exception(
          "Subject criteria for certificate selector to find issuer certificate for CRL could not be set.", e);
      }

      // get CRL signing certs
      ArrayList coll = new ArrayList();

      try
      {
        coll.AddRange(PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetStores()));
        coll.AddRange(PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetAdditionalStores()));
      }
      catch (Exception e)
      {
        throw new Exception("Issuer certificate for CRL cannot be searched.", e);
      }

      coll.Add(defaultCRLSignCert);

      IEnumerator cert_it = coll.GetEnumerator();

      IList validCerts = new ArrayList();
      IList validKeys = new ArrayList();

      while (cert_it.MoveNext())
      {
        X509Certificate signingCert = (X509Certificate)cert_it.Current;

        /*
         * CA of the certificate, for which this CRL is checked, has also
         * signed CRL, so skip the path validation, because is already done
         */
        if (signingCert.Equals(defaultCRLSignCert))
        {
          validCerts.Add(signingCert);
          validKeys.Add(defaultCRLSignKey);
          continue;
        }
        try
        {
//          CertPathBuilder builder = CertPathBuilder.GetInstance("PKIX");
          PkixCertPathBuilder builder = new PkixCertPathBuilder();
          selector = new X509CertStoreSelector();
          selector.Certificate = signingCert;

          PkixParameters temp = (PkixParameters)paramsPKIX.Clone();
          temp.SetTargetCertConstraints(selector);

          PkixBuilderParameters parameters = (PkixBuilderParameters)
            PkixBuilderParameters.GetInstance(temp);

          /*
           * if signingCert is placed not higher on the cert path a
           * dependency loop results. CRL for cert is checked, but
           * signingCert is needed for checking the CRL which is dependent
           * on checking cert because it is higher in the cert path and so
           * signing signingCert transitively. so, revocation is disabled,
           * forgery attacks of the CRL are detected in this outer loop
           * for all other it must be enabled to prevent forgery attacks
           */
          if (certPathCerts.Contains(signingCert))
          {
            parameters.IsRevocationEnabled = false;
          }
          else
          {
            parameters.IsRevocationEnabled = true;
          }
          IList certs = builder.Build(parameters).CertPath.Certificates;
          validCerts.Add(signingCert);
          validKeys.Add(PkixCertPathValidatorUtilities.GetNextWorkingKey(certs, 0));
        }
        catch (PkixCertPathBuilderException e)
        {
          throw new Exception("Internal error.", e);
        }
        catch (PkixCertPathValidatorException e)
        {
          throw new Exception("Public key of issuer certificate of CRL could not be retrieved.", e);
        }
        //catch (Exception e)
        //{
        //    throw new Exception(e.Message);
        //}
      }

      ISet checkKeys = new HashSet();

      Exception lastException = null;
      for (int i = 0; i < validCerts.Count; i++)
      {
        X509Certificate signCert = (X509Certificate)validCerts[i];
        bool[] keyusage = signCert.GetKeyUsage();

        if (keyusage != null && (keyusage.Length < 7 || !keyusage[CRL_SIGN]))
        {
          lastException = new Exception(
            "Issuer certificate key usage extension does not permit CRL signing.");
        }
        else
        {
          checkKeys.Add(validKeys[i]);
        }
      }

      if ((checkKeys.Count == 0) && lastException == null)
      {
        throw new Exception("Cannot find a valid issuer certificate.");
      }
      if ((checkKeys.Count == 0) && lastException != null)
      {
        throw lastException;
      }

      return checkKeys;
    }

    internal static AsymmetricKeyParameter ProcessCrlG(
      X509Crl  crl,
      ISet  keys)
    {
      Exception lastException = null;
      foreach (AsymmetricKeyParameter key in keys)
      {
        try
        {
          crl.Verify(key);
          return key;
        }
        catch (Exception e)
        {
          lastException = e;
        }
      }
      throw new Exception("Cannot verify CRL.", lastException);
    }

    internal static X509Crl ProcessCrlH(
      ISet          deltaCrls,
      AsymmetricKeyParameter  key)
    {
      Exception lastException = null;
      foreach (X509Crl crl in deltaCrls)
      {
        try
        {
          crl.Verify(key);
          return crl;
        }
        catch (Exception e)
        {
          lastException = e;
        }
      }
      if (lastException != null)
      {
        throw new Exception("Cannot verify delta CRL.", lastException);
      }
      return null;
    }

    /**
    * Checks a distribution point for revocation information for the
    * certificate <code>cert</code>.
    *
    * @param dp                 The distribution point to consider.
    * @param paramsPKIX         PKIX parameters.
    * @param cert               Certificate to check if it is revoked.
    * @param validDate          The date when the certificate revocation status should be
    *                           checked.
    * @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
    * @param defaultCRLSignKey  The public key of the issuer certificate
    *                           <code>defaultCRLSignCert</code>.
    * @param certStatus         The current certificate revocation status.
    * @param reasonMask         The reasons mask which is already checked.
    * @param certPathCerts      The certificates of the certification path.
    * @throws AnnotatedException if the certificate is revoked or the status cannot be checked
    *                            or some error occurs.
    */
    private static void CheckCrl(
      DistributionPoint dp,
      PkixParameters paramsPKIX,
      X509Certificate cert,
      DateTime validDate,
      X509Certificate defaultCRLSignCert,
      AsymmetricKeyParameter defaultCRLSignKey,
      CertStatus certStatus,
      ReasonsMask reasonMask,
      IList certPathCerts)
      //throws AnnotatedException
    {
      DateTime currentDate = DateTime.UtcNow;

      if (validDate.Ticks > currentDate.Ticks)
      {
        throw new Exception("Validation time is in future.");
      }

      // (a)
      /*
       * We always get timely valid CRLs, so there is no step (a) (1).
       * "locally cached" CRLs are assumed to be in getStore(), additional
       * CRLs must be enabled in the ExtendedPKIXParameters and are in
       * getAdditionalStore()
       */

      ISet crls = PkixCertPathValidatorUtilities.GetCompleteCrls(dp, cert, currentDate, paramsPKIX);
      bool validCrlFound = false;
      Exception lastException = null;

      IEnumerator crl_iter = crls.GetEnumerator();

      while (crl_iter.MoveNext() && certStatus.Status == CertStatus.Unrevoked && !reasonMask.IsAllReasons)
      {
        try
        {
          X509Crl crl = (X509Crl)crl_iter.Current;

          // (d)
          ReasonsMask interimReasonsMask = Rfc3280CertPathUtilities.ProcessCrlD(crl, dp);

          // (e)
          /*
           * The reasons mask is updated at the end, so only valid CRLs
           * can update it. If this CRL does not contain new reasons it
           * must be ignored.
           */
          if (!interimReasonsMask.HasNewReasons(reasonMask))
          {
            continue;
          }

          // (f)
          ISet keys = Rfc3280CertPathUtilities.ProcessCrlF(crl, cert, defaultCRLSignCert, defaultCRLSignKey,
            paramsPKIX, certPathCerts);
          // (g)
          AsymmetricKeyParameter key = Rfc3280CertPathUtilities.ProcessCrlG(crl, keys);

          X509Crl deltaCRL = null;

          if (paramsPKIX.IsUseDeltasEnabled)
          {
            // get delta CRLs
            ISet deltaCRLs = PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl);
            // we only want one valid delta CRL
            // (h)
            deltaCRL = Rfc3280CertPathUtilities.ProcessCrlH(deltaCRLs, key);
          }

          /*
           * CRL must be be valid at the current time, not the validation
           * time. If a certificate is revoked with reason keyCompromise,
           * cACompromise, it can be used for forgery, also for the past.
           * This reason may not be contained in older CRLs.
           */

          /*
           * in the chain model signatures stay valid also after the
           * certificate has been expired, so they do not have to be in
           * the CRL validity time
           */

          if (paramsPKIX.ValidityModel != PkixParameters.ChainValidityModel)
          {
            /*
             * if a certificate has expired, but was revoked, it is not
             * more in the CRL, so it would be regarded as valid if the
             * first check is not done
             */
            if (cert.NotAfter.Ticks < crl.ThisUpdate.Ticks)
            {
              throw new Exception("No valid CRL for current time found.");
            }
          }

          Rfc3280CertPathUtilities.ProcessCrlB1(dp, cert, crl);
                    
          // (b) (2)
          Rfc3280CertPathUtilities.ProcessCrlB2(dp, cert, crl);

          // (c)
          Rfc3280CertPathUtilities.ProcessCrlC(deltaCRL, crl, paramsPKIX);

          // (i)
          Rfc3280CertPathUtilities.ProcessCrlI(validDate, deltaCRL, cert, certStatus, paramsPKIX);

          // (j)
          Rfc3280CertPathUtilities.ProcessCrlJ(validDate, crl, cert, certStatus);

          // (k)
          if (certStatus.Status == CrlReason.RemoveFromCrl)
          {
            certStatus.Status = CertStatus.Unrevoked;
          }

          // update reasons mask
          reasonMask.AddReasons(interimReasonsMask);

          ISet criticalExtensions = crl.GetCriticalExtensionOids();

          if (criticalExtensions != null)
          {
            criticalExtensions = new HashSet(criticalExtensions);
            criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
            criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);

            if (!criticalExtensions.IsEmpty)
              throw new Exception("CRL contains unsupported critical extensions.");
          }

          if (deltaCRL != null)
          {
            criticalExtensions = deltaCRL.GetCriticalExtensionOids();
            if (criticalExtensions != null)
            {
              criticalExtensions = new HashSet(criticalExtensions);
              criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
              criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);

              if (!criticalExtensions.IsEmpty)
                throw new Exception("Delta CRL contains unsupported critical extension.");
            }
          }

          validCrlFound = true;
        }
        catch (Exception e)
        {
          lastException = e;
        }
      }
      if (!validCrlFound)
      {
        throw lastException;
      }
    }

    /**
     * Checks a certificate if it is revoked.
     *
     * @param paramsPKIX       PKIX parameters.
     * @param cert             Certificate to check if it is revoked.
     * @param validDate        The date when the certificate revocation status should be
     *                         checked.
     * @param sign             The issuer certificate of the certificate <code>cert</code>.
     * @param workingPublicKey The public key of the issuer certificate <code>sign</code>.
     * @param certPathCerts    The certificates of the certification path.
     * @throws AnnotatedException if the certificate is revoked or the status cannot be checked
     *                            or some error occurs.
     */
    protected static void CheckCrls(
      PkixParameters      paramsPKIX,
      X509Certificate      cert,
      DateTime        validDate,
      X509Certificate      sign,
      AsymmetricKeyParameter  workingPublicKey,
      IList          certPathCerts)
    {
      Exception lastException = null;
      CrlDistPoint crldp = null;

      try
      {
        crldp = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CrlDistributionPoints));
      }
      catch (Exception e)
      {
        throw new Exception("CRL distribution point extension could not be read.", e);
      }

      try
      {
        PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
      }
      catch (Exception e)
      {
        throw new Exception(
          "No additional CRL locations could be decoded from CRL distribution point extension.", e);
      }
      CertStatus certStatus = new CertStatus();
      ReasonsMask reasonsMask = new ReasonsMask();

      bool validCrlFound = false;

      // for each distribution point
      if (crldp != null)
      {
        DistributionPoint[] dps = null;
        try
        {
          dps = crldp.GetDistributionPoints();
        }
        catch (Exception e)
        {
          throw new Exception("Distribution points could not be read.", e);
        }
        if (dps != null)
        {
          for (int i = 0; i < dps.Length && certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons; i++)
          {
            PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone();
            try
            {
              CheckCrl(dps[i], paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, certPathCerts);
              validCrlFound = true;
            }
            catch (Exception e)
            {
              lastException = e;
            }
          }
        }
      }

      /*
       * If the revocation status has not been determined, repeat the process
       * above with any available CRLs not specified in a distribution point
       * but issued by the certificate issuer.
       */

      if (certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons)
      {
        try
        {
          /*
           * assume a DP with both the reasons and the cRLIssuer fields
           * omitted and a distribution point name of the certificate
           * issuer.
           */
          Asn1Object issuer = null;
          try
          {
            issuer = new Asn1InputStream(cert.IssuerDN.GetEncoded()).ReadObject();
          }
          catch (Exception e)
          {
            throw new Exception("Issuer from certificate for CRL could not be reencoded.", e);
          }
          DistributionPoint dp = new DistributionPoint(new DistributionPointName(0, new GeneralNames(
            new GeneralName(GeneralName.DirectoryName, issuer))), null, null);
          PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone();

          CheckCrl(dp, paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask,
            certPathCerts);
                    
          validCrlFound = true;
        }
        catch (Exception e)
        {
          lastException = e;
        }
      }

      if (!validCrlFound)
      {
        throw lastException;
      }
      if (certStatus.Status != CertStatus.Unrevoked)
      {
        // TODO This format is forced by the NistCertPath tests
        string formattedDate = certStatus.RevocationDate.Value.ToString(
          "G", CultureInfo.CreateSpecificCulture("en-us"));
        string message = "Certificate revocation after " + formattedDate;
        message += ", reason: " + CrlReasons[certStatus.Status];
        throw new Exception(message);
      }

      if (!reasonsMask.IsAllReasons && certStatus.Status == CertStatus.Unrevoked)
      {
        certStatus.Status = CertStatus.Undetermined;
      }
           
      if (certStatus.Status == CertStatus.Undetermined)
      {
        throw new Exception("Certificate status could not be determined.");
      }
    }

    internal static PkixPolicyNode PrepareCertB(
      PkixCertPath  certPath,
      int        index,
      IList[]      policyNodes,
      PkixPolicyNode  validPolicyTree,
      int        policyMapping)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      int n = certs.Count;
      // i as defined in the algorithm description
      int i = n - index;
      // (b)
      //
      Asn1Sequence pm = null;
      try
      {
        pm = (Asn1Sequence)Asn1Sequence.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyMappings));
      }
      catch (Exception ex)
      {
        throw new PkixCertPathValidatorException(
          "Policy mappings extension could not be decoded.", ex, certPath, index);
      }
      PkixPolicyNode _validPolicyTree = validPolicyTree;
      if (pm != null)
      {
        Asn1Sequence mappings = (Asn1Sequence)pm;
        IDictionary m_idp = new Hashtable();
        ISet s_idp = new HashSet();

        for (int j = 0; j < mappings.Count; j++)
        {
          Asn1Sequence mapping = (Asn1Sequence) mappings[j];
          string id_p = ((DerObjectIdentifier) mapping[0]).Id;
          string sd_p = ((DerObjectIdentifier) mapping[1]).Id;
          ISet tmp;
                
          if (!m_idp.Contains(id_p))
          {
            tmp = new HashSet();
            tmp.Add(sd_p);
            m_idp[id_p] = tmp;
            s_idp.Add(id_p);
          }
          else
          {
            tmp = (ISet)m_idp[id_p];
            tmp.Add(sd_p);
          }
        }

        IEnumerator it_idp = s_idp.GetEnumerator();
        while (it_idp.MoveNext())
        {
          string id_p = (string)it_idp.Current;

          //
          // (1)
          //
          if (policyMapping > 0)
          {
            bool idp_found = false;
            IEnumerator nodes_i = policyNodes[i].GetEnumerator();

            while (nodes_i.MoveNext())
            {
              PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current;
              if (node.ValidPolicy.Equals(id_p))
              {
                idp_found = true;
                node.ExpectedPolicies = (ISet)m_idp[id_p];
                break;
              }
            }

            if (!idp_found)
            {
              nodes_i = policyNodes[i].GetEnumerator();
              while (nodes_i.MoveNext())
              {
                PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current;
                if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(node.ValidPolicy))
                {
                  ISet pq = null;
                  Asn1Sequence policies = null;
                  try
                  {
                    policies = (Asn1Sequence)PkixCertPathValidatorUtilities.GetExtensionValue(cert,
                      X509Extensions.CertificatePolicies);
                  }
                  catch (Exception e)
                  {
                    throw new PkixCertPathValidatorException(
                      "Certificate policies extension could not be decoded.", e, certPath, index);
                  }

                  foreach (Asn1Encodable ae in policies)
                  {
                    PolicyInformation pinfo = null;
                    try
                    {
                      pinfo = PolicyInformation.GetInstance(ae.ToAsn1Object());
                    }
                    catch (Exception ex)
                    {
                      throw new PkixCertPathValidatorException(
                        "Policy information could not be decoded.", ex, certPath, index);
                    }
                    if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(pinfo.PolicyIdentifier.Id))
                    {
                      try
                      {
                        pq = PkixCertPathValidatorUtilities
                          .GetQualifierSet(pinfo.PolicyQualifiers);
                      }
                      catch (PkixCertPathValidatorException ex)
                      {
                        throw new PkixCertPathValidatorException(
                          "Policy qualifier info set could not be decoded.", ex, certPath,
                          index);
                      }
                      break;
                    }
                  }
                  bool ci = false;
                  ISet critExtOids = cert.GetCriticalExtensionOids();
                  if (critExtOids != null)
                  {
                    ci = critExtOids.Contains(X509Extensions.CertificatePolicies.Id);
                  }

                  PkixPolicyNode p_node = (PkixPolicyNode)node.Parent;
                  if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(p_node.ValidPolicy))
                  {
                    PkixPolicyNode c_node = new PkixPolicyNode(new ArrayList(), i, 
                      (ISet)m_idp[id_p], p_node, pq, id_p, ci);
                    p_node.AddChild(c_node);
                    policyNodes[i].Add(c_node);
                  }
                  break;
                }
              }
            }

            //
            // (2)
            //
          }
          else if (policyMapping <= 0)
          {
            //IEnumerator nodes_i = policyNodes[i].GetEnumerator();
            //IEnumerator nodes_i = ArrayList.ReadOnly(policyNodes[i]).GetEnumerator();

            IEnumerator nodes_i = new ArrayList(policyNodes[i]).GetEnumerator();

            while (nodes_i.MoveNext())
            {
              PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current;
              if (node.ValidPolicy.Equals(id_p))
              {
                PkixPolicyNode p_node = (PkixPolicyNode)node.Parent;
                //p_node.RemoveChild(node);
                p_node.RemoveChild(node);
                //((IList)policyNodes[i]).Remove(nodes_i.Current);
                            
                for (int k = (i - 1); k >= 0; k--)
                {
                  IList nodes = policyNodes[k];
                  for (int l = 0; l < nodes.Count; l++)
                  {
                    PkixPolicyNode node2 = (PkixPolicyNode)nodes[l];
                    if (!node2.HasChildren)
                    {
                      _validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(
                        _validPolicyTree, policyNodes, node2);
                      if (_validPolicyTree == null)
                      {
                        break;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      return _validPolicyTree;
    }

    internal static ISet[] ProcessCrlA1ii(
      DateTime    currentDate,
      PkixParameters  paramsPKIX,
      X509Certificate  cert,
      X509Crl      crl)
    {
      ISet completeSet = new HashSet();
      ISet deltaSet = new HashSet();
      X509CrlStoreSelector crlselect = new X509CrlStoreSelector();
      crlselect.CertificateChecking = cert;

      if (paramsPKIX.Date != null)
      {
        crlselect.DateAndTime = paramsPKIX.Date;
      }
      else
      {
        crlselect.DateAndTime = new DateTimeObject(currentDate);
      }

      try
      {                
        IList issuer = new ArrayList();
        issuer.Add(crl.IssuerDN);
        crlselect.Issuers = issuer;
      }
      catch (IOException e)
      {
        throw new Exception("Cannot extract issuer from CRL." + e, e);
      }

      crlselect.CompleteCrlEnabled = true;

      // get complete CRL(s)
      try
      {
        completeSet.AddAll(PkixCertPathValidatorUtilities.FindCrls(crlselect, paramsPKIX.GetAdditionalStores()));
        completeSet.AddAll(PkixCertPathValidatorUtilities.FindCrls(crlselect, paramsPKIX.GetStores()));
      }
      catch (Exception e)
      {
        throw new Exception("Exception obtaining complete CRLs.", e);
      }
      if (paramsPKIX.IsUseDeltasEnabled)
      {
        // get delta CRL(s)
        try
        {
          deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
        }
        catch (Exception e)
        {
          throw new Exception("Exception obtaining delta CRLs.", e);
        }
      }
      return new ISet[]
      {
        completeSet,
        deltaSet};
    }

    internal static ISet ProcessCrlA1i(
      DateTime    currentDate,
      PkixParameters  paramsPKIX,
      X509Certificate  cert,
      X509Crl      crl)
    {
      ISet deltaSet = new HashSet();
      if (paramsPKIX.IsUseDeltasEnabled)
      {
        CrlDistPoint freshestCRL = null;
        try
        {
          freshestCRL = CrlDistPoint.GetInstance(
            PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.FreshestCrl));
        }
        catch (Exception e)
        {
          throw new Exception("Freshest CRL extension could not be decoded from certificate.", e);
        }

        if (freshestCRL == null)
        {
          try
          {
            freshestCRL = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.FreshestCrl));
          }
          catch (Exception e)
          {
            throw new Exception("Freshest CRL extension could not be decoded from CRL.", e);
          }
        }
        if (freshestCRL != null)
        {
          try
          {
            PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(freshestCRL, paramsPKIX);
          }
          catch (Exception e)
          {
            throw new Exception(
              "No new delta CRL locations could be added from Freshest CRL extension.", e);
          }
          // get delta CRL(s)
          try
          {
            deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
          }
          catch (Exception e)
          {
            throw new Exception("Exception obtaining delta CRLs.", e);
          }
        }
      }
      return deltaSet;
    }

    internal static void ProcessCertF(
      PkixCertPath  certPath,
      int        index,
      PkixPolicyNode  validPolicyTree,
      int        explicitPolicy)
    {
      //
      // (f)
      //
      if (explicitPolicy <= 0 && validPolicyTree == null)
      {
        throw new PkixCertPathValidatorException(
          "No valid policy tree found when one expected.", null, certPath, index);
      }
    }

    internal static void ProcessCertA(
      PkixCertPath      certPath,
      PkixParameters      paramsPKIX,
      int            index,
      AsymmetricKeyParameter  workingPublicKey,
      X509Name        workingIssuerName,
      X509Certificate      sign)
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      //
      // (a) verify
      //
      try
      {
        // (a) (1)
        //
        cert.Verify(workingPublicKey);
      }
      catch (GeneralSecurityException e)
      {
        throw new PkixCertPathValidatorException("Could not validate certificate signature.", e, certPath, index);
      }

      try
      {
        // (a) (2)
        //
        cert.CheckValidity(PkixCertPathValidatorUtilities
          .GetValidCertDateFromValidityModel(paramsPKIX, certPath, index));
      }
      catch (CertificateExpiredException e)
      {
        throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index);
      }
      catch (CertificateNotYetValidException e)
      {
        throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index);
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException("Could not validate time of certificate.", e, certPath, index);
      }

      //
      // (a) (3)
      //
      if (paramsPKIX.IsRevocationEnabled)
      {
        try
        {
          CheckCrls(paramsPKIX, cert, PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(paramsPKIX,
            certPath, index), sign, workingPublicKey, certs);
        }
        catch (Exception e)
        {
          Exception cause = e.InnerException;
          if (cause == null)
          {
            cause = e;            
          }
          throw new PkixCertPathValidatorException(e.Message, cause, certPath, index);
        }
      }

      //
      // (a) (4) name chaining
      //
      X509Name issuer = PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert);
      if (!issuer.Equivalent(workingIssuerName, true))
      {
        throw new PkixCertPathValidatorException("IssuerName(" + issuer
          + ") does not match SubjectName(" + workingIssuerName + ") of signing certificate.", null,
          certPath, index);
      }
    }

    internal static int PrepareNextCertI1(
      PkixCertPath  certPath,
      int        index,
      int        explicitPolicy)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      //
      // (i)
      //
      Asn1Sequence pc = null;
      try
      {
        pc = DerSequence.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints));
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException(
          "Policy constraints extension cannot be decoded.", e, certPath, index);
      }

      int tmpInt;

      if (pc != null)
      {
        IEnumerator policyConstraints = pc.GetEnumerator();

        while (policyConstraints.MoveNext())
        {
          try
          {

            Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current);
            if (constraint.TagNo == 0)
            {
              tmpInt = DerInteger.GetInstance(constraint).Value.IntValue;
              if (tmpInt < explicitPolicy)
              {
                return tmpInt;
              }
              break;
            }
          }
          catch (ArgumentException e)
          {
            throw new PkixCertPathValidatorException(
              "Policy constraints extension contents cannot be decoded.", e, certPath, index);
          }
        }
      }
      return explicitPolicy;
    }

    internal static int PrepareNextCertI2(
      PkixCertPath  certPath,
      int        index,
      int        policyMapping)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (i)
      //
      Asn1Sequence pc = null;
      try
      {
        pc = DerSequence.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints));
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException(
          "Policy constraints extension cannot be decoded.", e, certPath, index);
      }

      int tmpInt;

      if (pc != null)
      {
        IEnumerator policyConstraints = pc.GetEnumerator();

        while (policyConstraints.MoveNext())
        {
          try
          {
            Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current);
            if (constraint.TagNo == 1)
            {
              tmpInt = DerInteger.GetInstance(constraint).Value.IntValue;
              if (tmpInt < policyMapping)
              {
                return tmpInt;
              }
              break;
            }
          }
          catch (ArgumentException e)
          {
            throw new PkixCertPathValidatorException(
              "Policy constraints extension contents cannot be decoded.", e, certPath, index);
          }
        }
      }
      return policyMapping;
    }

    internal static void PrepareNextCertG(
      PkixCertPath        certPath,
      int              index,
      PkixNameConstraintValidator  nameConstraintValidator)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (g) handle the name constraints extension
      //
      NameConstraints nc = null;
      try
      {
        Asn1Sequence ncSeq = DerSequence.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.NameConstraints));
        if (ncSeq != null)
        {
          nc = new NameConstraints(ncSeq);
        }
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException(
          "Name constraints extension could not be decoded.", e, certPath, index);
      }
      if (nc != null)
      {
        //
        // (g) (1) permitted subtrees
        //
        Asn1Sequence permitted = nc.PermittedSubtrees;
        if (permitted != null)
        {
          try
          {
            nameConstraintValidator.IntersectPermittedSubtree(permitted);
          }
          catch (Exception ex)
          {
            throw new PkixCertPathValidatorException(
              "Permitted subtrees cannot be build from name constraints extension.", ex, certPath, index);
          }
        }

        //
        // (g) (2) excluded subtrees
        //
        Asn1Sequence excluded = nc.ExcludedSubtrees;
        if (excluded != null)
        {
          IEnumerator e = excluded.GetEnumerator();
          try
          {
            while (e.MoveNext())
            {
              GeneralSubtree subtree = GeneralSubtree.GetInstance(e.Current);
              nameConstraintValidator.AddExcludedSubtree(subtree);
            }
          }
          catch (Exception ex)
          {
            throw new PkixCertPathValidatorException(
              "Excluded subtrees cannot be build from name constraints extension.", ex, certPath, index);
          }
        }
      }
    }

    internal static int PrepareNextCertJ(
      PkixCertPath  certPath,
      int        index,
      int        inhibitAnyPolicy)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (j)
      //
      DerInteger iap = null;
      try
      {
        iap = DerInteger.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.InhibitAnyPolicy));
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException(
          "Inhibit any-policy extension cannot be decoded.", e, certPath, index);
      }

      if (iap != null)
      {
        int _inhibitAnyPolicy = iap.Value.IntValue;

        if (_inhibitAnyPolicy < inhibitAnyPolicy)
          return _inhibitAnyPolicy;
      }
      return inhibitAnyPolicy;
    }

    internal static void PrepareNextCertK(
      PkixCertPath  certPath,
      int        index)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      //
      // (k)
      //
      BasicConstraints bc = null;
      try
      {
        bc = BasicConstraints.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.BasicConstraints));
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException("Basic constraints extension cannot be decoded.", e, certPath,
          index);
      }
      if (bc != null)
      {
        if (!(bc.IsCA()))
          throw new PkixCertPathValidatorException("Not a CA certificate");
      }
      else
      {
        throw new PkixCertPathValidatorException("Intermediate certificate lacks BasicConstraints");
      }
    }

    internal static int PrepareNextCertL(
      PkixCertPath  certPath,
      int        index,
      int        maxPathLength)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      //
      // (l)
      //
      if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
      {
        if (maxPathLength <= 0)
        {
          throw new PkixCertPathValidatorException("Max path length not greater than zero", null, certPath, index);
        }

        return maxPathLength - 1;
      }
      return maxPathLength;
    }

    internal static int PrepareNextCertM(
      PkixCertPath  certPath,
      int        index,
      int        maxPathLength)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (m)
      //
      BasicConstraints bc = null;
      try
      {
        bc = BasicConstraints.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.BasicConstraints));
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException("Basic constraints extension cannot be decoded.", e, certPath,
          index);
      }
      if (bc != null)
      {
        BigInteger _pathLengthConstraint = bc.PathLenConstraint;

        if (_pathLengthConstraint != null)
        {
          int _plc = _pathLengthConstraint.IntValue;

          if (_plc < maxPathLength)
          {
            return _plc;
          }
        }
      }
      return maxPathLength;
    }

    internal static void PrepareNextCertN(
      PkixCertPath  certPath,
      int        index)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (n)
      //
      bool[] _usage = cert.GetKeyUsage();

      if ((_usage != null) && !_usage[Rfc3280CertPathUtilities.KEY_CERT_SIGN])
      {
        throw new PkixCertPathValidatorException(
          "Issuer certificate keyusage extension is critical and does not permit key signing.", null,
          certPath, index);
      }
    }

    internal static void PrepareNextCertO(
      PkixCertPath  certPath,
      int        index,
      ISet      criticalExtensions,
      IList      pathCheckers)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (o)
      //
      IEnumerator tmpIter = pathCheckers.GetEnumerator();
      while (tmpIter.MoveNext())
      {
        try
        {
          ((PkixCertPathChecker)tmpIter.Current).Check(cert, criticalExtensions);
        }
        catch (PkixCertPathValidatorException e)
        {
          throw new PkixCertPathValidatorException(e.Message, e.InnerException, certPath, index);
        }
      }
      if (!criticalExtensions.IsEmpty)
      {
        throw new PkixCertPathValidatorException("Certificate has unsupported critical extension.", null, certPath,
          index);
      }
    }

    internal static int PrepareNextCertH1(
      PkixCertPath  certPath,
      int        index,
      int        explicitPolicy)
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (h)
      //
      if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
      {
        //
        // (1)
        //
        if (explicitPolicy != 0)
          return explicitPolicy - 1;
      }
      return explicitPolicy;
    }

    internal static int PrepareNextCertH2(
      PkixCertPath  certPath,
      int        index,
      int        policyMapping)
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (h)
      //
      if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
      {
        //
        // (2)
        //
        if (policyMapping != 0)
          return policyMapping - 1;
      }
      return policyMapping;
    }


    internal static int PrepareNextCertH3(
      PkixCertPath  certPath,
      int        index,
      int        inhibitAnyPolicy)
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (h)
      //
      if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
      {
        //
        // (3)
        //
        if (inhibitAnyPolicy != 0)
          return inhibitAnyPolicy - 1;
      }
      return inhibitAnyPolicy;
    }

    internal static int WrapupCertA(
      int        explicitPolicy,
      X509Certificate  cert)
    {
      //
      // (a)
      //
      if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert) && (explicitPolicy != 0))
      {
        explicitPolicy--;
      }
      return explicitPolicy;
    }

    internal static int WrapupCertB(
      PkixCertPath  certPath,
      int        index,
      int        explicitPolicy)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (b)
      //
      int tmpInt;
      Asn1Sequence pc = null;
      try
      {
        pc = DerSequence.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints));
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException("Policy constraints could no be decoded.", e, certPath, index);
      }

      if (pc != null)
      {
        IEnumerator policyConstraints = pc.GetEnumerator();

        while (policyConstraints.MoveNext())
        {
          Asn1TaggedObject constraint = (Asn1TaggedObject)policyConstraints.Current;
          switch (constraint.TagNo)
          {
            case 0:
              try
              {
                tmpInt = DerInteger.GetInstance(constraint).Value.IntValue;
              }
              catch (Exception e)
              {
                throw new PkixCertPathValidatorException(
                  "Policy constraints requireExplicitPolicy field could no be decoded.", e, certPath,
                  index);
              }
              if (tmpInt == 0)
              {
                return 0;
              }
              break;
          }
        }
      }
      return explicitPolicy;
    }

    internal static void WrapupCertF(
      PkixCertPath  certPath,
      int        index,
      IList      pathCheckers,
      ISet      criticalExtensions)
      //throws CertPathValidatorException
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];
      IEnumerator tmpIter = pathCheckers.GetEnumerator();

      while (tmpIter.MoveNext())
      {
        try
        {
          ((PkixCertPathChecker)tmpIter.Current).Check(cert, criticalExtensions);
        }
        catch (PkixCertPathValidatorException e)
        {
          throw new PkixCertPathValidatorException("Additional certificate path checker failed.", e, certPath,
            index);
        }
      }

      if (!criticalExtensions.IsEmpty)
      {
        throw new PkixCertPathValidatorException("Certificate has unsupported critical extension",
          null, certPath, index);
      }
    }

    internal static PkixPolicyNode WrapupCertG(
      PkixCertPath  certPath,
      PkixParameters  paramsPKIX,
      ISet      userInitialPolicySet,
      int        index,
      IList[]      policyNodes,
      PkixPolicyNode  validPolicyTree,
      ISet      acceptablePolicies)
    {
      int n = certPath.Certificates.Count;

      //
      // (g)
      //
      PkixPolicyNode intersection;

      //
      // (g) (i)
      //
      if (validPolicyTree == null)
      {
        if (paramsPKIX.IsExplicitPolicyRequired)
        {
          throw new PkixCertPathValidatorException(
            "Explicit policy requested but none available.", null, certPath, index);
        }
        intersection = null;
      }
      else if (PkixCertPathValidatorUtilities.IsAnyPolicy(userInitialPolicySet)) // (g)
        // (ii)
      {
        if (paramsPKIX.IsExplicitPolicyRequired)
        {
          if (acceptablePolicies.IsEmpty)
          {
            throw new PkixCertPathValidatorException(
              "Explicit policy requested but none available.", null, certPath, index);
          }
          else
          {
            ISet _validPolicyNodeSet = new HashSet();

            for (int j = 0; j < policyNodes.Length; j++)
            {
              IList _nodeDepth = policyNodes[j];

              for (int k = 0; k < _nodeDepth.Count; k++)
              {
                PkixPolicyNode _node = (PkixPolicyNode)_nodeDepth[k];

                if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(_node.ValidPolicy))
                {
                  foreach (object o in _node.Children)
                  {
                    _validPolicyNodeSet.Add(o);
                  }
                }
              }
            }

            foreach (PkixPolicyNode _node in _validPolicyNodeSet)
            {
              string _validPolicy = _node.ValidPolicy;

              if (!acceptablePolicies.Contains(_validPolicy))
              {
                // TODO?
                // validPolicyTree =
                // removePolicyNode(validPolicyTree, policyNodes,
                // _node);
              }
            }
            if (validPolicyTree != null)
            {
              for (int j = (n - 1); j >= 0; j--)
              {
                IList nodes = policyNodes[j];

                for (int k = 0; k < nodes.Count; k++)
                {
                  PkixPolicyNode node = (PkixPolicyNode)nodes[k];
                  if (!node.HasChildren)
                  {
                    validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree,
                      policyNodes, node);
                  }
                }
              }
            }
          }
        }

        intersection = validPolicyTree;
      }
      else
      {
        //
        // (g) (iii)
        //
        // This implementation is not exactly same as the one described in
        // RFC3280.
        // However, as far as the validation result is concerned, both
        // produce
        // adequate result. The only difference is whether AnyPolicy is
        // remain
        // in the policy tree or not.
        //
        // (g) (iii) 1
        //
        ISet _validPolicyNodeSet = new HashSet();

        for (int j = 0; j < policyNodes.Length; j++)
        {
          IList _nodeDepth = policyNodes[j];

          for (int k = 0; k < _nodeDepth.Count; k++)
          {
            PkixPolicyNode _node = (PkixPolicyNode)_nodeDepth[k];

            if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(_node.ValidPolicy))
            {
              foreach (PkixPolicyNode _c_node in _node.Children)
              {
                if (!Rfc3280CertPathUtilities.ANY_POLICY.Equals(_c_node.ValidPolicy))
                {
                  _validPolicyNodeSet.Add(_c_node);
                }
              }
            }
          }
        }

        //
        // (g) (iii) 2
        //
        IEnumerator _vpnsIter = _validPolicyNodeSet.GetEnumerator();
        while (_vpnsIter.MoveNext())
        {
          PkixPolicyNode _node = (PkixPolicyNode)_vpnsIter.Current;
          string _validPolicy = _node.ValidPolicy;

          if (!userInitialPolicySet.Contains(_validPolicy))
          {
            validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree, policyNodes, _node);
          }
        }

        //
        // (g) (iii) 4
        //
        if (validPolicyTree != null)
        {
          for (int j = (n - 1); j >= 0; j--)
          {
            IList nodes = policyNodes[j];

            for (int k = 0; k < nodes.Count; k++)
            {
              PkixPolicyNode node = (PkixPolicyNode)nodes[k];
              if (!node.HasChildren)
              {
                validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree, policyNodes,
                  node);
              }
            }
          }
        }

        intersection = validPolicyTree;
      }
      return intersection;
    }

    /**
    * If use-deltas is set, verify the issuer and scope of the delta CRL.
    *
    * @param deltaCRL    The delta CRL.
    * @param completeCRL The complete CRL.
    * @param pkixParams  The PKIX paramaters.
    * @throws AnnotatedException if an exception occurs.
    */
    internal static void ProcessCrlC(
      X509Crl      deltaCRL,
      X509Crl      completeCRL,
      PkixParameters  pkixParams)
    {
      if (deltaCRL == null)
        return;

      IssuingDistributionPoint completeidp = null;
      try
      {
        completeidp = IssuingDistributionPoint.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(completeCRL, X509Extensions.IssuingDistributionPoint));
      }
      catch (Exception e)
      {
        throw new Exception("000 Issuing distribution point extension could not be decoded.", e);
      }

      if (pkixParams.IsUseDeltasEnabled)
      {
        // (c) (1)
        if (!deltaCRL.IssuerDN.Equivalent(completeCRL.IssuerDN, true))
          throw new Exception("Complete CRL issuer does not match delta CRL issuer.");

        // (c) (2)
        IssuingDistributionPoint deltaidp = null;
        try
        {
          deltaidp = IssuingDistributionPoint.GetInstance(
            PkixCertPathValidatorUtilities.GetExtensionValue(deltaCRL, X509Extensions.IssuingDistributionPoint));
        }
        catch (Exception e)
        {
          throw new Exception(
            "Issuing distribution point extension from delta CRL could not be decoded.", e);
        }

        if (!Platform.Equals(completeidp, deltaidp))
        {
          throw new Exception(
            "Issuing distribution point extension from delta CRL and complete CRL does not match.");
        }

        // (c) (3)
        Asn1Object completeKeyIdentifier = null;
        try
        {
          completeKeyIdentifier = PkixCertPathValidatorUtilities.GetExtensionValue(
            completeCRL, X509Extensions.AuthorityKeyIdentifier);
        }
        catch (Exception e)
        {
          throw new Exception(
            "Authority key identifier extension could not be extracted from complete CRL.", e);
        }

        Asn1Object deltaKeyIdentifier = null;
        try
        {
          deltaKeyIdentifier = PkixCertPathValidatorUtilities.GetExtensionValue(
            deltaCRL, X509Extensions.AuthorityKeyIdentifier);
        }
        catch (Exception e)
        {
          throw new Exception(
            "Authority key identifier extension could not be extracted from delta CRL.", e);
        }

        if (completeKeyIdentifier == null)
          throw new Exception("CRL authority key identifier is null.");

        if (deltaKeyIdentifier == null)
          throw new Exception("Delta CRL authority key identifier is null.");

        if (!completeKeyIdentifier.Equals(deltaKeyIdentifier))
        {
          throw new Exception(
            "Delta CRL authority key identifier does not match complete CRL authority key identifier.");
        }
      }
    }

    internal static void ProcessCrlI(
      DateTime    validDate,
      X509Crl      deltacrl,
      object      cert,
      CertStatus    certStatus,
      PkixParameters  pkixParams)
    {
      if (pkixParams.IsUseDeltasEnabled && deltacrl != null)
      {
        PkixCertPathValidatorUtilities.GetCertStatus(validDate, deltacrl, cert, certStatus);
      }
    }

    internal static void ProcessCrlJ(
      DateTime  validDate,
      X509Crl    completecrl,
      object    cert,
      CertStatus  certStatus)
    {
      if (certStatus.Status == CertStatus.Unrevoked)
      {
        PkixCertPathValidatorUtilities.GetCertStatus(validDate, completecrl, cert, certStatus);
      }
    }

    internal static PkixPolicyNode ProcessCertE(
      PkixCertPath  certPath,
      int        index,
      PkixPolicyNode  validPolicyTree)
    {
      IList certs = certPath.Certificates;
      X509Certificate cert = (X509Certificate)certs[index];

      //
      // (e)
      //
      Asn1Sequence certPolicies = null;
      try
      {
        certPolicies = DerSequence.GetInstance(
          PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CertificatePolicies));
      }
      catch (Exception e)
      {
        throw new PkixCertPathValidatorException("Could not read certificate policies extension from certificate.",
          e, certPath, index);
      }
      if (certPolicies == null)
      {
        validPolicyTree = null;
      }
      return validPolicyTree;
    }

    internal static readonly string[] CrlReasons = new string[]
    {
      "unspecified",
      "keyCompromise",
      "cACompromise",
      "affiliationChanged",
      "superseded",
      "cessationOfOperation",
      "certificateHold",
      "unknown",
      "removeFromCRL",
      "privilegeWithdrawn",
      "aACompromise"
    };
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.