summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2022-09-01 15:13:01 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2022-09-01 15:13:01 +0700
commit4b8ca91cabe63d889f2dd770f629ba62444ed1ac (patch)
tree147c0e2818f464d5bb099ddbc241cc5c76a78603
parentSpan-based variants for IAeadCipher.ProcessByte(s) (diff)
downloadBouncyCastle.NET-ed25519-4b8ca91cabe63d889f2dd770f629ba62444ed1ac.tar.xz
Span-base variants for IBufferedCipher
-rw-r--r--crypto/src/crypto/BufferedAeadBlockCipher.cs27
-rw-r--r--crypto/src/crypto/BufferedAeadCipher.cs21
-rw-r--r--crypto/src/crypto/BufferedAsymmetricBlockCipher.cs35
-rw-r--r--crypto/src/crypto/BufferedBlockCipher.cs72
-rw-r--r--crypto/src/crypto/BufferedCipherBase.cs15
-rw-r--r--crypto/src/crypto/BufferedIesCipher.cs27
-rw-r--r--crypto/src/crypto/BufferedStreamCipher.cs25
-rw-r--r--crypto/src/crypto/IBufferedCipher.cs9
8 files changed, 208 insertions, 23 deletions
diff --git a/crypto/src/crypto/BufferedAeadBlockCipher.cs b/crypto/src/crypto/BufferedAeadBlockCipher.cs
index 7ba41090f..92eab9dd4 100644
--- a/crypto/src/crypto/BufferedAeadBlockCipher.cs
+++ b/crypto/src/crypto/BufferedAeadBlockCipher.cs
@@ -172,7 +172,14 @@ namespace Org.BouncyCastle.Crypto
 			return cipher.ProcessBytes(input, inOff, length, output, outOff);
 		}
 
-		public override byte[] DoFinal()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+        {
+            return cipher.ProcessBytes(input, output);
+        }
+#endif
+
+        public override byte[] DoFinal()
 		{
             byte[] outBytes = new byte[GetOutputSize(0)];
 
@@ -235,11 +242,25 @@ namespace Org.BouncyCastle.Crypto
 			return cipher.DoFinal(output, outOff);
 		}
 
-		/**
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int DoFinal(Span<byte> output)
+		{
+            return cipher.DoFinal(output);
+        }
+
+        public override int DoFinal(ReadOnlySpan<byte> input, Span<byte> output)
+        {
+            int len = cipher.ProcessBytes(input, output);
+            len += cipher.DoFinal(output[len..]);
+            return len;
+        }
+#endif
+
+        /**
 		* Reset the buffer and cipher. After resetting the object is in the same
 		* state as it was after the last init (if there was one).
 		*/
-		public override void Reset()
+        public override void Reset()
 		{
 			cipher.Reset();
 		}
diff --git a/crypto/src/crypto/BufferedAeadCipher.cs b/crypto/src/crypto/BufferedAeadCipher.cs
index c689c1eab..aba64f0f4 100644
--- a/crypto/src/crypto/BufferedAeadCipher.cs
+++ b/crypto/src/crypto/BufferedAeadCipher.cs
@@ -171,6 +171,13 @@ namespace Org.BouncyCastle.Crypto
             return cipher.ProcessBytes(input, inOff, length, output, outOff);
         }
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+        {
+            return cipher.ProcessBytes(input, output);
+        }
+#endif
+
         public override byte[] DoFinal()
         {
             byte[] outBytes = new byte[GetOutputSize(0)];
@@ -234,6 +241,20 @@ namespace Org.BouncyCastle.Crypto
             return cipher.DoFinal(output, outOff);
         }
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int DoFinal(Span<byte> output)
+        {
+            return cipher.DoFinal(output);
+        }
+
+        public override int DoFinal(ReadOnlySpan<byte> input, Span<byte> output)
+        {
+            int len = cipher.ProcessBytes(input, output);
+            len += cipher.DoFinal(output[len..]);
+            return len;
+        }
+#endif
+
         /**
         * Reset the buffer and cipher. After resetting the object is in the same
         * state as it was after the last init (if there was one).
diff --git a/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs b/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs
index bf00f3ece..83c2fe70c 100644
--- a/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs
+++ b/crypto/src/crypto/BufferedAsymmetricBlockCipher.cs
@@ -1,7 +1,4 @@
 using System;
-using System.Diagnostics;
-
-using Org.BouncyCastle.Crypto.Engines;
 
 namespace Org.BouncyCastle.Crypto
 {
@@ -111,7 +108,18 @@ namespace Org.BouncyCastle.Crypto
 			return null;
 		}
 
-		/**
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+		{
+			Check.DataLength(input, buffer.Length - bufOff, "attempt to process message too long for cipher");
+
+			input.CopyTo(buffer.AsSpan(bufOff));
+            bufOff += input.Length;
+            return 0;
+        }
+#endif
+
+        /**
         * process the contents of the buffer using the underlying
         * cipher.
         *
@@ -139,7 +147,24 @@ namespace Org.BouncyCastle.Crypto
 			return DoFinal();
 		}
 
-		/// <summary>Reset the buffer</summary>
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int DoFinal(Span<byte> output)
+		{
+			int result = 0;
+			if (bufOff > 0)
+			{
+				byte[] outBytes = cipher.ProcessBlock(buffer, 0, bufOff);
+				outBytes.CopyTo(output);
+				result = outBytes.Length;
+            }
+
+            Reset();
+
+            return result;
+        }
+#endif
+
+        /// <summary>Reset the buffer</summary>
         public override void Reset()
         {
 			if (buffer != null)
diff --git a/crypto/src/crypto/BufferedBlockCipher.cs b/crypto/src/crypto/BufferedBlockCipher.cs
index c87d2daf9..3b000ed59 100644
--- a/crypto/src/crypto/BufferedBlockCipher.cs
+++ b/crypto/src/crypto/BufferedBlockCipher.cs
@@ -1,5 +1,4 @@
 using System;
-using System.Diagnostics;
 
 using Org.BouncyCastle.Crypto.Parameters;
 
@@ -228,14 +227,14 @@ namespace Org.BouncyCastle.Crypto
 
             int resultLen = 0;
 			int gapLen = buf.Length - bufOff;
-			if (length > gapLen)
+			if (length >= gapLen)
 			{
 				Array.Copy(input, inOff, buf, bufOff, gapLen);
 				resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
 				bufOff = 0;
 				length -= gapLen;
 				inOff += gapLen;
-				while (length > buf.Length)
+				while (length >= buf.Length)
 				{
 					resultLen += cipher.ProcessBlock(input, inOff, output, outOff + resultLen);
 					length -= blockSize;
@@ -244,15 +243,44 @@ namespace Org.BouncyCastle.Crypto
 			}
 			Array.Copy(input, inOff, buf, bufOff, length);
 			bufOff += length;
-			if (bufOff == buf.Length)
-			{
-				resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen);
-				bufOff = 0;
-			}
 			return resultLen;
 		}
 
-		public override byte[] DoFinal()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+        {
+            if (input.IsEmpty)
+                return 0;
+
+            int blockSize = GetBlockSize();
+            int outLength = GetUpdateOutputSize(input.Length);
+
+            if (outLength > 0)
+            {
+                Check.OutputLength(output, outLength, "output buffer too short");
+            }
+
+            int resultLen = 0;
+            int gapLen = buf.Length - bufOff;
+            if (input.Length >= gapLen)
+            {
+				input[..gapLen].CopyTo(buf.AsSpan(bufOff));
+                resultLen += cipher.ProcessBlock(buf, output);
+                bufOff = 0;
+				input = input[gapLen..];
+                while (input.Length >= buf.Length)
+                {
+                    resultLen += cipher.ProcessBlock(input, output[resultLen..]);
+					input = input[blockSize..];
+                }
+            }
+            input.CopyTo(buf.AsSpan(bufOff));
+            bufOff += input.Length;
+            return resultLen;
+        }
+#endif
+
+        public override byte[] DoFinal()
 		{
 			byte[] outBytes = EmptyBuffer;
 
@@ -352,7 +380,31 @@ namespace Org.BouncyCastle.Crypto
 			}
 		}
 
-		/**
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int DoFinal(Span<byte> output)
+		{
+            try
+            {
+                if (bufOff != 0)
+                {
+                    Check.DataLength(!cipher.IsPartialBlockOkay, "data not block size aligned");
+                    Check.OutputLength(output, bufOff, "output buffer too short for DoFinal()");
+
+                    // NB: Can't copy directly, or we may write too much output
+                    cipher.ProcessBlock(buf, buf);
+					buf.AsSpan(0, bufOff).CopyTo(output);
+                }
+
+                return bufOff;
+            }
+            finally
+            {
+                Reset();
+            }
+        }
+#endif
+
+        /**
 		* Reset the buffer and cipher. After resetting the object is in the same
 		* state as it was after the last init (if there was one).
 		*/
diff --git a/crypto/src/crypto/BufferedCipherBase.cs b/crypto/src/crypto/BufferedCipherBase.cs
index 9d8610211..4b3069d0d 100644
--- a/crypto/src/crypto/BufferedCipherBase.cs
+++ b/crypto/src/crypto/BufferedCipherBase.cs
@@ -64,6 +64,10 @@ namespace Org.BouncyCastle.Crypto
 			return outBytes.Length;
 		}
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+		public abstract int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output);
+#endif
+
 		public abstract byte[] DoFinal();
 
 		public virtual byte[] DoFinal(
@@ -108,6 +112,17 @@ namespace Org.BouncyCastle.Crypto
 			return len;
 		}
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+		public abstract int DoFinal(Span<byte> output);
+
+		public virtual int DoFinal(ReadOnlySpan<byte> input, Span<byte> output)
+		{
+			int len = ProcessBytes(input, output);
+			len += DoFinal(output[len..]);
+			return len;
+		}
+#endif
+
 		public abstract void Reset();
 	}
 }
diff --git a/crypto/src/crypto/BufferedIesCipher.cs b/crypto/src/crypto/BufferedIesCipher.cs
index b0330e416..1aff47ab4 100644
--- a/crypto/src/crypto/BufferedIesCipher.cs
+++ b/crypto/src/crypto/BufferedIesCipher.cs
@@ -2,8 +2,6 @@ using System;
 using System.IO;
 
 using Org.BouncyCastle.Crypto.Engines;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto
 {
@@ -87,7 +85,15 @@ namespace Org.BouncyCastle.Crypto
 			return null;
 		}
 
-		public override byte[] DoFinal()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+		{
+			buffer.Write(input);
+			return 0;
+		}
+#endif
+
+        public override byte[] DoFinal()
 		{
 			byte[] buf = buffer.ToArray();
 
@@ -105,7 +111,20 @@ namespace Org.BouncyCastle.Crypto
 			return DoFinal();
 		}
 
-		public override void Reset()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int DoFinal(Span<byte> output)
+		{
+            byte[] buf = buffer.ToArray();
+
+            Reset();
+
+            byte[] block = engine.ProcessBlock(buf, 0, buf.Length);
+			block.CopyTo(output);
+			return block.Length;
+        }
+#endif
+
+        public override void Reset()
 		{
 			buffer.SetLength(0);
 		}
diff --git a/crypto/src/crypto/BufferedStreamCipher.cs b/crypto/src/crypto/BufferedStreamCipher.cs
index 2d4987bba..8307429cb 100644
--- a/crypto/src/crypto/BufferedStreamCipher.cs
+++ b/crypto/src/crypto/BufferedStreamCipher.cs
@@ -101,6 +101,14 @@ namespace Org.BouncyCastle.Crypto
 			return length;
 		}
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+		public override int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
+		{
+			cipher.ProcessBytes(input, output);
+			return input.Length;
+		}
+#endif
+
 		public override byte[] DoFinal()
 		{
 			Reset();
@@ -123,7 +131,22 @@ namespace Org.BouncyCastle.Crypto
 			return output;
 		}
 
-		public override void Reset()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+        public override int DoFinal(Span<byte> output)
+		{
+			Reset();
+			return 0;
+		}
+
+        public virtual int DoFinal(ReadOnlySpan<byte> input, Span<byte> output)
+        {
+            int len = ProcessBytes(input, output);
+			Reset();
+            return len;
+        }
+#endif
+
+        public override void Reset()
 		{
 			cipher.Reset();
 		}
diff --git a/crypto/src/crypto/IBufferedCipher.cs b/crypto/src/crypto/IBufferedCipher.cs
index 69dec9596..ddfb524c9 100644
--- a/crypto/src/crypto/IBufferedCipher.cs
+++ b/crypto/src/crypto/IBufferedCipher.cs
@@ -28,6 +28,10 @@ namespace Org.BouncyCastle.Crypto
 		int ProcessBytes(byte[] input, byte[] output, int outOff);
 		int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff);
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+		int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output);
+#endif
+
 		byte[] DoFinal();
 		byte[] DoFinal(byte[] input);
 		byte[] DoFinal(byte[] input, int inOff, int length);
@@ -35,6 +39,11 @@ namespace Org.BouncyCastle.Crypto
 		int DoFinal(byte[] input, byte[] output, int outOff);
 		int DoFinal(byte[] input, int inOff, int length, byte[] output, int outOff);
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+		int DoFinal(Span<byte> output);
+		int DoFinal(ReadOnlySpan<byte> input, Span<byte> output);
+#endif
+
 		/// <summary>
 		/// Reset the cipher. After resetting the cipher is in the same state
 		/// as it was after the last init (if there was one).