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));
+ }
}
}
diff --git a/crypto/src/cms/CMSUtils.cs b/crypto/src/cms/CMSUtils.cs
index 281e1e73a..0041d2fac 100644
--- a/crypto/src/cms/CMSUtils.cs
+++ b/crypto/src/cms/CMSUtils.cs
@@ -33,26 +33,27 @@ namespace Org.BouncyCastle.Cms
}
}
- internal static ContentInfo ReadContentInfo(
- byte[] input)
+ internal static ContentInfo ReadContentInfo(byte[] input)
{
- // enforce limit checking as from a byte array
- return ReadContentInfo(new Asn1InputStream(input));
- }
+ using (var asn1In = new Asn1InputStream(input))
+ {
+ return ReadContentInfo(asn1In);
+ }
+ }
- internal static ContentInfo ReadContentInfo(
- Stream input)
+ internal static ContentInfo ReadContentInfo(Stream input)
{
- // enforce some limit checking
- return ReadContentInfo(new Asn1InputStream(input, MaximumMemory));
+ using (var asn1In = new Asn1InputStream(input, MaximumMemory, leaveOpen: true))
+ {
+ return ReadContentInfo(asn1In);
+ }
}
- private static ContentInfo ReadContentInfo(
- Asn1InputStream aIn)
+ private static ContentInfo ReadContentInfo(Asn1InputStream asn1In)
{
try
{
- return ContentInfo.GetInstance(aIn.ReadObject());
+ return ContentInfo.GetInstance(asn1In.ReadObject());
}
catch (IOException e)
{
diff --git a/crypto/src/tls/TlsUtilities.cs b/crypto/src/tls/TlsUtilities.cs
index 7a601bebf..d187aeed2 100644
--- a/crypto/src/tls/TlsUtilities.cs
+++ b/crypto/src/tls/TlsUtilities.cs
@@ -966,14 +966,15 @@ namespace Org.BouncyCastle.Tls
public static Asn1Object ReadAsn1Object(byte[] encoding)
{
- Asn1InputStream asn1 = new Asn1InputStream(encoding);
- Asn1Object result = asn1.ReadObject();
- if (null == result)
- throw new TlsFatalAlert(AlertDescription.decode_error);
- if (null != asn1.ReadObject())
- throw new TlsFatalAlert(AlertDescription.decode_error);
-
- return result;
+ using (var asn1In = new Asn1InputStream(encoding))
+ {
+ Asn1Object result = asn1In.ReadObject();
+ if (null == result)
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ if (asn1In.Length != asn1In.Position)
+ throw new TlsFatalAlert(AlertDescription.decode_error);
+ return result;
+ }
}
/// <exception cref="IOException"/>
diff --git a/crypto/src/x509/X509CertPairParser.cs b/crypto/src/x509/X509CertPairParser.cs
index 26b417898..95ba522c8 100644
--- a/crypto/src/x509/X509CertPairParser.cs
+++ b/crypto/src/x509/X509CertPairParser.cs
@@ -13,13 +13,12 @@ namespace Org.BouncyCastle.X509
{
private Stream currentStream;
- private X509CertificatePair ReadDerCrossCertificatePair(
- Stream inStream)
+ private X509CertificatePair ReadDerCrossCertificatePair(Stream inStream)
{
- Asn1InputStream dIn = new Asn1InputStream(inStream);//, ProviderUtil.getReadLimit(in));
- Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
- CertificatePair pair = CertificatePair.GetInstance(seq);
- return new X509CertificatePair(pair);
+ using (var asn1In = new Asn1InputStream(inStream, int.MaxValue, leaveOpen: true))
+ {
+ return new X509CertificatePair(CertificatePair.GetInstance(asn1In.ReadObject()));
+ }
}
/// <summary>
diff --git a/crypto/src/x509/X509CertificateParser.cs b/crypto/src/x509/X509CertificateParser.cs
index ce50dc8ed..6fc1b3ff4 100644
--- a/crypto/src/x509/X509CertificateParser.cs
+++ b/crypto/src/x509/X509CertificateParser.cs
@@ -138,7 +138,10 @@ namespace Org.BouncyCastle.X509
if (tag != 0x30) // assume ascii PEM encoded.
return ReadPemCertificate(inStream);
- return ReadDerCertificate(new Asn1InputStream(inStream));
+ using (var asn1In = new Asn1InputStream(inStream, int.MaxValue, leaveOpen: true))
+ {
+ return ReadDerCertificate(asn1In);
+ }
}
catch (Exception e)
{
diff --git a/crypto/src/x509/X509CrlParser.cs b/crypto/src/x509/X509CrlParser.cs
index ad2b4f704..a60a591c4 100644
--- a/crypto/src/x509/X509CrlParser.cs
+++ b/crypto/src/x509/X509CrlParser.cs
@@ -131,11 +131,14 @@ namespace Org.BouncyCastle.X509
return ReadPemCrl(inStream);
Asn1InputStream asn1 = lazyAsn1
- ? new LazyAsn1InputStream(inStream)
- : new Asn1InputStream(inStream);
+ ? new LazyAsn1InputStream(inStream, int.MaxValue, leaveOpen: true)
+ : new Asn1InputStream(inStream, int.MaxValue, leaveOpen: true);
- return ReadDerCrl(asn1);
- }
+ using (asn1)
+ {
+ return ReadDerCrl(asn1);
+ }
+ }
catch (CrlException e)
{
throw e;
diff --git a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
index fb035de18..2ae316f33 100644
--- a/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
+++ b/crypto/test/src/asn1/test/EqualsAndHashCodeTest.cs
@@ -54,26 +54,28 @@ namespace Org.BouncyCastle.Asn1.Tests
};
MemoryStream bOut = new MemoryStream();
- Asn1OutputStream aOut = Asn1OutputStream.Create(bOut);
-
- for (int i = 0; i != values.Length; i++)
+ using (var asn1Out = Asn1OutputStream.Create(bOut))
{
- aOut.WriteObject(values[i]);
- }
-
- Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray());
-
- for (int i = 0; i != values.Length; i++)
- {
- Asn1Object o = aIn.ReadObject();
- if (!o.Equals(values[i]))
+ for (int i = 0; i != values.Length; i++)
{
- Fail("Failed equality test for " + o.GetType().Name);
+ asn1Out.WriteObject(values[i]);
}
+ }
- if (o.GetHashCode() != values[i].GetHashCode())
+ byte[] output = bOut.ToArray();
+ using (var asn1In = new Asn1InputStream(output))
+ {
+ for (int i = 0; i != values.Length; i++)
{
- Fail("Failed hashCode test for " + o.GetType().Name);
+ Asn1Object o = asn1In.ReadObject();
+ if (!o.Equals(values[i]))
+ {
+ Fail("Failed equality test for " + o.GetType().Name);
+ }
+ if (o.GetHashCode() != values[i].GetHashCode())
+ {
+ Fail("Failed hashCode test for " + o.GetType().Name);
+ }
}
}
}
diff --git a/crypto/test/src/asn1/test/MiscTest.cs b/crypto/test/src/asn1/test/MiscTest.cs
index 96dfa4c3f..0cbf6e8fc 100644
--- a/crypto/test/src/asn1/test/MiscTest.cs
+++ b/crypto/test/src/asn1/test/MiscTest.cs
@@ -105,32 +105,33 @@ namespace Org.BouncyCastle.Asn1.Tests
byte[] data = Base64.Decode("MA4ECAECAwQFBgcIAgIAgAMCBSAWBWhlbGxvMAoECAECAwQFBgcIFgtodHRwOi8vdGVzdA==");
MemoryStream bOut = new MemoryStream();
- Asn1OutputStream aOut = Asn1OutputStream.Create(bOut);
-
- for (int i = 0; i != values.Length; i++)
+ using (var asn1Out = Asn1OutputStream.Create(bOut))
{
- aOut.WriteObject(values[i]);
+ for (int i = 0; i != values.Length; i++)
+ {
+ asn1Out.WriteObject(values[i]);
+ }
}
- if (!Arrays.AreEqual(bOut.ToArray(), data))
+ byte[] output = bOut.ToArray();
+ if (!Arrays.AreEqual(output, data))
{
Fail("Failed data check");
}
- Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray());
-
- for (int i = 0; i != values.Length; i++)
+ using (var asn1In = new Asn1InputStream(output))
{
- Asn1Object o = aIn.ReadObject();
-
- if (!values[i].Equals(o))
- {
- Fail("Failed equality test for " + o);
- }
-
- if (o.GetHashCode() != values[i].GetHashCode())
+ for (int i = 0; i != values.Length; i++)
{
- Fail("Failed hashCode test for " + o);
+ Asn1Object o = asn1In.ReadObject();
+ if (!values[i].Equals(o))
+ {
+ Fail("Failed equality test for " + o);
+ }
+ if (o.GetHashCode() != values[i].GetHashCode())
+ {
+ Fail("Failed hashCode test for " + o);
+ }
}
}
diff --git a/crypto/test/src/asn1/test/ParsingTest.cs b/crypto/test/src/asn1/test/ParsingTest.cs
index 43a97555f..c5d2eed9c 100644
--- a/crypto/test/src/asn1/test/ParsingTest.cs
+++ b/crypto/test/src/asn1/test/ParsingTest.cs
@@ -37,7 +37,7 @@ namespace Org.BouncyCastle.Asn1.Tests
public override void PerformTest()
{
- inputStreamTest();
+ InputStreamTest();
parserTest();
}
@@ -68,31 +68,32 @@ namespace Org.BouncyCastle.Asn1.Tests
}
}
- private void inputStreamTest()
+ private void InputStreamTest()
{
foreach (string stream in streams)
{
- Asn1InputStream aIn = new Asn1InputStream(Base64.Decode(stream));
-
- try
+ using (var aIn = new Asn1InputStream(Base64.Decode(stream)))
{
- object obj;
- while ((obj = aIn.ReadObject()) != null)
- {
- }
+ try
+ {
+ object obj;
+ while ((obj = aIn.ReadObject()) != null)
+ {
+ }
- Fail("bad stream parsed successfully!");
- }
- catch (IOException)
- {
- // ignore
- }
- // Note: C# may throw these instead, since no InMemoryRepresentable support
- catch (Asn1ParsingException)
- {
- // ignore
- }
- }
+ Fail("bad stream parsed successfully!");
+ }
+ catch (IOException)
+ {
+ // ignore
+ }
+ // Note: C# may throw these instead, since no InMemoryRepresentable support
+ catch (Asn1ParsingException)
+ {
+ // ignore
+ }
+ }
+ }
}
}
}
diff --git a/crypto/test/src/cms/test/SignedDataTest.cs b/crypto/test/src/cms/test/SignedDataTest.cs
index d0702c836..9d1d18ad3 100644
--- a/crypto/test/src/cms/test/SignedDataTest.cs
+++ b/crypto/test/src/cms/test/SignedDataTest.cs
@@ -1057,12 +1057,12 @@ namespace Org.BouncyCastle.Cms.Tests
Assert.AreEqual(3, s.Version);
- MemoryStream bIn = new MemoryStream(s.GetEncoded(), false);
- Asn1InputStream aIn = new Asn1InputStream(bIn);
-
- s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject()));
+ using (var aIn = new Asn1InputStream(s.GetEncoded()))
+ {
+ s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject()));
+ }
- x509Certs = s.GetCertificates();
+ x509Certs = s.GetCertificates();
x509Crls = s.GetCrls();
SignerInformationStore signers = s.GetSignerInfos();
@@ -1101,12 +1101,12 @@ namespace Org.BouncyCastle.Cms.Tests
s = gen.Generate(msg, true);
- bIn = new MemoryStream(s.GetEncoded(), false);
- aIn = new Asn1InputStream(bIn);
-
- s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject()));
+ using (var aIn = new Asn1InputStream(s.GetEncoded()))
+ {
+ s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject()));
+ }
- x509Certs = s.GetCertificates();
+ x509Certs = s.GetCertificates();
x509Crls = s.GetCrls();
signers = s.GetSignerInfos();
|