diff --git a/crypto/src/crypto/engines/ElephantEngine.cs b/crypto/src/crypto/engines/ElephantEngine.cs
deleted file mode 100644
index 89d2ca6be..000000000
--- a/crypto/src/crypto/engines/ElephantEngine.cs
+++ /dev/null
@@ -1,556 +0,0 @@
-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
-{
- /**
- * Elephant AEAD v2, based on the current round 3 submission, https://www.esat.kuleuven.be/cosic/elephant/
- * Reference C implementation: https://github.com/TimBeyne/Elephant
- * 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
- {
- elephant160,
- elephant176,
- elephant200
- }
-
- private bool forEncryption = true; // Safe output sizes before initialization
- private readonly string algorithmName;
- private ElephantParameters parameters;
- private int BLOCK_SIZE;
- private int nBits;
- private int nSBox;
- private int nRounds;
- private byte lfsrIV;
- private byte[] npub;
- private byte[] expanded_key;
- private byte[] tag;
- private byte CRYPTO_KEYBYTES = 16;
- private byte CRYPTO_NPUBBYTES = 12;
- private byte CRYPTO_ABYTES;
- private bool initialised;
- private MemoryStream aadData = new MemoryStream();
- private MemoryStream message = new MemoryStream();
-
- private readonly byte[] sBoxLayer = {
- (byte)0xee, (byte)0xed, (byte)0xeb, (byte)0xe0, (byte)0xe2, (byte)0xe1, (byte)0xe4, (byte)0xef, (byte)0xe7, (byte)0xea, (byte)0xe8, (byte)0xe5, (byte)0xe9, (byte)0xec, (byte)0xe3, (byte)0xe6,
- (byte)0xde, (byte)0xdd, (byte)0xdb, (byte)0xd0, (byte)0xd2, (byte)0xd1, (byte)0xd4, (byte)0xdf, (byte)0xd7, (byte)0xda, (byte)0xd8, (byte)0xd5, (byte)0xd9, (byte)0xdc, (byte)0xd3, (byte)0xd6,
- (byte)0xbe, (byte)0xbd, (byte)0xbb, (byte)0xb0, (byte)0xb2, (byte)0xb1, (byte)0xb4, (byte)0xbf, (byte)0xb7, (byte)0xba, (byte)0xb8, (byte)0xb5, (byte)0xb9, (byte)0xbc, (byte)0xb3, (byte)0xb6,
- (byte)0x0e, (byte)0x0d, (byte)0x0b, (byte)0x00, (byte)0x02, (byte)0x01, (byte)0x04, (byte)0x0f, (byte)0x07, (byte)0x0a, (byte)0x08, (byte)0x05, (byte)0x09, (byte)0x0c, (byte)0x03, (byte)0x06,
- (byte)0x2e, (byte)0x2d, (byte)0x2b, (byte)0x20, (byte)0x22, (byte)0x21, (byte)0x24, (byte)0x2f, (byte)0x27, (byte)0x2a, (byte)0x28, (byte)0x25, (byte)0x29, (byte)0x2c, (byte)0x23, (byte)0x26,
- (byte)0x1e, (byte)0x1d, (byte)0x1b, (byte)0x10, (byte)0x12, (byte)0x11, (byte)0x14, (byte)0x1f, (byte)0x17, (byte)0x1a, (byte)0x18, (byte)0x15, (byte)0x19, (byte)0x1c, (byte)0x13, (byte)0x16,
- (byte)0x4e, (byte)0x4d, (byte)0x4b, (byte)0x40, (byte)0x42, (byte)0x41, (byte)0x44, (byte)0x4f, (byte)0x47, (byte)0x4a, (byte)0x48, (byte)0x45, (byte)0x49, (byte)0x4c, (byte)0x43, (byte)0x46,
- (byte)0xfe, (byte)0xfd, (byte)0xfb, (byte)0xf0, (byte)0xf2, (byte)0xf1, (byte)0xf4, (byte)0xff, (byte)0xf7, (byte)0xfa, (byte)0xf8, (byte)0xf5, (byte)0xf9, (byte)0xfc, (byte)0xf3, (byte)0xf6,
- (byte)0x7e, (byte)0x7d, (byte)0x7b, (byte)0x70, (byte)0x72, (byte)0x71, (byte)0x74, (byte)0x7f, (byte)0x77, (byte)0x7a, (byte)0x78, (byte)0x75, (byte)0x79, (byte)0x7c, (byte)0x73, (byte)0x76,
- (byte)0xae, (byte)0xad, (byte)0xab, (byte)0xa0, (byte)0xa2, (byte)0xa1, (byte)0xa4, (byte)0xaf, (byte)0xa7, (byte)0xaa, (byte)0xa8, (byte)0xa5, (byte)0xa9, (byte)0xac, (byte)0xa3, (byte)0xa6,
- (byte)0x8e, (byte)0x8d, (byte)0x8b, (byte)0x80, (byte)0x82, (byte)0x81, (byte)0x84, (byte)0x8f, (byte)0x87, (byte)0x8a, (byte)0x88, (byte)0x85, (byte)0x89, (byte)0x8c, (byte)0x83, (byte)0x86,
- (byte)0x5e, (byte)0x5d, (byte)0x5b, (byte)0x50, (byte)0x52, (byte)0x51, (byte)0x54, (byte)0x5f, (byte)0x57, (byte)0x5a, (byte)0x58, (byte)0x55, (byte)0x59, (byte)0x5c, (byte)0x53, (byte)0x56,
- (byte)0x9e, (byte)0x9d, (byte)0x9b, (byte)0x90, (byte)0x92, (byte)0x91, (byte)0x94, (byte)0x9f, (byte)0x97, (byte)0x9a, (byte)0x98, (byte)0x95, (byte)0x99, (byte)0x9c, (byte)0x93, (byte)0x96,
- (byte)0xce, (byte)0xcd, (byte)0xcb, (byte)0xc0, (byte)0xc2, (byte)0xc1, (byte)0xc4, (byte)0xcf, (byte)0xc7, (byte)0xca, (byte)0xc8, (byte)0xc5, (byte)0xc9, (byte)0xcc, (byte)0xc3, (byte)0xc6,
- (byte)0x3e, (byte)0x3d, (byte)0x3b, (byte)0x30, (byte)0x32, (byte)0x31, (byte)0x34, (byte)0x3f, (byte)0x37, (byte)0x3a, (byte)0x38, (byte)0x35, (byte)0x39, (byte)0x3c, (byte)0x33, (byte)0x36,
- (byte)0x6e, (byte)0x6d, (byte)0x6b, (byte)0x60, (byte)0x62, (byte)0x61, (byte)0x64, (byte)0x6f, (byte)0x67, (byte)0x6a, (byte)0x68, (byte)0x65, (byte)0x69, (byte)0x6c, (byte)0x63, (byte)0x66
- };
-
- private readonly byte[] KeccakRoundConstants = {
- (byte)0x01, (byte)0x82, (byte)0x8a, (byte)0x00, (byte)0x8b, (byte)0x01, (byte)0x81, (byte)0x09, (byte)0x8a,
- (byte)0x88, (byte)0x09, (byte)0x0a, (byte)0x8b, (byte)0x8b, (byte)0x89, (byte)0x03, (byte)0x02, (byte)0x80
- };
-
- private readonly int[] KeccakRhoOffsets = { 0, 1, 6, 4, 3, 4, 4, 6, 7, 4, 3, 2, 3, 1, 7, 1, 5, 7, 5, 0, 2, 2, 5, 0, 6 };
-
- public ElephantEngine(ElephantParameters parameters)
- {
- switch (parameters)
- {
- case ElephantParameters.elephant160:
- BLOCK_SIZE = 20;
- nBits = 160;
- nSBox = 20;
- nRounds = 80;
- lfsrIV = 0x75;
- CRYPTO_ABYTES = 8;
- algorithmName = "Elephant 160 AEAD";
- break;
- case ElephantParameters.elephant176:
- BLOCK_SIZE = 22;
- nBits = 176;
- nSBox = 22;
- nRounds = 90;
- lfsrIV = 0x45;
- CRYPTO_ABYTES = 8;
- algorithmName = "Elephant 176 AEAD";
- break;
- case ElephantParameters.elephant200:
- BLOCK_SIZE = 25;
- nRounds = 18;
- CRYPTO_ABYTES = 16;
- algorithmName = "Elephant 200 AEAD";
- break;
- default:
- throw new ArgumentException("Invalid parameter settings for Elephant");
- }
- this.parameters = parameters;
- initialised = false;
- reset(false);
- }
-
- private void permutation(byte[] state)
- {
- switch (parameters)
- {
- case ElephantParameters.elephant160:
- case ElephantParameters.elephant176:
- byte IV = lfsrIV;
- byte[] tmp = new byte[nSBox];
- for (int i = 0; i < nRounds; i++)
- {
- /* Add counter values */
- state[0] ^= IV;
- state[nSBox - 1] ^= (byte)(((IV & 0x01) << 7) | ((IV & 0x02) << 5) | ((IV & 0x04) << 3) | ((IV & 0x08)
- << 1) | ((IV & 0x10) >> 1) | ((IV & 0x20) >> 3) | ((IV & 0x40) >> 5) | ((IV & 0x80) >> 7));
- IV = (byte)(((IV << 1) | (((0x40 & IV) >> 6) ^ ((0x20 & IV) >> 5))) & 0x7f);
- /* sBoxLayer layer */
- for (int j = 0; j < nSBox; j++)
- {
- state[j] = sBoxLayer[(state[j] & 0xFF)];
- }
- /* pLayer */
- int PermutedBitNo;
- Arrays.Fill(tmp, (byte)0);
- for (int j = 0; j < nSBox; j++)
- {
- for (int k = 0; k < 8; k++)
- {
- PermutedBitNo = (j << 3) + k;
- if (PermutedBitNo != nBits - 1)
- {
- PermutedBitNo = ((PermutedBitNo * nBits) >> 2) % (nBits - 1);
- }
- tmp[PermutedBitNo >> 3] ^= (byte)((((state[j] & 0xFF) >> k) & 0x1) << (PermutedBitNo & 7));
- }
- }
- Array.Copy(tmp, 0, state, 0, nSBox);
- }
- break;
- case ElephantParameters.elephant200:
- for (int i = 0; i < nRounds; i++)
- {
- KeccakP200Round(state, i);
- }
- break;
- }
- }
-
- private byte rotl(byte b)
- {
- return (byte)(((b & 0xFF) << 1) | ((b & 0xFF) >> 7));
- }
-
- private byte ROL8(byte a, int offset)
- {
- return (byte)((offset != 0) ? (((a & 0xFF) << offset) ^ ((a & 0xFF) >> (8 - offset))) : a);
- }
-
- private int index(int x, int y)
- {
- return x + y * 5;
- }
-
- private void KeccakP200Round(byte[] state, int indexRound)
- {
- int x, y;
- byte[] tempA = new byte[25];
- //theta
- for (x = 0; x < 5; x++)
- {
- for (y = 0; y < 5; y++)
- {
- tempA[x] ^= state[index(x, y)];
- }
- }
- for (x = 0; x < 5; x++)
- {
- tempA[x + 5] = (byte)(ROL8(tempA[(x + 1) % 5], 1) ^ tempA[(x + 4) % 5]);
- }
- for (x = 0; x < 5; x++)
- {
- for (y = 0; y < 5; y++)
- {
- state[index(x, y)] ^= tempA[x + 5];
- }
- }
- //rho
- for (x = 0; x < 5; x++)
- {
- for (y = 0; y < 5; y++)
- {
- tempA[index(x, y)] = ROL8(state[index(x, y)], KeccakRhoOffsets[index(x, y)]);
- }
- }
- //pi
- for (x = 0; x < 5; x++)
- {
- for (y = 0; y < 5; y++)
- {
- state[index(y, (2 * x + 3 * y) % 5)] = tempA[index(x, y)];
- }
- }
- //chi
- for (y = 0; y < 5; y++)
- {
- for (x = 0; x < 5; x++)
- {
- tempA[x] = (byte)(state[index(x, y)] ^ ((~state[index((x + 1) % 5, y)]) & state[index((x + 2) % 5, y)]));
- }
- for (x = 0; x < 5; x++)
- {
- state[index(x, y)] = tempA[x];
- }
- }
- //iota
- state[index(0, 0)] ^= KeccakRoundConstants[indexRound];
- }
-
-
- // State should be BLOCK_SIZE bytes long
- // Note: input may be equal to output
- private void lfsr_step(byte[] output, byte[] input)
- {
- 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;
- }
- Array.Copy(input, 1, output, 0, BLOCK_SIZE - 1);
- }
-
- // 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
- private void get_ad_block(byte[] output, byte[] ad, int adlen, byte[] npub, int i)
- {
- int len = 0;
- // First block contains nonce
- // Remark: nonce may not be longer then BLOCK_SIZE
- if (i == 0)
- {
- Array.Copy(npub, 0, output, 0, CRYPTO_NPUBBYTES);
- len += CRYPTO_NPUBBYTES;
- }
- int block_offset = i * BLOCK_SIZE - ((i != 0) ? 1 : 0) * CRYPTO_NPUBBYTES;
- // If adlen is divisible by BLOCK_SIZE, add an additional padding block
- if (i != 0 && block_offset == adlen)
- {
- Arrays.Fill(output, 0, BLOCK_SIZE, (byte)0);
- output[0] = 0x01;
- return;
- }
- int r_outlen = BLOCK_SIZE - len;
- int r_adlen = adlen - block_offset;
- // Fill with associated data if available
- if (r_outlen <= r_adlen)
- { // enough AD
- Array.Copy(ad, block_offset, output, len, r_outlen);
- }
- else
- { // not enough AD, need to pad
- if (r_adlen > 0) // ad might be nullptr
- {
- Array.Copy(ad, block_offset, output, len, r_adlen);
- }
- Arrays.Fill(output, len + r_adlen, len + r_outlen, (byte)0);
- output[len + r_adlen] = 0x01;
- }
- }
-
- // Return the ith ciphertext block.
- // clen is the length of the ciphertext in bytes
- private void get_c_block(byte[] output, byte[] c, int cOff, int clen, int i)
- {
- int block_offset = i * BLOCK_SIZE;
- // If clen is divisible by BLOCK_SIZE, add an additional padding block
- if (block_offset == clen)
- {
- Arrays.Fill(output, 0, BLOCK_SIZE, (byte)0);
- output[0] = 0x01;
- return;
- }
- int r_clen = clen - block_offset;
- // Fill with ciphertext if available
- if (BLOCK_SIZE <= r_clen)
- { // enough ciphertext
- Array.Copy(c, cOff + block_offset, output, 0, BLOCK_SIZE);
- }
- else
- { // not enough ciphertext, need to pad
- if (r_clen > 0) // c might be nullptr
- {
- Array.Copy(c, cOff + block_offset, output, 0, r_clen);
- }
- Arrays.Fill(output, r_clen, BLOCK_SIZE, (byte)0);
- output[r_clen] = 0x01;
- }
- }
-
- public void Init(bool forEncryption, ICipherParameters param)
- {
- this.forEncryption = forEncryption;
-
- if (!(param is ParametersWithIV ivParams))
- throw new ArgumentException("Elephant init parameters must include an IV");
-
- npub = ivParams.GetIV();
-
- if (npub == null || npub.Length != 12)
- throw new ArgumentException("Elephant requires exactly 12 bytes of IV");
-
- if (!(ivParams.Parameters is KeyParameter key))
- throw new ArgumentException("Elephant init parameters must include a key");
-
- byte[] k = key.GetKey();
- if (k.Length != 16)
- throw new ArgumentException("Elephant key must be 128 bits long");
-
- // Storage for the expanded key L
- expanded_key = new byte[BLOCK_SIZE];
- Array.Copy(k, 0, expanded_key, 0, CRYPTO_KEYBYTES);
- permutation(expanded_key);
- initialised = true;
- reset(false);
- }
-
-
- public string AlgorithmName => algorithmName;
-
- public IBlockCipher UnderlyingCipher => throw new NotImplementedException();
-
- public void ProcessAadByte(byte input)
- {
- aadData.WriteByte(input);
- }
-
- public void ProcessAadBytes(byte[] inBytes, int inOff, int len)
- {
- Check.DataLength(inBytes, inOff, len, "input buffer too short");
-
- aadData.Write(inBytes, inOff, len);
- }
-
- public int ProcessByte(byte input, byte[] outBytes, int outOff)
- {
- message.Write(new byte[]{ input }, 0, 1);
- return 0;
- }
-
- public int ProcessBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff)
- {
- Check.DataLength(inBytes, inOff, len, "input buffer too short");
-
- message.Write(inBytes, inOff, len);
- return 0;
- }
-
- public int DoFinal(byte[] output, int outOff)
- {
- if (!initialised)
- throw new ArgumentException("Need to call Init function before encryption/decryption");
-
- int mlen = (int)message.Length - (forEncryption ? 0 : CRYPTO_ABYTES);
- if ((forEncryption && mlen + outOff + CRYPTO_ABYTES > output.Length) ||
- (!forEncryption && mlen + outOff - CRYPTO_ABYTES > output.Length))
- {
- throw new OutputLengthException("output buffer is too short");
- }
- byte[] tag_buffer = new byte[BLOCK_SIZE];
- byte[] m = message.GetBuffer();
- byte[] ad = aadData.GetBuffer();
- int adlen = (int)aadData.Length;
- int nblocks_c = 1 + mlen / BLOCK_SIZE;
- int nblocks_m = (mlen % BLOCK_SIZE) != 0 ? nblocks_c : nblocks_c - 1;
- int nblocks_ad = 1 + (CRYPTO_NPUBBYTES + adlen) / BLOCK_SIZE;
- int nb_it = System.Math.Max(nblocks_c + 1, nblocks_ad - 1);
- // Buffers for storing previous, current and next mask
- byte[] previous_mask = new byte[BLOCK_SIZE];
- byte[] current_mask = new byte[BLOCK_SIZE];
- byte[] next_mask = new byte[BLOCK_SIZE];
- Array.Copy(expanded_key, 0, current_mask, 0, BLOCK_SIZE);
- // Buffer to store current ciphertext/AD block
- byte[] buffer = new byte[BLOCK_SIZE];
- // Tag buffer and initialization of tag to first AD block
- get_ad_block(tag_buffer, ad, adlen, npub, 0);
- int offset = 0;
- for (int i = 0; i < nb_it; ++i)
- {
- // Compute mask for the next message
- lfsr_step(next_mask, current_mask);
- if (i < nblocks_m)
- {
- // Compute ciphertext block
- Array.Copy(npub, 0, buffer, 0, CRYPTO_NPUBBYTES);
- Arrays.Fill(buffer, CRYPTO_NPUBBYTES, BLOCK_SIZE, (byte)0);
- Bytes.XorTo(BLOCK_SIZE, current_mask, buffer);
- Bytes.XorTo(BLOCK_SIZE, next_mask, buffer);
- permutation(buffer);
- 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;
- Bytes.Xor(r_size, m, offset, buffer, 0, output, outOff + offset);
- }
- if (i > 0 && i <= nblocks_c)
- {
- // Compute tag for ciphertext block
- if (forEncryption)
- {
- get_c_block(buffer, output, outOff, mlen, i - 1);
- }
- else
- {
- get_c_block(buffer, m, 0, mlen, i - 1);
- }
- Bytes.XorTo(BLOCK_SIZE, previous_mask, buffer);
- Bytes.XorTo(BLOCK_SIZE, next_mask, buffer);
- permutation(buffer);
- 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);
- Bytes.XorTo(BLOCK_SIZE, next_mask, buffer);
- permutation(buffer);
- 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
- byte[] temp = previous_mask;
- previous_mask = current_mask;
- current_mask = next_mask;
- next_mask = temp;
- offset += BLOCK_SIZE;
- }
- outOff += mlen;
- tag = new byte[CRYPTO_ABYTES];
- Bytes.XorTo(BLOCK_SIZE, expanded_key, tag_buffer);
- permutation(tag_buffer);
- Bytes.XorTo(BLOCK_SIZE, expanded_key, tag_buffer);
- if (forEncryption)
- {
- Array.Copy(tag_buffer, 0, tag, 0, CRYPTO_ABYTES);
- Array.Copy(tag, 0, output, outOff, tag.Length);
- mlen += CRYPTO_ABYTES;
- }
- else
- {
- if (!Arrays.FixedTimeEquals(CRYPTO_ABYTES, tag_buffer, 0, m, mlen))
- throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed");
- }
- reset(false);
- return mlen;
- }
-
- public byte[] GetMac()
- {
- return tag;
- }
-
- public int GetUpdateOutputSize(int len)
- {
- // TODO
- return len;
- }
-
- public int GetOutputSize(int len)
- {
- // TODO
- return len + CRYPTO_ABYTES;
- }
-
- public void Reset()
- {
- reset(true);
- }
-
- private void reset(bool clearMac)
- {
- if (clearMac)
- {
- tag = null;
- }
- aadData.SetLength(0);
- message.SetLength(0);
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public void ProcessAadBytes(ReadOnlySpan<byte> input)
- {
- aadData.Write(input);
- }
-
- public int ProcessByte(byte input, Span<byte> output)
- {
- message.WriteByte(input);
- return 0;
- }
-
- public int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
- {
- message.Write(input);
- return 0;
- }
-
- public int DoFinal(Span<byte> output)
- {
- byte[] rv;
- if (forEncryption)
- {
- rv = new byte[message.Length + CRYPTO_ABYTES];
- }
- else
- {
- rv = new byte[message.Length - CRYPTO_ABYTES];
- }
- int len = DoFinal(rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return rv.Length;
-
- }
-#endif
-
- public int GetKeyBytesSize()
- {
- return CRYPTO_KEYBYTES;
- }
-
- public int GetIVBytesSize()
- {
- return CRYPTO_NPUBBYTES;
- }
-
- public int GetBlockSize()
- {
- return BLOCK_SIZE;
- }
- }
-}
diff --git a/crypto/src/crypto/engines/ISAPEngine.cs b/crypto/src/crypto/engines/ISAPEngine.cs
deleted file mode 100644
index 17c679439..000000000
--- a/crypto/src/crypto/engines/ISAPEngine.cs
+++ /dev/null
@@ -1,1035 +0,0 @@
-using System;
-using System.Drawing;
-using System.IO;
-#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
-using System.Runtime.CompilerServices;
-#endif
-
-using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Crypto.Utilities;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Engines
-{
- /**
- * ISAP AEAD v2, https://isap.iaik.tugraz.at/
- * https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/constist-round/updated-spec-doc/isap-spec-const.pdf
- * <p>
- * ISAP AEAD v2 with reference to C Reference Impl from: https://github.com/isap-lwc/isap-code-package
- * </p>
- */
- public sealed class IsapEngine
- : IAeadCipher
- {
- public enum IsapType
- {
- ISAP_A_128A,
- ISAP_K_128A,
- ISAP_A_128,
- ISAP_K_128
- }
-
- private const int CRYPTO_KEYBYTES = 16;
- private const int CRYPTO_NPUBBYTES = 16;
- private const int ISAP_STATE_SZ = 40;
-
- private string algorithmName;
- private bool forEncryption = true; // Safe output sizes before initialization
- private bool initialised;
- private byte[] mac;
- private MemoryStream aadData = new MemoryStream();
- private MemoryStream message = new MemoryStream();
- private MemoryStream outputStream = new MemoryStream();
- private ISAP_AEAD ISAPAEAD;
- private int ISAP_rH;
- private int ISAP_rH_SZ;
-
- public IsapEngine(IsapType isapType)
- {
- switch (isapType)
- {
- case IsapType.ISAP_A_128A:
- ISAPAEAD = new ISAPAEAD_A_128A();
- ISAP_rH = 64;
- algorithmName = "ISAP-A-128A AEAD";
- break;
- case IsapType.ISAP_K_128A:
- ISAPAEAD = new ISAPAEAD_K_128A();
- ISAP_rH = 144;
- algorithmName = "ISAP-K-128A AEAD";
- break;
- case IsapType.ISAP_A_128:
- ISAPAEAD = new ISAPAEAD_A_128();
- ISAP_rH = 64;
- algorithmName = "ISAP-A-128 AEAD";
- break;
- case IsapType.ISAP_K_128:
- ISAPAEAD = new ISAPAEAD_K_128();
- ISAP_rH = 144;
- algorithmName = "ISAP-K-128 AEAD";
- break;
- }
- ISAP_rH_SZ = (ISAP_rH + 7) >> 3;
- }
-
- public int GetKeyBytesSize()
- {
- return CRYPTO_KEYBYTES;
- }
-
- public int GetIVBytesSize()
- {
- return CRYPTO_NPUBBYTES;
- }
-
- public string AlgorithmName => algorithmName;
-
- private abstract class ISAP_AEAD
- {
- protected byte[] k;
- protected byte[] npub;
- protected int ISAP_rH;
- protected int ISAP_rH_SZ;
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public abstract void isap_enc(ReadOnlySpan<byte> m, Span<byte> c);
-#else
- public abstract void isap_enc(byte[] m, int mOff, int mlen, byte[] c, int cOff);
-#endif
-
- public abstract void init(byte[] k, byte[] npub, int ISAP_rH, int ISAP_rH_SZ);
-
- public abstract void isap_mac(byte[] ad, int adlen, byte[] c, int clen, byte[] tag, int tagOff);
-
- public abstract void reset();
- }
-
- private abstract class ISAPAEAD_A : ISAP_AEAD
- {
- protected ulong[] k64;
- protected ulong[] npub64;
- protected ulong ISAP_IV1_64;
- protected ulong ISAP_IV2_64;
- protected ulong ISAP_IV3_64;
- protected ulong x0, x1, x2, x3, x4;
-
- public override void init(byte[] k, byte[] npub, int ISAP_rH, int ISAP_rH_SZ)
- {
- this.k = k;
- this.npub = npub;
- this.ISAP_rH = ISAP_rH;
- this.ISAP_rH_SZ = ISAP_rH_SZ;
- npub64 = new ulong[(npub.Length + 7) / 8];
- Pack.BE_To_UInt64(npub, 0, npub64, 0, npub64.Length);
- k64 = new ulong[(k.Length + 7) / 8];
- Pack.BE_To_UInt64(k, 0, k64, 0, k64.Length);
- reset();
- }
-
- protected abstract void PX1();
-
- protected abstract void PX2();
-
- protected void ABSORB_MAC(byte[] src, int len)
- {
- int off = 0;
- while (len >= 8)
- {
- x0 ^= Pack.BE_To_UInt64(src, off);
- off += 8;
- len -= 8;
- P12();
- }
- if (len > 0)
- {
- x0 ^= Pack.BE_To_UInt64_High(src, off, len);
- }
- x0 ^= 0x8000000000000000UL >> (len << 3);
- P12();
- }
-
- public override void isap_mac(byte[] ad, int adlen, byte[] c, int clen, byte[] tag, int tagOff)
- {
- // Init State
- x0 = npub64[0];
- x1 = npub64[1];
- x2 = ISAP_IV1_64;
- x3 = x4 = 0;
- P12();
- ABSORB_MAC(ad, adlen);
- // Domain seperation
- x4 ^= 1L;
- ABSORB_MAC(c, clen);
- // Derive K*
- Pack.UInt64_To_BE(x0, tag, 0);
- Pack.UInt64_To_BE(x1, tag, 8);
- ulong tmp_x2 = x2, tmp_x3 = x3, tmp_x4 = x4;
- isap_rk(ISAP_IV2_64, tag, CRYPTO_KEYBYTES);
- x2 = tmp_x2;
- x3 = tmp_x3;
- x4 = tmp_x4;
- // Squeeze tag
- P12();
- Pack.UInt64_To_BE(x0, tag, tagOff);
- Pack.UInt64_To_BE(x1, tag, tagOff + 8);
- }
-
- public void isap_rk(ulong iv64, byte[] y, int ylen)
- {
- // Init state
- x0 = k64[0];
- x1 = k64[1];
- x2 = iv64;
- x3 = x4 = 0;
- P12();
- // Absorb Y
- for (int i = 0; i < (ylen << 3) - 1; i++)
- {
- x0 ^= (((((ulong)y[i >> 3] >> (7 - (i & 7))) & 0x01UL) << 7) & 0xFFUL) << 56;
- PX2();
- }
- x0 ^= (((y[ylen - 1]) & 0x01UL) << 7) << 56;
- P12();
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public override void isap_enc(ReadOnlySpan<byte> m, Span<byte> c)
- {
- while (m.Length >= 8)
- {
- ulong t = Pack.BE_To_UInt64(m);
- t ^= x0;
- Pack.UInt64_To_BE(t, c);
- m = m[8..];
- c = c[8..];
- PX1();
- }
- if (!m.IsEmpty)
- {
- ulong t = Pack.BE_To_UInt64_High(m);
- t ^= x0;
- Pack.UInt64_To_BE_High(t, c[..m.Length]);
- }
- }
-#else
- public override void isap_enc(byte[] m, int mOff, int mlen, byte[] c, int cOff)
- {
- while (mlen >= 8)
- {
- ulong t = Pack.BE_To_UInt64(m, mOff);
- t ^= x0;
- Pack.UInt64_To_BE(t, c, cOff);
- mOff += 8;
- mlen -= 8;
- cOff += 8;
- PX1();
- }
- if (mlen > 0)
- {
- ulong t = Pack.BE_To_UInt64_High(m, mOff, mlen);
- t ^= x0;
- Pack.UInt64_To_BE_High(t, c, cOff, mlen);
- }
- }
-#endif
-
- public override void reset()
- {
- // Init state
- isap_rk(ISAP_IV3_64, npub, CRYPTO_NPUBBYTES);
- x3 = npub64[0];
- x4 = npub64[1];
- PX1();
- }
-
-#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
-#endif
- protected void ROUND(ulong C)
- {
- 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));
- x3 = t3 ^ Longs.RotateRight(t3, 10) ^ Longs.RotateRight(t3, 17);
- x4 = t4 ^ Longs.RotateRight(t4, 7) ^ Longs.RotateRight(t4, 41);
- }
-
- public void P12()
- {
- ROUND(0xf0);
- ROUND(0xe1);
- ROUND(0xd2);
- ROUND(0xc3);
- ROUND(0xb4);
- ROUND(0xa5);
- P6();
- }
-
- protected void P6()
- {
- ROUND(0x96);
- ROUND(0x87);
- ROUND(0x78);
- ROUND(0x69);
- ROUND(0x5a);
- ROUND(0x4b);
- }
- }
-
- private class ISAPAEAD_A_128A : ISAPAEAD_A
- {
- public ISAPAEAD_A_128A()
- {
- ISAP_IV1_64 = 108156764297430540UL;
- ISAP_IV2_64 = 180214358335358476UL;
- ISAP_IV3_64 = 252271952373286412UL;
- }
-
- protected override void PX1()
- {
- P6();
- }
-
- protected override void PX2()
- {
- ROUND(0x4b);
- }
- }
-
- private class ISAPAEAD_A_128 : ISAPAEAD_A
- {
- public ISAPAEAD_A_128()
- {
- ISAP_IV1_64 = 108156764298152972L;
- ISAP_IV2_64 = 180214358336080908L;
- ISAP_IV3_64 = 252271952374008844L;
- }
-
- protected override void PX1()
- {
- P12();
- }
-
- protected override void PX2()
- {
- P12();
- }
- }
-
- private abstract class ISAPAEAD_K : ISAP_AEAD
- {
- const int ISAP_STATE_SZ_CRYPTO_NPUBBYTES = ISAP_STATE_SZ - CRYPTO_NPUBBYTES;
- protected ushort[] ISAP_IV1_16;
- protected ushort[] ISAP_IV2_16;
- protected ushort[] ISAP_IV3_16;
- protected ushort[] k16;
- protected ushort[] iv16;
- private readonly int[] KeccakF400RoundConstants = {
- 0x0001, 0x8082, 0x808a, 0x8000, 0x808b, 0x0001, 0x8081, 0x8009, 0x008a, 0x0088, 0x8009, 0x000a, 0x808b,
- 0x008b, 0x8089, 0x8003, 0x8002, 0x0080, 0x800a, 0x000a };
- protected ushort[] SX = new ushort[25];
- protected ushort[] E = new ushort[25];
- protected ushort[] C = new ushort[5];
-
- public override void init(byte[] k, byte[] npub, int ISAP_rH, int ISAP_rH_SZ)
- {
- this.k = k;
- this.npub = npub;
- this.ISAP_rH = ISAP_rH;
- this.ISAP_rH_SZ = ISAP_rH_SZ;
- k16 = new ushort[k.Length >> 1];
- Pack.LE_To_UInt16(k, 0, k16);
- iv16 = new ushort[npub.Length >> 1];
- Pack.LE_To_UInt16(npub, 0, iv16);
- reset();
- }
-
- public override void reset()
- {
- // Init state
- SX = new ushort[25];
- E = new ushort[25];
- C = new ushort[5];
- isap_rk(ISAP_IV3_16, npub, CRYPTO_NPUBBYTES, SX, ISAP_STATE_SZ_CRYPTO_NPUBBYTES, C);
- Array.Copy(iv16, 0, SX, 17, 8);
- PermuteRoundsKX(SX, E, C);
- }
-
- protected abstract void PermuteRoundsHX(ushort[] SX, ushort[] E, ushort[] C);
-
- protected abstract void PermuteRoundsKX(ushort[] SX, ushort[] E, ushort[] C);
-
- protected abstract void PermuteRoundsBX(ushort[] SX, ushort[] E, ushort[] C);
-
- protected void ABSORB_MAC(ushort[] SX, byte[] src, int len, ushort[] E, ushort[] C)
- {
- int rem_bytes = len;
- int idx = 0;
- while (rem_bytes > ISAP_rH_SZ)
- {
- byteToushortXor(src, SX, ISAP_rH_SZ >> 1);
- idx += ISAP_rH_SZ;
- rem_bytes -= ISAP_rH_SZ;
- PermuteRoundsHX(SX, E, C);
- }
- if (rem_bytes == ISAP_rH_SZ)
- {
- byteToushortXor(src, SX, ISAP_rH_SZ >> 1);
- PermuteRoundsHX(SX, E, C);
- SX[0] ^= 0x80;
- PermuteRoundsHX(SX, E, C);
- }
- else
- {
- for (int i = 0; i < rem_bytes; i++)
- {
- SX[i >> 1] ^= (ushort)((src[idx++] & 0xFFU) << ((i & 1) << 3));
- }
- SX[rem_bytes >> 1] ^= (ushort)(0x80U << ((rem_bytes & 1) << 3));
- PermuteRoundsHX(SX, E, C);
- }
- }
-
- public void isap_rk(ushort[] iv16, byte[] y, int ylen, ushort[] out16, int outlen, ushort[] C)
- {
- // Init state
- ushort[] SX = new ushort[25];
- ushort[] E = new ushort[25];
- Array.Copy(k16, 0, SX, 0, 8);
- Array.Copy(iv16, 0, SX, 8, 4);
- PermuteRoundsKX(SX, E, C);
- // Absorb all bits of Y
- for (int i = 0; i < (ylen << 3) - 1; i++)
- {
- SX[0] ^= (ushort)(((y[i >> 3] >> (7 - (i & 7))) & 0x01) << 7);
- PermuteRoundsBX(SX, E, C);
- }
- SX[0] ^= (ushort)(((y[ylen - 1]) & 0x01) << 7);
- PermuteRoundsKX(SX, E, C);
- // Extract K*
- Array.Copy(SX, 0, out16, 0, outlen == ISAP_STATE_SZ_CRYPTO_NPUBBYTES ? 17 : 8);
- }
-
- public override void isap_mac(byte[] ad, int adlen, byte[] c, int clen, byte[] tag, int tagOff)
- {
- SX = new ushort[25];
- // Init state
- Array.Copy(iv16, 0, SX, 0, 8);
- Array.Copy(ISAP_IV1_16, 0, SX, 8, 4);
- PermuteRoundsHX(SX, E, C);
- // Absorb AD
- ABSORB_MAC(SX, ad, adlen, E, C);
- // Domain seperation
- SX[24] ^= 0x0100;
- // Absorb C
- ABSORB_MAC(SX, c, clen, E, C);
- // Derive K*
- Pack.UInt16_To_LE(SX, 0, 8, tag, tagOff);
- isap_rk(ISAP_IV2_16, tag, CRYPTO_KEYBYTES, SX, CRYPTO_KEYBYTES, C);
- // Squeeze tag
- PermuteRoundsHX(SX, E, C);
- Pack.UInt16_To_LE(SX, 0, 8, tag, tagOff);
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public override void isap_enc(ReadOnlySpan<byte> m, Span<byte> c)
- {
- int off = 0, len = m.Length;
-
- // Squeeze key stream
- while (len >= ISAP_rH_SZ)
- {
- // Squeeze full lane and continue
- for (int i = 0; i < ISAP_rH_SZ; ++i)
- {
- c[off] = (byte)((SX[i >> 1] >> ((i & 1) << 3)) ^ m[off]);
- ++off;
- }
- len -= ISAP_rH_SZ;
- PermuteRoundsKX(SX, E, C);
- }
- // Squeeze partial lane and stop
- for (int i = 0; i < len; ++i)
- {
- c[off] = (byte)((SX[i >> 1] >> ((i & 1) << 3)) ^ m[off]);
- ++off;
- }
- }
-#else
- public override void isap_enc(byte[] m, int mOff, int mlen, byte[] c, int cOff)
- {
- // Squeeze key stream
- while (mlen >= ISAP_rH_SZ)
- {
- // Squeeze full lane and continue
- for (int i = 0; i < ISAP_rH_SZ; ++i)
- {
- c[cOff++] = (byte)((SX[i >> 1] >> ((i & 1) << 3)) ^ m[mOff++]);
- }
- mlen -= ISAP_rH_SZ;
- PermuteRoundsKX(SX, E, C);
- }
- // Squeeze partial lane and stop
- for (int i = 0; i < mlen; ++i)
- {
- c[cOff++] = (byte)((SX[i >> 1] >> ((i & 1) << 3)) ^ m[mOff++]);
- }
- }
-#endif
-
- private void byteToushortXor(byte[] input, ushort[] output, int outLen)
- {
- for (int i = 0; i < outLen; ++i)
- {
- output[i] ^= Pack.LE_To_UInt16(input, (i << 1));
- }
- }
-
- protected void rounds12X(ushort[] SX, ushort[] E, ushort[] C)
- {
- prepareThetaX(SX, C);
- rounds_8_18(SX, E, C);
- }
-
- protected void rounds_4_18(ushort[] SX, ushort[] E, ushort[] C)
- {
- thetaRhoPiChiIotaPrepareTheta(4, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(5, E, SX, C);
- thetaRhoPiChiIotaPrepareTheta(6, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(7, E, SX, C);
- rounds_8_18(SX, E, C);
- }
-
- protected void rounds_8_18(ushort[] SX, ushort[] E, ushort[] C)
- {
- thetaRhoPiChiIotaPrepareTheta(8, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(9, E, SX, C);
- thetaRhoPiChiIotaPrepareTheta(10, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(11, E, SX, C);
- rounds_12_18(SX, E, C);
- }
-
- protected void rounds_12_18(ushort[] SX, ushort[] E, ushort[] C)
- {
- thetaRhoPiChiIotaPrepareTheta(12, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(13, E, SX, C);
- thetaRhoPiChiIotaPrepareTheta(14, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(15, E, SX, C);
- thetaRhoPiChiIotaPrepareTheta(16, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(17, E, SX, C);
- thetaRhoPiChiIotaPrepareTheta(18, SX, E, C);
- thetaRhoPiChiIota(E, SX, C);
- }
-
- protected void prepareThetaX(ushort[] SX, ushort[] C)
- {
- C[0] = (ushort)(SX[0] ^ SX[5] ^ SX[10] ^ SX[15] ^ SX[20]);
- C[1] = (ushort)(SX[1] ^ SX[6] ^ SX[11] ^ SX[16] ^ SX[21]);
- C[2] = (ushort)(SX[2] ^ SX[7] ^ SX[12] ^ SX[17] ^ SX[22]);
- C[3] = (ushort)(SX[3] ^ SX[8] ^ SX[13] ^ SX[18] ^ SX[23]);
- C[4] = (ushort)(SX[4] ^ SX[9] ^ SX[14] ^ SX[19] ^ SX[24]);
- }
-
- protected void thetaRhoPiChiIotaPrepareTheta(int i, ushort[] A, ushort[] E, ushort[] C)
- {
- ushort Da = (ushort)(C[4] ^ Shorts.RotateLeft(C[1], 1));
- ushort De = (ushort)(C[0] ^ Shorts.RotateLeft(C[2], 1));
- ushort Di = (ushort)(C[1] ^ Shorts.RotateLeft(C[3], 1));
- ushort Do = (ushort)(C[2] ^ Shorts.RotateLeft(C[4], 1));
- ushort Du = (ushort)(C[3] ^ Shorts.RotateLeft(C[0], 1));
-
- ushort Ba = A[0] ^= Da;
- A[6] ^= De;
- ushort Be = Shorts.RotateLeft(A[6], 12);
- A[12] ^= Di;
- ushort Bi = Shorts.RotateLeft(A[12], 11);
- A[18] ^= Do;
- ushort Bo = Shorts.RotateLeft(A[18], 5);
- A[24] ^= Du;
- ushort Bu = Shorts.RotateLeft(A[24], 14);
- C[0] = E[0] = (ushort)(Ba ^ ((~Be) & Bi) ^ KeccakF400RoundConstants[i]);
- C[1] = E[1] = (ushort)(Be ^ ((~Bi) & Bo));
- C[2] = E[2] = (ushort)(Bi ^ ((~Bo) & Bu));
- C[3] = E[3] = (ushort)(Bo ^ ((~Bu) & Ba));
- C[4] = E[4] = (ushort)(Bu ^ ((~Ba) & Be));
-
- A[3] ^= Do;
- Ba = Shorts.RotateLeft(A[3], 12);
- A[9] ^= Du;
- Be = Shorts.RotateLeft(A[9], 4);
- A[10] ^= Da;
- Bi = Shorts.RotateLeft(A[10], 3);
- A[16] ^= De;
- Bo = Shorts.RotateLeft(A[16], 13);
- A[22] ^= Di;
- Bu = Shorts.RotateLeft(A[22], 13);
- E[5] = (ushort)(Ba ^ ((~Be) & Bi));
- C[0] ^= E[5];
- E[6] = (ushort)(Be ^ ((~Bi) & Bo));
- C[1] ^= E[6];
- E[7] = (ushort)(Bi ^ ((~Bo) & Bu));
- C[2] ^= E[7];
- E[8] = (ushort)(Bo ^ ((~Bu) & Ba));
- C[3] ^= E[8];
- E[9] = (ushort)(Bu ^ ((~Ba) & Be));
- C[4] ^= E[9];
-
- A[1] ^= De;
- Ba = Shorts.RotateLeft(A[1], 1);
- A[7] ^= Di;
- Be = Shorts.RotateLeft(A[7], 6);
- A[13] ^= Do;
- Bi = Shorts.RotateLeft(A[13], 9);
- A[19] ^= Du;
- Bo = Shorts.RotateLeft(A[19], 8);
- A[20] ^= Da;
- Bu = Shorts.RotateLeft(A[20], 2);
- E[10] = (ushort)(Ba ^ ((~Be) & Bi));
- C[0] ^= E[10];
- E[11] = (ushort)(Be ^ ((~Bi) & Bo));
- C[1] ^= E[11];
- E[12] = (ushort)(Bi ^ ((~Bo) & Bu));
- C[2] ^= E[12];
- E[13] = (ushort)(Bo ^ ((~Bu) & Ba));
- C[3] ^= E[13];
- E[14] = (ushort)(Bu ^ ((~Ba) & Be));
- C[4] ^= E[14];
-
- A[4] ^= Du;
- Ba = Shorts.RotateLeft(A[4], 11);
- A[5] ^= Da;
- Be = Shorts.RotateLeft(A[5], 4);
- A[11] ^= De;
- Bi = Shorts.RotateLeft(A[11], 10);
- A[17] ^= Di;
- Bo = Shorts.RotateLeft(A[17], 15);
- A[23] ^= Do;
- Bu = Shorts.RotateLeft(A[23], 8);
- E[15] = (ushort)(Ba ^ ((~Be) & Bi));
- C[0] ^= E[15];
- E[16] = (ushort)(Be ^ ((~Bi) & Bo));
- C[1] ^= E[16];
- E[17] = (ushort)(Bi ^ ((~Bo) & Bu));
- C[2] ^= E[17];
- E[18] = (ushort)(Bo ^ ((~Bu) & Ba));
- C[3] ^= E[18];
- E[19] = (ushort)(Bu ^ ((~Ba) & Be));
- C[4] ^= E[19];
-
- A[2] ^= Di;
- Ba = Shorts.RotateLeft(A[2], 14);
- A[8] ^= Do;
- Be = Shorts.RotateLeft(A[8], 7);
- A[14] ^= Du;
- Bi = Shorts.RotateLeft(A[14], 7);
- A[15] ^= Da;
- Bo = Shorts.RotateLeft(A[15], 9);
- A[21] ^= De;
- Bu = Shorts.RotateLeft(A[21], 2);
- E[20] = (ushort)(Ba ^ ((~Be) & Bi));
- C[0] ^= E[20];
- E[21] = (ushort)(Be ^ ((~Bi) & Bo));
- C[1] ^= E[21];
- E[22] = (ushort)(Bi ^ ((~Bo) & Bu));
- C[2] ^= E[22];
- E[23] = (ushort)(Bo ^ ((~Bu) & Ba));
- C[3] ^= E[23];
- E[24] = (ushort)(Bu ^ ((~Ba) & Be));
- C[4] ^= E[24];
- }
-
- protected void thetaRhoPiChiIota(ushort[] A, ushort[] E, ushort[] C)
- {
- ushort Da = (ushort)(C[4] ^ Shorts.RotateLeft(C[1], 1));
- ushort De = (ushort)(C[0] ^ Shorts.RotateLeft(C[2], 1));
- ushort Di = (ushort)(C[1] ^ Shorts.RotateLeft(C[3], 1));
- ushort Do = (ushort)(C[2] ^ Shorts.RotateLeft(C[4], 1));
- ushort Du = (ushort)(C[3] ^ Shorts.RotateLeft(C[0], 1));
-
- ushort Ba = A[0] ^= Da;
- A[6] ^= De;
- ushort Be = Shorts.RotateLeft(A[6], 12);
- A[12] ^= Di;
- ushort Bi = Shorts.RotateLeft(A[12], 11);
- A[18] ^= Do;
- ushort Bo = Shorts.RotateLeft(A[18], 5);
- A[24] ^= Du;
- ushort Bu = Shorts.RotateLeft(A[24], 14);
- E[0] = (ushort)(Ba ^ ((~Be) & Bi) ^ KeccakF400RoundConstants[19]);
- E[1] = (ushort)(Be ^ ((~Bi) & Bo));
- E[2] = (ushort)(Bi ^ ((~Bo) & Bu));
- E[3] = (ushort)(Bo ^ ((~Bu) & Ba));
- E[4] = (ushort)(Bu ^ ((~Ba) & Be));
-
- A[3] ^= Do;
- Ba = Shorts.RotateLeft(A[3], 12);
- A[9] ^= Du;
- Be = Shorts.RotateLeft(A[9], 4);
- A[10] ^= Da;
- Bi = Shorts.RotateLeft(A[10], 3);
- A[16] ^= De;
- Bo = Shorts.RotateLeft(A[16], 13);
- A[22] ^= Di;
- Bu = Shorts.RotateLeft(A[22], 13);
- E[5] = (ushort)(Ba ^ ((~Be) & Bi));
- E[6] = (ushort)(Be ^ ((~Bi) & Bo));
- E[7] = (ushort)(Bi ^ ((~Bo) & Bu));
- E[8] = (ushort)(Bo ^ ((~Bu) & Ba));
- E[9] = (ushort)(Bu ^ ((~Ba) & Be));
-
- A[1] ^= De;
- Ba = Shorts.RotateLeft(A[1], 1);
- A[7] ^= Di;
- Be = Shorts.RotateLeft(A[7], 6);
- A[13] ^= Do;
- Bi = Shorts.RotateLeft(A[13], 9);
- A[19] ^= Du;
- Bo = Shorts.RotateLeft(A[19], 8);
- A[20] ^= Da;
- Bu = Shorts.RotateLeft(A[20], 2);
- E[10] = (ushort)(Ba ^ ((~Be) & Bi));
- E[11] = (ushort)(Be ^ ((~Bi) & Bo));
- E[12] = (ushort)(Bi ^ ((~Bo) & Bu));
- E[13] = (ushort)(Bo ^ ((~Bu) & Ba));
- E[14] = (ushort)(Bu ^ ((~Ba) & Be));
-
- A[4] ^= Du;
- Ba = Shorts.RotateLeft(A[4], 11);
- A[5] ^= Da;
- Be = Shorts.RotateLeft(A[5], 4);
- A[11] ^= De;
- Bi = Shorts.RotateLeft(A[11], 10);
- A[17] ^= Di;
- Bo = Shorts.RotateLeft(A[17], 15);
- A[23] ^= Do;
- Bu = Shorts.RotateLeft(A[23], 8);
- E[15] = (ushort)(Ba ^ ((~Be) & Bi));
- E[16] = (ushort)(Be ^ ((~Bi) & Bo));
- E[17] = (ushort)(Bi ^ ((~Bo) & Bu));
- E[18] = (ushort)(Bo ^ ((~Bu) & Ba));
- E[19] = (ushort)(Bu ^ ((~Ba) & Be));
-
- A[2] ^= Di;
- Ba = Shorts.RotateLeft(A[2], 14);
- A[8] ^= Do;
- Be = Shorts.RotateLeft(A[8], 7);
- A[14] ^= Du;
- Bi = Shorts.RotateLeft(A[14], 7);
- A[15] ^= Da;
- Bo = Shorts.RotateLeft(A[15], 9);
- A[21] ^= De;
- Bu = Shorts.RotateLeft(A[21], 2);
- E[20] = (ushort)(Ba ^ ((~Be) & Bi));
- E[21] = (ushort)(Be ^ ((~Bi) & Bo));
- E[22] = (ushort)(Bi ^ ((~Bo) & Bu));
- E[23] = (ushort)(Bo ^ ((~Bu) & Ba));
- E[24] = (ushort)(Bu ^ ((~Ba) & Be));
- }
- }
-
- private class ISAPAEAD_K_128A : ISAPAEAD_K
- {
- public ISAPAEAD_K_128A()
- {
- ISAP_IV1_16 = new ushort[]{ 32769, 400, 272, 2056 };
- ISAP_IV2_16 = new ushort[]{ 32770, 400, 272, 2056 };
- ISAP_IV3_16 = new ushort[]{ 32771, 400, 272, 2056 };
- }
-
- protected override void PermuteRoundsHX(ushort[] SX, ushort[] E, ushort[] C)
- {
- prepareThetaX(SX, C);
- rounds_4_18(SX, E, C);
- }
-
- protected override void PermuteRoundsKX(ushort[] SX, ushort[] E, ushort[] C)
- {
- prepareThetaX(SX, C);
- rounds_12_18(SX, E, C);
- }
-
- protected override void PermuteRoundsBX(ushort[] SX, ushort[] E, ushort[] C)
- {
- prepareThetaX(SX, C);
- thetaRhoPiChiIotaPrepareTheta(19, SX, E, C);
- Array.Copy(E, 0, SX, 0, E.Length);
- }
- }
-
- private class ISAPAEAD_K_128
- : ISAPAEAD_K
- {
- public ISAPAEAD_K_128()
- {
- ISAP_IV1_16 = new ushort[]{ 32769, 400, 3092, 3084 };
- ISAP_IV2_16 = new ushort[]{ 32770, 400, 3092, 3084 };
- ISAP_IV3_16 = new ushort[]{ 32771, 400, 3092, 3084 };
- }
-
- protected override void PermuteRoundsHX(ushort[] SX, ushort[] E, ushort[] C)
- {
- prepareThetaX(SX, C);
- thetaRhoPiChiIotaPrepareTheta(0, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(1, E, SX, C);
- thetaRhoPiChiIotaPrepareTheta(2, SX, E, C);
- thetaRhoPiChiIotaPrepareTheta(3, E, SX, C);
- rounds_4_18(SX, E, C);
- }
-
- protected override void PermuteRoundsKX(ushort[] SX, ushort[] E, ushort[] C)
- {
- rounds12X(SX, E, C);
- }
-
- protected override void PermuteRoundsBX(ushort[] SX, ushort[] E, ushort[] C)
- {
- rounds12X(SX, E, C);
- }
- }
-
- public void Init(bool forEncryption, ICipherParameters param)
- {
- this.forEncryption = forEncryption;
- if (!(param is ParametersWithIV withIV))
- throw new ArgumentException("ISAP AEAD init parameters must include an IV");
-
- byte[] iv = withIV.GetIV();
- if (iv == null || iv.Length != 16)
- throw new ArgumentException("ISAP AEAD requires exactly 12 bytes of IV");
-
- if (!(withIV.Parameters is KeyParameter key))
- throw new ArgumentException("ISAP AEAD init parameters must include a key");
-
- byte[] keyBytes = key.GetKey();
- if (keyBytes.Length != 16)
- throw new ArgumentException("ISAP AEAD key must be 128 bits ulong");
-
- /*
- * Initialize variables.
- */
- initialised = true;
- ISAPAEAD.init(keyBytes, iv, ISAP_rH, ISAP_rH_SZ);
- Reset();
- }
-
- public void ProcessAadByte(byte input)
- {
- aadData.WriteByte(input);
- }
-
- public void ProcessAadBytes(byte[] inBytes, int inOff, int len)
- {
- Check.DataLength(inBytes, inOff, len, "input buffer too short");
-
- aadData.Write(inBytes, inOff, len);
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public void ProcessAadBytes(ReadOnlySpan<byte> input)
- {
- aadData.Write(input);
- }
-#endif
-
- public int ProcessByte(byte input, byte[] outBytes, int outOff)
- {
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- return ProcessByte(input, Spans.FromNullable(outBytes, outOff));
-#else
- return ProcessBytes(new byte[]{ input }, 0, 1, outBytes, outOff);
-#endif
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public int ProcessByte(byte input, Span<byte> output)
- {
- Span<byte> singleByte = stackalloc byte[1]{ input };
-
- return ProcessBytes(singleByte, output);
- }
-#endif
-
- public int ProcessBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff)
- {
- Check.DataLength(inBytes, inOff, len, "input buffer too short");
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- return ProcessBytes(inBytes.AsSpan(inOff, len), Spans.FromNullable(outBytes, outOff));
-#else
- if (!initialised)
- throw new ArgumentException("Need to call Init function before encryption/decryption");
-
- message.Write(inBytes, inOff, len);
-
- if (forEncryption)
- {
- int msgLen = Convert.ToInt32(message.Length);
- if (msgLen >= ISAP_rH_SZ)
- {
- int outLen = msgLen / ISAP_rH_SZ * ISAP_rH_SZ;
- Check.OutputLength(outBytes, outOff, outLen, "output buffer is too short");
- byte[] enc_input = message.GetBuffer();
- ISAPAEAD.isap_enc(enc_input, 0, outLen, outBytes, outOff);
- outputStream.Write(outBytes, outOff, outLen);
- int enc_input_len = msgLen;
- message.SetLength(0);
- message.Write(enc_input, outLen, enc_input_len - outLen);
- return outLen;
- }
- }
- return 0;
-#endif
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
- {
- if (!initialised)
- throw new ArgumentException("Need to call Init function before encryption/decryption");
-
- message.Write(input);
-
- if (forEncryption)
- {
- int msgLen = Convert.ToInt32(message.Length);
- if (msgLen >= ISAP_rH_SZ)
- {
- int outLen = msgLen / ISAP_rH_SZ * ISAP_rH_SZ;
- Check.OutputLength(output, outLen, "output buffer is too short");
- byte[] enc_input = message.GetBuffer();
- ISAPAEAD.isap_enc(enc_input.AsSpan(0, outLen), output);
- outputStream.Write(output[..outLen]);
- int enc_input_len = msgLen;
- message.SetLength(0);
- message.Write(enc_input, outLen, enc_input_len - outLen);
- return outLen;
- }
- }
- return 0;
- }
-#endif
-
- public int DoFinal(byte[] outBytes, int outOff)
- {
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- return DoFinal(outBytes.AsSpan(outOff));
-#else
- if (!initialised)
- throw new ArgumentException("Need to call Init before encryption/decryption");
-
- byte[] aad = aadData.GetBuffer();
- byte[] msg = message.GetBuffer();
-
- int aadLen = Convert.ToInt32(aadData.Length);
- int msgLen = Convert.ToInt32(message.Length);
- int outLen;
- if (forEncryption)
- {
- outLen = msgLen + 16;
- Check.OutputLength(outBytes, outOff, outLen, "output buffer is too short");
- ISAPAEAD.isap_enc(msg, 0, msgLen, outBytes, outOff);
- outputStream.Write(outBytes, outOff, msgLen);
- outOff += msgLen;
- byte[] c = outputStream.GetBuffer();
- mac = new byte[16];
- ISAPAEAD.isap_mac(aad, aadLen, c, Convert.ToInt32(outputStream.Length), mac, 0);
- Array.Copy(mac, 0, outBytes, outOff, 16);
- }
- else
- {
- outLen = msgLen - 16;
- Check.OutputLength(outBytes, outOff, outLen, "output buffer is too short");
- mac = new byte[16];
- ISAPAEAD.isap_mac(aad, aadLen, msg, outLen, mac, 0);
- ISAPAEAD.reset();
- if (!Arrays.FixedTimeEquals(16, mac, 0, msg, outLen))
- throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed");
-
- ISAPAEAD.isap_enc(msg, 0, outLen, outBytes, outOff);
- }
- return outLen;
-#endif
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public int DoFinal(Span<byte> output)
- {
- if (!initialised)
- throw new ArgumentException("Need to call Init before encryption/decryption");
-
- byte[] aad = aadData.GetBuffer();
- byte[] msg = message.GetBuffer();
-
- int aadLen = Convert.ToInt32(aadData.Length);
- int msgLen = Convert.ToInt32(message.Length);
- int outLen;
- if (forEncryption)
- {
- outLen = msgLen + 16;
- Check.OutputLength(output, outLen, "output buffer is too short");
- ISAPAEAD.isap_enc(msg.AsSpan(0, msgLen), output);
- outputStream.Write(output[..msgLen]);
- output = output[msgLen..];
- byte[] c = outputStream.GetBuffer();
- mac = new byte[16];
- ISAPAEAD.isap_mac(aad, aadLen, c, Convert.ToInt32(outputStream.Length), mac, 0);
- mac.CopyTo(output);
- }
- else
- {
- outLen = msgLen - 16;
- Check.OutputLength(output, outLen, "output buffer is too short");
- mac = new byte[16];
- ISAPAEAD.isap_mac(aad, aadLen, msg, outLen, mac, 0);
- ISAPAEAD.reset();
- if (!Arrays.FixedTimeEquals(16, mac, 0, msg, outLen))
- throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed");
-
- ISAPAEAD.isap_enc(msg.AsSpan(0, outLen), output);
- }
- return outLen;
- }
-#endif
-
- public byte[] GetMac()
- {
- return mac;
- }
-
- public int GetUpdateOutputSize(int len)
- {
- if (!forEncryption)
- return 0;
-
- int totalData = Convert.ToInt32(message.Length + len);
- return totalData - totalData % ISAP_rH_SZ;
- }
-
- public int GetOutputSize(int len)
- {
- int totalData = Convert.ToInt32(message.Length + len);
-
- if (forEncryption)
- return totalData + 16;
-
- return System.Math.Max(0, totalData - 16);
- }
-
- public void Reset()
- {
- if (!initialised)
- throw new ArgumentException("Need to call Init before encryption/decryption");
-
- aadData.SetLength(0);
- ISAPAEAD.reset();
- message.SetLength(0);
- outputStream.SetLength(0);
- }
- }
-}
diff --git a/crypto/src/crypto/engines/PhotonBeetleEngine.cs b/crypto/src/crypto/engines/PhotonBeetleEngine.cs
deleted file mode 100644
index 5d96213a1..000000000
--- a/crypto/src/crypto/engines/PhotonBeetleEngine.cs
+++ /dev/null
@@ -1,441 +0,0 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Engines
-{
- /**
- * Photon-Beetle, https://www.isical.ac.in/~lightweight/beetle/
- * https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/readonlyist-round/updated-spec-doc/photon-beetle-spec-readonly.pdf
- * <p>
- * Photon-Beetle with reference to C Reference Impl from: https://github.com/PHOTON-Beetle/Software
- * </p>
- */
- public sealed class PhotonBeetleEngine
- // TODO IAeadCipher only
- : IAeadBlockCipher
- {
- public enum PhotonBeetleParameters
- {
- pb32,
- pb128
- }
-
- private bool input_empty;
- private bool forEncryption = true; // Safe output sizes before initialization
- private bool initialised;
- private byte[] K;
- private byte[] N;
- private byte[] state;
- private byte[][] state_2d;
- private byte[] A;
- private byte[] T;
- private MemoryStream aadData = new MemoryStream();
- private MemoryStream message = new MemoryStream();
- private readonly int CRYPTO_KEYBYTES = 16;
- private readonly int CRYPTO_NPUBBYTES = 16;
- private readonly int RATE_INBYTES;
- private readonly int RATE_INBYTES_HALF;
- private int STATE_INBYTES;
- private int TAG_INBYTES = 16;
- private int LAST_THREE_BITS_OFFSET;
- private int ROUND = 12;
- private int D = 8;
- private int Dq = 3;
- private int Dr = 7;
- private int DSquare = 64;
- private int S = 4;
- private int S_1 = 3;
- private byte[][] RC = {
- new byte[]{1, 3, 7, 14, 13, 11, 6, 12, 9, 2, 5, 10},
- new byte[]{0, 2, 6, 15, 12, 10, 7, 13, 8, 3, 4, 11},
- new byte[]{2, 0, 4, 13, 14, 8, 5, 15, 10, 1, 6, 9},
- new byte[]{6, 4, 0, 9, 10, 12, 1, 11, 14, 5, 2, 13},
- new byte[]{14, 12, 8, 1, 2, 4, 9, 3, 6, 13, 10, 5},
- new byte[]{15, 13, 9, 0, 3, 5, 8, 2, 7, 12, 11, 4},
- new byte[]{13, 15, 11, 2, 1, 7, 10, 0, 5, 14, 9, 6},
- new byte[]{9, 11, 15, 6, 5, 3, 14, 4, 1, 10, 13, 2}
- };
- private byte[][] MixColMatrix = {
- new byte[]{2, 4, 2, 11, 2, 8, 5, 6},
- new byte[]{12, 9, 8, 13, 7, 7, 5, 2},
- new byte[]{4, 4, 13, 13, 9, 4, 13, 9},
- new byte[]{1, 6, 5, 1, 12, 13, 15, 14},
- new byte[]{15, 12, 9, 13, 14, 5, 14, 13},
- new byte[]{9, 14, 5, 15, 4, 12, 9, 6},
- new byte[]{12, 2, 2, 10, 3, 1, 1, 14},
- new byte[]{15, 1, 13, 10, 5, 10, 2, 3}
- };
-
- private byte[] sbox = { 12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2 };
- public PhotonBeetleEngine(PhotonBeetleParameters pbp)
- {
- int CAPACITY_INBITS = 0, RATE_INBITS = 0;
- switch (pbp)
- {
- case PhotonBeetleParameters.pb32:
- RATE_INBITS = 32;
- CAPACITY_INBITS = 224;
- break;
- case PhotonBeetleParameters.pb128:
- RATE_INBITS = 128;
- CAPACITY_INBITS = 128;
- break;
- }
- RATE_INBYTES = (RATE_INBITS + 7) >> 3;
- RATE_INBYTES_HALF = RATE_INBYTES >> 1;
- int STATE_INBITS = RATE_INBITS + CAPACITY_INBITS;
- STATE_INBYTES = (STATE_INBITS + 7) >> 3;
- LAST_THREE_BITS_OFFSET = (STATE_INBITS - ((STATE_INBYTES - 1) << 3) - 3);
- initialised = false;
- }
-
- public string AlgorithmName => "Photon-Beetle AEAD";
-
- // TODO
- public IBlockCipher UnderlyingCipher => throw new NotImplementedException();
-
- public byte[] GetMac()
- {
- return T;
- }
-
- 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 ivParams))
- throw new ArgumentException("Photon-Beetle AEAD init parameters must include an IV");
-
- 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 key))
- throw new ArgumentException("Photon-Beetle AEAD init parameters must include a key");
-
- 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][];
- for (int i = 0; i < D; ++i)
- {
- state_2d[i] = new byte[D];
- }
- T = new byte[TAG_INBYTES];
- initialised = true;
- reset(false);
- }
-
- public void ProcessAadByte(byte input)
- {
- aadData.WriteByte(input);
- }
-
- public void ProcessAadBytes(byte[] inBytes, int inOff, int len)
- {
- Check.DataLength(inBytes, inOff, len, "input buffer too short");
-
- aadData.Write(inBytes, inOff, len);
- }
-
- public int ProcessByte(byte input, byte[] outBytes, int outOff)
- {
- message.WriteByte(input);
- return 0;
- }
-
- public int ProcessBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff)
- {
- Check.DataLength(inBytes, inOff, len, "input buffer too short");
-
- message.Write(inBytes, inOff, len);
- return 0;
- }
-
- public void Reset()
- {
- if (!initialised)
- throw new ArgumentException("Need to call Init before encryption/decryption");
-
- reset(true);
- }
-
- private void reset(bool clearMac)
- {
- if (clearMac)
- {
- T = null;
- }
- input_empty = true;
- aadData.SetLength(0);
- message.SetLength(0);
- Array.Copy(K, 0, state, 0, K.Length);
- Array.Copy(N, 0, state, K.Length, N.Length);
- }
-
- void PHOTON_Permutation()
- {
- int i, j, k, l;
- for (i = 0; i < DSquare; i++)
- {
- state_2d[i >> Dq][i & Dr] = (byte)(((state[i >> 1] & 0xFF) >> (4 * (i & 1))) & 0xf);
- }
- for (int round = 0; round < ROUND; round++)
- {
- //AddKey
- for (i = 0; i < D; i++)
- {
- state_2d[i][0] ^= RC[i][round];
- }
- //SubCell
- for (i = 0; i < D; i++)
- {
- for (j = 0; j < D; j++)
- {
- state_2d[i][j] = sbox[state_2d[i][j]];
- }
- }
- //ShiftRow
- for (i = 1; i < D; i++)
- {
- Array.Copy(state_2d[i], 0, state, 0, D);
- Array.Copy(state, i, state_2d[i], 0, D - i);
- Array.Copy(state, 0, state_2d[i], D - i, i);
- }
- //MixColumn
- for (j = 0; j < D; j++)
- {
- for (i = 0; i < D; i++)
- {
- byte sum = 0;
- for (k = 0; k < D; k++)
- {
- int x = MixColMatrix[i][k], ret = 0, b = state_2d[k][j];
- for (l = 0; l < S; l++)
- {
- if (((b >> l) & 1) != 0)
- {
- ret ^= x;
- }
- if (((x >> S_1) & 1) != 0)
- {
- x <<= 1;
- x ^= 0x3;
- }
- else
- {
- x <<= 1;
- }
- }
- sum ^= (byte)(ret & 15);
- }
- state[i] = sum;
- }
- for (i = 0; i < D; i++)
- {
- state_2d[i][j] = state[i];
- }
- }
- }
- for (i = 0; i < DSquare; i += 2)
- {
- state[i >> 1] = (byte)(((state_2d[i >> Dq][i & Dr] & 0xf)) | ((state_2d[i >> Dq][(i + 1) & Dr] & 0xf) << 4));
- }
- }
-
- private byte select(bool condition1, bool condition2, byte option3, byte option4)
- {
- if (condition1 && condition2)
- {
- return 1;
- }
- if (condition1)
- {
- return 2;
- }
- if (condition2)
- {
- return option3;
- }
- return option4;
- }
-
- void rhoohr(byte[] ciphertext, int offset, byte[] plaintext, int inOff, int DBlen_inbytes)
- {
- byte[] OuterState_part1_ROTR1 = state_2d[0];
- int i, loop_end = System.Math.Min(DBlen_inbytes, RATE_INBYTES_HALF);
- for (i = 0; i < RATE_INBYTES_HALF - 1; i++)
- {
- OuterState_part1_ROTR1[i] = (byte)(((state[i] & 0xFF) >> 1) | ((state[(i + 1)] & 1) << 7));
- }
- OuterState_part1_ROTR1[RATE_INBYTES_HALF - 1] = (byte)(((state[i] & 0xFF) >> 1) | ((state[0] & 1) << 7));
- i = 0;
- while (i < loop_end)
- {
- ciphertext[i + offset] = (byte)(state[i + RATE_INBYTES_HALF] ^ plaintext[i++ + inOff]);
- }
- while (i < DBlen_inbytes)
- {
- ciphertext[i + offset] = (byte)(OuterState_part1_ROTR1[i - RATE_INBYTES_HALF] ^ plaintext[i++ + inOff]);
- }
- if (forEncryption)
- {
- Bytes.XorTo(DBlen_inbytes, plaintext, inOff, state, 0);
- }
- else
- {
- Bytes.XorTo(DBlen_inbytes, ciphertext, inOff, state, 0);
- }
- }
-
- public int DoFinal(byte[] output, int outOff)
- {
- if (!initialised)
- throw new ArgumentException("Need to call Init before encryption/decryption");
-
- int len = (int)message.Length - (forEncryption ? 0 : TAG_INBYTES);
- if ((forEncryption && len + TAG_INBYTES + outOff > output.Length) ||
- (!forEncryption && len + outOff > output.Length))
- {
- throw new OutputLengthException("output buffer too short");
- }
- byte[] input = message.GetBuffer();
- int inOff = 0;
- A = aadData.GetBuffer();
- int adlen = (int)aadData.Length, i;
- if (adlen != 0 || len != 0)
- {
- input_empty = false;
- }
- byte c0 = select((len != 0), ((adlen % RATE_INBYTES) == 0), (byte)3, (byte)4);
- byte c1 = select((adlen != 0), ((len % RATE_INBYTES) == 0), (byte)5, (byte)6);
- int Dlen_inblocks, LastDBlocklen;
- if (adlen != 0)
- {
- Dlen_inblocks = (adlen + RATE_INBYTES - 1) / RATE_INBYTES;
- for (i = 0; i < Dlen_inblocks - 1; i++)
- {
- PHOTON_Permutation();
- Bytes.XorTo(RATE_INBYTES, A, i * RATE_INBYTES, state, 0);
- }
- PHOTON_Permutation();
- LastDBlocklen = adlen - i * RATE_INBYTES;
- Bytes.XorTo(LastDBlocklen, A, i * RATE_INBYTES, state, 0);
- if (LastDBlocklen < RATE_INBYTES)
- {
- state[LastDBlocklen] ^= 0x01; // ozs
- }
- state[STATE_INBYTES - 1] ^= (byte)(c0 << LAST_THREE_BITS_OFFSET);
- }
- if (len != 0)
- {
- Dlen_inblocks = (len + RATE_INBYTES - 1) / RATE_INBYTES;
- for (i = 0; i < Dlen_inblocks - 1; i++)
- {
- PHOTON_Permutation();
- rhoohr(output, outOff + i * RATE_INBYTES, input, inOff + i * RATE_INBYTES, RATE_INBYTES);
- }
- PHOTON_Permutation();
- LastDBlocklen = len - i * RATE_INBYTES;
- rhoohr(output, outOff + i * RATE_INBYTES, input, inOff + i * RATE_INBYTES, LastDBlocklen);
- if (LastDBlocklen < RATE_INBYTES)
- {
- state[LastDBlocklen] ^= 0x01; // ozs
- }
- state[STATE_INBYTES - 1] ^= (byte)(c1 << LAST_THREE_BITS_OFFSET);
- }
- outOff += len;
- if (input_empty)
- {
- state[STATE_INBYTES - 1] ^= (byte)(1 << LAST_THREE_BITS_OFFSET);
- }
- PHOTON_Permutation();
- T = new byte[TAG_INBYTES];
- Array.Copy(state, 0, T, 0, TAG_INBYTES);
- if (forEncryption)
- {
- Array.Copy(T, 0, output, outOff, TAG_INBYTES);
- len += TAG_INBYTES;
- }
- else
- {
- if (!Arrays.FixedTimeEquals(TAG_INBYTES, T, 0, input, len))
- throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed");
- }
- reset(false);
- return len;
- }
-
- public int GetBlockSize()
- {
- return RATE_INBYTES;
- }
-
- public int GetKeyBytesSize()
- {
- return CRYPTO_KEYBYTES;
- }
-
- public int GetIVBytesSize()
- {
- return CRYPTO_NPUBBYTES;
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public void ProcessAadBytes(ReadOnlySpan<byte> input)
- {
- aadData.Write(input);
- }
-
- public int ProcessByte(byte input, Span<byte> output)
- {
- byte[] rv = new byte[1];
- int len = ProcessBytes(new byte[] { input }, 0, 1, rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return len;
- }
-
- public int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
- {
- byte[] rv = new byte[input.Length];
- int len = ProcessBytes(input.ToArray(), 0, rv.Length, rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return len;
- }
-
- public int DoFinal(Span<byte> output)
- {
- byte[] rv;
- if (forEncryption)
- {
- rv = new byte[message.Length + 16];
- }
- else
- {
- rv = new byte[message.Length - 16];
- }
- int len = DoFinal(rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return rv.Length;
- }
-#endif
- }
-}
diff --git a/crypto/src/crypto/engines/SparkleEngine.cs b/crypto/src/crypto/engines/SparkleEngine.cs
deleted file mode 100644
index 7d8c28f8e..000000000
--- a/crypto/src/crypto/engines/SparkleEngine.cs
+++ /dev/null
@@ -1,580 +0,0 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Crypto.Utilities;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Engines
-{
- /// <summary>Sparkle v1.2, based on the current round 3 submission, https://sparkle-lwc.github.io/ .</summary>
- /// <remarks>
- /// Reference C implementation: https://github.com/cryptolu/sparkle.<br/>
- /// Specification:
- /// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/sparkle-spec-final.pdf .
- /// </remarks>
- public sealed class SparkleEngine
- // TODO IAeadCipher only
- : IAeadBlockCipher
- {
- public enum SparkleParameters
- {
- SCHWAEMM128_128,
- SCHWAEMM256_128,
- SCHWAEMM192_192,
- SCHWAEMM256_256
- }
-
- private string algorithmName;
- private bool forEncryption = true; // Safe output sizes before initialization
- private readonly uint[] state;
- private readonly uint[] k;
- private readonly uint[] npub;
- private byte[] tag;
- private bool initialised;
- private bool encrypted;
- private bool aadFinished;
- private readonly MemoryStream aadData = new MemoryStream();
- private readonly MemoryStream message = new MemoryStream();
- private readonly int SCHWAEMM_KEY_LEN;
- private readonly int SCHWAEMM_NONCE_LEN;
- private readonly int SPARKLE_STEPS_SLIM;
- private readonly int SPARKLE_STEPS_BIG;
- private readonly int KEY_BYTES;
- private readonly int KEY_WORDS;
- private readonly int TAG_WORDS;
- private readonly int TAG_BYTES;
- private readonly int STATE_BRANS;
- private readonly int STATE_WORDS;
- private readonly int RATE_WORDS;
- private readonly int RATE_BYTES;
- private readonly int CAP_WORDS;
- private readonly uint _A0;
- private readonly uint _A1;
- private readonly uint _M2;
- private readonly uint _M3;
-
- public SparkleEngine(SparkleParameters sparkleParameters)
- {
- int SPARKLE_STATE;
- int SCHWAEMM_TAG_LEN;
- 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");
- }
- KEY_WORDS = SCHWAEMM_KEY_LEN >> 5;
- KEY_BYTES = SCHWAEMM_KEY_LEN >> 3;
- TAG_WORDS = SCHWAEMM_TAG_LEN >> 5;
- TAG_BYTES = SCHWAEMM_TAG_LEN >> 3;
- STATE_BRANS = SPARKLE_STATE >> 6;
- STATE_WORDS = SPARKLE_STATE >> 5;
- RATE_WORDS = SCHWAEMM_NONCE_LEN >> 5;
- RATE_BYTES = SCHWAEMM_NONCE_LEN >> 3;
- int CAP_BRANS = SPARKLE_CAPACITY >> 6;
- CAP_WORDS = SPARKLE_CAPACITY >> 5;
- _A0 = ((((1u << CAP_BRANS))) << 24);
- _A1 = (((1u ^ (1u << CAP_BRANS))) << 24);
- _M2 = (((2u ^ (1u << CAP_BRANS))) << 24);
- _M3 = (((3u ^ (1u << CAP_BRANS))) << 24);
- state = new uint[STATE_WORDS];
- tag = new byte[TAG_BYTES];
- k = new uint[KEY_WORDS];
- npub = new uint[RATE_WORDS];
- initialised = false;
- }
-
- private uint ELL(uint x)
- {
- return Integers.RotateRight(x ^ (x << 16), 16);
- }
-
- private static readonly uint[] RCON = {0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738, 0xBB1185EB, 0x4F7C7B57,
- 0xCFBFA1C8, 0xC2B3293D};
-
- void sparkle_opt(uint[] state, int brans, int steps)
- {
- uint i, j, rc, tmpx, tmpy, x0, y0;
- for (i = 0; i < steps; i++)
- {
- // Add round ant
- state[1] ^= RCON[i & 7];
- state[3] ^= i;
- // ARXBOX layer
- for (j = 0; j < 2 * brans; j += 2)
- {
- rc = RCON[j >> 1];
- state[j] += Integers.RotateRight(state[j + 1], 31);
- state[j + 1] ^= Integers.RotateRight(state[j], 24);
- state[j] ^= rc;
- 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] ^= Integers.RotateRight(state[j], 31);
- state[j] ^= rc;
- state[j] += Integers.RotateRight(state[j + 1], 24);
- state[j + 1] ^= Integers.RotateRight(state[j], 16);
- state[j] ^= rc;
- }
- // Linear layer
- tmpx = x0 = state[0];
- tmpy = y0 = state[1];
- for (j = 2; j < brans; j += 2)
- {
- tmpx ^= state[j];
- tmpy ^= state[j + 1];
- }
- tmpx = ELL(tmpx);
- tmpy = ELL(tmpy);
- for (j = 2; j < brans; j += 2)
- {
- state[j - 2] = state[j + brans] ^ state[j] ^ tmpy;
- state[j + brans] = state[j];
- state[j - 1] = state[j + brans + 1] ^ state[j + 1] ^ tmpx;
- state[j + brans + 1] = state[j + 1];
- }
- state[brans - 2] = state[brans] ^ x0 ^ tmpy;
- state[brans] = x0;
- state[brans - 1] = state[brans + 1] ^ y0 ^ tmpx;
- state[brans + 1] = y0;
- }
- }
-
- private int CAP_INDEX(int i)
- {
- if (RATE_WORDS > CAP_WORDS)
- {
- return i & (CAP_WORDS - 1);
- }
- return i;
- }
-
- // The ProcessAssocData function absorbs the associated data, which becomes
- // only authenticated but not encrypted, into the state (in blocks of size
- // RATE_BYTES). Note that this function MUST NOT be called when the length of
- // the associated data is 0.
- void ProcessAssocData(uint[] state)
- {
- int inlen = (int)aadData.Length;
- if (aadFinished || inlen == 0)
- {
- return;
- }
- aadFinished = true;
- byte[] input = aadData.GetBuffer();
- // Main Authentication Loop
- int inOff = 0, i, j;
- uint tmp;
- uint[] in32 = Pack.LE_To_UInt32(input, inOff, input.Length >> 2);
- while (inlen > RATE_BYTES)
- {
- // combined Rho and rate-whitening operation
- // Rho and rate-whitening for the authentication of associated data. The third
- // parameter indicates whether the uint8_t-pointer 'in' is properly aligned to
- // permit casting to a int-pointer. If this is the case then array 'in' is
- // processed directly, otherwise it is first copied to an aligned buffer.
- for (i = 0, j = RATE_WORDS / 2; i < RATE_WORDS / 2; i++, j++)
- {
- tmp = state[i];
- state[i] = state[j] ^ in32[i + (inOff >> 2)] ^ state[RATE_WORDS + i];
- state[j] ^= tmp ^ in32[j + (inOff >> 2)] ^ state[RATE_WORDS + CAP_INDEX(j)];
- }
- // execute SPARKLE with slim number of steps
- sparkle_opt(state, STATE_BRANS, SPARKLE_STEPS_SLIM);
- inlen -= RATE_BYTES;
- inOff += RATE_BYTES;
- }
- // Authentication of Last Block
- // addition of ant A0 or A1 to the state
- state[STATE_WORDS - 1] ^= ((inlen < RATE_BYTES) ? _A0 : _A1);
- // combined Rho and rate-whitening (incl. padding)
- // Rho and rate-whitening for the authentication of the last associated-data
- // block. Since this last block may require padding, it is always copied to a buffer.
- uint[] buffer = new uint[RATE_WORDS];
- for (i = 0; i < inlen; ++i)
- {
- buffer[i >> 2] |= (uint)input[inOff++] << ((i & 3) << 3);
- }
- if (inlen < RATE_BYTES)
- { // padding
- buffer[i >> 2] |= 0x80u << ((i & 3) << 3);
- }
- for (i = 0, j = RATE_WORDS / 2; i < RATE_WORDS / 2; i++, j++)
- {
- tmp = state[i];
- state[i] = state[j] ^ buffer[i] ^ state[RATE_WORDS + i];
- state[j] ^= tmp ^ buffer[j] ^ state[RATE_WORDS + CAP_INDEX(j)];
- }
- // execute SPARKLE with big number of steps
- sparkle_opt(state, STATE_BRANS, SPARKLE_STEPS_BIG);
- }
-
- // The ProcessPlainText function encrypts the plaintext (input blocks of size
- // RATE_BYTES) and generates the respective ciphertext. The uint8_t-array 'input'
- // contains the plaintext and the ciphertext is written to uint8_t-array 'output'
- // ('input' and 'output' can be the same array, i.e. they can have the same start
- // address). Note that this function MUST NOT be called when the length of the
- // plaintext is 0.
- private int ProcessPlainText(uint[] state, byte[] output, byte[] input, int inOff, int inlen)
- {
- // Main Encryption Loop
- int outOff = 0, i, j;
- uint tmp1, tmp2;
- uint[] in32 = Pack.LE_To_UInt32(input, inOff, input.Length >> 2);
- uint[] out32 = new uint[output.Length >> 2];
- int rv = 0;
- while (inlen > RATE_BYTES)
- {
- // combined Rho and rate-whitening operation
- // Rho and rate-whitening for the encryption of plaintext. The third parameter
- // indicates whether the uint8_t-pointers 'input' and 'output' are properly aligned
- // to permit casting to int-pointers. If this is the case then array 'input'
- // and 'output' are processed directly, otherwise 'input' is copied to an aligned buffer.
- for (i = 0, j = RATE_WORDS / 2; i < RATE_WORDS / 2; i++, j++)
- {
- tmp1 = state[i];
- tmp2 = state[j];
- if (forEncryption)
- {
- state[i] = state[j] ^ in32[i + (inOff >> 2)] ^ state[RATE_WORDS + i];
- state[j] ^= tmp1 ^ in32[j + (inOff >> 2)] ^ state[RATE_WORDS + CAP_INDEX(j)];
- }
- else
- {
- state[i] ^= state[j] ^ in32[i + (inOff >> 2)] ^ state[RATE_WORDS + i];
- state[j] = tmp1 ^ in32[j + (inOff >> 2)] ^ state[RATE_WORDS + CAP_INDEX(j)];
- }
- out32[i] = in32[i] ^ tmp1;
- out32[j] = in32[j] ^ tmp2;
- }
- Pack.UInt32_To_LE(out32, 0, RATE_WORDS, output, outOff);
- // execute SPARKLE with slim number of steps
- sparkle_opt(state, STATE_BRANS, SPARKLE_STEPS_SLIM);
- inlen -= RATE_BYTES;
- outOff += RATE_BYTES;
- inOff += RATE_BYTES;
- rv += RATE_BYTES;
- encrypted = true;
- }
- return rv;
- }
-
- public void Init(bool forEncryption, ICipherParameters param)
- {
- this.forEncryption = forEncryption;
- if (!(param is ParametersWithIV ivParams))
- throw new ArgumentException(algorithmName + " init parameters must include an IV");
-
- 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 key))
- throw new ArgumentException(algorithmName + " init parameters must include a key");
-
- 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);
- }
-
- public void ProcessAadByte(byte input)
- {
- if (encrypted)
- {
- throw new ArgumentException(algorithmName + ": AAD cannot be added after reading a full block(" +
- GetBlockSize() + " bytes) of input for " + (forEncryption ? "encryption" : "decryption"));
- }
-
- aadData.WriteByte(input);
- }
-
- public void ProcessAadBytes(byte[] input, int inOff, int len)
- {
- if (encrypted)
- {
- throw new ArgumentException(algorithmName + ": AAD cannot be added after reading a full block(" +
- GetBlockSize() + " bytes) of input for " + (forEncryption ? "encryption" : "decryption"));
- }
-
- 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);
- }
-
- 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");
-
- Check.DataLength(input, inOff, len, "input buffer too short");
-
- message.Write(input, inOff, len);
-
- int msgLen = Convert.ToInt32(message.Length);
-
- len = 0;
- if ((forEncryption && msgLen > GetBlockSize()) ||
- (!forEncryption && msgLen - TAG_BYTES > GetBlockSize()))
- {
- 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);
- }
- message.SetLength(0);
- // 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 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))
- {
- throw new OutputLengthException("output buffer is too short");
- }
- ProcessAssocData(state);
- int i, j;
- uint tmp1, tmp2;
- byte[] input = message.GetBuffer();
- int inOff = 0;
- if (encrypted || inlen != 0)
- {
- // Encryption of Last Block
- // addition of ant M2 or M3 to the state
- state[STATE_WORDS - 1] ^= ((inlen < RATE_BYTES) ? _M2 : _M3);
- // combined Rho and rate-whitening (incl. padding)
- // Rho and rate-whitening for the encryption of the last plaintext block. Since
- // this last block may require padding, it is always copied to a buffer.
- uint[] buffer = new uint[RATE_WORDS];
- for (i = 0; i < inlen; ++i)
- {
- buffer[i >> 2] |= (input[inOff++] & 0xffu) << ((i & 3) << 3);
- }
- if (inlen < RATE_BYTES)
- {
- if (!forEncryption)
- {
- int tmp = (i & 3) << 3;
- buffer[i >> 2] |= (state[i >> 2] >> tmp) << tmp;
- tmp = (i >> 2) + 1;
- Array.Copy(state, tmp, buffer, tmp, RATE_WORDS - tmp);
- }
- buffer[i >> 2] ^= 0x80u << ((i & 3) << 3);
- }
- for (i = 0, j = RATE_WORDS / 2; i < RATE_WORDS / 2; i++, j++)
- {
- tmp1 = state[i];
- tmp2 = state[j];
- if (forEncryption)
- {
- state[i] = state[j] ^ buffer[i] ^ state[RATE_WORDS + i];
- state[j] ^= tmp1 ^ buffer[j] ^ state[RATE_WORDS + CAP_INDEX(j)];
- }
- else
- {
- state[i] ^= state[j] ^ buffer[i] ^ state[RATE_WORDS + i];
- state[j] = tmp1 ^ buffer[j] ^ state[RATE_WORDS + CAP_INDEX(j)];
- }
- buffer[i] ^= tmp1;
- buffer[j] ^= tmp2;
- }
- for (i = 0; i < inlen; ++i)
- {
- output[outOff++] = (byte)(buffer[i >> 2] >> ((i & 3) << 3));
- }
- // execute SPARKLE with big number of steps
- sparkle_opt(state, STATE_BRANS, SPARKLE_STEPS_BIG);
- }
- // add key to the capacity-part of the state
- for (i = 0; i < KEY_WORDS; i++)
- {
- state[RATE_WORDS + i] ^= k[i];
- }
- tag = new byte[TAG_BYTES];
- Pack.UInt32_To_LE(state, RATE_WORDS, TAG_WORDS, tag, 0);
- if (forEncryption)
- {
- Array.Copy(tag, 0, output, outOff, TAG_BYTES);
- inlen += TAG_BYTES;
- }
- else
- {
- if (!Arrays.FixedTimeEquals(TAG_BYTES, tag, 0, input, inlen))
- throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed");
- }
- reset(false);
- return inlen;
- }
-
- public byte[] GetMac()
- {
- 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 to call Init before Reset");
-
- reset(true);
- }
-
- private void reset(bool clearMac)
- {
- if (clearMac)
- {
- tag = null;
- }
- // The Initialize function loads nonce and key into the state and executes the
- // SPARKLE permutation with the big number of steps.
- // load nonce into the rate-part of the state
- Array.Copy(npub, 0, state, 0, RATE_WORDS);
- // load key into the capacity-part of the sate
- Array.Copy(k, 0, state, RATE_WORDS, KEY_WORDS);
- // execute SPARKLE with big number of steps
- sparkle_opt(state, STATE_BRANS, SPARKLE_STEPS_BIG);
- aadData.SetLength(0);
- message.SetLength(0);
- encrypted = false;
- aadFinished = false;
- }
- public string AlgorithmName => algorithmName;
-
- public IBlockCipher UnderlyingCipher => throw new NotImplementedException();
-
- public int GetBlockSize()
- {
- return RATE_BYTES;
- }
-
-
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public void ProcessAadBytes(ReadOnlySpan<byte> input)
- {
- aadData.Write(input);
- }
-
- public int ProcessByte(byte input, Span<byte> output)
- {
- byte[] rv = new byte[1];
- int len = ProcessBytes(new byte[] { input }, 0, 1, rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return len;
-
- }
-
- public int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
- {
- byte[] rv = new byte[input.Length];
- int len = ProcessBytes(input.ToArray(), 0, rv.Length, rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return len;
- }
-
- public int DoFinal(Span<byte> output)
- {
- byte[] rv;
- if (forEncryption)
- {
- rv = new byte[message.Length + TAG_BYTES];
- }
- else
- {
- rv = new byte[message.Length - TAG_BYTES];
- }
- int len = DoFinal(rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return rv.Length;
-
- }
-#endif
-
- public int GetKeyBytesSize()
- {
- return KEY_BYTES;
- }
-
- public int GetIVBytesSize()
- {
- return RATE_BYTES;
- }
- }
-}
-
diff --git a/crypto/src/crypto/engines/XoodyakEngine.cs b/crypto/src/crypto/engines/XoodyakEngine.cs
deleted file mode 100644
index 2eb563525..000000000
--- a/crypto/src/crypto/engines/XoodyakEngine.cs
+++ /dev/null
@@ -1,431 +0,0 @@
-using System;
-using System.IO;
-
-using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Parameters;
-using Org.BouncyCastle.Crypto.Utilities;
-using Org.BouncyCastle.Utilities;
-
-namespace Org.BouncyCastle.Crypto.Engines
-{
- /**
- * Xoodyak v1, https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/xoodyak-spec-final.pdf
- * <p>
- * Xoodyak with reference to C Reference Impl from: https://github.com/XKCP/XKCP
- * </p>
- */
- public sealed class XoodyakEngine
- // TODO IAeadCipher only
- : IAeadBlockCipher
- {
- 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;
- private int Rabsorb;
- private const int f_bPrime = 48;
- private const int Rkout = 24;
- private byte[] K;
- private byte[] iv;
- private const int PhaseDown = 1;
- private const int PhaseUp = 2;
- private const int NLANES = 12;
- private const int NROWS = 3;
- private const int NCOLUMS = 4;
- private const int MAXROUNDS = 12;
- private const int TAGLEN = 16;
- private byte[] tag;
- private bool aadFinished;
- private bool encrypted;
- private bool initialised = false;
-
- private MemoryStream aadData = new MemoryStream();
- private MemoryStream message = new MemoryStream();
-
- public string AlgorithmName => "Xoodak AEAD";
-
- public IBlockCipher UnderlyingCipher => throw new NotImplementedException();
-
- public void Init(bool forEncryption, ICipherParameters parameters)
- {
- this.forEncryption = forEncryption;
-
- if (!(parameters is ParametersWithIV ivParams))
- throw new ArgumentException("Xoodyak init parameters must include an IV");
-
- iv = ivParams.GetIV();
- if (iv == null || iv.Length != 16)
- throw new ArgumentException("Xoodyak requires exactly 16 bytes of IV");
-
- if (!(ivParams.Parameters is KeyParameter key))
- throw new ArgumentException("Xoodyak init parameters must include a key");
-
- 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;
- reset(false);
- }
-
- public void ProcessAadByte(byte input)
- {
- if (aadFinished)
- {
- throw new ArgumentException("AAD cannot be added after reading a full block(" + GetBlockSize() +
- " bytes) of input for " + (forEncryption ? "encryption" : "decryption"));
- }
-
- aadData.WriteByte(input);
- }
-
- public void ProcessAadBytes(byte[] input, int inOff, int len)
- {
- if (aadFinished)
- {
- throw new ArgumentException("AAD cannot be added after reading a full block(" + GetBlockSize() +
- " bytes) of input for " + (forEncryption ? "encryption" : "decryption"));
- }
-
- Check.DataLength(input, inOff, len, "input buffer too short");
-
- aadData.Write(input, inOff, len);
- }
-
- public int ProcessByte(byte input, byte[] outBytes, int outOff)
- {
- return ProcessBytes(new byte[]{ input }, 0, 1, outBytes, outOff);
- }
-
- private void processAAD()
- {
- if (!aadFinished)
- {
- byte[] ad = aadData.GetBuffer();
- AbsorbAny(ad, 0, (int)aadData.Length, Rabsorb, 0x03);
- aadFinished = true;
- }
- }
-
- 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");
-
- if (mode != MODE.ModeKeyed)
- throw new ArgumentException("Xoodyak has not been initialised");
-
- Check.DataLength(inBytes, inOff, len, "input buffer too short");
-
- 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(outBytes, outOff, len, "output buffer is too short");
- processAAD();
- encrypt(blocks, 0, len, outBytes, outOff);
- int messageLen = (int)message.Length;
- message.SetLength(0);
- message.Write(blocks, len, messageLen - len);
- return len;
- }
- return 0;
- }
-
- private int encrypt(byte[] input, int inOff, int len, byte[] output, int outOff)
- {
- int IOLen = len;
- int splitLen;
- byte[] P = new byte[Rkout];
- uint Cu = encrypted ? 0u : 0x80u;
- while (IOLen != 0 || !encrypted)
- {
- splitLen = System.Math.Min(IOLen, Rkout); /* use Rkout instead of Rsqueeze, this function is only called in keyed mode */
- if (forEncryption)
- {
- Array.Copy(input, inOff, P, 0, splitLen);
- }
- Up(null, 0, Cu); /* Up without extract */
- /* Extract from Up and Add */
- for (int i = 0; i < splitLen; i++)
- {
- output[outOff + i] = (byte)(input[inOff++] ^ state[i]);
- }
- if (forEncryption)
- {
- Down(P, 0, splitLen, 0x00);
- }
- else
- {
- Down(output, outOff, splitLen, 0x00);
- }
- Cu = 0x00;
- outOff += splitLen;
- IOLen -= splitLen;
- encrypted = true;
- }
- return len;
- }
-
-
- 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 > outBytes.Length) ||
- (!forEncryption && len - TAGLEN + outOff > outBytes.Length))
- {
- throw new OutputLengthException("output buffer too short");
- }
- processAAD();
- int rv = 0;
- if (forEncryption)
- {
- encrypt(blocks, 0, len, outBytes, outOff);
- outOff += len;
- tag = new byte[TAGLEN];
- Up(tag, TAGLEN, 0x40);
- Array.Copy(tag, 0, outBytes, outOff, TAGLEN);
- rv = len + TAGLEN;
- }
- else
- {
- int inOff = len - TAGLEN;
- rv = inOff;
- encrypt(blocks, 0, inOff, outBytes, outOff);
- tag = new byte[TAGLEN];
- Up(tag, TAGLEN, 0x40);
-
- if (!Arrays.FixedTimeEquals(TAGLEN, tag, 0, blocks, inOff))
- throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed");
- }
- reset(false);
- return rv;
- }
-
- public byte[] GetMac()
- {
- return tag;
- }
-
- public int GetUpdateOutputSize(int len)
- {
- // TODO
- return len;
- }
-
- public int GetOutputSize(int len)
- {
- // TODO
- return len + TAGLEN;
- }
-
- public void Reset()
- {
- if (!initialised)
- throw new ArgumentException("Need to call Init before encryption/decryption");
-
- reset(true);
- }
-
- private void reset(bool clearMac)
- {
- if (clearMac)
- {
- tag = null;
- }
- Arrays.Fill(state, (byte)0);
- aadFinished = false;
- encrypted = false;
- phase = PhaseUp;
- message.SetLength(0);
- aadData.SetLength(0);
- //Absorb key
- int KLen = K.Length;
- int IDLen = iv.Length;
- byte[] KID = new byte[Rkin];
- mode = MODE.ModeKeyed;
- Rabsorb = Rkin;
- Array.Copy(K, 0, KID, 0, KLen);
- Array.Copy(iv, 0, KID, KLen, IDLen);
- KID[KLen + IDLen] = (byte)IDLen;
- AbsorbAny(KID, 0, KLen + IDLen + 1, Rabsorb, 0x02);
- }
-
- private void AbsorbAny(byte[] X, int Xoff, int XLen, int r, uint Cd)
- {
- int splitLen;
- do
- {
- if (phase != PhaseUp)
- {
- Up(null, 0, 0);
- }
- splitLen = System.Math.Min(XLen, r);
- Down(X, Xoff, splitLen, Cd);
- Cd = 0;
- Xoff += splitLen;
- XLen -= splitLen;
- }
- while (XLen != 0);
- }
-
- private void Up(byte[] Yi, int YiLen, uint Cu)
- {
- if (mode != MODE.ModeHash)
- {
- state[f_bPrime - 1] ^= (byte)Cu;
- }
- uint[] a = new uint[NLANES];
- Pack.LE_To_UInt32(state, 0, a, 0, a.Length);
- uint x, y;
- uint[] b = new uint[NLANES];
- uint[] p = new uint[NCOLUMS];
- uint[] e = new uint[NCOLUMS];
- for (int i = 0; i < MAXROUNDS; ++i)
- {
- /* Theta: Column Parity Mixer */
- for (x = 0; x < NCOLUMS; ++x)
- {
- p[x] = a[index(x, 0)] ^ a[index(x, 1)] ^ a[index(x, 2)];
- }
- for (x = 0; x < NCOLUMS; ++x)
- {
- y = p[(x + 3) & 3];
- e[x] = ROTL32(y, 5) ^ ROTL32(y, 14);
- }
- for (x = 0; x < NCOLUMS; ++x)
- {
- for (y = 0; y < NROWS; ++y)
- {
- a[index(x, y)] ^= e[x];
- }
- }
- /* Rho-west: plane shift */
- for (x = 0; x < NCOLUMS; ++x)
- {
- b[index(x, 0)] = a[index(x, 0)];
- b[index(x, 1)] = a[index(x + 3, 1)];
- b[index(x, 2)] = ROTL32(a[index(x, 2)], 11);
- }
- /* Iota: round ant */
- b[0] ^= RC[i];
- /* Chi: non linear layer */
- for (x = 0; x < NCOLUMS; ++x)
- {
- for (y = 0; y < NROWS; ++y)
- {
- a[index(x, y)] = b[index(x, y)] ^ (~b[index(x, y + 1)] & b[index(x, y + 2)]);
- }
- }
- /* Rho-east: plane shift */
- for (x = 0; x < NCOLUMS; ++x)
- {
- b[index(x, 0)] = a[index(x, 0)];
- b[index(x, 1)] = ROTL32(a[index(x, 1)], 1);
- b[index(x, 2)] = ROTL32(a[index(x + 2, 2)], 8);
- }
- Array.Copy(b, 0, a, 0, NLANES);
- }
- Pack.UInt32_To_LE(a, 0, a.Length, state, 0);
- phase = PhaseUp;
- if (Yi != null)
- {
- Array.Copy(state, 0, Yi, 0, YiLen);
- }
- }
-
- void Down(byte[] Xi, int XiOff, int XiLen, uint Cd)
- {
- for (int i = 0; i < XiLen; i++)
- {
- state[i] ^= Xi[XiOff++];
- }
- state[XiLen] ^= 0x01;
- state[f_bPrime - 1] ^= (byte)((mode == MODE.ModeHash) ? (Cd & 0x01) : Cd);
- phase = PhaseDown;
- }
-
- private uint index(uint x, uint y)
- {
- return (((y % NROWS) * NCOLUMS) + ((x) % NCOLUMS));
- }
-
- private uint ROTL32(uint a, int offset)
- {
- return (a << (offset & 31)) ^ (a >> ((32 - (offset)) & 31));
- }
-
- public int GetBlockSize()
- {
- return Rkout;
- }
-
- public int GetKeyBytesSize()
- {
- return 16;
- }
-
- public int GetIVBytesSize()
- {
- return 16;
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public void ProcessAadBytes(ReadOnlySpan<byte> input)
- {
- aadData.Write(input);
- }
-
- public int ProcessByte(byte input, Span<byte> output)
- {
- byte[] rv = new byte[1];
- int len = ProcessBytes(new byte[] { input }, 0, 1, rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return len;
- }
-
- public int ProcessBytes(ReadOnlySpan<byte> input, Span<byte> output)
- {
- byte[] rv = new byte[input.Length];
- int len = ProcessBytes(input.ToArray(), 0, rv.Length, rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return len;
- }
-
- public int DoFinal(Span<byte> output)
- {
- byte[] rv;
- if (forEncryption)
- {
- rv = new byte[message.Length + 16];
- }
- else
- {
- rv = new byte[message.Length - 16];
- }
- int len = DoFinal(rv, 0);
- rv.AsSpan(0, len).CopyTo(output);
- return rv.Length;
- }
-#endif
- }
-}
|