summary refs log tree commit diff
path: root/crypto/src
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src')
-rw-r--r--crypto/src/asn1/ASN1Generator.cs37
-rw-r--r--crypto/src/asn1/BERGenerator.cs68
-rw-r--r--crypto/src/asn1/BEROctetStringGenerator.cs56
-rw-r--r--crypto/src/asn1/DERGenerator.cs88
-rw-r--r--crypto/src/asn1/DERSequenceGenerator.cs20
-rw-r--r--crypto/src/asn1/DERSetGenerator.cs20
-rw-r--r--crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs47
-rw-r--r--crypto/src/cms/CMSCompressedDataStreamGenerator.cs24
-rw-r--r--crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs39
-rw-r--r--crypto/src/cms/CMSSignedDataStreamGenerator.cs35
-rw-r--r--crypto/src/cms/CMSUtils.cs6
11 files changed, 229 insertions, 211 deletions
diff --git a/crypto/src/asn1/ASN1Generator.cs b/crypto/src/asn1/ASN1Generator.cs
index cd2d06e72..28fffc6ab 100644
--- a/crypto/src/asn1/ASN1Generator.cs
+++ b/crypto/src/asn1/ASN1Generator.cs
@@ -1,20 +1,23 @@
+using System;
 using System.IO;
 
 namespace Org.BouncyCastle.Asn1
 {
     public abstract class Asn1Generator
+        : IDisposable
     {
-		private Stream _out;
+		private Stream m_outStream;
 
-		protected Asn1Generator(
-			Stream outStream)
+		protected Asn1Generator(Stream outStream)
         {
-            _out = outStream;
+            m_outStream = outStream ?? throw new ArgumentNullException(nameof(outStream));
         }
 
-		protected Stream Out
+        protected abstract void Finish();
+
+		protected Stream OutStream
 		{
-			get { return _out; }
+			get { return m_outStream ?? throw new InvalidOperationException(); }
 		}
 
 		public abstract void AddObject(Asn1Encodable obj);
@@ -23,6 +26,26 @@ namespace Org.BouncyCastle.Asn1
 
         public abstract Stream GetRawOutputStream();
 
-		public abstract void Close();
+        #region IDisposable
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (m_outStream != null) 
+                {
+                    Finish();
+                    m_outStream = null;
+                }
+            }
+        }
+
+        #endregion
     }
 }
diff --git a/crypto/src/asn1/BERGenerator.cs b/crypto/src/asn1/BERGenerator.cs
index e43d9f80c..073c36a30 100644
--- a/crypto/src/asn1/BERGenerator.cs
+++ b/crypto/src/asn1/BERGenerator.cs
@@ -1,3 +1,4 @@
+using System;
 using System.IO;
 
 using Org.BouncyCastle.Utilities.IO;
@@ -7,20 +8,16 @@ namespace Org.BouncyCastle.Asn1
     public abstract class BerGenerator
         : Asn1Generator
     {
-        private bool      _tagged = false;
-        private bool      _isExplicit;
-        private int          _tagNo;
+        private bool _tagged = false;
+        private bool _isExplicit;
+        private int _tagNo;
 
-        protected BerGenerator(
-            Stream outStream)
+        protected BerGenerator(Stream outStream)
             : base(outStream)
         {
         }
 
-        protected BerGenerator(
-            Stream outStream,
-            int tagNo,
-            bool isExplicit)
+        protected BerGenerator(Stream outStream, int tagNo, bool isExplicit)
             : base(outStream)
         {
             _tagged = true;
@@ -28,35 +25,33 @@ namespace Org.BouncyCastle.Asn1
             _tagNo = tagNo;
         }
 
-		public override void AddObject(Asn1Encodable obj)
+        protected override void Finish()
+        {
+            WriteBerEnd();
+        }
+
+        public override void AddObject(Asn1Encodable obj)
 		{
-            obj.EncodeTo(Out);
+            obj.EncodeTo(OutStream);
 		}
 
         public override void AddObject(Asn1Object obj)
         {
-            obj.EncodeTo(Out);
+            obj.EncodeTo(OutStream);
         }
 
         public override Stream GetRawOutputStream()
         {
-            return Out;
+            return OutStream;
         }
 
-		public override void Close()
-		{
-			WriteBerEnd();
-		}
-
-        private void WriteHdr(
-            int tag)
+        private void WriteHdr(int tag)
         {
-            Out.WriteByte((byte) tag);
-            Out.WriteByte(0x80);
+            OutStream.WriteByte((byte)tag);
+            OutStream.WriteByte(0x80);
         }
 
-        protected void WriteBerHeader(
-            int tag)
+        protected void WriteBerHeader(int tag)
         {
             if (_tagged)
             {
@@ -85,22 +80,33 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-		protected void WriteBerBody(
-            Stream contentStream)
+		protected void WriteBerBody(Stream contentStream)
         {
-			Streams.PipeAll(contentStream, Out);
+			Streams.PipeAll(contentStream, OutStream);
         }
 
 		protected void WriteBerEnd()
         {
-            Out.WriteByte(0x00);
-            Out.WriteByte(0x00);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            Span<byte> data = stackalloc byte[4]{ 0x00, 0x00, 0x00, 0x00 };
+            if (_tagged && _isExplicit)  // write extra end for tag header
+            {
+                OutStream.Write(data[..4]);
+            }
+            else
+            {
+                OutStream.Write(data[..2]);
+            }
+#else
+            OutStream.WriteByte(0x00);
+            OutStream.WriteByte(0x00);
 
             if (_tagged && _isExplicit)  // write extra end for tag header
             {
-                Out.WriteByte(0x00);
-                Out.WriteByte(0x00);
+                OutStream.WriteByte(0x00);
+                OutStream.WriteByte(0x00);
             }
+#endif
         }
     }
 }
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index b07576e7d..5472802a2 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -8,38 +8,39 @@ namespace Org.BouncyCastle.Asn1
 	public class BerOctetStringGenerator
 		: BerGenerator
 	{
-		public BerOctetStringGenerator(Stream outStream)
-			: base(outStream)
-		{
-			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
-		}
+        public BerOctetStringGenerator(Stream outStream)
+            : base(outStream)
+        {
+            WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+        }
 
-		public BerOctetStringGenerator(
-			Stream	outStream,
-			int		tagNo,
-			bool	isExplicit)
-			: base(outStream, tagNo, isExplicit)
-		{
-			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
-		}
+        public BerOctetStringGenerator(Stream outStream, int tagNo, bool isExplicit)
+            : base(outStream, tagNo, isExplicit)
+        {
+            WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+        }
 
+        /// <remarks>The caller is responsible for disposing the returned <see cref="Stream"/> before disposing
+        /// this generator.</remarks>
 		public Stream GetOctetOutputStream()
 		{
 			return GetOctetOutputStream(new byte[1000]); // limit for CER encoding.
 		}
 
-		public Stream GetOctetOutputStream(
-			int bufSize)
+        /// <remarks>The caller is responsible for disposing the returned <see cref="Stream"/> before disposing
+        /// this generator.</remarks>
+		public Stream GetOctetOutputStream(int bufSize)
 		{
-			return bufSize < 1
-				?	GetOctetOutputStream()
-				:	GetOctetOutputStream(new byte[bufSize]);
-		}
+            return bufSize < 1
+                ? GetOctetOutputStream()
+                : GetOctetOutputStream(new byte[bufSize]);
+        }
 
-		public Stream GetOctetOutputStream(
-			byte[] buf)
+        /// <remarks>The caller is responsible for disposing the returned <see cref="Stream"/> before disposing
+        /// this generator.</remarks>
+		public Stream GetOctetOutputStream(byte[] buf)
 		{
-			return new BufferedBerOctetStream(this, buf);
+			return new BufferedBerOctetStream(GetRawOutputStream(), buf);
 		}
 
 		private class BufferedBerOctetStream
@@ -47,17 +48,13 @@ namespace Org.BouncyCastle.Asn1
 		{
 			private byte[] _buf;
 			private int    _off;
-			private readonly BerOctetStringGenerator _gen;
 			private readonly Asn1OutputStream _derOut;
 
-			internal BufferedBerOctetStream(
-				BerOctetStringGenerator	gen,
-				byte[]					buf)
+			internal BufferedBerOctetStream(Stream outStream, byte[] buf)
 			{
-				_gen = gen;
 				_buf = buf;
 				_off = 0;
-				_derOut = Asn1OutputStream.Create(_gen.Out, Asn1Encodable.Der);
+				_derOut = Asn1OutputStream.Create(outStream, Asn1Encodable.Der);
 			}
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -145,11 +142,10 @@ namespace Org.BouncyCastle.Asn1
                     if (_off != 0)
                     {
                         DerOctetString.Encode(_derOut, _buf, 0, _off);
+                        _off = 0;
                     }
 
                     _derOut.FlushInternal();
-
-                    _gen.WriteBerEnd();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/asn1/DERGenerator.cs b/crypto/src/asn1/DERGenerator.cs
index 387a2c5f8..4bdc60972 100644
--- a/crypto/src/asn1/DERGenerator.cs
+++ b/crypto/src/asn1/DERGenerator.cs
@@ -11,16 +11,12 @@ namespace Org.BouncyCastle.Asn1
         private bool _isExplicit;
         private int _tagNo;
 
-		protected DerGenerator(
-            Stream outStream)
+        protected DerGenerator(Stream outStream)
             : base(outStream)
 		{
         }
 
-        protected DerGenerator(
-            Stream outStream,
-            int tagNo,
-            bool isExplicit)
+        protected DerGenerator(Stream outStream, int tagNo, bool isExplicit)
             : base(outStream)
         {
             _tagged = true;
@@ -28,80 +24,70 @@ namespace Org.BouncyCastle.Asn1
             _tagNo = tagNo;
         }
 
-		private static void WriteLength(
-            Stream	outStr,
-            int		length)
+		internal void WriteDerEncoded(int tag, byte[] bytes)
         {
-            if (length > 127)
+            if (_tagged)
             {
-                int size = 1;
-                int val = length;
+                int tagNum = _tagNo | Asn1Tags.ContextSpecific;
 
-				while ((val >>= 8) != 0)
+                if (_isExplicit)
                 {
-                    size++;
+                    int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.ContextSpecific;
+					MemoryStream bOut = new MemoryStream();
+                    WriteDerEncoded(bOut, tag, bytes);
+                    WriteDerEncoded(OutStream, newTag, bOut.ToArray());
                 }
-
-				outStr.WriteByte((byte)(size | 0x80));
-
-				for (int i = (size - 1) * 8; i >= 0; i -= 8)
+                else
                 {
-                    outStr.WriteByte((byte)(length >> i));
+					if ((tag & Asn1Tags.Constructed) != 0)
+					{
+						tagNum |= Asn1Tags.Constructed;
+					}
+
+					WriteDerEncoded(OutStream, tagNum, bytes);
                 }
             }
             else
             {
-                outStr.WriteByte((byte)length);
+                WriteDerEncoded(OutStream, tag, bytes);
             }
         }
 
-		internal static void WriteDerEncoded(
-            Stream	outStream,
-            int		tag,
-            byte[]	bytes)
+        internal static void WriteDerEncoded(Stream outStream, int tag, byte[] bytes)
         {
-            outStream.WriteByte((byte) tag);
+            outStream.WriteByte((byte)tag);
             WriteLength(outStream, bytes.Length);
             outStream.Write(bytes, 0, bytes.Length);
         }
 
-		internal void WriteDerEncoded(
-            int		tag,
-            byte[]	bytes)
+        internal static void WriteDerEncoded(Stream	outStream, int tag, Stream	inStream)
         {
-            if (_tagged)
+			WriteDerEncoded(outStream, tag, Streams.ReadAll(inStream));
+        }
+
+        private static void WriteLength(Stream outStream, int length)
+        {
+            if (length > 127)
             {
-                int tagNum = _tagNo | Asn1Tags.ContextSpecific;
+                int size = 1;
+                int val = length;
 
-                if (_isExplicit)
+                while ((val >>= 8) != 0)
                 {
-                    int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.ContextSpecific;
-					MemoryStream bOut = new MemoryStream();
-                    WriteDerEncoded(bOut, tag, bytes);
-                    WriteDerEncoded(Out, newTag, bOut.ToArray());
+                    size++;
                 }
-                else
-                {
-					if ((tag & Asn1Tags.Constructed) != 0)
-					{
-						tagNum |= Asn1Tags.Constructed;
-					}
 
-					WriteDerEncoded(Out, tagNum, bytes);
+                outStream.WriteByte((byte)(size | 0x80));
+
+                for (int i = (size - 1) * 8; i >= 0; i -= 8)
+                {
+                    outStream.WriteByte((byte)(length >> i));
                 }
             }
             else
             {
-                WriteDerEncoded(Out, tag, bytes);
+                outStream.WriteByte((byte)length);
             }
         }
-
-		internal static void WriteDerEncoded(
-            Stream	outStr,
-            int		tag,
-            Stream	inStr)
-        {
-			WriteDerEncoded(outStr, tag, Streams.ReadAll(inStr));
-        }
     }
 }
diff --git a/crypto/src/asn1/DERSequenceGenerator.cs b/crypto/src/asn1/DERSequenceGenerator.cs
index 12c978508..be240a86c 100644
--- a/crypto/src/asn1/DERSequenceGenerator.cs
+++ b/crypto/src/asn1/DERSequenceGenerator.cs
@@ -7,21 +7,22 @@ namespace Org.BouncyCastle.Asn1
 	{
 		private readonly MemoryStream _bOut = new MemoryStream();
 
-		public DerSequenceGenerator(
-			Stream outStream)
+		public DerSequenceGenerator(Stream outStream)
 			: base(outStream)
 		{
 		}
 
-		public DerSequenceGenerator(
-			Stream	outStream,
-			int		tagNo,
-			bool	isExplicit)
+		public DerSequenceGenerator(Stream outStream, int tagNo, bool isExplicit)
 			: base(outStream, tagNo, isExplicit)
 		{
 		}
 
-		public override void AddObject(Asn1Encodable obj)
+        protected override void Finish()
+        {
+            WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray());
+        }
+
+        public override void AddObject(Asn1Encodable obj)
 		{
             obj.EncodeTo(_bOut, Asn1Encodable.Der);
 		}
@@ -35,10 +36,5 @@ namespace Org.BouncyCastle.Asn1
 		{
 			return _bOut;
 		}
-
-		public override void Close()
-		{
-			WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray());
-		}
 	}
 }
diff --git a/crypto/src/asn1/DERSetGenerator.cs b/crypto/src/asn1/DERSetGenerator.cs
index 677241798..642744951 100644
--- a/crypto/src/asn1/DERSetGenerator.cs
+++ b/crypto/src/asn1/DERSetGenerator.cs
@@ -7,21 +7,22 @@ namespace Org.BouncyCastle.Asn1
 	{
 		private readonly MemoryStream _bOut = new MemoryStream();
 
-		public DerSetGenerator(
-			Stream outStream)
+		public DerSetGenerator(Stream outStream)
 			: base(outStream)
 		{
 		}
 
-		public DerSetGenerator(
-			Stream	outStream,
-			int		tagNo,
-			bool	isExplicit)
+		public DerSetGenerator(Stream outStream, int tagNo, bool isExplicit)
 			: base(outStream, tagNo, isExplicit)
 		{
 		}
 
-		public override void AddObject(Asn1Encodable obj)
+        protected override void Finish()
+        {
+            WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray());
+        }
+
+        public override void AddObject(Asn1Encodable obj)
 		{
             obj.EncodeTo(_bOut, Asn1Encodable.Der);
 		}
@@ -35,10 +36,5 @@ namespace Org.BouncyCastle.Asn1
 		{
 			return _bOut;
 		}
-
-		public override void Close()
-		{
-			WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray());
-		}
 	}
 }
diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
index fd2c743bb..054a9c45e 100644
--- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
@@ -140,31 +140,30 @@ namespace Org.BouncyCastle.Cms
 				authGen.AddObject(new DerInteger(AuthenticatedData.CalculateVersion(null)));
 
 				Stream authRaw = authGen.GetRawOutputStream();
-				Asn1Generator recipGen = _berEncodeRecipientSet
-					?	(Asn1Generator) new BerSetGenerator(authRaw)
-					:	new DerSetGenerator(authRaw);
-
-				foreach (Asn1Encodable ae in recipientInfos)
+				using (var recipGen = _berEncodeRecipientSet
+					? (Asn1Generator)new BerSetGenerator(authRaw)
+					: new DerSetGenerator(authRaw))
 				{
-					recipGen.AddObject(ae);
-				}
-
-				recipGen.Close();
+                    foreach (Asn1Encodable ae in recipientInfos)
+                    {
+                        recipGen.AddObject(ae);
+                    }
+                }
 
 				authGen.AddObject(macAlgId);
 
 				BerSequenceGenerator eiGen = new BerSequenceGenerator(authRaw);
 				eiGen.AddObject(CmsObjectIdentifiers.Data);
 
-				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
-					eiGen.GetRawOutputStream(), 0, true, _bufferSize);
+                BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
+                Stream octetOutputStream = octGen.GetOctetOutputStream(_bufferSize);
 
                 IMac mac = MacUtilities.GetMac(macAlgId.Algorithm);
 				// TODO Confirm no ParametersWithRandom needed
 	            mac.Init(cipherParameters);
 				Stream mOut = new TeeOutputStream(octetOutputStream, new MacSink(mac));
 
-				return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen);
+				return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen, octGen);
 			}
 			catch (SecurityUtilityException e)
 			{
@@ -214,23 +213,26 @@ namespace Org.BouncyCastle.Cms
 		{
 			private readonly Stream					macStream;
 			private readonly IMac					mac;
-			private readonly BerSequenceGenerator	cGen;
+            private readonly BerSequenceGenerator	cGen;
 			private readonly BerSequenceGenerator	authGen;
 			private readonly BerSequenceGenerator	eiGen;
+            private readonly BerOctetStringGenerator octGen;
 
-			public CmsAuthenticatedDataOutputStream(
+            public CmsAuthenticatedDataOutputStream(
 				Stream					macStream,
 				IMac					mac,
-				BerSequenceGenerator	cGen,
+                BerSequenceGenerator	cGen,
 				BerSequenceGenerator	authGen,
-				BerSequenceGenerator	eiGen)
-			{
+				BerSequenceGenerator	eiGen,
+                BerOctetStringGenerator octGen)
+            {
 				this.macStream = macStream;
 				this.mac = mac;
 				this.cGen = cGen;
 				this.authGen = authGen;
 				this.eiGen = eiGen;
-			}
+                this.octGen = octGen;
+            }
 
             public override void Write(byte[] buffer, int offset, int count)
             {
@@ -255,17 +257,18 @@ namespace Org.BouncyCastle.Cms
                 {
                     macStream.Dispose();
 
-                    // TODO Parent context(s) should really be be closed explicitly
+					// TODO Parent context(s) should really be be closed explicitly
 
-				    eiGen.Close();
+					octGen.Dispose();
+				    eiGen.Dispose();
 
 				    // [TODO] auth attributes go here 
 				    byte[] macOctets = MacUtilities.DoFinal(mac);
 				    authGen.AddObject(new DerOctetString(macOctets));
 				    // [TODO] unauth attributes go here
 
-				    authGen.Close();
-				    cGen.Close();
+				    authGen.Dispose();
+				    cGen.Dispose();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
index 64a978c6d..f992a8269 100644
--- a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
@@ -87,11 +87,11 @@ namespace Org.BouncyCastle.Cms
 
 			eiGen.AddObject(new DerObjectIdentifier(contentOid));
 
-			Stream octetStream = CmsUtilities.CreateBerOctetOutputStream(
-				eiGen.GetRawOutputStream(), 0, true, _bufferSize);
+            BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
+            Stream octetStream = octGen.GetOctetOutputStream(_bufferSize);
 
-			return new CmsCompressedOutputStream(
-				Utilities.IO.Compression.ZLib.CompressOutput(octetStream, -1), sGen, cGen, eiGen);
+            return new CmsCompressedOutputStream(
+				Utilities.IO.Compression.ZLib.CompressOutput(octetStream, -1), sGen, cGen, eiGen, octGen);
 		}
 
 		private class CmsCompressedOutputStream
@@ -101,17 +101,20 @@ namespace Org.BouncyCastle.Cms
 			private BerSequenceGenerator _sGen;
 			private BerSequenceGenerator _cGen;
 			private BerSequenceGenerator _eiGen;
+			private BerOctetStringGenerator _octGen;
 
-			internal CmsCompressedOutputStream(
+            internal CmsCompressedOutputStream(
 				Stream					outStream,
 				BerSequenceGenerator	sGen,
 				BerSequenceGenerator	cGen,
-				BerSequenceGenerator	eiGen)
+				BerSequenceGenerator	eiGen,
+                BerOctetStringGenerator octGen)
 			{
 				_out = outStream;
 				_sGen = sGen;
 				_cGen = cGen;
 				_eiGen = eiGen;
+				_octGen = octGen;
 			}
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -137,11 +140,12 @@ namespace Org.BouncyCastle.Cms
                 {
                     _out.Dispose();
 
-                    // TODO Parent context(s) should really be be closed explicitly
+					// TODO Parent context(s) should really be be closed explicitly
 
-                    _eiGen.Close();
-				    _cGen.Close();
-				    _sGen.Close();
+					_octGen.Dispose();
+                    _eiGen.Dispose();
+				    _cGen.Dispose();
+				    _sGen.Dispose();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
index cfd3dde10..64d501a41 100644
--- a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
@@ -142,29 +142,28 @@ namespace Org.BouncyCastle.Cms
 				envGen.AddObject(this.Version);
 
 				Stream envRaw = envGen.GetRawOutputStream();
-				Asn1Generator recipGen = _berEncodeRecipientSet
-					?	(Asn1Generator) new BerSetGenerator(envRaw)
-					:	new DerSetGenerator(envRaw);
-
-				foreach (Asn1Encodable ae in recipientInfos)
+				using (var recipGen = _berEncodeRecipientSet
+					? (Asn1Generator)new BerSetGenerator(envRaw)
+					: new DerSetGenerator(envRaw))
 				{
-					recipGen.AddObject(ae);
-				}
-
-				recipGen.Close();
+                    foreach (Asn1Encodable ae in recipientInfos)
+                    {
+                        recipGen.AddObject(ae);
+                    }
+                }
 
 				BerSequenceGenerator eiGen = new BerSequenceGenerator(envRaw);
 				eiGen.AddObject(CmsObjectIdentifiers.Data);
 				eiGen.AddObject(encAlgID);
 
-				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
-					eiGen.GetRawOutputStream(), 0, false, _bufferSize);
+                BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, false);
+                Stream octetOutputStream = octGen.GetOctetOutputStream(_bufferSize);
 
                 IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.Algorithm);
 				cipher.Init(true, new ParametersWithRandom(cipherParameters, m_random));
 				CipherStream cOut = new CipherStream(octetOutputStream, null, cipher);
 
-				return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen);
+				return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen, octGen);
 			}
 			catch (SecurityUtilityException e)
 			{
@@ -220,19 +219,22 @@ namespace Org.BouncyCastle.Cms
 			private readonly BerSequenceGenerator	_cGen;
 			private readonly BerSequenceGenerator	_envGen;
 			private readonly BerSequenceGenerator	_eiGen;
+			private readonly BerOctetStringGenerator _octGen;
 
-			public CmsEnvelopedDataOutputStream(
+            public CmsEnvelopedDataOutputStream(
 				CmsEnvelopedGenerator	outer,
 				CipherStream			outStream,
 				BerSequenceGenerator	cGen,
 				BerSequenceGenerator	envGen,
-				BerSequenceGenerator	eiGen)
+				BerSequenceGenerator	eiGen,
+                BerOctetStringGenerator octGen)
 			{
 				_outer = outer;
 				_out = outStream;
 				_cGen = cGen;
 				_envGen = envGen;
 				_eiGen = eiGen;
+				_octGen = octGen;
 			}
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -258,9 +260,10 @@ namespace Org.BouncyCastle.Cms
  				{
                     _out.Dispose();
 
-                    // TODO Parent context(s) should really be closed explicitly
+					// TODO Parent context(s) should really be closed explicitly
 
-                    _eiGen.Close();
+					_octGen.Dispose();
+                    _eiGen.Dispose();
 
                     if (_outer.unprotectedAttributeGenerator != null)
                     {
@@ -272,8 +275,8 @@ namespace Org.BouncyCastle.Cms
                         _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
                     }
 
-                    _envGen.Close();
-                    _cGen.Close();
+                    _envGen.Dispose();
+                    _cGen.Dispose();
                 }
                 base.Dispose(disposing);
             }
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index a4e960ba6..33b661761 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -570,18 +570,23 @@ namespace Org.BouncyCastle.Cms
 			BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
             eiGen.AddObject(contentTypeOid);
 
-        	// If encapsulating, add the data as an octet string in the sequence
-			Stream encapStream = encapsulate
-				?	CmsUtilities.CreateBerOctetOutputStream(eiGen.GetRawOutputStream(), 0, true, _bufferSize)
-				:	null;
+			BerOctetStringGenerator octGen = null;
+			Stream encapStream = null;
 
-        	// Also send the data to 'dataOutputStream' if necessary
-			Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream);
+            // If encapsulating, add the data as an octet string in the sequence
+            if (encapsulate)
+			{
+                octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
+                encapStream = octGen.GetOctetOutputStream(_bufferSize);
+            }
+
+            // Also send the data to 'dataOutputStream' if necessary
+            Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream);
 
         	// Let all the digests see the data as it is written
 			Stream digStream = AttachDigestsToOutputStream(m_messageDigests.Values, teeStream);
 
-			return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
+			return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen, octGen);
         }
 
 		private void RegisterDigestOid(
@@ -761,14 +766,16 @@ namespace Org.BouncyCastle.Cms
             private BerSequenceGenerator	_sGen;
             private BerSequenceGenerator	_sigGen;
             private BerSequenceGenerator	_eiGen;
+			private BerOctetStringGenerator _octGen;
 
-			public CmsSignedDataOutputStream(
+            public CmsSignedDataOutputStream(
 				CmsSignedDataStreamGenerator	outer,
 				Stream							outStream,
                 string							contentOID,
                 BerSequenceGenerator			sGen,
                 BerSequenceGenerator			sigGen,
-                BerSequenceGenerator			eiGen)
+                BerSequenceGenerator			eiGen,
+                BerOctetStringGenerator			octGen)
             {
 				this.outer = outer;
 
@@ -777,6 +784,7 @@ namespace Org.BouncyCastle.Cms
                 _sGen = sGen;
                 _sigGen = sigGen;
                 _eiGen = eiGen;
+				_octGen = octGen;
             }
 
 			public override void Write(byte[] buffer, int offset, int count)
@@ -811,7 +819,10 @@ namespace Org.BouncyCastle.Cms
 
                 // TODO Parent context(s) should really be be closed explicitly
 
-                _eiGen.Close();
+				// Only for encapsulation
+				_octGen?.Dispose();
+
+                _eiGen.Dispose();
 
                 outer.m_digests.Clear();    // clear the current preserved digest state
 
@@ -896,8 +907,8 @@ namespace Org.BouncyCastle.Cms
 
                 WriteToGenerator(_sigGen, new DerSet(signerInfos));
 
-				_sigGen.Close();
-                _sGen.Close();
+				_sigGen.Dispose();
+                _sGen.Dispose();
             }
 
 			private static void WriteToGenerator(Asn1Generator ag, Asn1Encodable ae)
diff --git a/crypto/src/cms/CMSUtils.cs b/crypto/src/cms/CMSUtils.cs
index 1a1577c4e..99258c995 100644
--- a/crypto/src/cms/CMSUtils.cs
+++ b/crypto/src/cms/CMSUtils.cs
@@ -176,12 +176,6 @@ namespace Org.BouncyCastle.Cms
 			return new DerSet(v);
 		}
 
-		internal static Stream CreateBerOctetOutputStream(Stream s, int tagNo, bool isExplicit, int bufferSize)
-		{
-			BerOctetStringGenerator octGen = new BerOctetStringGenerator(s, tagNo, isExplicit);
-			return octGen.GetOctetOutputStream(bufferSize);
-		}
-
 		internal static TbsCertificateStructure GetTbsCertificateStructure(X509Certificate cert)
 		{
 			return TbsCertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetTbsCertificate()));