diff options
Diffstat (limited to 'crypto/src/crypto/engines')
-rw-r--r-- | crypto/src/crypto/engines/ElephantEngine.cs | 71 | ||||
-rw-r--r-- | crypto/src/crypto/engines/ISAPEngine.cs | 14 | ||||
-rw-r--r-- | crypto/src/crypto/engines/PhotonBeetleEngine.cs | 44 | ||||
-rw-r--r-- | crypto/src/crypto/engines/SparkleEngine.cs | 188 | ||||
-rw-r--r-- | crypto/src/crypto/engines/XoodyakEngine.cs | 95 |
5 files changed, 186 insertions, 226 deletions
diff --git a/crypto/src/crypto/engines/ElephantEngine.cs b/crypto/src/crypto/engines/ElephantEngine.cs index 4e0e3216d..89d2ca6be 100644 --- a/crypto/src/crypto/engines/ElephantEngine.cs +++ b/crypto/src/crypto/engines/ElephantEngine.cs @@ -1,8 +1,10 @@ using System; +using System.Drawing; using System.IO; using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Engines @@ -13,6 +15,7 @@ namespace Org.BouncyCastle.Crypto.Engines * Specification: https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/elephant-spec-final.pdf */ public class ElephantEngine + // TODO IAeadCipher only : IAeadBlockCipher { public enum ElephantParameters @@ -22,7 +25,7 @@ namespace Org.BouncyCastle.Crypto.Engines elephant200 } - private bool forEncryption; + private bool forEncryption = true; // Safe output sizes before initialization private readonly string algorithmName; private ElephantParameters parameters; private int BLOCK_SIZE; @@ -226,28 +229,20 @@ namespace Org.BouncyCastle.Crypto.Engines { switch (parameters) { - case ElephantParameters.elephant160: - output[BLOCK_SIZE - 1] = (byte)((((input[0] & 0xFF) << 3) | ((input[0] & 0xFF) >> 5)) ^ - ((input[3] & 0xFF) << 7) ^ ((input[13] & 0xFF) >> 7)); - break; - case ElephantParameters.elephant176: - output[BLOCK_SIZE - 1] = (byte)(rotl(input[0]) ^ ((input[3] & 0xFF) << 7) ^ ((input[19] & 0xFF) >> 7)); - break; - case ElephantParameters.elephant200: - output[BLOCK_SIZE - 1] = (byte)(rotl(input[0]) ^ rotl(input[2]) ^ (input[13] << 1)); - break; + case ElephantParameters.elephant160: + output[BLOCK_SIZE - 1] = (byte)((((input[0] & 0xFF) << 3) | ((input[0] & 0xFF) >> 5)) ^ + ((input[3] & 0xFF) << 7) ^ ((input[13] & 0xFF) >> 7)); + break; + case ElephantParameters.elephant176: + output[BLOCK_SIZE - 1] = (byte)(rotl(input[0]) ^ ((input[3] & 0xFF) << 7) ^ ((input[19] & 0xFF) >> 7)); + break; + case ElephantParameters.elephant200: + output[BLOCK_SIZE - 1] = (byte)(rotl(input[0]) ^ rotl(input[2]) ^ (input[13] << 1)); + break; } Array.Copy(input, 1, output, 0, BLOCK_SIZE - 1); } - private void xor_block(byte[] state, byte[] block, int bOff, int size) - { - for (int i = 0; i < size; ++i) - { - state[i] ^= block[i + bOff]; - } - } - // Write the ith assocated data block to "output". // The nonce is prepended and padding is added as required. // adlen is the length of the associated data in bytes @@ -412,14 +407,13 @@ namespace Org.BouncyCastle.Crypto.Engines // Compute ciphertext block Array.Copy(npub, 0, buffer, 0, CRYPTO_NPUBBYTES); Arrays.Fill(buffer, CRYPTO_NPUBBYTES, BLOCK_SIZE, (byte)0); - xor_block(buffer, current_mask, 0, BLOCK_SIZE); - xor_block(buffer, next_mask, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, current_mask, buffer); + Bytes.XorTo(BLOCK_SIZE, next_mask, buffer); permutation(buffer); - xor_block(buffer, current_mask, 0, BLOCK_SIZE); - xor_block(buffer, next_mask, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, current_mask, buffer); + Bytes.XorTo(BLOCK_SIZE, next_mask, buffer); int r_size = (i == nblocks_m - 1) ? mlen - offset : BLOCK_SIZE; - xor_block(buffer, m, offset, r_size); - Array.Copy(buffer, 0, output, offset + outOff, r_size); + Bytes.Xor(r_size, m, offset, buffer, 0, output, outOff + offset); } if (i > 0 && i <= nblocks_c) { @@ -432,21 +426,21 @@ namespace Org.BouncyCastle.Crypto.Engines { get_c_block(buffer, m, 0, mlen, i - 1); } - xor_block(buffer, previous_mask, 0, BLOCK_SIZE); - xor_block(buffer, next_mask, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, previous_mask, buffer); + Bytes.XorTo(BLOCK_SIZE, next_mask, buffer); permutation(buffer); - xor_block(buffer, previous_mask, 0, BLOCK_SIZE); - xor_block(buffer, next_mask, 0, BLOCK_SIZE); - xor_block(tag_buffer, buffer, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, previous_mask, buffer); + Bytes.XorTo(BLOCK_SIZE, next_mask, buffer); + Bytes.XorTo(BLOCK_SIZE, buffer, tag_buffer); } // If there is any AD left, compute tag for AD block if (i + 1 < nblocks_ad) { get_ad_block(buffer, ad, adlen, npub, i + 1); - xor_block(buffer, next_mask, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, next_mask, buffer); permutation(buffer); - xor_block(buffer, next_mask, 0, BLOCK_SIZE); - xor_block(tag_buffer, buffer, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, next_mask, buffer); + Bytes.XorTo(BLOCK_SIZE, buffer, tag_buffer); } // Cyclically shift the mask buffers // Value of next_mask will be computed in the next iteration @@ -458,9 +452,9 @@ namespace Org.BouncyCastle.Crypto.Engines } outOff += mlen; tag = new byte[CRYPTO_ABYTES]; - xor_block(tag_buffer, expanded_key, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, expanded_key, tag_buffer); permutation(tag_buffer); - xor_block(tag_buffer, expanded_key, 0, BLOCK_SIZE); + Bytes.XorTo(BLOCK_SIZE, expanded_key, tag_buffer); if (forEncryption) { Array.Copy(tag_buffer, 0, tag, 0, CRYPTO_ABYTES); @@ -483,11 +477,13 @@ namespace Org.BouncyCastle.Crypto.Engines public int GetUpdateOutputSize(int len) { + // TODO return len; } public int GetOutputSize(int len) { + // TODO return len + CRYPTO_ABYTES; } @@ -514,13 +510,13 @@ namespace Org.BouncyCastle.Crypto.Engines public int ProcessByte(byte input, Span<byte> output) { - message.Write(new byte[]{ input }); + message.WriteByte(input); return 0; } public int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output) { - message.Write(input.ToArray()); + message.Write(input); return 0; } @@ -558,4 +554,3 @@ namespace Org.BouncyCastle.Crypto.Engines } } } - diff --git a/crypto/src/crypto/engines/ISAPEngine.cs b/crypto/src/crypto/engines/ISAPEngine.cs index 7ef629d1b..17c679439 100644 --- a/crypto/src/crypto/engines/ISAPEngine.cs +++ b/crypto/src/crypto/engines/ISAPEngine.cs @@ -35,7 +35,7 @@ namespace Org.BouncyCastle.Crypto.Engines private const int ISAP_STATE_SZ = 40; private string algorithmName; - private bool forEncryption; + private bool forEncryption = true; // Safe output sizes before initialization private bool initialised; private byte[] mac; private MemoryStream aadData = new MemoryStream(); @@ -112,7 +112,7 @@ namespace Org.BouncyCastle.Crypto.Engines protected ulong ISAP_IV1_64; protected ulong ISAP_IV2_64; protected ulong ISAP_IV3_64; - protected ulong x0, x1, x2, x3, x4, t0, t1, t2, t3, t4; + protected ulong x0, x1, x2, x3, x4; public override void init(byte[] k, byte[] npub, int ISAP_rH, int ISAP_rH_SZ) { @@ -248,11 +248,11 @@ namespace Org.BouncyCastle.Crypto.Engines #endif protected void ROUND(ulong C) { - t0 = x0 ^ x1 ^ x2 ^ x3 ^ C ^ (x1 & (x0 ^ x2 ^ x4 ^ C)); - t1 = x0 ^ x2 ^ x3 ^ x4 ^ C ^ ((x1 ^ x2 ^ C) & (x1 ^ x3)); - t2 = x1 ^ x2 ^ x4 ^ C ^ (x3 & x4); - t3 = x0 ^ x1 ^ x2 ^ C ^ ((~x0) & (x3 ^ x4)); - t4 = x1 ^ x3 ^ x4 ^ ((x0 ^ x4) & x1); + ulong t0 = x0 ^ x1 ^ x2 ^ x3 ^ C ^ (x1 & (x0 ^ x2 ^ x4 ^ C)); + ulong t1 = x0 ^ x2 ^ x3 ^ x4 ^ C ^ ((x1 ^ x2 ^ C) & (x1 ^ x3)); + ulong t2 = x1 ^ x2 ^ x4 ^ C ^ (x3 & x4); + ulong t3 = x0 ^ x1 ^ x2 ^ C ^ ((~x0) & (x3 ^ x4)); + ulong t4 = x1 ^ x3 ^ x4 ^ ((x0 ^ x4) & x1); x0 = t0 ^ Longs.RotateRight(t0, 19) ^ Longs.RotateRight(t0, 28); x1 = t1 ^ Longs.RotateRight(t1, 39) ^ Longs.RotateRight(t1, 61); x2 = ~(t2 ^ Longs.RotateRight(t2, 1) ^ Longs.RotateRight(t2, 6)); diff --git a/crypto/src/crypto/engines/PhotonBeetleEngine.cs b/crypto/src/crypto/engines/PhotonBeetleEngine.cs index e593bb6f5..5d96213a1 100644 --- a/crypto/src/crypto/engines/PhotonBeetleEngine.cs +++ b/crypto/src/crypto/engines/PhotonBeetleEngine.cs @@ -14,7 +14,8 @@ namespace Org.BouncyCastle.Crypto.Engines * Photon-Beetle with reference to C Reference Impl from: https://github.com/PHOTON-Beetle/Software * </p> */ - public class PhotonBeetleEngine + public sealed class PhotonBeetleEngine + // TODO IAeadCipher only : IAeadBlockCipher { public enum PhotonBeetleParameters @@ -24,7 +25,7 @@ namespace Org.BouncyCastle.Crypto.Engines } private bool input_empty; - private bool forEncryption; + private bool forEncryption = true; // Safe output sizes before initialization private bool initialised; private byte[] K; private byte[] N; @@ -94,6 +95,7 @@ namespace Org.BouncyCastle.Crypto.Engines public string AlgorithmName => "Photon-Beetle AEAD"; + // TODO public IBlockCipher UnderlyingCipher => throw new NotImplementedException(); public byte[] GetMac() @@ -103,37 +105,33 @@ namespace Org.BouncyCastle.Crypto.Engines public int GetOutputSize(int len) { + // TODO return len + TAG_INBYTES; } public int GetUpdateOutputSize(int len) { + // TODO return len; } public void Init(bool forEncryption, ICipherParameters parameters) { this.forEncryption = forEncryption; - if (!(parameters is ParametersWithIV param)) - { + + if (!(parameters is ParametersWithIV ivParams)) throw new ArgumentException("Photon-Beetle AEAD init parameters must include an IV"); - } - ParametersWithIV ivParams = param; + N = ivParams.GetIV(); if (N == null || N.Length != CRYPTO_NPUBBYTES) - { throw new ArgumentException("Photon-Beetle AEAD requires exactly 16 bytes of IV"); - } - if (!(ivParams.Parameters is KeyParameter)) - { + + if (!(ivParams.Parameters is KeyParameter key)) throw new ArgumentException("Photon-Beetle AEAD init parameters must include a key"); - } - KeyParameter key = (KeyParameter)ivParams.Parameters; + K = key.GetKey(); if (K.Length != CRYPTO_KEYBYTES) - { throw new ArgumentException("Photon-Beetle AEAD key must be 128 bits long"); - } state = new byte[STATE_INBYTES]; state_2d = new byte[D][]; @@ -148,7 +146,7 @@ namespace Org.BouncyCastle.Crypto.Engines public void ProcessAadByte(byte input) { - aadData.Write(new byte[] { input }, 0, 1); + aadData.WriteByte(input); } public void ProcessAadBytes(byte[] inBytes, int inOff, int len) @@ -300,19 +298,11 @@ namespace Org.BouncyCastle.Crypto.Engines } if (forEncryption) { - XOR(plaintext, inOff, DBlen_inbytes); + Bytes.XorTo(DBlen_inbytes, plaintext, inOff, state, 0); } else { - XOR(ciphertext, inOff, DBlen_inbytes); - } - } - - void XOR(byte[] in_right, int rOff, int iolen_inbytes) - { - for (int i = 0; i < iolen_inbytes; i++) - { - state[i] ^= in_right[rOff++]; + Bytes.XorTo(DBlen_inbytes, ciphertext, inOff, state, 0); } } @@ -344,11 +334,11 @@ namespace Org.BouncyCastle.Crypto.Engines for (i = 0; i < Dlen_inblocks - 1; i++) { PHOTON_Permutation(); - XOR(A, i * RATE_INBYTES, RATE_INBYTES); + Bytes.XorTo(RATE_INBYTES, A, i * RATE_INBYTES, state, 0); } PHOTON_Permutation(); LastDBlocklen = adlen - i * RATE_INBYTES; - XOR(A, i * RATE_INBYTES, LastDBlocklen); + Bytes.XorTo(LastDBlocklen, A, i * RATE_INBYTES, state, 0); if (LastDBlocklen < RATE_INBYTES) { state[LastDBlocklen] ^= 0x01; // ozs diff --git a/crypto/src/crypto/engines/SparkleEngine.cs b/crypto/src/crypto/engines/SparkleEngine.cs index 63e400d4c..7d8c28f8e 100644 --- a/crypto/src/crypto/engines/SparkleEngine.cs +++ b/crypto/src/crypto/engines/SparkleEngine.cs @@ -14,7 +14,8 @@ namespace Org.BouncyCastle.Crypto.Engines /// Specification: /// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/sparkle-spec-final.pdf . /// </remarks> - public class SparkleEngine + public sealed class SparkleEngine + // TODO IAeadCipher only : IAeadBlockCipher { public enum SparkleParameters @@ -24,8 +25,9 @@ namespace Org.BouncyCastle.Crypto.Engines SCHWAEMM192_192, SCHWAEMM256_256 } + private string algorithmName; - private bool forEncryption; + private bool forEncryption = true; // Safe output sizes before initialization private readonly uint[] state; private readonly uint[] k; private readonly uint[] npub; @@ -60,48 +62,48 @@ namespace Org.BouncyCastle.Crypto.Engines int SPARKLE_CAPACITY; switch (sparkleParameters) { - case SparkleParameters.SCHWAEMM128_128: - SCHWAEMM_KEY_LEN = 128; - SCHWAEMM_NONCE_LEN = 128; - SCHWAEMM_TAG_LEN = 128; - SPARKLE_STATE = 256; - SPARKLE_CAPACITY = 128; - SPARKLE_STEPS_SLIM = 7; - SPARKLE_STEPS_BIG = 10; - algorithmName = "SCHWAEMM128-128"; - break; - case SparkleParameters.SCHWAEMM256_128: - SCHWAEMM_KEY_LEN = 128; - SCHWAEMM_NONCE_LEN = 256; - SCHWAEMM_TAG_LEN = 128; - SPARKLE_STATE = 384; - SPARKLE_CAPACITY = 128; - SPARKLE_STEPS_SLIM = 7; - SPARKLE_STEPS_BIG = 11; - algorithmName = "SCHWAEMM256-128"; - break; - case SparkleParameters.SCHWAEMM192_192: - SCHWAEMM_KEY_LEN = 192; - SCHWAEMM_NONCE_LEN = 192; - SCHWAEMM_TAG_LEN = 192; - SPARKLE_STATE = 384; - SPARKLE_CAPACITY = 192; - SPARKLE_STEPS_SLIM = 7; - SPARKLE_STEPS_BIG = 11; - algorithmName = "SCHWAEMM192-192"; - break; - case SparkleParameters.SCHWAEMM256_256: - SCHWAEMM_KEY_LEN = 256; - SCHWAEMM_NONCE_LEN = 256; - SCHWAEMM_TAG_LEN = 256; - SPARKLE_STATE = 512; - SPARKLE_CAPACITY = 256; - SPARKLE_STEPS_SLIM = 8; - SPARKLE_STEPS_BIG = 12; - algorithmName = "SCHWAEMM256-256"; - break; - default: - throw new ArgumentException("Invalid definition of SCHWAEMM instance"); + case SparkleParameters.SCHWAEMM128_128: + SCHWAEMM_KEY_LEN = 128; + SCHWAEMM_NONCE_LEN = 128; + SCHWAEMM_TAG_LEN = 128; + SPARKLE_STATE = 256; + SPARKLE_CAPACITY = 128; + SPARKLE_STEPS_SLIM = 7; + SPARKLE_STEPS_BIG = 10; + algorithmName = "SCHWAEMM128-128"; + break; + case SparkleParameters.SCHWAEMM256_128: + SCHWAEMM_KEY_LEN = 128; + SCHWAEMM_NONCE_LEN = 256; + SCHWAEMM_TAG_LEN = 128; + SPARKLE_STATE = 384; + SPARKLE_CAPACITY = 128; + SPARKLE_STEPS_SLIM = 7; + SPARKLE_STEPS_BIG = 11; + algorithmName = "SCHWAEMM256-128"; + break; + case SparkleParameters.SCHWAEMM192_192: + SCHWAEMM_KEY_LEN = 192; + SCHWAEMM_NONCE_LEN = 192; + SCHWAEMM_TAG_LEN = 192; + SPARKLE_STATE = 384; + SPARKLE_CAPACITY = 192; + SPARKLE_STEPS_SLIM = 7; + SPARKLE_STEPS_BIG = 11; + algorithmName = "SCHWAEMM192-192"; + break; + case SparkleParameters.SCHWAEMM256_256: + SCHWAEMM_KEY_LEN = 256; + SCHWAEMM_NONCE_LEN = 256; + SCHWAEMM_TAG_LEN = 256; + SPARKLE_STATE = 512; + SPARKLE_CAPACITY = 256; + SPARKLE_STEPS_SLIM = 8; + SPARKLE_STEPS_BIG = 12; + algorithmName = "SCHWAEMM256-256"; + break; + default: + throw new ArgumentException("Invalid definition of SCHWAEMM instance"); } KEY_WORDS = SCHWAEMM_KEY_LEN >> 5; KEY_BYTES = SCHWAEMM_KEY_LEN >> 3; @@ -124,14 +126,9 @@ namespace Org.BouncyCastle.Crypto.Engines initialised = false; } - private uint ROT(uint x, int n) - { - return (((x) >> n) | ((x) << (32 - n))); - } - private uint ELL(uint x) { - return ROT(((x) ^ ((x) << 16)), 16); + return Integers.RotateRight(x ^ (x << 16), 16); } private static readonly uint[] RCON = {0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738, 0xBB1185EB, 0x4F7C7B57, @@ -149,17 +146,17 @@ namespace Org.BouncyCastle.Crypto.Engines for (j = 0; j < 2 * brans; j += 2) { rc = RCON[j >> 1]; - state[j] += ROT(state[j + 1], 31); - state[j + 1] ^= ROT(state[j], 24); + state[j] += Integers.RotateRight(state[j + 1], 31); + state[j + 1] ^= Integers.RotateRight(state[j], 24); state[j] ^= rc; - state[j] += ROT(state[j + 1], 17); - state[j + 1] ^= ROT(state[j], 17); + state[j] += Integers.RotateRight(state[j + 1], 17); + state[j + 1] ^= Integers.RotateRight(state[j], 17); state[j] ^= rc; state[j] += state[j + 1]; - state[j + 1] ^= ROT(state[j], 31); + state[j + 1] ^= Integers.RotateRight(state[j], 31); state[j] ^= rc; - state[j] += ROT(state[j + 1], 24); - state[j + 1] ^= ROT(state[j], 16); + state[j] += Integers.RotateRight(state[j + 1], 24); + state[j + 1] ^= Integers.RotateRight(state[j], 16); state[j] ^= rc; } // Linear layer @@ -308,31 +305,22 @@ namespace Org.BouncyCastle.Crypto.Engines public void Init(bool forEncryption, ICipherParameters param) { this.forEncryption = forEncryption; - if (!(param is ParametersWithIV)) - { + if (!(param is ParametersWithIV ivParams)) throw new ArgumentException(algorithmName + " init parameters must include an IV"); - } - ParametersWithIV ivParams = (ParametersWithIV)param; byte[] iv = ivParams.GetIV(); - if (iv == null || iv.Length != SCHWAEMM_NONCE_LEN >> 3) - { throw new ArgumentException(algorithmName + " requires exactly 16 bytes of IV"); - } + Pack.LE_To_UInt32(iv, 0, npub, 0, RATE_WORDS); - if (!(ivParams.Parameters is KeyParameter)) - { + if (!(ivParams.Parameters is KeyParameter key)) throw new ArgumentException(algorithmName + " init parameters must include a key"); - } - KeyParameter key = (KeyParameter)ivParams.Parameters; byte[] key8 = key.GetKey(); if (key8.Length != SCHWAEMM_KEY_LEN >> 3) - { throw new ArgumentException(algorithmName + " key must be 128 bits long"); - } + Pack.LE_To_UInt32(key8, 0, k, 0, KEY_WORDS); initialised = true; reset(false); @@ -345,9 +333,9 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException(algorithmName + ": AAD cannot be added after reading a full block(" + GetBlockSize() + " bytes) of input for " + (forEncryption ? "encryption" : "decryption")); } - aadData.Write(new byte[] { input }, 0, 1); - } + aadData.WriteByte(input); + } public void ProcessAadBytes(byte[] input, int inOff, int len) { @@ -356,61 +344,53 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException(algorithmName + ": AAD cannot be added after reading a full block(" + GetBlockSize() + " bytes) of input for " + (forEncryption ? "encryption" : "decryption")); } - if (inOff + len > input.Length) - { - throw new DataLengthException(algorithmName + " input buffer too short"); - } + + Check.DataLength(input, inOff, len, "input buffer too short"); + aadData.Write(input, inOff, len); } - public int ProcessByte(byte input, byte[] output, int outOff) { - return ProcessBytes(new byte[] { input }, 0, 1, output, outOff); + return ProcessBytes(new byte[]{ input }, 0, 1, output, outOff); } - public int ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff) { if (!initialised) - { throw new ArgumentException(algorithmName + " Need call init function before encryption/decryption"); - } - if (inOff + len > input.Length) - { - throw new DataLengthException(algorithmName + " input buffer too short"); - } + + Check.DataLength(input, inOff, len, "input buffer too short"); + message.Write(input, inOff, len); + + int msgLen = Convert.ToInt32(message.Length); + len = 0; - if ((forEncryption && (int)message.Length > GetBlockSize()) || - (!forEncryption && (int)message.Length - TAG_BYTES > GetBlockSize())) + if ((forEncryption && msgLen > GetBlockSize()) || + (!forEncryption && msgLen - TAG_BYTES > GetBlockSize())) { - len = ((int)message.Length - (forEncryption ? 0 : TAG_BYTES)); - if (len / RATE_BYTES * RATE_BYTES + outOff > output.Length) - { - throw new OutputLengthException(algorithmName + " output buffer is too short"); - } + len = msgLen - (forEncryption ? 0 : TAG_BYTES); + Check.OutputLength(output, outOff, len / RATE_BYTES * RATE_BYTES, "output buffer is too short"); byte[] m = message.GetBuffer(); ProcessAssocData(state); if (len != 0) { len = ProcessPlainText(state, output, m, 0, len); } - int mlen = (int)message.Length; message.SetLength(0); - message.Write(m, len, mlen - len); + // TODO Sketchy writing back to the buffer after setting length to 0 + message.Write(m, len, msgLen - len); } return len; } - public int DoFinal(byte[] output, int outOff) { if (!initialised) - { - throw new ArgumentException(algorithmName + " needs call init function before dofinal"); - } - int inlen = (int)message.Length - (forEncryption ? 0 : TAG_BYTES); + throw new ArgumentException(algorithmName + " needs to call Init before DoFinal"); + + int inlen = Convert.ToInt32(message.Length) - (forEncryption ? 0 : TAG_BYTES); if ((forEncryption && inlen + TAG_BYTES + outOff > output.Length) || (!forEncryption && inlen + outOff > output.Length)) { @@ -495,25 +475,23 @@ namespace Org.BouncyCastle.Crypto.Engines return tag; } - public int GetUpdateOutputSize(int len) { + // TODO return len; } - public int GetOutputSize(int len) { + // TODO return len + TAG_BYTES; } - public void Reset() { if (!initialised) - { - throw new ArgumentException(algorithmName + " needs call init function before reset"); - } + throw new ArgumentException(algorithmName + " needs to call Init before Reset"); + reset(true); } diff --git a/crypto/src/crypto/engines/XoodyakEngine.cs b/crypto/src/crypto/engines/XoodyakEngine.cs index e0263272e..2eb563525 100644 --- a/crypto/src/crypto/engines/XoodyakEngine.cs +++ b/crypto/src/crypto/engines/XoodyakEngine.cs @@ -13,11 +13,23 @@ namespace Org.BouncyCastle.Crypto.Engines * <p> * Xoodyak with reference to C Reference Impl from: https://github.com/XKCP/XKCP * </p> -*/ + */ public sealed class XoodyakEngine + // TODO IAeadCipher only : IAeadBlockCipher { - private bool forEncryption; + private enum MODE + { + ModeHash, + ModeKeyed + } + + private const int Rkin = 44; + + private static readonly uint[] RC = { 0x00000058U, 0x00000038U, 0x000003C0U, 0x000000D0U, 0x00000120U, + 0x00000014U, 0x00000060U, 0x0000002CU, 0x00000380U, 0x000000F0U, 0x000001A0U, 0x00000012U }; + + private bool forEncryption = true; // Safe output sizes before initialization private byte[] state; private int phase; private MODE mode; @@ -33,49 +45,36 @@ namespace Org.BouncyCastle.Crypto.Engines private const int NCOLUMS = 4; private const int MAXROUNDS = 12; private const int TAGLEN = 16; - const int Rkin = 44; private byte[] tag; - private readonly uint[] RC = {0x00000058, 0x00000038, 0x000003C0, 0x000000D0, 0x00000120, 0x00000014, 0x00000060, - 0x0000002C, 0x00000380, 0x000000F0, 0x000001A0, 0x00000012}; private bool aadFinished; private bool encrypted; private bool initialised = false; - public string AlgorithmName => "Xoodak AEAD"; - - public IBlockCipher UnderlyingCipher => throw new NotImplementedException(); private MemoryStream aadData = new MemoryStream(); private MemoryStream message = new MemoryStream(); - enum MODE - { - ModeHash, - ModeKeyed - } + public string AlgorithmName => "Xoodak AEAD"; + + public IBlockCipher UnderlyingCipher => throw new NotImplementedException(); - public void Init(bool forEncryption, ICipherParameters param) + public void Init(bool forEncryption, ICipherParameters parameters) { this.forEncryption = forEncryption; - if (!(param is ParametersWithIV)) - { + + if (!(parameters is ParametersWithIV ivParams)) throw new ArgumentException("Xoodyak init parameters must include an IV"); - } - ParametersWithIV ivParams = (ParametersWithIV)param; + iv = ivParams.GetIV(); if (iv == null || iv.Length != 16) - { throw new ArgumentException("Xoodyak requires exactly 16 bytes of IV"); - } - if (!(ivParams.Parameters is KeyParameter)) - { + + if (!(ivParams.Parameters is KeyParameter key)) throw new ArgumentException("Xoodyak init parameters must include a key"); - } - KeyParameter key = (KeyParameter)ivParams.Parameters; + K = key.GetKey(); if (K.Length != 16) - { throw new ArgumentException("Xoodyak key must be 128 bits long"); - } + state = new byte[48]; tag = new byte[TAGLEN]; initialised = true; @@ -89,9 +88,9 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException("AAD cannot be added after reading a full block(" + GetBlockSize() + " bytes) of input for " + (forEncryption ? "encryption" : "decryption")); } - aadData.Write(new byte[] { input }, 0, 1); - } + aadData.WriteByte(input); + } public void ProcessAadBytes(byte[] input, int inOff, int len) { @@ -100,17 +99,15 @@ namespace Org.BouncyCastle.Crypto.Engines throw new ArgumentException("AAD cannot be added after reading a full block(" + GetBlockSize() + " bytes) of input for " + (forEncryption ? "encryption" : "decryption")); } - if ((inOff + len) > input.Length) - { - throw new DataLengthException("input buffer too short"); - } + + Check.DataLength(input, inOff, len, "input buffer too short"); + aadData.Write(input, inOff, len); } - - public int ProcessByte(byte input, byte[] output, int outOff) + public int ProcessByte(byte input, byte[] outBytes, int outOff) { - return ProcessBytes(new byte[] { input }, 0, 1, output, outOff); + return ProcessBytes(new byte[]{ input }, 0, 1, outBytes, outOff); } private void processAAD() @@ -123,7 +120,7 @@ namespace Org.BouncyCastle.Crypto.Engines } } - public int ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff) + public int ProcessBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff) { if (!initialised) throw new ArgumentException("Need to call Init before encryption/decryption"); @@ -131,17 +128,17 @@ namespace Org.BouncyCastle.Crypto.Engines if (mode != MODE.ModeKeyed) throw new ArgumentException("Xoodyak has not been initialised"); - Check.DataLength(input, inOff, len, "input buffer too short"); + Check.DataLength(inBytes, inOff, len, "input buffer too short"); - message.Write(input, inOff, len); + message.Write(inBytes, inOff, len); int blockLen = (int)message.Length - (forEncryption ? 0 : TAGLEN); if (blockLen >= GetBlockSize()) { byte[] blocks = message.GetBuffer(); len = blockLen / GetBlockSize() * GetBlockSize(); - Check.OutputLength(output, outOff, len, "output buffer is too short"); + Check.OutputLength(outBytes, outOff, len, "output buffer is too short"); processAAD(); - encrypt(blocks, 0, len, output, outOff); + encrypt(blocks, 0, len, outBytes, outOff); int messageLen = (int)message.Length; message.SetLength(0); message.Write(blocks, len, messageLen - len); @@ -186,15 +183,15 @@ namespace Org.BouncyCastle.Crypto.Engines } - public int DoFinal(byte[] output, int outOff) + public int DoFinal(byte[] outBytes, int outOff) { if (!initialised) throw new ArgumentException("Need to call Init before encryption/decryption"); byte[] blocks = message.GetBuffer(); int len = (int)message.Length; - if ((forEncryption && len + TAGLEN + outOff > output.Length) || - (!forEncryption && len - TAGLEN + outOff > output.Length)) + if ((forEncryption && len + TAGLEN + outOff > outBytes.Length) || + (!forEncryption && len - TAGLEN + outOff > outBytes.Length)) { throw new OutputLengthException("output buffer too short"); } @@ -202,18 +199,18 @@ namespace Org.BouncyCastle.Crypto.Engines int rv = 0; if (forEncryption) { - encrypt(blocks, 0, len, output, outOff); + encrypt(blocks, 0, len, outBytes, outOff); outOff += len; tag = new byte[TAGLEN]; Up(tag, TAGLEN, 0x40); - Array.Copy(tag, 0, output, outOff, TAGLEN); + Array.Copy(tag, 0, outBytes, outOff, TAGLEN); rv = len + TAGLEN; } else { int inOff = len - TAGLEN; rv = inOff; - encrypt(blocks, 0, inOff, output, outOff); + encrypt(blocks, 0, inOff, outBytes, outOff); tag = new byte[TAGLEN]; Up(tag, TAGLEN, 0x40); @@ -231,11 +228,13 @@ namespace Org.BouncyCastle.Crypto.Engines public int GetUpdateOutputSize(int len) { + // TODO return len; } public int GetOutputSize(int len) { + // TODO return len + TAGLEN; } @@ -427,8 +426,6 @@ namespace Org.BouncyCastle.Crypto.Engines rv.AsSpan(0, len).CopyTo(output); return rv.Length; } - #endif - } -} \ No newline at end of file +} |