diff --git a/crypto/src/crypto/engines/AsconEngine.cs b/crypto/src/crypto/engines/AsconEngine.cs
index 4bda8a02a..fc38764d1 100644
--- a/crypto/src/crypto/engines/AsconEngine.cs
+++ b/crypto/src/crypto/engines/AsconEngine.cs
@@ -99,15 +99,9 @@ namespace Org.BouncyCastle.Crypto.Engines
m_buf = new byte[m_bufferSizeDecrypt];
}
- public int GetKeyBytesSize()
- {
- return CRYPTO_KEYBYTES;
- }
+ public int GetKeyBytesSize() => CRYPTO_KEYBYTES;
- public int GetIVBytesSize()
- {
- return CRYPTO_ABYTES;
- }
+ public int GetIVBytesSize() => CRYPTO_ABYTES;
public string AlgorithmName => algorithmName;
@@ -1060,6 +1054,9 @@ namespace Org.BouncyCastle.Crypto.Engines
}
}
+#if NETSTANDARD1_0_OR_GREATER || NETCOREAPP1_0_OR_GREATER
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+#endif
private static ulong PAD(int i)
{
return 0x8000000000000000UL >> (i << 3);
diff --git a/crypto/test/src/crypto/test/AsconTest.cs b/crypto/test/src/crypto/test/AsconTest.cs
index 313f7d45e..eabf7e043 100644
--- a/crypto/test/src/crypto/test/AsconTest.cs
+++ b/crypto/test/src/crypto/test/AsconTest.cs
@@ -15,164 +15,347 @@ namespace Org.BouncyCastle.Crypto.Tests
{
[TestFixture]
public class AsconTest
- : SimpleTest
{
- public override string Name => "ASCON";
+ [Test, Explicit]
+ public void BenchDigest_AsconHash()
+ {
+ ImplBenchDigest(AsconDigest.AsconParameters.AsconHash);
+ }
+
+ [Test, Explicit]
+ public void BenchDigest_AsconHashA()
+ {
+ ImplBenchDigest(AsconDigest.AsconParameters.AsconHashA);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineAuth_ascon128()
+ {
+ ImplBenchEngineAuth(AsconEngine.AsconParameters.ascon128);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineAuth_ascon128a()
+ {
+ ImplBenchEngineAuth(AsconEngine.AsconParameters.ascon128a);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineAuth_ascon80pq()
+ {
+ ImplBenchEngineAuth(AsconEngine.AsconParameters.ascon80pq);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineDecrypt_ascon128()
+ {
+ ImplBenchEngineCrypt(AsconEngine.AsconParameters.ascon128, false);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineDecrypt_ascon128a()
+ {
+ ImplBenchEngineCrypt(AsconEngine.AsconParameters.ascon128a, false);
+ }
[Test, Explicit]
- public void BenchAuth80pq()
+ public void BenchEngineDecrypt_ascon80pq()
+ {
+ ImplBenchEngineCrypt(AsconEngine.AsconParameters.ascon80pq, false);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineEncrypt_ascon128()
+ {
+ ImplBenchEngineCrypt(AsconEngine.AsconParameters.ascon128, true);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineEncrypt_ascon128a()
+ {
+ ImplBenchEngineCrypt(AsconEngine.AsconParameters.ascon128a, true);
+ }
+
+ [Test, Explicit]
+ public void BenchEngineEncrypt_ascon80pq()
+ {
+ ImplBenchEngineCrypt(AsconEngine.AsconParameters.ascon80pq, true);
+ }
+
+ [Test, Explicit]
+ public void BenchXof_AsconXof()
+ {
+ ImplBenchXof(AsconXof.AsconParameters.AsconXof);
+ }
+
+ [Test, Explicit]
+ public void BenchXof_AsconXofA()
+ {
+ ImplBenchXof(AsconXof.AsconParameters.AsconXofA);
+ }
+
+ [Test]
+ public void TestExceptionsDigest_AsconHash()
+ {
+ ImplTestExceptionsDigest(AsconDigest.AsconParameters.AsconHash);
+ }
+
+ [Test]
+ public void TestExceptionsDigest_AsconHashA()
+ {
+ ImplTestExceptionsDigest(AsconDigest.AsconParameters.AsconHashA);
+ }
+
+ [Test]
+ public void TestExceptionsEngine_ascon128()
+ {
+ ImplTestExceptionsEngine(AsconEngine.AsconParameters.ascon128);
+ }
+
+ [Test]
+ public void TestExceptionsEngine_ascon128a()
+ {
+ ImplTestExceptionsEngine(AsconEngine.AsconParameters.ascon128a);
+ }
+
+ [Test]
+ public void TestExceptionsEngine_ascon80pq()
+ {
+ ImplTestExceptionsEngine(AsconEngine.AsconParameters.ascon80pq);
+ }
+
+ [Test]
+ public void TestExceptionsXof_AsconXof()
+ {
+ ImplTestExceptionsXof(AsconXof.AsconParameters.AsconXof);
+ }
+
+ [Test]
+ public void TestExceptionsXof_AsconXofA()
+ {
+ ImplTestExceptionsXof(AsconXof.AsconParameters.AsconXofA);
+ }
+
+ [Test]
+ public void TestParametersDigest_AsconHash()
+ {
+ ImplTestParametersDigest(AsconDigest.AsconParameters.AsconHash, 32);
+ }
+
+ [Test]
+ public void TestParametersDigest_AsconHashA()
+ {
+ ImplTestParametersDigest(AsconDigest.AsconParameters.AsconHashA, 32);
+ }
+
+ [Test]
+ public void TestParametersEngine_ascon128()
+ {
+ ImplTestParametersEngine(AsconEngine.AsconParameters.ascon128, 16, 16, 16);
+ }
+
+ [Test]
+ public void TestParametersEngine_ascon128a()
+ {
+ ImplTestParametersEngine(AsconEngine.AsconParameters.ascon128a, 16, 16, 16);
+ }
+
+ [Test]
+ public void TestParametersEngine_ascon80pq()
+ {
+ ImplTestParametersEngine(AsconEngine.AsconParameters.ascon80pq, 20, 16, 16);
+ }
+
+ [Test]
+ public void TestParametersXof_AsconXof()
+ {
+ ImplTestParametersXof(AsconXof.AsconParameters.AsconXof, 32);
+ }
+
+ [Test]
+ public void TestParametersXof_AsconXofA()
+ {
+ ImplTestParametersXof(AsconXof.AsconParameters.AsconXofA, 32);
+ }
+
+ [Test]
+ public void TestVectorsDigest_AsconHash()
+ {
+ ImplTestVectorsDigest(AsconDigest.AsconParameters.AsconHash, "asconhash");
+ }
+
+ [Test]
+ public void TestVectorsDigest_AsconHashA()
+ {
+ ImplTestVectorsDigest(AsconDigest.AsconParameters.AsconHashA, "asconhasha");
+ }
+
+ [Test]
+ public void TestVectorsEngine_ascon128()
+ {
+ ImplTestVectorsEngine(AsconEngine.AsconParameters.ascon128, "128_128");
+ }
+
+ [Test]
+ public void TestVectorsEngine_ascon128a()
+ {
+ ImplTestVectorsEngine(AsconEngine.AsconParameters.ascon128a, "128_128_a");
+ }
+
+ [Test]
+ public void TestVectorsEngine_ascon80pq()
+ {
+ ImplTestVectorsEngine(AsconEngine.AsconParameters.ascon80pq, "160_128");
+ }
+
+ [Test]
+ public void TestVectorsXof_AsconXof()
{
- var parameters = new AeadParameters(new KeyParameter(new byte[20]), 128, new byte[16], null);
- var engine = new AsconEngine(AsconEngine.AsconParameters.ascon80pq);
- engine.Init(false, parameters);
+ ImplTestVectorsXof(AsconXof.AsconParameters.AsconXof, "asconxof");
+ }
+
+ [Test]
+ public void TestVectorsXof_AsconXofA()
+ {
+ ImplTestVectorsXof(AsconXof.AsconParameters.AsconXofA, "asconxofa");
+ }
+
+ private static AsconDigest CreateDigest(AsconDigest.AsconParameters asconParameters)
+ {
+ return new AsconDigest(asconParameters);
+ }
+
+ private static AsconEngine CreateEngine(AsconEngine.AsconParameters asconParameters)
+ {
+ return new AsconEngine(asconParameters);
+ }
+
+ private static AsconXof CreateXof(AsconXof.AsconParameters asconParameters)
+ {
+ return new AsconXof(asconParameters);
+ }
+
+ private static void ImplBenchDigest(AsconDigest.AsconParameters asconParameters)
+ {
+ var ascon = CreateDigest(asconParameters);
byte[] data = new byte[1024];
- for (int i = 0; i < 1024 * 1024; ++i)
+ for (int i = 0; i < 1024; ++i)
{
-#if NET6_0_OR_GREATER
- engine.ProcessAadBytes(data.AsSpan(0, 1024));
+ for (int j = 0; j < 1024; ++j)
+ {
+ // NOTE: .NET Core 3.1 has Span<T>, but is tested against our .NET Standard 2.0 assembly.
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ascon.BlockUpdate(data);
+#else
+ ascon.BlockUpdate(data, 0, 1024);
+#endif
+ }
+
+ // NOTE: .NET Core 3.1 has Span<T>, but is tested against our .NET Standard 2.0 assembly.
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ascon.DoFinal(data);
#else
- engine.ProcessAadBytes(data, 0, 1024);
+ ascon.DoFinal(data, 0);
#endif
}
}
- [Test, Explicit]
- public void BenchDecrypt80pq()
+ private static void ImplBenchEngineAuth(AsconEngine.AsconParameters asconParameters)
{
- var parameters = new AeadParameters(new KeyParameter(new byte[20]), 128, new byte[16], null);
- var engine = new AsconEngine(AsconEngine.AsconParameters.ascon80pq);
- engine.Init(false, parameters);
+ var ascon = CreateEngine(asconParameters);
+ InitEngine(ascon, true);
byte[] data = new byte[1024];
for (int i = 0; i < 1024 * 1024; ++i)
{
-#if NET6_0_OR_GREATER
- engine.ProcessBytes(data.AsSpan(0, 1024), data);
+ // NOTE: .NET Core 3.1 has Span<T>, but is tested against our .NET Standard 2.0 assembly.
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ascon.ProcessAadBytes(data);
#else
- engine.ProcessBytes(data, 0, 1024, data, 0);
+ ascon.ProcessAadBytes(data, 0, 1024);
#endif
}
}
- [Test, Explicit]
- public void BenchEncrypt80pq()
+ private static void ImplBenchEngineCrypt(AsconEngine.AsconParameters asconParameters, bool forEncryption)
{
- var parameters = new AeadParameters(new KeyParameter(new byte[20]), 128, new byte[16], null);
- var engine = new AsconEngine(AsconEngine.AsconParameters.ascon80pq);
- engine.Init(true, parameters);
+ var ascon = CreateEngine(asconParameters);
+ InitEngine(ascon, forEncryption);
- byte[] data = new byte[engine.GetUpdateOutputSize(1024)];
+ byte[] data = new byte[1024 + 64];
for (int i = 0; i < 1024 * 1024; ++i)
{
-#if NET6_0_OR_GREATER
- engine.ProcessBytes(data.AsSpan(0, 1024), data);
+ // NOTE: .NET Core 3.1 has Span<T>, but is tested against our .NET Standard 2.0 assembly.
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ascon.ProcessBytes(data.AsSpan(0, 1024), data);
#else
- engine.ProcessBytes(data, 0, 1024, data, 0);
+ ascon.ProcessBytes(data, 0, 1024, data, 0);
#endif
}
}
- [Test]
- public override void PerformTest()
+ private static void ImplBenchXof(AsconXof.AsconParameters asconParameters)
{
- ImplTestVectorsHash(AsconDigest.AsconParameters.AsconHashA, "asconhasha");
- ImplTestVectorsHash(AsconDigest.AsconParameters.AsconHash, "asconhash");
- ImplTestVectorsXof(AsconXof.AsconParameters.AsconXof, "asconxof");
- ImplTestVectorsXof(AsconXof.AsconParameters.AsconXofA, "asconxofa");
-
- ImplTestExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconHashA), 32);
- ImplTestExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconHash), 32);
- ImplTestExceptions(new AsconXof(AsconXof.AsconParameters.AsconXof), 32);
- ImplTestExceptions(new AsconXof(AsconXof.AsconParameters.AsconXofA), 32);
-
- AsconEngine asconEngine = new AsconEngine(AsconEngine.AsconParameters.ascon80pq);
- ImplTestExceptions(asconEngine);
- ImplTestParameters(asconEngine, 20, 16, 16);
-
- asconEngine = new AsconEngine(AsconEngine.AsconParameters.ascon128a);
- ImplTestExceptions(asconEngine);
- ImplTestParameters(asconEngine, 16, 16, 16);
+ var ascon = CreateXof(asconParameters);
- asconEngine = new AsconEngine(AsconEngine.AsconParameters.ascon128);
- ImplTestExceptions(asconEngine);
- ImplTestParameters(asconEngine, 16, 16, 16);
-
- ImplTestVectors(AsconEngine.AsconParameters.ascon80pq, "160_128");
- ImplTestVectors(AsconEngine.AsconParameters.ascon128a, "128_128_a");
- ImplTestVectors(AsconEngine.AsconParameters.ascon128, "128_128");
- }
-
- private void ImplTestVectors(AsconEngine.AsconParameters asconParameters, string filename)
- {
- Random random = new Random();
- AsconEngine asconEngine = new AsconEngine(asconParameters);
- var buf = new Dictionary<string, string>();
- //TestSampler sampler = new TestSampler();
- using (var src = new StreamReader(SimpleTest.GetTestDataAsStream("crypto.ascon.LWC_AEAD_KAT_" + filename + ".txt")))
+ byte[] data = new byte[1024];
+ for (int i = 0; i < 1024; ++i)
{
- Dictionary<string, string> map = new Dictionary<string, string>();
- string line;
- while ((line = src.ReadLine()) != null)
+ for (int j = 0; j < 1024; ++j)
{
- var data = line.Split(' ');
- if (data.Length == 1)
- {
- byte[] key = Hex.Decode(map["Key"]);
- byte[] nonce = Hex.Decode(map["Nonce"]);
- byte[] ad = Hex.Decode(map["AD"]);
- byte[] pt = Hex.Decode(map["PT"]);
- byte[] ct = Hex.Decode(map["CT"]);
- map.Clear();
-
- var parameters = new ParametersWithIV(new KeyParameter(key), nonce);
-
- // Encrypt
- {
- asconEngine.Init(true, parameters);
-
- var rv = new byte[asconEngine.GetOutputSize(pt.Length)];
- random.NextBytes(rv); // should overwrite any existing data
-
- asconEngine.ProcessAadBytes(ad, 0, ad.Length);
- int len = asconEngine.ProcessBytes(pt, 0, pt.Length, rv, 0);
- len += asconEngine.DoFinal(rv, len);
-
- Assert.True(Arrays.AreEqual(rv, 0, len, ct, 0, ct.Length));
- }
+ // NOTE: .NET Core 3.1 has Span<T>, but is tested against our .NET Standard 2.0 assembly.
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ascon.BlockUpdate(data);
+#else
+ ascon.BlockUpdate(data, 0, 1024);
+#endif
+ }
- // Decrypt
- {
- asconEngine.Init(false, parameters);
+ // NOTE: .NET Core 3.1 has Span<T>, but is tested against our .NET Standard 2.0 assembly.
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ ascon.OutputFinal(data);
+#else
+ ascon.OutputFinal(data, 0, data.Length);
+#endif
+ }
+ }
- var rv = new byte[asconEngine.GetOutputSize(ct.Length)];
- random.NextBytes(rv); // should overwrite any existing data
+ private static void ImplTestExceptionsDigest(AsconDigest.AsconParameters asconParameters)
+ {
+ var ascon = new AsconDigest(asconParameters);
- asconEngine.ProcessAadBytes(ad, 0, ad.Length);
- int len = asconEngine.ProcessBytes(ct, 0, ct.Length, rv, 0);
- len += asconEngine.DoFinal(rv, len);
+ try
+ {
+ ascon.BlockUpdate(new byte[1], 1, 1);
+ Assert.Fail(ascon.AlgorithmName + ": input for BlockUpdate is too short");
+ }
+ catch (DataLengthException)
+ {
+ //expected
+ }
- Assert.True(Arrays.AreEqual(rv, 0, len, pt, 0, pt.Length));
- }
- }
- else
- {
- if (data.Length >= 3)
- {
- map[data[0].Trim()] = data[2].Trim();
- }
- else
- {
- map[data[0].Trim()] = "";
- }
- }
- }
+ try
+ {
+ ascon.DoFinal(new byte[ascon.GetDigestSize() - 1], 2);
+ Assert.Fail(ascon.AlgorithmName + ": output for DoFinal is too short");
+ }
+ catch (OutputLengthException)
+ {
+ //expected
}
}
- private void ImplTestExceptions(AsconEngine asconEngine)
+ private void ImplTestExceptionsEngine(AsconEngine.AsconParameters asconParameters)
{
- int keySize = asconEngine.GetKeyBytesSize(), ivSize = asconEngine.GetIVBytesSize();
+ var ascon = CreateEngine(asconParameters);
+ int keySize = ascon.GetKeyBytesSize(), ivSize = ascon.GetIVBytesSize();
int offset;
byte[] k = new byte[keySize];
byte[] iv = new byte[ivSize];
@@ -180,8 +363,8 @@ namespace Org.BouncyCastle.Crypto.Tests
var param = new ParametersWithIV(new KeyParameter(k), iv);
try
{
- asconEngine.ProcessBytes(m, 0, m.Length, null, 0);
- Assert.Fail(asconEngine.AlgorithmName + " needs to be initialized before ProcessBytes");
+ ascon.ProcessBytes(m, 0, m.Length, null, 0);
+ Assert.Fail(ascon.AlgorithmName + " needs to be initialized before ProcessBytes");
}
catch (InvalidOperationException)
{
@@ -190,8 +373,8 @@ namespace Org.BouncyCastle.Crypto.Tests
try
{
- asconEngine.ProcessByte(0x00, null, 0);
- Assert.Fail(asconEngine.AlgorithmName + " needs to be initialized before ProcessByte");
+ ascon.ProcessByte(0x00, null, 0);
+ Assert.Fail(ascon.AlgorithmName + " needs to be initialized before ProcessByte");
}
catch (InvalidOperationException)
{
@@ -200,8 +383,8 @@ namespace Org.BouncyCastle.Crypto.Tests
try
{
- asconEngine.Reset();
- Assert.Fail(asconEngine.AlgorithmName + " needs to be initialized before Reset");
+ ascon.Reset();
+ Assert.Fail(ascon.AlgorithmName + " needs to be initialized before Reset");
}
catch (InvalidOperationException)
{
@@ -210,8 +393,8 @@ namespace Org.BouncyCastle.Crypto.Tests
try
{
- asconEngine.DoFinal(null, m.Length);
- Assert.Fail(asconEngine.AlgorithmName + " needs to be initialized before DoFinal");
+ ascon.DoFinal(null, m.Length);
+ Assert.Fail(ascon.AlgorithmName + " needs to be initialized before DoFinal");
}
catch (InvalidOperationException)
{
@@ -220,14 +403,14 @@ namespace Org.BouncyCastle.Crypto.Tests
try
{
- asconEngine.GetMac();
- asconEngine.GetOutputSize(0);
- asconEngine.GetUpdateOutputSize(0);
+ ascon.GetMac();
+ ascon.GetOutputSize(0);
+ ascon.GetUpdateOutputSize(0);
}
catch (InvalidOperationException)
{
//expected
- Assert.Fail(asconEngine.AlgorithmName + " functions can be called before initialization");
+ Assert.Fail(ascon.AlgorithmName + " functions can be called before initialization");
}
Random rand = new Random();
@@ -238,8 +421,8 @@ namespace Org.BouncyCastle.Crypto.Tests
byte[] iv1 = new byte[randomNum];
try
{
- asconEngine.Init(true, new ParametersWithIV(new KeyParameter(k1), iv));
- Assert.Fail(asconEngine.AlgorithmName + " k size does not match");
+ ascon.Init(true, new ParametersWithIV(new KeyParameter(k1), iv));
+ Assert.Fail(ascon.AlgorithmName + " k size does not match");
}
catch (ArgumentException)
{
@@ -247,25 +430,25 @@ namespace Org.BouncyCastle.Crypto.Tests
}
try
{
- asconEngine.Init(true, new ParametersWithIV(new KeyParameter(k), iv1));
- Assert.Fail(asconEngine.AlgorithmName + "iv size does not match");
+ ascon.Init(true, new ParametersWithIV(new KeyParameter(k), iv1));
+ Assert.Fail(ascon.AlgorithmName + "iv size does not match");
}
catch (ArgumentException)
{
//expected
}
- asconEngine.Init(true, param);
- byte[] c1 = new byte[asconEngine.GetOutputSize(m.Length)];
+ ascon.Init(true, param);
+ byte[] c1 = new byte[ascon.GetOutputSize(m.Length)];
try
{
- asconEngine.DoFinal(c1, m.Length);
+ ascon.DoFinal(c1, m.Length);
}
catch (Exception)
{
- Assert.Fail(asconEngine.AlgorithmName + " allows no input for AAD and plaintext");
+ Assert.Fail(ascon.AlgorithmName + " allows no input for AAD and plaintext");
}
- byte[] mac2 = asconEngine.GetMac();
+ byte[] mac2 = ascon.GetMac();
if (mac2 == null)
{
Assert.Fail("mac should not be empty after DoFinal");
@@ -276,21 +459,21 @@ namespace Org.BouncyCastle.Crypto.Tests
}
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- asconEngine.ProcessAadByte(0x00);
- byte[] mac1 = new byte[asconEngine.GetOutputSize(0)];
- asconEngine.DoFinal(mac1, 0);
+ ascon.Init(true, param);
+ ascon.ProcessAadByte(0x00);
+ byte[] mac1 = new byte[ascon.GetOutputSize(0)];
+ ascon.DoFinal(mac1, 0);
if (Arrays.AreEqual(mac1, mac2))
{
Assert.Fail("mac should not match");
}
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- asconEngine.ProcessByte(0, null, 0);
+ ascon.Init(true, param);
+ ascon.ProcessByte(0, null, 0);
try
{
- asconEngine.ProcessAadByte(0x00);
+ ascon.ProcessAadByte(0x00);
Assert.Fail("ProcessAadByte cannot be called after encryption/decryption");
}
catch (InvalidOperationException)
@@ -299,7 +482,7 @@ namespace Org.BouncyCastle.Crypto.Tests
}
try
{
- asconEngine.ProcessAadBytes(new byte[1], 0, 1);
+ ascon.ProcessAadBytes(new byte[1], 0, 1);
Assert.Fail("ProcessAadBytes cannot be called after encryption/decryption");
}
catch (InvalidOperationException)
@@ -308,10 +491,10 @@ namespace Org.BouncyCastle.Crypto.Tests
}
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
+ ascon.Init(true, param);
try
{
- asconEngine.ProcessAadBytes(new byte[1], 1, 1);
+ ascon.ProcessAadBytes(new byte[1], 1, 1);
Assert.Fail("input for ProcessAadBytes is too short");
}
catch (DataLengthException)
@@ -320,28 +503,16 @@ namespace Org.BouncyCastle.Crypto.Tests
}
try
{
- asconEngine.ProcessBytes(new byte[1], 1, 1, c1, 0);
+ ascon.ProcessBytes(new byte[1], 1, 1, c1, 0);
Assert.Fail("input for ProcessBytes is too short");
}
catch (DataLengthException)
{
//expected
}
-
- try
- {
- int inputSize = rand.Next(32, 64);
- int outputSize = asconEngine.GetUpdateOutputSize(inputSize);
- asconEngine.ProcessBytes(new byte[inputSize], 0, inputSize, new byte[outputSize], 1);
- Assert.Fail("output for ProcessBytes is too short");
- }
- catch (OutputLengthException)
- {
- //expected
- }
try
{
- asconEngine.DoFinal(new byte[2], 2);
+ ascon.DoFinal(new byte[2], 2);
Assert.Fail("output for DoFinal is too short");
}
catch (OutputLengthException)
@@ -349,19 +520,22 @@ namespace Org.BouncyCastle.Crypto.Tests
//expected
}
- mac1 = new byte[asconEngine.GetOutputSize(0)];
- mac2 = new byte[asconEngine.GetOutputSize(0)];
+ ImplTestExceptionsGetUpdateOutputSize(ascon, false, param, 100);
+ ImplTestExceptionsGetUpdateOutputSize(ascon, true, param, 100);
+
+ mac1 = new byte[ascon.GetOutputSize(0)];
+ mac2 = new byte[ascon.GetOutputSize(0)];
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- asconEngine.ProcessAadBytes(new byte[2], 0, 2);
- asconEngine.DoFinal(mac1, 0);
+ ascon.Init(true, param);
+ ascon.ProcessAadBytes(new byte[2], 0, 2);
+ ascon.DoFinal(mac1, 0);
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- asconEngine.ProcessAadByte(0x00);
- asconEngine.ProcessAadByte(0x00);
- asconEngine.DoFinal(mac2, 0);
+ ascon.Init(true, param);
+ ascon.ProcessAadByte(0x00);
+ ascon.ProcessAadByte(0x00);
+ ascon.DoFinal(mac2, 0);
if (!Arrays.AreEqual(mac1, mac2))
{
@@ -373,20 +547,20 @@ namespace Org.BouncyCastle.Crypto.Tests
byte[] m2 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
byte[] m3 = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
byte[] m4 = new byte[m2.Length];
- byte[] c2 = new byte[asconEngine.GetOutputSize(m2.Length)];
- byte[] c3 = new byte[asconEngine.GetOutputSize(m3.Length)];
+ byte[] c2 = new byte[ascon.GetOutputSize(m2.Length)];
+ byte[] c3 = new byte[ascon.GetOutputSize(m3.Length)];
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
- offset = asconEngine.ProcessBytes(m2, 0, m2.Length, c2, 0);
- asconEngine.DoFinal(c2, offset);
+ ascon.Init(true, param);
+ ascon.ProcessAadBytes(aad2, 0, aad2.Length);
+ offset = ascon.ProcessBytes(m2, 0, m2.Length, c2, 0);
+ ascon.DoFinal(c2, offset);
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- asconEngine.ProcessAadBytes(aad3, 1, aad2.Length);
- offset = asconEngine.ProcessBytes(m3, 1, m2.Length, c3, 1);
- asconEngine.DoFinal(c3, offset + 1);
+ ascon.Init(true, param);
+ ascon.ProcessAadBytes(aad3, 1, aad2.Length);
+ offset = ascon.ProcessBytes(m3, 1, m2.Length, c3, 1);
+ ascon.DoFinal(c3, offset + 1);
byte[] c3_partial = new byte[c2.Length];
Array.Copy(c3, 1, c3_partial, 0, c2.Length);
@@ -395,10 +569,10 @@ namespace Org.BouncyCastle.Crypto.Tests
Assert.Fail("mac should match for the same AAD and message with different offset for both input and output");
}
- asconEngine.Init(false, param);
- asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
- offset = asconEngine.ProcessBytes(c2, 0, c2.Length, m4, 0);
- asconEngine.DoFinal(m4, offset);
+ ascon.Init(false, param);
+ ascon.ProcessAadBytes(aad2, 0, aad2.Length);
+ offset = ascon.ProcessBytes(c2, 0, c2.Length, m4, 0);
+ ascon.DoFinal(m4, offset);
if (!Arrays.AreEqual(m2, m4))
{
Assert.Fail("The encryption and decryption does not recover the plaintext");
@@ -406,11 +580,11 @@ namespace Org.BouncyCastle.Crypto.Tests
c2[c2.Length - 1] ^= 1;
- asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
- offset = asconEngine.ProcessBytes(c2, 0, c2.Length, m4, 0);
+ ascon.ProcessAadBytes(aad2, 0, aad2.Length);
+ offset = ascon.ProcessBytes(c2, 0, c2.Length, m4, 0);
try
{
- asconEngine.DoFinal(m4, offset);
+ ascon.DoFinal(m4, offset);
Assert.Fail("The decryption should fail");
}
catch (InvalidCipherTextException)
@@ -423,51 +597,52 @@ namespace Org.BouncyCastle.Crypto.Tests
rand.NextBytes(m7);
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- byte[] c7 = new byte[asconEngine.GetOutputSize(m7.Length)];
+ ascon.Init(true, param);
+ byte[] c7 = new byte[ascon.GetOutputSize(m7.Length)];
byte[] c8 = new byte[c7.Length];
byte[] c9 = new byte[c7.Length];
- asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
- offset = asconEngine.ProcessBytes(m7, 0, m7.Length, c7, 0);
- offset += asconEngine.DoFinal(c7, offset);
+ ascon.ProcessAadBytes(aad2, 0, aad2.Length);
+ offset = ascon.ProcessBytes(m7, 0, m7.Length, c7, 0);
+ offset += ascon.DoFinal(c7, offset);
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
- offset = asconEngine.ProcessBytes(m7, 0, m7.Length / 2, c8, 0);
- offset += asconEngine.ProcessBytes(m7, m7.Length / 2, m7.Length - m7.Length / 2, c8, offset);
- offset += asconEngine.DoFinal(c8, offset);
+ ascon.Init(true, param);
+ ascon.ProcessAadBytes(aad2, 0, aad2.Length);
+ offset = ascon.ProcessBytes(m7, 0, m7.Length / 2, c8, 0);
+ offset += ascon.ProcessBytes(m7, m7.Length / 2, m7.Length - m7.Length / 2, c8, offset);
+ offset += ascon.DoFinal(c8, offset);
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
+ ascon.Init(true, param);
int split = rand.Next(1, m7.Length);
- asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
- offset = asconEngine.ProcessBytes(m7, 0, split, c9, 0);
- offset += asconEngine.ProcessBytes(m7, split, m7.Length - split, c9, offset);
- offset += asconEngine.DoFinal(c9, offset);
+ ascon.ProcessAadBytes(aad2, 0, aad2.Length);
+ offset = ascon.ProcessBytes(m7, 0, split, c9, 0);
+ offset += ascon.ProcessBytes(m7, split, m7.Length - split, c9, offset);
+ offset += ascon.DoFinal(c9, offset);
if (!Arrays.AreEqual(c7, c8) || !Arrays.AreEqual(c7, c9))
{
Assert.Fail("Splitting input of plaintext should output the same ciphertext");
}
+
// NOTE: .NET Core 3.1 has Span<T>, but is tested against our .NET Standard 2.0 assembly.
- //#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+//#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
#if NET6_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
// TODO Maybe use a different IV for this
- asconEngine.Init(true, param);
- Span<byte> c4 = new byte[asconEngine.GetOutputSize(m2.Length)];
- asconEngine.ProcessAadBytes(aad2);
- offset = asconEngine.ProcessBytes(m2, c4);
- offset += asconEngine.DoFinal(c4[offset..]);
+ ascon.Init(true, param);
+ Span<byte> c4 = new byte[ascon.GetOutputSize(m2.Length)];
+ ascon.ProcessAadBytes(aad2);
+ offset = ascon.ProcessBytes(m2, c4);
+ offset += ascon.DoFinal(c4[offset..]);
if (!c4[..offset].SequenceEqual(c2))
{
Assert.Fail("Encryption should match for the same AAD and message with/without Span-based API");
}
- asconEngine.Init(false, param);
+ ascon.Init(false, param);
Span<byte> m6 = new byte[m2.Length];
- asconEngine.ProcessAadBytes(aad2);
- offset = asconEngine.ProcessBytes(c2, m6);
- offset += asconEngine.DoFinal(m6[offset..]);
+ ascon.ProcessAadBytes(aad2);
+ offset = ascon.ProcessBytes(c2, m6);
+ offset += ascon.DoFinal(m6[offset..]);
if (!m6[..offset].SequenceEqual(m2))
{
Assert.Fail("Decryption should match for the same AAD and message with/without Span-based API");
@@ -475,27 +650,106 @@ namespace Org.BouncyCastle.Crypto.Tests
#endif
}
- private void ImplTestParameters(AsconEngine asconEngine, int keySize, int ivSize, int macSize)
+ private static void ImplTestExceptionsGetUpdateOutputSize(AsconEngine ascon, bool forEncryption,
+ ICipherParameters parameters, int maxInputSize)
+ {
+ // TODO Maybe use a different IV for this
+ ascon.Init(forEncryption, parameters);
+
+ int maxOutputSize = ascon.GetUpdateOutputSize(maxInputSize);
+
+ byte[] input = new byte[maxInputSize];
+ byte[] output = new byte[maxOutputSize];
+
+ for (int inputSize = 0; inputSize <= maxInputSize; ++inputSize)
+ {
+ // TODO Maybe use a different IV for this
+ ascon.Init(forEncryption, parameters);
+
+ int outputSize = ascon.GetUpdateOutputSize(inputSize);
+ if (outputSize > 0)
+ {
+ try
+ {
+ ascon.ProcessBytes(input, 0, inputSize, output, maxOutputSize - outputSize + 1);
+ Assert.Fail("output for ProcessBytes is too short");
+ }
+ catch (OutputLengthException)
+ {
+ //expected
+ }
+ }
+ else
+ {
+ ascon.ProcessBytes(input, 0, inputSize, null, 0);
+ }
+ }
+ }
+
+ private static void ImplTestExceptionsXof(AsconXof.AsconParameters asconParameters)
+ {
+ var ascon = CreateXof(asconParameters);
+
+ try
+ {
+ ascon.BlockUpdate(new byte[1], 1, 1);
+ Assert.Fail(ascon.AlgorithmName + ": input for BlockUpdate is too short");
+ }
+ catch (DataLengthException)
+ {
+ //expected
+ }
+
+ try
+ {
+ ascon.DoFinal(new byte[ascon.GetDigestSize() - 1], 2);
+ Assert.Fail(ascon.AlgorithmName + ": output for DoFinal is too short");
+ }
+ catch (OutputLengthException)
+ {
+ //expected
+ }
+ }
+
+ private static void ImplTestParametersDigest(AsconDigest.AsconParameters asconParameters, int digestSize)
+ {
+ var ascon = CreateDigest(asconParameters);
+
+ Assert.AreEqual(digestSize, ascon.GetDigestSize(), ascon.AlgorithmName + ": digest size is not correct");
+ }
+
+ private static void ImplTestParametersEngine(AsconEngine.AsconParameters asconParameters, int keySize,
+ int ivSize, int macSize)
{
- Assert.AreEqual(keySize, asconEngine.GetKeyBytesSize(),
- "key bytes of " + asconEngine.AlgorithmName + " is not correct");
- Assert.AreEqual(ivSize, asconEngine.GetIVBytesSize(),
- "iv bytes of " + asconEngine.AlgorithmName + " is not correct");
+ var ascon = CreateEngine(asconParameters);
+
+ Assert.AreEqual(keySize, ascon.GetKeyBytesSize(),
+ "key bytes of " + ascon.AlgorithmName + " is not correct");
+ Assert.AreEqual(ivSize, ascon.GetIVBytesSize(),
+ "iv bytes of " + ascon.AlgorithmName + " is not correct");
var parameters = new ParametersWithIV(new KeyParameter(new byte[keySize]), new byte[ivSize]);
+ ascon.Init(true, parameters);
- asconEngine.Init(true, parameters);
- Assert.AreEqual(macSize, asconEngine.GetOutputSize(0),
- "GetOutputSize of " + asconEngine.AlgorithmName + " is incorrect for encryption");
+ Assert.AreEqual(macSize, ascon.GetOutputSize(0),
+ "GetOutputSize of " + ascon.AlgorithmName + " is incorrect for encryption");
- asconEngine.Init(false, parameters);
- Assert.AreEqual(0, asconEngine.GetOutputSize(macSize),
- "GetOutputSize of " + asconEngine.AlgorithmName + " is incorrect for decryption");
+ ascon.Init(false, parameters);
+ Assert.AreEqual(0, ascon.GetOutputSize(macSize),
+ "GetOutputSize of " + ascon.AlgorithmName + " is incorrect for decryption");
}
- private void ImplTestVectorsHash(AsconDigest.AsconParameters asconParameters, string filename)
+ private static void ImplTestParametersXof(AsconXof.AsconParameters asconParameters, int digestSize)
{
- AsconDigest ascon = new AsconDigest(asconParameters);
+ var ascon = CreateXof(asconParameters);
+
+ Assert.AreEqual(digestSize, ascon.GetDigestSize(),
+ ascon.AlgorithmName + ": digest size is not correct");
+ }
+
+ private static void ImplTestVectorsDigest(AsconDigest.AsconParameters asconParameters, string filename)
+ {
+ var ascon = CreateDigest(asconParameters);
var map = new Dictionary<string, string>();
using (var src = new StreamReader(
SimpleTest.GetTestDataAsStream("crypto.ascon." + filename + "_LWC_HASH_KAT_256.txt")))
@@ -530,7 +784,74 @@ namespace Org.BouncyCastle.Crypto.Tests
}
}
- private void ImplTestVectorsXof(AsconXof.AsconParameters asconParameters, string filename)
+ private static void ImplTestVectorsEngine(AsconEngine.AsconParameters asconParameters, string filename)
+ {
+ Random random = new Random();
+ var asconEngine = CreateEngine(asconParameters);
+ var buf = new Dictionary<string, string>();
+ //TestSampler sampler = new TestSampler();
+ using (var src = new StreamReader(SimpleTest.GetTestDataAsStream("crypto.ascon.LWC_AEAD_KAT_" + filename + ".txt")))
+ {
+ Dictionary<string, string> map = new Dictionary<string, string>();
+ string line;
+ while ((line = src.ReadLine()) != null)
+ {
+ var data = line.Split(' ');
+ if (data.Length == 1)
+ {
+ byte[] key = Hex.Decode(map["Key"]);
+ byte[] nonce = Hex.Decode(map["Nonce"]);
+ byte[] ad = Hex.Decode(map["AD"]);
+ byte[] pt = Hex.Decode(map["PT"]);
+ byte[] ct = Hex.Decode(map["CT"]);
+ map.Clear();
+
+ var parameters = new ParametersWithIV(new KeyParameter(key), nonce);
+
+ // Encrypt
+ {
+ asconEngine.Init(true, parameters);
+
+ var rv = new byte[asconEngine.GetOutputSize(pt.Length)];
+ random.NextBytes(rv); // should overwrite any existing data
+
+ asconEngine.ProcessAadBytes(ad, 0, ad.Length);
+ int len = asconEngine.ProcessBytes(pt, 0, pt.Length, rv, 0);
+ len += asconEngine.DoFinal(rv, len);
+
+ Assert.True(Arrays.AreEqual(rv, 0, len, ct, 0, ct.Length));
+ }
+
+ // Decrypt
+ {
+ asconEngine.Init(false, parameters);
+
+ var rv = new byte[asconEngine.GetOutputSize(ct.Length)];
+ random.NextBytes(rv); // should overwrite any existing data
+
+ asconEngine.ProcessAadBytes(ad, 0, ad.Length);
+ int len = asconEngine.ProcessBytes(ct, 0, ct.Length, rv, 0);
+ len += asconEngine.DoFinal(rv, len);
+
+ Assert.True(Arrays.AreEqual(rv, 0, len, pt, 0, pt.Length));
+ }
+ }
+ else
+ {
+ if (data.Length >= 3)
+ {
+ map[data[0].Trim()] = data[2].Trim();
+ }
+ else
+ {
+ map[data[0].Trim()] = "";
+ }
+ }
+ }
+ }
+ }
+
+ private static void ImplTestVectorsXof(AsconXof.AsconParameters asconParameters, string filename)
{
AsconXof ascon = new AsconXof(asconParameters);
var buf = new Dictionary<string, string>();
@@ -568,54 +889,14 @@ namespace Org.BouncyCastle.Crypto.Tests
}
}
- private void ImplTestExceptions(AsconDigest asconDigest, int digestSize)
+ private static void InitEngine(AsconEngine ascon, bool forEncryption)
{
- Assert.AreEqual(digestSize, asconDigest.GetDigestSize(),
- asconDigest.AlgorithmName + ": digest size is not correct");
+ int keySize = ascon.GetKeyBytesSize();
+ int ivSize = ascon.GetIVBytesSize();
+ int macSize = ivSize * 8;
- try
- {
- asconDigest.BlockUpdate(new byte[1], 1, 1);
- Assert.Fail(asconDigest.AlgorithmName + ": input for BlockUpdate is too short");
- }
- catch (DataLengthException)
- {
- //expected
- }
- try
- {
- asconDigest.DoFinal(new byte[digestSize - 1], 2);
- Assert.Fail(asconDigest.AlgorithmName + ": output for DoFinal is too short");
- }
- catch (OutputLengthException)
- {
- //expected
- }
- }
-
- private void ImplTestExceptions(AsconXof asconXof, int digestSize)
- {
- Assert.AreEqual(digestSize, asconXof.GetDigestSize(),
- asconXof.AlgorithmName + ": digest size is not correct");
-
- try
- {
- asconXof.BlockUpdate(new byte[1], 1, 1);
- Assert.Fail(asconXof.AlgorithmName + ": input for BlockUpdate is too short");
- }
- catch (DataLengthException)
- {
- //expected
- }
- try
- {
- asconXof.DoFinal(new byte[digestSize - 1], 2);
- Assert.Fail(asconXof.AlgorithmName + ": output for DoFinal is too short");
- }
- catch (OutputLengthException)
- {
- //expected
- }
+ var parameters = new AeadParameters(new KeyParameter(new byte[keySize]), macSize, new byte[ivSize], null);
+ ascon.Init(forEncryption, parameters);
}
}
}
|