Skip to content

Commit 0f613fa

Browse files
committed
Enable AsconXof to perform multiple outputs
1 parent 0f08ecd commit 0f613fa

File tree

3 files changed

+73
-88
lines changed

3 files changed

+73
-88
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ public void update(byte[] input, int inOff, int len)
127127
@Override
128128
public int doFinal(byte[] output, int outOff)
129129
{
130-
return hash(output, outOff, CRYPTO_BYTES);
130+
int rv = hash(output, outOff, CRYPTO_BYTES);
131+
reset();
132+
return rv;
131133
}
132134

133135
protected void padAndAbsorb()
@@ -149,7 +151,7 @@ protected void squeeze(byte[] output, int outOff, int len)
149151
}
150152
/* squeeze final output block */
151153
setBytes(x0, output, outOff, len);
152-
reset();
154+
p(ASCON_PB_ROUNDS);
153155
}
154156

155157
protected int hash(byte[] output, int outOff, int outLen)
Lines changed: 5 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package org.bouncycastle.crypto.digests;
22

33
import org.bouncycastle.crypto.DataLengthException;
4-
import org.bouncycastle.crypto.OutputLengthException;
5-
import org.bouncycastle.crypto.Xof;
64
import org.bouncycastle.util.Pack;
75

86
/**
@@ -17,10 +15,8 @@
1715
* </p>
1816
*/
1917
public class AsconCXof128
20-
extends AsconBaseDigest
21-
implements Xof
18+
extends AsconXof128
2219
{
23-
private boolean m_squeezing = false;
2420
private final long z0, z1, z2, z3, z4;
2521

2622
public AsconCXof128()
@@ -35,6 +31,7 @@ public AsconCXof128(byte[] s)
3531

3632
public AsconCXof128(byte[] s, int off, int len)
3733
{
34+
super(false);
3835
if ((off + len) > s.length)
3936
{
4037
throw new DataLengthException("input buffer too short");
@@ -52,90 +49,18 @@ public AsconCXof128(byte[] s, int off, int len)
5249
z4 = x4;
5350
}
5451

55-
@Override
56-
public void update(byte in)
57-
{
58-
if (m_squeezing)
59-
{
60-
throw new IllegalArgumentException("attempt to absorb while squeezing");
61-
}
62-
super.update(in);
63-
}
64-
65-
@Override
66-
public void update(byte[] input, int inOff, int len)
67-
{
68-
if (m_squeezing)
69-
{
70-
throw new IllegalArgumentException("attempt to absorb while squeezing");
71-
}
72-
super.update(input, inOff, len);
73-
}
74-
75-
protected long pad(int i)
76-
{
77-
return 0x01L << (i << 3);
78-
}
79-
80-
protected long loadBytes(final byte[] bytes, int inOff)
81-
{
82-
return Pack.littleEndianToLong(bytes, inOff);
83-
}
84-
85-
protected long loadBytes(final byte[] bytes, int inOff, int n)
86-
{
87-
return Pack.littleEndianToLong(bytes, inOff, n);
88-
}
89-
90-
protected void setBytes(long w, byte[] bytes, int inOff)
91-
{
92-
Pack.longToLittleEndian(w, bytes, inOff);
93-
}
94-
95-
protected void setBytes(long w, byte[] bytes, int inOff, int n)
96-
{
97-
Pack.longToLittleEndian(w, bytes, inOff, n);
98-
}
99-
100-
protected void padAndAbsorb()
101-
{
102-
m_squeezing = true;
103-
super.padAndAbsorb();
104-
}
105-
10652
@Override
10753
public String getAlgorithmName()
10854
{
10955
return "Ascon-CXOF128";
11056
}
11157

112-
@Override
113-
public int doOutput(byte[] output, int outOff, int outLen)
114-
{
115-
if (CRYPTO_BYTES + outOff > output.length)
116-
{
117-
throw new OutputLengthException("output buffer is too short");
118-
}
119-
padAndAbsorb();
120-
/* squeeze full output blocks */
121-
squeeze(output, outOff, outLen);
122-
return outLen;
123-
}
124-
125-
126-
@Override
127-
public int doFinal(byte[] output, int outOff, int outLen)
128-
{
129-
int rlt = doOutput(output, outOff, outLen);
130-
reset();
131-
return rlt;
132-
}
133-
13458
@Override
13559
public void reset()
13660
{
137-
super.reset();
61+
baseReset();
13862
m_squeezing = false;
63+
bytesInBuffer = 0;
13964
/* initialize */
14065
x0 = z0;
14166
x1 = z1;
@@ -157,6 +82,6 @@ private void initState(byte[] z, int zOff, int zLen)
15782
update(z, zOff, zLen);
15883
padAndAbsorb();
15984
m_squeezing = false;
85+
bytesInBuffer = 0;
16086
}
16187
}
162-

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

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.bouncycastle.crypto.digests;
22

3+
import org.bouncycastle.crypto.OutputLengthException;
34
import org.bouncycastle.crypto.Xof;
45
import org.bouncycastle.util.Pack;
56

@@ -18,11 +19,22 @@ public class AsconXof128
1819
extends AsconBaseDigest
1920
implements Xof
2021
{
21-
private boolean m_squeezing = false;
22+
protected boolean m_squeezing = false;
23+
24+
private final byte[] buffer = new byte[ASCON_HASH_RATE];
25+
protected int bytesInBuffer;
2226

2327
public AsconXof128()
2428
{
25-
reset();
29+
this(true);
30+
}
31+
32+
protected AsconXof128(final boolean doReset)
33+
{
34+
if (doReset)
35+
{
36+
reset();
37+
}
2638
}
2739

2840
protected long pad(int i)
@@ -52,8 +64,11 @@ protected void setBytes(long w, byte[] bytes, int inOff, int n)
5264

5365
protected void padAndAbsorb()
5466
{
55-
m_squeezing = true;
56-
super.padAndAbsorb();
67+
if (!m_squeezing)
68+
{
69+
m_squeezing = true;
70+
super.padAndAbsorb();
71+
}
5772
}
5873

5974
@Override
@@ -85,7 +100,45 @@ public void update(byte[] input, int inOff, int len)
85100
@Override
86101
public int doOutput(byte[] output, int outOff, int outLen)
87102
{
88-
return hash(output, outOff, outLen);
103+
if (outLen + outOff > output.length)
104+
{
105+
throw new OutputLengthException("output buffer is too short");
106+
}
107+
108+
/* Use buffered output first */
109+
int bytesOutput = 0;
110+
if (bytesInBuffer != 0)
111+
{
112+
int startPos = ASCON_HASH_RATE - bytesInBuffer;
113+
int bytesToOutput = Math.min(outLen, bytesInBuffer);
114+
System.arraycopy(buffer, startPos, output, outOff, bytesToOutput);
115+
bytesInBuffer -= bytesToOutput;
116+
bytesOutput += bytesToOutput;
117+
}
118+
119+
/* If we still need to output data */
120+
if (outLen - bytesOutput >= ASCON_HASH_RATE)
121+
{
122+
/* Output full blocks */
123+
int bytesToOutput = ASCON_HASH_RATE * ((outLen - bytesOutput) / ASCON_HASH_RATE);
124+
bytesOutput += hash(output, outOff + bytesOutput, bytesToOutput);
125+
}
126+
127+
/* If we need to output a partial buffer */
128+
if (bytesOutput < outLen)
129+
{
130+
/* Access the next buffer's worth of data */
131+
hash(buffer, 0, ASCON_HASH_RATE);
132+
133+
/* Copy required length of data */
134+
int bytesToOutput = outLen - bytesOutput;
135+
System.arraycopy(buffer, 0, output, outOff + bytesOutput, bytesToOutput);
136+
bytesInBuffer = buffer.length - bytesToOutput;
137+
bytesOutput += bytesToOutput;
138+
}
139+
140+
/* return the length of data output */
141+
return bytesOutput;
89142
}
90143

91144
@Override
@@ -106,6 +159,7 @@ public int getByteLength()
106159
public void reset()
107160
{
108161
m_squeezing = false;
162+
bytesInBuffer = 0;
109163
super.reset();
110164
/* initialize */
111165
x0 = -2701369817892108309L;
@@ -114,5 +168,9 @@ public void reset()
114168
x3 = 1072114354614917324L;
115169
x4 = -2282070310009238562L;
116170
}
117-
}
118171

172+
protected void baseReset()
173+
{
174+
super.reset();
175+
}
176+
}

0 commit comments

Comments
 (0)