diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-11-01 14:39:54 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2022-11-01 14:39:54 +0700 |
commit | 716a491e3ed312da6c80a74e327d62dd4388b11e (patch) | |
tree | 0adabea28431857f372256233ddd4b2e0982190b /crypto/src/asn1 | |
parent | Package with LICENSE.md file (diff) | |
download | BouncyCastle.NET-ed25519-716a491e3ed312da6c80a74e327d62dd4388b11e.tar.xz |
More Span-based Stream methods
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r-- | crypto/src/asn1/Asn1OutputStream.cs | 16 | ||||
-rw-r--r-- | crypto/src/asn1/ConstructedBitStream.cs | 52 | ||||
-rw-r--r-- | crypto/src/asn1/ConstructedOctetStream.cs | 52 | ||||
-rw-r--r-- | crypto/src/asn1/DefiniteLengthInputStream.cs | 21 | ||||
-rw-r--r-- | crypto/src/asn1/IndefiniteLengthInputStream.cs | 23 |
5 files changed, 158 insertions, 6 deletions
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) { |