1111import org .bouncycastle .crypto .modes .AEADCipher ;
1212import org .bouncycastle .crypto .params .KeyParameter ;
1313import org .bouncycastle .crypto .params .ParametersWithIV ;
14- import org .bouncycastle .util .Arrays ;
14+ import org .bouncycastle .util .Pack ;
1515
1616/**
1717 * Grain-128 AEAD, based on the current round 3 submission, https://grain-128aead.github.io/
1818 */
1919public class Grain128AEADEngine
2020 implements AEADCipher
2121{
22-
2322 /**
2423 * Constants
2524 */
@@ -35,10 +34,8 @@ public class Grain128AEADEngine
3534 private int [] nfsr ;
3635 private int [] authAcc ;
3736 private int [] authSr ;
38- private int output ;
3937
4038 private boolean initialised = false ;
41- private boolean isEven = true ; // zero treated as even
4239 private boolean aadFinished = false ;
4340 private ErasableOutputStream aadData = new ErasableOutputStream ();
4441
@@ -56,7 +53,6 @@ public String getAlgorithmName()
5653 * @param params The parameters required to set up the cipher.
5754 * @throws IllegalArgumentException If the params argument is inappropriate.
5855 */
59- @ Override
6056 public void init (boolean forEncryption , CipherParameters params )
6157 throws IllegalArgumentException
6258 {
@@ -120,15 +116,15 @@ private void initGrain()
120116 {
121117 for (int i = 0 ; i < 320 ; ++i )
122118 {
123- output = getOutput ();
119+ int output = getOutput ();
124120 nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ] ^ output ) & 1 );
125121 lfsr = shift (lfsr , (getOutputLFSR () ^ output ) & 1 );
126122 }
127123 for (int quotient = 0 ; quotient < 8 ; ++quotient )
128124 {
129125 for (int remainder = 0 ; remainder < 8 ; ++remainder )
130126 {
131- output = getOutput ();
127+ int output = getOutput ();
132128 nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ] ^ output ^ ((workingKey [quotient ]) >> remainder )) & 1 );
133129 lfsr = shift (lfsr , (getOutputLFSR () ^ output ^ ((workingKey [quotient + 8 ]) >> remainder )) & 1 );
134130 }
@@ -137,7 +133,7 @@ private void initGrain()
137133 {
138134 for (int remainder = 0 ; remainder < 32 ; ++remainder )
139135 {
140- output = getOutput ();
136+ int output = getOutput ();
141137 nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ]) & 1 );
142138 lfsr = shift (lfsr , (getOutputLFSR ()) & 1 );
143139 authAcc [quotient ] |= output << remainder ;
@@ -147,7 +143,7 @@ private void initGrain()
147143 {
148144 for (int remainder = 0 ; remainder < 32 ; ++remainder )
149145 {
150- output = getOutput ();
146+ int output = getOutput ();
151147 nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ]) & 1 );
152148 lfsr = shift (lfsr , (getOutputLFSR ()) & 1 );
153149 authSr [quotient ] |= output << remainder ;
@@ -238,6 +234,7 @@ private int getOutput()
238234 int s79 = lfsr [2 ] >>> 15 ;
239235 int s93 = lfsr [2 ] >>> 29 ;
240236 int s94 = lfsr [2 ] >>> 30 ;
237+
241238 return ((b12 & s8 ) ^ (s13 & s20 ) ^ (b95 & s42 ) ^ (s60 & s79 ) ^ (b12 & b95 & s94 ) ^ s93
242239 ^ b2 ^ b15 ^ b36 ^ b45 ^ b64 ^ b73 ^ b89 ) & 1 ;
243240 }
@@ -251,12 +248,10 @@ private int getOutput()
251248 */
252249 private int [] shift (int [] array , int val )
253250 {
254-
255251 array [0 ] = (array [0 ] >>> 1 ) | (array [1 ] << 31 );
256252 array [1 ] = (array [1 ] >>> 1 ) | (array [2 ] << 31 );
257253 array [2 ] = (array [2 ] >>> 1 ) | (array [3 ] << 31 );
258254 array [3 ] = (array [3 ] >>> 1 ) | (val << 31 );
259-
260255 return array ;
261256 }
262257
@@ -271,35 +266,23 @@ private void setKey(byte[] keyBytes, byte[] ivBytes)
271266 ivBytes [12 ] = (byte )0xFF ;
272267 ivBytes [13 ] = (byte )0xFF ;
273268 ivBytes [14 ] = (byte )0xFF ;
274- ivBytes [15 ] = (byte )0x7F ;//(byte) 0xFE;
269+ ivBytes [15 ] = (byte )0x7F ;
275270 workingKey = keyBytes ;
276271 workingIV = ivBytes ;
277272
278273 /**
279274 * Load NFSR and LFSR
280275 */
281- int j = 0 ;
282- for (int i = 0 ; i < nfsr .length ; i ++)
283- {
284- nfsr [i ] = ((workingKey [j + 3 ]) << 24 ) | ((workingKey [j + 2 ]) << 16 )
285- & 0x00FF0000 | ((workingKey [j + 1 ]) << 8 ) & 0x0000FF00
286- | ((workingKey [j ]) & 0x000000FF );
287-
288- lfsr [i ] = ((workingIV [j + 3 ]) << 24 ) | ((workingIV [j + 2 ]) << 16 )
289- & 0x00FF0000 | ((workingIV [j + 1 ]) << 8 ) & 0x0000FF00
290- | ((workingIV [j ]) & 0x000000FF );
291- j += 4 ;
292- }
276+ Pack .littleEndianToInt (workingKey , 0 , nfsr );
277+ Pack .littleEndianToInt (workingIV , 0 , lfsr );
293278 }
294279
295- public int processBytes (byte [] input , int inOff , int len , byte [] output ,
296- int outOff )
280+ public int processBytes (byte [] input , int inOff , int len , byte [] output , int outOff )
297281 throws DataLengthException
298282 {
299283 if (!initialised )
300284 {
301- throw new IllegalStateException (getAlgorithmName ()
302- + " not initialised" );
285+ throw new IllegalStateException (getAlgorithmName () + " not initialised" );
303286 }
304287
305288 if (!aadFinished )
@@ -328,51 +311,42 @@ public void reset()
328311
329312 private void reset (boolean clearMac )
330313 {
331- this .isEven = true ;
332314 if (clearMac )
333315 {
334316 this .mac = null ;
335317 }
336318 this .aadData .reset ();
337319 this .aadFinished = false ;
320+
338321 setKey (workingKey , workingIV );
339322 initGrain ();
340323 }
341324
342325 private byte [] getKeyStream (byte [] input , int inOff , int len , byte [] ciphertext , int outOff )
343326 {
344- int mCnt = 0 , acCnt = 0 , cCnt = 0 ;
345- byte cc ;
346- byte [] plaintext = new byte [len ];
347327 for (int i = 0 ; i < len ; ++i )
348328 {
349- plaintext [i ] = (byte )reverseByte (input [inOff + i ]);
350- }
351- for (int i = 0 ; i < len ; ++i )
352- {
353- cc = 0 ;
354- for (int j = 0 ; j < 16 ; ++j )
329+ byte cc = 0 , input_i = input [inOff + i ];
330+ for (int j = 0 ; j < 8 ; ++j )
355331 {
356- output = getOutput ();
332+ int output = getOutput ();
333+ nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ]) & 1 );
334+ lfsr = shift (lfsr , (getOutputLFSR ()) & 1 );
335+
336+ int input_i_j = (input_i >> j ) & 1 ;
337+ cc |= (input_i_j ^ output ) << j ;
338+
339+ // if (input_i_j != 0)
340+ // {
341+ // accumulate();
342+ // }
343+ int mask = -input_i_j ;
344+ authAcc [0 ] ^= authSr [0 ] & mask ;
345+ authAcc [1 ] ^= authSr [1 ] & mask ;
346+
347+ authShift (getOutput ());
357348 nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ]) & 1 );
358349 lfsr = shift (lfsr , (getOutputLFSR ()) & 1 );
359- if (isEven )
360- {
361- cc |= (((plaintext [mCnt >> 3 ] >>> (7 - (mCnt & 7 ))) & 1 ) ^ output ) << (cCnt & 7 );
362- mCnt ++;
363- cCnt ++;
364- isEven = false ;
365- }
366- else
367- {
368- if ((plaintext [acCnt >> 3 ] & (1 << (7 - (acCnt & 7 )))) != 0 )
369- {
370- accumulate ();
371- }
372- authShift (output );
373- acCnt ++;
374- isEven = true ;
375- }
376350 }
377351 ciphertext [outOff + i ] = cc ;
378352 }
@@ -406,46 +380,47 @@ private void doProcessAADBytes(byte[] input, int inOff, int len)
406380 if (len < 128 )
407381 {
408382 ader = new byte [1 + len ];
409- ader [0 ] = (byte )reverseByte ( len ) ;
383+ ader [0 ] = (byte )len ;
410384 aderlen = 0 ;
411385 }
412386 else
413387 {
414388 // aderlen is the highest bit position divided by 8
415389 aderlen = len_length (len );
416390 ader = new byte [1 + aderlen + len ];
417- ader [0 ] = (byte )reverseByte (0x80 | aderlen );
391+ ader [0 ] = (byte )(0x80 | aderlen );
418392 int tmp = len ;
419393 for (int i = 0 ; i < aderlen ; ++i )
420394 {
421- ader [1 + i ] = (byte )reverseByte ( tmp & 0xff ) ;
395+ ader [1 + i ] = (byte )tmp ;
422396 tmp >>>= 8 ;
423397 }
424398 }
425399 for (int i = 0 ; i < len ; ++i )
426400 {
427- ader [1 + aderlen + i ] = ( byte ) reverseByte ( input [inOff + i ]) ;
401+ ader [1 + aderlen + i ] = input [inOff + i ];
428402 }
429403
430- byte adval ;
431- int adCnt = 0 ;
432404 for (int i = 0 ; i < ader .length ; ++i )
433405 {
434- for (int j = 0 ; j < 16 ; ++j )
406+ byte ader_i = ader [i ];
407+ for (int j = 0 ; j < 8 ; ++j )
435408 {
436- output = getOutput ();
437409 nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ]) & 1 );
438410 lfsr = shift (lfsr , (getOutputLFSR ()) & 1 );
439- if ((j & 1 ) == 1 )
440- {
441- adval = (byte )(ader [adCnt >> 3 ] & (1 << (7 - (adCnt & 7 ))));
442- if (adval != 0 )
443- {
444- accumulate ();
445- }
446- authShift (output );
447- adCnt ++;
448- }
411+
412+ int ader_i_j = (ader_i >> j ) & 1 ;
413+ // if (ader_i_j != 0)
414+ // {
415+ // accumulate();
416+ // }
417+ int mask = -ader_i_j ;
418+ authAcc [0 ] ^= authSr [0 ] & mask ;
419+ authAcc [1 ] ^= authSr [1 ] & mask ;
420+
421+ authShift (getOutput ());
422+ nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ]) & 1 );
423+ lfsr = shift (lfsr , (getOutputLFSR ()) & 1 );
449424 }
450425 }
451426 }
@@ -477,21 +452,9 @@ public int doFinal(byte[] out, int outOff)
477452 aadFinished = true ;
478453 }
479454
480- this .mac = new byte [8 ];
481-
482- output = getOutput ();
483- nfsr = shift (nfsr , (getOutputNFSR () ^ lfsr [0 ]) & 1 );
484- lfsr = shift (lfsr , (getOutputLFSR ()) & 1 );
485455 accumulate ();
486456
487- int cCnt = 0 ;
488- for (int i = 0 ; i < 2 ; ++i )
489- {
490- for (int j = 0 ; j < 4 ; ++j )
491- {
492- mac [cCnt ++] = (byte )((authAcc [i ] >>> (j << 3 )) & 0xff );
493- }
494- }
457+ this .mac = Pack .intToLittleEndian (authAcc );
495458
496459 System .arraycopy (mac , 0 , out , outOff , mac .length );
497460
@@ -516,15 +479,7 @@ public int getOutputSize(int len)
516479 return len + 8 ;
517480 }
518481
519- private int reverseByte (int x )
520- {
521- x = (((x & 0x55 ) << 1 ) | ((x & (0xAA )) >>> 1 )) & 0xFF ;
522- x = (((x & 0x33 ) << 2 ) | ((x & (0xCC )) >>> 2 )) & 0xFF ;
523- x = (((x & 0x0f ) << 4 ) | ((x & (0xf0 )) >>> 4 )) & 0xFF ;
524- return x ;
525- }
526-
527- private int len_length (int v )
482+ private static int len_length (int v )
528483 {
529484 if ((v & 0xff ) == v )
530485 {
@@ -554,11 +509,11 @@ public byte[] getBuf()
554509 return buf ;
555510 }
556511
557- public void erase ()
558- {
559- Arrays .fill (this .buf , (byte )0 );
560- // this for JVM compatibility
561- this .reset ();
562- }
512+ // public void erase()
513+ // {
514+ // Arrays.fill(this.buf, (byte)0);
515+ // // this for JVM compatibility
516+ // this.reset();
517+ // }
563518 }
564519}
0 commit comments