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 ;
86import org .bouncycastle .crypto .OutputLengthException ;
97import org .bouncycastle .util .Arrays ;
108
119/**
12- * Photon-Beetle, https://www.isical.ac.in/~lightweight/beetle/
10+ * Photon-Beetle, <a href=" https://www.isical.ac.in/~lightweight/beetle/"></a>
1311 * https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/finalist-round/updated-spec-doc/photon-beetle-spec-final.pdf
1412 * <p>
1513 * Photon-Beetle with reference to C Reference Impl from: https://github.com/PHOTON-Beetle/Software
@@ -31,15 +29,16 @@ public enum PhotonBeetleParameters
3129 private byte [] state ;
3230 private byte [][] state_2d ;
3331 private boolean initialised ;
34- private final byte [] aadData ;
35- private int aadOff ;
32+ private final byte [] buffer ;
33+ private int bufferOff ;
3634 private int aadLen ;
37- private final ByteArrayOutputStream message = new ByteArrayOutputStream () ;
35+ private int messageLen ;
3836 private final int RATE_INBYTES ;
3937 private final int RATE_INBYTES_HALF ;
4038 private final int STATE_INBYTES ;
4139 private final int LAST_THREE_BITS_OFFSET ;
4240 private final int D = 8 ;
41+ private boolean aadFinished ;
4342 private final byte [][] RC = {
4443 {1 , 3 , 7 , 14 , 13 , 11 , 6 , 12 , 9 , 2 , 5 , 10 },
4544 {0 , 2 , 6 , 15 , 12 , 10 , 7 , 13 , 8 , 3 , 4 , 11 },
@@ -87,7 +86,7 @@ public PhotonBeetleEngine(PhotonBeetleParameters pbp)
8786 LAST_THREE_BITS_OFFSET = (STATE_INBITS - ((STATE_INBYTES - 1 ) << 3 ) - 3 );
8887 initialised = false ;
8988 algorithmName = "Photon-Beetle AEAD" ;
90- aadData = new byte [RATE_INBYTES ];
89+ buffer = new byte [RATE_INBYTES + ( forEncryption ? 0 : MAC_SIZE ) ];
9190 }
9291
9392 @ Override
@@ -107,13 +106,13 @@ public void init(boolean forEncryption, CipherParameters params)
107106 @ Override
108107 public void processAADByte (byte input )
109108 {
110- if (aadOff >= aadData . length )
109+ if (bufferOff >= RATE_INBYTES )
111110 {
112111 PHOTON_Permutation ();
113- XOR (aadData , 0 , RATE_INBYTES );
114- aadOff = 0 ;
112+ XOR (buffer , 0 , RATE_INBYTES );
113+ bufferOff = 0 ;
115114 }
116- aadData [ aadOff ++] = input ;
115+ buffer [ bufferOff ++] = input ;
117116 aadLen ++;
118117 }
119118
@@ -126,15 +125,15 @@ public void processAADBytes(byte[] input, int inOff, int len)
126125 }
127126 int tmp ;
128127 aadLen += len ;
129- if (aadOff + len >= RATE_INBYTES )
128+ if (bufferOff + len >= RATE_INBYTES )
130129 {
131- tmp = RATE_INBYTES - aadOff ;
132- System .arraycopy (input , inOff , aadData , aadOff , tmp );
130+ tmp = RATE_INBYTES - bufferOff ;
131+ System .arraycopy (input , inOff , buffer , bufferOff , tmp );
133132 PHOTON_Permutation ();
134- XOR (aadData , 0 , RATE_INBYTES );
133+ XOR (buffer , 0 , RATE_INBYTES );
135134 inOff += tmp ;
136135 len -= tmp ;
137- aadOff = 0 ;
136+ bufferOff = 0 ;
138137 }
139138 while (len >= RATE_INBYTES )
140139 {
@@ -143,9 +142,8 @@ public void processAADBytes(byte[] input, int inOff, int len)
143142 inOff += RATE_INBYTES ;
144143 len -= RATE_INBYTES ;
145144 }
146- System .arraycopy (input , inOff , aadData , aadOff , len );
147- aadOff += len ;
148-
145+ System .arraycopy (input , inOff , buffer , bufferOff , len );
146+ bufferOff += len ;
149147 }
150148
151149 @ Override
@@ -156,8 +154,40 @@ public int processBytes(byte[] input, int inOff, int len, byte[] output, int out
156154 {
157155 throw new DataLengthException ("input buffer too short" );
158156 }
159- message .write (input , inOff , len );
160- return 0 ;
157+ messageLen += len ;
158+ // bufferOff will be set back to 0 if processFinalAADBlock is processed
159+ processFinalAADBlock (messageLen - (forEncryption ? 0 : MAC_SIZE ) > 0 );
160+ int blockLen = len + bufferOff - (forEncryption ? 0 : MAC_SIZE );
161+ int tmp ;
162+ int rv = 0 ;
163+
164+ int originalInOff = inOff ;
165+ if (blockLen >= RATE_INBYTES )
166+ {
167+ tmp = Math .max (RATE_INBYTES - bufferOff , 0 );
168+ System .arraycopy (input , inOff , buffer , bufferOff , tmp );
169+
170+ PHOTON_Permutation ();
171+ rhoohr (output , outOff , buffer , 0 , RATE_INBYTES );
172+ inOff += tmp ;
173+ rv += RATE_INBYTES ;
174+ blockLen -= RATE_INBYTES ;
175+ outOff += RATE_INBYTES ;
176+ bufferOff = 0 ;
177+ }
178+ while (blockLen >= RATE_INBYTES )
179+ {
180+ PHOTON_Permutation ();
181+ rhoohr (output , outOff , input , inOff , RATE_INBYTES );
182+ outOff += RATE_INBYTES ;
183+ inOff += RATE_INBYTES ;
184+ rv += RATE_INBYTES ;
185+ blockLen -= RATE_INBYTES ;
186+ }
187+ len -= inOff - originalInOff ;
188+ System .arraycopy (input , inOff , buffer , bufferOff , len );
189+ bufferOff += len ;
190+ return rv ;
161191 }
162192
163193 @ Override
@@ -168,51 +198,32 @@ public int doFinal(byte[] output, int outOff)
168198 {
169199 throw new IllegalArgumentException ("Need call init function before encryption/decryption" );
170200 }
171- int len = message .size () - (forEncryption ? 0 : MAC_SIZE );
172- if ((forEncryption && len + MAC_SIZE + outOff > output .length ) ||
173- (!forEncryption && len + outOff > output .length ))
201+ processFinalAADBlock (false );
202+ int len = messageLen - (forEncryption ? 0 : MAC_SIZE );
203+ int bufferLen = bufferOff - (forEncryption ? 0 : MAC_SIZE );
204+ if ((forEncryption && bufferLen + MAC_SIZE + outOff > output .length ) ||
205+ (!forEncryption && bufferLen + outOff > output .length ))
174206 {
175207 throw new OutputLengthException ("output buffer too short" );
176208 }
177- byte [] input = message .toByteArray ();
178- int inOff = 0 ;
179-
180209 int i ;
181210 if (aadLen != 0 || len != 0 )
182211 {
183212 input_empty = false ;
184213 }
185- byte c0 = select ((len != 0 ), ((aadLen % RATE_INBYTES ) == 0 ), (byte )3 , (byte )4 );
186214 byte c1 = select ((aadLen != 0 ), ((len % RATE_INBYTES ) == 0 ), (byte )5 , (byte )6 );
187- int Dlen_inblocks , LastDBlocklen ;
188- if (aadLen != 0 )
189- {
190- if (aadOff != 0 )
191- {
192- PHOTON_Permutation ();
193- XOR (aadData , 0 , aadOff );
194- state [aadOff ] ^= 0x01 ; // ozs
195- }
196- state [STATE_INBYTES - 1 ] ^= c0 << LAST_THREE_BITS_OFFSET ;
197- }
215+
198216 if (len != 0 )
199217 {
200- Dlen_inblocks = (len + RATE_INBYTES - 1 ) / RATE_INBYTES ;
201- for (i = 0 ; i < Dlen_inblocks - 1 ; i ++)
218+ if (bufferLen != 0 )
202219 {
203220 PHOTON_Permutation ();
204- rhoohr (output , outOff + i * RATE_INBYTES , input , inOff + i * RATE_INBYTES , RATE_INBYTES );
205- }
206- PHOTON_Permutation ();
207- LastDBlocklen = len - i * RATE_INBYTES ;
208- rhoohr (output , outOff + i * RATE_INBYTES , input , inOff + i * RATE_INBYTES , LastDBlocklen );
209- if (LastDBlocklen < RATE_INBYTES )
210- {
211- state [LastDBlocklen ] ^= 0x01 ; // ozs
221+ rhoohr (output , outOff , buffer , 0 , bufferLen );
222+ state [bufferLen ] ^= 0x01 ; // ozs
212223 }
213224 state [STATE_INBYTES - 1 ] ^= c1 << LAST_THREE_BITS_OFFSET ;
214225 }
215- outOff += len ;
226+ outOff += bufferLen ;
216227 if (input_empty )
217228 {
218229 state [STATE_INBYTES - 1 ] ^= 1 << LAST_THREE_BITS_OFFSET ;
@@ -223,33 +234,71 @@ public int doFinal(byte[] output, int outOff)
223234 if (forEncryption )
224235 {
225236 System .arraycopy (mac , 0 , output , outOff , MAC_SIZE );
226- len += MAC_SIZE ;
237+ bufferLen += MAC_SIZE ;
227238 }
228239 else
229240 {
230241 for (i = 0 ; i < MAC_SIZE ; ++i )
231242 {
232- if (mac [i ] != input [ len + i ])
243+ if (mac [i ] != buffer [ bufferLen + i ])
233244 {
234245 throw new IllegalArgumentException ("Mac does not match" );
235246 }
236247 }
237248 }
238249 reset (false );
239- return len ;
250+ return bufferLen ;
251+ }
252+
253+ private void processFinalAADBlock (boolean lenIsNotZero )
254+ {
255+ if (!aadFinished )
256+ {
257+ if (aadLen != 0 )
258+ {
259+ if (bufferOff != 0 )
260+ {
261+ PHOTON_Permutation ();
262+ XOR (buffer , 0 , bufferOff );
263+ if (bufferOff < RATE_INBYTES )
264+ {
265+ state [bufferOff ] ^= 0x01 ; // ozs
266+ }
267+ }
268+ state [STATE_INBYTES - 1 ] ^= select (lenIsNotZero , ((aadLen % RATE_INBYTES ) == 0 ), (byte )3 , (byte )4 ) << LAST_THREE_BITS_OFFSET ;
269+ }
270+ bufferOff = 0 ;
271+ aadFinished = true ;
272+ }
240273 }
241274
242275 @ Override
243276 public int getUpdateOutputSize (int len )
244277 {
245- int total = Math .max (0 , len + message .size () + (forEncryption ? 0 : -MAC_SIZE ));
278+ int total ;
279+ if (aadFinished )
280+ {
281+ total = Math .max (0 , len + bufferOff + (forEncryption ? 0 : -MAC_SIZE ));
282+ }
283+ else
284+ {
285+ total = Math .max (0 , len + (forEncryption ? 0 : -MAC_SIZE ));
286+ }
246287 return total - total % RATE_INBYTES ;
247288 }
248289
249290 @ Override
250291 public int getOutputSize (int len )
251292 {
252- return Math .max (0 , len + message .size () + (forEncryption ? MAC_SIZE : -MAC_SIZE ));
293+ if (aadFinished )
294+ {
295+ return Math .max (0 , len + bufferOff + (forEncryption ? MAC_SIZE : -MAC_SIZE ));
296+ }
297+ else
298+ {
299+ return Math .max (0 , len + (forEncryption ? MAC_SIZE : -MAC_SIZE ));
300+ }
301+
253302 }
254303
255304 @ Override
@@ -266,10 +315,11 @@ public void reset()
266315 protected void reset (boolean clearMac )
267316 {
268317 input_empty = true ;
269- Arrays .fill (aadData , (byte )0 );
270- aadOff = 0 ;
318+ Arrays .fill (buffer , (byte )0 );
319+ bufferOff = 0 ;
271320 aadLen = 0 ;
272- message .reset ();
321+ aadFinished = false ;
322+ messageLen = 0 ;
273323 System .arraycopy (K , 0 , state , 0 , K .length );
274324 System .arraycopy (N , 0 , state , K .length , N .length );
275325 super .reset (clearMac );
@@ -386,7 +436,7 @@ private void rhoohr(byte[] ciphertext, int outOff, byte[] plaintext, int inOff,
386436 }
387437 else
388438 {
389- XOR (ciphertext , inOff , DBlen_inbytes );
439+ XOR (ciphertext , outOff , DBlen_inbytes );
390440 }
391441 }
392442
0 commit comments