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