Skip to content

Commit 6ddc87c

Browse files
author
gefeili
committed
Finish the work on the counter
1 parent 043b54c commit 6ddc87c

File tree

3 files changed

+195
-52
lines changed

3 files changed

+195
-52
lines changed

core/src/main/java/org/bouncycastle/crypto/engines/AEADBaseEngine.java

Lines changed: 154 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,12 @@ protected static class AADOperatorType
3838
public static final int DEFAULT = 0;
3939
public static final int COUNTER = 1;//add a counter to count the size of AAD
4040
public static final int STREAM = 2; //process AAD data during the process data, used for elephant
41+
public static final int DATA_LIMIT = 3;// count AAD data to the counter, used for AsconAEAD128
4142

4243
public static final AADOperatorType Default = new AADOperatorType(DEFAULT);
4344
public static final AADOperatorType Counter = new AADOperatorType(COUNTER);
4445
public static final AADOperatorType Stream = new AADOperatorType(STREAM);
46+
public static final AADOperatorType DataLimit = new AADOperatorType(DATA_LIMIT);
4547

4648
private final int ord;
4749

@@ -57,11 +59,13 @@ protected static class DataOperatorType
5759
public static final int COUNTER = 1;
5860
public static final int STREAM = 2;
5961
public static final int STREAM_CIPHER = 3;
62+
public static final int DATA_LIMIT = 4; // count AAD data to the counter, used for AsconAEAD128
6063

6164
public static final DataOperatorType Default = new DataOperatorType(DEFAULT);
6265
public static final DataOperatorType Counter = new DataOperatorType(COUNTER);
6366
public static final DataOperatorType Stream = new DataOperatorType(STREAM);
6467
public static final DataOperatorType StreamCipher = new DataOperatorType(STREAM_CIPHER);
68+
public static final DataOperatorType DataLimit = new DataOperatorType(DATA_LIMIT);
6569

6670
private final int ord;
6771

@@ -121,7 +125,8 @@ protected static class State
121125
protected AADOperator aadOperator;
122126
protected DataOperator dataOperator;
123127
//Only AsconAEAD128 uses this counter;
124-
protected Counter decryptionFailureCounter = null;
128+
protected DecryptionFailureCounter decryptionFailureCounter = null;
129+
protected DataLimitCounter dataLimitCounter = null;
125130

126131
@Override
127132
public String getAlgorithmName()
@@ -210,6 +215,10 @@ else if (params instanceof ParametersWithIV)
210215

211216
m_state = forEncryption ? State.EncInit : State.DecInit;
212217
init(k, npub);
218+
if (dataLimitCounter != null)
219+
{
220+
dataLimitCounter.increment(npub.length);
221+
}
213222
reset(true);
214223
if (initialAssociatedText != null)
215224
{
@@ -290,6 +299,10 @@ protected void setInnerMembers(ProcessingBufferType type, AADOperatorType aadOpe
290299
AADBufferSize = 0;
291300
aadOperator = new StreamAADOperator();
292301
break;
302+
case AADOperatorType.DATA_LIMIT:
303+
m_aad = new byte[AADBufferSize];
304+
aadOperator = new DataLimitAADOperator();
305+
break;
293306
}
294307

295308
switch (dataOperatorType.ord)
@@ -311,6 +324,10 @@ protected void setInnerMembers(ProcessingBufferType type, AADOperatorType aadOpe
311324
m_buf = new byte[m_bufferSizeDecrypt];
312325
dataOperator = new StreamCipherOperator();
313326
break;
327+
case DataOperatorType.DATA_LIMIT:
328+
m_buf = new byte[m_bufferSizeDecrypt];
329+
dataOperator = new DataLimitDataOperator();
330+
break;
314331
}
315332
}
316333

@@ -511,6 +528,34 @@ public int getLen()
511528
}
512529
}
513530

531+
private class DataLimitAADOperator
532+
implements AADOperator
533+
{
534+
@Override
535+
public void processAADByte(byte input)
536+
{
537+
dataLimitCounter.increment();
538+
processor.processAADByte(input);
539+
}
540+
541+
@Override
542+
public void processAADBytes(byte[] input, int inOff, int len)
543+
{
544+
dataLimitCounter.increment(len);
545+
processAadBytes(input, inOff, len);
546+
}
547+
548+
public void reset()
549+
{
550+
}
551+
552+
@Override
553+
public int getLen()
554+
{
555+
return m_aadPos;
556+
}
557+
}
558+
514559
protected interface DataOperator
515560
{
516561
int processByte(byte input, byte[] output, int outOff);
@@ -707,7 +752,34 @@ public void reset()
707752
}
708753
}
709754

710-
protected static class Counter
755+
private class DataLimitDataOperator
756+
implements DataOperator
757+
{
758+
public int processByte(byte input, byte[] output, int outOff)
759+
{
760+
dataLimitCounter.increment();
761+
return processor.processByte(input, output, outOff);
762+
}
763+
764+
public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
765+
{
766+
dataLimitCounter.increment(len);
767+
return processEncDecBytes(input, inOff, len, output, outOff);
768+
}
769+
770+
@Override
771+
public int getLen()
772+
{
773+
return m_bufPos;
774+
}
775+
776+
@Override
777+
public void reset()
778+
{
779+
}
780+
}
781+
782+
protected static class DecryptionFailureCounter
711783
{
712784
private int n;
713785
private int[] counter;
@@ -739,19 +811,92 @@ public boolean increment()
739811
break;
740812
}
741813
}
742-
for (i = 1; i < counter.length; ++i)
814+
int r = n & 31;
815+
return i <= 0 && counter[0] == (r == 0 ? 0 : (1 << r));
816+
}
817+
818+
// In case when we need to use this counter to count data limit
819+
// public boolean increment(int delta)
820+
// {
821+
// // Convert to long to handle unsigned arithmetic
822+
// long carry = delta & 0xFFFFFFFFL;
823+
// // Process each word starting from LSB
824+
// int i = counter.length;
825+
// while (carry != 0 && --i >= 0)
826+
// {
827+
// long sum = (counter[i] & 0xFFFFFFFFL) + carry;
828+
// counter[i] = (int)sum;
829+
// carry = sum >>> 32;
830+
// }
831+
//
832+
// // Final limit check if we didn't overflow
833+
// return carry != 0 || checkLimit();
834+
// }
835+
//
836+
// private boolean checkLimit()
837+
// {
838+
// int bitIndex = ((n - 1) & 31) + 1;
839+
// long bound = 1L << bitIndex;
840+
// long val = counter[0] & 0xFFFFFFFFL;
841+
// if (val > bound)
842+
// {
843+
// return true;
844+
// }
845+
// if (val < bound)
846+
// {
847+
// return false;
848+
// }
849+
// // Check if we've reached/exceeded 2^n
850+
// for (int i = 1; i < counter.length; ++i)
851+
// {
852+
// val = counter[i] & 0xFFFFFFFFL;
853+
// if (val > 0)
854+
// {
855+
// return true;
856+
// }
857+
// }
858+
// return true; // Exactly equal to 2^n
859+
// }
860+
861+
public void reset()
862+
{
863+
Arrays.fill(counter, 0);
864+
}
865+
}
866+
867+
protected static class DataLimitCounter
868+
{
869+
//if the maximum exceed Long.MAX_VALUE, Improve DecryptionFailureCounter and use it instead
870+
private long count;
871+
private long max;
872+
private int n;
873+
874+
public void init(int n)
875+
{
876+
this.n = n;
877+
this.max = 1L << n;
878+
}
879+
880+
public void increment()
881+
{
882+
if (++count > max)
743883
{
744-
if (counter[i] != 0)
745-
{
746-
return false;
747-
}
884+
throw new IllegalStateException("Total data limit exceeded: maximum 2^" + n + " bytes per key (including nonce, AAD, and message)");
885+
}
886+
}
887+
888+
public void increment(int n)
889+
{
890+
count += n;
891+
if (count > max)
892+
{
893+
throw new IllegalStateException("Total data limit exceeded: maximum 2^" + n + " bytes per key (including nonce, AAD, and message)");
748894
}
749-
return counter[0] != ((n & 31) == 0 ? 0 : 1 << (n & 31));
750895
}
751896

752897
public void reset()
753898
{
754-
Arrays.fill(counter, 0);
899+
count = 0;
755900
}
756901
}
757902

core/src/main/java/org/bouncycastle/crypto/engines/AsconAEAD128.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ public AsconAEAD128()
2727
nr = 8;
2828
dsep = -9223372036854775808L; //0x80L << 56
2929
macSizeLowerBound = 4;
30-
setInnerMembers(ProcessingBufferType.Immediate, AADOperatorType.Default, DataOperatorType.Default);
31-
decryptionFailureCounter = new Counter();
30+
dataLimitCounter = new DataLimitCounter();
31+
dataLimitCounter.init(54);
32+
setInnerMembers(ProcessingBufferType.Immediate, AADOperatorType.DataLimit, DataOperatorType.DataLimit);
33+
decryptionFailureCounter = new DecryptionFailureCounter();
3234
}
3335

3436
protected long pad(int i)
@@ -148,6 +150,7 @@ protected void init(byte[] key, byte[] iv)
148150
decryptionFailureCounter.init(lambda);
149151
if (this.K0 != K0 || this.K1 != K1)
150152
{
153+
dataLimitCounter.reset();
151154
decryptionFailureCounter.reset();
152155
this.K0 = K0;
153156
this.K1 = K1;

core/src/test/java/org/bouncycastle/crypto/test/AsconTest.java

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,43 +1389,30 @@ public boolean increment()
13891389
break;
13901390
}
13911391
}
1392-
for (i = 1; i < counter.length; ++i)
1393-
{
1394-
if (counter[i] != 0)
1395-
{
1396-
return false;
1397-
}
1398-
}
1399-
return counter[0] == 1 << (n & 31);
1392+
int r = n & 31;
1393+
return i <= 0 && counter[0] == (r == 0 ? 0 : (1 << r));
14001394
}
14011395

14021396
public boolean increment(int delta)
14031397
{
14041398
// Convert to long to handle unsigned arithmetic
14051399
long carry = delta & 0xFFFFFFFFL;
1406-
boolean limitReached = false;
1407-
14081400
// Process each word starting from LSB
1409-
for (int i = counter.length - 1; i >= 0 && carry != 0; --i)
1401+
int i = counter.length;
1402+
while (carry != 0 && --i >= 0)
14101403
{
14111404
long sum = (counter[i] & 0xFFFFFFFFL) + carry;
14121405
counter[i] = (int)sum;
14131406
carry = sum >>> 32;
1414-
1415-
// Check if we've passed the limit during carry propagation
1416-
if (carry != 0 && i == counter.length - 1)
1417-
{
1418-
limitReached = true;
1419-
}
14201407
}
14211408

14221409
// Final limit check if we didn't overflow
1423-
return limitReached || checkLimit();
1410+
return carry != 0 || checkLimit();
14241411
}
14251412

14261413
private boolean checkLimit()
14271414
{
1428-
int bitIndex = n & 31;
1415+
int bitIndex = ((n - 1) & 31) + 1;
14291416
long bound = 1L << bitIndex;
14301417
long val = counter[0] & 0xFFFFFFFFL;
14311418
if (val > bound)
@@ -1456,29 +1443,37 @@ public void reset()
14561443

14571444
public void testCounter()
14581445
{
1459-
// int n = 33;
14601446
Counter counter = new Counter();
1461-
// counter.init(33);
1462-
// isTrue(!counter.increment(-1));
1463-
// isTrue(!counter.increment());
1464-
// isTrue(!counter.increment(-1));
1465-
// isTrue(counter.increment());
1466-
//
1467-
// counter.init(32);
1468-
// isTrue(!counter.increment(-1));
1469-
// isTrue(counter.increment());
1470-
// counter.reset();
1471-
// isTrue(!counter.increment());
1472-
// counter.reset();
1473-
// isTrue(!counter.increment(-1));
1474-
// isTrue(counter.increment(1));
1475-
//
1476-
// counter.init(31);
1477-
// isTrue(!counter.increment(1 << 30));
1478-
// isTrue(counter.increment());
1479-
// counter.reset();
1480-
// isTrue(!counter.increment(1 << 30));
1481-
// isTrue(counter.increment(1 << 30));
1447+
counter.init(64);
1448+
isTrue(!counter.increment(-1));
1449+
isTrue(!counter.increment());
1450+
isTrue(!counter.increment(-1));
1451+
isTrue(!counter.increment());
1452+
1453+
counter.init(33);
1454+
isTrue(!counter.increment(-1));
1455+
isTrue(!counter.increment());
1456+
isTrue(!counter.increment(-1));
1457+
isTrue(counter.increment());
1458+
1459+
counter.init(32);
1460+
isTrue(!counter.increment(-1));
1461+
isTrue(counter.increment());
1462+
counter.reset();
1463+
isTrue(!counter.increment());
1464+
counter.reset();
1465+
isTrue(!counter.increment(-1));
1466+
isTrue(counter.increment(1));
1467+
1468+
counter.init(31);
1469+
isTrue(!counter.increment((1 << 31) - 1));
1470+
isTrue(counter.increment());
1471+
counter.reset();
1472+
isTrue(!counter.increment(1 << 30));
1473+
isTrue(counter.increment(1 << 30));
1474+
counter.reset();
1475+
isTrue(!counter.increment(1 << 30));
1476+
isTrue(counter.increment((1 << 30) + 1));
14821477

14831478
counter.init(5);
14841479
isTrue(!counter.increment((1 << 5) - 1));

0 commit comments

Comments
 (0)