diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-06-04 13:53:00 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2019-06-04 13:53:00 +0700 |
commit | 6c7a86e0b73074b2a42ea129acc831ace01d41a5 (patch) | |
tree | c0bb41783442ef197d0f10bcb56f6e015fc687ec /crypto | |
parent | Name constraint validation updates from bc-java (diff) | |
download | BouncyCastle.NET-ed25519-6c7a86e0b73074b2a42ea129acc831ace01d41a5.tar.xz |
Port LinkedCertificate from bc-java
Diffstat (limited to '')
-rw-r--r-- | crypto/BouncyCastle.Android.csproj | 1 | ||||
-rw-r--r-- | crypto/BouncyCastle.csproj | 1 | ||||
-rw-r--r-- | crypto/BouncyCastle.iOS.csproj | 1 | ||||
-rw-r--r-- | crypto/crypto.csproj | 10 | ||||
-rw-r--r-- | crypto/src/asn1/Asn1EncodableVector.cs | 8 | ||||
-rw-r--r-- | crypto/src/asn1/bc/BCObjectIdentifiers.cs | 11 | ||||
-rw-r--r-- | crypto/src/asn1/bc/LinkedCertificate.cs | 100 | ||||
-rw-r--r-- | crypto/test/UnitTests.csproj | 1 | ||||
-rw-r--r-- | crypto/test/src/asn1/test/LinkedCertificateTest.cs | 97 | ||||
-rw-r--r-- | crypto/test/src/asn1/test/RegressionTest.cs | 1 |
10 files changed, 230 insertions, 1 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj index a356bce2c..41ad0c236 100644 --- a/crypto/BouncyCastle.Android.csproj +++ b/crypto/BouncyCastle.Android.csproj @@ -142,6 +142,7 @@ <Compile Include="src\asn1\anssi\ANSSINamedCurves.cs" /> <Compile Include="src\asn1\anssi\ANSSIObjectIdentifiers.cs" /> <Compile Include="src\asn1\bc\BCObjectIdentifiers.cs" /> + <Compile Include="src\asn1\bc\LinkedCertificate.cs" /> <Compile Include="src\asn1\bsi\BsiObjectIdentifiers.cs" /> <Compile Include="src\asn1\cmp\CAKeyUpdAnnContent.cs" /> <Compile Include="src\asn1\cmp\CertConfirmContent.cs" /> diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj index c79463f7c..8c7f342d2 100644 --- a/crypto/BouncyCastle.csproj +++ b/crypto/BouncyCastle.csproj @@ -136,6 +136,7 @@ <Compile Include="src\asn1\anssi\ANSSINamedCurves.cs" /> <Compile Include="src\asn1\anssi\ANSSIObjectIdentifiers.cs" /> <Compile Include="src\asn1\bc\BCObjectIdentifiers.cs" /> + <Compile Include="src\asn1\bc\LinkedCertificate.cs" /> <Compile Include="src\asn1\bsi\BsiObjectIdentifiers.cs" /> <Compile Include="src\asn1\cmp\CAKeyUpdAnnContent.cs" /> <Compile Include="src\asn1\cmp\CertConfirmContent.cs" /> diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj index 630df8a1f..f3ffb3b66 100644 --- a/crypto/BouncyCastle.iOS.csproj +++ b/crypto/BouncyCastle.iOS.csproj @@ -137,6 +137,7 @@ <Compile Include="src\asn1\anssi\ANSSINamedCurves.cs" /> <Compile Include="src\asn1\anssi\ANSSIObjectIdentifiers.cs" /> <Compile Include="src\asn1\bc\BCObjectIdentifiers.cs" /> + <Compile Include="src\asn1\bc\LinkedCertificate.cs" /> <Compile Include="src\asn1\bsi\BsiObjectIdentifiers.cs" /> <Compile Include="src\asn1\cmp\CAKeyUpdAnnContent.cs" /> <Compile Include="src\asn1\cmp\CertConfirmContent.cs" /> diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj index 38f4544d8..55fcf1704 100644 --- a/crypto/crypto.csproj +++ b/crypto/crypto.csproj @@ -569,6 +569,11 @@ BuildAction = "Compile" /> <File + RelPath = "src\asn1\bc\LinkedCertificate.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "src\asn1\bsi\BsiObjectIdentifiers.cs" SubType = "Code" BuildAction = "Compile" @@ -11668,6 +11673,11 @@ BuildAction = "Compile" /> <File + RelPath = "test\src\asn1\test\LinkedCertificateTest.cs" + SubType = "Code" + BuildAction = "Compile" + /> + <File RelPath = "test\src\asn1\test\MiscTest.cs" SubType = "Code" BuildAction = "Compile" diff --git a/crypto/src/asn1/Asn1EncodableVector.cs b/crypto/src/asn1/Asn1EncodableVector.cs index 49532fe57..8a97e8b4f 100644 --- a/crypto/src/asn1/Asn1EncodableVector.cs +++ b/crypto/src/asn1/Asn1EncodableVector.cs @@ -61,6 +61,14 @@ namespace Org.BouncyCastle.Asn1 } } + public void AddOptionalTagged(bool isExplicit, int tagNo, Asn1Encodable obj) + { + if (null != obj) + { + v.Add(new DerTaggedObject(isExplicit, tagNo, obj)); + } + } + public Asn1Encodable this[ int index] { diff --git a/crypto/src/asn1/bc/BCObjectIdentifiers.cs b/crypto/src/asn1/bc/BCObjectIdentifiers.cs index 1e2448853..0ffd65dfc 100644 --- a/crypto/src/asn1/bc/BCObjectIdentifiers.cs +++ b/crypto/src/asn1/bc/BCObjectIdentifiers.cs @@ -101,5 +101,14 @@ namespace Org.BouncyCastle.Asn1.BC * NewHope */ public static readonly DerObjectIdentifier newHope = bc_exch.Branch("1"); + + /** + * X.509 extension(4) values + * <p> + * 1.3.6.1.4.1.22554.4 + */ + public static readonly DerObjectIdentifier bc_ext = bc.Branch("4"); + + public static readonly DerObjectIdentifier linkedCertificate = bc_ext.Branch("1"); } -} \ No newline at end of file +} diff --git a/crypto/src/asn1/bc/LinkedCertificate.cs b/crypto/src/asn1/bc/LinkedCertificate.cs new file mode 100644 index 000000000..c8d05d8f5 --- /dev/null +++ b/crypto/src/asn1/bc/LinkedCertificate.cs @@ -0,0 +1,100 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.BC +{ + /** + * Extension to tie an alternate certificate to the containing certificate. + * <pre> + * LinkedCertificate := SEQUENCE { + * digest DigestInfo, -- digest of PQC certificate + * certLocation GeneralName, -- location of PQC certificate + * certIssuer [0] Name OPTIONAL, -- issuer of PQC cert (if different from current certificate) + * cACerts [1] GeneralNames OPTIONAL, -- CA certificates for PQC cert (one of more locations) + * } + * </pre> + */ + public class LinkedCertificate + : Asn1Encodable + { + private readonly DigestInfo mDigest; + private readonly GeneralName mCertLocation; + + private X509Name mCertIssuer; + private GeneralNames mCACerts; + + public LinkedCertificate(DigestInfo digest, GeneralName certLocation) + : this(digest, certLocation, null, null) + { + } + + public LinkedCertificate(DigestInfo digest, GeneralName certLocation, X509Name certIssuer, GeneralNames caCerts) + { + this.mDigest = digest; + this.mCertLocation = certLocation; + this.mCertIssuer = certIssuer; + this.mCACerts = caCerts; + } + + private LinkedCertificate(Asn1Sequence seq) + { + this.mDigest = DigestInfo.GetInstance(seq[0]); + this.mCertLocation = GeneralName.GetInstance(seq[1]); + + for (int i = 2; i < seq.Count; ++i) + { + Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[i]); + + switch (tagged.TagNo) + { + case 0: + this.mCertIssuer = X509Name.GetInstance(tagged, false); + break; + case 1: + this.mCACerts = GeneralNames.GetInstance(tagged, false); + break; + default: + throw new ArgumentException("unknown tag in tagged field"); + } + } + } + + public static LinkedCertificate GetInstance(object obj) + { + if (obj is LinkedCertificate) + return (LinkedCertificate)obj; + if (obj != null) + return new LinkedCertificate(Asn1Sequence.GetInstance(obj)); + return null; + } + + public virtual DigestInfo Digest + { + get { return mDigest; } + } + + public virtual GeneralName CertLocation + { + get { return mCertLocation; } + } + + public virtual X509Name CertIssuer + { + get { return mCertIssuer; } + } + + public virtual GeneralNames CACerts + { + get { return mCACerts; } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(mDigest, mCertLocation); + v.AddOptionalTagged(false, 0, mCertIssuer); + v.AddOptionalTagged(false, 1, mCACerts); + return new DerSequence(v); + } + } +} diff --git a/crypto/test/UnitTests.csproj b/crypto/test/UnitTests.csproj index 9420cc832..1378034a6 100644 --- a/crypto/test/UnitTests.csproj +++ b/crypto/test/UnitTests.csproj @@ -85,6 +85,7 @@ <Compile Include="src\asn1\test\IssuingDistributionPointTest.cs" /> <Compile Include="src\asn1\test\KeyUsageTest.cs" /> <Compile Include="src\asn1\test\LDSSecurityObjectUnitTest.cs" /> + <Compile Include="src\asn1\test\LinkedCertificateTest.cs" /> <Compile Include="src\asn1\test\MiscTest.cs" /> <Compile Include="src\asn1\test\MonetaryLimitUnitTest.cs" /> <Compile Include="src\asn1\test\MonetaryValueUnitTest.cs" /> diff --git a/crypto/test/src/asn1/test/LinkedCertificateTest.cs b/crypto/test/src/asn1/test/LinkedCertificateTest.cs new file mode 100644 index 000000000..416c048c0 --- /dev/null +++ b/crypto/test/src/asn1/test/LinkedCertificateTest.cs @@ -0,0 +1,97 @@ +using System; + +using NUnit.Framework; + +using Org.BouncyCastle.Asn1.BC; +using Org.BouncyCastle.Asn1.Nist; +using Org.BouncyCastle.Asn1.X509; + +namespace Org.BouncyCastle.Asn1.Tests +{ + [TestFixture] + public class LinkedCertificateTest + : Asn1UnitTest + { + public override string Name + { + get { return "LinkedCertificate"; } + } + + public override void PerformTest() + { + DigestInfo digInfo = new DigestInfo(new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256), new byte[32]); + GeneralName certLocation = new GeneralName(GeneralName.UniformResourceIdentifier, "https://www.bouncycastle.org/certs"); + X509Name certIssuer = null; + GeneralNames cACerts = null; + + LinkedCertificate linked = new LinkedCertificate(digInfo, certLocation); + + CheckConstruction(linked, digInfo, certLocation, certIssuer, cACerts); + + certIssuer = new X509Name("CN=Test"); + cACerts = new GeneralNames(new GeneralName(new X509Name("CN=CA Test"))); + + linked = new LinkedCertificate(digInfo, certLocation, certIssuer, cACerts); + + CheckConstruction(linked, digInfo, certLocation, certIssuer, cACerts); + + linked = LinkedCertificate.GetInstance(null); + + if (linked != null) + { + Fail("null getInstance() failed."); + } + + try + { + LinkedCertificate.GetInstance(new object()); + + Fail("getInstance() failed to detect bad object."); + } + catch (ArgumentException e) + { + // expected + } + } + + private void CheckConstruction(LinkedCertificate linked, DigestInfo digestInfo, GeneralName certLocation, + X509Name certIssuer, GeneralNames caCerts) + { + CheckValues(linked, digestInfo, certLocation, certIssuer, caCerts); + + linked = LinkedCertificate.GetInstance(linked); + + CheckValues(linked, digestInfo, certLocation, certIssuer, caCerts); + + Asn1InputStream aIn = new Asn1InputStream(linked.ToAsn1Object().GetEncoded()); + + Asn1Sequence seq = (Asn1Sequence)aIn.ReadObject(); + + linked = LinkedCertificate.GetInstance(seq); + + CheckValues(linked, digestInfo, certLocation, certIssuer, caCerts); + } + + private void CheckValues(LinkedCertificate linked, DigestInfo digestInfo, GeneralName certLocation, + X509Name certIssuer, GeneralNames caCerts) + { + checkMandatoryField("digest", digestInfo, linked.Digest); + checkMandatoryField("certLocatin", certLocation, linked.CertLocation); + checkOptionalField("certIssuer", certIssuer, linked.CertIssuer); + checkOptionalField("caCerts", caCerts, linked.CACerts); + } + + public static void Main(string[] args) + { + RunTest(new LinkedCertificateTest()); + } + + [Test] + public void TestFunction() + { + string resultText = Perform().ToString(); + + Assert.AreEqual(Name + ": Okay", resultText); + } + } +} diff --git a/crypto/test/src/asn1/test/RegressionTest.cs b/crypto/test/src/asn1/test/RegressionTest.cs index 4534f2c75..67860ccd7 100644 --- a/crypto/test/src/asn1/test/RegressionTest.cs +++ b/crypto/test/src/asn1/test/RegressionTest.cs @@ -37,6 +37,7 @@ namespace Org.BouncyCastle.Asn1.Tests new IssuingDistributionPointUnitTest(), new KeyUsageTest(), new LDSSecurityObjectUnitTest(), + new LinkedCertificateTest(), new MiscTest(), new MonetaryLimitUnitTest(), new MonetaryValueUnitTest(), |