summary refs log tree commit diff
path: root/Crypto/src/pkix/TrustAnchor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/pkix/TrustAnchor.cs')
-rw-r--r--Crypto/src/pkix/TrustAnchor.cs259
1 files changed, 259 insertions, 0 deletions
diff --git a/Crypto/src/pkix/TrustAnchor.cs b/Crypto/src/pkix/TrustAnchor.cs
new file mode 100644
index 000000000..22078baf2
--- /dev/null
+++ b/Crypto/src/pkix/TrustAnchor.cs
@@ -0,0 +1,259 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// A trust anchor or most-trusted Certification Authority (CA).
+	/// 
+	/// This class represents a "most-trusted CA", which is used as a trust anchor
+	/// for validating X.509 certification paths. A most-trusted CA includes the
+	/// public key of the CA, the CA's name, and any constraints upon the set of
+	/// paths which may be validated using this key. These parameters can be
+	/// specified in the form of a trusted X509Certificate or as individual
+	/// parameters.
+	/// </summary>
+	public class TrustAnchor
+	{
+		private readonly AsymmetricKeyParameter pubKey;
+		private readonly string caName;
+		private readonly X509Name caPrincipal;
+		private readonly X509Certificate trustedCert;
+		private byte[] ncBytes;
+		private NameConstraints nc;
+
+		/// <summary>
+		/// Creates an instance of TrustAnchor with the specified X509Certificate and
+	    /// optional name constraints, which are intended to be used as additional
+	    /// constraints when validating an X.509 certification path.
+	    ///	The name constraints are specified as a byte array. This byte array
+	    ///	should contain the DER encoded form of the name constraints, as they
+	    ///	would appear in the NameConstraints structure defined in RFC 2459 and
+	    ///	X.509. The ASN.1 definition of this structure appears below.
+	    ///	
+	    ///	<pre>
+	    ///	NameConstraints ::= SEQUENCE {
+	    ///		permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+	    ///		excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+	    ///	   
+        /// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+        /// 
+        ///		GeneralSubtree ::= SEQUENCE {
+        ///		base                    GeneralName,
+        ///		minimum         [0]     BaseDistance DEFAULT 0,
+        ///		maximum         [1]     BaseDistance OPTIONAL }
+        ///		
+        ///		BaseDistance ::= INTEGER (0..MAX)
+		///
+		///		GeneralName ::= CHOICE {
+		///		otherName                       [0]     OtherName,
+		///		rfc822Name                      [1]     IA5String,
+		///		dNSName                         [2]     IA5String,
+		///		x400Address                     [3]     ORAddress,
+		///		directoryName                   [4]     Name,
+		///		ediPartyName                    [5]     EDIPartyName,
+		///		uniformResourceIdentifier       [6]     IA5String,
+		///		iPAddress                       [7]     OCTET STRING,
+		///		registeredID                    [8]     OBJECT IDENTIFIER}
+		///	</pre>
+		///	
+		///	Note that the name constraints byte array supplied is cloned to protect
+		///	against subsequent modifications.
+		/// </summary>
+		/// <param name="trustedCert">a trusted X509Certificate</param>
+		/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+		/// NameConstraints extension to be used for checking name
+		/// constraints. Only the value of the extension is included, not
+		/// the OID or criticality flag. Specify null to omit the
+		/// parameter.</param>
+		/// <exception cref="ArgumentNullException">if the specified X509Certificate is null</exception>
+		public TrustAnchor(
+			X509Certificate	trustedCert,
+			byte[]			nameConstraints)
+		{
+			if (trustedCert == null)
+				throw new ArgumentNullException("trustedCert");
+
+			this.trustedCert = trustedCert;
+			this.pubKey = null;
+			this.caName = null;
+			this.caPrincipal = null;
+			setNameConstraints(nameConstraints);
+		}
+
+		/// <summary>
+		/// Creates an instance of <c>TrustAnchor</c> where the
+		/// most-trusted CA is specified as an X500Principal and public key.
+		/// </summary>
+		/// <remarks>
+		/// <p>
+		/// Name constraints are an optional parameter, and are intended to be used
+		/// as additional constraints when validating an X.509 certification path.
+		/// </p><p>
+		/// The name constraints are specified as a byte array. This byte array
+		/// contains the DER encoded form of the name constraints, as they
+		/// would appear in the NameConstraints structure defined in RFC 2459
+		/// and X.509. The ASN.1 notation for this structure is supplied in the
+		/// documentation for the other constructors.
+		/// </p><p>
+		/// Note that the name constraints byte array supplied here is cloned to
+		/// protect against subsequent modifications.
+		/// </p>
+		/// </remarks>
+		/// <param name="caPrincipal">the name of the most-trusted CA as X509Name</param>
+		/// <param name="pubKey">the public key of the most-trusted CA</param>
+		/// <param name="nameConstraints">
+		/// a byte array containing the ASN.1 DER encoding of a NameConstraints extension to
+		/// be used for checking name constraints. Only the value of the extension is included,
+		/// not the OID or criticality flag. Specify <c>null</c> to omit the parameter.
+		/// </param>
+		/// <exception cref="ArgumentNullException">
+		/// if <c>caPrincipal</c> or <c>pubKey</c> is null
+		/// </exception>
+		public TrustAnchor(
+			X509Name				caPrincipal,
+			AsymmetricKeyParameter	pubKey,
+			byte[]					nameConstraints) 
+		{
+			if (caPrincipal == null)
+				throw new ArgumentNullException("caPrincipal");
+			if (pubKey == null)
+				throw new ArgumentNullException("pubKey");
+
+			this.trustedCert = null;
+			this.caPrincipal = caPrincipal;
+			this.caName = caPrincipal.ToString();
+			this.pubKey = pubKey;
+			setNameConstraints(nameConstraints);
+		}
+
+		/// <summary>
+		/// Creates an instance of <code>TrustAnchor</code> where the most-trusted
+		/// CA is specified as a distinguished name and public key. Name constraints
+		/// are an optional parameter, and are intended to be used as additional
+		/// constraints when validating an X.509 certification path.
+		/// <br/>
+		/// The name constraints are specified as a byte array. This byte array
+		/// contains the DER encoded form of the name constraints, as they would
+		/// appear in the NameConstraints structure defined in RFC 2459 and X.509.
+		/// </summary>
+		/// <param name="caName">the X.500 distinguished name of the most-trusted CA in RFC
+		/// 2253 string format</param>
+		/// <param name="pubKey">the public key of the most-trusted CA</param>
+		/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+		/// NameConstraints extension to be used for checking name
+		/// constraints. Only the value of the extension is included, not 
+		/// the OID or criticality flag. Specify null to omit the 
+		/// parameter.</param>
+		/// throws NullPointerException, IllegalArgumentException
+		public TrustAnchor(
+			string					caName,
+			AsymmetricKeyParameter	pubKey,
+			byte[]					nameConstraints)
+		{
+			if (caName == null)
+				throw new ArgumentNullException("caName");
+			if (pubKey == null)
+				throw new ArgumentNullException("pubKey");
+			if (caName.Length == 0)
+				throw new ArgumentException("caName can not be an empty string");
+
+			this.caPrincipal = new X509Name(caName);
+			this.pubKey = pubKey;
+			this.caName = caName;
+			this.trustedCert = null;
+			setNameConstraints(nameConstraints);
+		}
+
+		/// <summary>
+		/// Returns the most-trusted CA certificate.
+		/// </summary>
+		public X509Certificate TrustedCert
+		{
+			get { return this.trustedCert; }
+		}
+
+		/// <summary>
+		/// Returns the name of the most-trusted CA as an X509Name.
+		/// </summary>
+		public X509Name CA
+		{
+			get { return this.caPrincipal; }
+		}
+
+		/// <summary>
+		/// Returns the name of the most-trusted CA in RFC 2253 string format.
+		/// </summary>
+		public string CAName
+		{
+			get { return this.caName; }
+		}
+
+		/// <summary>
+		/// Returns the public key of the most-trusted CA.
+		/// </summary>
+		public AsymmetricKeyParameter CAPublicKey
+		{
+			get { return this.pubKey; }
+		}
+
+		/// <summary>
+		/// Decode the name constraints and clone them if not null.
+		/// </summary>
+		private void setNameConstraints(
+			byte[] bytes) 
+		{
+			if (bytes == null) 
+			{
+				ncBytes = null;
+				nc = null;
+			} 
+			else 
+			{
+				ncBytes = (byte[]) bytes.Clone();
+				// validate DER encoding
+				//nc = new NameConstraintsExtension(Boolean.FALSE, bytes);
+				nc = NameConstraints.GetInstance(Asn1Object.FromByteArray(bytes));
+			}
+		}
+
+		public byte[] GetNameConstraints
+		{
+			get { return Arrays.Clone(ncBytes); }
+		}
+
+		/// <summary>
+		/// Returns a formatted string describing the <code>TrustAnchor</code>.
+		/// </summary>
+		/// <returns>a formatted string describing the <code>TrustAnchor</code></returns>
+		public override string ToString()
+		{
+			// TODO Some of the sub-objects might not implement ToString() properly
+			string nl = Platform.NewLine;
+			StringBuilder sb = new StringBuilder();
+			sb.Append("[");
+			sb.Append(nl);
+			if (this.pubKey != null)
+			{
+				sb.Append("  Trusted CA Public Key: ").Append(this.pubKey).Append(nl);
+				sb.Append("  Trusted CA Issuer Name: ").Append(this.caName).Append(nl);
+			}
+			else
+			{
+				sb.Append("  Trusted CA cert: ").Append(this.TrustedCert).Append(nl);
+			}
+			if (nc != null)
+			{
+				sb.Append("  Name Constraints: ").Append(nc).Append(nl);
+			}
+			return sb.ToString();
+		}
+	}
+}
\ No newline at end of file