1package org.bouncycastle.crypto.modes.gcm;
2
3import org.bouncycastle.crypto.util.Pack;
4import org.bouncycastle.util.Arrays;
5
6abstract class GCMUtil
7{
8    private static final int E1 = 0xe1000000;
9    private static final byte E1B = (byte)0xe1;
10    private static final long E1L = (E1 & 0xFFFFFFFFL) << 24;
11
12    private static int[] generateLookup()
13    {
14        int[] lookup = new int[256];
15
16        for (int c = 0; c < 256; ++c)
17        {
18            int v = 0;
19            for (int i = 7; i >= 0; --i)
20            {
21                if ((c & (1 << i)) != 0)
22                {
23                    v ^= (E1 >>> (7 - i));
24                }
25            }
26            lookup[c] = v;
27        }
28
29        return lookup;
30    }
31
32    private static final int[] LOOKUP = generateLookup();
33
34    static byte[] oneAsBytes()
35    {
36        byte[] tmp = new byte[16];
37        tmp[0] = (byte)0x80;
38        return tmp;
39    }
40
41    static int[] oneAsInts()
42    {
43        int[] tmp = new int[4];
44        tmp[0] = 1 << 31;
45        return tmp;
46    }
47
48    static long[] oneAsLongs()
49    {
50        long[] tmp = new long[2];
51        tmp[0] = 1L << 63;
52        return tmp;
53    }
54
55    static byte[] asBytes(int[] x)
56    {
57        byte[] z = new byte[16];
58        Pack.intToBigEndian(x, z, 0);
59        return z;
60    }
61
62    static void asBytes(int[] x, byte[] z)
63    {
64        Pack.intToBigEndian(x, z, 0);
65    }
66
67    static byte[] asBytes(long[] x)
68    {
69        byte[] z = new byte[16];
70        Pack.longToBigEndian(x, z, 0);
71        return z;
72    }
73
74    static void asBytes(long[] x, byte[] z)
75    {
76        Pack.longToBigEndian(x, z, 0);
77    }
78
79    static int[] asInts(byte[] x)
80    {
81        int[] z = new int[4];
82        Pack.bigEndianToInt(x, 0, z);
83        return z;
84    }
85
86    static void asInts(byte[] x, int[] z)
87    {
88        Pack.bigEndianToInt(x, 0, z);
89    }
90
91    static long[] asLongs(byte[] x)
92    {
93        long[] z = new long[2];
94        Pack.bigEndianToLong(x, 0, z);
95        return z;
96    }
97
98    static void asLongs(byte[] x, long[] z)
99    {
100        Pack.bigEndianToLong(x, 0, z);
101    }
102
103    static void multiply(byte[] x, byte[] y)
104    {
105        byte[] r0 = Arrays.clone(x);
106        byte[] r1 = new byte[16];
107
108        for (int i = 0; i < 16; ++i)
109        {
110            byte bits = y[i];
111            for (int j = 7; j >= 0; --j)
112            {
113                if ((bits & (1 << j)) != 0)
114                {
115                    xor(r1, r0);
116                }
117
118                if (shiftRight(r0) != 0)
119                {
120                    r0[0] ^= E1B;
121                }
122            }
123        }
124
125        System.arraycopy(r1, 0, x, 0, 16);
126    }
127
128    static void multiply(int[] x, int[] y)
129    {
130        int[] r0 = Arrays.clone(x);
131        int[] r1 = new int[4];
132
133        for (int i = 0; i < 4; ++i)
134        {
135            int bits = y[i];
136            for (int j = 31; j >= 0; --j)
137            {
138                if ((bits & (1 << j)) != 0)
139                {
140                    xor(r1, r0);
141                }
142
143                if (shiftRight(r0) != 0)
144                {
145                    r0[0] ^= E1;
146                }
147            }
148        }
149
150        System.arraycopy(r1, 0, x, 0, 4);
151    }
152
153    static void multiply(long[] x, long[] y)
154    {
155        long[] r0 = new long[]{ x[0], x[1] };
156        long[] r1 = new long[2];
157
158        for (int i = 0; i < 2; ++i)
159        {
160            long bits = y[i];
161            for (int j = 63; j >= 0; --j)
162            {
163                if ((bits & (1L << j)) != 0)
164                {
165                    xor(r1, r0);
166                }
167
168                if (shiftRight(r0) != 0)
169                {
170                    r0[0] ^= E1L;
171                }
172            }
173        }
174
175        x[0] = r1[0];
176        x[1] = r1[1];
177    }
178
179    // P is the value with only bit i=1 set
180    static void multiplyP(int[] x)
181    {
182        if (shiftRight(x) != 0)
183        {
184            x[0] ^= E1;
185        }
186    }
187
188    static void multiplyP(int[] x, int[] y)
189    {
190        if (shiftRight(x, y) != 0)
191        {
192            y[0] ^= E1;
193        }
194    }
195
196    // P is the value with only bit i=1 set
197    static void multiplyP8(int[] x)
198    {
199//        for (int i = 8; i != 0; --i)
200//        {
201//            multiplyP(x);
202//        }
203
204        int c = shiftRightN(x, 8);
205        x[0] ^= LOOKUP[c >>> 24];
206    }
207
208    static void multiplyP8(int[] x, int[] y)
209    {
210        int c = shiftRightN(x, 8, y);
211        y[0] ^= LOOKUP[c >>> 24];
212    }
213
214    static byte shiftRight(byte[] x)
215    {
216//        int c = 0;
217//        for (int i = 0; i < 16; ++i)
218//        {
219//            int b = x[i] & 0xff;
220//            x[i] = (byte)((b >>> 1) | c);
221//            c = (b & 1) << 7;
222//        }
223//        return (byte)c;
224
225        int i = 0, c = 0;
226        do
227        {
228            int b = x[i] & 0xff;
229            x[i++] = (byte)((b >>> 1) | c);
230            c = (b & 1) << 7;
231            b = x[i] & 0xff;
232            x[i++] = (byte)((b >>> 1) | c);
233            c = (b & 1) << 7;
234            b = x[i] & 0xff;
235            x[i++] = (byte)((b >>> 1) | c);
236            c = (b & 1) << 7;
237            b = x[i] & 0xff;
238            x[i++] = (byte)((b >>> 1) | c);
239            c = (b & 1) << 7;
240        }
241        while (i < 16);
242        return (byte)c;
243    }
244
245    static byte shiftRight(byte[] x, byte[] z)
246    {
247//        int c = 0;
248//        for (int i = 0; i < 16; ++i)
249//        {
250//            int b = x[i] & 0xff;
251//            z[i] = (byte) ((b >>> 1) | c);
252//            c = (b & 1) << 7;
253//        }
254//        return (byte) c;
255
256        int i = 0, c = 0;
257        do
258        {
259            int b = x[i] & 0xff;
260            z[i++] = (byte)((b >>> 1) | c);
261            c = (b & 1) << 7;
262            b = x[i] & 0xff;
263            z[i++] = (byte)((b >>> 1) | c);
264            c = (b & 1) << 7;
265            b = x[i] & 0xff;
266            z[i++] = (byte)((b >>> 1) | c);
267            c = (b & 1) << 7;
268            b = x[i] & 0xff;
269            z[i++] = (byte)((b >>> 1) | c);
270            c = (b & 1) << 7;
271        }
272        while (i < 16);
273        return (byte)c;
274    }
275
276    static int shiftRight(int[] x)
277    {
278//        int c = 0;
279//        for (int i = 0; i < 4; ++i)
280//        {
281//            int b = x[i];
282//            x[i] = (b >>> 1) | c;
283//            c = b << 31;
284//        }
285//        return c;
286
287        int b = x[0];
288        x[0] = b >>> 1;
289        int c = b << 31;
290        b = x[1];
291        x[1] = (b >>> 1) | c;
292        c = b << 31;
293        b = x[2];
294        x[2] = (b >>> 1) | c;
295        c = b << 31;
296        b = x[3];
297        x[3] = (b >>> 1) | c;
298        return b << 31;
299    }
300
301    static int shiftRight(int[] x, int[] z)
302    {
303//      int c = 0;
304//      for (int i = 0; i < 4; ++i)
305//      {
306//          int b = x[i];
307//          z[i] = (b >>> 1) | c;
308//          c = b << 31;
309//      }
310//      return c;
311
312        int b = x[0];
313        z[0] = b >>> 1;
314        int c = b << 31;
315        b = x[1];
316        z[1] = (b >>> 1) | c;
317        c = b << 31;
318        b = x[2];
319        z[2] = (b >>> 1) | c;
320        c = b << 31;
321        b = x[3];
322        z[3] = (b >>> 1) | c;
323        return b << 31;
324    }
325
326    static long shiftRight(long[] x)
327    {
328        long b = x[0];
329        x[0] = b >>> 1;
330        long c = b << 63;
331        b = x[1];
332        x[1] = (b >>> 1) | c;
333        return b << 63;
334    }
335
336    static long shiftRight(long[] x, long[] z)
337    {
338        long b = x[0];
339        z[0] = b >>> 1;
340        long c = b << 63;
341        b = x[1];
342        z[1] = (b >>> 1) | c;
343        return b << 63;
344    }
345
346    static int shiftRightN(int[] x, int n)
347    {
348//        int c = 0, nInv = 32 - n;
349//        for (int i = 0; i < 4; ++i)
350//        {
351//            int b = x[i];
352//            x[i] = (b >>> n) | c;
353//            c = b << nInv;
354//        }
355//        return c;
356
357        int b = x[0], nInv = 32 - n;
358        x[0] = b >>> n;
359        int c = b << nInv;
360        b = x[1];
361        x[1] = (b >>> n) | c;
362        c = b << nInv;
363        b = x[2];
364        x[2] = (b >>> n) | c;
365        c = b << nInv;
366        b = x[3];
367        x[3] = (b >>> n) | c;
368        return b << nInv;
369    }
370
371    static int shiftRightN(int[] x, int n, int[] z)
372    {
373//        int c = 0, nInv = 32 - n;
374//        for (int i = 0; i < 4; ++i)
375//        {
376//            int b = x[i];
377//            z[i] = (b >>> n) | c;
378//            c = b << nInv;
379//        }
380//        return c;
381
382        int b = x[0], nInv = 32 - n;
383        z[0] = b >>> n;
384        int c = b << nInv;
385        b = x[1];
386        z[1] = (b >>> n) | c;
387        c = b << nInv;
388        b = x[2];
389        z[2] = (b >>> n) | c;
390        c = b << nInv;
391        b = x[3];
392        z[3] = (b >>> n) | c;
393        return b << nInv;
394    }
395
396    static void xor(byte[] x, byte[] y)
397    {
398        int i = 0;
399        do
400        {
401            x[i] ^= y[i]; ++i;
402            x[i] ^= y[i]; ++i;
403            x[i] ^= y[i]; ++i;
404            x[i] ^= y[i]; ++i;
405        }
406        while (i < 16);
407    }
408
409    static void xor(byte[] x, byte[] y, int yOff, int yLen)
410    {
411        while (yLen-- > 0)
412        {
413            x[yLen] ^= y[yOff + yLen];
414        }
415    }
416
417    static void xor(byte[] x, byte[] y, byte[] z)
418    {
419        int i = 0;
420        do
421        {
422            z[i] = (byte)(x[i] ^ y[i]); ++i;
423            z[i] = (byte)(x[i] ^ y[i]); ++i;
424            z[i] = (byte)(x[i] ^ y[i]); ++i;
425            z[i] = (byte)(x[i] ^ y[i]); ++i;
426        }
427        while (i < 16);
428    }
429
430    static void xor(int[] x, int[] y)
431    {
432        x[0] ^= y[0];
433        x[1] ^= y[1];
434        x[2] ^= y[2];
435        x[3] ^= y[3];
436    }
437
438    static void xor(int[] x, int[] y, int[] z)
439    {
440        z[0] = x[0] ^ y[0];
441        z[1] = x[1] ^ y[1];
442        z[2] = x[2] ^ y[2];
443        z[3] = x[3] ^ y[3];
444    }
445
446    static void xor(long[] x, long[] y)
447    {
448        x[0] ^= y[0];
449        x[1] ^= y[1];
450    }
451
452    static void xor(long[] x, long[] y, long[] z)
453    {
454        z[0] = x[0] ^ y[0];
455        z[1] = x[1] ^ y[1];
456    }
457}
458