summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crypto/src/crypto/engines/SEEDEngine.cs237
1 files changed, 110 insertions, 127 deletions
diff --git a/crypto/src/crypto/engines/SEEDEngine.cs b/crypto/src/crypto/engines/SEEDEngine.cs
index 07ffe06bb..c3d364f95 100644
--- a/crypto/src/crypto/engines/SEEDEngine.cs
+++ b/crypto/src/crypto/engines/SEEDEngine.cs
@@ -1,14 +1,17 @@
 using System;
+#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
+using System.Runtime.CompilerServices;
+#endif
 
 using Org.BouncyCastle.Crypto.Parameters;
 using Org.BouncyCastle.Crypto.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Engines
 {
-	/**
+    /**
 	* Implementation of the SEED algorithm as described in RFC 4009
 	*/
-	public class SeedEngine
+    public class SeedEngine
 		: IBlockCipher
 	{
 		private const int BlockSize = 16;
@@ -173,48 +176,51 @@ namespace Org.BouncyCastle.Crypto.Engines
         public virtual void Init(bool forEncryption, ICipherParameters parameters)
 		{
 			this.forEncryption = forEncryption;
-			wKey = CreateWorkingKey(((KeyParameter)parameters).GetKey());
+			wKey = CreateWorkingKey((KeyParameter)parameters);
 		}
 
-        public virtual string AlgorithmName
-		{
-			get { return "SEED"; }
-		}
+        public virtual string AlgorithmName => "SEED";
 
-        public virtual int GetBlockSize()
-		{
-			return BlockSize;
-		}
+        public virtual int GetBlockSize() => BlockSize;
 
         public virtual int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff)
 		{
-			if (wKey == null)
-				throw new InvalidOperationException("SEED engine not initialised");
-
             Check.DataLength(inBuf, inOff, BlockSize, "input buffer too short");
             Check.OutputLength(outBuf, outOff, BlockSize, "output buffer too short");
 
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+			return ProcessBlock(inBuf.AsSpan(inOff), outBuf.AsSpan(outOff));
+#else
+			if (wKey == null)
+                throw new InvalidOperationException("SEED engine not initialised");
+
             long l = (long)Pack.BE_To_UInt64(inBuf, inOff + 0);
 			long r = (long)Pack.BE_To_UInt64(inBuf, inOff + 8);
 
 			if (forEncryption)
 			{
-				for (int i = 0; i < 16; i++)
+				for (int i = 0; i < 32; i += 4)
 				{
-					long nl = r;
-
-					r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
-					l = nl;
-				}
-			}
+					int w0 = wKey[i + 0];
+                    int w1 = wKey[i + 1];
+                    int w2 = wKey[i + 2];
+                    int w3 = wKey[i + 3];
+
+                    l ^= F(w0, w1, r);
+                    r ^= F(w2, w3, l);
+                }
+            }
 			else
 			{
-				for (int i = 15; i >= 0; i--)
+				for (int i = 28; i >= 0; i -= 4)
 				{
-					long nl = r;
+                    int w0 = wKey[i + 0];
+                    int w1 = wKey[i + 1];
+                    int w2 = wKey[i + 2];
+                    int w3 = wKey[i + 3];
 
-					r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
-					l = nl;
+                    l ^= F(w2, w3, r);
+                    r ^= F(w0, w1, l);
 				}
 			}
 
@@ -222,6 +228,7 @@ namespace Org.BouncyCastle.Crypto.Engines
 			Pack.UInt64_To_BE((ulong)l, outBuf, outOff + 8);
 
 			return BlockSize;
+#endif
 		}
 
 #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
@@ -236,129 +243,105 @@ namespace Org.BouncyCastle.Crypto.Engines
 			long l = (long)Pack.BE_To_UInt64(input);
 			long r = (long)Pack.BE_To_UInt64(input[8..]);
 
-			if (forEncryption)
-			{
-				for (int i = 0; i < 16; i++)
-				{
-					long nl = r;
-
-					r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
-					l = nl;
-				}
-			}
-			else
-			{
-				for (int i = 15; i >= 0; i--)
-				{
-					long nl = r;
-
-					r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
-					l = nl;
-				}
-			}
-
-			Pack.UInt64_To_BE((ulong)r, output);
+            if (forEncryption)
+            {
+                for (int i = 0; i < 32; i += 4)
+                {
+                    int w0 = wKey[i + 0];
+                    int w1 = wKey[i + 1];
+                    int w2 = wKey[i + 2];
+                    int w3 = wKey[i + 3];
+
+                    l ^= F(w0, w1, r);
+                    r ^= F(w2, w3, l);
+                }
+            }
+            else
+            {
+                for (int i = 28; i >= 0; i -= 4)
+                {
+                    int w0 = wKey[i + 0];
+                    int w1 = wKey[i + 1];
+                    int w2 = wKey[i + 2];
+                    int w3 = wKey[i + 3];
+
+                    l ^= F(w2, w3, r);
+                    r ^= F(w0, w1, l);
+                }
+            }
+
+            Pack.UInt64_To_BE((ulong)r, output);
 			Pack.UInt64_To_BE((ulong)l, output[8..]);
 
 			return BlockSize;
 		}
 #endif
 
-		private int[] CreateWorkingKey(byte[] inKey)
+		private static int[] CreateWorkingKey(KeyParameter keyParameter)
 		{
-			if (inKey.Length != 16)
+			if (keyParameter.KeyLength != 16)
 				throw new ArgumentException("key size must be 128 bits");
 
-			int[] key = new int[32];
-			long lower = (long)Pack.BE_To_UInt64(inKey, 0);
-			long upper = (long)Pack.BE_To_UInt64(inKey, 8);
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            var inKey = keyParameter.Key;
+#else
+            byte[] inKey = keyParameter.GetKey();
+#endif
 
-			int key0 = extractW0(lower);
-			int key1 = extractW1(lower);
-			int key2 = extractW0(upper);
-			int key3 = extractW1(upper);
+            int[] key = new int[32];
 
-			for (int i = 0; i < 16; i++)
-			{
-				key[2 * i] = G(key0 + key2 - (int)KC[i]);
-				key[2 * i + 1] = G(key1 - key3 + (int)KC[i]);
+			uint key0 = Pack.BE_To_UInt32(inKey, 0);
+            uint key1 = Pack.BE_To_UInt32(inKey, 4);
+            uint key2 = Pack.BE_To_UInt32(inKey, 8);
+            uint key3 = Pack.BE_To_UInt32(inKey, 12);
 
-				if (i % 2 == 0)
-				{
-					lower = rotateRight8(lower);
-					key0 = extractW0(lower);
-					key1 = extractW1(lower);
-				}
-				else
-				{
-					upper = rotateLeft8(upper);
-					key2 = extractW0(upper);
-					key3 = extractW1(upper);
-				}
-			}
+            for (int i = 0; i < 16; i += 2)
+			{
+				uint KC_i, keyt;
 
-			return key;
-		}
+                KC_i = KC[i];
+                key[2 * i + 0] = G((int)(key0 + key2 - KC_i));
+				key[2 * i + 1] = G((int)(key1 - key3 + KC_i));
 
-		private int extractW1(
-			long lVal)
-		{
-			return (int)lVal;
-		}
+				keyt = key0 >> 8 | key1 << 24;
+                key1 = key1 >> 8 | key0 << 24;
+				key0 = keyt;
 
-		private int extractW0(
-			long lVal)
-		{
-			return (int)(lVal >> 32);
-		}
+                KC_i = KC[i + 1];
+                key[2 * i + 2] = G((int)(key0 + key2 - KC_i));
+                key[2 * i + 3] = G((int)(key1 - key3 + KC_i));
 
-		private long rotateLeft8(
-			long x)
-		{
-			return (x << 8) | ((long)((ulong) x >> 56));
-		}
+                keyt = key2 << 8 | key3 >> 24;
+                key3 = key3 << 8 | key2 >> 24;
+                key2 = keyt;
+            }
 
-		private long rotateRight8(
-			long x)
-		{
-			return ((long)((ulong) x >> 8)) | (x << 56);
+            return key;
 		}
 
-		private int G(
-			int x)
-		{
-			return (int)(SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff]);
-		}
+#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+        private static long F(int ki0, int ki1, long r)
+        {
+            int r0 = ki0 ^ (int)(r >> 32);
+            int r1 = ki1 ^ (int)r;
 
-		private long F(
-			int		ki0,
-			int		ki1,
-			long	r)
-		{
-			int r0 = (int)(r >> 32);
-			int r1 = (int)r;
-			int rd1 = phaseCalc2(r0, ki0, r1, ki1);
-			int rd0 = rd1 + phaseCalc1(r0, ki0, r1, ki1);
+			int t0 = G(r0 ^ r1);
+			int t1 = G(r0 + t0);
 
-			return ((long)rd0 << 32) | (rd1 & 0xffffffffL);
-		}
+            int rd1 = G(t1 + t0);
+            int rd0 = rd1 + t1;
 
-		private int phaseCalc1(
-			int	r0,
-			int	ki0,
-			int	r1,
-			int	ki1)
-		{
-			return G(G((r0 ^ ki0) ^ (r1 ^ ki1)) + (r0 ^ ki0));
-		}
+            return (long)rd0 << 32 | rd1 & 0xFFFFFFFFL;
+        }
 
-		private int phaseCalc2(
-			int	r0,
-			int	ki0,
-			int	r1,
-			int	ki1)
-		{
-			return G(phaseCalc1(r0, ki0, r1, ki1) + G((r0 ^ ki0) ^ (r1 ^ ki1)));
-		}
-	}
+#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
+        private static int G(int x)
+        {
+            return (int)(SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff]);
+        }
+    }
 }