11package org .bouncycastle .crypto .engines ;
22
3- import java .io .ByteArrayOutputStream ;
4-
53import org .bouncycastle .crypto .CipherParameters ;
64import org .bouncycastle .crypto .DataLengthException ;
75import org .bouncycastle .crypto .InvalidCipherTextException ;
119import org .bouncycastle .util .Pack ;
1210
1311/**
14- * Xoodyak v1, https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/xoodyak-spec-final.pdf
12+ * Xoodyak v1, <a href=" https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/xoodyak-spec-final.pdf"></a>
1513 * <p>
16- * Xoodyak with reference to C Reference Impl from: https://github.com/XKCP/XKCP
14+ * Xoodyak with reference to C Reference Impl from: <a href=" https://github.com/XKCP/XKCP"></a>
1715 * </p>
1816 */
1917
@@ -34,9 +32,11 @@ public class XoodyakEngine
3432 private boolean aadFinished ;
3533 private boolean encrypted ;
3634 private boolean initialised = false ;
37- private final ByteArrayOutputStream aadData = new ByteArrayOutputStream () ;
35+ private final byte [] aadData = new byte [ Rkin ] ;
3836 private byte [] message ;
3937 private int messageOff ;
38+ private int aadOff ;
39+ private byte aadcd ;
4040
4141 enum MODE
4242 {
@@ -75,7 +75,13 @@ public void processAADByte(byte input)
7575 throw new IllegalArgumentException ("AAD cannot be added after reading a full block(" + Rkout +
7676 " bytes) of input for " + (forEncryption ? "encryption" : "decryption" ));
7777 }
78- aadData .write (input );
78+ if (aadOff >= aadData .length )
79+ {
80+ AbsorbAny (aadData , 0 , aadData .length , aadcd );
81+ aadcd = 0 ;
82+ aadOff = 0 ;
83+ }
84+ aadData [aadOff ++] = input ;
7985 }
8086
8187 @ Override
@@ -90,15 +96,33 @@ public void processAADBytes(byte[] input, int inOff, int len)
9096 {
9197 throw new DataLengthException ("input buffer too short" );
9298 }
93- aadData .write (input , inOff , len );
99+ if (aadOff + len >= Rkin )
100+ {
101+ System .arraycopy (input , inOff , aadData , aadOff , Rkin - aadOff );
102+ AbsorbAny (aadData , 0 , aadData .length , aadcd );
103+ aadcd = 0 ;
104+ aadOff = Rkin - aadOff ;
105+ inOff += aadOff ;
106+ len -= aadOff ;
107+ aadOff = 0 ;
108+ }
109+ int tmp = len / Rkin ;
110+ if (tmp > 0 )
111+ {
112+ tmp *= Rkin ;
113+ AbsorbAny (input , inOff , tmp , aadcd );
114+ inOff += tmp ;
115+ len -= tmp ;
116+ }
117+ System .arraycopy (input , inOff , aadData , aadOff , len );
118+ aadOff += len ;
94119 }
95120
96121 private void processAAD ()
97122 {
98123 if (!aadFinished )
99124 {
100- byte [] ad = aadData .toByteArray ();
101- AbsorbAny (ad , ad .length , Rkin , 0x03 );
125+ AbsorbAny (aadData , 0 , aadOff , aadcd );
102126 aadFinished = true ;
103127 }
104128 }
@@ -268,7 +292,9 @@ protected void reset(boolean clearMac)
268292 phase = PhaseUp ;
269293 Arrays .fill (message , (byte )0 );
270294 messageOff = 0 ;
271- aadData .reset ();
295+ Arrays .fill (aadData , (byte )0 );
296+ aadOff = 0 ;
297+ aadcd = (byte )0x03 ;
272298 //Absorb key
273299 int KLen = K .length ;
274300 int IDLen = iv .length ;
@@ -277,21 +303,20 @@ protected void reset(boolean clearMac)
277303 System .arraycopy (K , 0 , KID , 0 , KLen );
278304 System .arraycopy (iv , 0 , KID , KLen , IDLen );
279305 KID [KLen + IDLen ] = (byte )IDLen ;
280- AbsorbAny (KID , KLen + IDLen + 1 , Rkin , 0x02 );
306+ AbsorbAny (KID , 0 , KLen + IDLen + 1 , 0x02 );
281307 super .reset (clearMac );
282308 }
283309
284- private void AbsorbAny (byte [] X , int XLen , int r , int Cd )
310+ private void AbsorbAny (byte [] X , int Xoff , int XLen , int Cd )
285311 {
286- int Xoff = 0 ;
287312 int splitLen ;
288313 do
289314 {
290315 if (phase != PhaseUp )
291316 {
292317 Up (null , 0 , 0 );
293318 }
294- splitLen = Math .min (XLen , r );
319+ splitLen = Math .min (XLen , Rkin );
295320 Down (X , Xoff , splitLen , Cd );
296321 Cd = 0 ;
297322 Xoff += splitLen ;
@@ -320,8 +345,7 @@ private void Up(byte[] Yi, int YiLen, int Cu)
320345 int a10 = Pack .littleEndianToInt (state , 40 );
321346 int a11 = Pack .littleEndianToInt (state , 44 );
322347
323- int MAXROUNDS = 12 ;
324- for (int i = 0 ; i < MAXROUNDS ; ++i )
348+ for (int i = 0 ; i < 12 ; ++i )
325349 {
326350 /* Theta: Column Parity Mixer */
327351 int p0 = a0 ^ a4 ^ a8 ;
0 commit comments