summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-11-08 20:14:47 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-11-08 20:14:47 +0700
commit2f23f0acb5dba40ed9fb7e9d340c0dfaf3db035b (patch)
tree99ea424d4c8718f8db82a945d082c5f0f9e49bc8
parentASN.1 refactoring (diff)
downloadBouncyCastle.NET-ed25519-2f23f0acb5dba40ed9fb7e9d340c0dfaf3db035b.tar.xz
Lazy ASN.1 enumeration and refactoring
-rw-r--r--crypto/BouncyCastle.Android.csproj5
-rw-r--r--crypto/BouncyCastle.csproj5
-rw-r--r--crypto/BouncyCastle.iOS.csproj5
-rw-r--r--crypto/crypto.csproj9
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs10
-rw-r--r--crypto/src/asn1/LazyASN1InputStream.cs16
-rw-r--r--crypto/src/asn1/LazyDERSequence.cs109
-rw-r--r--crypto/src/asn1/LazyDERSet.cs109
-rw-r--r--crypto/src/asn1/LazyDLEnumerator.cs56
-rw-r--r--crypto/src/asn1/LazyDLSequence.cs116
-rw-r--r--crypto/src/asn1/LazyDLSet.cs116
11 files changed, 314 insertions, 242 deletions
diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 165e97219..3e75ff3a4 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -137,8 +137,9 @@
     <Compile Include="src\asn1\IAsn1String.cs" />
     <Compile Include="src\asn1\IndefiniteLengthInputStream.cs" />
     <Compile Include="src\asn1\LazyASN1InputStream.cs" />
-    <Compile Include="src\asn1\LazyDERSequence.cs" />
-    <Compile Include="src\asn1\LazyDERSet.cs" />
+    <Compile Include="src\asn1\LazyDLEnumerator.cs" />
+    <Compile Include="src\asn1\LazyDLSequence.cs" />
+    <Compile Include="src\asn1\LazyDLSet.cs" />
     <Compile Include="src\asn1\LimitedInputStream.cs" />
     <Compile Include="src\asn1\OidTokenizer.cs" />
     <Compile Include="src\asn1\anssi\ANSSINamedCurves.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index ff0490af8..183e4b3d8 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -131,8 +131,9 @@
     <Compile Include="src\asn1\IAsn1String.cs" />
     <Compile Include="src\asn1\IndefiniteLengthInputStream.cs" />
     <Compile Include="src\asn1\LazyASN1InputStream.cs" />
-    <Compile Include="src\asn1\LazyDERSequence.cs" />
-    <Compile Include="src\asn1\LazyDERSet.cs" />
+    <Compile Include="src\asn1\LazyDLEnumerator.cs" />
+    <Compile Include="src\asn1\LazyDLSequence.cs" />
+    <Compile Include="src\asn1\LazyDLSet.cs" />
     <Compile Include="src\asn1\LimitedInputStream.cs" />
     <Compile Include="src\asn1\OidTokenizer.cs" />
     <Compile Include="src\asn1\anssi\ANSSINamedCurves.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index 5b7adbb36..99bd91fbd 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -132,8 +132,9 @@
     <Compile Include="src\asn1\IAsn1String.cs" />
     <Compile Include="src\asn1\IndefiniteLengthInputStream.cs" />
     <Compile Include="src\asn1\LazyASN1InputStream.cs" />
-    <Compile Include="src\asn1\LazyDERSequence.cs" />
-    <Compile Include="src\asn1\LazyDERSet.cs" />
+    <Compile Include="src\asn1\LazyDLEnumerator.cs" />
+    <Compile Include="src\asn1\LazyDLSequence.cs" />
+    <Compile Include="src\asn1\LazyDLSet.cs" />
     <Compile Include="src\asn1\LimitedInputStream.cs" />
     <Compile Include="src\asn1\OidTokenizer.cs" />
     <Compile Include="src\asn1\anssi\ANSSINamedCurves.cs" />
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index 2030c97a4..bb35c6f99 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -544,12 +544,17 @@
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "src\asn1\LazyDERSequence.cs"
+                    RelPath = "src\asn1\LazyDLEnumerator.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
                 <File
-                    RelPath = "src\asn1\LazyDERSet.cs"
+                    RelPath = "src\asn1\LazyDLSequence.cs"
+                    SubType = "Code"
+                    BuildAction = "Compile"
+                />
+                <File
+                    RelPath = "src\asn1\LazyDLSet.cs"
                     SubType = "Code"
                     BuildAction = "Compile"
                 />
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 935568550..4cca8aaf5 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -109,9 +109,9 @@ namespace Org.BouncyCastle.Asn1
                 return BuildConstructedOctetString(ReadVector(defIn));
             }
             case Asn1Tags.Sequence:
-                return CreateDerSequence(defIn);
+                return CreateDLSequence(defIn);
             case Asn1Tags.Set:
-                return CreateDerSet(defIn);
+                return CreateDLSet(defIn);
             case Asn1Tags.External:
                 return new DerExternal(ReadVector(defIn));                
             default:
@@ -143,14 +143,12 @@ namespace Org.BouncyCastle.Asn1
             return new Asn1InputStream(defIn, remaining, tmpBuffers).ReadVector();
         }
 
-        internal virtual DerSequence CreateDerSequence(
-            DefiniteLengthInputStream dIn)
+        internal virtual DerSequence CreateDLSequence(DefiniteLengthInputStream dIn)
         {
             return DerSequence.FromVector(ReadVector(dIn));
         }
 
-        internal virtual DerSet CreateDerSet(
-            DefiniteLengthInputStream dIn)
+        internal virtual DerSet CreateDLSet(DefiniteLengthInputStream dIn)
         {
             return DerSet.FromVector(ReadVector(dIn), false);
         }
diff --git a/crypto/src/asn1/LazyASN1InputStream.cs b/crypto/src/asn1/LazyASN1InputStream.cs
index 1a85e455a..2b120aafd 100644
--- a/crypto/src/asn1/LazyASN1InputStream.cs
+++ b/crypto/src/asn1/LazyASN1InputStream.cs
@@ -6,14 +6,12 @@ namespace Org.BouncyCastle.Asn1
     public class LazyAsn1InputStream
         : Asn1InputStream
     {
-        public LazyAsn1InputStream(
-            byte[] input)
+        public LazyAsn1InputStream(byte[] input)
             : base(input)
         {
         }
 
-        public LazyAsn1InputStream(
-            Stream inputStream)
+        public LazyAsn1InputStream(Stream inputStream)
             : base(inputStream)
         {
         }
@@ -23,16 +21,14 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
-        internal override DerSequence CreateDerSequence(
-            DefiniteLengthInputStream dIn)
+        internal override DerSequence CreateDLSequence(DefiniteLengthInputStream dIn)
         {
-            return new LazyDerSequence(dIn.ToArray());
+            return new LazyDLSequence(dIn.ToArray());
         }
 
-        internal override DerSet CreateDerSet(
-            DefiniteLengthInputStream dIn)
+        internal override DerSet CreateDLSet(DefiniteLengthInputStream dIn)
         {
-            return new LazyDerSet(dIn.ToArray());
+            return new LazyDLSet(dIn.ToArray());
         }
 
         internal override Asn1EncodableVector ReadVector(DefiniteLengthInputStream defIn)
diff --git a/crypto/src/asn1/LazyDERSequence.cs b/crypto/src/asn1/LazyDERSequence.cs
deleted file mode 100644
index e1ee29c81..000000000
--- a/crypto/src/asn1/LazyDERSequence.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using System;
-using System.Collections;
-
-namespace Org.BouncyCastle.Asn1
-{
-    internal class LazyDerSequence
-        : DerSequence
-    {
-        private byte[] encoded;
-
-        internal LazyDerSequence(byte[] encoded)
-            : base()
-        {
-            if (null == encoded)
-                throw new ArgumentNullException("encoded");
-
-            this.encoded = encoded;
-        }
-
-        private void Parse()
-        {
-            lock (this)
-            {
-                if (null != encoded)
-                {
-                    Asn1InputStream e = new LazyAsn1InputStream(encoded);
-                    Asn1EncodableVector v = e.ReadVector();
-
-                    this.elements = v.TakeElements();
-                    this.encoded = null;
-                }
-            }
-        }
-
-        public override Asn1Encodable this[int index]
-        {
-            get
-            {
-                Parse();
-
-                return base[index];
-            }
-        }
-
-        public override IEnumerator GetEnumerator()
-        {
-            // TODO[asn1] Support lazy enumeration
-            // lock (this) if (null != encoded) return new LazyConstructionEnumeration(encoded);
-
-            Parse();
-
-            return base.GetEnumerator();
-        }
-
-        public override int Count
-        {
-            get
-            {
-                Parse();
-
-                return base.Count;
-            }
-        }
-
-        public override Asn1Encodable[] ToArray()
-        {
-            Parse();
-
-            return base.ToArray();
-        }
-
-        public override string ToString()
-        {
-            Parse();
-
-            return base.ToString();
-        }
-
-        internal override int EncodedLength(bool withID)
-        {
-            lock (this)
-            {
-                if (encoded == null)
-                {
-                    return base.EncodedLength(withID);
-                }
-                else
-                {
-                    return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length);
-                }
-            }
-        }
-
-        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
-        {
-            lock (this)
-            {
-                if (encoded == null)
-                {
-                    base.Encode(asn1Out, withID);
-                }
-                else
-                {
-                    asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, encoded);
-                }
-            }
-        }
-    }
-}
diff --git a/crypto/src/asn1/LazyDERSet.cs b/crypto/src/asn1/LazyDERSet.cs
deleted file mode 100644
index 36e7bf53c..000000000
--- a/crypto/src/asn1/LazyDERSet.cs
+++ /dev/null
@@ -1,109 +0,0 @@
-using System;
-using System.Collections;
-
-namespace Org.BouncyCastle.Asn1
-{
-    internal class LazyDerSet
-        : DerSet
-    {
-        private byte[] encoded;
-
-        internal LazyDerSet(byte[] encoded)
-            : base()
-        {
-            if (null == encoded)
-                throw new ArgumentNullException("encoded");
-
-            this.encoded = encoded;
-        }
-
-        private void Parse()
-        {
-            lock (this)
-            {
-                if (encoded != null)
-                {
-                    Asn1InputStream e = new LazyAsn1InputStream(encoded);
-                    Asn1EncodableVector v = e.ReadVector();
-
-                    this.elements = v.TakeElements();
-                    this.encoded = null;
-                }
-            }
-        }
-
-        public override Asn1Encodable this[int index]
-        {
-            get
-            {
-                Parse();
-
-                return base[index];
-            }
-        }
-
-        public override IEnumerator GetEnumerator()
-        {
-            // TODO[asn1] Support lazy enumeration
-            // lock (this) if (null != encoded) return new LazyConstructionEnumeration(encoded);
-
-            Parse();
-
-            return base.GetEnumerator();
-        }
-
-        public override int Count
-        {
-            get
-            {
-                Parse();
-
-                return base.Count;
-            }
-        }
-
-        public override Asn1Encodable[] ToArray()
-        {
-            Parse();
-
-            return base.ToArray();
-        }
-
-        public override string ToString()
-        {
-            Parse();
-
-            return base.ToString();
-        }
-
-        internal override int EncodedLength(bool withID)
-        {
-            lock (this)
-            {
-                if (encoded == null)
-                {
-                    return base.EncodedLength(withID);
-                }
-                else
-                {
-                    return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length);
-                }
-            }
-        }
-
-        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
-        {
-            lock (this)
-            {
-                if (encoded == null)
-                {
-                    base.Encode(asn1Out, withID);
-                }
-                else
-                {
-                    asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, encoded);
-                }
-            }
-        }
-    }
-}
diff --git a/crypto/src/asn1/LazyDLEnumerator.cs b/crypto/src/asn1/LazyDLEnumerator.cs
new file mode 100644
index 000000000..efe383e3d
--- /dev/null
+++ b/crypto/src/asn1/LazyDLEnumerator.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    internal class LazyDLEnumerator
+        : IEnumerator
+    {
+        private readonly byte[] m_contents;
+
+        private Asn1InputStream m_input;
+        private Asn1Object m_current;
+
+        internal LazyDLEnumerator(byte[] contents)
+        {
+            this.m_contents = contents;
+
+            Reset();
+        }
+
+        public object Current
+        {
+            get
+            {
+                if (null == m_current)
+                    throw new InvalidOperationException();
+
+                return m_current;
+            }
+        }
+
+        public bool MoveNext()
+        {
+            return null != (this.m_current = ReadObject());
+        }
+
+        public void Reset()
+        {
+            this.m_input = new LazyAsn1InputStream(m_contents);
+            this.m_current = null;
+        }
+
+        private Asn1Object ReadObject()
+        {
+            try
+            {
+                return m_input.ReadObject();
+            }
+            catch (IOException e)
+            {
+                throw new Asn1ParsingException("malformed ASN.1: " + e.Message, e);
+            }
+        }
+    }
+}
diff --git a/crypto/src/asn1/LazyDLSequence.cs b/crypto/src/asn1/LazyDLSequence.cs
new file mode 100644
index 000000000..fe8e71794
--- /dev/null
+++ b/crypto/src/asn1/LazyDLSequence.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    internal class LazyDLSequence
+        : DerSequence
+    {
+        private byte[] encoded;
+
+        internal LazyDLSequence(byte[] encoded)
+            : base()
+        {
+            if (null == encoded)
+                throw new ArgumentNullException("encoded");
+
+            this.encoded = encoded;
+        }
+
+        public override Asn1Encodable this[int index]
+        {
+            get
+            {
+                Force();
+
+                return base[index];
+            }
+        }
+
+        public override IEnumerator GetEnumerator()
+        {
+            byte[] encoded = GetContents();
+            if (null != encoded)
+            {
+                return new LazyDLEnumerator(encoded);
+            }
+
+            return base.GetEnumerator();
+        }
+
+        public override int Count
+        {
+            get
+            {
+                Force();
+
+                return base.Count;
+            }
+        }
+
+        public override Asn1Encodable[] ToArray()
+        {
+            Force();
+
+            return base.ToArray();
+        }
+
+        public override string ToString()
+        {
+            Force();
+
+            return base.ToString();
+        }
+
+        internal override int EncodedLength(bool withID)
+        {
+            byte[] encoded = GetContents();
+            if (encoded != null)
+            {
+                return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length);
+            }
+
+            return base.EncodedLength(withID);
+        }
+
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
+        {
+            byte[] encoded = GetContents();
+            if (encoded != null)
+            {
+                asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Sequence, encoded);
+                return;
+            }
+
+            base.Encode(asn1Out, withID);
+        }
+
+        private void Force()
+        {
+            lock (this)
+            {
+                if (null != encoded)
+                {
+                    Asn1InputStream input = new LazyAsn1InputStream(encoded);
+                    try
+                    {
+                        Asn1EncodableVector v = input.ReadVector();
+
+                        this.elements = v.TakeElements();
+                        this.encoded = null;
+                    }
+                    catch (IOException e)
+                    {
+                        throw new Asn1ParsingException("malformed ASN.1: " + e.Message, e);
+                    }
+                }
+            }
+        }
+
+        private byte[] GetContents()
+        {
+            lock (this) return encoded;
+        }
+    }
+}
diff --git a/crypto/src/asn1/LazyDLSet.cs b/crypto/src/asn1/LazyDLSet.cs
new file mode 100644
index 000000000..f644f69e5
--- /dev/null
+++ b/crypto/src/asn1/LazyDLSet.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    internal class LazyDLSet
+        : DerSet
+    {
+        private byte[] encoded;
+
+        internal LazyDLSet(byte[] encoded)
+            : base()
+        {
+            if (null == encoded)
+                throw new ArgumentNullException("encoded");
+
+            this.encoded = encoded;
+        }
+
+        public override Asn1Encodable this[int index]
+        {
+            get
+            {
+                Force();
+
+                return base[index];
+            }
+        }
+
+        public override IEnumerator GetEnumerator()
+        {
+            byte[] encoded = GetContents();
+            if (null != encoded)
+            {
+                return new LazyDLEnumerator(encoded);
+            }
+
+            return base.GetEnumerator();
+        }
+
+        public override int Count
+        {
+            get
+            {
+                Force();
+
+                return base.Count;
+            }
+        }
+
+        public override Asn1Encodable[] ToArray()
+        {
+            Force();
+
+            return base.ToArray();
+        }
+
+        public override string ToString()
+        {
+            Force();
+
+            return base.ToString();
+        }
+
+        internal override int EncodedLength(bool withID)
+        {
+            byte[] encoded = GetContents();
+            if (encoded != null)
+            {
+                return Asn1OutputStream.GetLengthOfEncodingDL(withID, encoded.Length);
+            }
+
+            return base.EncodedLength(withID);
+        }
+
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
+        {
+            byte[] encoded = GetContents();
+            if (encoded != null)
+            {
+                asn1Out.WriteEncodingDL(withID, Asn1Tags.Constructed | Asn1Tags.Set, encoded);
+                return;
+            }
+
+            base.Encode(asn1Out, withID);
+        }
+
+        private void Force()
+        {
+            lock (this)
+            {
+                if (null != encoded)
+                {
+                    Asn1InputStream input = new LazyAsn1InputStream(encoded);
+                    try
+                    {
+                        Asn1EncodableVector v = input.ReadVector();
+
+                        this.elements = v.TakeElements();
+                        this.encoded = null;
+                    }
+                    catch (IOException e)
+                    {
+                        throw new Asn1ParsingException("malformed ASN.1: " + e.Message, e);
+                    }
+                }
+            }
+        }
+
+        private byte[] GetContents()
+        {
+            lock (this) return encoded;
+        }
+    }
+}