/**
		* Validates an attribute certificate with the given certificate path.
		* 
		* <p>
		* <code>params</code> must be an instance of
		* <code>ExtendedPkixParameters</code>.
		* </p><p>
		* The target constraints in the <code>params</code> must be an
		* <code>X509AttrCertStoreSelector</code> with at least the attribute
		* certificate criterion set. Obey that also target informations may be
		* necessary to correctly validate this attribute certificate.
		* </p><p>
		* The attribute certificate issuer must be added to the trusted attribute
		* issuers with {@link ExtendedPkixParameters#setTrustedACIssuers(Set)}.
		* </p>
		* @param certPath The certificate path which belongs to the attribute
		*            certificate issuer public key certificate.
		* @param params The PKIX parameters.
		* @return A <code>PKIXCertPathValidatorResult</code> of the result of
		*         validating the <code>certPath</code>.
		* @throws InvalidAlgorithmParameterException if <code>params</code> is
		*             inappropriate for this validator.
		* @throws CertPathValidatorException if the verification fails.
		*/
		public virtual PkixCertPathValidatorResult Validate(
			PkixCertPath	certPath,
			PkixParameters	pkixParams)
		{
			IX509Selector certSelect = pkixParams.GetTargetConstraints();
			if (!(certSelect is X509AttrCertStoreSelector))
			{
				throw new ArgumentException(
					"TargetConstraints must be an instance of " + typeof(X509AttrCertStoreSelector).FullName,
					"pkixParams");
			}
			IX509AttributeCertificate attrCert = ((X509AttrCertStoreSelector) certSelect).AttributeCert;

			PkixCertPath holderCertPath = Rfc3281CertPathUtilities.ProcessAttrCert1(attrCert, pkixParams);
			PkixCertPathValidatorResult result = Rfc3281CertPathUtilities.ProcessAttrCert2(certPath, pkixParams);
			X509Certificate issuerCert = (X509Certificate)certPath.Certificates[0];
			Rfc3281CertPathUtilities.ProcessAttrCert3(issuerCert, pkixParams);
			Rfc3281CertPathUtilities.ProcessAttrCert4(issuerCert, pkixParams);
			Rfc3281CertPathUtilities.ProcessAttrCert5(attrCert, pkixParams);
			// 6 already done in X509AttrCertStoreSelector
			Rfc3281CertPathUtilities.ProcessAttrCert7(attrCert, certPath, holderCertPath, pkixParams);
			Rfc3281CertPathUtilities.AdditionalChecks(attrCert, pkixParams);
			DateTime date;
			try
			{
				date = PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(pkixParams, null, -1);
			}
			catch (Exception e)
			{
				throw new PkixCertPathValidatorException(
					"Could not get validity date from attribute certificate.", e);
			}
			Rfc3281CertPathUtilities.CheckCrls(attrCert, pkixParams, issuerCert, date, certPath.Certificates);
			return result;
		}
		public PkixCertPathBuilderResult(
			PkixCertPath			certPath,
			TrustAnchor				trustAnchor,
			PkixPolicyNode			policyTree,
			AsymmetricKeyParameter	subjectPublicKey)
			: base(trustAnchor, policyTree, subjectPublicKey)
		{			
			if (certPath == null)
				throw new ArgumentNullException("certPath");

			this.certPath = certPath;
		}
예제 #3
0
        public PkixCertPathBuilderResult(
            PkixCertPath certPath,
            TrustAnchor trustAnchor,
            PkixPolicyNode policyTree,
            AsymmetricKeyParameter subjectPublicKey)
            : base(trustAnchor, policyTree, subjectPublicKey)
        {
            if (certPath == null)
            {
                throw new ArgumentNullException("certPath");
            }

            this.certPath = certPath;
        }
예제 #4
0
        internal static DateTime GetValidCertDateFromValidityModel(
            PkixParameters paramsPkix,
            PkixCertPath certPath,
            int index)
        {
            if (paramsPkix.ValidityModel != PkixParameters.ChainValidityModel)
            {
                return(GetValidDate(paramsPkix));
            }

            // if end cert use given signing/encryption/... time
            if (index <= 0)
            {
                return(PkixCertPathValidatorUtilities.GetValidDate(paramsPkix));
                // else use time when previous cert was created
            }

            if (index - 1 == 0)
            {
                DerGeneralizedTime dateOfCertgen = null;
                try
                {
                    X509Certificate cert   = (X509Certificate)certPath.Certificates[index - 1];
                    Asn1OctetString extVal = cert.GetExtensionValue(
                        IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen);
                    dateOfCertgen = DerGeneralizedTime.GetInstance(extVal);
                }
                catch (ArgumentException)
                {
                    throw new Exception(
                              "Date of cert gen extension could not be read.");
                }
                if (dateOfCertgen != null)
                {
                    try
                    {
                        return(dateOfCertgen.ToDateTime());
                    }
                    catch (ArgumentException e)
                    {
                        throw new Exception(
                                  "Date from date of cert gen extension could not be parsed.",
                                  e);
                    }
                }
            }

            return(((X509Certificate)certPath.Certificates[index - 1]).NotBefore);
        }
예제 #5
0
        internal static PkixCertPathValidatorResult ProcessAttrCert2(
            PkixCertPath certPath,
            PkixParameters pkixParams)
        {
            PkixCertPathValidator validator = new PkixCertPathValidator();

            try
            {
                return(validator.Validate(certPath, pkixParams));
            }
            catch (PkixCertPathValidatorException e)
            {
                throw new PkixCertPathValidatorException(
                          "Certification path for issuer certificate of attribute certificate could not be validated.",
                          e);
            }
        }
예제 #6
0
        /**
         * Compares this certification path for equality with the specified object.
         * Two CertPaths are equal if and only if their types are equal and their
         * certificate Lists (and by implication the Certificates in those Lists)
         * are equal. A CertPath is never equal to an object that is not a CertPath.<br />
         * <br />
         * This algorithm is implemented by this method. If it is overridden, the
         * behavior specified here must be maintained.
         *
         * @param other
         *            the object to test for equality with this certification path
         *
         * @return true if the specified object is equal to this certification path,
         *         false otherwise
         *
         * @see Object#hashCode() Object.hashCode()
         */
        public override bool Equals(
            object obj)
        {
            if (this == obj)
            {
                return(true);
            }

            PkixCertPath other = obj as PkixCertPath;

            if (other == null)
            {
                return(false);
            }

//			if (!this.Type.Equals(other.Type))
//				return false;

            //return this.Certificates.Equals(other.Certificates);

            // TODO Extract this to a utility class
            IList thisCerts  = this.Certificates;
            IList otherCerts = other.Certificates;

            if (thisCerts.Count != otherCerts.Count)
            {
                return(false);
            }

            IEnumerator e1 = thisCerts.GetEnumerator();
            IEnumerator e2 = thisCerts.GetEnumerator();

            while (e1.MoveNext())
            {
                e2.MoveNext();

                if (!Platform.Equals(e1.Current, e2.Current))
                {
                    return(false);
                }
            }

            return(true);
        }
		internal static void ProcessAttrCert7(
			IX509AttributeCertificate	attrCert,
			PkixCertPath				certPath,
			PkixCertPath				holderCertPath,
			PkixParameters				pkixParams)
		{
			// TODO:
			// AA Controls
			// Attribute encryption
			// Proxy
			ISet critExtOids = attrCert.GetCriticalExtensionOids();

			// 7.1
			// process extensions

			// target information checked in step 6 / X509AttributeCertStoreSelector
			if (critExtOids.Contains(X509Extensions.TargetInformation.Id))
			{
				try
				{
					TargetInformation.GetInstance(PkixCertPathValidatorUtilities
						.GetExtensionValue(attrCert, X509Extensions.TargetInformation));
				}
				catch (Exception e)
				{
					throw new PkixCertPathValidatorException(
						"Target information extension could not be read.", e);
				}
			}
			critExtOids.Remove(X509Extensions.TargetInformation.Id);
			foreach (PkixAttrCertChecker checker in pkixParams.GetAttrCertCheckers())
			{
				checker.Check(attrCert, certPath, holderCertPath, critExtOids);
			}
			if (!critExtOids.IsEmpty)
			{
				throw new PkixCertPathValidatorException(
					"Attribute certificate contains unsupported critical extensions: "
						+ critExtOids);
			}
		}
예제 #8
0
        internal static void ProcessAttrCert7(
            IX509AttributeCertificate attrCert,
            PkixCertPath certPath,
            PkixCertPath holderCertPath,
            PkixParameters pkixParams)
        {
            // TODO:
            // AA Controls
            // Attribute encryption
            // Proxy
            ISet critExtOids = attrCert.GetCriticalExtensionOids();

            // 7.1
            // process extensions

            // target information checked in step 6 / X509AttributeCertStoreSelector
            if (critExtOids.Contains(X509Extensions.TargetInformation.Id))
            {
                try
                {
                    TargetInformation.GetInstance(PkixCertPathValidatorUtilities
                                                  .GetExtensionValue(attrCert, X509Extensions.TargetInformation));
                }
                catch (Exception e)
                {
                    throw new PkixCertPathValidatorException(
                              "Target information extension could not be read.", e);
                }
            }
            critExtOids.Remove(X509Extensions.TargetInformation.Id);
            foreach (PkixAttrCertChecker checker in pkixParams.GetAttrCertCheckers())
            {
                checker.Check(attrCert, certPath, holderCertPath, critExtOids);
            }
            if (!critExtOids.IsEmpty)
            {
                throw new PkixCertPathValidatorException(
                          "Attribute certificate contains unsupported critical extensions: "
                          + critExtOids);
            }
        }
        /**
         * Validates an attribute certificate with the given certificate path.
         *
         * <p>
         * <code>params</code> must be an instance of
         * <code>ExtendedPkixParameters</code>.
         * </p><p>
         * The target constraints in the <code>params</code> must be an
         * <code>X509AttrCertStoreSelector</code> with at least the attribute
         * certificate criterion set. Obey that also target informations may be
         * necessary to correctly validate this attribute certificate.
         * </p><p>
         * The attribute certificate issuer must be added to the trusted attribute
         * issuers with {@link ExtendedPkixParameters#setTrustedACIssuers(Set)}.
         * </p>
         * @param certPath The certificate path which belongs to the attribute
         *            certificate issuer public key certificate.
         * @param params The PKIX parameters.
         * @return A <code>PKIXCertPathValidatorResult</code> of the result of
         *         validating the <code>certPath</code>.
         * @throws InvalidAlgorithmParameterException if <code>params</code> is
         *             inappropriate for this validator.
         * @throws CertPathValidatorException if the verification fails.
         */
        public virtual PkixCertPathValidatorResult Validate(
            PkixCertPath certPath,
            PkixParameters pkixParams)
        {
            IX509Selector certSelect = pkixParams.GetTargetConstraints();

            if (!(certSelect is X509AttrCertStoreSelector))
            {
                throw new ArgumentException(
                          "TargetConstraints must be an instance of " + typeof(X509AttrCertStoreSelector).FullName,
                          "pkixParams");
            }
            IX509AttributeCertificate attrCert = ((X509AttrCertStoreSelector)certSelect).AttributeCert;

            PkixCertPath holderCertPath            = Rfc3281CertPathUtilities.ProcessAttrCert1(attrCert, pkixParams);
            PkixCertPathValidatorResult result     = Rfc3281CertPathUtilities.ProcessAttrCert2(certPath, pkixParams);
            X509Certificate             issuerCert = (X509Certificate)certPath.Certificates[0];

            Rfc3281CertPathUtilities.ProcessAttrCert3(issuerCert, pkixParams);
            Rfc3281CertPathUtilities.ProcessAttrCert4(issuerCert, pkixParams);
            Rfc3281CertPathUtilities.ProcessAttrCert5(attrCert, pkixParams);
            // 6 already done in X509AttrCertStoreSelector
            Rfc3281CertPathUtilities.ProcessAttrCert7(attrCert, certPath, holderCertPath, pkixParams);
            Rfc3281CertPathUtilities.AdditionalChecks(attrCert, pkixParams);
            DateTime date;

            try
            {
                date = PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(pkixParams, null, -1);
            }
            catch (Exception e)
            {
                throw new PkixCertPathValidatorException(
                          "Could not get validity date from attribute certificate.", e);
            }
            Rfc3281CertPathUtilities.CheckCrls(attrCert, pkixParams, issuerCert, date, certPath.Certificates);
            return(result);
        }
		/// <summary>
		/// Creates a <code>PkixCertPathValidatorException</code> with the specified
		/// detail message, cause, certification path, and index.
		/// </summary>
		/// <param name="message">the detail message (or <code>null</code> if none)</param>
		/// <param name="cause">the cause (or <code>null</code> if none)</param>
		/// <param name="certPath">the certification path that was in the process of being
		/// validated when the error was encountered</param>
		/// <param name="index">the index of the certificate in the certification path that</param>																																																																																   * 
		public PkixCertPathValidatorException(
			string			message,
			Exception		cause,
			PkixCertPath	certPath,
			int				index)
			: base(message)
		{
			if (certPath == null && index != -1)
			{
				throw new ArgumentNullException(
					"certPath = null and index != -1");
			}
			if (index < -1
				|| (certPath != null && index >= certPath.Certificates.Count))
			{
				throw new IndexOutOfRangeException(
					" index < -1 or out of bound of certPath.getCertificates()");
			}

			this.cause = cause;
			this.certPath = certPath;
			this.index = index;
		}
        /// <summary>
        /// Creates a <code>PkixCertPathValidatorException</code> with the specified
        /// detail message, cause, certification path, and index.
        /// </summary>
        /// <param name="message">the detail message (or <code>null</code> if none)</param>
        /// <param name="cause">the cause (or <code>null</code> if none)</param>
        /// <param name="certPath">the certification path that was in the process of being
        /// validated when the error was encountered</param>
        /// <param name="index">the index of the certificate in the certification path that</param>																																																																																   *
        public PkixCertPathValidatorException(
            string message,
            Exception cause,
            PkixCertPath certPath,
            int index)
            : base(message)
        {
            if (certPath == null && index != -1)
            {
                throw new ArgumentNullException(
                          "certPath = null and index != -1");
            }
            if (index < -1 ||
                (certPath != null && index >= certPath.Certificates.Count))
            {
                throw new IndexOutOfRangeException(
                          " index < -1 or out of bound of certPath.getCertificates()");
            }

            this.cause    = cause;
            this.certPath = certPath;
            this.index    = index;
        }
        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.ObjectID;
//			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.ObjectID;
                    // (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);
        }
		private PkixCertPathBuilderResult Build(
			IX509AttributeCertificate	attrCert,
			X509Certificate				tbvCert,
			PkixBuilderParameters		pkixParams,
			IList						tbvPath)
		{
			// If tbvCert is readily present in tbvPath, it indicates having run
			// into a cycle in the
			// PKI graph.
			if (tbvPath.Contains(tbvCert))
				return null;

			// step out, the certificate is not allowed to appear in a certification
			// chain
			if (pkixParams.GetExcludedCerts().Contains(tbvCert))
				return null;

			// test if certificate path exceeds maximum length
			if (pkixParams.MaxPathLength != -1)
			{
				if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
					return null;
			}

			tbvPath.Add(tbvCert);

			PkixCertPathBuilderResult builderResult = null;

//			X509CertificateParser certParser = new X509CertificateParser();
			PkixAttrCertPathValidator validator = new PkixAttrCertPathValidator();

			try
			{
				// check whether the issuer of <tbvCert> is a TrustAnchor
				if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
				{
					PkixCertPath certPath = new PkixCertPath(tbvPath);
					PkixCertPathValidatorResult result;

					try
					{
						result = validator.Validate(certPath, pkixParams);
					}
					catch (Exception e)
					{
						throw new Exception("Certification path could not be validated.", e);
					}

					return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
						result.PolicyTree, result.SubjectPublicKey);
				}
				else
				{
					// add additional X.509 stores from locations in certificate
					try
					{
						PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams);
					}
					catch (CertificateParsingException e)
					{
						throw new Exception("No additional X.509 stores can be added from certificate locations.", e);
					}

					// try to get the issuer certificate from one of the stores
					ISet issuers = new HashSet();
					try
					{
						issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
					}
					catch (Exception e)
					{
						throw new Exception("Cannot find issuer certificate for certificate in certification path.", e);
					}

					if (issuers.IsEmpty)
						throw new Exception("No issuer certificate for certificate in certification path found.");

					foreach (X509Certificate issuer in issuers)
					{
						// if untrusted self signed certificate continue
						if (PkixCertPathValidatorUtilities.IsSelfIssued(issuer))
							continue;

						builderResult = Build(attrCert, issuer, pkixParams, tbvPath);

						if (builderResult != null)
							break;
					}
				}
			}
			catch (Exception e)
			{
				certPathException = new Exception("No valid certification path could be build.", e);
			}

			if (builderResult == null)
			{
				tbvPath.Remove(tbvCert);
			}

			return builderResult;
		}
		internal static DateTime GetValidCertDateFromValidityModel(
			PkixParameters	paramsPkix,
			PkixCertPath	certPath,
			int				index)
		{
			if (paramsPkix.ValidityModel != PkixParameters.ChainValidityModel)
			{
				return GetValidDate(paramsPkix);
			}

			// if end cert use given signing/encryption/... time
			if (index <= 0)
			{
				return PkixCertPathValidatorUtilities.GetValidDate(paramsPkix);
				// else use time when previous cert was created
			}

			if (index - 1 == 0)
			{
				DerGeneralizedTime dateOfCertgen = null;
				try
				{
					X509Certificate cert = (X509Certificate)certPath.Certificates[index - 1];
					Asn1OctetString extVal = cert.GetExtensionValue(
						IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen);
					dateOfCertgen = DerGeneralizedTime.GetInstance(extVal);
				}
				catch (ArgumentException)
				{
					throw new Exception(
						"Date of cert gen extension could not be read.");
				}
				if (dateOfCertgen != null)
				{
					try
					{
						return dateOfCertgen.ToDateTime();
					}
					catch (ArgumentException e)
					{
						throw new Exception(
							"Date from date of cert gen extension could not be parsed.",
							e);
					}
				}
			}

			return ((X509Certificate)certPath.Certificates[index - 1]).NotBefore;
		}
		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 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);
				}

				IList emails = X509Name.GetInstance(dns).GetValueList(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 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 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 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 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 PkixCertPathValidatorResult ProcessAttrCert2(
			PkixCertPath	certPath,
			PkixParameters	pkixParams)
		{
			PkixCertPathValidator validator = new PkixCertPathValidator();

			try
			{
				return validator.Validate(certPath, pkixParams);
			}
			catch (PkixCertPathValidatorException e)
			{
				throw new PkixCertPathValidatorException(
					"Certification path for issuer certificate of attribute certificate could not be validated.",
					e);
			}
		}
		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 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 = Platform.CreateHashtable();
				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(Platform.CreateArrayList(), 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)
					{
                        foreach (PkixPolicyNode node in Platform.CreateArrayList(policyNodes[i]))
                        {
							if (node.ValidPolicy.Equals(id_p))
							{
								node.Parent.RemoveChild(node);

                                for (int k = i - 1; k >= 0; k--)
								{
                                    foreach (PkixPolicyNode node2 in Platform.CreateArrayList(policyNodes[k]))
									{
										if (!node2.HasChildren)
										{
											_validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(
												_validPolicyTree, policyNodes, node2);

                                            if (_validPolicyTree == null)
												break;
										}
									}
								}
							}
						}
					}
				}
			}
			return _validPolicyTree;
		}
		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 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 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 not 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, false).Value.IntValue;
							}
							catch (Exception e)
							{
								throw new PkixCertPathValidatorException(
									"Policy constraints requireExplicitPolicy field could not be decoded.", e, certPath,
									index);
							}
							if (tmpInt == 0)
							{
								return 0;
							}
							break;
					}
				}
			}
			return explicitPolicy;
		}
		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 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;
		}
		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, false).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 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 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 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(Platform.CreateArrayList(), 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;
		}
		/**
		* Performs checks on the specified attribute certificate. Every handled
		* extension is rmeoved from the <code>unresolvedCritExts</code>
		* collection.
		* 
		* @param attrCert The attribute certificate to be checked.
		* @param certPath The certificate path which belongs to the attribute
		*            certificate issuer public key certificate.
		* @param holderCertPath The certificate path which belongs to the holder
		*            certificate.
		* @param unresolvedCritExts a <code>Collection</code> of OID strings
		*            representing the current set of unresolved critical extensions
		* @throws CertPathValidatorException if the specified attribute certificate
		*             does not pass the check.
		*/
		public abstract void Check(IX509AttributeCertificate attrCert, PkixCertPath certPath,
			PkixCertPath holderCertPath, ICollection unresolvedCritExts);
예제 #34
0
        private PkixCertPathBuilderResult Build(
            IX509AttributeCertificate attrCert,
            X509Certificate tbvCert,
            PkixBuilderParameters pkixParams,
            IList tbvPath)
        {
            // If tbvCert is readily present in tbvPath, it indicates having run
            // into a cycle in the
            // PKI graph.
            if (tbvPath.Contains(tbvCert))
            {
                return(null);
            }

            // step out, the certificate is not allowed to appear in a certification
            // chain
            if (pkixParams.GetExcludedCerts().Contains(tbvCert))
            {
                return(null);
            }

            // test if certificate path exceeds maximum length
            if (pkixParams.MaxPathLength != -1)
            {
                if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
                {
                    return(null);
                }
            }

            tbvPath.Add(tbvCert);

            PkixCertPathBuilderResult builderResult = null;

//			X509CertificateParser certParser = new X509CertificateParser();
            PkixAttrCertPathValidator validator = new PkixAttrCertPathValidator();

            try
            {
                // check whether the issuer of <tbvCert> is a TrustAnchor
                if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
                {
                    PkixCertPath certPath = new PkixCertPath(tbvPath);
                    PkixCertPathValidatorResult result;

                    try
                    {
                        result = validator.Validate(certPath, pkixParams);
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Certification path could not be validated.", e);
                    }

                    return(new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
                                                         result.PolicyTree, result.SubjectPublicKey));
                }
                else
                {
                    // add additional X.509 stores from locations in certificate
                    try
                    {
                        PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams);
                    }
                    catch (CertificateParsingException e)
                    {
                        throw new Exception("No additional X.509 stores can be added from certificate locations.", e);
                    }

                    // try to get the issuer certificate from one of the stores
                    ISet issuers = new HashSet();
                    try
                    {
                        issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
                    }
                    catch (Exception e)
                    {
                        throw new Exception("Cannot find issuer certificate for certificate in certification path.", e);
                    }

                    if (issuers.IsEmpty)
                    {
                        throw new Exception("No issuer certificate for certificate in certification path found.");
                    }

                    foreach (X509Certificate issuer in issuers)
                    {
                        // if untrusted self signed certificate continue
                        if (PkixCertPathValidatorUtilities.IsSelfIssued(issuer))
                        {
                            continue;
                        }

                        builderResult = Build(attrCert, issuer, pkixParams, tbvPath);

                        if (builderResult != null)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                certPathException = new Exception("No valid certification path could be build.", e);
            }

            if (builderResult == null)
            {
                tbvPath.Remove(tbvCert);
            }

            return(builderResult);
        }
예제 #35
0
 /**
  * Performs checks on the specified attribute certificate. Every handled
  * extension is rmeoved from the <code>unresolvedCritExts</code>
  * collection.
  *
  * @param attrCert The attribute certificate to be checked.
  * @param certPath The certificate path which belongs to the attribute
  *            certificate issuer public key certificate.
  * @param holderCertPath The certificate path which belongs to the holder
  *            certificate.
  * @param unresolvedCritExts a <code>Collection</code> of OID strings
  *            representing the current set of unresolved critical extensions
  * @throws CertPathValidatorException if the specified attribute certificate
  *             does not pass the check.
  */
 public abstract void Check(IX509AttributeCertificate attrCert, PkixCertPath certPath,
                            PkixCertPath holderCertPath, ICollection unresolvedCritExts);
		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 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;
		}
예제 #38
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.ObjectID;
//			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.ObjectID;
                    // (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);
        }
		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");
			}
		}