diff options
38 files changed, 844 insertions, 588 deletions
diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs index 1a69d7c2c..59178ea31 100644 --- a/crypto/src/asn1/Asn1OutputStream.cs +++ b/crypto/src/asn1/Asn1OutputStream.cs @@ -77,7 +77,11 @@ namespace Org.BouncyCastle.Asn1 return; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span<byte> stack = stackalloc byte[5]; +#else byte[] stack = new byte[5]; +#endif int pos = stack.Length; do @@ -90,7 +94,11 @@ namespace Org.BouncyCastle.Asn1 int count = stack.Length - pos; stack[--pos] = (byte)(0x80 | count); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Write(stack[pos..]); +#else Write(stack, pos, count + 1); +#endif } internal void WriteIdentifier(int tagClass, int tagNo) @@ -101,7 +109,11 @@ namespace Org.BouncyCastle.Asn1 return; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Span<byte> stack = stackalloc byte[6]; +#else byte[] stack = new byte[6]; +#endif int pos = stack.Length; stack[--pos] = (byte)(tagNo & 0x7F); @@ -113,7 +125,11 @@ namespace Org.BouncyCastle.Asn1 stack[--pos] = (byte)(tagClass | 0x1F); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Write(stack[pos..]); +#else Write(stack, pos, stack.Length - pos); +#endif } internal static IAsn1Encoding[] GetContentsEncodings(int encoding, Asn1Encodable[] elements) diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs index 7893139d6..b07576e7d 100644 --- a/crypto/src/asn1/BEROctetStringGenerator.cs +++ b/crypto/src/asn1/BEROctetStringGenerator.cs @@ -64,6 +64,9 @@ namespace Org.BouncyCastle.Asn1 { Streams.ValidateBufferArguments(buffer, offset, count); +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + Write(buffer.AsSpan(offset, count)); +#else int bufLen = _buf.Length; int available = bufLen - _off; if (count < available) @@ -77,8 +80,9 @@ namespace Org.BouncyCastle.Asn1 if (_off > 0) { Array.Copy(buffer, offset, _buf, _off, available); - pos += available; + pos = available; DerOctetString.Encode(_derOut, _buf, 0, bufLen); + //_off = 0; } int remaining; @@ -90,9 +94,40 @@ namespace Org.BouncyCastle.Asn1 Array.Copy(buffer, offset + pos, _buf, 0, remaining); this._off = remaining; +#endif + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + int bufLen = _buf.Length; + int available = bufLen - _off; + if (buffer.Length < available) + { + buffer.CopyTo(_buf.AsSpan(_off)); + _off += buffer.Length; + return; + } + + if (_off > 0) + { + DerOctetString.Encode(_derOut, _buf.AsSpan(0, _off), buffer[..available]); + buffer = buffer[available..]; + //_off = 0; + } + + while (buffer.Length >= bufLen) + { + DerOctetString.Encode(_derOut, buffer[..bufLen]); + buffer = buffer[bufLen..]; + } + + buffer.CopyTo(_buf.AsSpan()); + _off = buffer.Length; } +#endif - public override void WriteByte(byte value) + public override void WriteByte(byte value) { _buf[_off++] = value; @@ -103,33 +138,20 @@ namespace Org.BouncyCastle.Asn1 } } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) { - ImplClose(); - } - base.Dispose(disposing); - } -#else - public override void Close() - { - ImplClose(); - base.Close(); - } -#endif - - private void ImplClose() - { - if (_off != 0) - { - DerOctetString.Encode(_derOut, _buf, 0, _off); - } + if (_off != 0) + { + DerOctetString.Encode(_derOut, _buf, 0, _off); + } - _derOut.FlushInternal(); + _derOut.FlushInternal(); - _gen.WriteBerEnd(); + _gen.WriteBerEnd(); + } + base.Dispose(disposing); } } } diff --git a/crypto/src/asn1/DerOctetString.cs b/crypto/src/asn1/DerOctetString.cs index d9913f065..ea13765ec 100644 --- a/crypto/src/asn1/DerOctetString.cs +++ b/crypto/src/asn1/DerOctetString.cs @@ -37,5 +37,22 @@ namespace Org.BouncyCastle.Asn1 asn1Out.WriteDL(len); asn1Out.Write(buf, off, len); } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal static void Encode(Asn1OutputStream asn1Out, ReadOnlySpan<byte> buf) + { + asn1Out.WriteIdentifier(Asn1Tags.Universal, Asn1Tags.OctetString); + asn1Out.WriteDL(buf.Length); + asn1Out.Write(buf); + } + + internal static void Encode(Asn1OutputStream asn1Out, ReadOnlySpan<byte> buf1, ReadOnlySpan<byte> buf2) + { + asn1Out.WriteIdentifier(Asn1Tags.Universal, Asn1Tags.OctetString); + asn1Out.WriteDL(buf1.Length + buf2.Length); + asn1Out.Write(buf1); + asn1Out.Write(buf2); + } +#endif } } diff --git a/crypto/src/bcpg/ArmoredInputStream.cs b/crypto/src/bcpg/ArmoredInputStream.cs index 224ef7d28..1c5ebd7c5 100644 --- a/crypto/src/bcpg/ArmoredInputStream.cs +++ b/crypto/src/bcpg/ArmoredInputStream.cs @@ -482,7 +482,6 @@ namespace Org.BouncyCastle.Bcpg return c; } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -491,13 +490,6 @@ namespace Org.BouncyCastle.Bcpg } base.Dispose(disposing); } -#else - public override void Close() - { - Platform.Dispose(input); - base.Close(); - } -#endif /** * Change how the stream should react if it encounters missing CRC checksum. diff --git a/crypto/src/bcpg/ArmoredOutputStream.cs b/crypto/src/bcpg/ArmoredOutputStream.cs index 4a726e2dd..7f3bcc2ef 100644 --- a/crypto/src/bcpg/ArmoredOutputStream.cs +++ b/crypto/src/bcpg/ArmoredOutputStream.cs @@ -331,35 +331,20 @@ namespace Org.BouncyCastle.Bcpg * <b>Note</b>: Close() does not close the underlying stream. So it is possible to write * multiple objects using armoring to a single stream. */ -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) { - if (type == null) - return; - - DoClose(); + if (type != null) + { + DoClose(); - type = null; - start = true; + type = null; + start = true; + } } base.Dispose(disposing); } -#else - public override void Close() - { - if (type == null) - return; - - DoClose(); - - type = null; - start = true; - - base.Close(); - } -#endif private void DoClose() { diff --git a/crypto/src/bcpg/BcpgInputStream.cs b/crypto/src/bcpg/BcpgInputStream.cs index 895b03260..5aa7ae306 100644 --- a/crypto/src/bcpg/BcpgInputStream.cs +++ b/crypto/src/bcpg/BcpgInputStream.cs @@ -184,11 +184,7 @@ namespace Org.BouncyCastle.Bcpg else { PartialInputStream pis = new PartialInputStream(this, partial, bodyLen); -#if PORTABLE - Stream buf = pis; -#else Stream buf = new BufferedStream(pis); -#endif objStream = new BcpgInputStream(buf); } @@ -251,7 +247,6 @@ namespace Org.BouncyCastle.Bcpg return tag; } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -260,13 +255,6 @@ namespace Org.BouncyCastle.Bcpg } base.Dispose(disposing); } -#else - public override void Close() - { - Platform.Dispose(m_in); - base.Close(); - } -#endif /// <summary> /// A stream that overlays our input stream, allowing the user to only read a segment of it. diff --git a/crypto/src/bcpg/BcpgOutputStream.cs b/crypto/src/bcpg/BcpgOutputStream.cs index fbce0820e..fbdd75bff 100644 --- a/crypto/src/bcpg/BcpgOutputStream.cs +++ b/crypto/src/bcpg/BcpgOutputStream.cs @@ -376,7 +376,6 @@ namespace Org.BouncyCastle.Bcpg } } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -387,14 +386,5 @@ namespace Org.BouncyCastle.Bcpg } base.Dispose(disposing); } -#else - public override void Close() - { - this.Finish(); - outStr.Flush(); - Platform.Dispose(outStr); - base.Close(); - } -#endif } } diff --git a/crypto/src/bzip2/CBZip2OutputStream.cs b/crypto/src/bzip2/CBZip2OutputStream.cs index 38966efd4..5521dce56 100644 --- a/crypto/src/bzip2/CBZip2OutputStream.cs +++ b/crypto/src/bzip2/CBZip2OutputStream.cs @@ -421,39 +421,32 @@ namespace Org.BouncyCastle.Bzip2 bool closed = false; -// protected void Finalize() -// { -// Close(); -// } - -#if PORTABLE - protected override void Dispose(bool disposing) + protected void Detach(bool disposing) { if (disposing) { - if (closed) - return; - - Finish(); - closed = true; - Platform.Dispose(this.bsStream); + if (!closed) + { + Finish(); + closed = true; + } } base.Dispose(disposing); } -#else - public override void Close() - { - if (closed) - return; - - Finish(); - - closed = true; - Platform.Dispose(this.bsStream); - base.Close(); + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (!closed) + { + Finish(); + closed = true; + Platform.Dispose(this.bsStream); + } + } + base.Dispose(disposing); } -#endif public void Finish() { diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs index 4ac2b34c9..d66b0aea9 100644 --- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs @@ -248,7 +248,6 @@ namespace Org.BouncyCastle.Cms macStream.WriteByte(value); } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -269,25 +268,6 @@ namespace Org.BouncyCastle.Cms } base.Dispose(disposing); } -#else - public override void Close() - { - Platform.Dispose(macStream); - - // TODO Parent context(s) should really be be closed explicitly - - eiGen.Close(); - - // [TODO] auth attributes go here - byte[] macOctets = MacUtilities.DoFinal(mac); - authGen.AddObject(new DerOctetString(macOctets)); - // [TODO] unauth attributes go here - - authGen.Close(); - cGen.Close(); - base.Close(); - } -#endif } } } diff --git a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs index 1a9513ce6..9a9c29b01 100644 --- a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs @@ -121,7 +121,6 @@ namespace Org.BouncyCastle.Cms _out.WriteByte(value); } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -136,19 +135,6 @@ namespace Org.BouncyCastle.Cms } base.Dispose(disposing); } -#else - public override void Close() - { - Platform.Dispose(_out); - - // TODO Parent context(s) should really be be closed explicitly - - _eiGen.Close(); - _cGen.Close(); - _sGen.Close(); - base.Close(); - } -#endif } } } diff --git a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs index 90ecf0748..4a8b57aad 100644 --- a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs @@ -246,44 +246,31 @@ namespace Org.BouncyCastle.Cms _out.WriteByte(value); } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) { - ImplClose(); - } - base.Dispose(disposing); - } -#else - public override void Close() - { - ImplClose(); - base.Close(); - } -#endif + Platform.Dispose(_out); - private void ImplClose() - { - Platform.Dispose(_out); + // TODO Parent context(s) should really be closed explicitly - // TODO Parent context(s) should really be closed explicitly + _eiGen.Close(); - _eiGen.Close(); + if (_outer.unprotectedAttributeGenerator != null) + { + Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes( + new Dictionary<CmsAttributeTableParameter, object>()); - if (_outer.unprotectedAttributeGenerator != null) - { - Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes( - new Dictionary<CmsAttributeTableParameter, object>()); + Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector()); - Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector()); + _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs)); + } - _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs)); - } - - _envGen.Close(); - _cGen.Close(); - } + _envGen.Close(); + _cGen.Close(); + } + base.Dispose(disposing); + } } } } diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs index 5587a9d07..69427c246 100644 --- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs +++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs @@ -791,7 +791,6 @@ namespace Org.BouncyCastle.Cms _out.WriteByte(value); } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -800,13 +799,6 @@ namespace Org.BouncyCastle.Cms } base.Dispose(disposing); } -#else - public override void Close() - { - DoClose(); - base.Close(); - } -#endif private void DoClose() { diff --git a/crypto/src/cms/CMSTypedStream.cs b/crypto/src/cms/CMSTypedStream.cs index e99d904b5..d4ca62256 100644 --- a/crypto/src/cms/CMSTypedStream.cs +++ b/crypto/src/cms/CMSTypedStream.cs @@ -33,11 +33,7 @@ namespace Org.BouncyCastle.Cms int bufSize) { _oid = oid; -#if PORTABLE - _in = new FullReaderStream(inStream); -#else _in = new FullReaderStream(new BufferedStream(inStream, bufSize)); -#endif } public string ContentType @@ -63,10 +59,24 @@ namespace Org.BouncyCastle.Cms { } - public override int Read(byte[] buf, int off, int len) +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void CopyTo(Stream destination, int bufferSize) + { + s.CopyTo(destination, bufferSize); + } +#endif + + public override int Read(byte[] buf, int off, int len) { - return Streams.ReadFully(base.s, buf, off, len); + return Streams.ReadFully(s, buf, off, len); } - } - } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + return Streams.ReadFully(s, buffer); + } +#endif + } + } } diff --git a/crypto/src/crypto/io/CipherStream.cs b/crypto/src/crypto/io/CipherStream.cs index 06a3d392c..e59f33679 100644 --- a/crypto/src/crypto/io/CipherStream.cs +++ b/crypto/src/crypto/io/CipherStream.cs @@ -1,4 +1,7 @@ using System; +#if NETCOREAPP1_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER +using System.Buffers; +#endif using System.Diagnostics; using System.IO; @@ -7,44 +10,39 @@ using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.IO { - public class CipherStream + public sealed class CipherStream : Stream { - internal Stream stream; - internal IBufferedCipher inCipher, outCipher; - private byte[] mInBuf; - private int mInPos; - private bool inStreamEnded; + private readonly Stream m_stream; + private readonly IBufferedCipher m_readCipher, m_writeCipher; + + private byte[] m_readBuf; + private int m_readBufPos; + private bool m_readEnded; public CipherStream(Stream stream, IBufferedCipher readCipher, IBufferedCipher writeCipher) { - this.stream = stream; + m_stream = stream; if (readCipher != null) { - this.inCipher = readCipher; - mInBuf = null; + m_readCipher = readCipher; + m_readBuf = null; } if (writeCipher != null) { - this.outCipher = writeCipher; + m_writeCipher = writeCipher; } } - public IBufferedCipher ReadCipher - { - get { return inCipher; } - } + public IBufferedCipher ReadCipher => m_readCipher; - public IBufferedCipher WriteCipher - { - get { return outCipher; } - } + public IBufferedCipher WriteCipher => m_writeCipher; public override bool CanRead { - get { return stream.CanRead; } + get { return m_stream.CanRead; } } public sealed override bool CanSeek @@ -54,42 +52,26 @@ namespace Org.BouncyCastle.Crypto.IO public override bool CanWrite { - get { return stream.CanWrite; } + get { return m_stream.CanWrite; } } -#if PORTABLE - protected override void Dispose(bool disposing) +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void CopyTo(Stream destination, int bufferSize) { - if (disposing) + if (m_readCipher == null) { - if (outCipher != null) - { - byte[] data = outCipher.DoFinal(); - stream.Write(data, 0, data.Length); - stream.Flush(); - } - Platform.Dispose(stream); + m_stream.CopyTo(destination, bufferSize); } - base.Dispose(disposing); - } -#else - public override void Close() - { - if (outCipher != null) + else { - byte[] data = outCipher.DoFinal(); - stream.Write(data, 0, data.Length); - stream.Flush(); + base.CopyTo(destination, bufferSize); } - Platform.Dispose(stream); - base.Close(); } #endif public override void Flush() { - // Note: outCipher.DoFinal is only called during Close() - stream.Flush(); + m_stream.Flush(); } public sealed override long Length @@ -105,41 +87,70 @@ namespace Org.BouncyCastle.Crypto.IO public override int Read(byte[] buffer, int offset, int count) { - if (inCipher == null) - return stream.Read(buffer, offset, count); + if (m_readCipher == null) + return m_stream.Read(buffer, offset, count); Streams.ValidateBufferArguments(buffer, offset, count); int num = 0; while (num < count) { - if (mInBuf == null || mInPos >= mInBuf.Length) + if (m_readBuf == null || m_readBufPos >= m_readBuf.Length) + { + if (!FillInBuf()) + break; + } + + int numToCopy = System.Math.Min(count - num, m_readBuf.Length - m_readBufPos); + Array.Copy(m_readBuf, m_readBufPos, buffer, offset + num, numToCopy); + m_readBufPos += numToCopy; + num += numToCopy; + } + + return num; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + if (buffer.IsEmpty) + return 0; + + if (m_readCipher == null) + return m_stream.Read(buffer); + + int num = 0; + while (num < buffer.Length) + { + if (m_readBuf == null || m_readBufPos >= m_readBuf.Length) { if (!FillInBuf()) break; } - int numToCopy = System.Math.Min(count - num, mInBuf.Length - mInPos); - Array.Copy(mInBuf, mInPos, buffer, offset + num, numToCopy); - mInPos += numToCopy; + int numToCopy = System.Math.Min(buffer.Length - num, m_readBuf.Length - m_readBufPos); + m_readBuf.AsSpan(m_readBufPos, numToCopy).CopyTo(buffer[num..]); + + m_readBufPos += numToCopy; num += numToCopy; } return num; } +#endif public override int ReadByte() { - if (inCipher == null) - return stream.ReadByte(); + if (m_readCipher == null) + return m_stream.ReadByte(); - if (mInBuf == null || mInPos >= mInBuf.Length) + if (m_readBuf == null || m_readBufPos >= m_readBuf.Length) { if (!FillInBuf()) return -1; } - return mInBuf[mInPos++]; + return m_readBuf[m_readBufPos++]; } public sealed override long Seek(long offset, SeekOrigin origin) @@ -154,9 +165,9 @@ namespace Org.BouncyCastle.Crypto.IO public override void Write(byte[] buffer, int offset, int count) { - if (outCipher == null) + if (m_writeCipher == null) { - stream.Write(buffer, offset, count); + m_stream.Write(buffer, offset, count); return; } @@ -164,69 +175,142 @@ namespace Org.BouncyCastle.Crypto.IO if (count > 0) { - byte[] data = outCipher.ProcessBytes(buffer, offset, count); - if (data != null) +#if NETCOREAPP1_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + int outputSize = m_writeCipher.GetUpdateOutputSize(count); + byte[] output = outputSize > 0 ? ArrayPool<byte>.Shared.Rent(outputSize) : null; + try + { + int length = m_writeCipher.ProcessBytes(buffer, offset, count, output, 0); + if (length > 0) + { + m_stream.Write(output, 0, length); + } + } + finally + { + if (output != null) + { + ArrayPool<byte>.Shared.Return(output); + } + } +#else + byte[] output = m_writeCipher.ProcessBytes(buffer, offset, count); + if (output != null) + { + m_stream.Write(output, 0, output.Length); + } +#endif + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + if (buffer.IsEmpty) + return; + + if (m_writeCipher == null) + { + m_stream.Write(buffer); + return; + } + + int outputSize = m_writeCipher.GetUpdateOutputSize(buffer.Length); + byte[] output = outputSize > 0 ? ArrayPool<byte>.Shared.Rent(outputSize) : null; + try + { + int length = m_writeCipher.ProcessBytes(buffer, Spans.FromNullable(output, 0)); + if (length > 0) { - stream.Write(data, 0, data.Length); + m_stream.Write(output[..length]); + } + } + finally + { + if (output != null) + { + ArrayPool<byte>.Shared.Return(output); } } } +#endif public override void WriteByte(byte value) { - if (outCipher == null) + if (m_writeCipher == null) { - stream.WriteByte(value); + m_stream.WriteByte(value); return; } - byte[] data = outCipher.ProcessByte(value); + byte[] data = m_writeCipher.ProcessByte(value); if (data != null) { - stream.Write(data, 0, data.Length); + m_stream.Write(data, 0, data.Length); } } + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (m_writeCipher != null) + { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + int outputSize = m_writeCipher.GetOutputSize(0); + Span<byte> output = stackalloc byte[outputSize]; + int len = m_writeCipher.DoFinal(output); + m_stream.Write(output[..len]); +#else + byte[] data = m_writeCipher.DoFinal(); + m_stream.Write(data, 0, data.Length); +#endif + } + Platform.Dispose(m_stream); + } + base.Dispose(disposing); + } + private bool FillInBuf() { - if (inStreamEnded) + if (m_readEnded) return false; - mInPos = 0; + m_readBufPos = 0; do { - mInBuf = ReadAndProcessBlock(); + m_readBuf = ReadAndProcessBlock(); } - while (!inStreamEnded && mInBuf == null); + while (!m_readEnded && m_readBuf == null); - return mInBuf != null; + return m_readBuf != null; } private byte[] ReadAndProcessBlock() { - int blockSize = inCipher.GetBlockSize(); - int readSize = (blockSize == 0) ? 256 : blockSize; + int blockSize = m_readCipher.GetBlockSize(); + int readSize = blockSize == 0 ? 256 : blockSize; byte[] block = new byte[readSize]; int numRead = 0; do { - int count = stream.Read(block, numRead, block.Length - numRead); + int count = m_stream.Read(block, numRead, block.Length - numRead); if (count < 1) { - inStreamEnded = true; + m_readEnded = true; break; } numRead += count; } while (numRead < block.Length); - Debug.Assert(inStreamEnded || numRead == block.Length); + Debug.Assert(m_readEnded || numRead == block.Length); - byte[] bytes = inStreamEnded - ? inCipher.DoFinal(block, 0, numRead) - : inCipher.ProcessBytes(block); + byte[] bytes = m_readEnded + ? m_readCipher.DoFinal(block, 0, numRead) + : m_readCipher.ProcessBytes(block); if (bytes != null && bytes.Length == 0) { diff --git a/crypto/src/crypto/io/DigestSink.cs b/crypto/src/crypto/io/DigestSink.cs index c2a168bfe..283bda28b 100644 --- a/crypto/src/crypto/io/DigestSink.cs +++ b/crypto/src/crypto/io/DigestSink.cs @@ -4,20 +4,17 @@ using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.IO { - public class DigestSink + public sealed class DigestSink : BaseOutputStream { - private readonly IDigest mDigest; + private readonly IDigest m_digest; public DigestSink(IDigest digest) { - this.mDigest = digest; + m_digest = digest; } - public virtual IDigest Digest - { - get { return mDigest; } - } + public IDigest Digest => m_digest; public override void Write(byte[] buffer, int offset, int count) { @@ -25,13 +22,23 @@ namespace Org.BouncyCastle.Crypto.IO if (count > 0) { - mDigest.BlockUpdate(buffer, offset, count); + m_digest.BlockUpdate(buffer, offset, count); + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + if (!buffer.IsEmpty) + { + m_digest.BlockUpdate(buffer); } } +#endif public override void WriteByte(byte value) { - mDigest.Update(value); + m_digest.Update(value); } } } diff --git a/crypto/src/crypto/io/DigestStream.cs b/crypto/src/crypto/io/DigestStream.cs index 387f42766..ae7fc94de 100644 --- a/crypto/src/crypto/io/DigestStream.cs +++ b/crypto/src/crypto/io/DigestStream.cs @@ -5,33 +5,27 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.IO { - public class DigestStream + public sealed class DigestStream : Stream { - protected readonly Stream stream; - protected readonly IDigest inDigest; - protected readonly IDigest outDigest; + private readonly Stream m_stream; + private readonly IDigest m_readDigest; + private readonly IDigest m_writeDigest; public DigestStream(Stream stream, IDigest readDigest, IDigest writeDigest) { - this.stream = stream; - this.inDigest = readDigest; - this.outDigest = writeDigest; + m_stream = stream; + m_readDigest = readDigest; + m_writeDigest = writeDigest; } - public virtual IDigest ReadDigest() - { - return inDigest; - } + public IDigest ReadDigest => m_readDigest; - public virtual IDigest WriteDigest() - { - return outDigest; - } + public IDigest WriteDigest => m_writeDigest; public override bool CanRead { - get { return stream.CanRead; } + get { return m_stream.CanRead; } } public sealed override bool CanSeek @@ -41,29 +35,26 @@ namespace Org.BouncyCastle.Crypto.IO public override bool CanWrite { - get { return stream.CanWrite; } + get { return m_stream.CanWrite; } } -#if PORTABLE - protected override void Dispose(bool disposing) +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void CopyTo(Stream destination, int bufferSize) { - if (disposing) + if (m_readDigest == null) { - Platform.Dispose(stream); + m_stream.CopyTo(destination, bufferSize); + } + else + { + base.CopyTo(destination, bufferSize); } - base.Dispose(disposing); - } -#else - public override void Close() - { - Platform.Dispose(stream); - base.Close(); } #endif public override void Flush() { - stream.Flush(); + m_stream.Flush(); } public sealed override long Length @@ -79,23 +70,37 @@ namespace Org.BouncyCastle.Crypto.IO public override int Read(byte[] buffer, int offset, int count) { - int n = stream.Read(buffer, offset, count); + int n = m_stream.Read(buffer, offset, count); + + if (m_readDigest != null && n > 0) + { + m_readDigest.BlockUpdate(buffer, offset, n); + } + + return n; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + int n = m_stream.Read(buffer); - if (inDigest != null && n > 0) + if (m_readDigest != null && n > 0) { - inDigest.BlockUpdate(buffer, offset, n); + m_readDigest.BlockUpdate(buffer[..n]); } return n; } +#endif public override int ReadByte() { - int b = stream.ReadByte(); + int b = m_stream.ReadByte(); - if (inDigest != null && b >= 0) + if (m_readDigest != null && b >= 0) { - inDigest.Update((byte)b); + m_readDigest.Update((byte)b); } return b; @@ -113,23 +118,43 @@ namespace Org.BouncyCastle.Crypto.IO public override void Write(byte[] buffer, int offset, int count) { - stream.Write(buffer, offset, count); + m_stream.Write(buffer, offset, count); - if (outDigest != null && count > 0) + if (m_writeDigest != null && count > 0) { - outDigest.BlockUpdate(buffer, offset, count); + m_writeDigest.BlockUpdate(buffer, offset, count); } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + m_stream.Write(buffer); + + if (m_writeDigest != null && !buffer.IsEmpty) + { + m_writeDigest.BlockUpdate(buffer); + } + } +#endif + public override void WriteByte(byte value) { - stream.WriteByte(value); + m_stream.WriteByte(value); - if (outDigest != null) + if (m_writeDigest != null) { - outDigest.Update(value); + m_writeDigest.Update(value); } } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Platform.Dispose(m_stream); + } + base.Dispose(disposing); + } } } - diff --git a/crypto/src/crypto/io/MacSink.cs b/crypto/src/crypto/io/MacSink.cs index aa72e9047..cc5d93b37 100644 --- a/crypto/src/crypto/io/MacSink.cs +++ b/crypto/src/crypto/io/MacSink.cs @@ -4,20 +4,17 @@ using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.IO { - public class MacSink + public sealed class MacSink : BaseOutputStream { - private readonly IMac mMac; + private readonly IMac m_mac; public MacSink(IMac mac) { - this.mMac = mac; + m_mac = mac; } - public virtual IMac Mac - { - get { return mMac; } - } + public IMac Mac => m_mac; public override void Write(byte[] buffer, int offset, int count) { @@ -25,13 +22,23 @@ namespace Org.BouncyCastle.Crypto.IO if (count > 0) { - mMac.BlockUpdate(buffer, offset, count); + m_mac.BlockUpdate(buffer, offset, count); + } + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + if (!buffer.IsEmpty) + { + m_mac.BlockUpdate(buffer); } } +#endif public override void WriteByte(byte value) { - mMac.Update(value); + m_mac.Update(value); } } } diff --git a/crypto/src/crypto/io/MacStream.cs b/crypto/src/crypto/io/MacStream.cs index c56e00d2c..c97614289 100644 --- a/crypto/src/crypto/io/MacStream.cs +++ b/crypto/src/crypto/io/MacStream.cs @@ -5,33 +5,27 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.IO { - public class MacStream + public sealed class MacStream : Stream { - protected readonly Stream stream; - protected readonly IMac inMac; - protected readonly IMac outMac; + private readonly Stream m_stream; + private readonly IMac m_readMac; + private readonly IMac m_writeMac; public MacStream(Stream stream, IMac readMac, IMac writeMac) { - this.stream = stream; - this.inMac = readMac; - this.outMac = writeMac; + m_stream = stream; + m_readMac = readMac; + m_writeMac = writeMac; } - public virtual IMac ReadMac() - { - return inMac; - } + public IMac ReadMac => m_readMac; - public virtual IMac WriteMac() - { - return outMac; - } + public IMac WriteMac => m_writeMac; public override bool CanRead { - get { return stream.CanRead; } + get { return m_stream.CanRead; } } public sealed override bool CanSeek @@ -41,29 +35,26 @@ namespace Org.BouncyCastle.Crypto.IO public override bool CanWrite { - get { return stream.CanWrite; } + get { return m_stream.CanWrite; } } -#if PORTABLE - protected override void Dispose(bool disposing) +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void CopyTo(Stream destination, int bufferSize) { - if (disposing) + if (m_readMac == null) { - Platform.Dispose(stream); + m_stream.CopyTo(destination, bufferSize); + } + else + { + base.CopyTo(destination, bufferSize); } - base.Dispose(disposing); - } -#else - public override void Close() - { - Platform.Dispose(stream); - base.Close(); } #endif public override void Flush() { - stream.Flush(); + m_stream.Flush(); } public sealed override long Length @@ -79,23 +70,37 @@ namespace Org.BouncyCastle.Crypto.IO public override int Read(byte[] buffer, int offset, int count) { - int n = stream.Read(buffer, offset, count); + int n = m_stream.Read(buffer, offset, count); + + if (m_readMac != null && n > 0) + { + m_readMac.BlockUpdate(buffer, offset, n); + } + + return n; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + int n = m_stream.Read(buffer); - if (inMac != null && n > 0) + if (m_readMac != null && n > 0) { - inMac.BlockUpdate(buffer, offset, n); + m_readMac.BlockUpdate(buffer[..n]); } return n; } +#endif public override int ReadByte() { - int b = stream.ReadByte(); + int b = m_stream.ReadByte(); - if (inMac != null && b >= 0) + if (m_readMac != null && b >= 0) { - inMac.Update((byte)b); + m_readMac.Update((byte)b); } return b; @@ -113,23 +118,43 @@ namespace Org.BouncyCastle.Crypto.IO public override void Write(byte[] buffer, int offset, int count) { - stream.Write(buffer, offset, count); + m_stream.Write(buffer, offset, count); - if (outMac != null && count > 0) + if (m_writeMac != null && count > 0) { - outMac.BlockUpdate(buffer, offset, count); + m_writeMac.BlockUpdate(buffer, offset, count); } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + m_stream.Write(buffer); + + if (m_writeMac != null && !buffer.IsEmpty) + { + m_writeMac.BlockUpdate(buffer); + } + } +#endif + public override void WriteByte(byte value) { - stream.WriteByte(value); + m_stream.WriteByte(value); - if (outMac != null) + if (m_writeMac != null) { - outMac.Update(value); + m_writeMac.Update(value); } } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Platform.Dispose(m_stream); + } + base.Dispose(disposing); + } } } - diff --git a/crypto/src/crypto/io/SignerSink.cs b/crypto/src/crypto/io/SignerSink.cs index 3485d3cdc..aaae59966 100644 --- a/crypto/src/crypto/io/SignerSink.cs +++ b/crypto/src/crypto/io/SignerSink.cs @@ -4,20 +4,17 @@ using Org.BouncyCastle.Utilities.IO; namespace Org.BouncyCastle.Crypto.IO { - public class SignerSink + public sealed class SignerSink : BaseOutputStream { - private readonly ISigner mSigner; + private readonly ISigner m_signer; public SignerSink(ISigner signer) { - this.mSigner = signer; + m_signer = signer; } - public virtual ISigner Signer - { - get { return mSigner; } - } + public ISigner Signer => m_signer; public override void Write(byte[] buffer, int offset, int count) { @@ -25,13 +22,23 @@ namespace Org.BouncyCastle.Crypto.IO if (count > 0) { - mSigner.BlockUpdate(buffer, offset, count); + m_signer.BlockUpdate(buffer, offset, count); } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + if (!buffer.IsEmpty) + { + m_signer.BlockUpdate(buffer); + } + } +#endif + public override void WriteByte(byte value) { - mSigner.Update(value); + m_signer.Update(value); } } } diff --git a/crypto/src/crypto/io/SignerStream.cs b/crypto/src/crypto/io/SignerStream.cs index d25d7e285..fecc0d309 100644 --- a/crypto/src/crypto/io/SignerStream.cs +++ b/crypto/src/crypto/io/SignerStream.cs @@ -5,12 +5,12 @@ using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.IO { - public class SignerStream + public sealed class SignerStream : Stream { - protected readonly Stream stream; - protected readonly ISigner inSigner; - protected readonly ISigner outSigner; + private readonly Stream stream; + private readonly ISigner inSigner; + private readonly ISigner outSigner; public SignerStream(Stream stream, ISigner readSigner, ISigner writeSigner) { @@ -19,15 +19,9 @@ namespace Org.BouncyCastle.Crypto.IO this.outSigner = writeSigner; } - public virtual ISigner ReadSigner() - { - return inSigner; - } + public ISigner ReadSigner => inSigner; - public virtual ISigner WriteSigner() - { - return outSigner; - } + public ISigner WriteSigner => outSigner; public override bool CanRead { @@ -44,20 +38,17 @@ namespace Org.BouncyCastle.Crypto.IO get { return stream.CanWrite; } } -#if PORTABLE - protected override void Dispose(bool disposing) +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void CopyTo(Stream destination, int bufferSize) { - if (disposing) + if (inSigner == null) { - Platform.Dispose(stream); + stream.CopyTo(destination, bufferSize); + } + else + { + base.CopyTo(destination, bufferSize); } - base.Dispose(disposing); - } -#else - public override void Close() - { - Platform.Dispose(stream); - base.Close(); } #endif @@ -89,6 +80,20 @@ namespace Org.BouncyCastle.Crypto.IO return n; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + int n = stream.Read(buffer); + + if (inSigner != null && n > 0) + { + inSigner.BlockUpdate(buffer[..n]); + } + + return n; + } +#endif + public override int ReadByte() { int b = stream.ReadByte(); @@ -121,6 +126,18 @@ namespace Org.BouncyCastle.Crypto.IO } } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + stream.Write(buffer); + + if (outSigner != null && !buffer.IsEmpty) + { + outSigner.BlockUpdate(buffer); + } + } +#endif + public override void WriteByte(byte value) { stream.WriteByte(value); @@ -130,6 +147,14 @@ namespace Org.BouncyCastle.Crypto.IO outSigner.Update(value); } } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + Platform.Dispose(stream); + } + base.Dispose(disposing); + } } } - diff --git a/crypto/src/openpgp/PgpCompressedDataGenerator.cs b/crypto/src/openpgp/PgpCompressedDataGenerator.cs index 88a1070d1..791aac0bf 100644 --- a/crypto/src/openpgp/PgpCompressedDataGenerator.cs +++ b/crypto/src/openpgp/PgpCompressedDataGenerator.cs @@ -76,7 +76,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData); - doOpen(); + DoOpen(); return new WrappedGeneratorStream(this, dOut); } @@ -120,12 +120,12 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp this.pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData, buffer); - doOpen(); + DoOpen(); return new WrappedGeneratorStream(this, dOut); } - private void doOpen() + private void DoOpen() { pkOut.WriteByte((byte) algorithm); @@ -173,22 +173,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { } -#if PORTABLE protected override void Dispose(bool disposing) { - if (disposing) - { - Finish(); - return; - } - base.Dispose(disposing); + Detach(disposing); } -#else - public override void Close() - { - Finish(); - } -#endif } private class SafeZOutputStream : ZOutputStream @@ -198,24 +186,10 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp { } -#if PORTABLE protected override void Dispose(bool disposing) { - if (disposing) - { - Finish(); - End(); - return; - } - base.Dispose(disposing); + Detach(disposing); } -#else - public override void Close() - { - Finish(); - End(); - } -#endif } } } diff --git a/crypto/src/openpgp/PgpEncryptedData.cs b/crypto/src/openpgp/PgpEncryptedData.cs index d3220fe86..5cdc0d533 100644 --- a/crypto/src/openpgp/PgpEncryptedData.cs +++ b/crypto/src/openpgp/PgpEncryptedData.cs @@ -140,7 +140,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp // byte[] lookAhead = truncStream.GetLookAhead(); - IDigest hash = dIn.ReadDigest(); + IDigest hash = dIn.ReadDigest; hash.BlockUpdate(lookAhead, 0, 2); byte[] digest = DigestUtilities.DoFinal(hash); diff --git a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs index d16f328d9..f086aaf75 100644 --- a/crypto/src/openpgp/PgpEncryptedDataGenerator.cs +++ b/crypto/src/openpgp/PgpEncryptedDataGenerator.cs @@ -561,7 +561,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp digestOut.Flush(); // TODO - byte[] dig = DigestUtilities.DoFinal(digestOut.WriteDigest()); + byte[] dig = DigestUtilities.DoFinal(digestOut.WriteDigest); cOut.Write(dig, 0, dig.Length); } diff --git a/crypto/src/openpgp/WrappedGeneratorStream.cs b/crypto/src/openpgp/WrappedGeneratorStream.cs index df31d71f0..c54ee0b3b 100644 --- a/crypto/src/openpgp/WrappedGeneratorStream.cs +++ b/crypto/src/openpgp/WrappedGeneratorStream.cs @@ -31,11 +31,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp m_generator = null; } - // Don't dispose the wrapped Stream - if (!disposing) - { - base.Dispose(disposing); - } + Detach(disposing); } } } diff --git a/crypto/src/tls/ByteQueue.cs b/crypto/src/tls/ByteQueue.cs index 45bec8be4..b85106528 100644 --- a/crypto/src/tls/ByteQueue.cs +++ b/crypto/src/tls/ByteQueue.cs @@ -56,6 +56,9 @@ namespace Org.BouncyCastle.Tls /// <param name="len">How many bytes to read from the array.</param> public void AddData(byte[] buf, int off, int len) { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + AddData(buf.AsSpan(off, len)); +#else if (m_readOnlyBuf) throw new InvalidOperationException("Cannot add data to read-only buffer"); @@ -86,8 +89,46 @@ namespace Org.BouncyCastle.Tls Array.Copy(buf, off, m_databuf, m_skipped + m_available, len); m_available += len; +#endif } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public void AddData(ReadOnlySpan<byte> buffer) + { + if (m_readOnlyBuf) + throw new InvalidOperationException("Cannot add data to read-only buffer"); + + int len = buffer.Length; + if (m_available == 0) + { + if (len > m_databuf.Length) + { + int desiredSize = NextTwoPow(len | 256); + m_databuf = new byte[desiredSize]; + } + m_skipped = 0; + } + else if ((m_skipped + m_available + len) > m_databuf.Length) + { + int desiredSize = NextTwoPow(m_available + len); + if (desiredSize > m_databuf.Length) + { + byte[] tmp = new byte[desiredSize]; + Array.Copy(m_databuf, m_skipped, tmp, 0, m_available); + m_databuf = tmp; + } + else + { + Array.Copy(m_databuf, m_skipped, m_databuf, 0, m_available); + } + m_skipped = 0; + } + + buffer.CopyTo(m_databuf.AsSpan(m_skipped + m_available)); + m_available += len; + } +#endif + /// <returns>The number of bytes which are available in this buffer.</returns> public int Available { @@ -124,6 +165,16 @@ namespace Org.BouncyCastle.Tls Array.Copy(m_databuf, m_skipped + skip, buf, offset, len); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public void Read(Span<byte> buffer, int skip) + { + if ((m_available - skip) < buffer.Length) + throw new InvalidOperationException("Not enough data to read"); + + m_databuf.AsSpan(m_skipped + skip, buffer.Length).CopyTo(buffer); + } +#endif + /// <summary>Return a <see cref="HandshakeMessageInput"/> over some bytes at the beginning of the data. /// </summary> /// <param name="length">How many bytes will be readable.</param> @@ -182,6 +233,14 @@ namespace Org.BouncyCastle.Tls RemoveData(skip + len); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public void RemoveData(Span<byte> buffer, int skip) + { + Read(buffer, skip); + RemoveData(skip + buffer.Length); + } +#endif + public byte[] RemoveData(int len, int skip) { byte[] buf = new byte[len]; diff --git a/crypto/src/tls/ByteQueueInputStream.cs b/crypto/src/tls/ByteQueueInputStream.cs index 0b15071ad..ab26faa98 100644 --- a/crypto/src/tls/ByteQueueInputStream.cs +++ b/crypto/src/tls/ByteQueueInputStream.cs @@ -40,6 +40,15 @@ namespace Org.BouncyCastle.Tls return bytesToRead; } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + int bytesToRead = System.Math.Min(m_buffer.Available, buffer.Length); + m_buffer.RemoveData(buffer[..bytesToRead], 0); + return bytesToRead; + } +#endif + public override int ReadByte() { if (m_buffer.Available == 0) @@ -59,16 +68,5 @@ namespace Org.BouncyCastle.Tls { get { return m_buffer.Available; } } - -#if PORTABLE - //protected override void Dispose(bool disposing) - //{ - // base.Dispose(disposing); - //} -#else - public override void Close() - { - } -#endif } } diff --git a/crypto/src/tls/ByteQueueOutputStream.cs b/crypto/src/tls/ByteQueueOutputStream.cs index 441a3773a..ecb1f865d 100644 --- a/crypto/src/tls/ByteQueueOutputStream.cs +++ b/crypto/src/tls/ByteQueueOutputStream.cs @@ -27,6 +27,13 @@ namespace Org.BouncyCastle.Tls m_buffer.AddData(buffer, offset, count); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + m_buffer.AddData(buffer); + } +#endif + public override void WriteByte(byte value) { m_buffer.AddData(new byte[]{ value }, 0, 1); diff --git a/crypto/src/tls/TlsStream.cs b/crypto/src/tls/TlsStream.cs index f3dea1574..01b990799 100644 --- a/crypto/src/tls/TlsStream.cs +++ b/crypto/src/tls/TlsStream.cs @@ -28,7 +28,6 @@ namespace Org.BouncyCastle.Tls get { return true; } } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -37,13 +36,6 @@ namespace Org.BouncyCastle.Tls } base.Dispose(disposing); } -#else - public override void Close() - { - m_handler.Close(); - base.Close(); - } -#endif public override void Flush() { @@ -69,7 +61,7 @@ namespace Org.BouncyCastle.Tls public override int ReadByte() { byte[] buf = new byte[1]; - int ret = Read(buf, 0, 1); + int ret = m_handler.ReadApplicationData(buf, 0, 1); return ret <= 0 ? -1 : buf[0]; } @@ -90,7 +82,7 @@ namespace Org.BouncyCastle.Tls public override void WriteByte(byte value) { - Write(new byte[]{ value }, 0, 1); + m_handler.WriteApplicationData(new byte[]{ value }, 0, 1); } } } diff --git a/crypto/src/util/io/BaseOutputStream.cs b/crypto/src/util/io/BaseOutputStream.cs index d9a5b92d6..dad9b19a4 100644 --- a/crypto/src/util/io/BaseOutputStream.cs +++ b/crypto/src/util/io/BaseOutputStream.cs @@ -10,6 +10,9 @@ namespace Org.BouncyCastle.Utilities.IO public sealed override bool CanSeek { get { return false; } } public sealed override bool CanWrite { get { return true; } } +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void CopyTo(Stream destination, int bufferSize) { throw new NotSupportedException(); } +#endif public override void Flush() {} public sealed override long Length { get { throw new NotSupportedException(); } } public sealed override long Position @@ -35,10 +38,5 @@ namespace Org.BouncyCastle.Utilities.IO { Write(buffer, 0, buffer.Length); } - - public override void WriteByte(byte value) - { - Write(new byte[]{ value }, 0, 1); - } } } diff --git a/crypto/src/util/io/FilterStream.cs b/crypto/src/util/io/FilterStream.cs index 0db82ec88..d9bcbb8ef 100644 --- a/crypto/src/util/io/FilterStream.cs +++ b/crypto/src/util/io/FilterStream.cs @@ -15,15 +15,6 @@ namespace Org.BouncyCastle.Utilities.IO this.s = s; } - protected override void Dispose(bool disposing) - { - if (disposing) - { - s.Dispose(); - } - - base.Dispose(disposing); - } public override bool CanRead { get { return s.CanRead; } @@ -36,6 +27,10 @@ namespace Org.BouncyCastle.Utilities.IO { get { return s.CanWrite; } } + public override void Flush() + { + s.Flush(); + } public override long Length { get { return s.Length; } @@ -45,9 +40,13 @@ namespace Org.BouncyCastle.Utilities.IO get { return s.Position; } set { s.Position = value; } } - public override void Flush() + public override int Read(byte[] buffer, int offset, int count) { - s.Flush(); + return s.Read(buffer, offset, count); + } + public override int ReadByte() + { + return s.ReadByte(); } public override long Seek(long offset, SeekOrigin origin) { @@ -57,14 +56,6 @@ namespace Org.BouncyCastle.Utilities.IO { s.SetLength(value); } - public override int Read(byte[] buffer, int offset, int count) - { - return s.Read(buffer, offset, count); - } - public override int ReadByte() - { - return s.ReadByte(); - } public override void Write(byte[] buffer, int offset, int count) { s.Write(buffer, offset, count); @@ -73,5 +64,18 @@ namespace Org.BouncyCastle.Utilities.IO { s.WriteByte(value); } + protected void Detach(bool disposing) + { + base.Dispose(disposing); + } + protected override void Dispose(bool disposing) + { + if (disposing) + { + s.Dispose(); + } + + base.Dispose(disposing); + } } } diff --git a/crypto/src/util/io/LimitedInputStream.cs b/crypto/src/util/io/LimitedInputStream.cs new file mode 100644 index 000000000..d6616eff5 --- /dev/null +++ b/crypto/src/util/io/LimitedInputStream.cs @@ -0,0 +1,56 @@ +using Org.BouncyCastle.Utilities.Zlib; +using System; +using System.IO; + +namespace Org.BouncyCastle.Utilities.IO +{ + internal class LimitedInputStream + : BaseInputStream + { + private readonly Stream m_stream; + private long m_limit; + + internal LimitedInputStream(Stream stream, long limit) + { + this.m_stream = stream; + this.m_limit = limit; + } + + internal long CurrentLimit => m_limit; + + public override int Read(byte[] buffer, int offset, int count) + { + int numRead = m_stream.Read(buffer, offset, count); + if (numRead > 0) + { + if ((m_limit -= numRead) < 0) + throw new StreamOverflowException("Data Overflow"); + } + return numRead; + } + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + int numRead = m_stream.Read(buffer); + if (numRead > 0) + { + if ((m_limit -= numRead) < 0) + throw new StreamOverflowException("Data Overflow"); + } + return numRead; + } +#endif + + public override int ReadByte() + { + int b = m_stream.ReadByte(); + if (b >= 0) + { + if (--m_limit < 0) + throw new StreamOverflowException("Data Overflow"); + } + return b; + } + } +} diff --git a/crypto/src/util/io/PushbackStream.cs b/crypto/src/util/io/PushbackStream.cs index 2ceb64361..15ba70501 100644 --- a/crypto/src/util/io/PushbackStream.cs +++ b/crypto/src/util/io/PushbackStream.cs @@ -13,7 +13,20 @@ namespace Org.BouncyCastle.Utilities.IO { } - public override int Read(byte[] buffer, int offset, int count) +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void CopyTo(Stream destination, int bufferSize) + { + if (m_buf != -1) + { + destination.WriteByte((byte)m_buf); + m_buf = -1; + } + + s.CopyTo(destination, bufferSize); + } +#endif + + public override int Read(byte[] buffer, int offset, int count) { Streams.ValidateBufferArguments(buffer, offset, count); @@ -27,10 +40,27 @@ namespace Org.BouncyCastle.Utilities.IO return 1; } - return base.Read(buffer, offset, count); + return s.Read(buffer, offset, count); } - public override int ReadByte() +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + if (m_buf != -1) + { + if (buffer.IsEmpty) + return 0; + + buffer[0] = (byte)m_buf; + m_buf = -1; + return 1; + } + + return s.Read(buffer); + } +#endif + + public override int ReadByte() { if (m_buf != -1) { diff --git a/crypto/src/util/io/Streams.cs b/crypto/src/util/io/Streams.cs index e1da47fcd..c23332909 100644 --- a/crypto/src/util/io/Streams.cs +++ b/crypto/src/util/io/Streams.cs @@ -13,10 +13,7 @@ namespace Org.BouncyCastle.Utilities.IO public static void Drain(Stream inStr) { - byte[] bs = new byte[BufferSize]; - while (inStr.Read(bs, 0, bs.Length) > 0) - { - } + inStr.CopyTo(Stream.Null, BufferSize); } /// <summary>Write the full contents of inStr to the destination stream outStr.</summary> @@ -25,7 +22,7 @@ namespace Org.BouncyCastle.Utilities.IO /// <exception cref="IOException">In case of IO failure.</exception> public static void PipeAll(Stream inStr, Stream outStr) { - PipeAll(inStr, outStr, BufferSize); + inStr.CopyTo(outStr, BufferSize); } /// <summary>Write the full contents of inStr to the destination stream outStr.</summary> @@ -35,12 +32,7 @@ namespace Org.BouncyCastle.Utilities.IO /// <exception cref="IOException">In case of IO failure.</exception> public static void PipeAll(Stream inStr, Stream outStr, int bufferSize) { - byte[] bs = new byte[bufferSize]; - int numRead; - while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0) - { - outStr.Write(bs, 0, numRead); - } + inStr.CopyTo(outStr, bufferSize); } /// <summary> @@ -60,17 +52,9 @@ namespace Org.BouncyCastle.Utilities.IO /// <exception cref="IOException"></exception> public static long PipeAllLimited(Stream inStr, long limit, Stream outStr) { - byte[] bs = new byte[BufferSize]; - long total = 0; - int numRead; - while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0) - { - if ((limit - total) < numRead) - throw new StreamOverflowException("Data Overflow"); - total += numRead; - outStr.Write(bs, 0, numRead); - } - return total; + var limited = new LimitedInputStream(inStr, limit); + limited.CopyTo(outStr, BufferSize); + return limit - limited.CurrentLimit; } public static byte[] ReadAll(Stream inStr) @@ -105,7 +89,22 @@ namespace Org.BouncyCastle.Utilities.IO return totalRead; } - public static void ValidateBufferArguments(byte[] buffer, int offset, int count) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public static int ReadFully(Stream inStr, Span<byte> buffer) + { + int totalRead = 0; + while (totalRead < buffer.Length) + { + int numRead = inStr.Read(buffer[totalRead..]); + if (numRead < 1) + break; + totalRead += numRead; + } + return totalRead; + } +#endif + + public static void ValidateBufferArguments(byte[] buffer, int offset, int count) { if (buffer == null) throw new ArgumentNullException("buffer"); @@ -120,6 +119,14 @@ namespace Org.BouncyCastle.Utilities.IO /// <exception cref="IOException"></exception> public static int WriteBufTo(MemoryStream buf, byte[] output, int offset) { +#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER + if (buf.TryGetBuffer(out var buffer)) + { + buffer.CopyTo(output, offset); + return buffer.Count; + } +#endif + int size = Convert.ToInt32(buf.Length); buf.WriteTo(new MemoryStream(output, offset, size)); return size; diff --git a/crypto/src/util/io/TeeInputStream.cs b/crypto/src/util/io/TeeInputStream.cs index 73ea8fed0..3d45bb4f1 100644 --- a/crypto/src/util/io/TeeInputStream.cs +++ b/crypto/src/util/io/TeeInputStream.cs @@ -18,7 +18,6 @@ namespace Org.BouncyCastle.Utilities.IO this.tee = tee; } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -28,14 +27,6 @@ namespace Org.BouncyCastle.Utilities.IO } base.Dispose(disposing); } -#else - public override void Close() - { - Platform.Dispose(input); - Platform.Dispose(tee); - base.Close(); - } -#endif public override int Read(byte[] buffer, int offset, int count) { @@ -49,7 +40,21 @@ namespace Org.BouncyCastle.Utilities.IO return i; } - public override int ReadByte() +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override int Read(Span<byte> buffer) + { + int i = input.Read(buffer); + + if (i > 0) + { + tee.Write(buffer[..i]); + } + + return i; + } +#endif + + public override int ReadByte() { int i = input.ReadByte(); diff --git a/crypto/src/util/io/TeeOutputStream.cs b/crypto/src/util/io/TeeOutputStream.cs index 5f447b18b..fc213ae55 100644 --- a/crypto/src/util/io/TeeOutputStream.cs +++ b/crypto/src/util/io/TeeOutputStream.cs @@ -18,7 +18,6 @@ namespace Org.BouncyCastle.Utilities.IO this.tee = tee; } -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) @@ -28,14 +27,6 @@ namespace Org.BouncyCastle.Utilities.IO } base.Dispose(disposing); } -#else - public override void Close() - { - Platform.Dispose(output); - Platform.Dispose(tee); - base.Close(); - } -#endif public override void Write(byte[] buffer, int offset, int count) { @@ -43,7 +34,15 @@ namespace Org.BouncyCastle.Utilities.IO tee.Write(buffer, offset, count); } - public override void WriteByte(byte value) +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public override void Write(ReadOnlySpan<byte> buffer) + { + output.Write(buffer); + tee.Write(buffer); + } +#endif + + public override void WriteByte(byte value) { output.WriteByte(value); tee.WriteByte(value); diff --git a/crypto/src/util/zlib/ZInputStream.cs b/crypto/src/util/zlib/ZInputStream.cs index 3e6fcc1be..0433a0182 100644 --- a/crypto/src/util/zlib/ZInputStream.cs +++ b/crypto/src/util/zlib/ZInputStream.cs @@ -116,34 +116,18 @@ namespace Org.BouncyCastle.Utilities.Zlib this.z.avail_in = 0; } - /*public int available() throws IOException { - return inf.finished() ? 0 : 1; - }*/ - -#if PORTABLE protected override void Dispose(bool disposing) { if (disposing) { - if (closed) - return; - - closed = true; - Platform.Dispose(input); + if (!closed) + { + closed = true; + Platform.Dispose(input); + } } base.Dispose(disposing); } -#else - public override void Close() - { - if (closed) - return; - - closed = true; - Platform.Dispose(input); - base.Close(); - } -#endif public virtual int FlushMode { diff --git a/crypto/src/util/zlib/ZOutputStream.cs b/crypto/src/util/zlib/ZOutputStream.cs index dcb93f97b..301516e57 100644 --- a/crypto/src/util/zlib/ZOutputStream.cs +++ b/crypto/src/util/zlib/ZOutputStream.cs @@ -109,49 +109,61 @@ namespace Org.BouncyCastle.Utilities.Zlib this.z.deflateInit(level, nowrap); } -#if PORTABLE - protected override void Dispose(bool disposing) + protected void Detach(bool disposing) { if (disposing) { - if (closed) - return; - - DoClose(); + if (!closed) + { + try + { + try + { + Finish(); + } + catch (IOException) + { + // Ignore + } + } + finally + { + this.closed = true; + End(); + output = null; + } + } } base.Dispose(disposing); } -#else - public override void Close() - { - if (closed) - return; - - DoClose(); - base.Close(); - } -#endif - private void DoClose() + protected override void Dispose(bool disposing) { - try + if (disposing) { - try - { - Finish(); - } - catch (IOException) + if (!closed) { - // Ignore + try + { + try + { + Finish(); + } + catch (IOException) + { + // Ignore + } + } + finally + { + this.closed = true; + End(); + Platform.Dispose(output); + output = null; + } } } - finally - { - this.closed = true; - End(); - Platform.Dispose(output); - output = null; - } + base.Dispose(disposing); } public virtual void End() diff --git a/crypto/test/src/crypto/io/test/CipherStreamTest.cs b/crypto/test/src/crypto/io/test/CipherStreamTest.cs index 44462418c..799b44521 100644 --- a/crypto/test/src/crypto/io/test/CipherStreamTest.cs +++ b/crypto/test/src/crypto/io/test/CipherStreamTest.cs @@ -1,13 +1,10 @@ -using System; using System.IO; using System.Text; using NUnit.Framework; -using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Parameters; -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.IO.Tests { @@ -20,9 +17,9 @@ namespace Org.BouncyCastle.Crypto.IO.Tests public void TestEncryptDecryptA() { byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); - byte[] encryptedDataBytes = encryptOnWrite(dataBytes); + byte[] encryptedDataBytes = EncryptOnWrite(dataBytes); - byte[] decryptedDataBytes = decryptOnRead(encryptedDataBytes); + byte[] decryptedDataBytes = DecryptOnRead(encryptedDataBytes); string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); Assert.AreEqual(DATA, decryptedData); } @@ -31,9 +28,9 @@ namespace Org.BouncyCastle.Crypto.IO.Tests public void TestEncryptDecryptB() { byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); - byte[] encryptedDataBytes = encryptOnRead(dataBytes); + byte[] encryptedDataBytes = EncryptOnRead(dataBytes); - byte[] decryptedDataBytes = decryptOnWrite(encryptedDataBytes); + byte[] decryptedDataBytes = DecryptOnWrite(encryptedDataBytes); string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); Assert.AreEqual(DATA, decryptedData); } @@ -42,9 +39,9 @@ namespace Org.BouncyCastle.Crypto.IO.Tests public void TestEncryptDecryptC() { byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); - byte[] encryptedDataBytes = encryptOnWrite(dataBytes); + byte[] encryptedDataBytes = EncryptOnWrite(dataBytes); - byte[] decryptedDataBytes = decryptOnWrite(encryptedDataBytes); + byte[] decryptedDataBytes = DecryptOnWrite(encryptedDataBytes); string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); Assert.AreEqual(DATA, decryptedData); } @@ -53,17 +50,17 @@ namespace Org.BouncyCastle.Crypto.IO.Tests public void TestEncryptDecryptD() { byte[] dataBytes = Encoding.ASCII.GetBytes(DATA); - byte[] encryptedDataBytes = encryptOnRead(dataBytes); + byte[] encryptedDataBytes = EncryptOnRead(dataBytes); - byte[] decryptedDataBytes = decryptOnRead(encryptedDataBytes); + byte[] decryptedDataBytes = DecryptOnRead(encryptedDataBytes); string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length); Assert.AreEqual(DATA, decryptedData); } - private byte[] encryptOnWrite(byte[] dataBytes) + private byte[] EncryptOnWrite(byte[] dataBytes) { MemoryStream encryptedDataStream = new MemoryStream(); - IBufferedCipher outCipher = createCipher(true); + IBufferedCipher outCipher = CreateCipher(true); CipherStream outCipherStream = new CipherStream(encryptedDataStream, null, outCipher); outCipherStream.Write(dataBytes, 0, dataBytes.Length); Assert.AreEqual(0L, encryptedDataStream.Position % outCipher.GetBlockSize()); @@ -75,11 +72,11 @@ namespace Org.BouncyCastle.Crypto.IO.Tests return encryptedDataBytes; } - private byte[] encryptOnRead(byte[] dataBytes) + private byte[] EncryptOnRead(byte[] dataBytes) { MemoryStream dataStream = new MemoryStream(dataBytes, false); MemoryStream encryptedDataStream = new MemoryStream(); - IBufferedCipher inCipher = createCipher(true); + IBufferedCipher inCipher = CreateCipher(true); CipherStream inCipherStream = new CipherStream(dataStream, inCipher, null); int ch; @@ -97,11 +94,11 @@ namespace Org.BouncyCastle.Crypto.IO.Tests return encryptedDataBytes; } - private byte[] decryptOnRead(byte[] encryptedDataBytes) + private byte[] DecryptOnRead(byte[] encryptedDataBytes) { MemoryStream encryptedDataStream = new MemoryStream(encryptedDataBytes, false); MemoryStream dataStream = new MemoryStream(); - IBufferedCipher inCipher = createCipher(false); + IBufferedCipher inCipher = CreateCipher(false); CipherStream inCipherStream = new CipherStream(encryptedDataStream, inCipher, null); int ch; @@ -119,11 +116,11 @@ namespace Org.BouncyCastle.Crypto.IO.Tests return dataBytes; } - private byte[] decryptOnWrite(byte[] encryptedDataBytes) + private byte[] DecryptOnWrite(byte[] encryptedDataBytes) { MemoryStream encryptedDataStream = new MemoryStream(encryptedDataBytes, false); MemoryStream dataStream = new MemoryStream(); - IBufferedCipher outCipher = createCipher(false); + IBufferedCipher outCipher = CreateCipher(false); CipherStream outCipherStream = new CipherStream(dataStream, null, outCipher); int ch; @@ -141,7 +138,7 @@ namespace Org.BouncyCastle.Crypto.IO.Tests return dataBytes; } - private IBufferedCipher createCipher(bool forEncryption) + private IBufferedCipher CreateCipher(bool forEncryption) { // IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CFB/NoPadding"); |