summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2020-04-05 21:16:59 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2020-04-05 21:16:59 +0700
commit184077ebeabe315ec4dc13e2670868422f7b9594 (patch)
tree2178074db98529109b9d91e5e42e8c555bd904e8
parentAdd OIW dsaWithSHA1 OID to 'noParams' (diff)
downloadBouncyCastle.NET-ed25519-184077ebeabe315ec4dc13e2670868422f7b9594.tar.xz
Add OtherName support and refactoring
-rw-r--r--crypto/BouncyCastle.Android.csproj1
-rw-r--r--crypto/BouncyCastle.csproj1
-rw-r--r--crypto/BouncyCastle.iOS.csproj1
-rw-r--r--crypto/crypto.csproj5
-rw-r--r--crypto/src/asn1/x509/OtherName.cs71
-rw-r--r--crypto/src/pkix/PkixNameConstraintValidator.cs1045
-rw-r--r--crypto/test/src/test/PkixNameConstraintsTest.cs31
7 files changed, 628 insertions, 527 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 96d3f7cb6..08d105ada 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -435,6 +435,7 @@
     <Compile Include="src\asn1\x509\NameConstraints.cs" />
     <Compile Include="src\asn1\x509\NoticeReference.cs" />
     <Compile Include="src\asn1\x509\ObjectDigestInfo.cs" />
+    <Compile Include="src\asn1\x509\OtherName.cs" />
     <Compile Include="src\asn1\x509\PolicyInformation.cs" />
     <Compile Include="src\asn1\x509\PolicyMappings.cs" />
     <Compile Include="src\asn1\x509\PolicyQualifierId.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 0183d97ab..95a38e29b 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -429,6 +429,7 @@
     <Compile Include="src\asn1\x509\NameConstraints.cs" />
     <Compile Include="src\asn1\x509\NoticeReference.cs" />
     <Compile Include="src\asn1\x509\ObjectDigestInfo.cs" />
+    <Compile Include="src\asn1\x509\OtherName.cs" />
     <Compile Include="src\asn1\x509\PolicyInformation.cs" />
     <Compile Include="src\asn1\x509\PolicyMappings.cs" />
     <Compile Include="src\asn1\x509\PolicyQualifierId.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index f58ee2ec6..83f03b4ce 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -430,6 +430,7 @@
     <Compile Include="src\asn1\x509\NameConstraints.cs" />
     <Compile Include="src\asn1\x509\NoticeReference.cs" />
     <Compile Include="src\asn1\x509\ObjectDigestInfo.cs" />
+    <Compile Include="src\asn1\x509\OtherName.cs" />
     <Compile Include="src\asn1\x509\PolicyInformation.cs" />
     <Compile Include="src\asn1\x509\PolicyMappings.cs" />
     <Compile Include="src\asn1\x509\PolicyQualifierId.cs" />
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index d7034cad7..c40c55117 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -2034,6 +2034,11 @@
                     BuildAction = "Compile"
                 />
                 <File
+                    RelPath = "src\asn1\x509\OtherName.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
                     RelPath = "src\asn1\x509\PolicyInformation.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
diff --git a/crypto/src/asn1/x509/OtherName.cs b/crypto/src/asn1/x509/OtherName.cs
new file mode 100644
index 000000000..3e6a61499
--- /dev/null
+++ b/crypto/src/asn1/x509/OtherName.cs
@@ -0,0 +1,71 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The OtherName object.
+     * <pre>
+     * OtherName ::= SEQUENCE {
+     *      type-id    OBJECT IDENTIFIER,
+     *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+     * </pre>
+     */
+    public class OtherName
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier typeID;
+        private readonly Asn1Encodable value;
+
+        /**
+         * OtherName factory method.
+         * @param obj the object used to construct an instance of <code>
+         * OtherName</code>. It must be an instance of <code>OtherName
+         * </code> or <code>ASN1Sequence</code>.
+         * @return the instance of <code>OtherName</code> built from the
+         * supplied object.
+         * @throws java.lang.IllegalArgumentException if the object passed
+         * to the factory is not an instance of <code>OtherName</code> or something that
+         * can be converted into an appropriate <code>ASN1Sequence</code>.
+         */
+        public static OtherName GetInstance(object obj)
+        {
+            if (obj is OtherName)
+                return (OtherName)obj;
+            if (obj == null)
+                return null;
+            return new OtherName(Asn1Sequence.GetInstance(obj));
+        }
+
+        /**
+         * Base constructor.
+         * @param typeID the type of the other name.
+         * @param value the ANY object that represents the value.
+         */
+        public OtherName(DerObjectIdentifier typeID, Asn1Encodable value)
+        {
+            this.typeID = typeID;
+            this.value  = value;
+        }
+
+        private OtherName(Asn1Sequence seq)
+        {
+            this.typeID = DerObjectIdentifier.GetInstance(seq[0]);
+            this.value = DerTaggedObject.GetInstance(seq[1]).GetObject(); // explicitly tagged
+        }
+
+        public virtual DerObjectIdentifier TypeID
+        {
+            get { return typeID; }
+        }
+
+        public Asn1Encodable Value
+        {
+            get { return value; }
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(typeID, new DerTaggedObject(true, 0, value));
+        }
+    }
+}
diff --git a/crypto/src/pkix/PkixNameConstraintValidator.cs b/crypto/src/pkix/PkixNameConstraintValidator.cs
index fbec6fb72..dbf7625c6 100644
--- a/crypto/src/pkix/PkixNameConstraintValidator.cs
+++ b/crypto/src/pkix/PkixNameConstraintValidator.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections;
+using System.IO;
 
 using Org.BouncyCastle.Asn1;
 using Org.BouncyCastle.Asn1.X500;
@@ -7,6 +8,7 @@ using Org.BouncyCastle.Asn1.X500.Style;
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Utilities;
 using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
 
 namespace Org.BouncyCastle.Pkix
 {
@@ -26,6 +28,8 @@ namespace Org.BouncyCastle.Pkix
 
         private ISet excludedSubtreesIP = new HashSet();
 
+        private ISet excludedSubtreesOtherName = new HashSet();
+
         private ISet permittedSubtreesDN;
 
         private ISet permittedSubtreesDNS;
@@ -36,6 +40,8 @@ namespace Org.BouncyCastle.Pkix
 
         private ISet permittedSubtreesIP;
 
+        private ISet permittedSubtreesOtherName;
+
         public PkixNameConstraintValidator()
         {
         }
@@ -91,97 +97,42 @@ namespace Org.BouncyCastle.Pkix
             return true;
         }
 
-        public void CheckPermittedDN(Asn1Sequence dns)
-        //throws PkixNameConstraintValidatorException
-        {
-            CheckPermittedDN(permittedSubtreesDN, dns);
-        }
-
-        public void CheckExcludedDN(Asn1Sequence dns)
-        //throws PkixNameConstraintValidatorException
+        public void CheckPermittedDN(Asn1Sequence dn)
         {
-            CheckExcludedDN(excludedSubtreesDN, dns);
+            CheckPermittedDirectory(permittedSubtreesDN, dn);
         }
 
-        private void CheckPermittedDN(ISet permitted, Asn1Sequence dns)
-        //throws PkixNameConstraintValidatorException
-        {
-            if (permitted == null)
-            {
-                return;
-            }
-
-            if ((permitted.Count == 0) && dns.Count == 0)
-            {
-                return;
-            }
-
-            IEnumerator it = permitted.GetEnumerator();
-
-            while (it.MoveNext())
-            {
-                Asn1Sequence subtree = (Asn1Sequence)it.Current;
-
-                if (WithinDNSubtree(dns, subtree))
-                {
-                    return;
-                }
-            }
-
-            throw new PkixNameConstraintValidatorException(
-                "Subject distinguished name is not from a permitted subtree");
-        }
-
-        private void CheckExcludedDN(ISet excluded, Asn1Sequence dns)
-        //throws PkixNameConstraintValidatorException
+        public void CheckExcludedDN(Asn1Sequence dn)
         {
-            if (excluded.IsEmpty)
-            {
-                return;
-            }
-
-            IEnumerator it = excluded.GetEnumerator();
-
-            while (it.MoveNext())
-            {
-                Asn1Sequence subtree = (Asn1Sequence)it.Current;
-
-                if (WithinDNSubtree(dns, subtree))
-                {
-                    throw new PkixNameConstraintValidatorException(
-                        "Subject distinguished name is from an excluded subtree");
-                }
-            }
+            CheckExcludedDirectory(excludedSubtreesDN, dn);
         }
 
         private ISet IntersectDN(ISet permitted, ISet dns)
         {
             ISet intersect = new HashSet();
-            for (IEnumerator it = dns.GetEnumerator(); it.MoveNext(); )
+            foreach (GeneralSubtree subtree1 in dns)
             {
-                Asn1Sequence dn = Asn1Sequence.GetInstance(((GeneralSubtree)it
-                    .Current).Base.Name.ToAsn1Object());
+                Asn1Sequence dn1 = Asn1Sequence.GetInstance(subtree1.Base.Name);
                 if (permitted == null)
                 {
-                    if (dn != null)
+                    if (dn1 != null)
                     {
-                        intersect.Add(dn);
+                        intersect.Add(dn1);
                     }
                 }
                 else
                 {
-                    IEnumerator _iter = permitted.GetEnumerator();
-                    while (_iter.MoveNext())
+                    foreach (object obj2 in permitted)
                     {
-                        Asn1Sequence subtree = (Asn1Sequence)_iter.Current;
+                        Asn1Sequence dn2 = Asn1Sequence.GetInstance(obj2);
 
-                        if (WithinDNSubtree(dn, subtree))
+                        if (WithinDNSubtree(dn1, dn2))
                         {
-                            intersect.Add(dn);
+                            intersect.Add(dn1);
                         }
-                        else if (WithinDNSubtree(subtree, dn))
+                        else if (WithinDNSubtree(dn2, dn1))
                         {
-                            intersect.Add(subtree);
+                            intersect.Add(dn2);
                         }
                     }
                 }
@@ -194,48 +145,87 @@ namespace Org.BouncyCastle.Pkix
             if (excluded.IsEmpty)
             {
                 if (dn == null)
-                {
                     return excluded;
-                }
-                excluded.Add(dn);
 
+                excluded.Add(dn);
                 return excluded;
             }
             else
             {
-                ISet intersect = new HashSet();
+                ISet union = new HashSet();
 
-                IEnumerator it = excluded.GetEnumerator();
-                while (it.MoveNext())
+                foreach (object obj in excluded)
                 {
-                    Asn1Sequence subtree = (Asn1Sequence)it.Current;
+                    Asn1Sequence subtree = Asn1Sequence.GetInstance(obj);
 
                     if (WithinDNSubtree(dn, subtree))
                     {
-                        intersect.Add(subtree);
+                        union.Add(subtree);
                     }
                     else if (WithinDNSubtree(subtree, dn))
                     {
-                        intersect.Add(dn);
+                        union.Add(dn);
                     }
                     else
                     {
-                        intersect.Add(subtree);
-                        intersect.Add(dn);
+                        union.Add(subtree);
+                        union.Add(dn);
+                    }
+                }
+
+                return union;
+            }
+        }
+
+        private ISet IntersectOtherName(ISet permitted, ISet otherNames)
+        {
+            ISet intersect = new HashSet();
+            foreach (GeneralSubtree subtree1 in otherNames)
+            {
+                OtherName otherName1 = OtherName.GetInstance(subtree1.Base.Name);
+                if (otherName1 == null)
+                    continue;
+
+                if (permitted == null)
+                {
+                    intersect.Add(otherName1);
+                }
+                else
+                {
+                    foreach (object obj2 in permitted)
+                    {
+                        OtherName otherName2 = OtherName.GetInstance(obj2);
+                        if (otherName2 == null)
+                            continue;
+
+                        IntersectOtherName(otherName1, otherName2, intersect);
                     }
                 }
+            }
+            return intersect;
+        }
 
-                return intersect;
+        private void IntersectOtherName(OtherName otherName1, OtherName otherName2, ISet intersect)
+        {
+            if (otherName1.Equals(otherName2))
+            {
+                intersect.Add(otherName1);
             }
         }
 
+        private ISet UnionOtherName(ISet permitted, OtherName otherName)
+        {
+            ISet union = permitted != null ? new HashSet(permitted) : new HashSet();
+            union.Add(otherName);
+            return union;
+        }
+
         private ISet IntersectEmail(ISet permitted, ISet emails)
         {
             ISet intersect = new HashSet();
-            for (IEnumerator it = emails.GetEnumerator(); it.MoveNext(); )
+            foreach (GeneralSubtree subtree1 in emails)
             {
-                string email = ExtractNameAsString(((GeneralSubtree)it.Current)
-                    .Base);
+                string email = ExtractNameAsString(subtree1.Base);
 
                 if (permitted == null)
                 {
@@ -246,12 +236,9 @@ namespace Org.BouncyCastle.Pkix
                 }
                 else
                 {
-                    IEnumerator it2 = permitted.GetEnumerator();
-                    while (it2.MoveNext())
+                    foreach (string _permitted in permitted)
                     {
-                        string _permitted = (string)it2.Current;
-
-                        intersectEmail(email, _permitted, intersect);
+                        IntersectEmail(email, _permitted, intersect);
                     }
                 }
             }
@@ -272,15 +259,10 @@ namespace Org.BouncyCastle.Pkix
             else
             {
                 ISet union = new HashSet();
-
-                IEnumerator it = excluded.GetEnumerator();
-                while (it.MoveNext())
+                foreach (string _excluded in excluded)
                 {
-                    string _excluded = (string)it.Current;
-
                     UnionEmail(_excluded, email, union);
                 }
-
                 return union;
             }
         }
@@ -298,10 +280,9 @@ namespace Org.BouncyCastle.Pkix
         private ISet IntersectIP(ISet permitted, ISet ips)
         {
             ISet intersect = new HashSet();
-            for (IEnumerator it = ips.GetEnumerator(); it.MoveNext(); )
+            foreach (GeneralSubtree subtree in ips)
             {
-                byte[] ip = Asn1OctetString.GetInstance(
-                    ((GeneralSubtree)it.Current).Base.Name).GetOctets();
+                byte[] ip = Asn1OctetString.GetInstance(subtree.Base.Name).GetOctets();
                 if (permitted == null)
                 {
                     if (ip != null)
@@ -311,10 +292,8 @@ namespace Org.BouncyCastle.Pkix
                 }
                 else
                 {
-                    IEnumerator it2 = permitted.GetEnumerator();
-                    while (it2.MoveNext())
+                    foreach (byte[] _permitted in permitted)
                     {
-                        byte[] _permitted = (byte[])it2.Current;
                         intersect.AddAll(IntersectIPRange(_permitted, ip));
                     }
                 }
@@ -347,14 +326,10 @@ namespace Org.BouncyCastle.Pkix
             else
             {
                 ISet union = new HashSet();
-
-                IEnumerator it = excluded.GetEnumerator();
-                while (it.MoveNext())
+                foreach (byte[] _excluded in excluded)
                 {
-                    byte[] _excluded = (byte[])it.Current;
                     union.AddAll(UnionIPRange(_excluded, ip));
                 }
-
                 return union;
             }
         }
@@ -369,9 +344,8 @@ namespace Org.BouncyCastle.Pkix
         private ISet UnionIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
         {
             ISet set = new HashSet();
-
             // difficult, adding always all IPs is not wrong
-            if (Org.BouncyCastle.Utilities.Arrays.AreEqual(ipWithSubmask1, ipWithSubmask2))
+            if (Arrays.AreEqual(ipWithSubmask1, ipWithSubmask2))
             {
                 set.Add(ipWithSubmask1);
             }
@@ -392,41 +366,41 @@ namespace Org.BouncyCastle.Pkix
          *         mask as a byte array or an empty <code>Set</code>.
          */
         private ISet IntersectIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
-    {
-        if (ipWithSubmask1.Length != ipWithSubmask2.Length)
         {
-            //Collections.EMPTY_SET;
-            return new HashSet();
-        }
+            if (ipWithSubmask1.Length != ipWithSubmask2.Length)
+            {
+                //Collections.EMPTY_SET;
+                return new HashSet();
+            }
 
-        byte[][] temp = ExtractIPsAndSubnetMasks(ipWithSubmask1, ipWithSubmask2);
-        byte[] ip1 = temp[0];
-        byte[] subnetmask1 = temp[1];
-        byte[] ip2 = temp[2];
-        byte[] subnetmask2 = temp[3];
+            byte[][] temp = ExtractIPsAndSubnetMasks(ipWithSubmask1, ipWithSubmask2);
+            byte[] ip1 = temp[0];
+            byte[] subnetmask1 = temp[1];
+            byte[] ip2 = temp[2];
+            byte[] subnetmask2 = temp[3];
 
-        byte[][] minMax = MinMaxIPs(ip1, subnetmask1, ip2, subnetmask2);
-        byte[] min;
-        byte[] max;
-        max = Min(minMax[1], minMax[3]);
-        min = Max(minMax[0], minMax[2]);
+            byte[][] minMax = MinMaxIPs(ip1, subnetmask1, ip2, subnetmask2);
+            byte[] min;
+            byte[] max;
+            max = Min(minMax[1], minMax[3]);
+            min = Max(minMax[0], minMax[2]);
 
-        // minimum IP address must be bigger than max
-        if (CompareTo(min, max) == 1)
-        {
-            //return Collections.EMPTY_SET;
-            return new HashSet();
-        }
-        // OR keeps all significant bits
-        byte[] ip = Or(minMax[0], minMax[2]);
-        byte[] subnetmask = Or(subnetmask1, subnetmask2);
+            // minimum IP address must be bigger than max
+            if (CompareTo(min, max) == 1)
+            {
+                //return Collections.EMPTY_SET;
+                return new HashSet();
+            }
+            // OR keeps all significant bits
+            byte[] ip = Or(minMax[0], minMax[2]);
+            byte[] subnetmask = Or(subnetmask1, subnetmask2);
 
-            //return new HashSet( ICollectionsingleton(IpWithSubnetMask(ip, subnetmask));
-        ISet hs = new HashSet();
-        hs.Add(IpWithSubnetMask(ip, subnetmask));
+                //return new HashSet( ICollectionsingleton(IpWithSubnetMask(ip, subnetmask));
+            ISet hs = new HashSet();
+            hs.Add(IpWithSubnetMask(ip, subnetmask));
 
             return hs;
-    }
+        }
 
         /**
          * Concatenates the IP address with its subnet mask.
@@ -455,20 +429,19 @@ namespace Org.BouncyCastle.Pkix
         private byte[][] ExtractIPsAndSubnetMasks(
             byte[] ipWithSubmask1,
             byte[] ipWithSubmask2)
-    {
-        int ipLength = ipWithSubmask1.Length / 2;
-        byte[] ip1 = new byte[ipLength];
-        byte[] subnetmask1 = new byte[ipLength];
-        Array.Copy(ipWithSubmask1, 0, ip1, 0, ipLength);
-        Array.Copy(ipWithSubmask1, ipLength, subnetmask1, 0, ipLength);
-
-        byte[] ip2 = new byte[ipLength];
-        byte[] subnetmask2 = new byte[ipLength];
-        Array.Copy(ipWithSubmask2, 0, ip2, 0, ipLength);
-        Array.Copy(ipWithSubmask2, ipLength, subnetmask2, 0, ipLength);
-        return new byte[][]
-            {ip1, subnetmask1, ip2, subnetmask2};
-    }
+        {
+            int ipLength = ipWithSubmask1.Length / 2;
+            byte[] ip1 = new byte[ipLength];
+            byte[] subnetmask1 = new byte[ipLength];
+            Array.Copy(ipWithSubmask1, 0, ip1, 0, ipLength);
+            Array.Copy(ipWithSubmask1, ipLength, subnetmask1, 0, ipLength);
+
+            byte[] ip2 = new byte[ipLength];
+            byte[] subnetmask2 = new byte[ipLength];
+            Array.Copy(ipWithSubmask2, 0, ip2, 0, ipLength);
+            Array.Copy(ipWithSubmask2, ipLength, subnetmask2, 0, ipLength);
+            return new byte[][]{ ip1, subnetmask1, ip2, subnetmask2 };
+        }
 
         /**
          * Based on the two IP addresses and their subnet masks the IP range is
@@ -505,126 +478,214 @@ namespace Org.BouncyCastle.Pkix
                 max2[i] = (byte)(ip2[i] & subnetmask2[i] | ~subnetmask2[i]);
             }
 
-            return new byte[][] { min1, max1, min2, max2 };
+            return new byte[][]{ min1, max1, min2, max2 };
         }
 
-        private void CheckPermittedEmail(ISet permitted, string email)
-        //throws PkixNameConstraintValidatorException
+        private bool IsOtherNameConstrained(OtherName constraint, OtherName otherName)
+        {
+            return constraint.Equals(otherName);
+        }
+
+        private bool IsOtherNameConstrained(ISet constraints, OtherName otherName)
         {
-            if (permitted == null)
+            foreach (object obj in constraints)
             {
-                return;
+                OtherName constraint = OtherName.GetInstance(obj);
+
+                if (IsOtherNameConstrained(constraint, otherName))
+                    return true;
             }
 
-            IEnumerator it = permitted.GetEnumerator();
+            return false;
+        }
+
+        private void CheckPermittedOtherName(ISet permitted, OtherName name)
+        {
+            if (permitted != null && !IsOtherNameConstrained(permitted, name))
+            {
+                throw new PkixNameConstraintValidatorException(
+                    "Subject OtherName is not from a permitted subtree.");
+            }
+        }
 
-            while (it.MoveNext())
+        private void CheckExcludedOtherName(ISet excluded, OtherName name)
+        {
+            if (IsOtherNameConstrained(excluded, name))
             {
-                string str = ((string)it.Current);
+                throw new PkixNameConstraintValidatorException(
+                    "OtherName is from an excluded subtree.");
+            }
+        }
 
-                if (EmailIsConstrained(email, str))
+        private bool IsEmailConstrained(string constraint, string email)
+        {
+            string sub = email.Substring(email.IndexOf('@') + 1);
+            // a particular mailbox
+            if (constraint.IndexOf('@') != -1)
+            {
+                if (Platform.ToUpperInvariant(email).Equals(Platform.ToUpperInvariant(constraint)))
                 {
-                    return;
+                    return true;
                 }
             }
+            // on particular host
+            else if (!(constraint[0].Equals('.')))
+            {
+                if (Platform.ToUpperInvariant(sub).Equals(Platform.ToUpperInvariant(constraint)))
+                {
+                    return true;
+                }
+            }
+            // address in sub domain
+            else if (WithinDomain(sub, constraint))
+            {
+                return true;
+            }
+            return false;
+        }
 
-            if (email.Length == 0 && permitted.Count == 0)
+        private bool IsEmailConstrained(ISet constraints, string email)
+        {
+            foreach (string constraint in constraints)
             {
-                return;
+                if (IsEmailConstrained(constraint, email))
+                    return true;
             }
 
-            throw new PkixNameConstraintValidatorException(
-                "Subject email address is not from a permitted subtree.");
+            return false;
+        }
+
+        private void CheckPermittedEmail(ISet permitted, string email)
+        {
+            if (permitted != null
+                && !(email.Length == 0 && permitted.IsEmpty)
+                && !IsEmailConstrained(permitted, email))
+            {
+                throw new PkixNameConstraintValidatorException(
+                    "Subject email address is not from a permitted subtree.");
+            }
         }
 
         private void CheckExcludedEmail(ISet excluded, string email)
-        //throws PkixNameConstraintValidatorException
         {
-            if (excluded.IsEmpty)
+            if (IsEmailConstrained(excluded, email))
             {
-                return;
+                throw new PkixNameConstraintValidatorException(
+                    "Email address is from an excluded subtree.");
             }
+        }
 
-            IEnumerator it = excluded.GetEnumerator();
+        private bool IsDnsConstrained(string constraint, string dns)
+        {
+            return WithinDomain(dns, constraint) || Platform.EqualsIgnoreCase(dns, constraint);
+        }
 
-            while (it.MoveNext())
+        private bool IsDnsConstrained(ISet constraints, string dns)
+        {
+            foreach (string constraint in constraints)
             {
-                string str = (string)it.Current;
+                if (IsDnsConstrained(constraint, dns))
+                    return true;
+            }
 
-                if (EmailIsConstrained(email, str))
-                {
-                    throw new PkixNameConstraintValidatorException(
-                        "Email address is from an excluded subtree.");
-                }
+            return false;
+        }
+
+        private void CheckPermittedDns(ISet permitted, string dns)
+        {
+            if (permitted != null
+                && !(dns.Length == 0 && permitted.IsEmpty)
+                && !IsDnsConstrained(permitted, dns))
+            {
+                throw new PkixNameConstraintValidatorException(
+                    "DNS is not from a permitted subtree.");
             }
         }
 
-        /**
-         * Checks if the IP <code>ip</code> is included in the permitted ISet
-         * <code>permitted</code>.
-         *
-         * @param permitted A <code>Set</code> of permitted IP addresses with
-         *                  their subnet mask as byte arrays.
-         * @param ip        The IP address.
-         * @throws PkixNameConstraintValidatorException
-         *          if the IP is not permitted.
-         */
-        private void CheckPermittedIP(ISet permitted, byte[] ip)
-        //throws PkixNameConstraintValidatorException
+        private void CheckExcludedDns(ISet excluded, string dns)
+        {
+            if (IsDnsConstrained(excluded, dns))
+            {
+                throw new PkixNameConstraintValidatorException(
+                    "DNS is from an excluded subtree.");
+            }
+        }
+
+        private bool IsDirectoryConstrained(ISet constraints, Asn1Sequence directory)
         {
-            if (permitted == null)
+            foreach (object obj in constraints)
             {
-                return;
+                Asn1Sequence constraint = Asn1Sequence.GetInstance(obj);
+
+                if (WithinDNSubtree(directory, constraint))
+                    return true;
             }
 
-            IEnumerator it = permitted.GetEnumerator();
+            return false;
+        }
 
-            while (it.MoveNext())
+        private void CheckPermittedDirectory(ISet permitted, Asn1Sequence directory)
+        {
+            if (permitted != null
+                && !(directory.Count == 0 && permitted.IsEmpty)
+                && !IsDirectoryConstrained(permitted, directory))
             {
-                byte[] ipWithSubnet = (byte[])it.Current;
+                throw new PkixNameConstraintValidatorException(
+                    "Subject distinguished name is not from a permitted subtree");
+            }
+        }
 
-                if (IsIPConstrained(ip, ipWithSubnet))
-                {
-                    return;
-                }
+        private void CheckExcludedDirectory(ISet excluded, Asn1Sequence directory)
+        {
+            if (IsDirectoryConstrained(excluded, directory))
+            {
+                throw new PkixNameConstraintValidatorException(
+                    "Subject distinguished name is from an excluded subtree");
             }
-            if (ip.Length == 0 && permitted.Count == 0)
+        }
+
+        private bool IsUriConstrained(string constraint, string uri)
+        {
+            string host = ExtractHostFromURL(uri);
+
+            if (Platform.StartsWith(constraint, "."))
             {
-                return;
+                // in sub domain or domain
+                return WithinDomain(host, constraint);
             }
-            throw new PkixNameConstraintValidatorException(
-                "IP is not from a permitted subtree.");
+
+            // a host
+            return Platform.EqualsIgnoreCase(host, constraint);
         }
 
-        /**
-         * Checks if the IP <code>ip</code> is included in the excluded ISet
-         * <code>excluded</code>.
-         *
-         * @param excluded A <code>Set</code> of excluded IP addresses with their
-         *                 subnet mask as byte arrays.
-         * @param ip       The IP address.
-         * @throws PkixNameConstraintValidatorException
-         *          if the IP is excluded.
-         */
-        private void CheckExcludedIP(ISet excluded, byte[] ip)
-        //throws PkixNameConstraintValidatorException
+        private bool IsUriConstrained(ISet constraints, string uri)
         {
-            if (excluded.IsEmpty)
+            foreach (string constraint in constraints)
             {
-                return;
+                if (IsUriConstrained(constraint, uri))
+                    return true;
             }
 
-            IEnumerator it = excluded.GetEnumerator();
+            return false;
+        }
 
-            while (it.MoveNext())
+        private void CheckPermittedUri(ISet permitted, string uri)
+        {
+            if (permitted != null
+                && !(uri.Length == 0 && permitted.IsEmpty)
+                && !IsUriConstrained(permitted, uri))
             {
-                byte[] ipWithSubnet = (byte[])it.Current;
+                throw new PkixNameConstraintValidatorException(
+                    "URI is not from a permitted subtree.");
+            }
+        }
 
-                if (IsIPConstrained(ip, ipWithSubnet))
-                {
-                    throw new PkixNameConstraintValidatorException(
-                        "IP is from an excluded subtree.");
-                }
+        private void CheckExcludedUri(ISet excluded, string uri)
+        {
+            if (IsUriConstrained(excluded, uri))
+            {
+                throw new PkixNameConstraintValidatorException(
+                    "URI is from an excluded subtree.");
             }
         }
 
@@ -632,16 +693,15 @@ namespace Org.BouncyCastle.Pkix
          * Checks if the IP address <code>ip</code> is constrained by
          * <code>constraint</code>.
          *
-         * @param ip         The IP address.
          * @param constraint The constraint. This is an IP address concatenated with
          *                   its subnetmask.
+         * @param ip         The IP address.
          * @return <code>true</code> if constrained, <code>false</code>
          *         otherwise.
          */
-        private bool IsIPConstrained(byte[] ip, byte[] constraint)
+        private bool IsIPConstrained(byte[] constraint, byte[] ip)
         {
             int ipLength = ip.Length;
-
             if (ipLength != (constraint.Length / 2))
             {
                 return false;
@@ -661,34 +721,58 @@ namespace Org.BouncyCastle.Pkix
                 ipSubnetAddress[i] = (byte)(ip[i] & subnetMask[i]);
             }
 
-            return Org.BouncyCastle.Utilities.Arrays.AreEqual(permittedSubnetAddress, ipSubnetAddress);
+            return Arrays.AreEqual(permittedSubnetAddress, ipSubnetAddress);
         }
 
-        private bool EmailIsConstrained(string email, string constraint)
+        private bool IsIPConstrained(ISet constraints, byte[] ip)
         {
-            string sub = email.Substring(email.IndexOf('@') + 1);
-            // a particular mailbox
-            if (constraint.IndexOf('@') != -1)
+            foreach (byte[] constraint in constraints)
             {
-                if (Platform.ToUpperInvariant(email).Equals(Platform.ToUpperInvariant(constraint)))
-                {
+                if (IsIPConstrained(constraint, ip))
                     return true;
-                }
             }
-            // on particular host
-            else if (!(constraint[0].Equals('.')))
+
+            return false;
+        }
+
+        /**
+         * Checks if the IP <code>ip</code> is included in the permitted ISet
+         * <code>permitted</code>.
+         *
+         * @param permitted A <code>Set</code> of permitted IP addresses with
+         *                  their subnet mask as byte arrays.
+         * @param ip        The IP address.
+         * @throws PkixNameConstraintValidatorException
+         *          if the IP is not permitted.
+         */
+        private void CheckPermittedIP(ISet permitted, byte[] ip)
+        {
+            if (permitted != null
+                && !(ip.Length == 0 && permitted.IsEmpty)
+                && !IsIPConstrained(permitted, ip))
             {
-                if (Platform.ToUpperInvariant(sub).Equals(Platform.ToUpperInvariant(constraint)))
-                {
-                    return true;
-                }
+                throw new PkixNameConstraintValidatorException(
+                    "IP is not from a permitted subtree.");
             }
-            // address in sub domain
-            else if (WithinDomain(sub, constraint))
+        }
+
+        /**
+         * Checks if the IP <code>ip</code> is included in the excluded ISet
+         * <code>excluded</code>.
+         *
+         * @param excluded A <code>Set</code> of excluded IP addresses with their
+         *                 subnet mask as byte arrays.
+         * @param ip       The IP address.
+         * @throws PkixNameConstraintValidatorException
+         *          if the IP is excluded.
+         */
+        private void CheckExcludedIP(ISet excluded, byte[] ip)
+        {
+            if (IsIPConstrained(excluded, ip))
             {
-                return true;
+                throw new PkixNameConstraintValidatorException(
+                    "IP is from an excluded subtree.");
             }
-            return false;
         }
 
         private bool WithinDomain(string testDomain, string domain)
@@ -724,36 +808,6 @@ namespace Org.BouncyCastle.Pkix
             return true;
         }
 
-        private void CheckPermittedDns(ISet permitted, string dns)
-            //throws PkixNameConstraintValidatorException
-        {
-            if (null == permitted)
-                return;
-
-            foreach (string str in permitted)
-            {
-                // is sub domain or the same
-                if (WithinDomain(dns, str) || Platform.EqualsIgnoreCase(dns, str))
-                    return;
-            }
-
-            if (dns.Length == 0 && permitted.Count == 0)
-                return;
-
-            throw new PkixNameConstraintValidatorException("DNS is not from a permitted subtree.");
-        }
-
-        private void CheckExcludedDns(ISet excluded, string dns)
-            //throws PkixNameConstraintValidatorException
-        {
-            foreach (string str in excluded)
-            {
-                // is sub domain or the same
-				if (WithinDomain(dns, str) || Platform.EqualsIgnoreCase(dns, str))
-                    throw new PkixNameConstraintValidatorException("DNS is from an excluded subtree.");
-            }
-        }
-
         /**
          * The common part of <code>email1</code> and <code>email2</code> is
          * added to the union <code>union</code>. If <code>email1</code> and
@@ -1038,13 +1092,12 @@ namespace Org.BouncyCastle.Pkix
             }
         }
 
-        private ISet intersectDNS(ISet permitted, ISet dnss)
+        private ISet IntersectDns(ISet permitted, ISet dnss)
         {
             ISet intersect = new HashSet();
-            for (IEnumerator it = dnss.GetEnumerator(); it.MoveNext(); )
+            foreach (GeneralSubtree subtree in dnss)
             {
-                string dns = ExtractNameAsString(((GeneralSubtree)it.Current)
-                    .Base);
+                string dns = ExtractNameAsString(subtree.Base);
                 if (permitted == null)
                 {
                     if (dns != null)
@@ -1054,11 +1107,8 @@ namespace Org.BouncyCastle.Pkix
                 }
                 else
                 {
-                    IEnumerator _iter = permitted.GetEnumerator();
-                    while (_iter.MoveNext())
+                    foreach (string _permitted in permitted)
                     {
-                        string _permitted = (string)_iter.Current;
-
                         if (WithinDomain(_permitted, dns))
                         {
                             intersect.Add(_permitted);
@@ -1074,42 +1124,35 @@ namespace Org.BouncyCastle.Pkix
             return intersect;
         }
 
-        protected ISet unionDNS(ISet excluded, string dns)
+        private ISet UnionDns(ISet excluded, string dns)
         {
             if (excluded.IsEmpty)
             {
                 if (dns == null)
-                {
                     return excluded;
-                }
-                excluded.Add(dns);
 
+                excluded.Add(dns);
                 return excluded;
             }
             else
             {
                 ISet union = new HashSet();
-
-                IEnumerator _iter = excluded.GetEnumerator();
-                while (_iter.MoveNext())
+                foreach (string _excluded in excluded)
                 {
-                    string _permitted = (string)_iter.Current;
-
-                    if (WithinDomain(_permitted, dns))
+                    if (WithinDomain(_excluded, dns))
                     {
                         union.Add(dns);
                     }
-                    else if (WithinDomain(dns, _permitted))
+                    else if (WithinDomain(dns, _excluded))
                     {
-                        union.Add(_permitted);
+                        union.Add(_excluded);
                     }
                     else
                     {
-                        union.Add(_permitted);
+                        union.Add(_excluded);
                         union.Add(dns);
                     }
                 }
-
                 return union;
             }
         }
@@ -1122,7 +1165,7 @@ namespace Org.BouncyCastle.Pkix
          * @param email2    Email address constraint 2.
          * @param intersect The intersection.
          */
-        private void intersectEmail(string email1, string email2, ISet intersect)
+        private void IntersectEmail(string email1, string email2, ISet intersect)
         {
             // email1 is a particular address
             if (email1.IndexOf('@') != -1)
@@ -1214,35 +1257,12 @@ namespace Org.BouncyCastle.Pkix
             }
         }
 
-        private void checkExcludedURI(ISet excluded, string uri)
-        //       throws PkixNameConstraintValidatorException
-        {
-            if (excluded.IsEmpty)
-            {
-                return;
-            }
-
-            IEnumerator it = excluded.GetEnumerator();
-
-            while (it.MoveNext())
-            {
-                string str = ((string)it.Current);
-
-                if (IsUriConstrained(uri, str))
-                {
-                    throw new PkixNameConstraintValidatorException(
-                        "URI is from an excluded subtree.");
-                }
-            }
-        }
-
-        private ISet intersectURI(ISet permitted, ISet uris)
+        private ISet IntersectUri(ISet permitted, ISet uris)
         {
             ISet intersect = new HashSet();
-            for (IEnumerator it = uris.GetEnumerator(); it.MoveNext(); )
+            foreach (GeneralSubtree subtree in uris)
             {
-                string uri = ExtractNameAsString(((GeneralSubtree)it.Current)
-                    .Base);
+                string uri = ExtractNameAsString(subtree.Base);
                 if (permitted == null)
                 {
                     if (uri != null)
@@ -1252,46 +1272,37 @@ namespace Org.BouncyCastle.Pkix
                 }
                 else
                 {
-                    IEnumerator _iter = permitted.GetEnumerator();
-                    while (_iter.MoveNext())
+                    foreach (string _permitted in permitted)
                     {
-                        string _permitted = (string)_iter.Current;
-                        intersectURI(_permitted, uri, intersect);
+                        IntersectUri(_permitted, uri, intersect);
                     }
                 }
             }
             return intersect;
         }
 
-        private ISet unionURI(ISet excluded, string uri)
+        private ISet UnionUri(ISet excluded, string uri)
         {
             if (excluded.IsEmpty)
             {
                 if (uri == null)
-                {
                     return excluded;
-                }
-                excluded.Add(uri);
 
+                excluded.Add(uri);
                 return excluded;
             }
             else
             {
                 ISet union = new HashSet();
-
-                IEnumerator _iter = excluded.GetEnumerator();
-                while (_iter.MoveNext())
+                foreach (string _excluded in excluded)
                 {
-                    string _excluded = (string)_iter.Current;
-
                     unionURI(_excluded, uri, union);
                 }
-
                 return union;
             }
         }
 
-        private void intersectURI(string email1, string email2, ISet intersect)
+        private void IntersectUri(string email1, string email2, ISet intersect)
         {
             // email1 is a particular address
             if (email1.IndexOf('@') != -1)
@@ -1383,54 +1394,6 @@ namespace Org.BouncyCastle.Pkix
             }
         }
 
-        private void CheckPermittedURI(ISet permitted, string uri)
-        //        throws PkixNameConstraintValidatorException
-        {
-            if (permitted == null)
-            {
-                return;
-            }
-
-            IEnumerator it = permitted.GetEnumerator();
-
-            while (it.MoveNext())
-            {
-                string str = ((string)it.Current);
-
-                if (IsUriConstrained(uri, str))
-                {
-                    return;
-                }
-            }
-            if (uri.Length == 0 && permitted.Count == 0)
-            {
-                return;
-            }
-            throw new PkixNameConstraintValidatorException(
-                "URI is not from a permitted subtree.");
-        }
-
-        private bool IsUriConstrained(string uri, string constraint)
-        {
-            string host = ExtractHostFromURL(uri);
-            // a host
-            if (!Platform.StartsWith(constraint, "."))
-            {
-                if (Platform.EqualsIgnoreCase(host, constraint))
-                {
-                    return true;
-                }
-            }
-
-            // in sub domain or domain
-            else if (WithinDomain(host, constraint))
-            {
-                return true;
-            }
-
-            return false;
-        }
-
         private static string ExtractHostFromURL(string url)
         {
             // see RFC 1738
@@ -1466,30 +1429,28 @@ namespace Org.BouncyCastle.Pkix
          *          If the <code>name</code>
          */
         public void checkPermitted(GeneralName name)
-        //        throws PkixNameConstraintValidatorException
+        //throws PkixNameConstraintValidatorException
         {
             switch (name.TagNo)
             {
-                case 1:
-                    CheckPermittedEmail(permittedSubtreesEmail,
-                        ExtractNameAsString(name));
-                    break;
-                case 2:
-                    CheckPermittedDns(permittedSubtreesDNS, DerIA5String.GetInstance(
-                        name.Name).GetString());
-                    break;
-                case 4:
-                    CheckPermittedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
-                    break;
-                case 6:
-                    CheckPermittedURI(permittedSubtreesURI, DerIA5String.GetInstance(
-                        name.Name).GetString());
-                    break;
-                case 7:
-                    byte[] ip = Asn1OctetString.GetInstance(name.Name).GetOctets();
-
-                    CheckPermittedIP(permittedSubtreesIP, ip);
-                    break;
+            case GeneralName.OtherName:
+                CheckPermittedOtherName(permittedSubtreesOtherName, OtherName.GetInstance(name.Name));
+                break;
+            case GeneralName.Rfc822Name:
+                CheckPermittedEmail(permittedSubtreesEmail, ExtractNameAsString(name));
+                break;
+            case GeneralName.DnsName:
+                CheckPermittedDns(permittedSubtreesDNS, ExtractNameAsString(name));
+                break;
+            case GeneralName.DirectoryName:
+                CheckPermittedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
+                break;
+            case GeneralName.UniformResourceIdentifier:
+                CheckPermittedUri(permittedSubtreesURI, ExtractNameAsString(name));
+                break;
+            case GeneralName.IPAddress:
+                CheckPermittedIP(permittedSubtreesIP, Asn1OctetString.GetInstance(name.Name).GetOctets());
+                break;
             }
         }
 
@@ -1502,29 +1463,28 @@ namespace Org.BouncyCastle.Pkix
          *          excluded.
          */
         public void checkExcluded(GeneralName name)
-        //        throws PkixNameConstraintValidatorException
+        //throws PkixNameConstraintValidatorException
         {
             switch (name.TagNo)
             {
-                case 1:
-                    CheckExcludedEmail(excludedSubtreesEmail, ExtractNameAsString(name));
-                    break;
-                case 2:
-                    CheckExcludedDns(excludedSubtreesDNS, DerIA5String.GetInstance(
-                        name.Name).GetString());
-                    break;
-                case 4:
-                    CheckExcludedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
-                    break;
-                case 6:
-                    checkExcludedURI(excludedSubtreesURI, DerIA5String.GetInstance(
-                        name.Name).GetString());
-                    break;
-                case 7:
-                    byte[] ip = Asn1OctetString.GetInstance(name.Name).GetOctets();
-
-                    CheckExcludedIP(excludedSubtreesIP, ip);
-                    break;
+            case GeneralName.OtherName:
+                CheckExcludedOtherName(excludedSubtreesOtherName, OtherName.GetInstance(name.Name));
+                break;
+            case GeneralName.Rfc822Name:
+                CheckExcludedEmail(excludedSubtreesEmail, ExtractNameAsString(name));
+                break;
+            case GeneralName.DnsName:
+                CheckExcludedDns(excludedSubtreesDNS, ExtractNameAsString(name));
+                break;
+            case GeneralName.DirectoryName:
+                CheckExcludedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
+                break;
+            case GeneralName.UniformResourceIdentifier:
+                CheckExcludedUri(excludedSubtreesURI, ExtractNameAsString(name));
+                break;
+            case GeneralName.IPAddress:
+                CheckExcludedIP(excludedSubtreesIP, Asn1OctetString.GetInstance(name.Name).GetOctets());
+                break;
             }
         }
 
@@ -1540,9 +1500,9 @@ namespace Org.BouncyCastle.Pkix
             IDictionary subtreesMap = Platform.CreateHashtable();
 
             // group in ISets in a map ordered by tag no.
-            for (IEnumerator e = permitted.GetEnumerator(); e.MoveNext(); )
+            foreach (object obj in permitted)
             {
-                GeneralSubtree subtree = GeneralSubtree.GetInstance(e.Current);
+                GeneralSubtree subtree = GeneralSubtree.GetInstance(obj);
 
                 int tagNo = subtree.Base.TagNo;
                 if (subtreesMap[tagNo] == null)
@@ -1553,33 +1513,35 @@ namespace Org.BouncyCastle.Pkix
                 ((ISet)subtreesMap[tagNo]).Add(subtree);
             }
 
-            for (IEnumerator it = subtreesMap.GetEnumerator(); it.MoveNext(); )
+            foreach (DictionaryEntry entry in subtreesMap)
             {
-                DictionaryEntry entry = (DictionaryEntry)it.Current;
-
                 // go through all subtree groups
-                switch ((int)entry.Key )
+                switch ((int)entry.Key)
                 {
-                    case 1:
-                        permittedSubtreesEmail = IntersectEmail(permittedSubtreesEmail,
-                            (ISet)entry.Value);
-                        break;
-                    case 2:
-                        permittedSubtreesDNS = intersectDNS(permittedSubtreesDNS,
-                            (ISet)entry.Value);
-                        break;
-                    case 4:
-                        permittedSubtreesDN = IntersectDN(permittedSubtreesDN,
-                            (ISet)entry.Value);
-                        break;
-                    case 6:
-                        permittedSubtreesURI = intersectURI(permittedSubtreesURI,
-                            (ISet)entry.Value);
-                        break;
-                    case 7:
-                        permittedSubtreesIP = IntersectIP(permittedSubtreesIP,
-                            (ISet)entry.Value);
-                        break;
+                case GeneralName.OtherName:
+                    permittedSubtreesOtherName = IntersectOtherName(permittedSubtreesOtherName,
+                        (ISet)entry.Value);
+                    break;
+                case GeneralName.Rfc822Name:
+                    permittedSubtreesEmail = IntersectEmail(permittedSubtreesEmail,
+                        (ISet)entry.Value);
+                    break;
+                case GeneralName.DnsName:
+                    permittedSubtreesDNS = IntersectDns(permittedSubtreesDNS,
+                        (ISet)entry.Value);
+                    break;
+                case GeneralName.DirectoryName:
+                    permittedSubtreesDN = IntersectDN(permittedSubtreesDN,
+                        (ISet)entry.Value);
+                    break;
+                case GeneralName.UniformResourceIdentifier:
+                    permittedSubtreesURI = IntersectUri(permittedSubtreesURI,
+                        (ISet)entry.Value);
+                    break;
+                case GeneralName.IPAddress:
+                    permittedSubtreesIP = IntersectIP(permittedSubtreesIP,
+                        (ISet)entry.Value);
+                    break;
                 }
             }
         }
@@ -1593,21 +1555,24 @@ namespace Org.BouncyCastle.Pkix
         {
             switch (nameType)
             {
-                case 1:
-                    permittedSubtreesEmail = new HashSet();
-                    break;
-                case 2:
-                    permittedSubtreesDNS = new HashSet();
-                    break;
-                case 4:
-                    permittedSubtreesDN = new HashSet();
-                    break;
-                case 6:
-                    permittedSubtreesURI = new HashSet();
-                    break;
-                case 7:
-                    permittedSubtreesIP = new HashSet();
-                    break;
+            case GeneralName.OtherName:
+                permittedSubtreesOtherName = new HashSet();
+                break;
+            case GeneralName.Rfc822Name:
+                permittedSubtreesEmail = new HashSet();
+                break;
+            case GeneralName.DnsName:
+                permittedSubtreesDNS = new HashSet();
+                break;
+            case GeneralName.DirectoryName:
+                permittedSubtreesDN = new HashSet();
+                break;
+            case GeneralName.UniformResourceIdentifier:
+                permittedSubtreesURI = new HashSet();
+                break;
+            case GeneralName.IPAddress:
+                permittedSubtreesIP = new HashSet();
+                break;
             }
         }
 
@@ -1622,26 +1587,30 @@ namespace Org.BouncyCastle.Pkix
 
             switch (subTreeBase.TagNo)
             {
-                case 1:
-                    excludedSubtreesEmail = UnionEmail(excludedSubtreesEmail,
-                        ExtractNameAsString(subTreeBase));
-                    break;
-                case 2:
-                    excludedSubtreesDNS = unionDNS(excludedSubtreesDNS,
-                        ExtractNameAsString(subTreeBase));
-                    break;
-                case 4:
-                    excludedSubtreesDN = UnionDN(excludedSubtreesDN,
-                        (Asn1Sequence)subTreeBase.Name.ToAsn1Object());
-                    break;
-                case 6:
-                    excludedSubtreesURI = unionURI(excludedSubtreesURI,
-                        ExtractNameAsString(subTreeBase));
-                    break;
-                case 7:
-                    excludedSubtreesIP = UnionIP(excludedSubtreesIP, Asn1OctetString
-                        .GetInstance(subTreeBase.Name).GetOctets());
-                    break;
+            case GeneralName.OtherName:
+                excludedSubtreesOtherName = UnionOtherName(excludedSubtreesOtherName,
+                    OtherName.GetInstance(subTreeBase.Name));
+                break;
+            case GeneralName.Rfc822Name:
+                excludedSubtreesEmail = UnionEmail(excludedSubtreesEmail,
+                    ExtractNameAsString(subTreeBase));
+                break;
+            case GeneralName.DnsName:
+                excludedSubtreesDNS = UnionDns(excludedSubtreesDNS,
+                    ExtractNameAsString(subTreeBase));
+                break;
+            case GeneralName.DirectoryName:
+                excludedSubtreesDN = UnionDN(excludedSubtreesDN,
+                    (Asn1Sequence)subTreeBase.Name.ToAsn1Object());
+                break;
+            case GeneralName.UniformResourceIdentifier:
+                excludedSubtreesURI = UnionUri(excludedSubtreesURI,
+                    ExtractNameAsString(subTreeBase));
+                break;
+            case GeneralName.IPAddress:
+                excludedSubtreesIP = UnionIP(excludedSubtreesIP,
+                    Asn1OctetString.GetInstance(subTreeBase.Name).GetOctets());
+                break;
             }
         }
 
@@ -1736,27 +1705,26 @@ namespace Org.BouncyCastle.Pkix
                 + HashCollection(excludedSubtreesEmail)
                 + HashCollection(excludedSubtreesIP)
                 + HashCollection(excludedSubtreesURI)
+                + HashCollection(excludedSubtreesOtherName)
                 + HashCollection(permittedSubtreesDN)
                 + HashCollection(permittedSubtreesDNS)
                 + HashCollection(permittedSubtreesEmail)
                 + HashCollection(permittedSubtreesIP)
-                + HashCollection(permittedSubtreesURI);
+                + HashCollection(permittedSubtreesURI)
+                + HashCollection(permittedSubtreesOtherName);
         }
 
-        private int HashCollection(ICollection coll)
+        private int HashCollection(ICollection c)
         {
-            if (coll == null)
-            {
+            if (c == null)
                 return 0;
-            }
+
             int hash = 0;
-            IEnumerator it1 = coll.GetEnumerator();
-            while (it1.MoveNext())
+            foreach (Object o in c)
             {
-                Object o = it1.Current;
                 if (o is byte[])
                 {
-                    hash += Org.BouncyCastle.Utilities.Arrays.GetHashCode((byte[])o);
+                    hash += Arrays.GetHashCode((byte[])o);
                 }
                 else
                 {
@@ -1773,52 +1741,41 @@ namespace Org.BouncyCastle.Pkix
 
 			PkixNameConstraintValidator constraintValidator = (PkixNameConstraintValidator)o;
 
-			return CollectionsAreEqual(constraintValidator.excludedSubtreesDN, excludedSubtreesDN)
-				&& CollectionsAreEqual(constraintValidator.excludedSubtreesDNS, excludedSubtreesDNS)
-				&& CollectionsAreEqual(constraintValidator.excludedSubtreesEmail, excludedSubtreesEmail)
-				&& CollectionsAreEqual(constraintValidator.excludedSubtreesIP, excludedSubtreesIP)
-				&& CollectionsAreEqual(constraintValidator.excludedSubtreesURI, excludedSubtreesURI)
-				&& CollectionsAreEqual(constraintValidator.permittedSubtreesDN, permittedSubtreesDN)
-				&& CollectionsAreEqual(constraintValidator.permittedSubtreesDNS, permittedSubtreesDNS)
-				&& CollectionsAreEqual(constraintValidator.permittedSubtreesEmail, permittedSubtreesEmail)
-				&& CollectionsAreEqual(constraintValidator.permittedSubtreesIP, permittedSubtreesIP)
-				&& CollectionsAreEqual(constraintValidator.permittedSubtreesURI, permittedSubtreesURI);
+            return CollectionsAreEqual(constraintValidator.excludedSubtreesDN, excludedSubtreesDN)
+                && CollectionsAreEqual(constraintValidator.excludedSubtreesDNS, excludedSubtreesDNS)
+                && CollectionsAreEqual(constraintValidator.excludedSubtreesEmail, excludedSubtreesEmail)
+                && CollectionsAreEqual(constraintValidator.excludedSubtreesIP, excludedSubtreesIP)
+                && CollectionsAreEqual(constraintValidator.excludedSubtreesURI, excludedSubtreesURI)
+                && CollectionsAreEqual(constraintValidator.excludedSubtreesOtherName, excludedSubtreesOtherName)
+                && CollectionsAreEqual(constraintValidator.permittedSubtreesDN, permittedSubtreesDN)
+                && CollectionsAreEqual(constraintValidator.permittedSubtreesDNS, permittedSubtreesDNS)
+                && CollectionsAreEqual(constraintValidator.permittedSubtreesEmail, permittedSubtreesEmail)
+                && CollectionsAreEqual(constraintValidator.permittedSubtreesIP, permittedSubtreesIP)
+                && CollectionsAreEqual(constraintValidator.permittedSubtreesURI, permittedSubtreesURI)
+                && CollectionsAreEqual(constraintValidator.permittedSubtreesOtherName, permittedSubtreesOtherName);
 		}
 
         private bool CollectionsAreEqual(ICollection coll1, ICollection coll2)
         {
             if (coll1 == coll2)
-            {
                 return true;
-            }
-            if (coll1 == null || coll2 == null)
-            {
-                return false;
-            }
-            if (coll1.Count != coll2.Count)
-            {
+            if (coll1 == null || coll2 == null || coll1.Count != coll2.Count)
                 return false;
-            }
-            IEnumerator it1 = coll1.GetEnumerator();
 
-            while (it1.MoveNext())
+            foreach (Object a in coll1)
             {
-                Object a = it1.Current;
-                IEnumerator it2 = coll2.GetEnumerator();
                 bool found = false;
-                while (it2.MoveNext())
+                foreach (Object b in coll2)
                 {
-                    Object b = it2.Current;
                     if (SpecialEquals(a, b))
                     {
                         found = true;
                         break;
                     }
                 }
+
                 if (!found)
-                {
                     return false;
-                }
             }
             return true;
         }
@@ -1835,7 +1792,7 @@ namespace Org.BouncyCastle.Pkix
             }
             if ((o1 is byte[]) && (o2 is byte[]))
             {
-                return Org.BouncyCastle.Utilities.Arrays.AreEqual((byte[])o1, (byte[])o2);
+                return Arrays.AreEqual((byte[])o1, (byte[])o2);
             }
             else
             {
@@ -1872,16 +1829,41 @@ namespace Org.BouncyCastle.Pkix
         {
             string temp = "";
             temp += "[";
-            for (IEnumerator it = ips.GetEnumerator(); it.MoveNext(); )
+            foreach (byte[] ip in ips)
             {
-                temp += StringifyIP((byte[])it.Current) + ",";
+                temp += StringifyIP(ip) + ",";
             }
             if (temp.Length > 1)
             {
                 temp = temp.Substring(0, temp.Length - 1);
             }
             temp += "]";
+            return temp;
+        }
 
+        private string StringifyOtherNameCollection(ISet otherNames)
+        {
+            string temp = "";
+            temp += "[";
+            foreach (object obj in otherNames)
+            {
+                OtherName name = OtherName.GetInstance(obj);
+                if (temp.Length > 1)
+                {
+                    temp += ",";
+                }
+                temp += name.TypeID.Id;
+                temp += ":";
+                try
+                {
+                    temp += Hex.ToHexString(name.Value.ToAsn1Object().GetEncoded());
+                }
+                catch (IOException e)
+                {
+                    temp += e.ToString();
+                }
+            }
+            temp += "]";
             return temp;
         }
 
@@ -1915,6 +1897,11 @@ namespace Org.BouncyCastle.Pkix
                 temp += "IP:\n";
                 temp += StringifyIPCollection(permittedSubtreesIP) + "\n";
             }
+            if (permittedSubtreesOtherName != null)
+            {
+                temp += "OtherName:\n";
+                temp += StringifyOtherNameCollection(permittedSubtreesOtherName);
+            }
             temp += "excluded:\n";
             if (!(excludedSubtreesDN.IsEmpty))
             {
@@ -1941,8 +1928,12 @@ namespace Org.BouncyCastle.Pkix
                 temp += "IP:\n";
                 temp += StringifyIPCollection(excludedSubtreesIP) + "\n";
             }
+            if (!excludedSubtreesOtherName.IsEmpty)
+            {
+                temp += "OtherName:\n";
+                temp += StringifyOtherNameCollection(excludedSubtreesOtherName);
+            }
             return temp;
         }
-
     }
 }
diff --git a/crypto/test/src/test/PkixNameConstraintsTest.cs b/crypto/test/src/test/PkixNameConstraintsTest.cs
index 073f9f2a3..65f39dcd2 100644
--- a/crypto/test/src/test/PkixNameConstraintsTest.cs
+++ b/crypto/test/src/test/PkixNameConstraintsTest.cs
@@ -197,6 +197,37 @@ namespace Org.BouncyCastle.Tests
             constraintValidator.checkPermitted(
                 new GeneralName(GeneralName.DirectoryName,
                     new X509Name(true, "cn=Valid DN nameConstraints EE Certificate Test1, ou=permittedSubtree1, o=Test Certificates 2011, c=US")));
+
+            GeneralName name = new GeneralName(GeneralName.OtherName, new OtherName(new DerObjectIdentifier("1.1"), DerNull.Instance));
+            GeneralSubtree subtree = new GeneralSubtree(name);
+
+            PkixNameConstraintValidator validator = new PkixNameConstraintValidator();
+            validator.IntersectPermittedSubtree(new DerSequence(subtree));
+
+            name = new GeneralName(GeneralName.OtherName, new OtherName(new DerObjectIdentifier("1.1"), DerNull.Instance));
+            subtree = new GeneralSubtree(name);
+
+            validator = new PkixNameConstraintValidator();
+            validator.IntersectPermittedSubtree(new DerSequence(subtree));
+            validator.AddExcludedSubtree(subtree);
+
+            try
+            {
+                validator.checkExcluded(name);
+            }
+            catch (PkixNameConstraintValidatorException e)
+            {
+                IsEquals("OtherName is from an excluded subtree.", e.Message);
+            }
+
+            try
+            {
+                validator.checkPermitted(name);
+            }
+            catch (PkixNameConstraintValidatorException e)
+            {
+                Fail(e.Message);
+            }
         }
 
 		/**