summary refs log tree commit diff
path: root/crypto/src/x509/store/X509CertStoreSelector.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/x509/store/X509CertStoreSelector.cs')
-rw-r--r--crypto/src/x509/store/X509CertStoreSelector.cs337
1 files changed, 337 insertions, 0 deletions
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());
+		}
+	}
+}