summary refs log tree commit diff
path: root/crypto/src/asn1
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r--crypto/src/asn1/Asn1EncodableVector.cs8
-rw-r--r--crypto/src/asn1/bc/BCObjectIdentifiers.cs11
-rw-r--r--crypto/src/asn1/bc/LinkedCertificate.cs100
3 files changed, 118 insertions, 1 deletions
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);
+        }
+    }
+}