diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-02-13 00:34:55 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2023-02-13 00:34:55 +0700 |
commit | f52b9a1ea4b3b1aea3615636d282b119a2e7a05e (patch) | |
tree | 7b41c49bc5cdd3af6f12e8fd33896c5d831601e6 /crypto/src | |
parent | Support explicit blockSize (diff) | |
download | BouncyCastle.NET-ed25519-f52b9a1ea4b3b1aea3615636d282b119a2e7a05e.tar.xz |
Fix/refactor LWC algorithms
Diffstat (limited to 'crypto/src')
-rw-r--r-- | crypto/src/crypto/digests/AsconDigest.cs | 385 | ||||
-rw-r--r-- | crypto/src/crypto/digests/ISAPDigest.cs | 184 | ||||
-rw-r--r-- | crypto/src/crypto/digests/PhotonBeetleDigest.cs | 14 | ||||
-rw-r--r-- | crypto/src/crypto/digests/SparkleDigest.cs | 75 | ||||
-rw-r--r-- | crypto/src/crypto/engines/AsconEngine.cs | 10 | ||||
-rw-r--r-- | crypto/src/crypto/engines/ElephantEngine.cs | 131 | ||||
-rw-r--r-- | crypto/src/crypto/engines/ISAPEngine.cs | 12 | ||||
-rw-r--r-- | crypto/src/crypto/engines/PhotonBeetleEngine.cs | 44 | ||||
-rw-r--r-- | crypto/src/crypto/engines/SparkleEngine.cs | 25 | ||||
-rw-r--r-- | crypto/src/crypto/engines/XoodyakEngine.cs | 42 |
10 files changed, 451 insertions, 471 deletions
diff --git a/crypto/src/crypto/digests/AsconDigest.cs b/crypto/src/crypto/digests/AsconDigest.cs index 2607cddde..343036b99 100644 --- a/crypto/src/crypto/digests/AsconDigest.cs +++ b/crypto/src/crypto/digests/AsconDigest.cs @@ -1,10 +1,15 @@ using System; -using System.IO; +#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER +using System.Runtime.CompilerServices; +#endif + using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests { - public class AsconDigest : IDigest + public sealed class AsconDigest + : IDigest { public enum AsconParameters { @@ -14,236 +19,266 @@ namespace Org.BouncyCastle.Crypto.Digests AsconXofA, } - public AsconDigest(AsconParameters parameters) - { - asconParameters = parameters; - switch (parameters) - { - case AsconParameters.AsconHash: - ASCON_PB_ROUNDS = 12; - algorithmName = "Ascon-Hash"; - break; - case AsconParameters.AsconHashA: - ASCON_PB_ROUNDS = 8; - algorithmName = "Ascon-HashA"; - break; - case AsconParameters.AsconXof: - ASCON_PB_ROUNDS = 12; - algorithmName = "Ascon-Xof"; - break; - case AsconParameters.AsconXofA: - ASCON_PB_ROUNDS = 8; - algorithmName = "Ascon-XofA"; - break; - default: - throw new ArgumentException("Invalid parameter settings for Ascon Hash"); - } - Reset(); - } - - private AsconParameters asconParameters; + private readonly AsconParameters m_asconParameters; + private readonly int ASCON_PB_ROUNDS; - private string algorithmName; - - private readonly MemoryStream buffer = new MemoryStream(); private ulong x0; private ulong x1; private ulong x2; private ulong x3; private ulong x4; - private readonly int CRYPTO_BYTES = 32; - private int ASCON_PB_ROUNDS; - - public string AlgorithmName => algorithmName; - private ulong ROR(ulong x, int n) - { - return x >> n | x << (64 - n); - } + private readonly byte[] m_buf = new byte[8]; + private int m_bufPos = 0; - private void ROUND(ulong C) + public AsconDigest(AsconParameters parameters) { - 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 ^ ROR(t0, 19) ^ ROR(t0, 28); - x1 = t1 ^ ROR(t1, 39) ^ ROR(t1, 61); - x2 = ~(t2 ^ ROR(t2, 1) ^ ROR(t2, 6)); - x3 = t3 ^ ROR(t3, 10) ^ ROR(t3, 17); - x4 = t4 ^ ROR(t4, 7) ^ ROR(t4, 41); + m_asconParameters = parameters; + switch (parameters) + { + case AsconParameters.AsconHash: + ASCON_PB_ROUNDS = 12; + break; + case AsconParameters.AsconHashA: + ASCON_PB_ROUNDS = 8; + break; + case AsconParameters.AsconXof: + ASCON_PB_ROUNDS = 12; + break; + case AsconParameters.AsconXofA: + ASCON_PB_ROUNDS = 8; + break; + default: + throw new ArgumentException("Invalid parameter settings for Ascon Hash"); + } + Reset(); } - private void P(int nr) + public string AlgorithmName { - if (nr == 12) + get { - ROUND(0xf0UL); - ROUND(0xe1UL); - ROUND(0xd2UL); - ROUND(0xc3UL); + switch (m_asconParameters) + { + case AsconParameters.AsconHash: return "Ascon-Hash"; + case AsconParameters.AsconHashA: return "Ascon-HashA"; + case AsconParameters.AsconXof: return "Ascon-Xof"; + case AsconParameters.AsconXofA: return "Ascon-XofA"; + default: throw new InvalidOperationException(); + } } - if (nr >= 8) - { - ROUND(0xb4UL); - ROUND(0xa5UL); - } - ROUND(0x96UL); - ROUND(0x87UL); - ROUND(0x78UL); - ROUND(0x69UL); - ROUND(0x5aUL); - ROUND(0x4bUL); } - private ulong PAD(int i) - { - return 0x80UL << (56 - (i << 3)); - } + public int GetDigestSize() => 32; + + public int GetByteLength() => 8; - private ulong LOADBYTES(byte[] bytes, int inOff, int n) + public void Update(byte input) { - ulong x = 0; - for (int i = 0; i < n; ++i) + m_buf[m_bufPos] = input; + if (++m_bufPos == 8) { - x |= (bytes[i + inOff] & 0xFFUL) << ((7 - i) << 3); + x0 ^= Pack.BE_To_UInt64(m_buf, 0); + P(ASCON_PB_ROUNDS); + m_bufPos = 0; } - return x; } - private void STOREBYTES(byte[] bytes, int inOff, ulong w, int n) + public void BlockUpdate(byte[] input, int inOff, int inLen) { - for (int i = 0; i < n; ++i) + Check.DataLength(input, inOff, inLen, "input buffer too short"); + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + BlockUpdate(input.AsSpan(inOff, inLen)); +#else + if (inLen < 1) + return; + + int available = 8 - m_bufPos; + if (inLen < available) { - bytes[i + inOff] = (byte)(w >> ((7 - i) << 3)); + Array.Copy(input, inOff, m_buf, m_bufPos, inLen); + m_bufPos += inLen; + return; } - } - public int GetDigestSize() - { - return CRYPTO_BYTES; - } + int inPos = 0; + if (m_bufPos > 0) + { + Array.Copy(input, inOff, m_buf, m_bufPos, available); + inPos += available; + x0 ^= Pack.BE_To_UInt64(m_buf, 0); + P(ASCON_PB_ROUNDS); + } + int remaining; + while ((remaining = inLen - inPos) >= 8) + { + x0 ^= Pack.BE_To_UInt64(input, inOff + inPos); + P(ASCON_PB_ROUNDS); + inPos += 8; + } - public void Update(byte input) - { - buffer.Write(new byte[] { input }, 0, 1); + Array.Copy(input, inOff + inPos, m_buf, 0, remaining); + m_bufPos = remaining; +#endif } - - 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) + int available = 8 - m_bufPos; + if (input.Length < available) { - throw new DataLengthException("input buffer too ushort"); + input.CopyTo(m_buf.AsSpan(m_bufPos)); + m_bufPos += input.Length; + return; } - buffer.Write(input, inOff, len); - } - - public int DoFinal(byte[] output, int outOff) - { - if (CRYPTO_BYTES + outOff > output.Length) + if (m_bufPos > 0) { - throw new OutputLengthException("output buffer is too ushort"); + input[..available].CopyTo(m_buf.AsSpan(m_bufPos)); + x0 ^= Pack.BE_To_UInt64(m_buf); + P(ASCON_PB_ROUNDS); + input = input[available..]; } - byte[] input = buffer.GetBuffer(); - int len = (int)buffer.Length; - int inOff = 0; - ///* initialize */ - //x0 = ASCON_IV; - //x1 = 0; - //x2 = 0; - //x3 = 0; - //x4 = 0; - //P(ASCON_PA_ROUNDS); - /* absorb full plaintext blocks */ - int ASCON_HASH_RATE = 8; - while (len >= ASCON_HASH_RATE) + + while (input.Length >= 8) { - x0 ^= LOADBYTES(input, inOff, 8); + x0 ^= Pack.BE_To_UInt64(input); P(ASCON_PB_ROUNDS); - inOff += ASCON_HASH_RATE; - len -= ASCON_HASH_RATE; + input = input[8..]; } - /* absorb readonly plaintext block */ - x0 ^= LOADBYTES(input, inOff, len); - x0 ^= PAD(len); - int ASCON_PA_ROUNDS = 12; - P(ASCON_PA_ROUNDS); - /* squeeze full output blocks */ - len = CRYPTO_BYTES; - while (len > ASCON_HASH_RATE) + + input.CopyTo(m_buf); + m_bufPos = input.Length; + } +#endif + + public int DoFinal(byte[] output, int outOff) + { +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return DoFinal(output.AsSpan(outOff)); +#else + Check.OutputLength(output, outOff, 32, "output buffer is too short"); + + m_buf[m_bufPos] = 0x80; + x0 ^= Pack.BE_To_UInt64(m_buf, 0) & (ulong.MaxValue << (56 - (m_bufPos << 3))); + + P(12); + Pack.UInt64_To_BE(x0, output, outOff); + + for (int i = 0; i < 3; ++i) { - STOREBYTES(output, outOff, x0, 8); + outOff += 8; + P(ASCON_PB_ROUNDS); - outOff += ASCON_HASH_RATE; - len -= ASCON_HASH_RATE; + Pack.UInt64_To_BE(x0, output, outOff); } - /* squeeze readonly output block */ - STOREBYTES(output, outOff, x0, len); + Reset(); - return CRYPTO_BYTES; + return 32; +#endif } - - public void Reset() +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int DoFinal(Span<byte> output) { - buffer.SetLength(0); - /* initialize */ - switch (asconParameters) + Check.OutputLength(output, 32, "output buffer is too short"); + + m_buf[m_bufPos] = 0x80; + x0 ^= Pack.BE_To_UInt64(m_buf) & (ulong.MaxValue << (56 - (m_bufPos << 3))); + + P(12); + Pack.UInt64_To_BE(x0, output); + + for (int i = 0; i < 3; ++i) { - case AsconParameters.AsconHashA: - x0 = 92044056785660070UL; - x1 = 8326807761760157607UL; - x2 = 3371194088139667532UL; - x3 = 15489749720654559101UL; - x4 = 11618234402860862855UL; - break; - case AsconParameters.AsconHash: - x0 = 17191252062196199485UL; - x1 = 10066134719181819906UL; - x2 = 13009371945472744034UL; - x3 = 4834782570098516968UL; - x4 = 3787428097924915520UL; - break; - case AsconParameters.AsconXof: - x0 = 13077933504456348694UL; - x1 = 3121280575360345120UL; - x2 = 7395939140700676632UL; - x3 = 6533890155656471820UL; - x4 = 5710016986865767350UL; - break; - case AsconParameters.AsconXofA: - x0 = 4940560291654768690UL; - x1 = 14811614245468591410UL; - x2 = 17849209150987444521UL; - x3 = 2623493988082852443UL; - x4 = 12162917349548726079UL; - break; + output = output[8..]; + + P(ASCON_PB_ROUNDS); + Pack.UInt64_To_BE(x0, output); } + + Reset(); + return 32; } +#endif - public int GetByteLength() + public void Reset() { - throw new NotImplementedException(); + Array.Clear(m_buf, 0, m_buf.Length); + m_bufPos = 0; + + switch (m_asconParameters) + { + case AsconParameters.AsconHashA: + x0 = 92044056785660070UL; + x1 = 8326807761760157607UL; + x2 = 3371194088139667532UL; + x3 = 15489749720654559101UL; + x4 = 11618234402860862855UL; + break; + case AsconParameters.AsconHash: + x0 = 17191252062196199485UL; + x1 = 10066134719181819906UL; + x2 = 13009371945472744034UL; + x3 = 4834782570098516968UL; + x4 = 3787428097924915520UL; + break; + case AsconParameters.AsconXof: + x0 = 13077933504456348694UL; + x1 = 3121280575360345120UL; + x2 = 7395939140700676632UL; + x3 = 6533890155656471820UL; + x4 = 5710016986865767350UL; + break; + case AsconParameters.AsconXofA: + x0 = 4940560291654768690UL; + x1 = 14811614245468591410UL; + x2 = 17849209150987444521UL; + x3 = 2623493988082852443UL; + x4 = 12162917349548726079UL; + break; + default: + throw new InvalidOperationException(); + } } -#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER - public int DoFinal(Span<byte> output) + private void P(int nr) { - byte[] rv = new byte[32]; - int rlt = DoFinal(rv, 0); - rv.AsSpan(0, 32).CopyTo(output); - return rlt; + if (nr == 12) + { + ROUND(0xf0UL); + ROUND(0xe1UL); + ROUND(0xd2UL); + ROUND(0xc3UL); + } + ROUND(0xb4UL); + ROUND(0xa5UL); + ROUND(0x96UL); + ROUND(0x87UL); + ROUND(0x78UL); + ROUND(0x69UL); + ROUND(0x5aUL); + ROUND(0x4bUL); } - public void BlockUpdate(ReadOnlySpan<byte> input) +#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#endif + private void ROUND(ulong C) { - buffer.Write(input.ToArray(), 0, input.Length); + 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); } -#endif } } - diff --git a/crypto/src/crypto/digests/ISAPDigest.cs b/crypto/src/crypto/digests/ISAPDigest.cs index 3be28e4e2..348242e6e 100644 --- a/crypto/src/crypto/digests/ISAPDigest.cs +++ b/crypto/src/crypto/digests/ISAPDigest.cs @@ -1,149 +1,165 @@ using System; using System.IO; +#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER +using System.Runtime.CompilerServices; +#endif + using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Digests { - public class ISAPDigest : IDigest + public sealed class IsapDigest + : IDigest { private ulong x0, x1, x2, x3, x4; private ulong t0, t1, t2, t3, t4; private MemoryStream buffer = new MemoryStream(); - 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); - x0 = t0 ^ ROTR(t0, 19) ^ ROTR(t0, 28); - x1 = t1 ^ ROTR(t1, 39) ^ ROTR(t1, 61); - x2 = ~(t2 ^ ROTR(t2, 1) ^ ROTR(t2, 6)); - x3 = t3 ^ ROTR(t3, 10) ^ ROTR(t3, 17); - x4 = t4 ^ ROTR(t4, 7) ^ ROTR(t4, 41); - } - - private void P12() - { - ROUND(0xf0); - ROUND(0xe1); - ROUND(0xd2); - ROUND(0xc3); - ROUND(0xb4); - ROUND(0xa5); - ROUND(0x96); - ROUND(0x87); - ROUND(0x78); - ROUND(0x69); - ROUND(0x5a); - ROUND(0x4b); - } + public string AlgorithmName => "ISAP Hash"; - private ulong ROTR(ulong x, int n) - { - return (x >> n) | (x << (64 - n)); - } + public int GetDigestSize() => 32; - protected ulong U64BIG(ulong x) - { - return ((ROTR(x, 8) & (0xFF000000FF000000UL)) | (ROTR(x, 24) & (0x00FF000000FF0000UL)) | - (ROTR(x, 40) & (0x0000FF000000FF00UL)) | (ROTR(x, 56) & (0x000000FF000000FFUL))); - } + public int GetByteLength() => 8; - public string AlgorithmName + public void Update(byte input) { - get { return "ISAP Hash"; } + buffer.WriteByte(input); } public void BlockUpdate(byte[] input, int inOff, int inLen) { - if (inOff + inLen > input.Length) - { - throw new DataLengthException("input buffer too short"); - } + 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.ToArray(), 0, input.Length); - } - - public int DoFinal(Span<byte> output) - { - byte[] rv = new byte[32]; - int rlt = DoFinal(rv, 0); - rv.AsSpan(0, 32).CopyTo(output); - return rlt; + buffer.Write(input); } - #endif public int DoFinal(byte[] output, int outOff) { - if (32 + outOff > output.Length) - { - throw new OutputLengthException("output buffer is too short"); - } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + return DoFinal(output.AsSpan(outOff)); +#else + Check.OutputLength(output, outOff, 32, "output buffer is too short"); + t0 = t1 = t2 = t3 = t4 = 0; + /* init state */ x0 = 17191252062196199485UL; x1 = 10066134719181819906UL; x2 = 13009371945472744034UL; x3 = 4834782570098516968UL; x4 = 3787428097924915520UL; - /* absorb */ + byte[] input = buffer.GetBuffer(); - int len = (int)buffer.Length; - ulong[] in64 = new ulong[len >> 3]; - Pack.LE_To_UInt64(input, 0, in64, 0, in64.Length); - int idx = 0; + int len = Convert.ToInt32(buffer.Length); + + int pos = 0; while (len >= 8) { - x0 ^= U64BIG(in64[idx++]); - P12(); + x0 ^= Pack.BE_To_UInt64(input, pos); + pos += 8; len -= 8; + P12(); } - /* absorb final input block */ x0 ^= 0x80UL << ((7 - len) << 3); - while (len > 0) + if (len > 0) { - x0 ^= (input[(idx << 3) + --len] & 0xFFUL) << ((7 - len) << 3); + x0 ^= Pack.BE_To_UInt64_High(input, pos, len); } - P12(); - // squeeze - ulong[] out64 = new ulong[4]; - for (idx = 0; idx < 3; ++idx) + + for (int i = 0; i < 4; ++i) { - out64[idx] = U64BIG(x0); P12(); + Pack.UInt64_To_BE(x0, output, outOff + (i << 3)); } - /* squeeze final output block */ - out64[idx] = U64BIG(x0); - Pack.UInt64_To_LE(out64, output, outOff); + return 32; +#endif } - public int GetByteLength() +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + public int DoFinal(Span<byte> output) { - throw new NotImplementedException(); - } + Check.OutputLength(output, 32, "output buffer is too short"); + + t0 = t1 = t2 = t3 = t4 = 0; + + /* init state */ + x0 = 17191252062196199485UL; + x1 = 10066134719181819906UL; + x2 = 13009371945472744034UL; + x3 = 4834782570098516968UL; + x4 = 3787428097924915520UL; + + if (!buffer.TryGetBuffer(out var bufferContents)) + throw new UnauthorizedAccessException(); + + var input = bufferContents.AsSpan(); + while (input.Length >= 8) + { + x0 ^= Pack.BE_To_UInt64(input); + input = input[8..]; + P12(); + } + x0 ^= 0x80UL << ((7 - input.Length) << 3); + if (!input.IsEmpty) + { + x0 ^= Pack.BE_To_UInt64_High(input); + } + + for (int i = 0; i < 4; ++i) + { + P12(); + Pack.UInt64_To_BE(x0, output[(i << 3)..]); + } - public int GetDigestSize() - { return 32; } +#endif public void Reset() { buffer.SetLength(0); } - public void Update(byte input) + private void P12() { - buffer.Write(new byte[] { input }, 0, 1); + ROUND(0xf0); + ROUND(0xe1); + ROUND(0xd2); + ROUND(0xc3); + ROUND(0xb4); + ROUND(0xa5); + ROUND(0x96); + ROUND(0x87); + ROUND(0x78); + ROUND(0x69); + ROUND(0x5a); + ROUND(0x4b); + } + +#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] +#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); + 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); } } } diff --git a/crypto/src/crypto/digests/PhotonBeetleDigest.cs b/crypto/src/crypto/digests/PhotonBeetleDigest.cs index 13b30e025..1af8aee2c 100644 --- a/crypto/src/crypto/digests/PhotonBeetleDigest.cs +++ b/crypto/src/crypto/digests/PhotonBeetleDigest.cs @@ -67,19 +67,19 @@ namespace Org.BouncyCastle.Crypto.Digests public String AlgorithmName => "Photon-Beetle Hash"; + public int GetDigestSize() => TAG_INBYTES; - public int GetDigestSize() + public int GetByteLength() { - return TAG_INBYTES; + // TODO + throw new NotImplementedException(); } - public void Update(byte input) { - buffer.Write(new byte[] { input }, 0, 1); + buffer.WriteByte(input); } - public void BlockUpdate(byte[] input, int inOff, int len) { if ((inOff + len) > input.Length) @@ -223,10 +223,6 @@ namespace Org.BouncyCastle.Crypto.Digests } } - public int GetByteLength() - { - throw new NotImplementedException(); - } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER public int DoFinal(Span<byte> output) diff --git a/crypto/src/crypto/digests/SparkleDigest.cs b/crypto/src/crypto/digests/SparkleDigest.cs index b8134dd91..ad558effc 100644 --- a/crypto/src/crypto/digests/SparkleDigest.cs +++ b/crypto/src/crypto/digests/SparkleDigest.cs @@ -1,23 +1,26 @@ using System; using System.IO; + using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; -/** - * Sparkle v1.2, based on the current round 3 submission, https://sparkle-lwc.github.io/ - * Reference C implementation: https://github.com/cryptolu/sparkle - * Specification: https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/sparkle-spec-final.pdf - */ - namespace Org.BouncyCastle.Crypto.Digests { - public class SparkleDigest : IDigest + /// <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 class SparkleDigest + : IDigest { public enum SparkleParameters { ESCH256, ESCH384 } + private string algorithmName; private readonly uint[] state; private MemoryStream message = new MemoryStream(); @@ -36,22 +39,22 @@ namespace Org.BouncyCastle.Crypto.Digests int SPARKLE_RATE = 128; switch (sparkleParameters) { - case SparkleParameters.ESCH256: - ESCH_DIGEST_LEN = 256; - SPARKLE_STATE = 384; - SPARKLE_STEPS_SLIM = 7; - SPARKLE_STEPS_BIG = 11; - algorithmName = "ESCH-256"; - break; - case SparkleParameters.ESCH384: - ESCH_DIGEST_LEN = 384; - SPARKLE_STATE = 512; - SPARKLE_STEPS_SLIM = 8; - SPARKLE_STEPS_BIG = 12; - algorithmName = "ESCH-384"; - break; - default: - throw new ArgumentException("Invalid definition of SCHWAEMM instance"); + case SparkleParameters.ESCH256: + ESCH_DIGEST_LEN = 256; + SPARKLE_STATE = 384; + SPARKLE_STEPS_SLIM = 7; + SPARKLE_STEPS_BIG = 11; + algorithmName = "ESCH-256"; + break; + case SparkleParameters.ESCH384: + ESCH_DIGEST_LEN = 384; + SPARKLE_STATE = 512; + SPARKLE_STEPS_SLIM = 8; + SPARKLE_STEPS_BIG = 12; + algorithmName = "ESCH-384"; + break; + default: + throw new ArgumentException("Invalid definition of SCHWAEMM instance"); } STATE_BRANS = SPARKLE_STATE >> 6; STATE_WORDS = SPARKLE_STATE >> 5; @@ -61,14 +64,9 @@ namespace Org.BouncyCastle.Crypto.Digests state = new uint[STATE_WORDS]; } - 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, @@ -86,17 +84,17 @@ namespace Org.BouncyCastle.Crypto.Digests 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 @@ -226,7 +224,6 @@ namespace Org.BouncyCastle.Crypto.Digests public string AlgorithmName => algorithmName; - public void Update(byte input) { message.Write(new byte[] { input }, 0, 1); @@ -240,7 +237,7 @@ namespace Org.BouncyCastle.Crypto.Digests public int GetByteLength() { - return STATE_WORDS; + return RATE_BYTES; } #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER @@ -258,7 +255,5 @@ namespace Org.BouncyCastle.Crypto.Digests return DIGEST_BYTES; } #endif - } } - diff --git a/crypto/src/crypto/engines/AsconEngine.cs b/crypto/src/crypto/engines/AsconEngine.cs index 21607483d..e8848c3d8 100644 --- a/crypto/src/crypto/engines/AsconEngine.cs +++ b/crypto/src/crypto/engines/AsconEngine.cs @@ -224,7 +224,7 @@ namespace Org.BouncyCastle.Crypto.Engines return DoFinal(outBytes.AsSpan(outOff)); #else if (!initialised) - throw new ArgumentException("Need call init function before encryption/decryption"); + throw new ArgumentException("Need to call Init before encryption/decryption"); if (!aadFinished) { @@ -265,7 +265,7 @@ namespace Org.BouncyCastle.Crypto.Engines Reset(true); if (result != 0UL) - throw new ArgumentException("Mac does not match"); + throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed"); return len; } @@ -276,7 +276,7 @@ namespace Org.BouncyCastle.Crypto.Engines public int DoFinal(Span<byte> output) { if (!initialised) - throw new ArgumentException("Need call init function before encryption/decryption"); + throw new ArgumentException("Need to call Init before encryption/decryption"); if (!aadFinished) { @@ -317,7 +317,7 @@ namespace Org.BouncyCastle.Crypto.Engines Reset(true); if (result != 0UL) - throw new ArgumentException("Mac does not match"); + throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed"); return len; } @@ -838,7 +838,7 @@ namespace Org.BouncyCastle.Crypto.Engines private void Reset(bool clearMac) { if (!initialised) - throw new ArgumentException("Need call init function before encryption/decryption"); + throw new ArgumentException("Need to call Init function before encryption/decryption"); x0 = x1 = x2 = x3 = x4 = 0; ascon_aeadinit(); diff --git a/crypto/src/crypto/engines/ElephantEngine.cs b/crypto/src/crypto/engines/ElephantEngine.cs index d5f05f658..4e0e3216d 100644 --- a/crypto/src/crypto/engines/ElephantEngine.cs +++ b/crypto/src/crypto/engines/ElephantEngine.cs @@ -70,32 +70,32 @@ namespace Org.BouncyCastle.Crypto.Engines { 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"); + 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; @@ -316,40 +316,25 @@ namespace Org.BouncyCastle.Crypto.Engines } } - - public void Init(bool forEncryption, ICipherParameters param) { this.forEncryption = forEncryption; - if (!(param is ParametersWithIV)) - { - throw new ArgumentException( - "Elephant init parameters must include an IV"); - } - ParametersWithIV ivParams = (ParametersWithIV)param; + 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"); - } + throw new ArgumentException("Elephant requires exactly 12 bytes of IV"); - if (!(ivParams.Parameters is KeyParameter)) - { - throw new ArgumentException( - "Elephant init parameters must include a key"); - } + if (!(ivParams.Parameters is KeyParameter key)) + throw new ArgumentException("Elephant init parameters must include a key"); - KeyParameter key = (KeyParameter)ivParams.Parameters; byte[] k = key.GetKey(); if (k.Length != 16) - { - throw new ArgumentException( - "Elephant key must be 128 bits long"); - } + 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); @@ -365,44 +350,35 @@ namespace Org.BouncyCastle.Crypto.Engines public void ProcessAadByte(byte input) { - aadData.Write(new byte[] { input }, 0, 1); + aadData.WriteByte(input); } - - public void ProcessAadBytes(byte[] input, int inOff, int len) + public void ProcessAadBytes(byte[] inBytes, int inOff, int len) { - if (inOff + len > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - aadData.Write(input, inOff, len); - } + Check.DataLength(inBytes, inOff, len, "input buffer too short"); + aadData.Write(inBytes, inOff, len); + } - public int ProcessByte(byte input, byte[] output, int outOff) + public int ProcessByte(byte input, byte[] outBytes, int outOff) { - message.Write(new byte[] { input }, 0, 1); + message.Write(new byte[]{ input }, 0, 1); return 0; } - - 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 (inOff + len > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - message.Write(input, inOff, len); + 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 call init function before encryption/decryption"); - } + 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)) @@ -493,37 +469,28 @@ namespace Org.BouncyCastle.Crypto.Engines } else { - for (int i = 0; i < CRYPTO_ABYTES; ++i) - { - if (tag_buffer[i] != m[mlen + i]) - { - throw new ArgumentException("Mac does not match"); - } - } + 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) { return len; } - public int GetOutputSize(int len) { return len + CRYPTO_ABYTES; } - public void Reset() { reset(true); @@ -547,7 +514,7 @@ namespace Org.BouncyCastle.Crypto.Engines public int ProcessByte(byte input, Span<byte> output) { - message.Write(new byte[] { input }); + message.Write(new byte[]{ input }); return 0; } diff --git a/crypto/src/crypto/engines/ISAPEngine.cs b/crypto/src/crypto/engines/ISAPEngine.cs index 8be5a79b2..7ef629d1b 100644 --- a/crypto/src/crypto/engines/ISAPEngine.cs +++ b/crypto/src/crypto/engines/ISAPEngine.cs @@ -921,7 +921,7 @@ namespace Org.BouncyCastle.Crypto.Engines return DoFinal(outBytes.AsSpan(outOff)); #else if (!initialised) - throw new ArgumentException("Need call init function before encryption/decryption"); + throw new ArgumentException("Need to call Init before encryption/decryption"); byte[] aad = aadData.GetBuffer(); byte[] msg = message.GetBuffer(); @@ -949,7 +949,8 @@ namespace Org.BouncyCastle.Crypto.Engines ISAPAEAD.isap_mac(aad, aadLen, msg, outLen, mac, 0); ISAPAEAD.reset(); if (!Arrays.FixedTimeEquals(16, mac, 0, msg, outLen)) - throw new ArgumentException("Mac does not match"); + throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed"); + ISAPAEAD.isap_enc(msg, 0, outLen, outBytes, outOff); } return outLen; @@ -960,7 +961,7 @@ namespace Org.BouncyCastle.Crypto.Engines public int DoFinal(Span<byte> output) { if (!initialised) - throw new ArgumentException("Need call init function before encryption/decryption"); + throw new ArgumentException("Need to call Init before encryption/decryption"); byte[] aad = aadData.GetBuffer(); byte[] msg = message.GetBuffer(); @@ -988,7 +989,8 @@ namespace Org.BouncyCastle.Crypto.Engines ISAPAEAD.isap_mac(aad, aadLen, msg, outLen, mac, 0); ISAPAEAD.reset(); if (!Arrays.FixedTimeEquals(16, mac, 0, msg, outLen)) - throw new ArgumentException("Mac does not match"); + throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed"); + ISAPAEAD.isap_enc(msg.AsSpan(0, outLen), output); } return outLen; @@ -1022,7 +1024,7 @@ namespace Org.BouncyCastle.Crypto.Engines public void Reset() { if (!initialised) - throw new ArgumentException("Need call init function before encryption/decryption"); + throw new ArgumentException("Need to call Init before encryption/decryption"); aadData.SetLength(0); ISAPAEAD.reset(); diff --git a/crypto/src/crypto/engines/PhotonBeetleEngine.cs b/crypto/src/crypto/engines/PhotonBeetleEngine.cs index 0d5728a76..e593bb6f5 100644 --- a/crypto/src/crypto/engines/PhotonBeetleEngine.cs +++ b/crypto/src/crypto/engines/PhotonBeetleEngine.cs @@ -3,6 +3,7 @@ using System.IO; using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Crypto.Engines { @@ -150,37 +151,32 @@ namespace Org.BouncyCastle.Crypto.Engines aadData.Write(new byte[] { input }, 0, 1); } - public void ProcessAadBytes(byte[] input, int inOff, int len) + public void ProcessAadBytes(byte[] inBytes, int inOff, int len) { - if (inOff + len > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - aadData.Write(input, inOff, len); + Check.DataLength(inBytes, inOff, len, "input buffer too short"); + + aadData.Write(inBytes, inOff, len); } - public int ProcessByte(byte input, byte[] output, int outOff) + public int ProcessByte(byte input, byte[] outBytes, int outOff) { - message.Write(new byte[] { input }, 0, 1); + message.WriteByte(input); return 0; } - 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 (inOff + len > input.Length) - { - throw new DataLengthException("input buffer too short"); - } - message.Write(input, inOff, len); + 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 call init function before encryption/decryption"); - } + throw new ArgumentException("Need to call Init before encryption/decryption"); + reset(true); } @@ -323,9 +319,8 @@ namespace Org.BouncyCastle.Crypto.Engines public int DoFinal(byte[] output, int outOff) { if (!initialised) - { - throw new ArgumentException("Need call init function before encryption/decryption"); - } + 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)) @@ -392,13 +387,8 @@ namespace Org.BouncyCastle.Crypto.Engines } else { - for (i = 0; i < TAG_INBYTES; ++i) - { - if (T[i] != input[len + i]) - { - throw new ArgumentException("Mac does not match"); - } - } + if (!Arrays.FixedTimeEquals(TAG_INBYTES, T, 0, input, len)) + throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed"); } reset(false); return len; diff --git a/crypto/src/crypto/engines/SparkleEngine.cs b/crypto/src/crypto/engines/SparkleEngine.cs index bbdce7ef8..63e400d4c 100644 --- a/crypto/src/crypto/engines/SparkleEngine.cs +++ b/crypto/src/crypto/engines/SparkleEngine.cs @@ -1,19 +1,21 @@ using System; using System.IO; + using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Crypto.Utilities; using Org.BouncyCastle.Utilities; -/** - * Sparkle v1.2, based on the current round 3 submission, https://sparkle-lwc.github.io/ - * Reference C implementation: https://github.com/cryptolu/sparkle - * Specification: https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/sparkle-spec-final.pdf - */ - namespace Org.BouncyCastle.Crypto.Engines { - public class SparkleEngine : IAeadBlockCipher + /// <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 class SparkleEngine + : IAeadBlockCipher { public enum SparkleParameters { @@ -481,13 +483,8 @@ namespace Org.BouncyCastle.Crypto.Engines } else { - for (i = 0; i < TAG_BYTES; ++i) - { - if (tag[i] != input[inlen + i]) - { - throw new ArgumentException(algorithmName + " mac does not match"); - } - } + if (!Arrays.FixedTimeEquals(TAG_BYTES, tag, 0, input, inlen)) + throw new InvalidCipherTextException("mac check in " + AlgorithmName + " failed"); } reset(false); return inlen; diff --git a/crypto/src/crypto/engines/XoodyakEngine.cs b/crypto/src/crypto/engines/XoodyakEngine.cs index caf49e53c..e0263272e 100644 --- a/crypto/src/crypto/engines/XoodyakEngine.cs +++ b/crypto/src/crypto/engines/XoodyakEngine.cs @@ -126,27 +126,20 @@ namespace Org.BouncyCastle.Crypto.Engines public int ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff) { if (!initialised) - { - throw new ArgumentException("Need call init function before encryption/decryption"); - } + throw new ArgumentException("Need to call Init before encryption/decryption"); + if (mode != MODE.ModeKeyed) - { throw new ArgumentException("Xoodyak has not been initialised"); - } - if (inOff + len > input.Length) - { - throw new DataLengthException("input buffer too short"); - } + + Check.DataLength(input, inOff, len, "input buffer too short"); + message.Write(input, inOff, len); int blockLen = (int)message.Length - (forEncryption ? 0 : TAGLEN); if (blockLen >= GetBlockSize()) { byte[] blocks = message.GetBuffer(); len = blockLen / GetBlockSize() * GetBlockSize(); - if (len + outOff > output.Length) - { - throw new OutputLengthException("output buffer is too short"); - } + Check.OutputLength(output, outOff, len, "output buffer is too short"); processAAD(); encrypt(blocks, 0, len, output, outOff); int messageLen = (int)message.Length; @@ -196,9 +189,7 @@ namespace Org.BouncyCastle.Crypto.Engines public int DoFinal(byte[] output, int outOff) { if (!initialised) - { - throw new ArgumentException("Need call init function before encryption/decryption"); - } + throw new ArgumentException("Need to call Init before encryption/decryption"); byte[] blocks = message.GetBuffer(); int len = (int)message.Length; @@ -225,43 +216,34 @@ namespace Org.BouncyCastle.Crypto.Engines encrypt(blocks, 0, inOff, output, outOff); tag = new byte[TAGLEN]; Up(tag, TAGLEN, 0x40); - for (int i = 0; i < TAGLEN; ++i) - { - if (tag[i] != blocks[inOff++]) - { - throw new ArgumentException("Mac does not match"); - } - } + + 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) { return len; } - public int GetOutputSize(int len) { return len + TAGLEN; } - public void Reset() { if (!initialised) - { - throw new ArgumentException("Need call init function before encryption/decryption"); - } + throw new ArgumentException("Need to call Init before encryption/decryption"); + reset(true); } |