summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-02-08 16:41:10 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-02-08 16:41:10 +0700
commite4fad8fe422ecf0cb5cd6de1d599ab0de63802d4 (patch)
treeb30563a54b219b0d96afb95f7415742c26b753c9
parentImplement TODO checks (diff)
downloadBouncyCastle.NET-ed25519-e4fad8fe422ecf0cb5cd6de1d599ab0de63802d4.tar.xz
Support V1 attribute certificates and holders
-rw-r--r--crypto/src/asn1/x509/AttributeCertificateInfo.cs40
-rw-r--r--crypto/src/asn1/x509/Holder.cs14
-rw-r--r--crypto/test/src/asn1/test/CertificateTest.cs164
3 files changed, 190 insertions, 28 deletions
diff --git a/crypto/src/asn1/x509/AttributeCertificateInfo.cs b/crypto/src/asn1/x509/AttributeCertificateInfo.cs
index a62b01981..29abaa6e4 100644
--- a/crypto/src/asn1/x509/AttributeCertificateInfo.cs
+++ b/crypto/src/asn1/x509/AttributeCertificateInfo.cs
@@ -43,20 +43,31 @@ namespace Org.BouncyCastle.Asn1.X509
 		private AttributeCertificateInfo(
             Asn1Sequence seq)
         {
-			if (seq.Count < 7 || seq.Count > 9)
+			if (seq.Count < 6 || seq.Count > 9)
 			{
 				throw new ArgumentException("Bad sequence size: " + seq.Count);
 			}
 
-			this.version = DerInteger.GetInstance(seq[0]);
-            this.holder = Holder.GetInstance(seq[1]);
-            this.issuer = AttCertIssuer.GetInstance(seq[2]);
-            this.signature = AlgorithmIdentifier.GetInstance(seq[3]);
-            this.serialNumber = DerInteger.GetInstance(seq[4]);
-            this.attrCertValidityPeriod = AttCertValidityPeriod.GetInstance(seq[5]);
-            this.attributes = Asn1Sequence.GetInstance(seq[6]);
+            int start;
+            if (seq[0] is DerInteger)   // in version 1 certs version is DEFAULT  v1(0)
+            {
+                this.version = DerInteger.GetInstance(seq[0]);
+                start = 1;
+            }
+            else
+            {
+                this.version = new DerInteger(0);
+                start = 0;
+            }
+
+            this.holder = Holder.GetInstance(seq[start]);
+            this.issuer = AttCertIssuer.GetInstance(seq[start + 1]);
+            this.signature = AlgorithmIdentifier.GetInstance(seq[start + 2]);
+            this.serialNumber = DerInteger.GetInstance(seq[start + 3]);
+            this.attrCertValidityPeriod = AttCertValidityPeriod.GetInstance(seq[start + 4]);
+            this.attributes = Asn1Sequence.GetInstance(seq[start + 5]);
 
-			for (int i = 7; i < seq.Count; i++)
+			for (int i = start + 6; i < seq.Count; i++)
             {
                 Asn1Encodable obj = (Asn1Encodable) seq[i];
 
@@ -136,9 +147,16 @@ namespace Org.BouncyCastle.Asn1.X509
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version, holder, issuer, signature, serialNumber,
-                attrCertValidityPeriod, attributes);
+            Asn1EncodableVector v = new Asn1EncodableVector(9);
+
+            if (version.IntValueExact != 0)
+            {
+                v.Add(version);
+            }
+
+            v.Add(holder, issuer, signature, serialNumber, attrCertValidityPeriod, attributes);
             v.AddOptional(issuerUniqueID, extensions);
+
             return new DerSequence(v);
         }
     }
diff --git a/crypto/src/asn1/x509/Holder.cs b/crypto/src/asn1/x509/Holder.cs
index b67c0b6c7..90df75a0f 100644
--- a/crypto/src/asn1/x509/Holder.cs
+++ b/crypto/src/asn1/x509/Holder.cs
@@ -27,9 +27,9 @@ namespace Org.BouncyCastle.Asn1.X509
 	 * 
 	 * <pre>
 	 *         subject CHOICE {
-	 *          baseCertificateID [0] IssuerSerial,
+	 *          baseCertificateID [0] EXPLICIT IssuerSerial,
 	 *          -- associated with a Public Key Certificate
-	 *          subjectName [1] GeneralNames },
+	 *          subjectName [1] EXPLICIT GeneralNames },
 	 *          -- associated with a name
 	 * </pre>
 	 * </p>
@@ -74,10 +74,10 @@ namespace Org.BouncyCastle.Asn1.X509
 			switch (tagObj.TagNo)
 			{
 				case 0:
-					baseCertificateID = IssuerSerial.GetInstance(tagObj, false);
+					baseCertificateID = IssuerSerial.GetInstance(tagObj, true);
 					break;
 				case 1:
-					entityName = GeneralNames.GetInstance(tagObj, false);
+					entityName = GeneralNames.GetInstance(tagObj, true);
 					break;
 				default:
 					throw new ArgumentException("unknown tag in Holder");
@@ -228,7 +228,7 @@ namespace Org.BouncyCastle.Asn1.X509
         {
             if (version == 1)
             {
-                Asn1EncodableVector v = new Asn1EncodableVector();
+                Asn1EncodableVector v = new Asn1EncodableVector(3);
                 v.AddOptionalTagged(false, 0, baseCertificateID);
                 v.AddOptionalTagged(false, 1, entityName);
                 v.AddOptionalTagged(false, 2, objectDigestInfo);
@@ -237,10 +237,10 @@ namespace Org.BouncyCastle.Asn1.X509
 
             if (entityName != null)
             {
-                return new DerTaggedObject(false, 1, entityName);
+                return new DerTaggedObject(true, 1, entityName);
             }
 
-            return new DerTaggedObject(false, 0, baseCertificateID);
+            return new DerTaggedObject(true, 0, baseCertificateID);
         }
 	}
 }
diff --git a/crypto/test/src/asn1/test/CertificateTest.cs b/crypto/test/src/asn1/test/CertificateTest.cs
index 7fcb1fffa..c2593fad2 100644
--- a/crypto/test/src/asn1/test/CertificateTest.cs
+++ b/crypto/test/src/asn1/test/CertificateTest.cs
@@ -1,6 +1,4 @@
 using System;
-using System.Collections;
-using System.IO;
 
 using NUnit.Framework;
 
@@ -180,6 +178,67 @@ namespace Org.BouncyCastle.Asn1.Tests
 			+ "lHMkpI7WqAZikdnAEQ5jQsVWEuVejWxR6gjejKxc0fb9qpIui7/GoI5Eh6dmG20e"
 			+ "xbwJL3+6YYFrZwxR8cC5rPvWrblUR5XKJy+Zp/H5+t9iANnL1L8J");
 
+        // V1 attribute certificate
+        private static readonly byte[] attrCertv1 = Base64.Decode(
+            "MIIFdDCCBFygXTBbMFOkUTBPMQswCQYDVQQGEwJERTEcMBoGA1UECgwTRGV1"
+            + "dHNjaGUgVGVsZWtvbSBBRzEiMCAGA1UEAwwZVGVsZVNlYyBQS1MgU2lnRyBD"
+            + "QSAxNzpQTgIEG1toDjBTpFEwTzELMAkGA1UEBhMCREUxHDAaBgNVBAoME0Rl"
+			+ "dXRzY2hlIFRlbGVrb20gQUcxIjAgBgNVBAMMGVRlbGVTZWMgUEtTIFNpZ0cg"
+			+ "Q0EgMjU6UE4wDQYJKoZIhvcNAQELBQACBCep3f0wIhgPMjAxMDA0MTIxMTI5"
+			+ "MTJaGA8yMDEyMDQxMjEwNTkyOFowggGmMIIBogYFKyQIAwgxggGXDIIBk1Ro"
+			+ "ZSBxdWFsaWZpZWQgc2lnbmF0dXJlIGF0IGhhbmQgaXMgcmVzdHJpY3RlZCB0"
+			+ "byBwcmVzZW50aW5nIGludm9pY2VzIG9yIGNyZWRpdHMgdG8gY3VzdG9tZXJz"
+			+ "IGFjY29yZGluZyB0byBFVSBDb3VuY2lsIGRpcmVjdGl2ZSAyMDAxLzExNS9F"
+			+ "QyAoMjB0aCBEZWNlbWJlciAyMDAxKSBhbmQgR2VybWFuIFZBVCB0YXggKMKn"
+			+ "MTQgVVN0RykuICBEaWUgdm9ybGllZ2VuZGUgcXVhbGlmaXppZXJ0ZSBTaWdu"
+			+ "YXR1ciBpc3QgYXVmIGRpZSAgUHJhZXNlbnRhdGlvbiB2b24gUmVjaG51bmdl"
+			+ "biBvZGVyIEd1dHNjaHJpZnRlbiBnZW1hZXNzIEVVIERpcmVrdGl2ZSAyMDAx"
+			+ "LzExNS9FQyAoMjAuIERlemVtYmVyIDIwMDEpIHVuZCBkZXV0c2NoZW0gVW1z"
+			+ "YXR6c3RldWVyZ2VzZXR6ICAowqcxNCBVU3RHKSBiZXNjaHJhZW5rdC4wggHB"
+			+ "MB8GA1UdIwQYMBaAFM6i1yR/z8IikpxpU/Fdh8BPxhq8MEMGA1UdIAQ8MDow"
+			+ "OAYFKyQIAQEwLzAtBggrBgEFBQcCARYhaHR0cDovL3Brcy50ZWxlc2VjLmRl"
+			+ "L2Nwcy9jcHMucGRmMIIBBAYDVR0fBIH8MIH5MIH2oG2ga4Y1bGRhcDovL3Br"
+			+ "cy1sZGFwLnRlbGVzZWMuZGUvbz1EZXV0c2NoZSBUZWxla29tIEFHLGM9ZGWG"
+			+ "Mmh0dHA6Ly9wa3MudGVsZXNlYy5kZS90ZWxlc2VjL3NlcnZsZXQvZG93bmxv"
+			+ "YWRfY3JsooGEpIGBMH8xCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2No"
+			+ "ZSBUZWxla29tIEFHMR8wHQYDVQQLFBZQcm9kdWt0emVudHJ1bSBUZWxlU2Vj"
+			+ "MTEwDAYHAoIGAQoHFBMBMTAhBgNVBAMUGlRlbGVTZWMgUEtTIFNpZ0cgRElS"
+			+ "IDM1OlBOMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3Br"
+			+ "cy50ZWxlc2VjLmRlL29jc3ByMBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEw"
+			+ "DQYJKoZIhvcNAQELBQADggEBAEz2OvU9YytJUKHMDQcND5njIyUXTkSrlWjV"
+			+ "F28uwxVlveO4JPTAY7PvXy69HUuTPwlvqCfJIUF2RLPZFQx0wFto8ajC9v5X"
+			+ "SqwQcINXRakpE6FPAdQFnH44TaIQWXW1hy9xr8GuD0uhQLTJGYqVzHfLoM8e"
+			+ "llPNHUVhC7CEOxDb1PTHCUlQFNkFRmeeqzEVoj1F0pM6wI5zf8+w2WwrFPCD"
+			+ "jrjEr/VoBRoEi/tKnsLq6oOkizUKT0KJEnSyYxoOa7euT1yX+Co94SPnMZi5"
+			+ "qukHSj8Kiio6Jecl//qDPG/mHo1ro+8rH+rbze7EEfKMp5yeWCwXGthL9oYo"
+            + "RYl+UuI=");
+
+		// bad issuer certificate
+		private static readonly byte[] dudCert = Base64.Decode(
+			"MIICLzCCAZgCBFp/9TowDQYJKoZIhvcNAQEFBQAwAjEAMB4XDTA4MDcyNTEzNTQ0" +
+			"MFoXDTEzMDgyNTA1MDAwMFowgboxCzAJBgNVBAYTAlVTMQ0wCwYDVQQIEwRJb3dh" +
+			"MRMwEQYDVQQHEwpEZXMgTW9pbmVzMT0wOwYDVQQKEzRTdGF0ZSBvZiBJb3dhLCBE" +
+			"ZXBhcnRtZW50IG9mIEFkbWluaXN0cmF0aXZlIFNlcnZpY2VzMSowKAYDVQQLEyFJ" +
+			"bmZvcm1hdGlvbiBUZWNobm9sb2d5IEVudGVycHJpc2UxHDAaBgNVBAMTE3d3dy5k" +
+			"b20uc3RhdGUuaWEudXMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK0C7Jca" +
+			"C0RiD0hcBcPUdGc78y815yPuHGmF/A2K+3LbwfFXDhsY7ebRxHVfL7gt+nFBvJ2r" +
+			"MqDBIMHFB3vYdSnGbND41eso6cLnzkMVtSisG25Tat3F8BF/js54sa0mFEn4qMQ+" +
+			"6T6jxyPflsjKpmi6L7lfRdPNbBbKSmK9ik2lAgMBAAEwDQYJKoZIhvcNAQEFBQAD" +
+			"gYEAc9Rx95MiPzJiCn3nOoP+3PPQCGTyUcUWZfYKXuC7aOzMYUXes71Q3K1/W6Vy" +
+			"V2Tlrbj0KT8j2/kBmy8+7d5whnUklJNsH6VJMst3V4Uxvk3os+uaW0FHsW389sNY" +
+			"/5LdslDjfqV2nUc2GqDPn38PATL26SRJKlCvU2NagdID3WM="
+		);
+
+		// malformed cert
+		private static readonly byte[] bangerCert = Base64.Decode(
+			"MIIBSKADAgECAgECMA0GCSqGSIb3DQEEBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYD" +
+			"VQQKDA1CaXVuYHkgQGFzdGtlMB4XDTcwMDExMTQyNjAwMVoXDTcwMDEwNzAwMDAw" +
+			"MlowNjELMQkGA1UBAwwCQVUxFjAUBgNVAQwMDUJsdW5jeSZDY3Nzb2UxDzANBgNV" +
+			"AQsMBlRlc3cgNTAYMBAGBisOBwMDATAGAgEBAgECAwQAAgEDoYGVMIGSMGEGA1Yd" +
+			"IwEB /wRXNVWAFDZPdpTPzKi7o8EJokoQU2uqCHRRoTqkOzA2NAs2CgYDVQYDDAJ" +
+			"HVTEWMBQGA1QECQwNQmhwbmR5J0Ngc3RsYDAPMA0CA1UECwwGUWVzdyA0hQECMCA" +
+			"GA1UdDgEB/wQWBBQ2T3OSzciou6PBCqRJEFNrqgh2UTALBgNVHQkEBAMGBBE=");
+
 		private static readonly string[] subjects =
 		{
 			"C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster@connect4.com.au",
@@ -200,10 +259,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 			int		id,
 			byte[]	cert)
 		{
-			Asn1Object seq = Asn1Object.FromByteArray(cert);
-			string dump = Asn1Dump.DumpAsString(seq);
-
-			X509CertificateStructure obj = X509CertificateStructure.GetInstance(seq);
+			X509CertificateStructure obj = X509CertificateStructure.GetInstance(cert);
 			TbsCertificateStructure tbsCert = obj.TbsCertificate;
 
 			if (!tbsCert.Subject.ToString().Equals(subjects[id - 1]))
@@ -300,10 +356,7 @@ namespace Org.BouncyCastle.Asn1.Tests
 			int		id,
 			byte[]	cert)
 		{
-			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(cert);
-			string dump = Asn1Dump.DumpAsString(seq);
-
-			AttributeCertificate obj = AttributeCertificate.GetInstance(seq);
+			AttributeCertificate obj = AttributeCertificate.GetInstance(cert);
 			AttributeCertificateInfo acInfo = obj.ACInfo;
 
 			// Version
@@ -366,6 +419,94 @@ namespace Org.BouncyCastle.Asn1.Tests
 			}
 		}
 
+		public void CheckV1AttributeCertificate(
+			int     id,
+			byte[]  cert)
+		{
+            AttributeCertificate obj = AttributeCertificate.GetInstance(cert);
+			AttributeCertificateInfo acInfo = obj.ACInfo;
+
+			// Version
+			if (acInfo.Version.IntValueExact != 0)
+			{
+				Fail("failed AC Version test for id " + id);
+			}
+
+			// Holder
+			Holder h = acInfo.Holder;
+			if (h == null)
+			{
+				Fail("failed AC Holder test, it's null, for id " + id);
+			}
+
+			// Issuer
+			AttCertIssuer aci = acInfo.Issuer;
+			if (aci == null)
+			{
+				Fail("failed AC Issuer test, it's null, for id " + id);
+			}
+
+			// Signature
+			AlgorithmIdentifier sig = acInfo.Signature;
+			if (sig == null)
+			{
+				Fail("failed AC Signature test for id " + id);
+			}
+
+			// Serial
+			DerInteger serial = acInfo.SerialNumber;
+
+			// Validity
+			AttCertValidityPeriod validity = acInfo.AttrCertValidityPeriod;
+			if (validity == null)
+			{
+				Fail("failed AC AttCertValidityPeriod test for id " + id);
+			}
+
+			// Attributes
+			Asn1Sequence attribSeq = acInfo.Attributes;
+			AttributeX509[] att = new AttributeX509[attribSeq.Count];
+			for (int i = 0; i < attribSeq.Count; i++)
+			{
+				att[i] = AttributeX509.GetInstance(attribSeq[i]);
+			}
+
+			// IssuerUniqueId
+			// TODO, how to best test?
+
+			// X509 Extensions
+			X509Extensions ext = acInfo.Extensions;
+			if (ext != null)
+			{
+				foreach (DerObjectIdentifier oid in ext.ExtensionOids)
+				{
+					X509Extension extVal = ext.GetExtension(oid);
+				}
+			}
+		}
+
+		private void CheckDudCertificate()
+		{
+			X509CertificateStructure cert = X509CertificateStructure.GetInstance(dudCert);
+
+			if (!"".Equals(cert.Issuer.ToString()))
+			{
+				Fail("empty issuer not recognised correctly");
+			}
+		}
+
+		private void CheckMalformed()
+		{
+			try
+			{
+				TbsCertificateStructure cert = TbsCertificateStructure.GetInstance(bangerCert);
+			}
+			catch (ArgumentException e)
+			{
+				// expected - anything else is not!
+			}
+		}
+
 		public override void PerformTest()
 		{
 			CheckCertificate(1, cert1);
@@ -376,6 +517,9 @@ namespace Org.BouncyCastle.Asn1.Tests
 			CheckCertificate(6, cert6);
 			CheckCertificate(7, cert7);
 			CheckAttributeCertificate(8, cert8);
+			CheckV1AttributeCertificate(9, attrCertv1);
+			CheckDudCertificate();
+			CheckMalformed();
 		}
 
 		public static void Main(