diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs
index 59178ea31..163e3848c 100644
--- a/crypto/src/asn1/Asn1OutputStream.cs
+++ b/crypto/src/asn1/Asn1OutputStream.cs
@@ -1,5 +1,10 @@
using System;
using System.IO;
+using System.Diagnostics;
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+using System.Buffers.Binary;
+using System.Numerics;
+#endif
using Org.BouncyCastle.Utilities.IO;
@@ -73,15 +78,19 @@ namespace Org.BouncyCastle.Asn1
{
if (dl < 128)
{
+ Debug.Assert(dl >= 0);
WriteByte((byte)dl);
return;
}
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- Span<byte> stack = stackalloc byte[5];
+ Span<byte> encoding = stackalloc byte[5];
+ BinaryPrimitives.WriteUInt32BigEndian(encoding[1..], (uint)dl);
+ int leadingZeroBytes = BitOperations.LeadingZeroCount((uint)dl) / 8;
+ encoding[leadingZeroBytes] = (byte)(0x84 - leadingZeroBytes);
+ Write(encoding[leadingZeroBytes..]);
#else
byte[] stack = new byte[5];
-#endif
int pos = stack.Length;
do
@@ -94,9 +103,6 @@ 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
}
diff --git a/crypto/src/asn1/ConstructedBitStream.cs b/crypto/src/asn1/ConstructedBitStream.cs
index 49f54fc1b..f089dac75 100644
--- a/crypto/src/asn1/ConstructedBitStream.cs
+++ b/crypto/src/asn1/ConstructedBitStream.cs
@@ -33,6 +33,9 @@ namespace Org.BouncyCastle.Asn1
{
Streams.ValidateBufferArguments(buffer, offset, count);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return Read(buffer.AsSpan(offset, count));
+#else
if (count < 1)
return 0;
@@ -75,8 +78,57 @@ namespace Org.BouncyCastle.Asn1
m_currentStream = m_currentParser.GetBitStream();
}
}
+#endif
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ if (buffer.IsEmpty)
+ return 0;
+
+ if (m_currentStream == null)
+ {
+ if (!m_first)
+ return 0;
+
+ m_currentParser = GetNextParser();
+ if (m_currentParser == null)
+ return 0;
+
+ m_first = false;
+ m_currentStream = m_currentParser.GetBitStream();
+ }
+
+ int totalRead = 0;
+
+ for (;;)
+ {
+ int numRead = m_currentStream.Read(buffer[totalRead..]);
+
+ if (numRead > 0)
+ {
+ totalRead += numRead;
+
+ if (totalRead == buffer.Length)
+ return totalRead;
+ }
+ else
+ {
+ m_padBits = m_currentParser.PadBits;
+ m_currentParser = GetNextParser();
+ if (m_currentParser == null)
+ {
+ m_currentStream = null;
+ return totalRead;
+ }
+
+ m_currentStream = m_currentParser.GetBitStream();
+ }
+ }
+ }
+#endif
+
public override int ReadByte()
{
if (m_currentStream == null)
diff --git a/crypto/src/asn1/ConstructedOctetStream.cs b/crypto/src/asn1/ConstructedOctetStream.cs
index 12aa14e74..d005f9fe7 100644
--- a/crypto/src/asn1/ConstructedOctetStream.cs
+++ b/crypto/src/asn1/ConstructedOctetStream.cs
@@ -1,3 +1,4 @@
+using System;
using System.IO;
using Org.BouncyCastle.Utilities;
@@ -22,6 +23,9 @@ namespace Org.BouncyCastle.Asn1
{
Streams.ValidateBufferArguments(buffer, offset, count);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return Read(buffer.AsSpan(offset, count));
+#else
if (count < 1)
return 0;
@@ -63,8 +67,56 @@ namespace Org.BouncyCastle.Asn1
m_currentStream = next.GetOctetStream();
}
}
+#endif
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ if (buffer.IsEmpty)
+ return 0;
+
+ if (m_currentStream == null)
+ {
+ if (!m_first)
+ return 0;
+
+ Asn1OctetStringParser next = GetNextParser();
+ if (next == null)
+ return 0;
+
+ m_first = false;
+ m_currentStream = next.GetOctetStream();
+ }
+
+ int totalRead = 0;
+
+ for (;;)
+ {
+ int numRead = m_currentStream.Read(buffer[totalRead..]);
+
+ if (numRead > 0)
+ {
+ totalRead += numRead;
+
+ if (totalRead == buffer.Length)
+ return totalRead;
+ }
+ else
+ {
+ Asn1OctetStringParser next = GetNextParser();
+ if (next == null)
+ {
+ m_currentStream = null;
+ return totalRead;
+ }
+
+ m_currentStream = next.GetOctetStream();
+ }
+ }
+ }
+#endif
+
public override int ReadByte()
{
if (m_currentStream == null)
diff --git a/crypto/src/asn1/DefiniteLengthInputStream.cs b/crypto/src/asn1/DefiniteLengthInputStream.cs
index ed5bd2446..89f0d5a62 100644
--- a/crypto/src/asn1/DefiniteLengthInputStream.cs
+++ b/crypto/src/asn1/DefiniteLengthInputStream.cs
@@ -79,6 +79,27 @@ namespace Org.BouncyCastle.Asn1
return numRead;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ if (_remaining == 0)
+ return 0;
+
+ int toRead = System.Math.Min(buffer.Length, _remaining);
+ int numRead = _in.Read(buffer[..toRead]);
+
+ if (numRead < 1)
+ throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+
+ if ((_remaining -= numRead) == 0)
+ {
+ SetParentEofDetect();
+ }
+
+ return numRead;
+ }
+#endif
+
internal void ReadAllIntoByteArray(byte[] buf)
{
if (_remaining != buf.Length)
diff --git a/crypto/src/asn1/IndefiniteLengthInputStream.cs b/crypto/src/asn1/IndefiniteLengthInputStream.cs
index 1c8bd9a15..e192e9e8b 100644
--- a/crypto/src/asn1/IndefiniteLengthInputStream.cs
+++ b/crypto/src/asn1/IndefiniteLengthInputStream.cs
@@ -57,7 +57,28 @@ namespace Org.BouncyCastle.Asn1
return numRead + 1;
}
- public override int ReadByte()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ // Only use this optimisation if we aren't checking for 00
+ if (_eofOn00 || buffer.Length <= 1)
+ return base.Read(buffer);
+
+ if (_lookAhead < 0)
+ return 0;
+
+ int numRead = _in.Read(buffer[1..]);
+ if (numRead <= 0)
+ throw new EndOfStreamException();
+
+ buffer[0] = (byte)_lookAhead;
+ _lookAhead = RequireByte();
+
+ return numRead + 1;
+ }
+#endif
+
+ public override int ReadByte()
{
if (_eofOn00 && _lookAhead <= 0)
{
diff --git a/crypto/src/bcpg/ArmoredInputStream.cs b/crypto/src/bcpg/ArmoredInputStream.cs
index 1c5ebd7c5..4fbb8baae 100644
--- a/crypto/src/bcpg/ArmoredInputStream.cs
+++ b/crypto/src/bcpg/ArmoredInputStream.cs
@@ -1,3 +1,4 @@
+using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
@@ -330,6 +331,26 @@ namespace Org.BouncyCastle.Bcpg
return pos;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ /*
+ * TODO Currently can't return partial data when exception thrown (breaking test case), so we don't inherit
+ * the base class implementation. Probably the reason is that throws don't mark this instance as 'failed'.
+ */
+ int pos = 0;
+ while (pos < buffer.Length)
+ {
+ int b = ReadByte();
+ if (b < 0)
+ break;
+
+ buffer[pos++] = (byte)b;
+ }
+ return pos;
+ }
+#endif
+
public override int ReadByte()
{
if (start)
diff --git a/crypto/src/bcpg/BcpgInputStream.cs b/crypto/src/bcpg/BcpgInputStream.cs
index 7a19a90dd..3b6f61bbc 100644
--- a/crypto/src/bcpg/BcpgInputStream.cs
+++ b/crypto/src/bcpg/BcpgInputStream.cs
@@ -57,6 +57,21 @@ namespace Org.BouncyCastle.Bcpg
return 1;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ if (!next)
+ return m_in.Read(buffer);
+
+ if (nextB < 0)
+ return 0;
+
+ buffer[0] = (byte)nextB;
+ next = false;
+ return 1;
+ }
+#endif
+
public byte[] ReadAll()
{
return Streams.ReadAll(this);
@@ -312,9 +327,8 @@ namespace Org.BouncyCastle.Bcpg
int readLen = (dataLength > count || dataLength < 0) ? count : dataLength;
int len = m_in.Read(buffer, offset, readLen);
if (len < 1)
- {
throw new EndOfStreamException("Premature end of stream in PartialInputStream");
- }
+
dataLength -= len;
return len;
}
@@ -324,6 +338,29 @@ namespace Org.BouncyCastle.Bcpg
return 0;
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ do
+ {
+ if (dataLength != 0)
+ {
+ int count = buffer.Length;
+ int readLen = (dataLength > count || dataLength < 0) ? count : dataLength;
+ int len = m_in.Read(buffer[..readLen]);
+ if (len < 1)
+ throw new EndOfStreamException("Premature end of stream in PartialInputStream");
+
+ dataLength -= len;
+ return len;
+ }
+ }
+ while (partial && ReadPartialDataLength() >= 0);
+
+ return 0;
+ }
+#endif
+
private int ReadPartialDataLength()
{
int l = m_in.ReadByte();
diff --git a/crypto/src/bcpg/BcpgOutputStream.cs b/crypto/src/bcpg/BcpgOutputStream.cs
index fbdd75bff..690686d88 100644
--- a/crypto/src/bcpg/BcpgOutputStream.cs
+++ b/crypto/src/bcpg/BcpgOutputStream.cs
@@ -164,7 +164,7 @@ namespace Org.BouncyCastle.Bcpg
if (partialBuffer != null)
{
- PartialFlush(true);
+ PartialFlushLast();
partialBuffer = null;
}
@@ -215,19 +215,26 @@ namespace Org.BouncyCastle.Bcpg
}
}
- private void PartialFlush(bool isLast)
+ private void PartialFlush()
{
- if (isLast)
- {
- WriteNewPacketLength(partialOffset);
- outStr.Write(partialBuffer, 0, partialOffset);
- }
- else
- {
- outStr.WriteByte((byte)(0xE0 | partialPower));
- outStr.Write(partialBuffer, 0, partialBufferLength);
- }
+ outStr.WriteByte((byte)(0xE0 | partialPower));
+ outStr.Write(partialBuffer, 0, partialBufferLength);
+ partialOffset = 0;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private void PartialFlush(ref ReadOnlySpan<byte> buffer)
+ {
+ outStr.WriteByte((byte)(0xE0 | partialPower));
+ outStr.Write(buffer[..partialBufferLength]);
+ buffer = buffer[partialBufferLength..];
+ }
+#endif
+ private void PartialFlushLast()
+ {
+ WriteNewPacketLength(partialOffset);
+ outStr.Write(partialBuffer, 0, partialOffset);
partialOffset = 0;
}
@@ -235,40 +242,71 @@ namespace Org.BouncyCastle.Bcpg
{
Streams.ValidateBufferArguments(buffer, offset, count);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ PartialWrite(buffer.AsSpan(offset, count));
+#else
if (partialOffset == partialBufferLength)
{
- PartialFlush(false);
+ PartialFlush();
}
if (count <= (partialBufferLength - partialOffset))
{
Array.Copy(buffer, offset, partialBuffer, partialOffset, count);
partialOffset += count;
+ return;
}
- else
+
+ int diff = partialBufferLength - partialOffset;
+ Array.Copy(buffer, offset, partialBuffer, partialOffset, diff);
+ offset += diff;
+ count -= diff;
+ PartialFlush();
+ while (count > partialBufferLength)
{
- int diff = partialBufferLength - partialOffset;
- Array.Copy(buffer, offset, partialBuffer, partialOffset, diff);
- offset += diff;
- count -= diff;
- PartialFlush(false);
- while (count > partialBufferLength)
- {
- Array.Copy(buffer, offset, partialBuffer, 0, partialBufferLength);
- offset += partialBufferLength;
- count -= partialBufferLength;
- PartialFlush(false);
- }
- Array.Copy(buffer, offset, partialBuffer, 0, count);
- partialOffset += count;
+ Array.Copy(buffer, offset, partialBuffer, 0, partialBufferLength);
+ offset += partialBufferLength;
+ count -= partialBufferLength;
+ PartialFlush();
}
+ Array.Copy(buffer, offset, partialBuffer, 0, count);
+ partialOffset = count;
+#endif
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ private void PartialWrite(ReadOnlySpan<byte> buffer)
+ {
+ if (partialOffset == partialBufferLength)
+ {
+ PartialFlush();
+ }
+
+ if (buffer.Length <= (partialBufferLength - partialOffset))
+ {
+ buffer.CopyTo(partialBuffer.AsSpan(partialOffset));
+ partialOffset += buffer.Length;
+ return;
+ }
+
+ int diff = partialBufferLength - partialOffset;
+ buffer[..diff].CopyTo(partialBuffer.AsSpan(partialOffset));
+ buffer = buffer[diff..];
+ PartialFlush();
+ while (buffer.Length > partialBufferLength)
+ {
+ PartialFlush(ref buffer);
+ }
+ buffer.CopyTo(partialBuffer);
+ partialOffset = buffer.Length;
+ }
+#endif
+
private void PartialWriteByte(byte value)
{
if (partialOffset == partialBufferLength)
{
- PartialFlush(false);
+ PartialFlush();
}
partialBuffer[partialOffset++] = value;
@@ -286,6 +324,20 @@ namespace Org.BouncyCastle.Bcpg
}
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ if (partialBuffer != null)
+ {
+ PartialWrite(buffer);
+ }
+ else
+ {
+ outStr.Write(buffer);
+ }
+ }
+#endif
+
public override void WriteByte(byte value)
{
if (partialBuffer != null)
@@ -370,7 +422,7 @@ namespace Org.BouncyCastle.Bcpg
{
if (partialBuffer != null)
{
- PartialFlush(true);
+ PartialFlushLast();
Array.Clear(partialBuffer, 0, partialBuffer.Length);
partialBuffer = null;
}
diff --git a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
index b2c5cac28..6348431a2 100644
--- a/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSAuthenticatedDataStreamGenerator.cs
@@ -237,7 +237,14 @@ namespace Org.BouncyCastle.Cms
macStream.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)
+ {
+ macStream.Write(buffer);
+ }
+#endif
+
+ public override void WriteByte(byte value)
{
macStream.WriteByte(value);
}
diff --git a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
index 1594500cd..3669c0b3a 100644
--- a/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSCompressedDataStreamGenerator.cs
@@ -4,6 +4,7 @@ using System.IO;
using Org.BouncyCastle.Asn1;
using Org.BouncyCastle.Asn1.Cms;
using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.IO;
using Org.BouncyCastle.Utilities;
using Org.BouncyCastle.Utilities.IO;
@@ -118,7 +119,14 @@ namespace Org.BouncyCastle.Cms
_out.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)
+ {
+ _out.Write(buffer);
+ }
+#endif
+
+ public override void WriteByte(byte value)
{
_out.WriteByte(value);
}
diff --git a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
index 6a362e13f..ad356a208 100644
--- a/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSEnvelopedDataStreamGenerator.cs
@@ -240,7 +240,14 @@ namespace Org.BouncyCastle.Cms
_out.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)
+ {
+ _out.Write(buffer);
+ }
+#endif
+
+ public override void WriteByte(byte value)
{
_out.WriteByte(value);
}
diff --git a/crypto/src/cms/CMSSignedDataStreamGenerator.cs b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
index f934b9259..3f2da5f7e 100644
--- a/crypto/src/cms/CMSSignedDataStreamGenerator.cs
+++ b/crypto/src/cms/CMSSignedDataStreamGenerator.cs
@@ -783,7 +783,14 @@ namespace Org.BouncyCastle.Cms
_out.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)
+ {
+ _out.Write(buffer);
+ }
+#endif
+
+ public override void WriteByte(byte value)
{
_out.WriteByte(value);
}
diff --git a/crypto/src/cms/CMSTypedStream.cs b/crypto/src/cms/CMSTypedStream.cs
index d4ca62256..7a66f0c74 100644
--- a/crypto/src/cms/CMSTypedStream.cs
+++ b/crypto/src/cms/CMSTypedStream.cs
@@ -59,13 +59,6 @@ namespace Org.BouncyCastle.Cms
{
}
-#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(s, buf, off, len);
diff --git a/crypto/src/openpgp/PgpEncryptedData.cs b/crypto/src/openpgp/PgpEncryptedData.cs
index 5cdc0d533..bad4cb8cd 100644
--- a/crypto/src/openpgp/PgpEncryptedData.cs
+++ b/crypto/src/openpgp/PgpEncryptedData.cs
@@ -54,6 +54,9 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
{
Streams.ValidateBufferArguments(buffer, offset, count);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ return Read(buffer.AsSpan(offset, count));
+#else
int avail = bufEnd - bufStart;
int pos = offset;
@@ -73,8 +76,34 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
bufStart += count;
return pos + count - offset;
+#endif
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ int avail = bufEnd - bufStart;
+
+ int pos = 0, count = buffer.Length;
+ while (count > avail)
+ {
+ lookAhead.AsSpan(bufStart, avail).CopyTo(buffer[pos..]);
+
+ bufStart += avail;
+ pos += avail;
+ count -= avail;
+
+ if ((avail = FillBuffer()) < 1)
+ return pos;
+ }
+
+ lookAhead.AsSpan(bufStart, count).CopyTo(buffer[pos..]);
+ bufStart += count;
+
+ return pos + count;
+ }
+#endif
+
public override int ReadByte()
{
if (bufStart < bufEnd)
diff --git a/crypto/src/openpgp/WrappedGeneratorStream.cs b/crypto/src/openpgp/WrappedGeneratorStream.cs
index c54ee0b3b..6f96dc9b8 100644
--- a/crypto/src/openpgp/WrappedGeneratorStream.cs
+++ b/crypto/src/openpgp/WrappedGeneratorStream.cs
@@ -13,10 +13,7 @@ namespace Org.BouncyCastle.Bcpg.OpenPgp
internal WrappedGeneratorStream(IStreamGenerator generator, Stream s)
: base(s)
{
- if (generator == null)
- throw new ArgumentNullException(nameof(generator));
-
- m_generator = generator;
+ m_generator = generator ?? throw new ArgumentNullException(nameof(generator));
}
protected override void Dispose(bool disposing)
diff --git a/crypto/src/tls/CombinedHash.cs b/crypto/src/tls/CombinedHash.cs
index 71151d2a5..360b9d426 100644
--- a/crypto/src/tls/CombinedHash.cs
+++ b/crypto/src/tls/CombinedHash.cs
@@ -43,6 +43,14 @@ namespace Org.BouncyCastle.Tls
m_sha1.Update(input, inOff, len);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void Update(ReadOnlySpan<byte> input)
+ {
+ m_md5.Update(input);
+ m_sha1.Update(input);
+ }
+#endif
+
public virtual byte[] CalculateHash()
{
if (null != m_context && TlsUtilities.IsSsl(m_context))
diff --git a/crypto/src/tls/DeferredHash.cs b/crypto/src/tls/DeferredHash.cs
index 82f7899a5..e6397ab1e 100644
--- a/crypto/src/tls/DeferredHash.cs
+++ b/crypto/src/tls/DeferredHash.cs
@@ -176,6 +176,22 @@ namespace Org.BouncyCastle.Tls
}
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void Update(ReadOnlySpan<byte> input)
+ {
+ if (m_buf != null)
+ {
+ m_buf.Write(input);
+ return;
+ }
+
+ foreach (TlsHash hash in m_hashes.Values)
+ {
+ hash.Update(input);
+ }
+ }
+#endif
+
public byte[] CalculateHash()
{
throw new InvalidOperationException("Use 'ForkPrfHash' to get a definite hash");
diff --git a/crypto/src/tls/crypto/TlsHash.cs b/crypto/src/tls/crypto/TlsHash.cs
index 4732fc280..6fbaeceb9 100644
--- a/crypto/src/tls/crypto/TlsHash.cs
+++ b/crypto/src/tls/crypto/TlsHash.cs
@@ -11,6 +11,10 @@ namespace Org.BouncyCastle.Tls.Crypto
/// <param name="length">the length of the input data.</param>
void Update(byte[] input, int inOff, int length);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ void Update(ReadOnlySpan<byte> input);
+#endif
+
/// <summary>Return calculated hash for any input passed in.</summary>
/// <returns>the hash value.</returns>
byte[] CalculateHash();
diff --git a/crypto/src/tls/crypto/TlsHashSink.cs b/crypto/src/tls/crypto/TlsHashSink.cs
index a1681b0c8..3401eb60e 100644
--- a/crypto/src/tls/crypto/TlsHashSink.cs
+++ b/crypto/src/tls/crypto/TlsHashSink.cs
@@ -29,6 +29,16 @@ namespace Org.BouncyCastle.Tls.Crypto
}
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ if (!buffer.IsEmpty)
+ {
+ m_hash.Update(buffer);
+ }
+ }
+#endif
+
public override void WriteByte(byte value)
{
m_hash.Update(new byte[]{ value }, 0, 1);
diff --git a/crypto/src/tls/crypto/TlsMac.cs b/crypto/src/tls/crypto/TlsMac.cs
index a898a9bcc..511e29d10 100644
--- a/crypto/src/tls/crypto/TlsMac.cs
+++ b/crypto/src/tls/crypto/TlsMac.cs
@@ -21,6 +21,10 @@ namespace Org.BouncyCastle.Tls.Crypto
/// <param name="length">the length of the input data.</param>
void Update(byte[] input, int inOff, int length);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ void Update(ReadOnlySpan<byte> input);
+#endif
+
/// <summary>Return calculated MAC for any input passed in.</summary>
/// <returns>the MAC value.</returns>
byte[] CalculateMac();
diff --git a/crypto/src/tls/crypto/TlsMacSink.cs b/crypto/src/tls/crypto/TlsMacSink.cs
index e7d5c70d7..fbb2e5893 100644
--- a/crypto/src/tls/crypto/TlsMacSink.cs
+++ b/crypto/src/tls/crypto/TlsMacSink.cs
@@ -29,6 +29,16 @@ namespace Org.BouncyCastle.Tls.Crypto
}
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ if (!buffer.IsEmpty)
+ {
+ m_mac.Update(buffer);
+ }
+ }
+#endif
+
public override void WriteByte(byte value)
{
m_mac.Update(new byte[]{ value }, 0, 1);
diff --git a/crypto/src/tls/crypto/impl/bc/BcSsl3Hmac.cs b/crypto/src/tls/crypto/impl/bc/BcSsl3Hmac.cs
index f26a50d46..a0378e334 100644
--- a/crypto/src/tls/crypto/impl/bc/BcSsl3Hmac.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcSsl3Hmac.cs
@@ -66,6 +66,13 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
m_digest.BlockUpdate(input, inOff, len);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void Update(ReadOnlySpan<byte> input)
+ {
+ m_digest.BlockUpdate(input);
+ }
+#endif
+
public virtual byte[] CalculateMac()
{
byte[] result = new byte[m_digest.GetDigestSize()];
diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsHash.cs b/crypto/src/tls/crypto/impl/bc/BcTlsHash.cs
index 0b35831f3..0ad2576cb 100644
--- a/crypto/src/tls/crypto/impl/bc/BcTlsHash.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcTlsHash.cs
@@ -28,6 +28,13 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
m_digest.BlockUpdate(data, offSet, length);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void Update(ReadOnlySpan<byte> input)
+ {
+ m_digest.BlockUpdate(input);
+ }
+#endif
+
public byte[] CalculateHash()
{
byte[] rv = new byte[m_digest.GetDigestSize()];
diff --git a/crypto/src/tls/crypto/impl/bc/BcTlsHmac.cs b/crypto/src/tls/crypto/impl/bc/BcTlsHmac.cs
index 7a2318a31..dbe7f4c69 100644
--- a/crypto/src/tls/crypto/impl/bc/BcTlsHmac.cs
+++ b/crypto/src/tls/crypto/impl/bc/BcTlsHmac.cs
@@ -32,6 +32,13 @@ namespace Org.BouncyCastle.Tls.Crypto.Impl.BC
m_hmac.BlockUpdate(input, inOff, length);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void Update(ReadOnlySpan<byte> input)
+ {
+ m_hmac.BlockUpdate(input);
+ }
+#endif
+
public byte[] CalculateMac()
{
byte[] rv = new byte[m_hmac.GetMacSize()];
diff --git a/crypto/src/util/io/BaseInputStream.cs b/crypto/src/util/io/BaseInputStream.cs
index ebe256632..eaaf9556d 100644
--- a/crypto/src/util/io/BaseInputStream.cs
+++ b/crypto/src/util/io/BaseInputStream.cs
@@ -45,5 +45,9 @@ namespace Org.BouncyCastle.Utilities.IO
public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
public sealed override void SetLength(long value) { throw new NotSupportedException(); }
public sealed override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void Write(ReadOnlySpan<byte> buffer) { throw new NotSupportedException(); }
+#endif
}
}
diff --git a/crypto/src/util/io/BaseOutputStream.cs b/crypto/src/util/io/BaseOutputStream.cs
index dad9b19a4..0fc8e9681 100644
--- a/crypto/src/util/io/BaseOutputStream.cs
+++ b/crypto/src/util/io/BaseOutputStream.cs
@@ -21,6 +21,9 @@ namespace Org.BouncyCastle.Utilities.IO
set { throw new NotSupportedException(); }
}
public sealed override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public sealed override int Read(Span<byte> buffer) { throw new NotSupportedException(); }
+#endif
public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
public sealed override void SetLength(long value) { throw new NotSupportedException(); }
diff --git a/crypto/src/util/io/FilterStream.cs b/crypto/src/util/io/FilterStream.cs
index d9bcbb8ef..38077edd2 100644
--- a/crypto/src/util/io/FilterStream.cs
+++ b/crypto/src/util/io/FilterStream.cs
@@ -10,10 +10,7 @@ namespace Org.BouncyCastle.Utilities.IO
public FilterStream(Stream s)
{
- if (s == null)
- throw new ArgumentNullException(nameof(s));
-
- this.s = s;
+ this.s = s ?? throw new ArgumentNullException(nameof(s));
}
public override bool CanRead
{
@@ -27,6 +24,12 @@ namespace Org.BouncyCastle.Utilities.IO
{
get { return s.CanWrite; }
}
+#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void CopyTo(Stream destination, int bufferSize)
+ {
+ s.CopyTo(destination, bufferSize);
+ }
+#endif
public override void Flush()
{
s.Flush();
@@ -44,6 +47,12 @@ namespace Org.BouncyCastle.Utilities.IO
{
return s.Read(buffer, offset, count);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ return s.Read(buffer);
+ }
+#endif
public override int ReadByte()
{
return s.ReadByte();
@@ -60,6 +69,12 @@ namespace Org.BouncyCastle.Utilities.IO
{
s.Write(buffer, offset, count);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ s.Write(buffer);
+ }
+#endif
public override void WriteByte(byte value)
{
s.WriteByte(value);
|