diff options
-rw-r--r-- | crypto/src/crypto/engines/NoekeonEngine.cs | 303 |
1 files changed, 158 insertions, 145 deletions
diff --git a/crypto/src/crypto/engines/NoekeonEngine.cs b/crypto/src/crypto/engines/NoekeonEngine.cs index f64be50ba..65f6e3878 100644 --- a/crypto/src/crypto/engines/NoekeonEngine.cs +++ b/crypto/src/crypto/engines/NoekeonEngine.cs @@ -12,25 +12,13 @@ namespace Org.BouncyCastle.Crypto.Engines public class NoekeonEngine : IBlockCipher { - private const int GenericSize = 16; // Block and key size, as well as the amount of rounds. + // Block and key size, as well as the amount of rounds. + private const int Size = 16; - private static readonly uint[] nullVector = - { - 0x00, 0x00, 0x00, 0x00 // Used in decryption - }; - - private static readonly uint[] roundConstants = - { - 0x80, 0x1b, 0x36, 0x6c, - 0xd8, 0xab, 0x4d, 0x9a, - 0x2f, 0x5e, 0xbc, 0x63, - 0xc6, 0x97, 0x35, 0x6a, - 0xd4 - }; + private static readonly byte[] RoundConstants = { 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, + 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4 }; - private uint[] state = new uint[4], // a - subKeys = new uint[4], // k - decryptKeys = new uint[4]; + private readonly uint[] k = new uint[4]; private bool _initialised, _forEncryption; @@ -55,7 +43,7 @@ namespace Org.BouncyCastle.Crypto.Engines public virtual int GetBlockSize() { - return GenericSize; + return Size; } /** @@ -66,20 +54,38 @@ namespace Org.BouncyCastle.Crypto.Engines * @exception ArgumentException if the params argument is * inappropriate. */ - public virtual void Init( - bool forEncryption, - ICipherParameters parameters) + public virtual void Init(bool forEncryption, ICipherParameters parameters) { if (!(parameters is KeyParameter)) throw new ArgumentException("Invalid parameters passed to Noekeon init - " + Platform.GetTypeName(parameters), "parameters"); - _forEncryption = forEncryption; - _initialised = true; + this._forEncryption = forEncryption; + this._initialised = true; KeyParameter p = (KeyParameter) parameters; - setKey(p.GetKey()); + Pack.BE_To_UInt32(p.GetKey(), 0, k, 0, 4); + + if (!forEncryption) + { + // theta(k, new uint[]{ 0x00, 0x00, 0x00, 0x00 }); + { + uint a0 = k[0], a1 = k[1], a2 = k[2], a3 = k[3]; + + uint t = a0 ^ a2; + t ^= Integers.RotateLeft(t, 8) ^ Integers.RotateLeft(t, 24); + a1 ^= t; + a3 ^= t; + + t = a1 ^ a3; + t ^= Integers.RotateLeft(t, 8) ^ Integers.RotateLeft(t, 24); + a0 ^= t; + a2 ^= t; + + k[0] = a0; k[1] = a1; k[2] = a2; k[3] = a3; + } + } } public virtual int ProcessBlock( @@ -91,151 +97,158 @@ namespace Org.BouncyCastle.Crypto.Engines if (!_initialised) throw new InvalidOperationException(AlgorithmName + " not initialised"); - Check.DataLength(input, inOff, GenericSize, "input buffer too short"); - Check.OutputLength(output, outOff, GenericSize, "output buffer too short"); + Check.DataLength(input, inOff, Size, "input buffer too short"); + Check.OutputLength(output, outOff, Size, "output buffer too short"); return _forEncryption - ? encryptBlock(input, inOff, output, outOff) - : decryptBlock(input, inOff, output, outOff); + ? EncryptBlock(input, inOff, output, outOff) + : DecryptBlock(input, inOff, output, outOff); } public virtual void Reset() { - // TODO This should do something in case the encryption is aborted } - /** - * Re-key the cipher. - * - * @param key the key to be used - */ - private void setKey(byte[] key) + private int EncryptBlock(byte[] input, int inOff, byte[] output, int outOff) { - subKeys[0] = Pack.BE_To_UInt32(key, 0); - subKeys[1] = Pack.BE_To_UInt32(key, 4); - subKeys[2] = Pack.BE_To_UInt32(key, 8); - subKeys[3] = Pack.BE_To_UInt32(key, 12); - } + uint a0 = Pack.BE_To_UInt32(input, inOff); + uint a1 = Pack.BE_To_UInt32(input, inOff + 4); + uint a2 = Pack.BE_To_UInt32(input, inOff + 8); + uint a3 = Pack.BE_To_UInt32(input, inOff + 12); - private int encryptBlock( - byte[] input, - int inOff, - byte[] output, - int outOff) - { - state[0] = Pack.BE_To_UInt32(input, inOff); - state[1] = Pack.BE_To_UInt32(input, inOff+4); - state[2] = Pack.BE_To_UInt32(input, inOff+8); - state[3] = Pack.BE_To_UInt32(input, inOff+12); + uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; - int i; - for (i = 0; i < GenericSize; i++) + int round = 0; + uint t; + for (;;) { - state[0] ^= roundConstants[i]; - theta(state, subKeys); - pi1(state); - gamma(state); - pi2(state); + a0 ^= RoundConstants[round]; + + // theta(a, k); + { + t = a0 ^ a2; + t ^= Integers.RotateLeft(t, 8) ^ Integers.RotateLeft(t, 24); + a1 ^= t; + a3 ^= t; + + a0 ^= k0; + a1 ^= k1; + a2 ^= k2; + a3 ^= k3; + + t = a1 ^ a3; + t ^= Integers.RotateLeft(t, 8) ^ Integers.RotateLeft(t, 24); + a0 ^= t; + a2 ^= t; + } + + if (++round > Size) + break; + + // pi1(a); + { + a1 = Integers.RotateLeft(a1, 1); + a2 = Integers.RotateLeft(a2, 5); + a3 = Integers.RotateLeft(a3, 2); + } + + // gamma(a); + { + a1 ^= ~a3 & ~a2; + a0 ^= a2 & a1; + + t = a3; a3 = a0; a0 = t; + a2 ^= a0 ^ a1 ^ a3; + + a1 ^= ~a3 & ~a2; + a0 ^= a2 & a1; + } + + // pi2(a); + { + a1 = Integers.RotateLeft(a1, 31); + a2 = Integers.RotateLeft(a2, 27); + a3 = Integers.RotateLeft(a3, 30); + } } - state[0] ^= roundConstants[i]; - theta(state, subKeys); - - Pack.UInt32_To_BE(state[0], output, outOff); - Pack.UInt32_To_BE(state[1], output, outOff+4); - Pack.UInt32_To_BE(state[2], output, outOff+8); - Pack.UInt32_To_BE(state[3], output, outOff+12); + Pack.UInt32_To_BE(a0, output, outOff); + Pack.UInt32_To_BE(a1, output, outOff + 4); + Pack.UInt32_To_BE(a2, output, outOff + 8); + Pack.UInt32_To_BE(a3, output, outOff + 12); - return GenericSize; + return Size; } - private int decryptBlock( - byte[] input, - int inOff, - byte[] output, - int outOff) + private int DecryptBlock(byte[] input, int inOff, byte[] output, int outOff) { - state[0] = Pack.BE_To_UInt32(input, inOff); - state[1] = Pack.BE_To_UInt32(input, inOff+4); - state[2] = Pack.BE_To_UInt32(input, inOff+8); - state[3] = Pack.BE_To_UInt32(input, inOff+12); + uint a0 = Pack.BE_To_UInt32(input, inOff); + uint a1 = Pack.BE_To_UInt32(input, inOff + 4); + uint a2 = Pack.BE_To_UInt32(input, inOff + 8); + uint a3 = Pack.BE_To_UInt32(input, inOff + 12); - Array.Copy(subKeys, 0, decryptKeys, 0, subKeys.Length); - theta(decryptKeys, nullVector); + uint k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3]; - int i; - for (i = GenericSize; i > 0; i--) + int round = Size; + uint t; + for (;;) { - theta(state, decryptKeys); - state[0] ^= roundConstants[i]; - pi1(state); - gamma(state); - pi2(state); + // theta(a, k); + { + t = a0 ^ a2; + t ^= Integers.RotateLeft(t, 8) ^ Integers.RotateLeft(t, 24); + a1 ^= t; + a3 ^= t; + + a0 ^= k0; + a1 ^= k1; + a2 ^= k2; + a3 ^= k3; + + t = a1 ^ a3; + t ^= Integers.RotateLeft(t, 8) ^ Integers.RotateLeft(t, 24); + a0 ^= t; + a2 ^= t; + } + + a0 ^= RoundConstants[round]; + + if (--round < 0) + break; + + // pi1(a); + { + a1 = Integers.RotateLeft(a1, 1); + a2 = Integers.RotateLeft(a2, 5); + a3 = Integers.RotateLeft(a3, 2); + } + + // gamma(a); + { + a1 ^= ~a3 & ~a2; + a0 ^= a2 & a1; + + t = a3; a3 = a0; a0 = t; + a2 ^= a0 ^ a1 ^ a3; + + a1 ^= ~a3 & ~a2; + a0 ^= a2 & a1; + } + + // pi2(a); + { + a1 = Integers.RotateLeft(a1, 31); + a2 = Integers.RotateLeft(a2, 27); + a3 = Integers.RotateLeft(a3, 30); + } } - theta(state, decryptKeys); - state[0] ^= roundConstants[i]; + Pack.UInt32_To_BE(a0, output, outOff); + Pack.UInt32_To_BE(a1, output, outOff + 4); + Pack.UInt32_To_BE(a2, output, outOff + 8); + Pack.UInt32_To_BE(a3, output, outOff + 12); - Pack.UInt32_To_BE(state[0], output, outOff); - Pack.UInt32_To_BE(state[1], output, outOff+4); - Pack.UInt32_To_BE(state[2], output, outOff+8); - Pack.UInt32_To_BE(state[3], output, outOff+12); - - return GenericSize; - } - - private void gamma(uint[] a) - { - a[1] ^= ~a[3] & ~a[2]; - a[0] ^= a[2] & a[1]; - - uint tmp = a[3]; - a[3] = a[0]; - a[0] = tmp; - a[2] ^= a[0]^a[1]^a[3]; - - a[1] ^= ~a[3] & ~a[2]; - a[0] ^= a[2] & a[1]; - } - - private void theta(uint[] a, uint[] k) - { - uint tmp; - tmp = a[0]^a[2]; - tmp ^= rotl(tmp,8)^rotl(tmp,24); - a[1] ^= tmp; - a[3] ^= tmp; - - for (int i = 0; i < 4; i++) - { - a[i] ^= k[i]; - } - - tmp = a[1]^a[3]; - tmp ^= rotl(tmp,8)^rotl(tmp,24); - a[0] ^= tmp; - a[2] ^= tmp; - } - - private void pi1(uint[] a) - { - a[1] = rotl(a[1], 1); - a[2] = rotl(a[2], 5); - a[3] = rotl(a[3], 2); - } - - private void pi2(uint[] a) - { - a[1] = rotl(a[1], 31); - a[2] = rotl(a[2], 27); - a[3] = rotl(a[3], 30); - } - - // Helpers - - private uint rotl(uint x, int y) - { - return (x << y) | (x >> (32-y)); + return Size; } } } |