summary refs log tree commit diff
path: root/crypto/src/asn1
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-11-11 15:24:08 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-11-11 15:24:08 +0700
commit46222a965fb85dfd5fdaf0ad273bb98e232d2b81 (patch)
tree1132d2f8523b3589b266b41c3505369482e76b8a /crypto/src/asn1
parentASN.1: Update encoding in line with bc-java (diff)
downloadBouncyCastle.NET-ed25519-46222a965fb85dfd5fdaf0ad273bb98e232d2b81.tar.xz
Add DLTaggedObject and use from parser
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r--crypto/src/asn1/ASN1StreamParser.cs6
-rw-r--r--crypto/src/asn1/DLTaggedObject.cs110
2 files changed, 113 insertions, 3 deletions
diff --git a/crypto/src/asn1/ASN1StreamParser.cs b/crypto/src/asn1/ASN1StreamParser.cs
index 0a575c8c5..55b5bc656 100644
--- a/crypto/src/asn1/ASN1StreamParser.cs
+++ b/crypto/src/asn1/ASN1StreamParser.cs
@@ -99,7 +99,7 @@ namespace Org.BouncyCastle.Asn1
 			{
 				// Note: !CONSTRUCTED => IMPLICIT
 				DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
-				return new DerTaggedObject(false, tag, new DerOctetString(defIn.ToArray()));
+				return new DLTaggedObject(false, tag, new DerOctetString(defIn.ToArray()));
 			}
 
 			Asn1EncodableVector v = ReadVector();
@@ -112,8 +112,8 @@ namespace Org.BouncyCastle.Asn1
 			}
 
 			return v.Count == 1
-				?   new DerTaggedObject(true, tag, v[0])
-				:   new DerTaggedObject(false, tag, DLSequence.FromVector(v));
+				?   new DLTaggedObject(true, tag, v[0])
+				:   new DLTaggedObject(false, tag, DLSequence.FromVector(v));
 		}
 
 		public virtual IAsn1Convertible ReadObject()
diff --git a/crypto/src/asn1/DLTaggedObject.cs b/crypto/src/asn1/DLTaggedObject.cs
new file mode 100644
index 000000000..a5135f2a5
--- /dev/null
+++ b/crypto/src/asn1/DLTaggedObject.cs
@@ -0,0 +1,110 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+    internal class DLTaggedObject
+        : DerTaggedObject
+    {
+        private int m_contentsLengthDL = -1;
+
+        internal DLTaggedObject(int tagNo, Asn1Encodable obj)
+            : base(tagNo, obj)
+        {
+        }
+
+        internal DLTaggedObject(bool explicitly, int tagNo, Asn1Encodable obj)
+            : base(explicitly, tagNo, obj)
+        {
+        }
+
+        internal DLTaggedObject(int tagNo)
+            : base(false, tagNo, BerSequence.Empty)
+        {
+        }
+
+        internal override string Asn1Encoding
+        {
+            // TODO[asn1] Use DL encoding when supported
+            get { return Ber; }
+        }
+
+        internal override bool EncodeConstructed(int encoding)
+        {
+            if (Asn1OutputStream.EncodingDer == encoding)
+                return base.EncodeConstructed(encoding);
+
+            // TODO[asn1] Use DL encoding when supported
+            //encoding = Asn1OutputStream.EncodingDL;
+
+            return IsExplicit() || GetBaseObject().ToAsn1Object().EncodeConstructed(encoding);
+        }
+
+        internal override int EncodedLength(int encoding, bool withID)
+        {
+            if (Asn1OutputStream.EncodingDer == encoding)
+                return base.EncodedLength(encoding, withID);
+
+            Asn1Object baseObject = GetBaseObject().ToAsn1Object();
+            bool withBaseID = IsExplicit();
+
+            int length = GetContentsLengthDL(baseObject, withBaseID);
+
+            if (withBaseID)
+            {
+                length += Asn1OutputStream.GetLengthOfDL(length);
+            }
+
+            length += withID ? Asn1OutputStream.GetLengthOfIdentifier(TagNo) : 0;
+
+            return length;
+        }
+
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
+        {
+            if (Asn1OutputStream.EncodingDer == asn1Out.Encoding)
+            {
+                base.Encode(asn1Out, withID);
+                return;
+            }
+
+            // TODO[asn1] Use DL encoding when supported
+            //asn1Out = asn1Out.GetDLSubStream();
+
+            Asn1Object baseObject = GetBaseObject().ToAsn1Object();
+            bool withBaseID = IsExplicit();
+
+            if (withID)
+            {
+                int flags = TagClass;
+                if (withBaseID || baseObject.EncodeConstructed(asn1Out.Encoding))
+                {
+                    flags |= Asn1Tags.Constructed;
+                }
+
+                asn1Out.WriteIdentifier(true, flags, TagNo);
+            }
+
+            if (withBaseID)
+            {
+                asn1Out.WriteDL(GetContentsLengthDL(baseObject, true));
+            }
+
+            baseObject.Encode(asn1Out, withBaseID);
+        }
+
+        internal override Asn1Sequence RebuildConstructed(Asn1Object asn1Object)
+        {
+            return new BerSequence(asn1Object);
+        }
+
+        private int GetContentsLengthDL(Asn1Object baseObject, bool withBaseID)
+        {
+            if (m_contentsLengthDL < 0)
+            {
+                // TODO[asn1] Use DL encoding when supported
+                m_contentsLengthDL = baseObject.EncodedLength(Asn1OutputStream.EncodingBer, withBaseID);
+            }
+            return m_contentsLengthDL;
+        }
+    }
+}