summary refs log tree commit diff
path: root/Crypto/src/pkix/PkixCertPathValidatorUtilities.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/pkix/PkixCertPathValidatorUtilities.cs')
-rw-r--r--Crypto/src/pkix/PkixCertPathValidatorUtilities.cs1194
1 files changed, 1194 insertions, 0 deletions
diff --git a/Crypto/src/pkix/PkixCertPathValidatorUtilities.cs b/Crypto/src/pkix/PkixCertPathValidatorUtilities.cs
new file mode 100644
index 000000000..305b2de35
--- /dev/null
+++ b/Crypto/src/pkix/PkixCertPathValidatorUtilities.cs
@@ -0,0 +1,1194 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.IsisMtt;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// Summary description for PkixCertPathValidatorUtilities.
+	/// </summary>
+	public class PkixCertPathValidatorUtilities
+	{
+		private static readonly PkixCrlUtilities CrlUtilities = new PkixCrlUtilities();
+
+		internal static readonly string ANY_POLICY = "2.5.29.32.0";
+
+		internal static readonly string CRL_NUMBER = X509Extensions.CrlNumber.Id;
+
+		/// <summary>
+		/// key usage bits
+		/// </summary>
+		internal static readonly int KEY_CERT_SIGN = 5;
+		internal static readonly int CRL_SIGN = 6;
+
+		internal static readonly string[] crlReasons = new string[]
+		{
+			"unspecified",
+			"keyCompromise",
+			"cACompromise",
+			"affiliationChanged",
+			"superseded",
+			"cessationOfOperation",
+			"certificateHold",
+			"unknown",
+			"removeFromCRL",
+			"privilegeWithdrawn",
+			"aACompromise"
+		};
+
+		/// <summary>
+		/// Search the given Set of TrustAnchor's for one that is the
+		/// issuer of the given X509 certificate.
+		/// </summary>
+		/// <param name="cert">the X509 certificate</param>
+		/// <param name="trustAnchors">a Set of TrustAnchor's</param>
+		/// <returns>the <code>TrustAnchor</code> object if found or
+		/// <code>null</code> if not.
+		/// </returns>
+		/// @exception
+		internal static TrustAnchor FindTrustAnchor(
+			X509Certificate	cert,
+			ISet			trustAnchors)
+		{
+			IEnumerator iter = trustAnchors.GetEnumerator();
+			TrustAnchor trust = null;
+			AsymmetricKeyParameter trustPublicKey = null;
+			Exception invalidKeyEx = null;
+
+			X509CertStoreSelector certSelectX509 = new X509CertStoreSelector();
+
+			try
+			{
+				certSelectX509.Subject = GetIssuerPrincipal(cert);
+			}
+			catch (IOException ex)
+			{
+				throw new Exception("Cannot set subject search criteria for trust anchor.", ex);
+			}
+
+			while (iter.MoveNext() && trust == null)
+			{
+				trust = (TrustAnchor) iter.Current;
+				if (trust.TrustedCert != null)
+				{
+					if (certSelectX509.Match(trust.TrustedCert))
+					{
+						trustPublicKey = trust.TrustedCert.GetPublicKey();
+					}
+					else
+					{
+						trust = null;
+					}
+				}
+				else if (trust.CAName != null && trust.CAPublicKey != null)
+				{
+					try
+					{
+						X509Name certIssuer = GetIssuerPrincipal(cert);
+						X509Name caName = new X509Name(trust.CAName);
+
+						if (certIssuer.Equivalent(caName, true))
+						{
+							trustPublicKey = trust.CAPublicKey;
+						}
+						else
+						{
+							trust = null;
+						}
+					}
+					catch (InvalidParameterException)
+					{
+						trust = null;
+					}
+				}
+				else
+				{
+					trust = null;
+				}
+
+				if (trustPublicKey != null)
+				{
+					try
+					{
+						cert.Verify(trustPublicKey);
+					}
+					catch (Exception ex)
+					{
+						invalidKeyEx = ex;
+						trust = null;
+					}
+				}
+			}
+
+			if (trust == null && invalidKeyEx != null)
+			{
+				throw new Exception("TrustAnchor found but certificate validation failed.", invalidKeyEx);
+			}
+
+			return trust;
+		}
+
+		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 DateTime GetValidDate(PkixParameters paramsPKIX)
+		{
+			DateTimeObject validDate = paramsPKIX.Date;
+
+			if (validDate == null)
+				return DateTime.UtcNow;
+
+			return validDate.Value;
+		}
+
+		/// <summary>
+		/// Returns the issuer of an attribute certificate or certificate.
+		/// </summary>
+		/// <param name="cert">The attribute certificate or certificate.</param>
+		/// <returns>The issuer as <code>X500Principal</code>.</returns>
+		internal static X509Name GetIssuerPrincipal(
+			object cert)
+		{
+			if (cert is X509Certificate)
+			{
+				return ((X509Certificate)cert).IssuerDN;
+			}
+			else
+			{
+				return ((IX509AttributeCertificate)cert).Issuer.GetPrincipals()[0];
+			}
+		}
+
+		internal static bool IsSelfIssued(
+			X509Certificate cert)
+		{
+			return cert.SubjectDN.Equivalent(cert.IssuerDN, true);
+		}
+
+		internal static AlgorithmIdentifier GetAlgorithmIdentifier(
+			AsymmetricKeyParameter key)
+		{
+			try
+			{
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
+
+				return info.AlgorithmID;
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException("Subject public key cannot be decoded.", e);
+			}
+		}
+
+		internal static bool IsAnyPolicy(
+			ISet policySet)
+		{
+			return policySet == null || policySet.Contains(ANY_POLICY) || policySet.Count == 0;
+		}
+
+		internal static void AddAdditionalStoreFromLocation(
+			string			location,
+			PkixParameters	pkixParams)
+		{
+			if (pkixParams.IsAdditionalLocationsEnabled)
+			{
+				try
+				{
+					if (location.StartsWith("ldap://"))
+					{
+						// ldap://directory.d-trust.net/CN=D-TRUST
+						// Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE
+						// skip "ldap://"
+						location = location.Substring(7);
+						// after first / baseDN starts
+						string url;//, baseDN;
+						int slashPos = location.IndexOf('/');
+						if (slashPos != -1)
+						{
+							url = "ldap://" + location.Substring(0, slashPos);
+//							baseDN = location.Substring(slashPos);
+						}
+						else
+						{
+							url = "ldap://" + location;
+//							baseDN = nsull;
+						}
+
+						throw Platform.CreateNotImplementedException("LDAP cert/CRL stores");
+
+						// use all purpose parameters
+						//X509LDAPCertStoreParameters ldapParams = new X509LDAPCertStoreParameters.Builder(
+						//                                url, baseDN).build();
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "CERTIFICATE/LDAP", ldapParams));
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "CRL/LDAP", ldapParams));
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "ATTRIBUTECERTIFICATE/LDAP", ldapParams));
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "CERTIFICATEPAIR/LDAP", ldapParams));
+					}
+				}
+				catch (Exception)
+				{
+					// cannot happen
+					throw new Exception("Exception adding X.509 stores.");
+				}
+			}
+		}
+
+		private static BigInteger GetSerialNumber(
+			object cert)
+		{
+			if (cert is X509Certificate)
+			{
+				return ((X509Certificate)cert).SerialNumber;
+			}
+			else
+			{
+				return ((X509V2AttributeCertificate)cert).SerialNumber;
+			}
+		}
+
+		//
+		// policy checking
+		//
+
+		internal static ISet GetQualifierSet(Asn1Sequence qualifiers)
+		{
+			ISet pq = new HashSet();
+
+			if (qualifiers == null)
+			{
+				return pq;
+			}
+
+			foreach (Asn1Encodable ae in qualifiers)
+			{
+				try
+				{
+//					pq.Add(PolicyQualifierInfo.GetInstance(Asn1Object.FromByteArray(ae.GetEncoded())));
+					pq.Add(PolicyQualifierInfo.GetInstance(ae.ToAsn1Object()));
+				}
+				catch (IOException ex)
+				{
+					throw new PkixCertPathValidatorException("Policy qualifier info cannot be decoded.", ex);
+				}
+			}
+
+			return pq;
+		}
+
+		internal static PkixPolicyNode RemovePolicyNode(
+			PkixPolicyNode validPolicyTree,
+			IList[] policyNodes,
+			PkixPolicyNode _node)
+		{
+			PkixPolicyNode _parent = (PkixPolicyNode)_node.Parent;
+
+			if (validPolicyTree == null)
+			{
+				return null;
+			}
+
+			if (_parent == null)
+			{
+				for (int j = 0; j < policyNodes.Length; j++)
+				{
+                    policyNodes[j] = Platform.CreateArrayList();
+				}
+
+				return null;
+			}
+			else
+			{
+				_parent.RemoveChild(_node);
+				RemovePolicyNodeRecurse(policyNodes, _node);
+
+				return validPolicyTree;
+			}
+		}
+
+		private static void RemovePolicyNodeRecurse(IList[] policyNodes, PkixPolicyNode _node)
+		{
+			policyNodes[_node.Depth].Remove(_node);
+
+			if (_node.HasChildren)
+			{
+				foreach (PkixPolicyNode _child in _node.Children)
+				{
+					RemovePolicyNodeRecurse(policyNodes, _child);
+				}
+			}
+		}
+
+		internal static void PrepareNextCertB1(
+			int i,
+			IList[] policyNodes,
+			string id_p,
+			IDictionary m_idp,
+			X509Certificate cert)
+		{
+			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 (ANY_POLICY.Equals(node.ValidPolicy))
+					{
+						ISet pq = null;
+						Asn1Sequence policies = null;
+						try
+						{
+							policies = DerSequence.GetInstance(GetExtensionValue(cert, X509Extensions.CertificatePolicies));
+						}
+						catch (Exception e)
+						{
+							throw new Exception("Certificate policies cannot be decoded.", e);
+						}
+
+						IEnumerator enm = policies.GetEnumerator();
+						while (enm.MoveNext())
+						{
+							PolicyInformation pinfo = null;
+
+							try
+							{
+								pinfo = PolicyInformation.GetInstance(enm.Current);
+							}
+							catch (Exception ex)
+							{
+								throw new Exception("Policy information cannot be decoded.", ex);
+							}
+
+							if (ANY_POLICY.Equals(pinfo.PolicyIdentifier.Id))
+							{
+								try
+								{
+									pq = GetQualifierSet(pinfo.PolicyQualifiers);
+								}
+								catch (PkixCertPathValidatorException ex)
+								{
+									throw new PkixCertPathValidatorException(
+										"Policy qualifier info set could not be built.", ex);
+								}
+								break;
+							}
+						}
+						bool ci = false;
+						ISet critExtOids = cert.GetCriticalExtensionOids();
+						if (critExtOids != null)
+						{
+							ci = critExtOids.Contains(X509Extensions.CertificatePolicies.Id);
+						}
+
+						PkixPolicyNode p_node = (PkixPolicyNode)node.Parent;
+						if (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;
+					}
+				}
+			}
+		}
+
+		internal static PkixPolicyNode PrepareNextCertB2(
+			int				i,
+			IList[]			policyNodes,
+			string			id_p,
+			PkixPolicyNode	validPolicyTree)
+		{
+			int pos = 0;
+
+			// Copy to avoid RemoveAt calls interfering with enumeration
+            foreach (PkixPolicyNode node in Platform.CreateArrayList(policyNodes[i]))
+			{
+				if (node.ValidPolicy.Equals(id_p))
+				{
+					PkixPolicyNode p_node = (PkixPolicyNode)node.Parent;
+					p_node.RemoveChild(node);
+
+					// Removal of element at current iterator position not supported in C#
+					//nodes_i.remove();
+					policyNodes[i].RemoveAt(pos);
+
+					for (int k = (i - 1); k >= 0; k--)
+					{
+						IList nodes = policyNodes[k];
+						for (int l = 0; l < nodes.Count; l++)
+						{
+							PkixPolicyNode node2 = (PkixPolicyNode)nodes[l];
+							if (!node2.HasChildren)
+							{
+								validPolicyTree = RemovePolicyNode(validPolicyTree, policyNodes, node2);
+								if (validPolicyTree == null)
+									break;
+							}
+						}
+					}
+				}
+				else
+				{
+					++pos;
+				}
+			}
+			return validPolicyTree;
+		}
+
+		internal static void GetCertStatus(
+			DateTime validDate,
+			X509Crl crl,
+			Object cert,
+			CertStatus certStatus)
+		{
+			X509Crl bcCRL = null;
+
+			try
+			{
+				bcCRL = new X509Crl(CertificateList.GetInstance((Asn1Sequence)Asn1Sequence.FromByteArray(crl.GetEncoded())));
+			}
+			catch (Exception exception)
+			{
+				throw new Exception("Bouncy Castle X509Crl could not be created.", exception);
+			}
+
+			X509CrlEntry crl_entry = (X509CrlEntry)bcCRL.GetRevokedCertificate(GetSerialNumber(cert));
+
+			if (crl_entry == null)
+				return;
+
+			X509Name issuer = GetIssuerPrincipal(cert);
+
+			if (issuer.Equivalent(crl_entry.GetCertificateIssuer(), true)
+				|| issuer.Equivalent(crl.IssuerDN, true))
+			{
+				DerEnumerated reasonCode = null;
+				if (crl_entry.HasExtensions)
+				{
+					try
+					{
+						reasonCode = DerEnumerated.GetInstance(
+							GetExtensionValue(crl_entry, X509Extensions.ReasonCode));
+					}
+					catch (Exception e)
+					{
+						new Exception(
+							"Reason code CRL entry extension could not be decoded.",
+							e);
+					}
+				}
+
+				// for reason keyCompromise, caCompromise, aACompromise or
+				// unspecified
+				if (!(validDate.Ticks < crl_entry.RevocationDate.Ticks)
+					|| reasonCode == null
+					|| reasonCode.Value.TestBit(0)
+					|| reasonCode.Value.TestBit(1)
+					|| reasonCode.Value.TestBit(2)
+					|| reasonCode.Value.TestBit(8))
+				{
+					if (reasonCode != null) // (i) or (j) (1)
+					{
+						certStatus.Status = reasonCode.Value.SignValue;
+					}
+					else // (i) or (j) (2)
+					{
+						certStatus.Status = CrlReason.Unspecified;
+					}
+					certStatus.RevocationDate = new DateTimeObject(crl_entry.RevocationDate);
+				}
+			}
+		}
+
+		/**
+		* Return the next working key inheriting DSA parameters if necessary.
+		* <p>
+		* This methods inherits DSA parameters from the indexed certificate or
+		* previous certificates in the certificate chain to the returned
+		* <code>PublicKey</code>. The list is searched upwards, meaning the end
+		* certificate is at position 0 and previous certificates are following.
+		* </p>
+		* <p>
+		* If the indexed certificate does not contain a DSA key this method simply
+		* returns the public key. If the DSA key already contains DSA parameters
+		* the key is also only returned.
+		* </p>
+		*
+		* @param certs The certification path.
+		* @param index The index of the certificate which contains the public key
+		*            which should be extended with DSA parameters.
+		* @return The public key of the certificate in list position
+		*         <code>index</code> extended with DSA parameters if applicable.
+		* @throws Exception if DSA parameters cannot be inherited.
+		*/
+		internal static AsymmetricKeyParameter GetNextWorkingKey(
+			IList	certs,
+			int		index)
+		{
+			//Only X509Certificate
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			AsymmetricKeyParameter pubKey = cert.GetPublicKey();
+
+			if (!(pubKey is DsaPublicKeyParameters))
+				return pubKey;
+
+			DsaPublicKeyParameters dsaPubKey = (DsaPublicKeyParameters)pubKey;
+
+			if (dsaPubKey.Parameters != null)
+				return dsaPubKey;
+
+			for (int i = index + 1; i < certs.Count; i++)
+			{
+				X509Certificate parentCert = (X509Certificate)certs[i];
+				pubKey = parentCert.GetPublicKey();
+
+				if (!(pubKey is DsaPublicKeyParameters))
+				{
+					throw new PkixCertPathValidatorException(
+						"DSA parameters cannot be inherited from previous certificate.");
+				}
+
+				DsaPublicKeyParameters prevDSAPubKey = (DsaPublicKeyParameters)pubKey;
+
+				if (prevDSAPubKey.Parameters == null)
+					continue;
+
+				DsaParameters dsaParams = prevDSAPubKey.Parameters;
+
+				try
+				{
+					return new DsaPublicKeyParameters(dsaPubKey.Y, dsaParams);
+				}
+				catch (Exception exception)
+				{
+					throw new Exception(exception.Message);
+				}
+			}
+
+			throw new PkixCertPathValidatorException("DSA parameters cannot be inherited from previous certificate.");
+		}
+
+		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;
+		}
+
+		/// <summary>
+		/// Return a Collection of all certificates or attribute certificates found
+		/// in the X509Store's that are matching the certSelect criteriums.
+		/// </summary>
+		/// <param name="certSelect">a {@link Selector} object that will be used to select
+		/// the certificates</param>
+		/// <param name="certStores">a List containing only X509Store objects. These
+		/// are used to search for certificates.</param>
+		/// <returns>a Collection of all found <see cref="X509Certificate "/> or
+		/// org.bouncycastle.x509.X509AttributeCertificate objects.
+		/// May be empty but never <code>null</code>.</returns>
+		/// <exception cref="Exception"></exception>
+		internal static ICollection FindCertificates(
+			X509CertStoreSelector	certSelect,
+			IList					certStores)
+		{
+			ISet certs = new HashSet();
+
+			foreach (IX509Store certStore in certStores)
+			{
+				try
+				{
+//					certs.AddAll(certStore.GetMatches(certSelect));
+					foreach (X509Certificate c in certStore.GetMatches(certSelect))
+					{
+						certs.Add(c);
+					}
+				}
+				catch (Exception e)
+				{
+					throw new Exception("Problem while picking certificates from X.509 store.", e);
+				}
+			}
+
+			return certs;
+		}
+
+		/**
+		* 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;
+		}
+
+		/**
+		 * Fetches complete CRLs according to RFC 3280.
+		 *
+		 * @param dp The distribution point for which the complete CRL
+		 * @param cert The <code>X509Certificate</code> or
+		 *            {@link org.bouncycastle.x509.X509AttributeCertificate} for
+		 *            which the CRL should be searched.
+		 * @param currentDate The date for which the delta CRLs must be valid.
+		 * @param paramsPKIX The extended PKIX parameters.
+		 * @return A <code>Set</code> of <code>X509CRL</code>s with complete
+		 *         CRLs.
+		 * @throws Exception if an exception occurs while picking the CRLs
+		 *             or no CRLs are found.
+		 */
+		internal static ISet GetCompleteCrls(
+			DistributionPoint	dp,
+			object				cert,
+			DateTime			currentDate,
+			PkixParameters		paramsPKIX)
+		{
+			X509CrlStoreSelector crlselect = new X509CrlStoreSelector();
+			try
+			{
+				ISet issuers = new HashSet();
+				if (cert is X509V2AttributeCertificate)
+				{
+					issuers.Add(((X509V2AttributeCertificate)cert)
+						.Issuer.GetPrincipals()[0]);
+				}
+				else
+				{
+					issuers.Add(GetIssuerPrincipal(cert));
+				}
+				PkixCertPathValidatorUtilities.GetCrlIssuersFromDistributionPoint(dp, issuers, crlselect, paramsPKIX);
+			}
+			catch (Exception e)
+			{
+				new Exception("Could not get issuer information from distribution point.", e);
+			}
+
+			if (cert is X509Certificate)
+			{
+				crlselect.CertificateChecking = (X509Certificate)cert;
+			}
+			else if (cert is X509V2AttributeCertificate)
+			{
+				crlselect.AttrCertChecking = (IX509AttributeCertificate)cert;
+			}
+
+			crlselect.CompleteCrlEnabled = true;
+			ISet crls = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate);
+
+			if (crls.IsEmpty)
+			{
+				if (cert is IX509AttributeCertificate)
+				{
+					IX509AttributeCertificate aCert = (IX509AttributeCertificate)cert;
+
+					throw new Exception("No CRLs found for issuer \"" + aCert.Issuer.GetPrincipals()[0] + "\"");
+				}
+				else
+				{
+					X509Certificate xCert = (X509Certificate)cert;
+
+					throw new Exception("No CRLs found for issuer \"" + xCert.IssuerDN + "\"");
+				}
+			}
+
+			return crls;
+		}
+
+		/**
+		 * 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)
+			{
+				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;
+		}
+
+		private static bool isDeltaCrl(
+			X509Crl crl)
+		{
+			ISet critical = crl.GetCriticalExtensionOids();
+
+			return critical.Contains(X509Extensions.DeltaCrlIndicator.Id);
+		}
+
+		internal static ICollection FindCertificates(
+			X509AttrCertStoreSelector	certSelect,
+			IList						certStores)
+		{
+			ISet certs = new HashSet();
+
+			foreach (IX509Store certStore in certStores)
+			{
+				try
+				{
+//					certs.AddAll(certStore.GetMatches(certSelect));
+					foreach (X509V2AttributeCertificate ac in certStore.GetMatches(certSelect))
+					{
+						certs.Add(ac);
+					}
+				}
+				catch (Exception e)
+				{
+					throw new Exception(
+						"Problem while picking certificates from X.509 store.", e);
+				}
+			}
+
+			return certs;
+		}
+
+		internal static void AddAdditionalStoresFromCrlDistributionPoint(
+			CrlDistPoint	crldp,
+			PkixParameters	pkixParams)
+		{
+			if (crldp != null)
+			{
+				DistributionPoint[] dps = null;
+				try
+				{
+					dps = crldp.GetDistributionPoints();
+				}
+				catch (Exception e)
+				{
+					throw new Exception(
+						"Distribution points could not be read.", e);
+				}
+				for (int i = 0; i < dps.Length; i++)
+				{
+					DistributionPointName dpn = dps[i].DistributionPointName;
+					// look for URIs in fullName
+					if (dpn != null)
+					{
+						if (dpn.PointType == DistributionPointName.FullName)
+						{
+							GeneralName[] genNames = GeneralNames.GetInstance(
+								dpn.Name).GetNames();
+							// look for an URI
+							for (int j = 0; j < genNames.Length; j++)
+							{
+								if (genNames[j].TagNo == GeneralName.UniformResourceIdentifier)
+								{
+									string location = DerIA5String.GetInstance(
+										genNames[j].Name).GetString();
+									PkixCertPathValidatorUtilities.AddAdditionalStoreFromLocation(
+										location, pkixParams);
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+
+		internal static bool ProcessCertD1i(
+			int					index,
+			IList[]				policyNodes,
+			DerObjectIdentifier	pOid,
+			ISet				pq)
+		{
+			IList policyNodeVec = policyNodes[index - 1];
+
+			for (int j = 0; j < policyNodeVec.Count; j++)
+			{
+				PkixPolicyNode node = (PkixPolicyNode)policyNodeVec[j];
+				ISet expectedPolicies = node.ExpectedPolicies;
+
+				if (expectedPolicies.Contains(pOid.Id))
+				{
+					ISet childExpectedPolicies = new HashSet();
+					childExpectedPolicies.Add(pOid.Id);
+
+                    PkixPolicyNode child = new PkixPolicyNode(Platform.CreateArrayList(),
+						index,
+						childExpectedPolicies,
+						node,
+						pq,
+						pOid.Id,
+						false);
+					node.AddChild(child);
+					policyNodes[index].Add(child);
+
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		internal static void ProcessCertD1ii(
+			int					index,
+			IList[]				policyNodes,
+			DerObjectIdentifier _poid,
+			ISet				_pq)
+		{
+			IList policyNodeVec = policyNodes[index - 1];
+
+			for (int j = 0; j < policyNodeVec.Count; j++)
+			{
+				PkixPolicyNode _node = (PkixPolicyNode)policyNodeVec[j];
+
+				if (ANY_POLICY.Equals(_node.ValidPolicy))
+				{
+					ISet _childExpectedPolicies = new HashSet();
+					_childExpectedPolicies.Add(_poid.Id);
+
+                    PkixPolicyNode _child = new PkixPolicyNode(Platform.CreateArrayList(),
+						index,
+						_childExpectedPolicies,
+						_node,
+						_pq,
+						_poid.Id,
+						false);
+					_node.AddChild(_child);
+					policyNodes[index].Add(_child);
+					return;
+				}
+			}
+		}
+
+		/**
+		* Find the issuer certificates of a given certificate.
+		*
+		* @param cert
+		*            The certificate for which an issuer should be found.
+		* @param pkixParams
+		* @return A <code>Collection</code> object containing the issuer
+		*         <code>X509Certificate</code>s. Never <code>null</code>.
+		*
+		* @exception Exception
+		*                if an error occurs.
+		*/
+		internal static ICollection FindIssuerCerts(
+			X509Certificate			cert,
+			PkixBuilderParameters	pkixParams)
+		{
+			X509CertStoreSelector certSelect = new X509CertStoreSelector();
+			ISet certs = new HashSet();
+			try
+			{
+				certSelect.Subject = cert.IssuerDN;
+			}
+			catch (IOException ex)
+			{
+				throw new Exception(
+					"Subject criteria for certificate selector to find issuer certificate could not be set.", ex);
+			}
+
+			try
+			{
+                certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetStores()));
+                certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetAdditionalStores()));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("Issuer certificate cannot be searched.", e);
+			}
+
+			return certs;
+		}
+
+		/// <summary>
+		/// Extract the value of the given extension, if it exists.
+		/// </summary>
+		/// <param name="ext">The extension object.</param>
+		/// <param name="oid">The object identifier to obtain.</param>
+		/// <returns>Asn1Object</returns>
+		/// <exception cref="Exception">if the extension cannot be read.</exception>
+		internal static Asn1Object GetExtensionValue(
+			IX509Extension		ext,
+			DerObjectIdentifier	oid)
+		{
+			Asn1OctetString bytes = ext.GetExtensionValue(oid);
+
+			if (bytes == null)
+				return null;
+
+			return X509ExtensionUtilities.FromExtensionValue(bytes);
+		}
+	}
+}