66import org .bouncycastle .crypto .DataLengthException ;
77import org .bouncycastle .crypto .InvalidCipherTextException ;
88import org .bouncycastle .crypto .OutputLengthException ;
9+ import org .bouncycastle .util .Arrays ;
910import org .bouncycastle .util .Pack ;
1011
1112/**
@@ -51,18 +52,22 @@ public ISAPEngine(IsapType isapType)
5152 algorithmName = "ISAP-K-128 AEAD" ;
5253 break ;
5354 }
55+ aadData = new byte [ISAP_rH_SZ ];
5456 }
5557
5658 private boolean initialised ;
5759 final int ISAP_STATE_SZ = 40 ;
5860 private byte [] k ;
5961 private byte [] npub ;
60- private final ByteArrayOutputStream aadData = new ByteArrayOutputStream ();
62+ //private final ByteArrayOutputStream aadData = new ByteArrayOutputStream();
63+ private final byte [] aadData ;
64+ private int aadOff ;
6165 private final ByteArrayOutputStream message = new ByteArrayOutputStream ();
6266 private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
6367 private int ISAP_rH ;
6468 private int ISAP_rH_SZ ;
6569 private ISAP_AEAD ISAPAEAD ;
70+ private boolean aadFinished ;
6671
6772 private interface ISAP_AEAD
6873 {
@@ -73,6 +78,10 @@ private interface ISAP_AEAD
7378 void isap_mac (byte [] ad , int adlen , byte [] c , int clen , byte [] tag );
7479
7580 void reset ();
81+
82+ void absorbMacBlock (byte [] input , int inOff );
83+
84+ void swapInternalState ();
7685 }
7786
7887 private abstract class ISAPAEAD_A
@@ -83,7 +92,7 @@ private abstract class ISAPAEAD_A
8392 protected long ISAP_IV1_64 ;
8493 protected long ISAP_IV2_64 ;
8594 protected long ISAP_IV3_64 ;
86- protected long x0 , x1 , x2 , x3 , x4 , t0 , t1 , t2 , t3 , t4 ;
95+ protected long x0 , x1 , x2 , x3 , x4 , t0 , t1 , t2 , t3 , t4 , macx0 , macx1 , macx2 , macx3 , macx4 ;
8796
8897 public ISAPAEAD_A ()
8998 {
@@ -97,13 +106,38 @@ public void init()
97106 k64 = new long [getLongSize (k .length )];
98107 Pack .bigEndianToLong (npub , 0 , npub64 );
99108 Pack .bigEndianToLong (k , 0 , k64 );
100- reset ();
109+ // reset();
101110 }
102111
103112 protected abstract void PX1 ();
104113
105114 protected abstract void PX2 ();
106115
116+ public void swapInternalState ()
117+ {
118+ t0 = x0 ;
119+ t1 = x1 ;
120+ t2 = x2 ;
121+ t3 = x3 ;
122+ t4 = x4 ;
123+ x0 = macx0 ;
124+ x1 = macx1 ;
125+ x2 = macx2 ;
126+ x3 = macx3 ;
127+ x4 = macx4 ;
128+ macx0 = t0 ;
129+ macx1 = t1 ;
130+ macx2 = t2 ;
131+ macx3 = t3 ;
132+ macx4 = t4 ;
133+ }
134+
135+ public void absorbMacBlock (byte [] input , int inOff )
136+ {
137+ x0 ^= Pack .bigEndianToLong (input , inOff );
138+ P12 ();
139+ }
140+
107141 protected void ABSORB_MAC (byte [] src , int len )
108142 {
109143 long [] src64 = new long [src .length >> 3 ];
@@ -127,11 +161,12 @@ protected void ABSORB_MAC(byte[] src, int len)
127161 public void isap_mac (byte [] ad , int adlen , byte [] c , int clen , byte [] tag )
128162 {
129163 // Init State
130- x0 = npub64 [0 ];
131- x1 = npub64 [1 ];
132- x2 = ISAP_IV1_64 ;
133- x3 = x4 = 0 ;
134- P12 ();
164+ // x0 = npub64[0];
165+ // x1 = npub64[1];
166+ // x2 = ISAP_IV1_64;
167+ // x3 = x4 = 0;
168+ // P12();
169+
135170 ABSORB_MAC (ad , adlen );
136171 // Domain seperation
137172 x4 ^= 1L ;
@@ -198,6 +233,13 @@ public void reset()
198233 x3 = npub64 [0 ];
199234 x4 = npub64 [1 ];
200235 PX1 ();
236+ swapInternalState ();
237+ // Init State for mac
238+ x0 = npub64 [0 ];
239+ x1 = npub64 [1 ];
240+ x2 = ISAP_IV1_64 ;
241+ x3 = x4 = 0 ;
242+ P12 ();
201243 }
202244
203245 private int getLongSize (int x )
@@ -306,8 +348,11 @@ private abstract class ISAPAEAD_K
306348 private final int [] KeccakF400RoundConstants = {0x0001 , 0x8082 , 0x808a , 0x8000 , 0x808b , 0x0001 , 0x8081 , 0x8009 ,
307349 0x008a , 0x0088 , 0x8009 , 0x000a , 0x808b , 0x008b , 0x8089 , 0x8003 , 0x8002 , 0x0080 , 0x800a , 0x000a };
308350 protected short [] SX = new short [25 ];
351+ protected short [] macSX = new short [25 ];
309352 protected short [] E = new short [25 ];
310353 protected short [] C = new short [5 ];
354+ protected short [] macE = new short [25 ];
355+ protected short [] macC = new short [5 ];
311356
312357 public ISAPAEAD_K ()
313358 {
@@ -321,18 +366,35 @@ public void init()
321366 byteToShort (k , k16 , k16 .length );
322367 iv16 = new short [npub .length >> 1 ];
323368 byteToShort (npub , iv16 , iv16 .length );
324- reset ();
369+ // reset();
325370 }
326371
327372 public void reset ()
328373 {
329374 // Init state
330- SX = new short [25 ];
331- E = new short [25 ];
332- C = new short [5 ];
375+ Arrays .fill (SX , (byte )0 );
333376 isap_rk (ISAP_IV3_16 , npub , IV_SIZE , SX , ISAP_STATE_SZ_CRYPTO_NPUBBYTES , C );
334377 System .arraycopy (iv16 , 0 , SX , 17 , 8 );
335378 PermuteRoundsKX (SX , E , C );
379+ // Init state for mac
380+ swapInternalState ();
381+ Arrays .fill (SX , 12 , 25 , (short ) 0 );
382+ System .arraycopy (iv16 , 0 , SX , 0 , 8 );
383+ System .arraycopy (ISAP_IV1_16 , 0 , SX , 8 , 4 );
384+ PermuteRoundsHX (SX , E , C );
385+ }
386+
387+ public void swapInternalState ()
388+ {
389+ short [] tmp = SX ;
390+ SX = macSX ;
391+ macSX = tmp ;
392+ tmp = E ;
393+ E = macE ;
394+ macE = tmp ;
395+ tmp = C ;
396+ C = macC ;
397+ macC = tmp ;
336398 }
337399
338400 protected abstract void PermuteRoundsHX (short [] SX , short [] E , short [] C );
@@ -341,6 +403,12 @@ public void reset()
341403
342404 protected abstract void PermuteRoundsBX (short [] SX , short [] E , short [] C );
343405
406+ public void absorbMacBlock (byte [] input , int inOff )
407+ {
408+ byteToShortXor (input , inOff , SX , ISAP_rH_SZ >> 1 );
409+ PermuteRoundsHX (SX , E , C );
410+ }
411+
344412 protected void ABSORB_MAC (short [] SX , byte [] src , int len , short [] E , short [] C )
345413 {
346414 int rem_bytes = len ;
@@ -349,14 +417,14 @@ protected void ABSORB_MAC(short[] SX, byte[] src, int len, short[] E, short[] C)
349417 {
350418 if (rem_bytes > ISAP_rH_SZ )
351419 {
352- byteToShortXor (src , SX , ISAP_rH_SZ >> 1 );
420+ byteToShortXor (src , idx , SX , ISAP_rH_SZ >> 1 );
353421 idx += ISAP_rH_SZ ;
354422 rem_bytes -= ISAP_rH_SZ ;
355423 PermuteRoundsHX (SX , E , C );
356424 }
357425 else if (rem_bytes == ISAP_rH_SZ )
358426 {
359- byteToShortXor (src , SX , ISAP_rH_SZ >> 1 );
427+ byteToShortXor (src , idx , SX , ISAP_rH_SZ >> 1 );
360428 PermuteRoundsHX (SX , E , C );
361429 SX [0 ] ^= 0x80 ;
362430 PermuteRoundsHX (SX , E , C );
@@ -397,11 +465,6 @@ public void isap_rk(short[] iv16, byte[] y, int ylen, short[] out16, int outlen,
397465
398466 public void isap_mac (byte [] ad , int adlen , byte [] c , int clen , byte [] tag )
399467 {
400- SX = new short [25 ];
401- // Init state
402- System .arraycopy (iv16 , 0 , SX , 0 , 8 );
403- System .arraycopy (ISAP_IV1_16 , 0 , SX , 8 , 4 );
404- PermuteRoundsHX (SX , E , C );
405468 // Absorb AD
406469 ABSORB_MAC (SX , ad , adlen , E , C );
407470 // Domain seperation
@@ -443,11 +506,11 @@ public void isap_enc(byte[] m, int mOff, int mlen, byte[] c, int cOff, int clen)
443506 }
444507 }
445508
446- private void byteToShortXor (byte [] input , short [] output , int outLen )
509+ private void byteToShortXor (byte [] input , int inOff , short [] output , int outLen )
447510 {
448511 for (int i = 0 ; i < outLen ; ++i )
449512 {
450- output [i ] ^= Pack .littleEndianToShort (input , (i << 1 ));
513+ output [i ] ^= Pack .littleEndianToShort (input , inOff + (i << 1 ));
451514 }
452515 }
453516
@@ -790,7 +853,12 @@ public void init(boolean forEncryption, CipherParameters params)
790853 @ Override
791854 public void processAADByte (byte in )
792855 {
793- aadData .write (in );
856+ if (aadOff >= aadData .length )
857+ {
858+ aadOff = 0 ;
859+ ISAPAEAD .absorbMacBlock (aadData , 0 );
860+ }
861+ aadData [aadOff ++] = in ;
794862 }
795863
796864 @ Override
@@ -800,8 +868,24 @@ public void processAADBytes(byte[] in, int inOff, int len)
800868 {
801869 throw new DataLengthException ("input buffer too short" + (forEncryption ? "encryption" : "decryption" ));
802870 }
803-
804- aadData .write (in , inOff , len );
871+ int tmp ;
872+ if (aadOff + len >= ISAP_rH_SZ )
873+ {
874+ tmp = ISAP_rH_SZ - aadOff ;
875+ System .arraycopy (in , inOff , aadData , aadOff , tmp );
876+ ISAPAEAD .absorbMacBlock (aadData , 0 );
877+ inOff += tmp ;
878+ len -= tmp ;
879+ aadOff = 0 ;
880+ }
881+ while (len > ISAP_rH_SZ )
882+ {
883+ ISAPAEAD .absorbMacBlock (in , inOff );
884+ inOff += ISAP_rH_SZ ;
885+ len -= ISAP_rH_SZ ;
886+ }
887+ System .arraycopy (in , inOff , aadData , aadOff , len );
888+ aadOff += len ;
805889 }
806890
807891 @ Override
@@ -816,6 +900,11 @@ public int processBytes(byte[] input, int inOff, int len, byte[] output, int out
816900 {
817901 throw new DataLengthException ("input buffer too short" );
818902 }
903+ if (!aadFinished )
904+ {
905+ ISAPAEAD .swapInternalState ();
906+ aadFinished = true ;
907+ }
819908 message .write (input , inOff , len );
820909 if (forEncryption )
821910 {
@@ -847,7 +936,7 @@ public int doFinal(byte[] output, int outOff)
847936 }
848937 int len ;
849938 byte [] c ;
850- byte [] ad = aadData . toByteArray ();
939+
851940 if (forEncryption )
852941 {
853942 byte [] enc_input = message .toByteArray ();
@@ -857,11 +946,13 @@ public int doFinal(byte[] output, int outOff)
857946 throw new OutputLengthException ("output buffer is too short" );
858947 }
859948 ISAPAEAD .isap_enc (enc_input , 0 , len , output , outOff , output .length );
949+
860950 outputStream .write (output , outOff , len );
861951 outOff += len ;
862952 c = outputStream .toByteArray ();
863953 mac = new byte [MAC_SIZE ];
864- ISAPAEAD .isap_mac (ad , ad .length , c , c .length , mac );
954+ ISAPAEAD .swapInternalState ();
955+ ISAPAEAD .isap_mac (aadData , aadOff , c , c .length , mac );
865956 System .arraycopy (mac , 0 , output , outOff , 16 );
866957 len += 16 ;
867958 }
@@ -874,7 +965,8 @@ public int doFinal(byte[] output, int outOff)
874965 {
875966 throw new OutputLengthException ("output buffer is too short" );
876967 }
877- ISAPAEAD .isap_mac (ad , ad .length , c , len , mac );
968+ ISAPAEAD .swapInternalState ();
969+ ISAPAEAD .isap_mac (aadData , aadOff , c , len , mac );
878970 ISAPAEAD .reset ();
879971 for (int i = 0 ; i < 16 ; ++i )
880972 {
@@ -883,6 +975,7 @@ public int doFinal(byte[] output, int outOff)
883975 throw new IllegalArgumentException ("Mac does not match" );
884976 }
885977 }
978+ ISAPAEAD .swapInternalState ();
886979 ISAPAEAD .isap_enc (c , 0 , len , output , outOff , output .length );
887980 }
888981 return len ;
@@ -907,11 +1000,14 @@ protected void reset(boolean clearMac)
9071000 {
9081001 throw new IllegalArgumentException ("Need call init function before encryption/decryption" );
9091002 }
910- aadData . reset ( );
1003+ Arrays . fill ( aadData , ( byte ) 0 );
9111004 ISAPAEAD .reset ();
9121005 message .reset ();
9131006 outputStream .reset ();
1007+ aadOff = 0 ;
1008+ aadFinished = false ;
9141009 super .reset (clearMac );
1010+
9151011 }
9161012
9171013 public int getBlockSize ()
0 commit comments