From 7735c6336809bc20d10dae1c15891143d0cc54c5 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Wed, 9 Nov 2022 16:08:19 +0700 Subject: Asn1Generator implements IDisposable - now expects BerOctetStringGenerator to be disposed, not just its octets stream --- crypto/src/asn1/ASN1Generator.cs | 37 ++++++++++--- crypto/src/asn1/BERGenerator.cs | 68 ++++++++++++----------- crypto/src/asn1/BEROctetStringGenerator.cs | 56 +++++++++---------- crypto/src/asn1/DERGenerator.cs | 88 +++++++++++++----------------- crypto/src/asn1/DERSequenceGenerator.cs | 20 +++---- crypto/src/asn1/DERSetGenerator.cs | 20 +++---- 6 files changed, 146 insertions(+), 143 deletions(-) (limited to 'crypto/src/asn1') 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 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); + } + /// The caller is responsible for disposing the returned before disposing + /// this generator. public Stream GetOctetOutputStream() { return GetOctetOutputStream(new byte[1000]); // limit for CER encoding. } - public Stream GetOctetOutputStream( - int bufSize) + /// The caller is responsible for disposing the returned before disposing + /// this generator. + 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) + /// The caller is responsible for disposing the returned before disposing + /// this generator. + 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()); - } } } -- cgit 1.4.1