View Javadoc
1   /*
2    * GordianKnot: Security Suite
3    * Copyright 2012-2026. Tony Washer
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6    * use this file except in compliance with the License.  You may obtain a copy
7    * of the License at
8    *
9    *   http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
14   * License for the specific language governing permissions and limitations under
15   * the License.
16   */
17  package io.github.tonywasher.joceanus.gordianknot.impl.ext.engines;
18  
19  import org.bouncycastle.crypto.CipherParameters;
20  import org.bouncycastle.crypto.DataLengthException;
21  import org.bouncycastle.crypto.OutputLengthException;
22  import org.bouncycastle.crypto.StreamCipher;
23  import org.bouncycastle.crypto.params.KeyParameter;
24  import org.bouncycastle.crypto.params.ParametersWithIV;
25  import org.bouncycastle.util.Memoable;
26  
27  /**
28   * Snow3GEngine implementation.
29   * Based on https://www.gsma.com/aboutus/wp-content/uploads/2014/12/snow3gspec.pdf
30   */
31  @SuppressWarnings("checkstyle:MagicNumber")
32  public class GordianSnow3GEngine
33          implements StreamCipher, Memoable {
34      /**
35       * Rijndael S-box SR.
36       */
37      private static final byte[] SR = {
38              (byte) 0x63, (byte) 0x7C, (byte) 0x77, (byte) 0x7B, (byte) 0xF2, (byte) 0x6B, (byte) 0x6F, (byte) 0xC5,
39              (byte) 0x30, (byte) 0x01, (byte) 0x67, (byte) 0x2B, (byte) 0xFE, (byte) 0xD7, (byte) 0xAB, (byte) 0x76,
40              (byte) 0xCA, (byte) 0x82, (byte) 0xC9, (byte) 0x7D, (byte) 0xFA, (byte) 0x59, (byte) 0x47, (byte) 0xF0,
41              (byte) 0xAD, (byte) 0xD4, (byte) 0xA2, (byte) 0xAF, (byte) 0x9C, (byte) 0xA4, (byte) 0x72, (byte) 0xC0,
42              (byte) 0xB7, (byte) 0xFD, (byte) 0x93, (byte) 0x26, (byte) 0x36, (byte) 0x3F, (byte) 0xF7, (byte) 0xCC,
43              (byte) 0x34, (byte) 0xA5, (byte) 0xE5, (byte) 0xF1, (byte) 0x71, (byte) 0xD8, (byte) 0x31, (byte) 0x15,
44              (byte) 0x04, (byte) 0xC7, (byte) 0x23, (byte) 0xC3, (byte) 0x18, (byte) 0x96, (byte) 0x05, (byte) 0x9A,
45              (byte) 0x07, (byte) 0x12, (byte) 0x80, (byte) 0xE2, (byte) 0xEB, (byte) 0x27, (byte) 0xB2, (byte) 0x75,
46              (byte) 0x09, (byte) 0x83, (byte) 0x2C, (byte) 0x1A, (byte) 0x1B, (byte) 0x6E, (byte) 0x5A, (byte) 0xA0,
47              (byte) 0x52, (byte) 0x3B, (byte) 0xD6, (byte) 0xB3, (byte) 0x29, (byte) 0xE3, (byte) 0x2F, (byte) 0x84,
48              (byte) 0x53, (byte) 0xD1, (byte) 0x00, (byte) 0xED, (byte) 0x20, (byte) 0xFC, (byte) 0xB1, (byte) 0x5B,
49              (byte) 0x6A, (byte) 0xCB, (byte) 0xBE, (byte) 0x39, (byte) 0x4A, (byte) 0x4C, (byte) 0x58, (byte) 0xCF,
50              (byte) 0xD0, (byte) 0xEF, (byte) 0xAA, (byte) 0xFB, (byte) 0x43, (byte) 0x4D, (byte) 0x33, (byte) 0x85,
51              (byte) 0x45, (byte) 0xF9, (byte) 0x02, (byte) 0x7F, (byte) 0x50, (byte) 0x3C, (byte) 0x9F, (byte) 0xA8,
52              (byte) 0x51, (byte) 0xA3, (byte) 0x40, (byte) 0x8F, (byte) 0x92, (byte) 0x9D, (byte) 0x38, (byte) 0xF5,
53              (byte) 0xBC, (byte) 0xB6, (byte) 0xDA, (byte) 0x21, (byte) 0x10, (byte) 0xFF, (byte) 0xF3, (byte) 0xD2,
54              (byte) 0xCD, (byte) 0x0C, (byte) 0x13, (byte) 0xEC, (byte) 0x5F, (byte) 0x97, (byte) 0x44, (byte) 0x17,
55              (byte) 0xC4, (byte) 0xA7, (byte) 0x7E, (byte) 0x3D, (byte) 0x64, (byte) 0x5D, (byte) 0x19, (byte) 0x73,
56              (byte) 0x60, (byte) 0x81, (byte) 0x4F, (byte) 0xDC, (byte) 0x22, (byte) 0x2A, (byte) 0x90, (byte) 0x88,
57              (byte) 0x46, (byte) 0xEE, (byte) 0xB8, (byte) 0x14, (byte) 0xDE, (byte) 0x5E, (byte) 0x0B, (byte) 0xDB,
58              (byte) 0xE0, (byte) 0x32, (byte) 0x3A, (byte) 0x0A, (byte) 0x49, (byte) 0x06, (byte) 0x24, (byte) 0x5C,
59              (byte) 0xC2, (byte) 0xD3, (byte) 0xAC, (byte) 0x62, (byte) 0x91, (byte) 0x95, (byte) 0xE4, (byte) 0x79,
60              (byte) 0xE7, (byte) 0xC8, (byte) 0x37, (byte) 0x6D, (byte) 0x8D, (byte) 0xD5, (byte) 0x4E, (byte) 0xA9,
61              (byte) 0x6C, (byte) 0x56, (byte) 0xF4, (byte) 0xEA, (byte) 0x65, (byte) 0x7A, (byte) 0xAE, (byte) 0x08,
62              (byte) 0xBA, (byte) 0x78, (byte) 0x25, (byte) 0x2E, (byte) 0x1C, (byte) 0xA6, (byte) 0xB4, (byte) 0xC6,
63              (byte) 0xE8, (byte) 0xDD, (byte) 0x74, (byte) 0x1F, (byte) 0x4B, (byte) 0xBD, (byte) 0x8B, (byte) 0x8A,
64              (byte) 0x70, (byte) 0x3E, (byte) 0xB5, (byte) 0x66, (byte) 0x48, (byte) 0x03, (byte) 0xF6, (byte) 0x0E,
65              (byte) 0x61, (byte) 0x35, (byte) 0x57, (byte) 0xB9, (byte) 0x86, (byte) 0xC1, (byte) 0x1D, (byte) 0x9E,
66              (byte) 0xE1, (byte) 0xF8, (byte) 0x98, (byte) 0x11, (byte) 0x69, (byte) 0xD9, (byte) 0x8E, (byte) 0x94,
67              (byte) 0x9B, (byte) 0x1E, (byte) 0x87, (byte) 0xE9, (byte) 0xCE, (byte) 0x55, (byte) 0x28, (byte) 0xDF,
68              (byte) 0x8C, (byte) 0xA1, (byte) 0x89, (byte) 0x0D, (byte) 0xBF, (byte) 0xE6, (byte) 0x42, (byte) 0x68,
69              (byte) 0x41, (byte) 0x99, (byte) 0x2D, (byte) 0x0F, (byte) 0xB0, (byte) 0x54, (byte) 0xBB, (byte) 0x16
70      };
71  
72      /**
73       * S-box SQ.
74       */
75      private static final byte[] SQ = {
76              (byte) 0x25, (byte) 0x24, (byte) 0x73, (byte) 0x67, (byte) 0xD7, (byte) 0xAE, (byte) 0x5C, (byte) 0x30,
77              (byte) 0xA4, (byte) 0xEE, (byte) 0x6E, (byte) 0xCB, (byte) 0x7D, (byte) 0xB5, (byte) 0x82, (byte) 0xDB,
78              (byte) 0xE4, (byte) 0x8E, (byte) 0x48, (byte) 0x49, (byte) 0x4F, (byte) 0x5D, (byte) 0x6A, (byte) 0x78,
79              (byte) 0x70, (byte) 0x88, (byte) 0xE8, (byte) 0x5F, (byte) 0x5E, (byte) 0x84, (byte) 0x65, (byte) 0xE2,
80              (byte) 0xD8, (byte) 0xE9, (byte) 0xCC, (byte) 0xED, (byte) 0x40, (byte) 0x2F, (byte) 0x11, (byte) 0x28,
81              (byte) 0x57, (byte) 0xD2, (byte) 0xAC, (byte) 0xE3, (byte) 0x4A, (byte) 0x15, (byte) 0x1B, (byte) 0xB9,
82              (byte) 0xB2, (byte) 0x80, (byte) 0x85, (byte) 0xA6, (byte) 0x2E, (byte) 0x02, (byte) 0x47, (byte) 0x29,
83              (byte) 0x07, (byte) 0x4B, (byte) 0x0E, (byte) 0xC1, (byte) 0x51, (byte) 0xAA, (byte) 0x89, (byte) 0xD4,
84              (byte) 0xCA, (byte) 0x01, (byte) 0x46, (byte) 0xB3, (byte) 0xEF, (byte) 0xDD, (byte) 0x44, (byte) 0x7B,
85              (byte) 0xC2, (byte) 0x7F, (byte) 0xBE, (byte) 0xC3, (byte) 0x9F, (byte) 0x20, (byte) 0x4C, (byte) 0x64,
86              (byte) 0x83, (byte) 0xA2, (byte) 0x68, (byte) 0x42, (byte) 0x13, (byte) 0xB4, (byte) 0x41, (byte) 0xCD,
87              (byte) 0xBA, (byte) 0xC6, (byte) 0xBB, (byte) 0x6D, (byte) 0x4D, (byte) 0x71, (byte) 0x21, (byte) 0xF4,
88              (byte) 0x8D, (byte) 0xB0, (byte) 0xE5, (byte) 0x93, (byte) 0xFE, (byte) 0x8F, (byte) 0xE6, (byte) 0xCF,
89              (byte) 0x43, (byte) 0x45, (byte) 0x31, (byte) 0x22, (byte) 0x37, (byte) 0x36, (byte) 0x96, (byte) 0xFA,
90              (byte) 0xBC, (byte) 0x0F, (byte) 0x08, (byte) 0x52, (byte) 0x1D, (byte) 0x55, (byte) 0x1A, (byte) 0xC5,
91              (byte) 0x4E, (byte) 0x23, (byte) 0x69, (byte) 0x7A, (byte) 0x92, (byte) 0xFF, (byte) 0x5B, (byte) 0x5A,
92              (byte) 0xEB, (byte) 0x9A, (byte) 0x1C, (byte) 0xA9, (byte) 0xD1, (byte) 0x7E, (byte) 0x0D, (byte) 0xFC,
93              (byte) 0x50, (byte) 0x8A, (byte) 0xB6, (byte) 0x62, (byte) 0xF5, (byte) 0x0A, (byte) 0xF8, (byte) 0xDC,
94              (byte) 0x03, (byte) 0x3C, (byte) 0x0C, (byte) 0x39, (byte) 0xF1, (byte) 0xB8, (byte) 0xF3, (byte) 0x3D,
95              (byte) 0xF2, (byte) 0xD5, (byte) 0x97, (byte) 0x66, (byte) 0x81, (byte) 0x32, (byte) 0xA0, (byte) 0x00,
96              (byte) 0x06, (byte) 0xCE, (byte) 0xF6, (byte) 0xEA, (byte) 0xB7, (byte) 0x17, (byte) 0xF7, (byte) 0x8C,
97              (byte) 0x79, (byte) 0xD6, (byte) 0xA7, (byte) 0xBF, (byte) 0x8B, (byte) 0x3F, (byte) 0x1F, (byte) 0x53,
98              (byte) 0x63, (byte) 0x75, (byte) 0x35, (byte) 0x2C, (byte) 0x60, (byte) 0xFD, (byte) 0x27, (byte) 0xD3,
99              (byte) 0x94, (byte) 0xA5, (byte) 0x7C, (byte) 0xA1, (byte) 0x05, (byte) 0x58, (byte) 0x2D, (byte) 0xBD,
100             (byte) 0xD9, (byte) 0xC7, (byte) 0xAF, (byte) 0x6B, (byte) 0x54, (byte) 0x0B, (byte) 0xE0, (byte) 0x38,
101             (byte) 0x04, (byte) 0xC8, (byte) 0x9D, (byte) 0xE7, (byte) 0x14, (byte) 0xB1, (byte) 0x87, (byte) 0x9C,
102             (byte) 0xDF, (byte) 0x6F, (byte) 0xF9, (byte) 0xDA, (byte) 0x2A, (byte) 0xC4, (byte) 0x59, (byte) 0x16,
103             (byte) 0x74, (byte) 0x91, (byte) 0xAB, (byte) 0x26, (byte) 0x61, (byte) 0x76, (byte) 0x34, (byte) 0x2B,
104             (byte) 0xAD, (byte) 0x99, (byte) 0xFB, (byte) 0x72, (byte) 0xEC, (byte) 0x33, (byte) 0x12, (byte) 0xDE,
105             (byte) 0x98, (byte) 0x3B, (byte) 0xC0, (byte) 0x9B, (byte) 0x3E, (byte) 0x18, (byte) 0x10, (byte) 0x3A,
106             (byte) 0x56, (byte) 0xE1, (byte) 0x77, (byte) 0xC9, (byte) 0x1E, (byte) 0x9E, (byte) 0x95, (byte) 0xA3,
107             (byte) 0x90, (byte) 0x19, (byte) 0xA8, (byte) 0x6C, (byte) 0x09, (byte) 0xD0, (byte) 0xF0, (byte) 0x86
108     };
109 
110     /**
111      * LFSR State.
112      */
113     private final int[] lfsrState = new int[16];
114 
115     /**
116      * FSM State.
117      */
118     private final int[] fsmState = new int[3];
119 
120     /**
121      * index of next byte in keyStream.
122      */
123     private int theIndex;
124 
125     /**
126      * Advanced stream.
127      */
128     private final byte[] keyStream = new byte[Integer.BYTES];
129 
130     /**
131      * The iterations.
132      */
133     private int theIterations;
134 
135     /**
136      * Reset state.
137      */
138     private GordianSnow3GEngine theResetState;
139 
140     /**
141      * Constructor.
142      */
143     public GordianSnow3GEngine() {
144     }
145 
146     /**
147      * Constructor.
148      *
149      * @param pSource the source engine
150      */
151     private GordianSnow3GEngine(final GordianSnow3GEngine pSource) {
152         reset(pSource);
153     }
154 
155     /**
156      * initialise a Snow3G cipher.
157      *
158      * @param forEncryption whether or not we are for encryption.
159      * @param params        the parameters required to set up the cipher.
160      * @throws IllegalArgumentException if the params argument is inappropriate.
161      */
162     public void init(final boolean forEncryption,
163                      final CipherParameters params) {
164         /*
165          * encryption and decryption is completely symmetrical, so the 'forEncryption' is
166          * irrelevant. (Like 90% of stream ciphers)
167          */
168 
169         /* Determine parameters */
170         CipherParameters myParams = params;
171         byte[] newKey = null;
172         byte[] newIV = null;
173         if ((myParams instanceof ParametersWithIV)) {
174             final ParametersWithIV ivParams = (ParametersWithIV) myParams;
175             newIV = ivParams.getIV();
176             myParams = ivParams.getParameters();
177         }
178         if (myParams instanceof KeyParameter) {
179             final KeyParameter keyParam = (KeyParameter) myParams;
180             newKey = keyParam.getKey();
181         }
182 
183         /* Initialise engine and mark as initialised */
184         theIndex = 0;
185         theIterations = 0;
186         setKeyAndIV(newKey, newIV);
187 
188         /* Save reset state */
189         theResetState = copy();
190     }
191 
192     /**
193      * Obtain Max iterations.
194      *
195      * @return the maximum iterations
196      */
197     protected int getMaxIterations() {
198         return 625;
199     }
200 
201     @Override
202     public String getAlgorithmName() {
203         return "Snow3G";
204     }
205 
206     @Override
207     public int processBytes(final byte[] in,
208                             final int inOff,
209                             final int len,
210                             final byte[] out,
211                             final int outOff) {
212         /* Check for errors */
213         if (theResetState == null) {
214             throw new IllegalStateException(getAlgorithmName() + " not initialised");
215         }
216         if ((inOff + len) > in.length) {
217             throw new DataLengthException("input buffer too short");
218         }
219         if ((outOff + len) > out.length) {
220             throw new OutputLengthException("output buffer too short");
221         }
222 
223         /* Loop through the input bytes */
224         for (int i = 0; i < len; i++) {
225             out[i + outOff] = returnByte(in[i + inOff]);
226         }
227         return len;
228     }
229 
230     @Override
231     public void reset() {
232         if (theResetState != null) {
233             reset(theResetState);
234         }
235     }
236 
237     @Override
238     public byte returnByte(final byte in) {
239         /* Make the keyStream if required */
240         if (theIndex == 0) {
241             makeKeyStream();
242         }
243 
244         /* Map the next byte and adjust index */
245         final byte out = (byte) (keyStream[theIndex] ^ in);
246         theIndex = (theIndex + 1) % Integer.BYTES;
247 
248         /* Return the mapped character */
249         return out;
250     }
251 
252     /**
253      * Decode a 32-bit value from a buffer (little-endian).
254      *
255      * @param buf the input buffer
256      * @param off the input offset
257      * @return the decoded value
258      */
259     private static int decode32be(final byte[] buf, final int off) {
260         return ((buf[off] & 0xFF) << 24)
261                 | ((buf[off + 1] & 0xFF) << 16)
262                 | ((buf[off + 2] & 0xFF) << 8)
263                 | (buf[off + 3] & 0xFF);
264     }
265 
266     /**
267      * Encode a 32-bit value into a buffer (little-endian).
268      *
269      * @param val the value to encode
270      * @param buf the output buffer
271      * @param off the output offset
272      */
273     private static void encode32be(final int val, final byte[] buf, final int off) {
274         buf[off] = (byte) (val >> 24);
275         buf[off + 1] = (byte) (val >> 16);
276         buf[off + 2] = (byte) (val >> 8);
277         buf[off + 3] = (byte) (val);
278     }
279 
280     /* MULx.
281      * Input v: an 8-bit input.
282      * Input c: an 8-bit input.
283      * Output : an 8-bit output.
284      * See section 3.1.1 for details.
285      */
286     int mulX(final byte v, final int c) {
287         if ((v & 0x80) != 0) {
288             return ((v << 1) ^ c) & 0xFF;
289         } else {
290             return (v << 1) & 0xFF;
291         }
292     }
293 
294     /* MULxPOW.
295      * Input v: an 8-bit input.
296      * Input i: a positive integer.
297      * Input c: an 8-bit input.
298      * Output : an 8-bit output.
299      * See section 3.1.2 for details.
300      */
301     int mulXpow(final byte v, final int i, final int c) {
302         if (i == 0) {
303             return v & 0xFF;
304         } else {
305             return mulX((byte) mulXpow(v, i - 1, c), c);
306         }
307     }
308 
309     /* The function MUL alpha.
310      * Input c: 8-bit input.
311      * Output : 32-bit output.
312      * See section 3.4.2 for details.
313      */
314     int mulAlpha(final byte c) {
315         return ((mulXpow(c, 23, 0xa9) << 24)
316                 | (mulXpow(c, 245, 0xa9) << 16)
317                 | (mulXpow(c, 48, 0xa9) << 8)
318                 | (mulXpow(c, 239, 0xa9)));
319     }
320 
321     /* The function DIV alpha.
322      * Input c: 8-bit input.
323      * Output : 32-bit output.
324      * See section 3.4.3 for details.
325      */
326     int divAlpha(final byte c) {
327         return ((mulXpow(c, 16, 0xa9) << 24)
328                 | (mulXpow(c, 39, 0xa9) << 16)
329                 | (mulXpow(c, 6, 0xa9) << 8)
330                 | (mulXpow(c, 64, 0xa9)));
331     }
332 
333     /* The 32x32-bit S-Box S1
334      * Input: a 32-bit input.
335      * Output: a 32-bit output of S1 box.
336      * See section 3.3.1.
337      */
338     int s1(final int w) {
339         final byte srw0 = SR[((w >> 24) & 0xff)];
340         final byte srw1 = SR[((w >> 16) & 0xff)];
341         final byte srw2 = SR[((w >> 8) & 0xff)];
342         final byte srw3 = SR[((w) & 0xff)];
343         final int r0 = ((mulX(srw0, 0x1b))
344                 ^ (srw1)
345                 ^ (srw2)
346                 ^ ((mulX(srw3, 0x1b)) ^ srw3)
347         ) & 0xFF;
348         final int r1 = (((mulX(srw0, 0x1b)) ^ srw0)
349                 ^ (mulX(srw1, 0x1b))
350                 ^ (srw2)
351                 ^ (srw3)
352         ) & 0xFF;
353         final int r2 = ((srw0)
354                 ^ ((mulX(srw1, 0x1b)) ^ srw1)
355                 ^ (mulX(srw2, 0x1b))
356                 ^ (srw3)
357         ) & 0xFF;
358         final int r3 = ((srw0)
359                 ^ (srw1)
360                 ^ ((mulX(srw2, 0x1b)) ^ srw2)
361                 ^ (mulX(srw3, 0x1b))
362         ) & 0xFF;
363         return (((r0) << 24) | ((r1) << 16) | ((r2) << 8)
364                 | (r3));
365     }
366 
367     /* The 32x32-bit S-Box S2
368      * Input: a 32-bit input.
369      * Output: a 32-bit output of S2 box.
370      * See section 3.3.2.
371      */
372     int s2(final int w) {
373         final byte sqw0 = SQ[((w >> 24) & 0xff)];
374         final byte sqw1 = SQ[((w >> 16) & 0xff)];
375         final byte sqw2 = SQ[((w >> 8) & 0xff)];
376         final byte sqw3 = SQ[((w) & 0xff)];
377         final int r0 = ((mulX(sqw0, 0x69))
378                 ^ (sqw1)
379                 ^ (sqw2)
380                 ^ ((mulX(sqw3, 0x69)) ^ sqw3)
381         ) & 0xFF;
382         final int r1 = (((mulX(sqw0, 0x69)) ^ sqw0)
383                 ^ (mulX(sqw1, 0x69))
384                 ^ (sqw2)
385                 ^ (sqw3)
386         ) & 0xFF;
387         final int r2 = ((sqw0)
388                 ^ ((mulX(sqw1, 0x69)) ^ sqw1)
389                 ^ (mulX(sqw2, 0x69))
390                 ^ (sqw3)
391         ) & 0xFF;
392         final int r3 = ((sqw0)
393                 ^ (sqw1)
394                 ^ ((mulX(sqw2, 0x69)) ^ sqw2)
395                 ^ (mulX(sqw3, 0x69))
396         ) & 0xFF;
397         return (((r0) << 24) | ((r1) << 16) | ((r2) << 8)
398                 | (r3));
399     }
400 
401     /* Clocking LFSR in initialization mode.
402      * LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
403      * Input f: a 32-bit word comes from output of FSM.
404      * See section 3.4.4.
405      */
406     void clockLFSRInitializationMode(final int f) {
407         final int v = (((lfsrState[0] << 8) & 0xffffff00)
408                 ^ (mulAlpha((byte) ((lfsrState[0] >>> 24) & 0xff)))
409                 ^ (lfsrState[2])
410                 ^ ((lfsrState[11] >>> 8) & 0x00ffffff)
411                 ^ (divAlpha((byte) ((lfsrState[11]) & 0xff)))
412                 ^ (f)
413         );
414         lfsrState[0] = lfsrState[1];
415         lfsrState[1] = lfsrState[2];
416         lfsrState[2] = lfsrState[3];
417         lfsrState[3] = lfsrState[4];
418         lfsrState[4] = lfsrState[5];
419         lfsrState[5] = lfsrState[6];
420         lfsrState[6] = lfsrState[7];
421         lfsrState[7] = lfsrState[8];
422         lfsrState[8] = lfsrState[9];
423         lfsrState[9] = lfsrState[10];
424         lfsrState[10] = lfsrState[11];
425         lfsrState[11] = lfsrState[12];
426         lfsrState[12] = lfsrState[13];
427         lfsrState[13] = lfsrState[14];
428         lfsrState[14] = lfsrState[15];
429         lfsrState[15] = v;
430     }
431 
432     /* Clocking LFSR in keystream mode.
433      * LFSR Registers S0 to S15 are updated as the LFSR receives a single clock.
434      * See section 3.4.5.
435      */
436     void clockLFSRKeyStreamMode() {
437         final int v = (((lfsrState[0] << 8) & 0xffffff00)
438                 ^ (mulAlpha((byte) ((lfsrState[0] >>> 24) & 0xff)))
439                 ^ (lfsrState[2])
440                 ^ ((lfsrState[11] >>> 8) & 0x00ffffff)
441                 ^ (divAlpha((byte) ((lfsrState[11]) & 0xff)))
442         );
443         lfsrState[0] = lfsrState[1];
444         lfsrState[1] = lfsrState[2];
445         lfsrState[2] = lfsrState[3];
446         lfsrState[3] = lfsrState[4];
447         lfsrState[4] = lfsrState[5];
448         lfsrState[5] = lfsrState[6];
449         lfsrState[6] = lfsrState[7];
450         lfsrState[7] = lfsrState[8];
451         lfsrState[8] = lfsrState[9];
452         lfsrState[9] = lfsrState[10];
453         lfsrState[10] = lfsrState[11];
454         lfsrState[11] = lfsrState[12];
455         lfsrState[12] = lfsrState[13];
456         lfsrState[13] = lfsrState[14];
457         lfsrState[14] = lfsrState[15];
458         lfsrState[15] = v;
459     }
460 
461     /* Clocking FSM.
462      * Produces a 32-bit word F.
463      * Updates FSM registers R1, R2, R3.
464      * See Section 3.4.6.
465      */
466     int clockFSM() {
467         final int f = ((lfsrState[15] + fsmState[0]) & 0xffffffff) ^ fsmState[1];
468         final int r = (fsmState[1] + (fsmState[2] ^ lfsrState[5])) & 0xffffffff;
469         fsmState[2] = s2(fsmState[1]);
470         fsmState[1] = s1(fsmState[0]);
471         fsmState[0] = r;
472         return f;
473     }
474 
475     /* Initialization.
476      * Input k[4]: Four 32-bit words making up 128-bit key.
477      * Input IV[4]: Four 32-bit words making 128-bit initialization variable.
478      * Output: All the LFSRs and FSM are initialized for key generation.
479      * See Section 4.1.
480      */
481     void setKeyAndIV(final byte[] key, final byte[] iv) {
482         /* Check lengths */
483         if (key == null || key.length != 16) {
484             throw new IllegalArgumentException("A key of 16 bytes is needed");
485         }
486         if (iv == null || iv.length != 16) {
487             throw new IllegalArgumentException("An IV of 16 bytes is needed");
488         }
489 
490         /* Generate four subkeys */
491         final int k0 = decode32be(key, 12);
492         final int k1 = decode32be(key, 8);
493         final int k2 = decode32be(key, 4);
494         final int k3 = decode32be(key, 0);
495 
496         /* Generate four subvectors */
497         final int i0 = decode32be(iv, 12);
498         final int i1 = decode32be(iv, 8);
499         final int i2 = decode32be(iv, 4);
500         final int i3 = decode32be(iv, 0);
501 
502         lfsrState[15] = k3 ^ i0;
503         lfsrState[14] = k2;
504         lfsrState[13] = k1;
505         lfsrState[12] = k0 ^ i1;
506         lfsrState[11] = k3 ^ 0xffffffff;
507         lfsrState[10] = k2 ^ 0xffffffff ^ i2;
508         lfsrState[9] = k1 ^ 0xffffffff ^ i3;
509         lfsrState[8] = k0 ^ 0xffffffff;
510         lfsrState[7] = k3;
511         lfsrState[6] = k2;
512         lfsrState[5] = k1;
513         lfsrState[4] = k0;
514         lfsrState[3] = k3 ^ 0xffffffff;
515         lfsrState[2] = k2 ^ 0xffffffff;
516         lfsrState[1] = k1 ^ 0xffffffff;
517         lfsrState[0] = k0 ^ 0xffffffff;
518         fsmState[0] = 0x0;
519         fsmState[1] = 0x0;
520         fsmState[2] = 0x0;
521         for (int i = 0; i < 32; i++) {
522             final int f = clockFSM();
523             clockLFSRInitializationMode(f);
524         }
525         /* Clock FSM once. Discard the output. */
526         clockFSM();
527         /* Clock LFSR in keystream mode once. */
528         clockLFSRKeyStreamMode();
529     }
530 
531     /* Generation of Keystream.
532      * input n: number of 32-bit words of keystream.
533      * input z: space for the generated keystream, assumes
534      * memory is allocated already.
535      * output: generated keystream which is filled in z
536      * See section 4.2.
537      */
538     void makeKeyStream() {
539         if (theIterations++ >= getMaxIterations()) {
540             throw new IllegalStateException("Too much data processed by singleKey/IV");
541         }
542 
543         final int f = clockFSM(); // STEP 1 */
544         encode32be(f ^ lfsrState[0], keyStream, 0); // STEP 2 */
545         /* Note that ks[t] corresponds to z_{t+1} in section 4.2 */
546         clockLFSRKeyStreamMode(); // STEP 3 */
547     }
548 
549     @Override
550     public GordianSnow3GEngine copy() {
551         return new GordianSnow3GEngine(this);
552     }
553 
554     @Override
555     public void reset(final Memoable pState) {
556         final GordianSnow3GEngine e = (GordianSnow3GEngine) pState;
557         System.arraycopy(e.lfsrState, 0, lfsrState, 0, lfsrState.length);
558         System.arraycopy(e.fsmState, 0, fsmState, 0, fsmState.length);
559         System.arraycopy(e.keyStream, 0, keyStream, 0, keyStream.length);
560         theIterations = e.theIterations;
561         theIndex = e.theIndex;
562     }
563 }