diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-02-08 16:41:10 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-02-08 16:41:10 +0700 |
commit | e4fad8fe422ecf0cb5cd6de1d599ab0de63802d4 (patch) | |
tree | b30563a54b219b0d96afb95f7415742c26b753c9 | |
parent | Implement TODO checks (diff) | |
download | BouncyCastle.NET-ed25519-e4fad8fe422ecf0cb5cd6de1d599ab0de63802d4.tar.xz |
Support V1 attribute certificates and holders
-rw-r--r-- | crypto/src/asn1/x509/AttributeCertificateInfo.cs | 40 | ||||
-rw-r--r-- | crypto/src/asn1/x509/Holder.cs | 14 | ||||
-rw-r--r-- | crypto/test/src/asn1/test/CertificateTest.cs | 164 |
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( |