diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-06-25 23:35:00 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-06-25 23:35:00 +0700 |
commit | dc6f751afb967cfea839c4f3e619c319a345b28d (patch) | |
tree | cc59e13dfaf30a3b6df1286e47a099a63e203eb4 | |
parent | Fix portability issues around Socket class (diff) | |
download | BouncyCastle.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.cs | 110 |
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); - } } - } |