@@ -36,7 +36,8 @@ public class XoodyakEngine
3636 private boolean encrypted ;
3737 private boolean initialised = false ;
3838 private final ByteArrayOutputStream aadData = new ByteArrayOutputStream ();
39- private final ByteArrayOutputStream message = new ByteArrayOutputStream ();
39+ private byte [] message ;
40+ private int messageOff ;
4041
4142 enum MODE
4243 {
@@ -62,6 +63,8 @@ public void init(boolean forEncryption, CipherParameters params)
6263 state = new byte [48 ];
6364 mac = new byte [MAC_SIZE ];
6465 initialised = true ;
66+ message = new byte [forEncryption ? Rkout : Rkout + MAC_SIZE ];
67+ messageOff = 0 ;
6568 reset ();
6669 }
6770
@@ -70,7 +73,7 @@ public void processAADByte(byte input)
7073 {
7174 if (aadFinished )
7275 {
73- throw new IllegalArgumentException ("AAD cannot be added after reading a full block(" + getBlockSize () +
76+ throw new IllegalArgumentException ("AAD cannot be added after reading a full block(" + Rkout +
7477 " bytes) of input for " + (forEncryption ? "encryption" : "decryption" ));
7578 }
7679 aadData .write (input );
@@ -81,7 +84,7 @@ public void processAADBytes(byte[] input, int inOff, int len)
8184 {
8285 if (aadFinished )
8386 {
84- throw new IllegalArgumentException ("AAD cannot be added after reading a full block(" + getBlockSize () +
87+ throw new IllegalArgumentException ("AAD cannot be added after reading a full block(" + Rkout +
8588 " bytes) of input for " + (forEncryption ? "encryption" : "decryption" ));
8689 }
8790 if ((inOff + len ) > input .length )
@@ -96,7 +99,7 @@ private void processAAD()
9699 if (!aadFinished )
97100 {
98101 byte [] ad = aadData .toByteArray ();
99- AbsorbAny (ad , 0 , ad .length , Rabsorb , 0x03 );
102+ AbsorbAny (ad , ad .length , Rabsorb , 0x03 );
100103 aadFinished = true ;
101104 }
102105 }
@@ -117,27 +120,34 @@ public int processBytes(byte[] input, int inOff, int len, byte[] output, int out
117120 {
118121 throw new DataLengthException ("input buffer too short" );
119122 }
120- message .write (input , inOff , len );
121- int blockLen = message .size () - (forEncryption ? 0 : MAC_SIZE );
122- if (blockLen >= getBlockSize ())
123+ int blockLen = len + messageOff - (forEncryption ? 0 : MAC_SIZE );
124+ if (blockLen / Rkout * Rkout + outOff > output .length )
123125 {
124- byte [] blocks = message .toByteArray ();
125- len = blockLen / getBlockSize () * getBlockSize ();
126- if (len + outOff > output .length )
127- {
128- throw new OutputLengthException ("output buffer is too short" );
129- }
126+ throw new OutputLengthException ("output buffer is too short" );
127+ }
128+ int rv = 0 ;
129+ int originalInOff = inOff ;
130+ while (blockLen >= Rkout )
131+ {
132+ int copyLen = Math .min (len , Rkout - messageOff );
133+ System .arraycopy (input , inOff , message , messageOff , copyLen );
130134 processAAD ();
131- encrypt (blocks , 0 , len , output , outOff );
132- message .reset ();
133- message .write (blocks , len , blocks .length - len );
134- return len ;
135+ encrypt (message , Rkout , output , outOff );
136+ messageOff = 0 ;
137+ outOff += Rkout ;
138+ rv += Rkout ;
139+ blockLen -= Rkout ;
140+ inOff += copyLen ;
135141 }
136- return 0 ;
142+ len -= inOff - originalInOff ;
143+ System .arraycopy (input , inOff , message , messageOff , len );
144+ messageOff = len ;
145+ return rv ;
137146 }
138147
139- private int encrypt (byte [] input , int inOff , int len , byte [] output , int outOff )
148+ private void encrypt (byte [] input , int len , byte [] output , int outOff )
140149 {
150+ int inOff = 0 ;
141151 int IOLen = len ;
142152 int splitLen ;
143153 byte [] P = new byte [Rkout ];
@@ -168,7 +178,6 @@ private int encrypt(byte[] input, int inOff, int len, byte[] output, int outOff)
168178 IOLen -= splitLen ;
169179 encrypted = true ;
170180 }
171- return len ;
172181 }
173182
174183 @ Override
@@ -179,8 +188,9 @@ public int doFinal(byte[] output, int outOff)
179188 {
180189 throw new IllegalArgumentException ("Need call init function before encryption/decryption" );
181190 }
182- byte [] blocks = message .toByteArray ();
183- int len = message .size ();
191+ byte [] blocks = message ;
192+ Arrays .fill (blocks , messageOff , message .length , (byte )0 );
193+ int len = messageOff ;
184194 if ((forEncryption && len + MAC_SIZE + outOff > output .length ) || (!forEncryption && len - MAC_SIZE + outOff > output .length ))
185195 {
186196 throw new OutputLengthException ("output buffer too short" );
@@ -189,7 +199,7 @@ public int doFinal(byte[] output, int outOff)
189199 int rv = 0 ;
190200 if (forEncryption )
191201 {
192- encrypt (blocks , 0 , len , output , outOff );
202+ encrypt (blocks , len , output , outOff );
193203 outOff += len ;
194204 mac = new byte [MAC_SIZE ];
195205 Up (mac , MAC_SIZE , 0x40 );
@@ -198,9 +208,14 @@ public int doFinal(byte[] output, int outOff)
198208 }
199209 else
200210 {
201- int inOff = len - MAC_SIZE ;
202- rv = inOff ;
203- encrypt (blocks , 0 , inOff , output , outOff );
211+ int inOff = 0 ;
212+ if (len >= MAC_SIZE )
213+ {
214+ inOff = len - MAC_SIZE ;
215+ rv = inOff ;
216+ encrypt (blocks , inOff , output , outOff );
217+ }
218+
204219 mac = new byte [MAC_SIZE ];
205220 Up (mac , MAC_SIZE , 0x40 );
206221 for (int i = 0 ; i < MAC_SIZE ; ++i )
@@ -218,14 +233,14 @@ public int doFinal(byte[] output, int outOff)
218233 @ Override
219234 public int getUpdateOutputSize (int len )
220235 {
221- int total = Math .max (0 , len + message . size () + (forEncryption ? 0 : -MAC_SIZE ));
236+ int total = Math .max (0 , len + messageOff + (forEncryption ? 0 : -MAC_SIZE ));
222237 return total - total % Rkout ;
223238 }
224239
225240 @ Override
226241 public int getOutputSize (int len )
227242 {
228- return Math .max (0 , len + message . size () + (forEncryption ? MAC_SIZE : -MAC_SIZE ));
243+ return Math .max (0 , len + messageOff + (forEncryption ? MAC_SIZE : -MAC_SIZE ));
229244 }
230245
231246 @ Override
@@ -244,7 +259,8 @@ protected void reset(boolean clearMac)
244259 aadFinished = false ;
245260 encrypted = false ;
246261 phase = PhaseUp ;
247- message .reset ();
262+ Arrays .fill (message , (byte )0 );
263+ messageOff = 0 ;
248264 aadData .reset ();
249265 //Absorb key
250266 int KLen = K .length ;
@@ -255,12 +271,13 @@ protected void reset(boolean clearMac)
255271 System .arraycopy (K , 0 , KID , 0 , KLen );
256272 System .arraycopy (iv , 0 , KID , KLen , IDLen );
257273 KID [KLen + IDLen ] = (byte )IDLen ;
258- AbsorbAny (KID , 0 , KLen + IDLen + 1 , Rabsorb , 0x02 );
274+ AbsorbAny (KID , KLen + IDLen + 1 , Rabsorb , 0x02 );
259275 super .reset (clearMac );
260276 }
261277
262- private void AbsorbAny (byte [] X , int Xoff , int XLen , int r , int Cd )
278+ private void AbsorbAny (byte [] X , int XLen , int r , int Cd )
263279 {
280+ int Xoff = 0 ;
264281 int splitLen ;
265282 do
266283 {
@@ -297,9 +314,6 @@ private void Up(byte[] Yi, int YiLen, int Cu)
297314 int a10 = Pack .littleEndianToInt (state , 40 );
298315 int a11 = Pack .littleEndianToInt (state , 44 );
299316
300- // private final int NLANES = 12;
301- // private final int NROWS = 3;
302- // private final int NCOLUMS = 4;
303317 int MAXROUNDS = 12 ;
304318 for (int i = 0 ; i < MAXROUNDS ; ++i )
305319 {
@@ -349,7 +363,7 @@ private void Up(byte[] Yi, int YiLen, int Cu)
349363 /* Iota: round ant */
350364 b0 ^= RC [i ];
351365
352- /* Chi: non linear layer */
366+ /* Chi: non- linear layer */
353367 a0 = b0 ^ (~b4 & b8 );
354368 a1 = b1 ^ (~b5 & b9 );
355369 a2 = b2 ^ (~b6 & b10 );
@@ -403,10 +417,13 @@ void Down(byte[] Xi, int XiOff, int XiLen, int Cd)
403417 {
404418 state [i ] ^= Xi [XiOff ++];
405419 }
420+ if (XiLen == -16 )
421+ {
422+ System .out .println ();
423+ }
406424 state [XiLen ] ^= 0x01 ;
407425 state [f_bPrime - 1 ] ^= (mode == MODE .ModeHash ) ? (Cd & 0x01 ) : Cd ;
408- int phaseDown = 1 ;
409- phase = phaseDown ;
426+ phase = 1 ;
410427 }
411428
412429 public int getBlockSize ()
0 commit comments