Skip to content

Commit 5815000

Browse files
author
gefeili
committed
Fix bugs in AsconAEAD128Engine. Pass Asconxof128
1 parent 512dfde commit 5815000

File tree

5 files changed

+270
-141
lines changed

5 files changed

+270
-141
lines changed

core/src/main/java/org/bouncycastle/crypto/digests/AsconXof.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
import org.bouncycastle.crypto.OutputLengthException;
77
import org.bouncycastle.crypto.Xof;
88

9-
/* ASCON v1.2 XOF, https://ascon.iaik.tugraz.at/ .
9+
/** ASCON v1.2 XOF, https://ascon.iaik.tugraz.at/ .
1010
* <p>
1111
* https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/ascon-spec-final.pdf
1212
* <p>
1313
* ASCON v1.2 XOF with reference to C Reference Impl from: https://github.com/ascon/ascon-c .
14+
* @deprecated Now superseded - please use AsconXof128
1415
*/
1516
public class AsconXof
1617
implements Xof
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
package org.bouncycastle.crypto.digests;
2+
3+
import java.io.ByteArrayOutputStream;
4+
5+
import org.bouncycastle.crypto.DataLengthException;
6+
import org.bouncycastle.crypto.OutputLengthException;
7+
import org.bouncycastle.crypto.Xof;
8+
import org.bouncycastle.util.Pack;
9+
10+
/**
11+
* ASCON v1.2 XOF, https://ascon.iaik.tugraz.at/ .
12+
* <p>
13+
* https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/ascon-spec-final.pdf
14+
* <p>
15+
* ASCON v1.2 XOF with reference to C Reference Impl from: https://github.com/ascon/ascon-c .
16+
*
17+
*/
18+
public class AsconXof128
19+
implements Xof
20+
{
21+
public AsconXof128()
22+
{
23+
reset();
24+
}
25+
26+
private final String algorithmName = "Ascon-XOF-128";
27+
private final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
28+
private long x0;
29+
private long x1;
30+
private long x2;
31+
private long x3;
32+
private long x4;
33+
private final int CRYPTO_BYTES = 32;
34+
private final int ASCON_PB_ROUNDS = 12;
35+
36+
private long ROR(long x, int n)
37+
{
38+
return x >>> n | x << (64 - n);
39+
}
40+
41+
private void ROUND(long C)
42+
{
43+
long t0 = x0 ^ x1 ^ x2 ^ x3 ^ C ^ (x1 & (x0 ^ x2 ^ x4 ^ C));
44+
long t1 = x0 ^ x2 ^ x3 ^ x4 ^ C ^ ((x1 ^ x2 ^ C) & (x1 ^ x3));
45+
long t2 = x1 ^ x2 ^ x4 ^ C ^ (x3 & x4);
46+
long t3 = x0 ^ x1 ^ x2 ^ C ^ ((~x0) & (x3 ^ x4));
47+
long t4 = x1 ^ x3 ^ x4 ^ ((x0 ^ x4) & x1);
48+
x0 = t0 ^ ROR(t0, 19) ^ ROR(t0, 28);
49+
x1 = t1 ^ ROR(t1, 39) ^ ROR(t1, 61);
50+
x2 = ~(t2 ^ ROR(t2, 1) ^ ROR(t2, 6));
51+
x3 = t3 ^ ROR(t3, 10) ^ ROR(t3, 17);
52+
x4 = t4 ^ ROR(t4, 7) ^ ROR(t4, 41);
53+
}
54+
55+
private void P(int nr)
56+
{
57+
if (nr == 12)
58+
{
59+
ROUND(0xf0L);
60+
ROUND(0xe1L);
61+
ROUND(0xd2L);
62+
ROUND(0xc3L);
63+
}
64+
if (nr >= 8)
65+
{
66+
ROUND(0xb4L);
67+
ROUND(0xa5L);
68+
}
69+
ROUND(0x96L);
70+
ROUND(0x87L);
71+
ROUND(0x78L);
72+
ROUND(0x69L);
73+
ROUND(0x5aL);
74+
ROUND(0x4bL);
75+
}
76+
77+
private long PAD(int i)
78+
{
79+
return 0x01L << (i << 3);
80+
}
81+
82+
@Override
83+
public String getAlgorithmName()
84+
{
85+
return algorithmName;
86+
}
87+
88+
@Override
89+
public int getDigestSize()
90+
{
91+
return CRYPTO_BYTES;
92+
}
93+
94+
@Override
95+
public void update(byte in)
96+
{
97+
buffer.write(in);
98+
}
99+
100+
@Override
101+
public void update(byte[] input, int inOff, int len)
102+
{
103+
if ((inOff + len) > input.length)
104+
{
105+
throw new DataLengthException("input buffer too short");
106+
}
107+
buffer.write(input, inOff, len);
108+
}
109+
110+
@Override
111+
public int doOutput(byte[] output, int outOff, int outLen)
112+
{
113+
if (CRYPTO_BYTES + outOff > output.length)
114+
{
115+
throw new OutputLengthException("output buffer is too short");
116+
}
117+
byte[] input = buffer.toByteArray();
118+
int len = buffer.size();
119+
int inOff = 0;
120+
/* absorb full plaintext blocks */
121+
int ASCON_HASH_RATE = 8;
122+
while (len >= ASCON_HASH_RATE)
123+
{
124+
x0 ^= Pack.littleEndianToLong(input, inOff, 8);
125+
P(ASCON_PB_ROUNDS);
126+
inOff += ASCON_HASH_RATE;
127+
len -= ASCON_HASH_RATE;
128+
}
129+
/* absorb final plaintext block */
130+
x0 ^= Pack.littleEndianToLong(input, inOff, len);
131+
x0 ^= PAD(len);
132+
P(12);
133+
/* squeeze full output blocks */
134+
len = CRYPTO_BYTES;
135+
while (len > ASCON_HASH_RATE)
136+
{
137+
Pack.longToLittleEndian(x0, output, outOff, 8);
138+
P(ASCON_PB_ROUNDS);
139+
outOff += ASCON_HASH_RATE;
140+
len -= ASCON_HASH_RATE;
141+
}
142+
/* squeeze final output block */
143+
Pack.longToLittleEndian(x0, output, outOff, len);
144+
reset();
145+
return CRYPTO_BYTES;
146+
}
147+
148+
@Override
149+
public int doFinal(byte[] output, int outOff)
150+
{
151+
return doOutput(output, outOff, getDigestSize());
152+
}
153+
154+
@Override
155+
public int doFinal(byte[] output, int outOff, int outLen)
156+
{
157+
return doOutput(output, outOff, outLen);
158+
}
159+
160+
@Override
161+
public int getByteLength()
162+
{
163+
return 8;
164+
}
165+
166+
@Override
167+
public void reset()
168+
{
169+
buffer.reset();
170+
/* initialize */
171+
x0 = -2701369817892108309L;
172+
x1 = -3711838248891385495L;
173+
x2 = -1778763697082575311L;
174+
x3 = 1072114354614917324L;
175+
x4 = -2282070310009238562L;
176+
}
177+
}
178+

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

Lines changed: 41 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,11 @@ private void P(int nr)
9393
ROUND(0xd2L);
9494
ROUND(0xc3L);
9595
}
96-
ROUND(0xb4L);
97-
ROUND(0xa5L);
96+
if (nr >= 8)
97+
{
98+
ROUND(0xb4L);
99+
ROUND(0xa5L);
100+
}
98101
ROUND(0x96L);
99102
ROUND(0x87L);
100103
ROUND(0x78L);
@@ -197,40 +200,33 @@ private void finishAAD(State nextState)
197200
m_state = nextState;
198201
}
199202

200-
private void processBufferDecrypt(byte[] buffer, int bufOff, byte[] output, int outOff)
203+
private void processBufferDecrypt(byte[] buffer, int bufOff, int bufLen, byte[] output, int outOff)
201204
{
202205
if (outOff + ASCON_AEAD_RATE > output.length)
203206
{
204207
throw new OutputLengthException("output buffer too short");
205208
}
206-
long t0 = Pack.littleEndianToLong(buffer, bufOff);
207-
Pack.longToLittleEndian(x0 ^ t0, output, outOff);
208-
x0 = t0;
209+
long c0 = Pack.littleEndianToLong(buffer, bufOff);
210+
long c1 = Pack.littleEndianToLong(buffer, bufOff + 8, 8);
211+
212+
Pack.longToLittleEndian(x0 ^ c0, output, outOff);
213+
Pack.longToLittleEndian(x1 ^ c1, output, outOff + 8, 8);
214+
x0 = c0;
215+
x1 = c1;
209216

210-
if (ASCON_AEAD_RATE == 16)
211-
{
212-
long t1 = Pack.littleEndianToLong(buffer, bufOff + 8);
213-
Pack.longToLittleEndian(x1 ^ t1, output, outOff + 8);
214-
x1 = t1;
215-
}
216217
P(nr);
217218
}
218219

219-
private void processBufferEncrypt(byte[] buffer, int bufOff, byte[] output, int outOff)
220+
private void processBufferEncrypt(byte[] buffer, int bufOff, int bufLen, byte[] output, int outOff)
220221
{
221222
if (outOff + ASCON_AEAD_RATE > output.length)
222223
{
223224
throw new OutputLengthException("output buffer too short");
224225
}
225-
x0 ^= Pack.littleEndianToLong(buffer, bufOff);
226+
x0 ^= Pack.littleEndianToLong(buffer, bufOff, 8);
227+
x1 ^= Pack.littleEndianToLong(buffer, bufOff + 8, 8);
226228
Pack.longToLittleEndian(x0, output, outOff);
227-
228-
if (ASCON_AEAD_RATE == 16)
229-
{
230-
x1 ^= Pack.littleEndianToLong(buffer, bufOff + 8);
231-
Pack.longToLittleEndian(x1, output, outOff + 8);
232-
}
233-
229+
Pack.longToLittleEndian(x1, output, outOff + 8);
234230
P(nr);
235231
}
236232

@@ -239,33 +235,27 @@ private void processFinalDecrypt(byte[] input, int inOff, int inLen, byte[] outp
239235
if (inLen >= 8) // ASCON_AEAD_RATE == 16 is implied
240236
{
241237
long c0 = Pack.littleEndianToLong(input, inOff);
242-
x0 ^= c0;
243-
Pack.longToLittleEndian(x0, output, outOff);
238+
long c1 = Pack.littleEndianToLong(input, inOff + 8, inLen - 8);
239+
240+
Pack.longToLittleEndian(x0 ^ c0, output, outOff);
241+
Pack.longToLittleEndian(x1 ^ c1, output, outOff + 8, inLen - 8);
242+
244243
x0 = c0;
245-
inOff += 8;
246-
outOff += 8;
247244
inLen -= 8;
245+
x1 &= -(1L << (inLen << 3));
246+
x1 |= c1;
248247
x1 ^= PAD(inLen);
249-
if (inLen != 0)
250-
{
251-
long c1 = Pack.littleEndianToLong_High(input, inOff, inLen);
252-
x1 ^= c1;
253-
Pack.longToLittleEndian_High(x1, output, outOff, inLen);
254-
x1 &= -1L >>> (inLen << 3);
255-
x1 ^= c1;
256-
}
257248
}
258249
else
259250
{
260-
x0 ^= PAD(inLen);
261251
if (inLen != 0)
262252
{
263-
long c0 = Pack.littleEndianToLong_High(input, inOff, inLen);
264-
x0 ^= c0;
265-
Pack.longToLittleEndian_High(x0, output, outOff, inLen);
266-
x0 &= -1L >>> (inLen << 3);
267-
x0 ^= c0;
253+
long c0 = Pack.littleEndianToLong(input, inOff, inLen);
254+
Pack.longToLittleEndian(x0 ^ c0, output, outOff, inLen);
255+
x0 &= -(1L << (inLen << 3));
256+
x0 |= c0;
268257
}
258+
x0 ^= PAD(inLen);
269259
}
270260

271261
finishData(State.DecFinal);
@@ -276,26 +266,23 @@ private void processFinalEncrypt(byte[] input, int inOff, int inLen, byte[] outp
276266
if (inLen >= 8) // ASCON_AEAD_RATE == 16 is implied
277267
{
278268
x0 ^= Pack.littleEndianToLong(input, inOff);
269+
x1 ^= Pack.littleEndianToLong(input, inOff + 8, inLen - 8);
279270
Pack.longToLittleEndian(x0, output, outOff);
280-
inOff += 8;
281-
outOff += 8;
271+
Pack.longToLittleEndian(x1, output, outOff + 8);
282272
inLen -= 8;
283273
x1 ^= PAD(inLen);
284-
if (inLen != 0)
285-
{
286-
x1 ^= Pack.littleEndianToLong_High(input, inOff, inLen);
287-
Pack.longToLittleEndian_High(x1, output, outOff, inLen);
288-
}
289274
}
290275
else
291276
{
292-
x0 ^= PAD(inLen);
293277
if (inLen != 0)
294278
{
295-
x0 ^= Pack.littleEndianToLong_High(input, inOff, inLen);
296-
Pack.longToLittleEndian_High(x0, output, outOff, inLen);
279+
x0 ^= Pack.littleEndianToLong(input, inOff, inLen);
280+
Pack.longToLittleEndian(x0, output, outOff, inLen);
297281
}
282+
x0 ^= PAD(inLen);
298283
}
284+
285+
299286
finishData(State.EncFinal);
300287
}
301288

@@ -455,14 +442,14 @@ public int processBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int
455442
inOff += available;
456443
len -= available;
457444

458-
processBufferEncrypt(m_buf, 0, outBytes, outOff);
445+
processBufferEncrypt(m_buf, 0, m_bufPos, outBytes, outOff);
459446
resultLength = ASCON_AEAD_RATE;
460447
//m_bufPos = 0;
461448
}
462449

463450
while (len >= ASCON_AEAD_RATE)
464451
{
465-
processBufferEncrypt(inBytes, inOff, outBytes, outOff + resultLength);
452+
processBufferEncrypt(inBytes, inOff, ASCON_AEAD_RATE, outBytes, outOff + resultLength);
466453
inOff += ASCON_AEAD_RATE;
467454
len -= ASCON_AEAD_RATE;
468455
resultLength += ASCON_AEAD_RATE;
@@ -481,7 +468,7 @@ public int processBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int
481468
// NOTE: Need 'while' here because ASCON_AEAD_RATE < CRYPTO_ABYTES in some parameter sets
482469
while (m_bufPos >= ASCON_AEAD_RATE)
483470
{
484-
processBufferDecrypt(m_buf, 0, outBytes, outOff + resultLength);
471+
processBufferDecrypt(m_buf, 0, m_bufPos, outBytes, outOff + resultLength);
485472
m_bufPos -= ASCON_AEAD_RATE;
486473
System.arraycopy(m_buf, ASCON_AEAD_RATE, m_buf, 0, m_bufPos);
487474
resultLength += ASCON_AEAD_RATE;
@@ -499,13 +486,13 @@ public int processBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int
499486
System.arraycopy(inBytes, inOff, m_buf, m_bufPos, available);
500487
inOff += available;
501488
len -= available;
502-
processBufferDecrypt(m_buf, 0, outBytes, outOff + resultLength);
489+
processBufferDecrypt(m_buf, 0, m_bufPos, outBytes, outOff + resultLength);
503490
resultLength += ASCON_AEAD_RATE;
504491
//m_bufPos = 0;
505492

506493
while (len >= m_bufferSizeDecrypt)
507494
{
508-
processBufferDecrypt(inBytes, inOff, outBytes, outOff + resultLength);
495+
processBufferDecrypt(inBytes, inOff, ASCON_AEAD_RATE, outBytes, outOff + resultLength);
509496
inOff += ASCON_AEAD_RATE;
510497
len -= ASCON_AEAD_RATE;
511498
resultLength += ASCON_AEAD_RATE;

0 commit comments

Comments
 (0)