internal static void AddAdditionalStoresFromAltNames(
     X509Certificate cert,
     PkixParameters pkixParams)
 {
     // if in the IssuerAltName extension an URI
     // is given, add an additinal X.509 store
     if (cert.GetIssuerAlternativeNames() != null)
     {
         IEnumerator it = cert.GetIssuerAlternativeNames().GetEnumerator();
         while (it.MoveNext())
         {
             // look for URI
             IList list = (IList)it.Current;
             //if (list[0].Equals(new Integer(GeneralName.UniformResourceIdentifier)))
             if (list[0].Equals(GeneralName.UniformResourceIdentifier))
             {
                 // found
                 string temp = (string)list[1];
                 PkixCertPathValidatorUtilities.AddAdditionalStoreFromLocation(temp, pkixParams);
             }
         }
     }
 }
 internal static void AdditionalChecks(
     IX509AttributeCertificate attrCert,
     PkixParameters pkixParams)
 {
     // 1
     foreach (string oid in pkixParams.GetProhibitedACAttributes())
     {
         if (attrCert.GetAttributes(oid) != null)
         {
             throw new PkixCertPathValidatorException(
                       "Attribute certificate contains prohibited attribute: "
                       + oid + ".");
         }
     }
     foreach (string oid in pkixParams.GetNecessaryACAttributes())
     {
         if (attrCert.GetAttributes(oid) == null)
         {
             throw new PkixCertPathValidatorException(
                       "Attribute certificate does not contain necessary attribute: "
                       + oid + ".");
         }
     }
 }
Example #3
0
        public virtual object Clone()
        {
            // FIXME Check this whole method against the Java implementation!

            PkixParameters parameters = new PkixParameters(GetTrustAnchors());

            parameters.SetParams(this);
            return(parameters);


//			PkixParameters obj = new PkixParameters(new HashSet());
////			(PkixParameters) this.MemberwiseClone();
//			obj.x509Stores = new ArrayList(x509Stores);
//			obj.certPathCheckers = new ArrayList(certPathCheckers);
//
//			//Iterator iter = certPathCheckers.iterator();
//			//obj.certPathCheckers = new ArrayList();
//			//while (iter.hasNext())
//			//{
//			//	obj.certPathCheckers.add(((PKIXCertPathChecker)iter.next())
//			//		.clone());
//			//}
//			//if (initialPolicies != null)
//			//{
//			//	obj.initialPolicies = new HashSet(initialPolicies);
//			//}
////			if (trustAnchors != null)
////			{
////				obj.trustAnchors = new HashSet(trustAnchors);
////			}
////			if (certSelector != null)
////			{
////				obj.certSelector = (X509CertStoreSelector) certSelector.Clone();
////			}
//			return obj;
        }
        /**
         * Fetches delta CRLs according to RFC 3280 section 5.2.4.
         *
         * @param currentDate The date for which the delta CRLs must be valid.
         * @param paramsPKIX The extended PKIX parameters.
         * @param completeCRL The complete CRL the delta CRL is for.
         * @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
         * @throws Exception if an exception occurs while picking the delta
         *             CRLs.
         */
        internal static ISet GetDeltaCrls(
            DateTime currentDate,
            PkixParameters paramsPKIX,
            X509Crl completeCRL)
        {
            X509CrlStoreSelector deltaSelect = new X509CrlStoreSelector();

            // 5.2.4 (a)
            try
            {
                IList deltaSelectIssuer = Platform.CreateArrayList();
                deltaSelectIssuer.Add(completeCRL.IssuerDN);
                deltaSelect.Issuers = deltaSelectIssuer;
            }
            catch (IOException e)
            {
                throw new Exception("Cannot extract issuer from CRL.", e);
            }

            BigInteger completeCRLNumber = null;

            try
            {
                Asn1Object asn1Object = GetExtensionValue(completeCRL, X509Extensions.CrlNumber);
                if (asn1Object != null)
                {
                    completeCRLNumber = CrlNumber.GetInstance(asn1Object).PositiveValue;
                }
            }
            catch (Exception e)
            {
                throw new Exception(
                          "CRL number extension could not be extracted from CRL.", e);
            }

            // 5.2.4 (b)
            byte[] idp = null;

            try
            {
                Asn1Object obj = GetExtensionValue(completeCRL, X509Extensions.IssuingDistributionPoint);
                if (obj != null)
                {
                    idp = obj.GetDerEncoded();
                }
            }
            catch (Exception e)
            {
                throw new Exception(
                          "Issuing distribution point extension value could not be read.",
                          e);
            }

            // 5.2.4 (d)

            deltaSelect.MinCrlNumber = (completeCRLNumber == null)
                                ?       null
                                :       completeCRLNumber.Add(BigInteger.One);

            deltaSelect.IssuingDistributionPoint        = idp;
            deltaSelect.IssuingDistributionPointEnabled = true;

            // 5.2.4 (c)
            deltaSelect.MaxBaseCrlNumber = completeCRLNumber;

            // find delta CRLs
            ISet temp = CrlUtilities.FindCrls(deltaSelect, paramsPKIX, currentDate);

            ISet result = new HashSet();

            foreach (X509Crl crl in temp)
            {
                if (isDeltaCrl(crl))
                {
                    result.Add(crl);
                }
            }

            return(result);
        }
        /**
         * Add the CRL issuers from the cRLIssuer field of the distribution point or
         * from the certificate if not given to the issuer criterion of the
         * <code>selector</code>.
         * <p>
         * The <code>issuerPrincipals</code> are a collection with a single
         * <code>X500Principal</code> for <code>X509Certificate</code>s. For
         * {@link X509AttributeCertificate}s the issuer may contain more than one
         * <code>X500Principal</code>.
         * </p>
         *
         * @param dp The distribution point.
         * @param issuerPrincipals The issuers of the certificate or attribute
         *            certificate which contains the distribution point.
         * @param selector The CRL selector.
         * @param pkixParams The PKIX parameters containing the cert stores.
         * @throws Exception if an exception occurs while processing.
         * @throws ClassCastException if <code>issuerPrincipals</code> does not
         * contain only <code>X500Principal</code>s.
         */
        internal static void GetCrlIssuersFromDistributionPoint(
            DistributionPoint dp,
            ICollection issuerPrincipals,
            X509CrlStoreSelector selector,
            PkixParameters pkixParams)
        {
            IList issuers = Platform.CreateArrayList();

            // indirect CRL
            if (dp.CrlIssuer != null)
            {
                GeneralName[] genNames = dp.CrlIssuer.GetNames();
                // look for a DN
                for (int j = 0; j < genNames.Length; j++)
                {
                    if (genNames[j].TagNo == GeneralName.DirectoryName)
                    {
                        try
                        {
                            issuers.Add(X509Name.GetInstance(genNames[j].Name.ToAsn1Object()));
                        }
                        catch (IOException e)
                        {
                            throw new Exception(
                                      "CRL issuer information from distribution point cannot be decoded.",
                                      e);
                        }
                    }
                }
            }
            else
            {
                /*
                 * certificate issuer is CRL issuer, distributionPoint field MUST be
                 * present.
                 */
                if (dp.DistributionPointName == null)
                {
                    throw new Exception(
                              "CRL issuer is omitted from distribution point but no distributionPoint field present.");
                }

                // add and check issuer principals
                for (IEnumerator it = issuerPrincipals.GetEnumerator(); it.MoveNext();)
                {
                    issuers.Add((X509Name)it.Current);
                }
            }
            // TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid
            // distributionPoint
            //        if (dp.getDistributionPoint() != null)
            //        {
            //            // look for nameRelativeToCRLIssuer
            //            if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
            //            {
            //                // append fragment to issuer, only one
            //                // issuer can be there, if this is given
            //                if (issuers.size() != 1)
            //                {
            //                    throw new AnnotatedException(
            //                        "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given.");
            //                }
            //                DEREncodable relName = dp.getDistributionPoint().getName();
            //                Iterator it = issuers.iterator();
            //                List issuersTemp = new ArrayList(issuers.size());
            //                while (it.hasNext())
            //                {
            //                    Enumeration e = null;
            //                    try
            //                    {
            //                        e = ASN1Sequence.getInstance(
            //                            new ASN1InputStream(((X500Principal) it.next())
            //                                .getEncoded()).readObject()).getObjects();
            //                    }
            //                    catch (IOException ex)
            //                    {
            //                        throw new AnnotatedException(
            //                            "Cannot decode CRL issuer information.", ex);
            //                    }
            //                    ASN1EncodableVector v = new ASN1EncodableVector();
            //                    while (e.hasMoreElements())
            //                    {
            //                        v.add((DEREncodable) e.nextElement());
            //                    }
            //                    v.add(relName);
            //                    issuersTemp.add(new X500Principal(new DERSequence(v)
            //                        .getDEREncoded()));
            //                }
            //                issuers.clear();
            //                issuers.addAll(issuersTemp);
            //            }
            //        }

            selector.Issuers = issuers;
        }
        /**
         * Checks if an attribute certificate is revoked.
         *
         * @param attrCert Attribute certificate to check if it is revoked.
         * @param paramsPKIX PKIX parameters.
         * @param issuerCert The issuer certificate of the attribute certificate
         *            <code>attrCert</code>.
         * @param validDate The date when the certificate revocation status should
         *            be checked.
         * @param certPathCerts The certificates of the certification path to be
         *            checked.
         *
         * @throws CertPathValidatorException if the certificate is revoked or the
         *             status cannot be checked or some error occurs.
         */
        internal static void CheckCrls(
            IX509AttributeCertificate attrCert,
            PkixParameters paramsPKIX,
            X509Certificate issuerCert,
            DateTime validDate,
            IList certPathCerts)
        {
            if (paramsPKIX.IsRevocationEnabled)
            {
                // check if revocation is available
                if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) == null)
                {
                    CrlDistPoint crldp = null;
                    try
                    {
                        crldp = CrlDistPoint.GetInstance(
                            PkixCertPathValidatorUtilities.GetExtensionValue(
                                attrCert, X509Extensions.CrlDistributionPoints));
                    }
                    catch (Exception e)
                    {
                        throw new PkixCertPathValidatorException(
                                  "CRL distribution point extension could not be read.", e);
                    }
                    try
                    {
                        PkixCertPathValidatorUtilities
                        .AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
                    }
                    catch (Exception e)
                    {
                        throw new PkixCertPathValidatorException(
                                  "No additional CRL locations could be decoded from CRL distribution point extension.", e);
                    }
                    CertStatus  certStatus  = new CertStatus();
                    ReasonsMask reasonsMask = new ReasonsMask();

                    Exception lastException = null;
                    bool      validCrlFound = false;
                    // for each distribution point
                    if (crldp != null)
                    {
                        DistributionPoint[] dps = null;
                        try
                        {
                            dps = crldp.GetDistributionPoints();
                        }
                        catch (Exception e)
                        {
                            throw new PkixCertPathValidatorException(
                                      "Distribution points could not be read.", e);
                        }
                        try
                        {
                            for (int i = 0; i < dps.Length &&
                                 certStatus.Status == CertStatus.Unrevoked &&
                                 !reasonsMask.IsAllReasons; i++)
                            {
                                PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX
                                                                 .Clone();
                                CheckCrl(dps[i], attrCert, paramsPKIXClone,
                                         validDate, issuerCert, certStatus, reasonsMask,
                                         certPathCerts);
                                validCrlFound = true;
                            }
                        }
                        catch (Exception e)
                        {
                            lastException = new Exception(
                                "No valid CRL for distribution point found.", 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(
                                    attrCert.Issuer.GetPrincipals()[0].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, attrCert, paramsPKIXClone, validDate,
                                     issuerCert, certStatus, reasonsMask, certPathCerts);
                            validCrlFound = true;
                        }
                        catch (Exception e)
                        {
                            lastException = new Exception(
                                "No valid CRL for distribution point found.", e);
                        }
                    }

                    if (!validCrlFound)
                    {
                        throw new PkixCertPathValidatorException(
                                  "No valid CRL found.", lastException);
                    }
                    if (certStatus.Status != CertStatus.Unrevoked)
                    {
                        // This format is enforced by the NistCertPath tests
                        string formattedDate = certStatus.RevocationDate.Value.ToString(
                            "ddd MMM dd HH:mm:ss K yyyy");
                        string message = "Attribute certificate revocation after "
                                         + formattedDate;
                        message += ", reason: "
                                   + Rfc3280CertPathUtilities.CrlReasons[certStatus.Status];
                        throw new PkixCertPathValidatorException(message);
                    }
                    if (!reasonsMask.IsAllReasons &&
                        certStatus.Status == CertStatus.Unrevoked)
                    {
                        certStatus.Status = CertStatus.Undetermined;
                    }
                    if (certStatus.Status == CertStatus.Undetermined)
                    {
                        throw new PkixCertPathValidatorException(
                                  "Attribute certificate status could not be determined.");
                    }
                }
                else
                {
                    if (attrCert.GetExtensionValue(X509Extensions.CrlDistributionPoints) != null ||
                        attrCert.GetExtensionValue(X509Extensions.AuthorityInfoAccess) != null)
                    {
                        throw new PkixCertPathValidatorException(
                                  "No rev avail extension is set, but also an AC revocation pointer.");
                    }
                }
            }
        }
        /**
         *
         * Checks a distribution point for revocation information for the
         * certificate <code>attrCert</code>.
         *
         * @param dp The distribution point to consider.
         * @param attrCert The attribute certificate which should be checked.
         * @param paramsPKIX PKIX parameters.
         * @param validDate The date when the certificate revocation status should
         *            be checked.
         * @param issuerCert Certificate to check if it is revoked.
         * @param reasonMask The reasons mask which is already checked.
         * @param certPathCerts The certificates of the certification path to be
         *            checked.
         * @throws Exception if the certificate is revoked or the status
         *             cannot be checked or some error occurs.
         */
        private static void CheckCrl(
            DistributionPoint dp,
            IX509AttributeCertificate attrCert,
            PkixParameters paramsPKIX,
            DateTime validDate,
            X509Certificate issuerCert,
            CertStatus certStatus,
            ReasonsMask reasonMask,
            IList certPathCerts)
        {
            /*
             * 4.3.6 No Revocation Available
             *
             * The noRevAvail extension, defined in [X.509-2000], allows an AC
             * issuer to indicate that no revocation information will be made
             * available for this AC.
             */
            if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) != null)
            {
                return;
            }

            DateTime currentDate = DateTime.UtcNow;

            if (validDate.CompareTo(currentDate) > 0)
            {
                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, attrCert,
                                                                       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, attrCert,
                                                                     null, null, paramsPKIX, certPathCerts);
                    // (g)
                    AsymmetricKeyParameter pubKey = 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, pubKey);
                    }

                    /*
                     * 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 vality 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 (attrCert.NotAfter.CompareTo(crl.ThisUpdate) < 0)
                        {
                            throw new Exception(
                                      "No valid CRL for current time found.");
                        }
                    }

                    Rfc3280CertPathUtilities.ProcessCrlB1(dp, attrCert, crl);

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

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

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

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

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

                    // update reasons mask
                    reasonMask.AddReasons(interimReasonsMask);
                    validCrlFound = true;
                }
                catch (Exception e)
                {
                    lastException = e;
                }
            }
            if (!validCrlFound)
            {
                throw lastException;
            }
        }
        /**
         * Searches for a holder public key certificate and verifies its
         * certification path.
         *
         * @param attrCert the attribute certificate.
         * @param pkixParams The PKIX parameters.
         * @return The certificate path of the holder certificate.
         * @throws Exception if
         *             <ul>
         *             <li>no public key certificate can be found although holder
         *             information is given by an entity name or a base certificate
         *             ID</li>
         *             <li>support classes cannot be created</li>
         *             <li>no certification path for the public key certificate can
         *             be built</li>
         *             </ul>
         */
        internal static PkixCertPath ProcessAttrCert1(
            IX509AttributeCertificate attrCert,
            PkixParameters pkixParams)
        {
            PkixCertPathBuilderResult result = null;
            // find holder PKCs
            ISet holderPKCs = new HashSet();

            if (attrCert.Holder.GetIssuer() != null)
            {
                X509CertStoreSelector selector = new X509CertStoreSelector();
                selector.SerialNumber = attrCert.Holder.SerialNumber;
                X509Name[] principals = attrCert.Holder.GetIssuer();
                for (int i = 0; i < principals.Length; i++)
                {
                    try
                    {
//						if (principals[i] is X500Principal)
                        {
                            selector.Issuer = principals[i];
                        }
                        holderPKCs.AddAll(PkixCertPathValidatorUtilities
                                          .FindCertificates(selector, pkixParams.GetStores()));
                    }
                    catch (Exception e)
                    {
                        throw new PkixCertPathValidatorException(
                                  "Public key certificate for attribute certificate cannot be searched.",
                                  e);
                    }
                }
                if (holderPKCs.IsEmpty)
                {
                    throw new PkixCertPathValidatorException(
                              "Public key certificate specified in base certificate ID for attribute certificate cannot be found.");
                }
            }
            if (attrCert.Holder.GetEntityNames() != null)
            {
                X509CertStoreSelector selector   = new X509CertStoreSelector();
                X509Name[]            principals = attrCert.Holder.GetEntityNames();
                for (int i = 0; i < principals.Length; i++)
                {
                    try
                    {
//						if (principals[i] is X500Principal)
                        {
                            selector.Issuer = principals[i];
                        }
                        holderPKCs.AddAll(PkixCertPathValidatorUtilities
                                          .FindCertificates(selector, pkixParams.GetStores()));
                    }
                    catch (Exception e)
                    {
                        throw new PkixCertPathValidatorException(
                                  "Public key certificate for attribute certificate cannot be searched.",
                                  e);
                    }
                }
                if (holderPKCs.IsEmpty)
                {
                    throw new PkixCertPathValidatorException(
                              "Public key certificate specified in entity name for attribute certificate cannot be found.");
                }
            }

            // verify cert paths for PKCs
            PkixBuilderParameters parameters = (PkixBuilderParameters)
                                               PkixBuilderParameters.GetInstance(pkixParams);

            PkixCertPathValidatorException lastException = null;

            foreach (X509Certificate cert in holderPKCs)
            {
                X509CertStoreSelector selector = new X509CertStoreSelector();
                selector.Certificate = cert;
                parameters.SetTargetConstraints(selector);

                PkixCertPathBuilder builder = new PkixCertPathBuilder();

                try
                {
                    result = builder.Build(PkixBuilderParameters.GetInstance(parameters));
                }
                catch (PkixCertPathBuilderException e)
                {
                    lastException = new PkixCertPathValidatorException(
                        "Certification path for public key certificate of attribute certificate could not be build.",
                        e);
                }
            }
            if (lastException != null)
            {
                throw lastException;
            }
            return(result.CertPath);
        }
Example #9
0
        public virtual PkixCertPathValidatorResult Validate(
            PkixCertPath certPath,
            PkixParameters paramsPkix)
        {
            if (paramsPkix.GetTrustAnchors() == null)
            {
                throw new ArgumentException(
                          "trustAnchors is null, this is not allowed for certification path validation.",
                          "parameters");
            }

            //
            // 6.1.1 - inputs
            //

            //
            // (a)
            //
            IList certs = certPath.Certificates;
            int   n     = certs.Count;

            if (certs.Count == 0)
            {
                throw new PkixCertPathValidatorException("Certification path is empty.", null, certPath, 0);
            }

            //
            // (b)
            //
            // DateTime validDate = PkixCertPathValidatorUtilities.GetValidDate(paramsPkix);

            //
            // (c)
            //
            ISet userInitialPolicySet = paramsPkix.GetInitialPolicies();

            //
            // (d)
            //
            TrustAnchor trust;

            try
            {
                trust = PkixCertPathValidatorUtilities.FindTrustAnchor(
                    (X509Certificate)certs[certs.Count - 1],
                    paramsPkix.GetTrustAnchors());
            }
            catch (Exception e)
            {
                throw new PkixCertPathValidatorException(e.Message, e, certPath, certs.Count - 1);
            }

            if (trust == null)
            {
                throw new PkixCertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1);
            }

            //
            // (e), (f), (g) are part of the paramsPkix object.
            //
            IEnumerator certIter;
            int         index = 0;
            int         i;

            // Certificate for each interation of the validation loop
            // Signature information for each iteration of the validation loop
            //
            // 6.1.2 - setup
            //

            //
            // (a)
            //
            IList[] policyNodes = new IList[n + 1];
            for (int j = 0; j < policyNodes.Length; j++)
            {
                policyNodes[j] = Platform.CreateArrayList();
            }

            ISet policySet = new HashSet();

            policySet.Add(Rfc3280CertPathUtilities.ANY_POLICY);

            PkixPolicyNode validPolicyTree = new PkixPolicyNode(Platform.CreateArrayList(), 0, policySet, null, new HashSet(),
                                                                Rfc3280CertPathUtilities.ANY_POLICY, false);

            policyNodes[0].Add(validPolicyTree);

            //
            // (b) and (c)
            //
            PkixNameConstraintValidator nameConstraintValidator = new PkixNameConstraintValidator();

            // (d)
            //
            int  explicitPolicy;
            ISet acceptablePolicies = new HashSet();

            if (paramsPkix.IsExplicitPolicyRequired)
            {
                explicitPolicy = 0;
            }
            else
            {
                explicitPolicy = n + 1;
            }

            //
            // (e)
            //
            int inhibitAnyPolicy;

            if (paramsPkix.IsAnyPolicyInhibited)
            {
                inhibitAnyPolicy = 0;
            }
            else
            {
                inhibitAnyPolicy = n + 1;
            }

            //
            // (f)
            //
            int policyMapping;

            if (paramsPkix.IsPolicyMappingInhibited)
            {
                policyMapping = 0;
            }
            else
            {
                policyMapping = n + 1;
            }

            //
            // (g), (h), (i), (j)
            //
            AsymmetricKeyParameter workingPublicKey;
            X509Name workingIssuerName;

            X509Certificate sign = trust.TrustedCert;

            try
            {
                if (sign != null)
                {
                    workingIssuerName = sign.SubjectDN;
                    workingPublicKey  = sign.GetPublicKey();
                }
                else
                {
                    workingIssuerName = new X509Name(trust.CAName);
                    workingPublicKey  = trust.CAPublicKey;
                }
            }
            catch (ArgumentException ex)
            {
                throw new PkixCertPathValidatorException("Subject of trust anchor could not be (re)encoded.", ex, certPath,
                                                         -1);
            }

            AlgorithmIdentifier workingAlgId = null;

            try
            {
                workingAlgId = PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey);
            }
            catch (PkixCertPathValidatorException e)
            {
                throw new PkixCertPathValidatorException(
                          "Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1);
            }

//			DerObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.Algorithm;
//			Asn1Encodable workingPublicKeyParameters = workingAlgId.Parameters;

            //
            // (k)
            //
            int maxPathLength = n;

            //
            // 6.1.3
            //

            X509CertStoreSelector certConstraints = paramsPkix.GetTargetCertConstraints();

            if (certConstraints != null && !certConstraints.Match((X509Certificate)certs[0]))
            {
                throw new PkixCertPathValidatorException(
                          "Target certificate in certification path does not match targetConstraints.", null, certPath, 0);
            }

            //
            // initialize CertPathChecker's
            //
            IList pathCheckers = paramsPkix.GetCertPathCheckers();

            certIter = pathCheckers.GetEnumerator();

            while (certIter.MoveNext())
            {
                ((PkixCertPathChecker)certIter.Current).Init(false);
            }

            X509Certificate cert = null;

            for (index = certs.Count - 1; index >= 0; index--)
            {
                // try
                // {
                //
                // i as defined in the algorithm description
                //
                i = n - index;

                //
                // set certificate to be checked in this round
                // sign and workingPublicKey and workingIssuerName are set
                // at the end of the for loop and initialized the
                // first time from the TrustAnchor
                //
                cert = (X509Certificate)certs[index];

                //
                // 6.1.3
                //

                Rfc3280CertPathUtilities.ProcessCertA(certPath, paramsPkix, index, workingPublicKey,
                                                      workingIssuerName, sign);

                Rfc3280CertPathUtilities.ProcessCertBC(certPath, index, nameConstraintValidator);

                validPolicyTree = Rfc3280CertPathUtilities.ProcessCertD(certPath, index,
                                                                        acceptablePolicies, validPolicyTree, policyNodes, inhibitAnyPolicy);

                validPolicyTree = Rfc3280CertPathUtilities.ProcessCertE(certPath, index, validPolicyTree);

                Rfc3280CertPathUtilities.ProcessCertF(certPath, index, validPolicyTree, explicitPolicy);

                //
                // 6.1.4
                //

                if (i != n)
                {
                    if (cert != null && cert.Version == 1)
                    {
                        throw new PkixCertPathValidatorException(
                                  "Version 1 certificates can't be used as CA ones.", null, certPath, index);
                    }

                    Rfc3280CertPathUtilities.PrepareNextCertA(certPath, index);

                    validPolicyTree = Rfc3280CertPathUtilities.PrepareCertB(certPath, index, policyNodes,
                                                                            validPolicyTree, policyMapping);

                    Rfc3280CertPathUtilities.PrepareNextCertG(certPath, index, nameConstraintValidator);

                    // (h)
                    explicitPolicy   = Rfc3280CertPathUtilities.PrepareNextCertH1(certPath, index, explicitPolicy);
                    policyMapping    = Rfc3280CertPathUtilities.PrepareNextCertH2(certPath, index, policyMapping);
                    inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertH3(certPath, index, inhibitAnyPolicy);

                    //
                    // (i)
                    //
                    explicitPolicy = Rfc3280CertPathUtilities.PrepareNextCertI1(certPath, index, explicitPolicy);
                    policyMapping  = Rfc3280CertPathUtilities.PrepareNextCertI2(certPath, index, policyMapping);

                    // (j)
                    inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertJ(certPath, index, inhibitAnyPolicy);

                    // (k)
                    Rfc3280CertPathUtilities.PrepareNextCertK(certPath, index);

                    // (l)
                    maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertL(certPath, index, maxPathLength);

                    // (m)
                    maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertM(certPath, index, maxPathLength);

                    // (n)
                    Rfc3280CertPathUtilities.PrepareNextCertN(certPath, index);

                    ISet criticalExtensions1 = cert.GetCriticalExtensionOids();

                    if (criticalExtensions1 != null)
                    {
                        criticalExtensions1 = new HashSet(criticalExtensions1);

                        // these extensions are handled by the algorithm
                        criticalExtensions1.Remove(X509Extensions.KeyUsage.Id);
                        criticalExtensions1.Remove(X509Extensions.CertificatePolicies.Id);
                        criticalExtensions1.Remove(X509Extensions.PolicyMappings.Id);
                        criticalExtensions1.Remove(X509Extensions.InhibitAnyPolicy.Id);
                        criticalExtensions1.Remove(X509Extensions.IssuingDistributionPoint.Id);
                        criticalExtensions1.Remove(X509Extensions.DeltaCrlIndicator.Id);
                        criticalExtensions1.Remove(X509Extensions.PolicyConstraints.Id);
                        criticalExtensions1.Remove(X509Extensions.BasicConstraints.Id);
                        criticalExtensions1.Remove(X509Extensions.SubjectAlternativeName.Id);
                        criticalExtensions1.Remove(X509Extensions.NameConstraints.Id);
                    }
                    else
                    {
                        criticalExtensions1 = new HashSet();
                    }

                    // (o)
                    Rfc3280CertPathUtilities.PrepareNextCertO(certPath, index, criticalExtensions1, pathCheckers);

                    // set signing certificate for next round
                    sign = cert;

                    // (c)
                    workingIssuerName = sign.SubjectDN;

                    // (d)
                    try
                    {
                        workingPublicKey = PkixCertPathValidatorUtilities.GetNextWorkingKey(certPath.Certificates, index);
                    }
                    catch (PkixCertPathValidatorException e)
                    {
                        throw new PkixCertPathValidatorException("Next working key could not be retrieved.", e, certPath, index);
                    }

                    workingAlgId = PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey);
                    // (f)
//                    workingPublicKeyAlgorithm = workingAlgId.Algorithm;
                    // (e)
//                    workingPublicKeyParameters = workingAlgId.Parameters;
                }
            }

            //
            // 6.1.5 Wrap-up procedure
            //

            explicitPolicy = Rfc3280CertPathUtilities.WrapupCertA(explicitPolicy, cert);

            explicitPolicy = Rfc3280CertPathUtilities.WrapupCertB(certPath, index + 1, explicitPolicy);

            //
            // (c) (d) and (e) are already done
            //

            //
            // (f)
            //
            ISet criticalExtensions = cert.GetCriticalExtensionOids();

            if (criticalExtensions != null)
            {
                criticalExtensions = new HashSet(criticalExtensions);

                // Requires .Id
                // these extensions are handled by the algorithm
                criticalExtensions.Remove(X509Extensions.KeyUsage.Id);
                criticalExtensions.Remove(X509Extensions.CertificatePolicies.Id);
                criticalExtensions.Remove(X509Extensions.PolicyMappings.Id);
                criticalExtensions.Remove(X509Extensions.InhibitAnyPolicy.Id);
                criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
                criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);
                criticalExtensions.Remove(X509Extensions.PolicyConstraints.Id);
                criticalExtensions.Remove(X509Extensions.BasicConstraints.Id);
                criticalExtensions.Remove(X509Extensions.SubjectAlternativeName.Id);
                criticalExtensions.Remove(X509Extensions.NameConstraints.Id);
                criticalExtensions.Remove(X509Extensions.CrlDistributionPoints.Id);
            }
            else
            {
                criticalExtensions = new HashSet();
            }

            Rfc3280CertPathUtilities.WrapupCertF(certPath, index + 1, pathCheckers, criticalExtensions);

            PkixPolicyNode intersection = Rfc3280CertPathUtilities.WrapupCertG(certPath, paramsPkix, userInitialPolicySet,
                                                                               index + 1, policyNodes, validPolicyTree, acceptablePolicies);

            if ((explicitPolicy > 0) || (intersection != null))
            {
                return(new PkixCertPathValidatorResult(trust, intersection, cert.GetPublicKey()));
            }

            throw new PkixCertPathValidatorException("Path processing failed on policy.", null, certPath, index);
        }