summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-06-25 23:35:00 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-06-25 23:35:00 +0700
commitdc6f751afb967cfea839c4f3e619c319a345b28d (patch)
treecc59e13dfaf30a3b6df1286e47a099a63e203eb4
parentFix portability issues around Socket class (diff)
downloadBouncyCastle.NET-ed25519-dc6f751afb967cfea839c4f3e619c319a345b28d.tar.xz
Check key sizes strictly
- see https://github.com/bcgit/bc-csharp/issues/303
- also refactor to use Pack and Integers
-rw-r--r--crypto/src/crypto/engines/TwofishEngine.cs110
1 files changed, 47 insertions, 63 deletions
diff --git a/crypto/src/crypto/engines/TwofishEngine.cs b/crypto/src/crypto/engines/TwofishEngine.cs
index 71c246594..0758451e4 100644
--- a/crypto/src/crypto/engines/TwofishEngine.cs
+++ b/crypto/src/crypto/engines/TwofishEngine.cs
@@ -1,6 +1,7 @@
 using System;
 
 using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
 using Org.BouncyCastle.Utilities;
 
 namespace Org.BouncyCastle.Crypto.Engines
@@ -272,7 +273,19 @@ namespace Org.BouncyCastle.Crypto.Engines
 
 			this.encrypting = forEncryption;
 			this.workingKey = ((KeyParameter)parameters).GetKey();
-			this.k64Cnt = (this.workingKey.Length / 8); // pre-padded ?
+
+            int keyBits = this.workingKey.Length * 8;
+            switch (keyBits)
+            {
+            case 128:
+            case 192:
+            case 256:
+                break;
+            default:
+                throw new ArgumentException("Key length not 128/192/256 bits.");
+            }
+
+            this.k64Cnt = this.workingKey.Length / 8;
 			SetKey(this.workingKey);
         }
 
@@ -335,28 +348,16 @@ namespace Org.BouncyCastle.Crypto.Engines
             int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4
             gSubKeys = new int[TOTAL_SUBKEYS];
 
-            if (k64Cnt < 1)
-            {
-                throw new ArgumentException("Key size less than 64 bits");
-            }
-
-            if (k64Cnt > 4)
-            {
-                throw new ArgumentException("Key size larger than 256 bits");
-            }
-
             /*
-            * k64Cnt is the number of 8 byte blocks (64 chunks)
-            * that are in the input key.  The input key is a
-            * maximum of 32 bytes ( 256 bits ), so the range
-            * for k64Cnt is 1..4
-            */
-            for (int i=0,p=0; i<k64Cnt ; i++)
+             * k64Cnt is the number of 8 byte blocks (64 chunks) that are in the input key.
+             * The input key is 16, 24 or 32 bytes, so the range for k64Cnt is 2..4
+             */
+            for (int i = 0; i < k64Cnt; i++)
             {
-                p = i* 8;
+                int p = i * 8;
 
-                k32e[i] = BytesTo32Bits(key, p);
-                k32o[i] = BytesTo32Bits(key, p+4);
+                k32e[i] = (int)Pack.LE_To_UInt32(key, p);
+                k32o[i] = (int)Pack.LE_To_UInt32(key, p + 4);
 
                 sBoxKeys[k64Cnt-1-i] = RS_MDS_Encode(k32e[i], k32o[i]);
             }
@@ -367,11 +368,11 @@ namespace Org.BouncyCastle.Crypto.Engines
                 q = i*SK_STEP;
                 A = F32(q,         k32e);
                 B = F32(q+SK_BUMP, k32o);
-                B = B << 8 | (int)((uint)B >> 24);
+                B = Integers.RotateLeft(B, 8);
                 A += B;
                 gSubKeys[i*2] = A;
                 A += B;
-                gSubKeys[i*2 + 1] = A << SK_ROTL | (int)((uint)A >> (32-SK_ROTL));
+                gSubKeys[i*2 + 1] = Integers.RotateLeft(A, SK_ROTL);
             }
 
             /*
@@ -437,10 +438,10 @@ namespace Org.BouncyCastle.Crypto.Engines
             byte[] dst,
             int dstIndex)
         {
-            int x0 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
-            int x1 = BytesTo32Bits(src, srcIndex + 4) ^ gSubKeys[INPUT_WHITEN + 1];
-            int x2 = BytesTo32Bits(src, srcIndex + 8) ^ gSubKeys[INPUT_WHITEN + 2];
-            int x3 = BytesTo32Bits(src, srcIndex + 12) ^ gSubKeys[INPUT_WHITEN + 3];
+            int x0 = (int)Pack.LE_To_UInt32(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
+            int x1 = (int)Pack.LE_To_UInt32(src, srcIndex + 4) ^ gSubKeys[INPUT_WHITEN + 1];
+            int x2 = (int)Pack.LE_To_UInt32(src, srcIndex + 8) ^ gSubKeys[INPUT_WHITEN + 2];
+            int x3 = (int)Pack.LE_To_UInt32(src, srcIndex + 12) ^ gSubKeys[INPUT_WHITEN + 3];
 
             int k = ROUND_SUBKEYS;
             int t0, t1;
@@ -449,20 +450,20 @@ namespace Org.BouncyCastle.Crypto.Engines
                 t0 = Fe32_0(x0);
                 t1 = Fe32_3(x1);
                 x2 ^= t0 + t1 + gSubKeys[k++];
-                x2 = (int)((uint)x2 >>1) | x2 << 31;
-                x3 = (x3 << 1 | (int) ((uint)x3 >> 31)) ^ (t0 + 2*t1 + gSubKeys[k++]);
+                x2 = Integers.RotateRight(x2, 1);
+                x3 = Integers.RotateLeft(x3, 1) ^ (t0 + 2*t1 + gSubKeys[k++]);
 
                 t0 = Fe32_0(x2);
                 t1 = Fe32_3(x3);
                 x0 ^= t0 + t1 + gSubKeys[k++];
-                x0 = (int) ((uint)x0 >>1) | x0 << 31;
-                x1 = (x1 << 1 | (int)((uint)x1 >> 31)) ^ (t0 + 2*t1 + gSubKeys[k++]);
+                x0 = Integers.RotateRight(x0, 1);
+                x1 = Integers.RotateLeft(x1, 1) ^ (t0 + 2*t1 + gSubKeys[k++]);
             }
 
-            Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
-            Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst, dstIndex + 4);
-            Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst, dstIndex + 8);
-            Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst, dstIndex + 12);
+            Pack.UInt32_To_LE((uint)(x2 ^ gSubKeys[OUTPUT_WHITEN]), dst, dstIndex);
+            Pack.UInt32_To_LE((uint)(x3 ^ gSubKeys[OUTPUT_WHITEN + 1]), dst, dstIndex + 4);
+            Pack.UInt32_To_LE((uint)(x0 ^ gSubKeys[OUTPUT_WHITEN + 2]), dst, dstIndex + 8);
+            Pack.UInt32_To_LE((uint)(x1 ^ gSubKeys[OUTPUT_WHITEN + 3]), dst, dstIndex + 12);
         }
 
         /**
@@ -476,10 +477,10 @@ namespace Org.BouncyCastle.Crypto.Engines
             byte[] dst,
             int dstIndex)
         {
-            int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
-            int x3 = BytesTo32Bits(src, srcIndex+4) ^ gSubKeys[OUTPUT_WHITEN + 1];
-            int x0 = BytesTo32Bits(src, srcIndex+8) ^ gSubKeys[OUTPUT_WHITEN + 2];
-            int x1 = BytesTo32Bits(src, srcIndex+12) ^ gSubKeys[OUTPUT_WHITEN + 3];
+            int x2 = (int)Pack.LE_To_UInt32(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
+            int x3 = (int)Pack.LE_To_UInt32(src, srcIndex + 4) ^ gSubKeys[OUTPUT_WHITEN + 1];
+            int x0 = (int)Pack.LE_To_UInt32(src, srcIndex + 8) ^ gSubKeys[OUTPUT_WHITEN + 2];
+            int x1 = (int)Pack.LE_To_UInt32(src, srcIndex + 12) ^ gSubKeys[OUTPUT_WHITEN + 3];
 
             int k = ROUND_SUBKEYS + 2 * ROUNDS -1 ;
             int t0, t1;
@@ -488,20 +489,20 @@ namespace Org.BouncyCastle.Crypto.Engines
                 t0 = Fe32_0(x2);
                 t1 = Fe32_3(x3);
                 x1 ^= t0 + 2*t1 + gSubKeys[k--];
-                x0 = (x0 << 1 | (int)((uint) x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
-                x1 = (int) ((uint)x1 >>1) | x1 << 31;
+                x0 = Integers.RotateLeft(x0, 1) ^ (t0 + t1 + gSubKeys[k--]);
+                x1 = Integers.RotateRight(x1, 1);
 
                 t0 = Fe32_0(x0);
                 t1 = Fe32_3(x1);
                 x3 ^= t0 + 2*t1 + gSubKeys[k--];
-                x2 = (x2 << 1 | (int)((uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
-                x3 = (int)((uint)x3 >>1) | x3 << 31;
+                x2 = Integers.RotateLeft(x2, 1) ^ (t0 + t1 + gSubKeys[k--]);
+                x3 = Integers.RotateRight(x3, 1);
             }
 
-            Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
-            Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst, dstIndex + 4);
-            Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst, dstIndex + 8);
-            Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst, dstIndex + 12);
+            Pack.UInt32_To_LE((uint)(x0 ^ gSubKeys[INPUT_WHITEN]), dst, dstIndex);
+            Pack.UInt32_To_LE((uint)(x1 ^ gSubKeys[INPUT_WHITEN + 1]), dst, dstIndex + 4);
+            Pack.UInt32_To_LE((uint)(x2 ^ gSubKeys[INPUT_WHITEN + 2]), dst, dstIndex + 8);
+            Pack.UInt32_To_LE((uint)(x3 ^ gSubKeys[INPUT_WHITEN + 3]), dst, dstIndex + 12);
         }
 
         /*
@@ -654,22 +655,5 @@ namespace Org.BouncyCastle.Crypto.Engines
                 gSBox[ 0x200 + 2*((int)((uint)x >> 8) & 0xff) ] ^
                 gSBox[ 0x201 + 2*((int)((uint)x >> 16) & 0xff) ];
         }
-
-        private  int BytesTo32Bits(byte[] b, int p)
-        {
-            return ((b[p] & 0xff) ) |
-                ((b[p+1] & 0xff) << 8) |
-                ((b[p+2] & 0xff) << 16) |
-                ((b[p+3] & 0xff) << 24);
-        }
-
-        private  void Bits32ToBytes(int inData,  byte[] b, int offset)
-        {
-            b[offset] = (byte)inData;
-            b[offset + 1] = (byte)(inData >> 8);
-            b[offset + 2] = (byte)(inData >> 16);
-            b[offset + 3] = (byte)(inData >> 24);
-        }
     }
-
 }