Skip to content

Commit 7c3606d

Browse files
committed
AsconEngine improvements
1 parent e077bfb commit 7c3606d

File tree

2 files changed

+92
-66
lines changed

2 files changed

+92
-66
lines changed

crypto/src/crypto/engines/AsconEngine.cs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,25 @@ public byte[] GetMac()
331331

332332
public int GetUpdateOutputSize(int len)
333333
{
334-
return len;
334+
int totalData = Convert.ToInt32(message.Length + len);
335+
if (!forEncryption)
336+
{
337+
if (totalData < CRYPTO_ABYTES)
338+
return 0;
339+
340+
totalData -= CRYPTO_ABYTES;
341+
}
342+
return totalData - totalData % ASCON_AEAD_RATE;
335343
}
336344

337345
public int GetOutputSize(int len)
338346
{
339-
return len + CRYPTO_ABYTES;
347+
int totalData = Convert.ToInt32(message.Length + len);
348+
349+
if (forEncryption)
350+
return totalData + CRYPTO_ABYTES;
351+
352+
return System.Math.Max(0, totalData - CRYPTO_ABYTES);
340353
}
341354

342355
public void Reset()
@@ -423,35 +436,35 @@ private void ascon_aeadinit()
423436
#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
424437
private int ProcessBytes(Span<byte> output)
425438
{
426-
int len_orig = Convert.ToInt32(message.Length);
427-
int len = 0;
439+
int msgLen = Convert.ToInt32(message.Length);
440+
int outLen = 0;
428441
if (forEncryption)
429442
{
430-
if (len_orig >= ASCON_AEAD_RATE)
443+
if (msgLen >= ASCON_AEAD_RATE)
431444
{
432445
ProcessAad();
433446
byte[] input = message.GetBuffer();
434-
len = (len_orig / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
435-
Check.OutputLength(output, len, "output buffer is too short");
436-
ascon_encrypt(output, input.AsSpan(0, len));
447+
outLen = (msgLen / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
448+
Check.OutputLength(output, outLen, "output buffer is too short");
449+
ascon_encrypt(output, input.AsSpan(0, outLen));
437450
message.SetLength(0);
438-
message.Write(input, len, len_orig - len);
451+
message.Write(input, outLen, msgLen - outLen);
439452
}
440453
}
441454
else
442455
{
443-
if (len_orig - CRYPTO_ABYTES >= ASCON_AEAD_RATE)
456+
if (msgLen - CRYPTO_ABYTES >= ASCON_AEAD_RATE)
444457
{
445458
ProcessAad();
446459
byte[] input = message.GetBuffer();
447-
len = ((len_orig - CRYPTO_ABYTES) / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
448-
Check.OutputLength(output, len, "output buffer is too short");
449-
ascon_decrypt(output, input.AsSpan(0, len));
460+
outLen = ((msgLen - CRYPTO_ABYTES) / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
461+
Check.OutputLength(output, outLen, "output buffer is too short");
462+
ascon_decrypt(output, input.AsSpan(0, outLen));
450463
message.SetLength(0);
451-
message.Write(input, len, len_orig - len);
464+
message.Write(input, outLen, msgLen - outLen);
452465
}
453466
}
454-
return len;
467+
return outLen;
455468
}
456469

457470
private void ascon_adata(ReadOnlySpan<byte> aad)
@@ -620,35 +633,35 @@ private void ascon_final(Span<byte> output, ReadOnlySpan<byte> input)
620633
#else
621634
private int ProcessBytes(byte[] output, int outOff)
622635
{
623-
int len_orig = Convert.ToInt32(message.Length);
624-
int len = 0;
636+
int msgLen = Convert.ToInt32(message.Length);
637+
int outLen = 0;
625638
if (forEncryption)
626639
{
627-
if (len_orig >= ASCON_AEAD_RATE)
640+
if (msgLen >= ASCON_AEAD_RATE)
628641
{
629642
ProcessAad();
630643
byte[] input = message.GetBuffer();
631-
len = (len_orig / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
632-
Check.OutputLength(output, outOff, len, "output buffer is too short");
633-
ascon_encrypt(output, outOff, input, 0, len);
644+
outLen = (msgLen / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
645+
Check.OutputLength(output, outOff, outLen, "output buffer is too short");
646+
ascon_encrypt(output, outOff, input, 0, outLen);
634647
message.SetLength(0);
635-
message.Write(input, len, len_orig - len);
648+
message.Write(input, outLen, msgLen - outLen);
636649
}
637650
}
638651
else
639652
{
640-
if (len_orig - CRYPTO_ABYTES >= ASCON_AEAD_RATE)
653+
if (msgLen - CRYPTO_ABYTES >= ASCON_AEAD_RATE)
641654
{
642655
ProcessAad();
643656
byte[] input = message.GetBuffer();
644-
len = ((len_orig - CRYPTO_ABYTES) / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
645-
Check.OutputLength(output, outOff, len, "output buffer is too short");
646-
ascon_decrypt(output, outOff, input, 0, len);
657+
outLen = ((msgLen - CRYPTO_ABYTES) / ASCON_AEAD_RATE) * ASCON_AEAD_RATE;
658+
Check.OutputLength(output, outOff, outLen, "output buffer is too short");
659+
ascon_decrypt(output, outOff, input, 0, outLen);
647660
message.SetLength(0);
648-
message.Write(input, len, len_orig - len);
661+
message.Write(input, outLen, msgLen - outLen);
649662
}
650663
}
651-
return len;
664+
return outLen;
652665
}
653666

654667
private void ascon_adata(byte[] ad, int adOff, int adlen)

crypto/test/src/crypto/test/AsconTest.cs

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44

55
using NUnit.Framework;
6+
67
using Org.BouncyCastle.Crypto.Digests;
78
using Org.BouncyCastle.Crypto.Engines;
89
using Org.BouncyCastle.Crypto.Parameters;
@@ -21,15 +22,15 @@ public class AsconTest
2122
[Test]
2223
public override void PerformTest()
2324
{
24-
testVectorsHash(AsconDigest.AsconParameters.AsconHashA, "asconhasha");
25-
testVectorsHash(AsconDigest.AsconParameters.AsconHash, "asconhash");
26-
testVectorsHash(AsconDigest.AsconParameters.AsconXof, "asconxof");
27-
testVectorsHash(AsconDigest.AsconParameters.AsconXofA, "asconxofa");
25+
ImplTestVectorsHash(AsconDigest.AsconParameters.AsconHashA, "asconhasha");
26+
ImplTestVectorsHash(AsconDigest.AsconParameters.AsconHash, "asconhash");
27+
ImplTestVectorsHash(AsconDigest.AsconParameters.AsconXof, "asconxof");
28+
ImplTestVectorsHash(AsconDigest.AsconParameters.AsconXofA, "asconxofa");
2829

29-
testExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconHashA), 32);
30-
testExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconHash), 32);
31-
testExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconXof), 32);
32-
testExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconXofA), 32);
30+
ImplTestExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconHashA), 32);
31+
ImplTestExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconHash), 32);
32+
ImplTestExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconXof), 32);
33+
ImplTestExceptions(new AsconDigest(AsconDigest.AsconParameters.AsconXofA), 32);
3334

3435
AsconEngine asconEngine = new AsconEngine(AsconEngine.AsconParameters.ascon80pq);
3536
ImplTestExceptions(asconEngine);
@@ -51,7 +52,7 @@ public override void PerformTest()
5152
private void ImplTestVectors(AsconEngine.AsconParameters asconParameters, string filename)
5253
{
5354
Random random = new Random();
54-
AsconEngine Ascon = new AsconEngine(asconParameters);
55+
AsconEngine asconEngine = new AsconEngine(asconParameters);
5556
var buf = new Dictionary<string, string>();
5657
//TestSampler sampler = new TestSampler();
5758
using (var src = new StreamReader(SimpleTest.GetTestDataAsStream("crypto.ascon.LWC_AEAD_KAT_" + filename + ".txt")))
@@ -70,32 +71,32 @@ private void ImplTestVectors(AsconEngine.AsconParameters asconParameters, string
7071
byte[] ct = Hex.Decode(map["CT"]);
7172
map.Clear();
7273

73-
var param = new ParametersWithIV(new KeyParameter(key), nonce);
74+
var parameters = new ParametersWithIV(new KeyParameter(key), nonce);
7475

7576
// Encrypt
7677
{
77-
Ascon.Init(true, param);
78+
asconEngine.Init(true, parameters);
7879

79-
var rv = new byte[Ascon.GetOutputSize(pt.Length)];
80+
var rv = new byte[asconEngine.GetOutputSize(pt.Length)];
8081
random.NextBytes(rv); // should overwrite any existing data
8182

82-
Ascon.ProcessAadBytes(ad, 0, ad.Length);
83-
int len = Ascon.ProcessBytes(pt, 0, pt.Length, rv, 0);
84-
len += Ascon.DoFinal(rv, len);
83+
asconEngine.ProcessAadBytes(ad, 0, ad.Length);
84+
int len = asconEngine.ProcessBytes(pt, 0, pt.Length, rv, 0);
85+
len += asconEngine.DoFinal(rv, len);
8586

8687
Assert.True(Arrays.AreEqual(rv, 0, len, ct, 0, ct.Length));
8788
}
8889

8990
// Decrypt
9091
{
91-
Ascon.Init(false, param);
92+
asconEngine.Init(false, parameters);
9293

93-
var rv = new byte[Ascon.GetOutputSize(ct.Length)];
94+
var rv = new byte[asconEngine.GetOutputSize(ct.Length)];
9495
random.NextBytes(rv); // should overwrite any existing data
9596

96-
Ascon.ProcessAadBytes(ad, 0, ad.Length);
97-
int len = Ascon.ProcessBytes(ct, 0, ct.Length, rv, 0);
98-
len += Ascon.DoFinal(rv, len);
97+
asconEngine.ProcessAadBytes(ad, 0, ad.Length);
98+
int len = asconEngine.ProcessBytes(ct, 0, ct.Length, rv, 0);
99+
len += asconEngine.DoFinal(rv, len);
99100

100101
Assert.True(Arrays.AreEqual(rv, 0, len, pt, 0, pt.Length));
101102
}
@@ -118,15 +119,15 @@ private void ImplTestVectors(AsconEngine.AsconParameters asconParameters, string
118119
private void ImplTestExceptions(AsconEngine asconEngine)
119120
{
120121
int keySize = asconEngine.GetKeyBytesSize(), ivSize = asconEngine.GetIVBytesSize();
122+
int offset;
121123
byte[] k = new byte[keySize];
122124
byte[] iv = new byte[ivSize];
123-
byte[] m = new byte[0];
124-
byte[] c1 = new byte[asconEngine.GetOutputSize(m.Length)];
125+
byte[] m = Array.Empty<byte>();
125126
var param = new ParametersWithIV(new KeyParameter(k), iv);
126127
try
127128
{
128-
asconEngine.ProcessBytes(m, 0, m.Length, c1, 0);
129-
Assert.Fail(asconEngine.AlgorithmName + " need to be initialed before ProcessBytes");
129+
asconEngine.ProcessBytes(m, 0, m.Length, null, 0);
130+
Assert.Fail(asconEngine.AlgorithmName + " need to be initialized before ProcessBytes");
130131
}
131132
catch (ArgumentException)
132133
{
@@ -135,8 +136,8 @@ private void ImplTestExceptions(AsconEngine asconEngine)
135136

136137
try
137138
{
138-
asconEngine.ProcessByte((byte)0, c1, 0);
139-
Assert.Fail(asconEngine.AlgorithmName + " need to be initialed before ProcessByte");
139+
asconEngine.ProcessByte((byte)0, null, 0);
140+
Assert.Fail(asconEngine.AlgorithmName + " need to be initialized before ProcessByte");
140141
}
141142
catch (ArgumentException)
142143
{
@@ -146,7 +147,7 @@ private void ImplTestExceptions(AsconEngine asconEngine)
146147
try
147148
{
148149
asconEngine.Reset();
149-
Assert.Fail(asconEngine.AlgorithmName + " need to be initialed before reset");
150+
Assert.Fail(asconEngine.AlgorithmName + " need to be initialized before reset");
150151
}
151152
catch (ArgumentException)
152153
{
@@ -155,8 +156,8 @@ private void ImplTestExceptions(AsconEngine asconEngine)
155156

156157
try
157158
{
158-
asconEngine.DoFinal(c1, m.Length);
159-
Assert.Fail(asconEngine.AlgorithmName + " need to be initialed before dofinal");
159+
asconEngine.DoFinal(null, m.Length);
160+
Assert.Fail(asconEngine.AlgorithmName + " need to be initialized before Dofinal");
160161
}
161162
catch (ArgumentException)
162163
{
@@ -201,6 +202,7 @@ private void ImplTestExceptions(AsconEngine asconEngine)
201202
}
202203

203204
asconEngine.Init(true, param);
205+
byte[] c1 = new byte[asconEngine.GetOutputSize(m.Length)];
204206
try
205207
{
206208
asconEngine.DoFinal(c1, m.Length);
@@ -267,7 +269,9 @@ private void ImplTestExceptions(AsconEngine asconEngine)
267269
}
268270
try
269271
{
270-
asconEngine.ProcessBytes(new byte[16], 0, 16, new byte[16], 8);
272+
int inputSize = rand.Next(32, 64);
273+
int outputSize = asconEngine.GetUpdateOutputSize(inputSize);
274+
asconEngine.ProcessBytes(new byte[inputSize], 0, inputSize, new byte[outputSize], 1);
271275
Assert.Fail("output for ProcessBytes is too short");
272276
}
273277
catch (OutputLengthException)
@@ -307,7 +311,7 @@ private void ImplTestExceptions(AsconEngine asconEngine)
307311
byte[] m4 = new byte[m2.Length];
308312
asconEngine.Reset();
309313
asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
310-
int offset = asconEngine.ProcessBytes(m2, 0, m2.Length, c2, 0);
314+
offset = asconEngine.ProcessBytes(m2, 0, m2.Length, c2, 0);
311315
asconEngine.DoFinal(c2, offset);
312316
asconEngine.Reset();
313317
asconEngine.ProcessAadBytes(aad3, 1, aad2.Length);
@@ -344,26 +348,27 @@ private void ImplTestExceptions(AsconEngine asconEngine)
344348
}
345349
c2[c2.Length - 1] ^= 1;
346350

347-
byte[] m7 = new byte[32 + rand.Next(16)];
351+
byte[] m7 = new byte[32 + rand.Next(32)];
348352
rand.NextBytes(m7);
349353

354+
asconEngine.Init(true, param);
350355
byte[] c7 = new byte[asconEngine.GetOutputSize(m7.Length)];
351356
byte[] c8 = new byte[c7.Length];
352357
byte[] c9 = new byte[c7.Length];
353-
asconEngine.Init(true, param);
354358
asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
355359
offset = asconEngine.ProcessBytes(m7, 0, m7.Length, c7, 0);
356360
asconEngine.DoFinal(c7, offset);
357361
asconEngine.Reset();
358362
asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
359-
offset = asconEngine.ProcessBytes(m7, 0, m7.Length, c8, 0);
363+
offset = asconEngine.ProcessBytes(m7, 0, m7.Length / 2, c8, 0);
364+
offset += asconEngine.ProcessBytes(m7, m7.Length / 2, m7.Length - m7.Length / 2, c8, offset);
360365
offset += asconEngine.DoFinal(c8, offset);
361366
asconEngine.Reset();
362367
int split = rand.Next(1, m7.Length);
363368
asconEngine.ProcessAadBytes(aad2, 0, aad2.Length);
364369
offset = asconEngine.ProcessBytes(m7, 0, split, c9, 0);
365370
offset += asconEngine.ProcessBytes(m7, split, m7.Length - split, c9, offset);
366-
asconEngine.DoFinal(c9, offset);
371+
offset += asconEngine.DoFinal(c9, offset);
367372
if (!Arrays.AreEqual(c7, c8) || !Arrays.AreEqual(c7, c9))
368373
{
369374
Assert.Fail("Splitting input of plaintext should output the same ciphertext");
@@ -410,11 +415,19 @@ private void ImplTestParameters(AsconEngine asconEngine, int keySize, int ivSize
410415
"key bytes of " + asconEngine.AlgorithmName + " is not correct");
411416
Assert.AreEqual(ivSize, asconEngine.GetIVBytesSize(),
412417
"iv bytes of " + asconEngine.AlgorithmName + " is not correct");
418+
419+
var parameters = new ParametersWithIV(new KeyParameter(new byte[keySize]), new byte[ivSize]);
420+
421+
asconEngine.Init(true, parameters);
413422
Assert.AreEqual(macSize, asconEngine.GetOutputSize(0),
414-
"mac bytes of " + asconEngine.AlgorithmName + " is not correct");
423+
"GetOutputSize of " + asconEngine.AlgorithmName + " is incorrect for encryption");
424+
425+
asconEngine.Init(false, parameters);
426+
Assert.AreEqual(0, asconEngine.GetOutputSize(macSize),
427+
"GetOutputSize of " + asconEngine.AlgorithmName + " is incorrect for decryption");
415428
}
416429

417-
private void testVectorsHash(AsconDigest.AsconParameters AsconParameters, String filename)
430+
private void ImplTestVectorsHash(AsconDigest.AsconParameters AsconParameters, String filename)
418431
{
419432
AsconDigest Ascon = new AsconDigest(AsconParameters);
420433
var buf = new Dictionary<string, string>();
@@ -455,7 +468,7 @@ private void testVectorsHash(AsconDigest.AsconParameters AsconParameters, String
455468
}
456469
}
457470

458-
private void testExceptions(IDigest digest, int digestsize)
471+
private void ImplTestExceptions(IDigest digest, int digestsize)
459472
{
460473
if (digest.GetDigestSize() != digestsize)
461474
{

0 commit comments

Comments
 (0)