summary refs log tree commit diff
path: root/crypto/src/x509/store
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2013-06-28 15:26:06 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2013-06-28 15:26:06 +0700
commit44288db4414158ac9b98a507b15e81d0d3c66ca6 (patch)
treeaa5ef88948ebb68ed6c8df81eb5da889641a9b50 /crypto/src/x509/store
parentSet up text/binary handling for existing file types (diff)
downloadBouncyCastle.NET-ed25519-44288db4414158ac9b98a507b15e81d0d3c66ca6.tar.xz
Initial import of old CVS repository
Diffstat (limited to 'crypto/src/x509/store')
-rw-r--r--crypto/src/x509/store/IX509Selector.cs15
-rw-r--r--crypto/src/x509/store/IX509Store.cs11
-rw-r--r--crypto/src/x509/store/IX509StoreParameters.cs8
-rw-r--r--crypto/src/x509/store/NoSuchStoreException.cs28
-rw-r--r--crypto/src/x509/store/X509AttrCertStoreSelector.cs376
-rw-r--r--crypto/src/x509/store/X509CertPairStoreSelector.cs92
-rw-r--r--crypto/src/x509/store/X509CertStoreSelector.cs337
-rw-r--r--crypto/src/x509/store/X509CollectionStore.cs51
-rw-r--r--crypto/src/x509/store/X509CollectionStoreParameters.cs60
-rw-r--r--crypto/src/x509/store/X509CrlStoreSelector.cs283
-rw-r--r--crypto/src/x509/store/X509StoreException.cs28
-rw-r--r--crypto/src/x509/store/X509StoreFactory.cs62
12 files changed, 1351 insertions, 0 deletions
diff --git a/crypto/src/x509/store/IX509Selector.cs b/crypto/src/x509/store/IX509Selector.cs
new file mode 100644
index 000000000..09f6f1849
--- /dev/null
+++ b/crypto/src/x509/store/IX509Selector.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public interface IX509Selector
+#if !SILVERLIGHT
+		: ICloneable
+#endif
+	{
+#if SILVERLIGHT
+        object Clone();
+#endif
+        bool Match(object obj);
+	}
+}
diff --git a/crypto/src/x509/store/IX509Store.cs b/crypto/src/x509/store/IX509Store.cs
new file mode 100644
index 000000000..e5c3a462a
--- /dev/null
+++ b/crypto/src/x509/store/IX509Store.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public interface IX509Store
+	{
+//		void Init(IX509StoreParameters parameters);
+		ICollection GetMatches(IX509Selector selector);
+	}
+}
diff --git a/crypto/src/x509/store/IX509StoreParameters.cs b/crypto/src/x509/store/IX509StoreParameters.cs
new file mode 100644
index 000000000..aee3036c2
--- /dev/null
+++ b/crypto/src/x509/store/IX509StoreParameters.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public interface IX509StoreParameters
+	{
+	}
+}
diff --git a/crypto/src/x509/store/NoSuchStoreException.cs b/crypto/src/x509/store/NoSuchStoreException.cs
new file mode 100644
index 000000000..02c593245
--- /dev/null
+++ b/crypto/src/x509/store/NoSuchStoreException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class NoSuchStoreException
+		: X509StoreException
+	{
+		public NoSuchStoreException()
+		{
+		}
+
+		public NoSuchStoreException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public NoSuchStoreException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509AttrCertStoreSelector.cs b/crypto/src/x509/store/X509AttrCertStoreSelector.cs
new file mode 100644
index 000000000..9f1dc20d1
--- /dev/null
+++ b/crypto/src/x509/store/X509AttrCertStoreSelector.cs
@@ -0,0 +1,376 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/**
+	* This class is an <code>Selector</code> like implementation to select
+	* attribute certificates from a given set of criteria.
+	*
+	* @see org.bouncycastle.x509.X509AttributeCertificate
+	* @see org.bouncycastle.x509.X509Store
+	*/
+	public class X509AttrCertStoreSelector
+		: IX509Selector
+	{
+		// TODO: name constraints???
+
+		private IX509AttributeCertificate attributeCert;
+		private DateTimeObject attributeCertificateValid;
+		private AttributeCertificateHolder holder;
+		private AttributeCertificateIssuer issuer;
+		private BigInteger serialNumber;
+		private ISet targetNames = new HashSet();
+		private ISet targetGroups = new HashSet();
+
+		public X509AttrCertStoreSelector()
+		{
+		}
+
+		private X509AttrCertStoreSelector(
+			X509AttrCertStoreSelector o)
+		{
+			this.attributeCert = o.attributeCert;
+			this.attributeCertificateValid = o.attributeCertificateValid;
+			this.holder = o.holder;
+			this.issuer = o.issuer;
+			this.serialNumber = o.serialNumber;
+			this.targetGroups = new HashSet(o.targetGroups);
+			this.targetNames = new HashSet(o.targetNames);
+		}
+
+		/// <summary>
+		/// Decides if the given attribute certificate should be selected.
+		/// </summary>
+		/// <param name="obj">The attribute certificate to be checked.</param>
+		/// <returns><code>true</code> if the object matches this selector.</returns>
+		public bool Match(
+			object obj)
+		{
+			if (obj == null)
+				throw new ArgumentNullException("obj");
+
+			IX509AttributeCertificate attrCert = obj as IX509AttributeCertificate;
+
+			if (attrCert == null)
+				return false;
+
+			if (this.attributeCert != null && !this.attributeCert.Equals(attrCert))
+				return false;
+
+			if (serialNumber != null && !attrCert.SerialNumber.Equals(serialNumber))
+				return false;
+
+			if (holder != null && !attrCert.Holder.Equals(holder))
+				return false;
+
+			if (issuer != null && !attrCert.Issuer.Equals(issuer))
+				return false;
+
+			if (attributeCertificateValid != null && !attrCert.IsValid(attributeCertificateValid.Value))
+				return false;
+
+			if (targetNames.Count > 0 || targetGroups.Count > 0)
+			{
+				Asn1OctetString targetInfoExt = attrCert.GetExtensionValue(
+					X509Extensions.TargetInformation);
+
+				if (targetInfoExt != null)
+				{
+					TargetInformation targetinfo;
+					try
+					{
+						targetinfo = TargetInformation.GetInstance(
+							X509ExtensionUtilities.FromExtensionValue(targetInfoExt));
+					}
+					catch (Exception)
+					{
+						return false;
+					}
+
+					Targets[] targetss = targetinfo.GetTargetsObjects();
+
+					if (targetNames.Count > 0)
+					{
+						bool found = false;
+
+						for (int i = 0; i < targetss.Length && !found; i++)
+						{
+							Target[] targets = targetss[i].GetTargets();
+
+							for (int j = 0; j < targets.Length; j++)
+							{
+								GeneralName targetName = targets[j].TargetName;
+
+								if (targetName != null && targetNames.Contains(targetName))
+								{
+									found = true;
+									break;
+								}
+							}
+						}
+						if (!found)
+						{
+							return false;
+						}
+					}
+
+					if (targetGroups.Count > 0)
+					{
+						bool found = false;
+
+						for (int i = 0; i < targetss.Length && !found; i++)
+						{
+							Target[] targets = targetss[i].GetTargets();
+
+							for (int j = 0; j < targets.Length; j++)
+							{
+								GeneralName targetGroup = targets[j].TargetGroup;
+
+								if (targetGroup != null && targetGroups.Contains(targetGroup))
+								{
+									found = true;
+									break;
+								}
+							}
+						}
+
+						if (!found)
+						{
+							return false;
+						}
+					}
+				}
+			}
+
+			return true;
+		}
+
+		public object Clone()
+		{
+			return new X509AttrCertStoreSelector(this);
+		}
+
+		/// <summary>The attribute certificate which must be matched.</summary>
+		/// <remarks>If <c>null</c> is given, any will do.</remarks>
+		public IX509AttributeCertificate AttributeCert
+		{
+			get { return attributeCert; }
+			set { this.attributeCert = value; }
+		}
+
+		[Obsolete("Use AttributeCertificateValid instead")]
+		public DateTimeObject AttribueCertificateValid
+		{
+			get { return attributeCertificateValid; }
+			set { this.attributeCertificateValid = value; }
+		}
+
+		/// <summary>The criteria for validity</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public DateTimeObject AttributeCertificateValid
+		{
+			get { return attributeCertificateValid; }
+			set { this.attributeCertificateValid = value; }
+		}
+
+		/// <summary>The holder.</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public AttributeCertificateHolder Holder
+		{
+			get { return holder; }
+			set { this.holder = value; }
+		}
+
+		/// <summary>The issuer.</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public AttributeCertificateIssuer Issuer
+		{
+			get { return issuer; }
+			set { this.issuer = value; }
+		}
+
+		/// <summary>The serial number.</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public BigInteger SerialNumber
+		{
+			get { return serialNumber; }
+			set { this.serialNumber = value; }
+		}
+
+		/**
+		* Adds a target name criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target names.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param name The name as a GeneralName (not <code>null</code>)
+		*/
+		public void AddTargetName(
+			GeneralName name)
+		{
+			targetNames.Add(name);
+		}
+
+		/**
+		* Adds a target name criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target names.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName
+		* @throws IOException if a parsing error occurs.
+		*/
+		public void AddTargetName(
+			byte[] name)
+		{
+			AddTargetName(GeneralName.GetInstance(Asn1Object.FromByteArray(name)));
+		}
+
+		/**
+		* Adds a collection with target names criteria. If <code>null</code> is
+		* given any will do.
+		* <p>
+		* The collection consists of either GeneralName objects or byte[] arrays representing
+		* DER encoded GeneralName structures.
+		* </p>
+		* 
+		* @param names A collection of target names.
+		* @throws IOException if a parsing error occurs.
+		* @see #AddTargetName(byte[])
+		* @see #AddTargetName(GeneralName)
+		*/
+		public void SetTargetNames(
+			IEnumerable names)
+		{
+			targetNames = ExtractGeneralNames(names);
+		}
+
+		/**
+		* Gets the target names. The collection consists of <code>List</code>s
+		* made up of an <code>Integer</code> in the first entry and a DER encoded
+		* byte array or a <code>String</code> in the second entry.
+		* <p>The returned collection is immutable.</p>
+		* 
+		* @return The collection of target names
+		* @see #setTargetNames(Collection)
+		*/
+		public IEnumerable GetTargetNames()
+		{
+			return new EnumerableProxy(targetNames);
+		}
+
+		/**
+		* Adds a target group criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target groups.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param group The group as GeneralName form (not <code>null</code>)
+		*/
+		public void AddTargetGroup(
+			GeneralName group)
+		{
+			targetGroups.Add(group);
+		}
+
+		/**
+		* Adds a target group criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target groups.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName
+		* @throws IOException if a parsing error occurs.
+		*/
+		public void AddTargetGroup(
+			byte[] name)
+		{
+			AddTargetGroup(GeneralName.GetInstance(Asn1Object.FromByteArray(name)));
+		}
+
+		/**
+		* Adds a collection with target groups criteria. If <code>null</code> is
+		* given any will do.
+		* <p>
+		* The collection consists of <code>GeneralName</code> objects or <code>byte[]</code>
+		* representing DER encoded GeneralNames.
+		* </p>
+		*
+		* @param names A collection of target groups.
+		* @throws IOException if a parsing error occurs.
+		* @see #AddTargetGroup(byte[])
+		* @see #AddTargetGroup(GeneralName)
+		*/
+		public void SetTargetGroups(
+			IEnumerable names)
+		{
+			targetGroups = ExtractGeneralNames(names);
+		}
+
+		/**
+		* Gets the target groups. The collection consists of <code>List</code>s
+		* made up of an <code>Integer</code> in the first entry and a DER encoded
+		* byte array or a <code>String</code> in the second entry.
+		* <p>The returned collection is immutable.</p>
+		*
+		* @return The collection of target groups.
+		* @see #setTargetGroups(Collection)
+		*/
+		public IEnumerable GetTargetGroups()
+		{
+			return new EnumerableProxy(targetGroups);
+		}
+
+		private ISet ExtractGeneralNames(
+			IEnumerable names)
+		{
+			ISet result = new HashSet();
+
+			if (names != null)
+			{
+				foreach (object o in names)
+				{
+					if (o is GeneralName)
+					{
+						result.Add(o);
+					}
+					else
+					{
+						result.Add(GeneralName.GetInstance(Asn1Object.FromByteArray((byte[]) o)));
+					}
+				}
+			}
+
+			return result;
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509CertPairStoreSelector.cs b/crypto/src/x509/store/X509CertPairStoreSelector.cs
new file mode 100644
index 000000000..2796971c7
--- /dev/null
+++ b/crypto/src/x509/store/X509CertPairStoreSelector.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/// <remarks>
+	/// This class is an <code>IX509Selector</code> implementation to select
+	/// certificate pairs, which are e.g. used for cross certificates. The set of
+	/// criteria is given from two <code>X509CertStoreSelector</code> objects,
+	/// each of which, if present, must match the respective component of a pair.
+	/// </remarks>
+	public class X509CertPairStoreSelector
+		: IX509Selector
+	{
+		private static X509CertStoreSelector CloneSelector(
+			X509CertStoreSelector s)
+		{
+			return s == null ? null : (X509CertStoreSelector) s.Clone();
+		}
+
+		private X509CertificatePair certPair;
+		private X509CertStoreSelector forwardSelector;
+		private X509CertStoreSelector reverseSelector;
+
+		public X509CertPairStoreSelector()
+		{
+		}
+
+		private X509CertPairStoreSelector(
+			X509CertPairStoreSelector o)
+		{
+			this.certPair = o.CertPair;
+			this.forwardSelector = o.ForwardSelector;
+			this.reverseSelector = o.ReverseSelector;
+		}
+
+		/// <summary>The certificate pair which is used for testing on equality.</summary>
+		public X509CertificatePair CertPair
+		{
+			get { return certPair; }
+			set { this.certPair = value; }
+		}
+
+		/// <summary>The certificate selector for the forward part.</summary>
+		public X509CertStoreSelector ForwardSelector
+		{
+			get { return CloneSelector(forwardSelector); }
+			set { this.forwardSelector = CloneSelector(value); }
+		}
+
+		/// <summary>The certificate selector for the reverse part.</summary>
+		public X509CertStoreSelector ReverseSelector
+		{
+			get { return CloneSelector(reverseSelector); }
+			set { this.reverseSelector = CloneSelector(value); }
+		}
+
+		/// <summary>
+		/// Decides if the given certificate pair should be selected. If
+		/// <c>obj</c> is not a <code>X509CertificatePair</code>, this method
+		/// returns <code>false</code>.
+		/// </summary>
+		/// <param name="obj">The <code>X509CertificatePair</code> to be tested.</param>
+		/// <returns><code>true</code> if the object matches this selector.</returns>
+		public bool Match(
+			object obj)
+		{
+			if (obj == null)
+				throw new ArgumentNullException("obj");
+
+			X509CertificatePair pair = obj as X509CertificatePair;
+
+			if (pair == null)
+				return false;
+
+			if (certPair != null && !certPair.Equals(pair))
+				return false;
+
+			if (forwardSelector != null && !forwardSelector.Match(pair.Forward))
+				return false;
+
+			if (reverseSelector != null && !reverseSelector.Match(pair.Reverse))
+				return false;
+
+			return true;
+		}
+
+		public object Clone()
+		{
+			return new X509CertPairStoreSelector(this);
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509CertStoreSelector.cs b/crypto/src/x509/store/X509CertStoreSelector.cs
new file mode 100644
index 000000000..3874edf1d
--- /dev/null
+++ b/crypto/src/x509/store/X509CertStoreSelector.cs
@@ -0,0 +1,337 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public class X509CertStoreSelector
+		: IX509Selector
+	{
+		// TODO Missing criteria?
+
+		private byte[] authorityKeyIdentifier;
+		private int basicConstraints = -1;
+		private X509Certificate certificate;
+		private DateTimeObject certificateValid;
+		private ISet extendedKeyUsage;
+		private X509Name issuer;
+		private bool[] keyUsage;
+		private ISet policy;
+		private DateTimeObject privateKeyValid;
+		private BigInteger serialNumber;
+		private X509Name subject;
+		private byte[] subjectKeyIdentifier;
+		private SubjectPublicKeyInfo subjectPublicKey;
+		private DerObjectIdentifier subjectPublicKeyAlgID;
+
+		public X509CertStoreSelector()
+		{
+		}
+
+		public X509CertStoreSelector(
+			X509CertStoreSelector o)
+		{
+			this.authorityKeyIdentifier = o.AuthorityKeyIdentifier;
+			this.basicConstraints = o.BasicConstraints;
+			this.certificate = o.Certificate;
+			this.certificateValid = o.CertificateValid;
+			this.extendedKeyUsage = o.ExtendedKeyUsage;
+			this.issuer = o.Issuer;
+			this.keyUsage = o.KeyUsage;
+			this.policy = o.Policy;
+			this.privateKeyValid = o.PrivateKeyValid;
+			this.serialNumber = o.SerialNumber;
+			this.subject = o.Subject;
+			this.subjectKeyIdentifier = o.SubjectKeyIdentifier;
+			this.subjectPublicKey = o.SubjectPublicKey;
+			this.subjectPublicKeyAlgID = o.SubjectPublicKeyAlgID;
+		}
+
+		public virtual object Clone()
+		{
+			return new X509CertStoreSelector(this);
+		}
+
+		public byte[] AuthorityKeyIdentifier
+		{
+			get { return Arrays.Clone(authorityKeyIdentifier); }
+			set { authorityKeyIdentifier = Arrays.Clone(value); }
+		}
+
+		public int BasicConstraints
+		{
+			get { return basicConstraints; }
+			set
+			{
+				if (value < -2)
+					throw new ArgumentException("value can't be less than -2", "value");
+
+				basicConstraints = value;
+			}
+		}
+
+		public X509Certificate Certificate
+		{
+			get { return certificate; }
+			set { this.certificate = value; }
+		}
+
+		public DateTimeObject CertificateValid
+		{
+			get { return certificateValid; }
+			set { certificateValid = value; }
+		}
+
+		public ISet ExtendedKeyUsage
+		{
+			get { return CopySet(extendedKeyUsage); }
+			set { extendedKeyUsage = CopySet(value); }
+		}
+
+		public X509Name Issuer
+		{
+			get { return issuer; }
+			set { issuer = value; }
+		}
+
+		[Obsolete("Avoid working with X509Name objects in string form")]
+		public string IssuerAsString
+		{
+			get { return issuer != null ? issuer.ToString() : null; }
+		}
+
+		public bool[] KeyUsage
+		{
+			get { return CopyBoolArray(keyUsage); }
+			set { keyUsage = CopyBoolArray(value); }
+		}
+
+		/// <summary>
+		/// An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
+		/// </summary>
+		public ISet Policy
+		{
+			get { return CopySet(policy); }
+			set { policy = CopySet(value); }
+		}
+
+		public DateTimeObject PrivateKeyValid
+		{
+			get { return privateKeyValid; }
+			set { privateKeyValid = value; }
+		}
+
+		public BigInteger SerialNumber
+		{
+			get { return serialNumber; }
+			set { serialNumber = value; }
+		}
+
+		public X509Name Subject
+		{
+			get { return subject; }
+			set { subject = value; }
+		}
+
+		public string SubjectAsString
+		{
+			get { return subject != null ? subject.ToString() : null; }
+		}
+
+		public byte[] SubjectKeyIdentifier
+		{
+			get { return Arrays.Clone(subjectKeyIdentifier); }
+			set { subjectKeyIdentifier = Arrays.Clone(value); }
+		}
+
+		public SubjectPublicKeyInfo SubjectPublicKey
+		{
+			get { return subjectPublicKey; }
+			set { subjectPublicKey = value; }
+		}
+
+		public DerObjectIdentifier SubjectPublicKeyAlgID
+		{
+			get { return subjectPublicKeyAlgID; }
+			set { subjectPublicKeyAlgID = value; }
+		}
+
+		public virtual bool Match(
+			object obj)
+		{
+			X509Certificate c = obj as X509Certificate;
+
+			if (c == null)
+				return false;
+
+			if (!MatchExtension(authorityKeyIdentifier, c, X509Extensions.AuthorityKeyIdentifier))
+				return false;
+
+			if (basicConstraints != -1)
+			{
+				int bc = c.GetBasicConstraints();
+
+				if (basicConstraints == -2)
+				{
+					if (bc != -1)
+						return false;
+				}
+				else
+				{
+					if (bc < basicConstraints)
+						return false;
+				}
+			}
+
+			if (certificate != null && !certificate.Equals(c))
+				return false;
+
+			if (certificateValid != null && !c.IsValid(certificateValid.Value))
+				return false;
+
+			if (extendedKeyUsage != null)
+			{
+				IList eku = c.GetExtendedKeyUsage();
+
+				// Note: if no extended key usage set, all key purposes are implicitly allowed
+
+				if (eku != null)
+				{
+					foreach (DerObjectIdentifier oid in extendedKeyUsage)
+					{
+						if (!eku.Contains(oid.Id))
+							return false;
+					}
+				}
+			}
+
+			if (issuer != null && !issuer.Equivalent(c.IssuerDN, true))
+				return false;
+
+			if (keyUsage != null)
+			{
+				bool[] ku = c.GetKeyUsage();
+
+				// Note: if no key usage set, all key purposes are implicitly allowed
+
+				if (ku != null)
+				{
+					for (int i = 0; i < 9; ++i)
+					{
+						if (keyUsage[i] && !ku[i])
+							return false;
+					}
+				}
+			}
+
+			if (policy != null)
+			{
+				Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CertificatePolicies);
+				if (extVal == null)
+					return false;
+
+				Asn1Sequence certPolicies = Asn1Sequence.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(extVal));
+
+				if (policy.Count < 1 && certPolicies.Count < 1)
+					return false;
+
+				bool found = false;
+				foreach (PolicyInformation pi in certPolicies)
+				{
+					if (policy.Contains(pi.PolicyIdentifier))
+					{
+						found = true;
+						break;
+					}
+				}
+
+				if (!found)
+					return false;
+			}
+
+			if (privateKeyValid != null)
+			{
+				Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.PrivateKeyUsagePeriod);
+				if (extVal == null)
+					return false;
+
+				PrivateKeyUsagePeriod pkup = PrivateKeyUsagePeriod.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(extVal));
+
+				DateTime dt = privateKeyValid.Value;
+				DateTime notAfter = pkup.NotAfter.ToDateTime();
+				DateTime notBefore = pkup.NotBefore.ToDateTime();
+
+				if (dt.CompareTo(notAfter) > 0 || dt.CompareTo(notBefore) < 0)
+					return false;
+			}
+
+			if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
+				return false;
+
+			if (subject != null && !subject.Equivalent(c.SubjectDN, true))
+				return false;
+
+			if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
+				return false;
+
+			if (subjectPublicKey != null && !subjectPublicKey.Equals(GetSubjectPublicKey(c)))
+				return false;
+
+			if (subjectPublicKeyAlgID != null
+				&& !subjectPublicKeyAlgID.Equals(GetSubjectPublicKey(c).AlgorithmID))
+				return false;
+
+			return true;
+		}
+
+		internal static bool IssuersMatch(
+			X509Name	a,
+			X509Name	b)
+		{
+			return a == null ? b == null : a.Equivalent(b, true);
+		}
+
+		private static bool[] CopyBoolArray(
+			bool[] b)
+		{
+			return b == null ? null : (bool[]) b.Clone();
+		}
+
+		private static ISet CopySet(
+			ISet s)
+		{
+			return s == null ? null : new HashSet(s);
+		}
+
+		private static SubjectPublicKeyInfo GetSubjectPublicKey(
+			X509Certificate c)
+		{
+			return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(c.GetPublicKey());
+		}
+
+		private static bool MatchExtension(
+			byte[]				b,
+			X509Certificate		c,
+			DerObjectIdentifier	oid)
+		{
+			if (b == null)
+				return true;
+
+			Asn1OctetString extVal = c.GetExtensionValue(oid);
+
+			if (extVal == null)
+				return false;
+
+			return Arrays.AreEqual(b, extVal.GetOctets());
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509CollectionStore.cs b/crypto/src/x509/store/X509CollectionStore.cs
new file mode 100644
index 000000000..92173140b
--- /dev/null
+++ b/crypto/src/x509/store/X509CollectionStore.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/**
+	 * A simple collection backed store.
+	 */
+	internal class X509CollectionStore
+		: IX509Store
+	{
+		private ICollection _local;
+
+		/**
+		 * Basic constructor.
+		 *
+		 * @param collection - initial contents for the store, this is copied.
+		 */
+		internal X509CollectionStore(
+			ICollection collection)
+		{
+			_local = Platform.CreateArrayList(collection);
+		}
+
+		/**
+		 * Return the matches in the collection for the passed in selector.
+		 *
+		 * @param selector the selector to match against.
+		 * @return a possibly empty collection of matching objects.
+		 */
+		public ICollection GetMatches(
+			IX509Selector selector)
+		{
+			if (selector == null)
+			{
+                return Platform.CreateArrayList(_local);
+			}
+
+            IList result = Platform.CreateArrayList();
+			foreach (object obj in _local)
+			{
+				if (selector.Match(obj))
+					result.Add(obj);
+			}
+
+			return result;
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509CollectionStoreParameters.cs b/crypto/src/x509/store/X509CollectionStoreParameters.cs
new file mode 100644
index 000000000..7fd047a47
--- /dev/null
+++ b/crypto/src/x509/store/X509CollectionStoreParameters.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/// <remarks>This class contains a collection for collection based <code>X509Store</code>s.</remarks>
+	public class X509CollectionStoreParameters
+		: IX509StoreParameters
+	{
+		private readonly IList collection;
+
+		/// <summary>
+		/// Constructor.
+		/// <p>
+		/// The collection is copied.
+		/// </p>
+		/// </summary>
+		/// <param name="collection">The collection containing X.509 object types.</param>
+		/// <exception cref="ArgumentNullException">If collection is null.</exception>
+		public X509CollectionStoreParameters(
+			ICollection collection)
+		{
+			if (collection == null)
+				throw new ArgumentNullException("collection");
+
+			this.collection = Platform.CreateArrayList(collection);
+		}
+
+		// TODO Do we need to be able to Clone() these, and should it really be shallow?
+//		/**
+//		* Returns a shallow clone. The returned contents are not copied, so adding
+//		* or removing objects will effect this.
+//		*
+//		* @return a shallow clone.
+//		*/
+//		public object Clone()
+//		{
+//			return new X509CollectionStoreParameters(collection);
+//		}
+
+		/// <summary>Returns a copy of the <code>ICollection</code>.</summary>
+		public ICollection GetCollection()
+		{
+			return Platform.CreateArrayList(collection);
+		}
+
+		/// <summary>Returns a formatted string describing the parameters.</summary>
+		public override string ToString()
+		{
+			StringBuilder sb = new StringBuilder();
+			sb.Append("X509CollectionStoreParameters: [\n");
+			sb.Append("  collection: " + collection + "\n");
+			sb.Append("]");
+			return sb.ToString();
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509CrlStoreSelector.cs b/crypto/src/x509/store/X509CrlStoreSelector.cs
new file mode 100644
index 000000000..c4b0062c1
--- /dev/null
+++ b/crypto/src/x509/store/X509CrlStoreSelector.cs
@@ -0,0 +1,283 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public class X509CrlStoreSelector
+		: IX509Selector
+	{
+		// TODO Missing criteria?
+
+		private X509Certificate certificateChecking;
+		private DateTimeObject dateAndTime;
+		private ICollection issuers;
+		private BigInteger maxCrlNumber;
+		private BigInteger minCrlNumber;
+
+		private IX509AttributeCertificate attrCertChecking;
+		private bool completeCrlEnabled;
+		private bool deltaCrlIndicatorEnabled;
+		private byte[] issuingDistributionPoint;
+		private bool issuingDistributionPointEnabled;
+		private BigInteger maxBaseCrlNumber;
+
+		public X509CrlStoreSelector()
+		{
+		}
+
+		public X509CrlStoreSelector(
+			X509CrlStoreSelector o)
+		{
+			this.certificateChecking = o.CertificateChecking;
+			this.dateAndTime = o.DateAndTime;
+			this.issuers = o.Issuers;
+			this.maxCrlNumber = o.MaxCrlNumber;
+			this.minCrlNumber = o.MinCrlNumber;
+
+			this.deltaCrlIndicatorEnabled = o.DeltaCrlIndicatorEnabled;
+			this.completeCrlEnabled = o.CompleteCrlEnabled;
+			this.maxBaseCrlNumber = o.MaxBaseCrlNumber;
+			this.attrCertChecking = o.AttrCertChecking;
+			this.issuingDistributionPointEnabled = o.IssuingDistributionPointEnabled;
+			this.issuingDistributionPoint = o.IssuingDistributionPoint;
+		}
+
+		public virtual object Clone()
+		{
+			return new X509CrlStoreSelector(this);
+		}
+
+		public X509Certificate CertificateChecking
+		{
+			get { return certificateChecking; }
+			set { certificateChecking = value; }
+		}
+
+		public DateTimeObject DateAndTime
+		{
+			get { return dateAndTime; }
+			set { dateAndTime = value; }
+		}
+
+		/// <summary>
+		/// An <code>ICollection</code> of <code>X509Name</code> objects
+		/// </summary>
+		public ICollection Issuers
+		{
+			get { return Platform.CreateArrayList(issuers); }
+            set { issuers = Platform.CreateArrayList(value); }
+		}
+
+		public BigInteger MaxCrlNumber
+		{
+			get { return maxCrlNumber; }
+			set { maxCrlNumber = value; }
+		}
+
+		public BigInteger MinCrlNumber
+		{
+			get { return minCrlNumber; }
+			set { minCrlNumber = value; }
+		}
+
+		/**
+		 * The attribute certificate being checked. This is not a criterion.
+		 * Rather, it is optional information that may help a {@link X509Store} find
+		 * CRLs that would be relevant when checking revocation for the specified
+		 * attribute certificate. If <code>null</code> is specified, then no such
+		 * optional information is provided.
+		 *
+		 * @param attrCert the <code>IX509AttributeCertificate</code> being checked (or
+		 *             <code>null</code>)
+		 * @see #getAttrCertificateChecking()
+		 */
+		public IX509AttributeCertificate AttrCertChecking
+		{
+			get { return attrCertChecking; }
+			set { this.attrCertChecking = value; }
+		}
+
+		/**
+		 * If <code>true</code> only complete CRLs are returned. Defaults to
+		 * <code>false</code>.
+		 *
+		 * @return <code>true</code> if only complete CRLs are returned.
+		 */
+		public bool CompleteCrlEnabled
+		{
+			get { return completeCrlEnabled; }
+			set { this.completeCrlEnabled = value; }
+		}
+
+		/**
+		 * Returns if this selector must match CRLs with the delta CRL indicator
+		 * extension set. Defaults to <code>false</code>.
+		 *
+		 * @return Returns <code>true</code> if only CRLs with the delta CRL
+		 *         indicator extension are selected.
+		 */
+		public bool DeltaCrlIndicatorEnabled
+		{
+			get { return deltaCrlIndicatorEnabled; }
+			set { this.deltaCrlIndicatorEnabled = value; }
+		}
+
+		/**
+		 * The issuing distribution point.
+		 * <p>
+		 * The issuing distribution point extension is a CRL extension which
+		 * identifies the scope and the distribution point of a CRL. The scope
+		 * contains among others information about revocation reasons contained in
+		 * the CRL. Delta CRLs and complete CRLs must have matching issuing
+		 * distribution points.</p>
+		 * <p>
+		 * The byte array is cloned to protect against subsequent modifications.</p>
+		 * <p>
+		 * You must also enable or disable this criteria with
+		 * {@link #setIssuingDistributionPointEnabled(bool)}.</p>
+		 *
+		 * @param issuingDistributionPoint The issuing distribution point to set.
+		 *                                 This is the DER encoded OCTET STRING extension value.
+		 * @see #getIssuingDistributionPoint()
+		 */
+		public byte[] IssuingDistributionPoint
+		{
+			get { return Arrays.Clone(issuingDistributionPoint); }
+			set { this.issuingDistributionPoint = Arrays.Clone(value); }
+		}
+
+		/**
+		 * Whether the issuing distribution point criteria should be applied.
+		 * Defaults to <code>false</code>.
+		 * <p>
+		 * You may also set the issuing distribution point criteria if not a missing
+		 * issuing distribution point should be assumed.</p>
+		 *
+		 * @return Returns if the issuing distribution point check is enabled.
+		 */
+		public bool IssuingDistributionPointEnabled
+		{
+			get { return issuingDistributionPointEnabled; }
+			set { this.issuingDistributionPointEnabled = value; }
+		}
+
+		/**
+		 * The maximum base CRL number. Defaults to <code>null</code>.
+		 *
+		 * @return Returns the maximum base CRL number.
+		 * @see #setMaxBaseCRLNumber(BigInteger)
+		 */
+		public BigInteger MaxBaseCrlNumber
+		{
+			get { return maxBaseCrlNumber; }
+			set { this.maxBaseCrlNumber = value; }
+		}
+
+		public virtual bool Match(
+			object obj)
+		{
+			X509Crl c = obj as X509Crl;
+
+			if (c == null)
+				return false;
+
+			if (dateAndTime != null)
+			{
+				DateTime dt = dateAndTime.Value;
+				DateTime tu = c.ThisUpdate;
+				DateTimeObject nu = c.NextUpdate;
+
+				if (dt.CompareTo(tu) < 0 || nu == null || dt.CompareTo(nu.Value) >= 0)
+					return false;
+			}
+
+			if (issuers != null)
+			{
+				X509Name i = c.IssuerDN;
+
+				bool found = false;
+
+				foreach (X509Name issuer in issuers)
+				{
+					if (issuer.Equivalent(i, true))
+					{
+						found = true;
+						break;
+					}
+				}
+
+				if (!found)
+					return false;
+			}
+
+			if (maxCrlNumber != null || minCrlNumber != null)
+			{
+				Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CrlNumber);
+				if (extVal == null)
+					return false;
+
+				BigInteger cn = CrlNumber.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(extVal)).PositiveValue;
+
+				if (maxCrlNumber != null && cn.CompareTo(maxCrlNumber) > 0)
+					return false;
+
+				if (minCrlNumber != null && cn.CompareTo(minCrlNumber) < 0)
+					return false;
+			}
+
+			DerInteger dci = null;
+			try
+			{
+				Asn1OctetString bytes = c.GetExtensionValue(X509Extensions.DeltaCrlIndicator);
+				if (bytes != null)
+				{
+					dci = DerInteger.GetInstance(X509ExtensionUtilities.FromExtensionValue(bytes));
+				}
+			}
+			catch (Exception)
+			{
+				return false;
+			}
+
+			if (dci == null)
+			{
+				if (DeltaCrlIndicatorEnabled)
+					return false;
+			}
+			else
+			{
+				if (CompleteCrlEnabled)
+					return false;
+
+				if (maxBaseCrlNumber != null && dci.PositiveValue.CompareTo(maxBaseCrlNumber) > 0)
+					return false;
+			}
+
+			if (issuingDistributionPointEnabled)
+			{
+				Asn1OctetString idp = c.GetExtensionValue(X509Extensions.IssuingDistributionPoint);
+				if (issuingDistributionPoint == null)
+				{
+					if (idp != null)
+						return false;
+				}
+				else
+				{
+					if (!Arrays.AreEqual(idp.GetOctets(), issuingDistributionPoint))
+						return false;
+				}
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509StoreException.cs b/crypto/src/x509/store/X509StoreException.cs
new file mode 100644
index 000000000..f781291e2
--- /dev/null
+++ b/crypto/src/x509/store/X509StoreException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class X509StoreException
+		: Exception
+	{
+		public X509StoreException()
+		{
+		}
+
+		public X509StoreException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public X509StoreException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/crypto/src/x509/store/X509StoreFactory.cs b/crypto/src/x509/store/X509StoreFactory.cs
new file mode 100644
index 000000000..96f22be3f
--- /dev/null
+++ b/crypto/src/x509/store/X509StoreFactory.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public sealed class X509StoreFactory
+	{
+		private X509StoreFactory()
+		{
+		}
+
+		public static IX509Store Create(
+			string					type,
+			IX509StoreParameters	parameters)
+		{
+			if (type == null)
+				throw new ArgumentNullException("type");
+
+			string[] parts = Platform.ToUpperInvariant(type).Split('/');
+
+            if (parts.Length < 2)
+				throw new ArgumentException("type");
+
+			if (parts[1] != "COLLECTION")
+				throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
+
+			X509CollectionStoreParameters p = (X509CollectionStoreParameters) parameters;
+			ICollection coll = p.GetCollection();
+
+			switch (parts[0])
+			{
+				case "ATTRIBUTECERTIFICATE":
+					checkCorrectType(coll, typeof(IX509AttributeCertificate));
+					break;
+				case "CERTIFICATE":
+					checkCorrectType(coll, typeof(X509Certificate));
+					break;
+				case "CERTIFICATEPAIR":
+					checkCorrectType(coll, typeof(X509CertificatePair));
+					break;
+				case "CRL":
+					checkCorrectType(coll, typeof(X509Crl));
+					break;
+				default:
+					throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
+			}
+
+			return new X509CollectionStore(coll);
+		}
+
+		private static void checkCorrectType(ICollection coll, Type t)
+		{
+			foreach (object o in coll)
+			{
+				if (!t.IsInstanceOfType(o))
+					throw new InvalidCastException("Can't cast object to type: " + t.FullName);
+			}
+		}
+	}
+}