diff --git a/crypto/src/crypto/digests/AsconDigest.cs b/crypto/src/crypto/digests/AsconDigest.cs
index 343036b99..20d39ce77 100644
--- a/crypto/src/crypto/digests/AsconDigest.cs
+++ b/crypto/src/crypto/digests/AsconDigest.cs
@@ -8,6 +8,11 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
+ /// <summary>ASCON v1.2 Hash, https://ascon.iaik.tugraz.at/ .</summary>
+ /// <remarks>
+ /// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/ascon-spec-final.pdf<br/>
+ /// ASCON v1.2 Hash with reference to C Reference Impl from: https://github.com/ascon/ascon-c .
+ /// </remarks>
public sealed class AsconDigest
: IDigest
{
@@ -247,15 +252,18 @@ namespace Org.BouncyCastle.Crypto.Digests
private void P(int nr)
{
- if (nr == 12)
+ //if (nr >= 8)
{
- ROUND(0xf0UL);
- ROUND(0xe1UL);
- ROUND(0xd2UL);
- ROUND(0xc3UL);
+ if (nr == 12)
+ {
+ ROUND(0xf0UL);
+ ROUND(0xe1UL);
+ ROUND(0xd2UL);
+ ROUND(0xc3UL);
+ }
+ ROUND(0xb4UL);
+ ROUND(0xa5UL);
}
- ROUND(0xb4UL);
- ROUND(0xa5UL);
ROUND(0x96UL);
ROUND(0x87UL);
ROUND(0x78UL);
@@ -267,12 +275,12 @@ namespace Org.BouncyCastle.Crypto.Digests
#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
[MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
- private void ROUND(ulong C)
+ private 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 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);
diff --git a/crypto/src/crypto/digests/ISAPDigest.cs b/crypto/src/crypto/digests/ISAPDigest.cs
index 348242e6e..83214fe6b 100644
--- a/crypto/src/crypto/digests/ISAPDigest.cs
+++ b/crypto/src/crypto/digests/ISAPDigest.cs
@@ -12,9 +12,8 @@ namespace Org.BouncyCastle.Crypto.Digests
public sealed class IsapDigest
: IDigest
{
+ private readonly MemoryStream buffer = new MemoryStream();
private ulong x0, x1, x2, x3, x4;
- private ulong t0, t1, t2, t3, t4;
- private MemoryStream buffer = new MemoryStream();
public string AlgorithmName => "ISAP Hash";
@@ -48,8 +47,6 @@ namespace Org.BouncyCastle.Crypto.Digests
#else
Check.OutputLength(output, outOff, 32, "output buffer is too short");
- t0 = t1 = t2 = t3 = t4 = 0;
-
/* init state */
x0 = 17191252062196199485UL;
x1 = 10066134719181819906UL;
@@ -89,8 +86,6 @@ namespace Org.BouncyCastle.Crypto.Digests
{
Check.OutputLength(output, 32, "output buffer is too short");
- t0 = t1 = t2 = t3 = t4 = 0;
-
/* init state */
x0 = 17191252062196199485UL;
x1 = 10066134719181819906UL;
@@ -150,11 +145,11 @@ namespace Org.BouncyCastle.Crypto.Digests
#endif
private 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/digests/PhotonBeetleDigest.cs b/crypto/src/crypto/digests/PhotonBeetleDigest.cs
index 1af8aee2c..c7cbfdfca 100644
--- a/crypto/src/crypto/digests/PhotonBeetleDigest.cs
+++ b/crypto/src/crypto/digests/PhotonBeetleDigest.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Crypto.Digests
* Photon-Beetle with reference to C Reference Impl from: https://github.com/PHOTON-Beetle/Software
* </p>
*/
- public class PhotonBeetleDigest
+ public sealed class PhotonBeetleDigest
: IDigest
{
private byte[] state;
@@ -64,7 +64,6 @@ namespace Org.BouncyCastle.Crypto.Digests
}
}
-
public String AlgorithmName => "Photon-Beetle Hash";
public int GetDigestSize() => TAG_INBYTES;
@@ -80,22 +79,24 @@ namespace Org.BouncyCastle.Crypto.Digests
buffer.WriteByte(input);
}
- public void BlockUpdate(byte[] input, int inOff, int len)
+ public void BlockUpdate(byte[] input, int inOff, int inLen)
{
- if ((inOff + len) > input.Length)
- {
- throw new DataLengthException("input buffer too short");
- }
- buffer.Write(input, inOff, len);
+ Check.DataLength(input, inOff, inLen, "input buffer too short");
+
+ buffer.Write(input, inOff, inLen);
}
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ buffer.Write(input);
+ }
+#endif
public int DoFinal(byte[] output, int outOff)
{
- if (32 + outOff > output.Length)
- {
- throw new OutputLengthException("output buffer is too short");
- }
+ Check.OutputLength(output, outOff, 32, "output buffer is too short");
+
byte[] input = buffer.GetBuffer();
int inlen = (int)buffer.Length;
if (inlen == 0)
@@ -120,11 +121,11 @@ namespace Org.BouncyCastle.Crypto.Digests
for (i = 0; i < Dlen_inblocks - 1; i++)
{
PHOTON_Permutation();
- XOR(input, INITIAL_RATE_INBYTES + i * RATE_INBYTES, RATE_INBYTES);
+ Bytes.XorTo(RATE_INBYTES, input, INITIAL_RATE_INBYTES + i * RATE_INBYTES, state, 0);
}
PHOTON_Permutation();
LastDBlocklen = inlen - i * RATE_INBYTES;
- XOR(input, INITIAL_RATE_INBYTES + i * RATE_INBYTES, LastDBlocklen);
+ Bytes.XorTo(LastDBlocklen, input, INITIAL_RATE_INBYTES + i * RATE_INBYTES, state, 0);
if (LastDBlocklen < RATE_INBYTES)
{
state[LastDBlocklen] ^= 0x01; // ozs
@@ -138,14 +139,15 @@ namespace Org.BouncyCastle.Crypto.Digests
return TAG_INBYTES;
}
- void XOR(byte[] in_right, int rOff, int iolen_inbytes)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int DoFinal(Span<byte> output)
{
- for (int i = 0; i < iolen_inbytes; i++)
- {
- state[i] ^= in_right[i + rOff];
- }
+ byte[] rv = new byte[32];
+ int rlt = DoFinal(rv, 0);
+ rv.AsSpan(0, 32).CopyTo(output);
+ return rlt;
}
-
+#endif
public void Reset()
{
@@ -153,7 +155,7 @@ namespace Org.BouncyCastle.Crypto.Digests
Arrays.Fill(state, (byte)0);
}
- void PHOTON_Permutation()
+ private void PHOTON_Permutation()
{
int i, j, k, l;
for (i = 0; i < DSquare; i++)
@@ -222,22 +224,5 @@ namespace Org.BouncyCastle.Crypto.Digests
state[i >> 1] = (byte)(((state_2d[i >> Dq][i & Dr] & 0xf)) | ((state_2d[i >> Dq][(i + 1) & Dr] & 0xf) << 4));
}
}
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
-
- public int DoFinal(Span<byte> output)
- {
- byte[] rv = new byte[32];
- int rlt = DoFinal(rv, 0);
- rv.AsSpan(0, 32).CopyTo(output);
- return rlt;
- }
-
- public void BlockUpdate(ReadOnlySpan<byte> input)
- {
- buffer.Write(input.ToArray(), 0, input.Length);
- }
-
-#endif
}
}
diff --git a/crypto/src/crypto/digests/SparkleDigest.cs b/crypto/src/crypto/digests/SparkleDigest.cs
index ad558effc..bd03fdf0d 100644
--- a/crypto/src/crypto/digests/SparkleDigest.cs
+++ b/crypto/src/crypto/digests/SparkleDigest.cs
@@ -12,7 +12,7 @@ namespace Org.BouncyCastle.Crypto.Digests
/// Specification:
/// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/sparkle-spec-final.pdf .
/// </remarks>
- public class SparkleDigest
+ public sealed class SparkleDigest
: IDigest
{
public enum SparkleParameters
@@ -21,9 +21,12 @@ namespace Org.BouncyCastle.Crypto.Digests
ESCH384
}
+ private static readonly uint[] RCON = { 0xB7E15162U, 0xBF715880U, 0x38B4DA56U, 0x324E7738U, 0xBB1185EBU,
+ 0x4F7C7B57U, 0xCFBFA1C8U, 0xC2B3293DU };
+
private string algorithmName;
private readonly uint[] state;
- private MemoryStream message = new MemoryStream();
+ private readonly MemoryStream message = new MemoryStream();
private readonly int DIGEST_BYTES;
private readonly int SPARKLE_STEPS_SLIM;
private readonly int SPARKLE_STEPS_BIG;
@@ -64,85 +67,35 @@ namespace Org.BouncyCastle.Crypto.Digests
state = new uint[STATE_WORDS];
}
- private uint ELL(uint x)
- {
- return Integers.RotateRight(x ^ (x << 16), 16);
- }
+ public string AlgorithmName => algorithmName;
- private static readonly uint[] RCON = {0xB7E15162, 0xBF715880, 0x38B4DA56, 0x324E7738, 0xBB1185EB, 0x4F7C7B57,
- 0xCFBFA1C8, 0xC2B3293D};
+ public int GetDigestSize() => DIGEST_BYTES;
- void sparkle_opt(uint[] state, int brans, int steps)
+ public int GetByteLength() => RATE_BYTES;
+
+ public void Update(byte input)
{
- 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;
- }
+ message.WriteByte(input);
}
- public int GetDigestSize()
+ public void BlockUpdate(byte[] input, int inOff, int inLen)
{
- return DIGEST_BYTES;
- }
+ Check.DataLength(input, inOff, inLen, "input buffer too short");
+ message.Write(input, inOff, inLen);
+ }
- public void BlockUpdate(byte[] input, int inOff, int len)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
{
- if (inOff + len > input.Length)
- {
- throw new DataLengthException(algorithmName + " input buffer too short");
- }
- message.Write(input, inOff, len);
+ message.Write(input);
}
-
+#endif
public int DoFinal(byte[] output, int outOff)
{
- if (outOff + DIGEST_BYTES > output.Length)
- {
- throw new OutputLengthException(algorithmName + " input buffer too short");
- }
+ Check.OutputLength(output, outOff, DIGEST_BYTES, "output buffer too short");
+
byte[] input = message.GetBuffer();
int inlen = (int)message.Length, i, inOff = 0;
uint tmpx, tmpy;
@@ -220,40 +173,80 @@ namespace Org.BouncyCastle.Crypto.Digests
outOff += RATE_BYTES;
}
return DIGEST_BYTES;
- }
- public string AlgorithmName => algorithmName;
+ // TODO Reset?
+ }
- public void Update(byte input)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int DoFinal(Span<byte> output)
{
- message.Write(new byte[] { input }, 0, 1);
+ byte[] rv = new byte[DIGEST_BYTES];
+ DoFinal(rv, 0);
+ // TODO Remove duplicate if added in other DoFinal
+ Reset();
+ rv.AsSpan(0, rv.Length).CopyTo(output);
+ return DIGEST_BYTES;
}
+#endif
public void Reset()
{
message.SetLength(0);
- Arrays.Fill(state, (byte)0);
+ Arrays.Fill(state, 0U);
}
- public int GetByteLength()
+ private void sparkle_opt(uint[] state, int brans, int steps)
{
- return RATE_BYTES;
- }
-
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public void BlockUpdate(ReadOnlySpan<byte> input)
- {
- message.Write(input);
+ 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;
+ }
}
- public int DoFinal(Span<byte> output)
+ private static uint ELL(uint x)
{
- byte[] rv=new byte[DIGEST_BYTES];
- DoFinal(rv, 0);
- Reset();
- rv.AsSpan(0, rv.Length).CopyTo(output);
- return DIGEST_BYTES;
+ return Integers.RotateRight(x ^ (x << 16), 16);
}
-#endif
}
}
diff --git a/crypto/src/crypto/digests/XoodyakDigest.cs b/crypto/src/crypto/digests/XoodyakDigest.cs
index cf1afcc10..4836f4d2b 100644
--- a/crypto/src/crypto/digests/XoodyakDigest.cs
+++ b/crypto/src/crypto/digests/XoodyakDigest.cs
@@ -1,11 +1,25 @@
using System;
using System.IO;
+
using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Digests
{
- public class XoodyakDigest : IDigest
+ public sealed class XoodyakDigest
+ : IDigest
{
+ 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 byte[] state;
private int phase;
private MODE mode;
@@ -16,19 +30,11 @@ namespace Org.BouncyCastle.Crypto.Digests
private const int PhaseUp = 2;
private const int NLANES = 12;
private const int NROWS = 3;
- private const int NCOLUMS = 4;
+ private const int NCOLUMNS = 4;
private const int MAXROUNDS = 12;
private const int TAGLEN = 16;
private const int Rhash = 16;
- const int Rkin = 44;
- private readonly uint[] RC = {0x00000058, 0x00000038, 0x000003C0, 0x000000D0, 0x00000120, 0x00000014, 0x00000060,
- 0x0000002C, 0x00000380, 0x000000F0, 0x000001A0, 0x00000012};
- private MemoryStream buffer = new MemoryStream();
- enum MODE
- {
- ModeHash,
- ModeKeyed
- }
+ private readonly MemoryStream buffer = new MemoryStream();
public XoodyakDigest()
{
@@ -38,6 +44,78 @@ namespace Org.BouncyCastle.Crypto.Digests
public string AlgorithmName => "Xoodyak Hash";
+ public int GetDigestSize() => 32;
+
+ public int GetByteLength() => Rabsorb;
+
+ public void Update(byte input)
+ {
+ buffer.WriteByte(input);
+ }
+
+ public void BlockUpdate(byte[] input, int inOff, int inLen)
+ {
+ Check.DataLength(input, inOff, inLen, "input buffer too short");
+
+ buffer.Write(input, inOff, inLen);
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public void BlockUpdate(ReadOnlySpan<byte> input)
+ {
+ buffer.Write(input);
+ }
+#endif
+
+ public int DoFinal(byte[] output, int outOff)
+ {
+ Check.OutputLength(output, outOff, 32, "output buffer is too short");
+
+ byte[] input = buffer.GetBuffer();
+ int inLen = (int)buffer.Length;
+ int inOff = 0;
+ uint Cd = 0x03;
+ int splitLen;
+ do
+ {
+ if (phase != PhaseUp)
+ {
+ Up(null, 0, 0, 0);
+ }
+ splitLen = System.Math.Min(inLen, Rabsorb);
+ Down(input, inOff, splitLen, Cd);
+ Cd = 0;
+ inOff += splitLen;
+ inLen -= splitLen;
+ }
+ while (inLen != 0);
+ Up(output, outOff, TAGLEN, 0x40);
+ Down(null, 0, 0, 0);
+ Up(output, outOff + TAGLEN, TAGLEN, 0);
+ return 32;
+
+ // TODO Reset?
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public int DoFinal(Span<byte> output)
+ {
+ byte[] rv = new byte[32];
+ int rlt = DoFinal(rv, 0);
+ rv.AsSpan(0, 32).CopyTo(output);
+ return rlt;
+ }
+#endif
+
+ public void Reset()
+ {
+ Array.Clear(state, 0, state.Length);
+ phase = PhaseUp;
+ mode = MODE.ModeHash;
+ Rabsorb = Rhash;
+ buffer.SetLength(0);
+ }
+
private void Up(byte[] Yi, int YiOff, int YiLen, uint Cu)
{
if (mode != MODE.ModeHash)
@@ -48,21 +126,21 @@ namespace Org.BouncyCastle.Crypto.Digests
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];
+ uint[] p = new uint[NCOLUMNS];
+ uint[] e = new uint[NCOLUMNS];
for (int i = 0; i < MAXROUNDS; ++i)
{
/* Theta: Column Parity Mixer */
- for (x = 0; x < NCOLUMS; ++x)
+ for (x = 0; x < NCOLUMNS; ++x)
{
p[x] = a[index(x, 0)] ^ a[index(x, 1)] ^ a[index(x, 2)];
}
- for (x = 0; x < NCOLUMS; ++x)
+ for (x = 0; x < NCOLUMNS; ++x)
{
y = p[(x + 3) & 3];
- e[x] = ROTL32(y, 5) ^ ROTL32(y, 14);
+ e[x] = Integers.RotateLeft(y, 5) ^ Integers.RotateLeft(y, 14);
}
- for (x = 0; x < NCOLUMS; ++x)
+ for (x = 0; x < NCOLUMNS; ++x)
{
for (y = 0; y < NROWS; ++y)
{
@@ -70,16 +148,16 @@ namespace Org.BouncyCastle.Crypto.Digests
}
}
/* Rho-west: plane shift */
- for (x = 0; x < NCOLUMS; ++x)
+ for (x = 0; x < NCOLUMNS; ++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);
+ b[index(x, 2)] = Integers.RotateLeft(a[index(x, 2)], 11);
}
/* Iota: round ant */
b[0] ^= RC[i];
/* Chi: non linear layer */
- for (x = 0; x < NCOLUMS; ++x)
+ for (x = 0; x < NCOLUMNS; ++x)
{
for (y = 0; y < NROWS; ++y)
{
@@ -87,11 +165,11 @@ namespace Org.BouncyCastle.Crypto.Digests
}
}
/* Rho-east: plane shift */
- for (x = 0; x < NCOLUMS; ++x)
+ for (x = 0; x < NCOLUMNS; ++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);
+ b[index(x, 1)] = Integers.RotateLeft(a[index(x, 1)], 1);
+ b[index(x, 2)] = Integers.RotateLeft(a[index(x + 2, 2)], 8);
}
Array.Copy(b, 0, a, 0, NLANES);
}
@@ -116,92 +194,7 @@ namespace Org.BouncyCastle.Crypto.Digests
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 void BlockUpdate(byte[] input, int inOff, int inLen)
- {
- if (inOff + inLen > input.Length)
- {
- throw new DataLengthException("input buffer too short");
- }
- buffer.Write(input, inOff, inLen);
- }
-
- public int DoFinal(byte[] output, int outOff)
- {
- if (32 + outOff > output.Length)
- {
- throw new OutputLengthException("output buffer is too short");
- }
- byte[] input = buffer.GetBuffer();
- int inLen = (int)buffer.Length;
- int inOff = 0;
- uint Cd = 0x03;
- int splitLen;
- do
- {
- if (phase != PhaseUp)
- {
- Up(null, 0, 0, 0);
- }
- splitLen = System.Math.Min(inLen, Rabsorb);
- Down(input, inOff, splitLen, Cd);
- Cd = 0;
- inOff += splitLen;
- inLen -= splitLen;
- }
- while (inLen != 0);
- Up(output, outOff, TAGLEN, 0x40);
- Down(null, 0, 0, 0);
- Up(output, outOff + TAGLEN, TAGLEN, 0);
- return 32;
- }
-
- public int GetByteLength()
- {
- throw new NotImplementedException();
- }
-
- public int GetDigestSize()
- {
- return 32;
+ return (((y % NROWS) * NCOLUMNS) + ((x) % NCOLUMNS));
}
-
- public void Reset()
- {
- for (int i = 0; i < state.Length; ++i)
- {
- state[i] = 0;
- }
- phase = PhaseUp;
- mode = MODE.ModeHash;
- Rabsorb = Rhash;
- buffer.SetLength(0);
- }
-
- public void Update(byte input)
- {
- buffer.Write(new byte[] { input }, 0, 1);
- }
-#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
- public int DoFinal(Span<byte> output)
- {
- byte[] rv = new byte[32];
- int rlt = DoFinal(rv, 0);
- rv.AsSpan(0, 32).CopyTo(output);
- return rlt;
- }
-
- public void BlockUpdate(ReadOnlySpan<byte> input)
- {
- buffer.Write(input.ToArray(), 0, input.Length);
- }
-#endif
}
}
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
+}
diff --git a/crypto/test/src/crypto/test/ElephantTest.cs b/crypto/test/src/crypto/test/ElephantTest.cs
index 406be7c6f..7e7e131ab 100644
--- a/crypto/test/src/crypto/test/ElephantTest.cs
+++ b/crypto/test/src/crypto/test/ElephantTest.cs
@@ -270,7 +270,7 @@ namespace Org.BouncyCastle.Crypto.Tests
elephantEngine.DoFinal(mac2, 0);
if (!Arrays.AreEqual(mac1, mac2))
{
- Assert.Fail("mac should match for the same AAD with different ways of inputing");
+ Assert.Fail("mac should match for the same AAD with different ways of inputting");
}
byte[] c2 = new byte[elephantEngine.GetOutputSize(10)];
diff --git a/crypto/test/src/crypto/test/ISAPTest.cs b/crypto/test/src/crypto/test/ISAPTest.cs
index e7b0bd25c..500026bf9 100644
--- a/crypto/test/src/crypto/test/ISAPTest.cs
+++ b/crypto/test/src/crypto/test/ISAPTest.cs
@@ -330,7 +330,7 @@ namespace Org.BouncyCastle.Crypto.Tests
isapEngine.DoFinal(mac2, 0);
if (!Arrays.AreEqual(mac1, mac2))
{
- Assert.Fail("mac should match for the same AAD with different ways of inputing");
+ Assert.Fail("mac should match for the same AAD with different ways of inputting");
}
byte[] c2 = new byte[isapEngine.GetOutputSize(10)];
diff --git a/crypto/test/src/crypto/test/PhotonBeetleTest.cs b/crypto/test/src/crypto/test/PhotonBeetleTest.cs
index 80e34ad4b..cd551432c 100644
--- a/crypto/test/src/crypto/test/PhotonBeetleTest.cs
+++ b/crypto/test/src/crypto/test/PhotonBeetleTest.cs
@@ -310,7 +310,7 @@ namespace Org.BouncyCastle.Crypto.Tests
aeadBlockCipher.DoFinal(mac2, 0);
if (!Arrays.AreEqual(mac1, mac2))
{
- Assert.Fail("mac should match for the same AAD with different ways of inputing");
+ Assert.Fail("mac should match for the same AAD with different ways of inputting");
}
byte[] c2 = new byte[aeadBlockCipher.GetOutputSize(10)];
diff --git a/crypto/test/src/crypto/test/SparkleTest.cs b/crypto/test/src/crypto/test/SparkleTest.cs
index 245a1831c..ea4520226 100644
--- a/crypto/test/src/crypto/test/SparkleTest.cs
+++ b/crypto/test/src/crypto/test/SparkleTest.cs
@@ -324,7 +324,7 @@ namespace Org.BouncyCastle.Crypto.Tests
sparkleEngine.DoFinal(mac2, 0);
if (!Arrays.AreEqual(mac1, mac2))
{
- Assert.Fail("mac should match for the same AAD with different ways of inputing");
+ Assert.Fail("mac should match for the same AAD with different ways of inputting");
}
byte[] c2 = new byte[sparkleEngine.GetOutputSize(10)];
diff --git a/crypto/test/src/crypto/test/XoodyakTest.cs b/crypto/test/src/crypto/test/XoodyakTest.cs
index d8664e82f..b73d998f4 100644
--- a/crypto/test/src/crypto/test/XoodyakTest.cs
+++ b/crypto/test/src/crypto/test/XoodyakTest.cs
@@ -300,7 +300,7 @@ namespace Org.BouncyCastle.Crypto.Tests
xoodyakEngine.DoFinal(mac2, 0);
if (!Arrays.AreEqual(mac1, mac2))
{
- Assert.Fail("mac should match for the same AAD with different ways of inputing");
+ Assert.Fail("mac should match for the same AAD with different ways of inputting");
}
byte[] c2 = new byte[xoodyakEngine.GetOutputSize(10)];
|