summary refs log tree commit diff
path: root/crypto/src/asn1
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2023-03-05 14:45:49 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2023-03-05 14:45:49 +0700
commit6b59dbbece3b1509b83b8479259a3c6059e9a60b (patch)
tree3dca66ea9a1e8aa02ac6099cde5844155783bd7b /crypto/src/asn1
parentRefactor Asn1Set classes (diff)
downloadBouncyCastle.NET-ed25519-6b59dbbece3b1509b83b8479259a3c6059e9a60b.tar.xz
Support 'leaveOpen' in Asn1 streams
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs43
-rw-r--r--crypto/src/asn1/Asn1OutputStream.cs46
-rw-r--r--crypto/src/asn1/BEROctetStringGenerator.cs4
-rw-r--r--crypto/src/asn1/DerOutputStream.cs4
-rw-r--r--crypto/src/asn1/LazyASN1InputStream.cs19
-rw-r--r--crypto/src/asn1/util/Asn1Dump.cs10
6 files changed, 100 insertions, 26 deletions
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 33db1e6d7..e250fe500 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -19,6 +19,7 @@ namespace Org.BouncyCastle.Asn1
         : FilterStream
     {
         private readonly int limit;
+        private readonly bool m_leaveOpen;
 
         internal byte[][] tmpBuffers;
 
@@ -36,11 +37,6 @@ namespace Org.BouncyCastle.Asn1
             return int.MaxValue;
         }
 
-        public Asn1InputStream(Stream input)
-            : this(input, FindLimit(input))
-        {
-        }
-
         /**
          * Create an ASN1InputStream based on the input byte array. The length of DER objects in
          * the stream is automatically limited to the length of the input array.
@@ -52,6 +48,11 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
+        public Asn1InputStream(Stream input)
+            : this(input, FindLimit(input))
+        {
+        }
+
         /**
          * Create an ASN1InputStream where no DER object will be longer than limit.
          *
@@ -59,22 +60,41 @@ namespace Org.BouncyCastle.Asn1
          * @param limit maximum size of a DER encoded object.
          */
         public Asn1InputStream(Stream input, int limit)
-            : this(input, limit, new byte[16][])
+            : this(input, limit, false)
+        {
+        }
+
+        public Asn1InputStream(Stream input, int limit, bool leaveOpen)
+            : this(input, limit, leaveOpen, new byte[16][])
         {
         }
 
-        internal Asn1InputStream(Stream input, int limit, byte[][] tmpBuffers)
+        internal Asn1InputStream(Stream input, int limit, bool leaveOpen, byte[][] tmpBuffers)
             : base(input)
         {
+            if (!input.CanRead)
+                throw new ArgumentException("Expected stream to be readable", nameof(input));
+
             this.limit = limit;
+            m_leaveOpen = leaveOpen;
             this.tmpBuffers = tmpBuffers;
         }
 
         protected override void Dispose(bool disposing)
         {
-            tmpBuffers = null;
+            if (disposing)
+            {
+                tmpBuffers = null;
+            }
 
-            base.Dispose(disposing);
+            if (m_leaveOpen)
+            {
+                base.Detach(disposing);
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
         }
 
         /**
@@ -146,7 +166,10 @@ namespace Org.BouncyCastle.Asn1
             if (remaining < 1)
                 return new Asn1EncodableVector(0);
 
-            return new Asn1InputStream(defIn, remaining, tmpBuffers).ReadVector();
+            using (var sub = new Asn1InputStream(defIn, remaining, leaveOpen: true, tmpBuffers))
+            {
+                return sub.ReadVector();
+            }
         }
 
         internal virtual Asn1Sequence CreateDLSequence(DefiniteLengthInputStream defIn)
diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs
index 745674930..588c3733d 100644
--- a/crypto/src/asn1/Asn1OutputStream.cs
+++ b/crypto/src/asn1/Asn1OutputStream.cs
@@ -18,20 +18,56 @@ namespace Org.BouncyCastle.Asn1
 
         public static Asn1OutputStream Create(Stream output)
         {
-            return new Asn1OutputStream(output);
+            return Create(output, Asn1Encodable.Ber);
         }
 
         public static Asn1OutputStream Create(Stream output, string encoding)
         {
+            return Create(output, encoding, false);
+        }
+
+        public static Asn1OutputStream Create(Stream output, string encoding, bool leaveOpen)
+        {
+            if (Asn1Encodable.Der.Equals(encoding))
+                return new DerOutputStream(output, leaveOpen);
+
+            return new Asn1OutputStream(output, leaveOpen);
+        }
+
+        internal static int GetEncodingType(string encoding)
+        {
             if (Asn1Encodable.Der.Equals(encoding))
-                return new DerOutputStream(output);
+                return EncodingDer;
+
+            return EncodingBer;
+        }
 
-            return new Asn1OutputStream(output);
+        private readonly bool m_leaveOpen;
+
+        internal Asn1OutputStream(Stream output, bool leaveOpen)
+            : base(output)
+        {
+            if (!output.CanWrite)
+                throw new ArgumentException("Expected stream to be writable", nameof(output));
+
+            m_leaveOpen = leaveOpen;
         }
 
-        internal Asn1OutputStream(Stream os)
-            : base(os)
+        protected override void Dispose(bool disposing)
         {
+            if (disposing)
+            {
+                FlushInternal();
+            }
+
+            if (m_leaveOpen)
+            {
+                base.Detach(disposing);
+            }
+            else
+            {
+                base.Dispose(disposing);
+            }
         }
 
         public virtual void WriteObject(Asn1Encodable asn1Encodable)
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index 5472802a2..ed2b85010 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -54,7 +54,7 @@ namespace Org.BouncyCastle.Asn1
 			{
 				_buf = buf;
 				_off = 0;
-				_derOut = Asn1OutputStream.Create(outStream, Asn1Encodable.Der);
+				_derOut = Asn1OutputStream.Create(outStream, Asn1Encodable.Der, leaveOpen: true);
 			}
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -145,7 +145,7 @@ namespace Org.BouncyCastle.Asn1
                         _off = 0;
                     }
 
-                    _derOut.FlushInternal();
+                    _derOut.Dispose();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs
index 6304ca852..509bd436b 100644
--- a/crypto/src/asn1/DerOutputStream.cs
+++ b/crypto/src/asn1/DerOutputStream.cs
@@ -6,8 +6,8 @@ namespace Org.BouncyCastle.Asn1
     internal class DerOutputStream
         : Asn1OutputStream
     {
-        internal DerOutputStream(Stream os)
-            : base(os)
+        internal DerOutputStream(Stream os, bool leaveOpen)
+            : base(os, leaveOpen)
         {
         }
 
diff --git a/crypto/src/asn1/LazyASN1InputStream.cs b/crypto/src/asn1/LazyASN1InputStream.cs
index 8dfbba122..8807416f4 100644
--- a/crypto/src/asn1/LazyASN1InputStream.cs
+++ b/crypto/src/asn1/LazyASN1InputStream.cs
@@ -16,8 +16,18 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
-        internal LazyAsn1InputStream(Stream input, int limit, byte[][] tmpBuffers)
-            : base(input, limit, tmpBuffers)
+        public LazyAsn1InputStream(Stream input, int limit)
+            : base(input, limit)
+        {
+        }
+
+        public LazyAsn1InputStream(Stream input, int limit, bool leaveOpen)
+            : base(input, limit, leaveOpen)
+        {
+        }
+
+        internal LazyAsn1InputStream(Stream input, int limit, bool leaveOpen, byte[][] tmpBuffers)
+            : base(input, limit, leaveOpen, tmpBuffers)
         {
         }
 
@@ -37,7 +47,10 @@ namespace Org.BouncyCastle.Asn1
             if (remaining < 1)
                 return new Asn1EncodableVector(0);
 
-            return new LazyAsn1InputStream(defIn, remaining, tmpBuffers).ReadVector();
+            using (var sub = new LazyAsn1InputStream(defIn, remaining, leaveOpen: true, tmpBuffers))
+            {
+                return sub.ReadVector();
+            }
         }
     }
 }
diff --git a/crypto/src/asn1/util/Asn1Dump.cs b/crypto/src/asn1/util/Asn1Dump.cs
index 3a19f1276..67fbba979 100644
--- a/crypto/src/asn1/util/Asn1Dump.cs
+++ b/crypto/src/asn1/util/Asn1Dump.cs
@@ -256,11 +256,13 @@ namespace Org.BouncyCastle.Asn1.Utilities
         /// <summary>Parse ASN.1 objects from input <see cref="Stream"/>, and write them to the output.</summary>
         public static void Dump(Stream input, TextWriter output)
         {
-            Asn1InputStream asn1InputStream = new Asn1InputStream(input);
-            Asn1Object asn1Object;
-            while ((asn1Object = asn1InputStream.ReadObject()) != null)
+            using (var asn1In = new Asn1InputStream(input, int.MaxValue, leaveOpen: true))
             {
-                output.Write(DumpAsString(asn1Object));
+                Asn1Object asn1Object;
+                while ((asn1Object = asn1In.ReadObject()) != null)
+                {
+                    output.Write(DumpAsString(asn1Object));
+                }
             }
         }