1package org.bouncycastle.crypto.modes.gcm;
2
3import org.bouncycastle.crypto.util.Pack;
4import org.bouncycastle.util.Arrays;
5
6abstract class GCMUtil
7{
8    static byte[] oneAsBytes()
9    {
10        byte[] tmp = new byte[16];
11        tmp[0] = (byte)0x80;
12        return tmp;
13    }
14
15    static int[] oneAsInts()
16    {
17        int[] tmp = new int[4];
18        tmp[0] = 0x80000000;
19        return tmp;
20    }
21
22    static byte[] asBytes(int[] ns)
23    {
24        byte[] output = new byte[16];
25        Pack.intToBigEndian(ns, output, 0);
26        return output;
27    }
28
29    static int[] asInts(byte[] bs)
30    {
31        int[] output = new int[4];
32        Pack.bigEndianToInt(bs, 0, output);
33        return output;
34    }
35
36    static void asInts(byte[] bs, int[] output)
37    {
38        Pack.bigEndianToInt(bs, 0, output);
39    }
40
41    static void multiply(byte[] block, byte[] val)
42    {
43        byte[] tmp = Arrays.clone(block);
44        byte[] c = new byte[16];
45
46        for (int i = 0; i < 16; ++i)
47        {
48            byte bits = val[i];
49            for (int j = 7; j >= 0; --j)
50            {
51                if ((bits & (1 << j)) != 0)
52                {
53                    xor(c, tmp);
54                }
55
56                boolean lsb = (tmp[15] & 1) != 0;
57                shiftRight(tmp);
58                if (lsb)
59                {
60                    // R = new byte[]{ 0xe1, ... };
61//                    GCMUtil.xor(v, R);
62                    tmp[0] ^= (byte)0xe1;
63                }
64            }
65        }
66
67        System.arraycopy(c, 0, block, 0, 16);
68    }
69
70    // P is the value with only bit i=1 set
71    static void multiplyP(int[] x)
72    {
73        boolean lsb = (x[3] & 1) != 0;
74        shiftRight(x);
75        if (lsb)
76        {
77            // R = new int[]{ 0xe1000000, 0, 0, 0 };
78//            xor(v, R);
79            x[0] ^= 0xe1000000;
80        }
81    }
82
83    static void multiplyP(int[] x, int[] output)
84    {
85        boolean lsb = (x[3] & 1) != 0;
86        shiftRight(x, output);
87        if (lsb)
88        {
89            output[0] ^= 0xe1000000;
90        }
91    }
92
93    // P is the value with only bit i=1 set
94    static void multiplyP8(int[] x)
95    {
96//        for (int i = 8; i != 0; --i)
97//        {
98//            multiplyP(x);
99//        }
100
101        int lsw = x[3];
102        shiftRightN(x, 8);
103        for (int i = 7; i >= 0; --i)
104        {
105            if ((lsw & (1 << i)) != 0)
106            {
107                x[0] ^= (0xe1000000 >>> (7 - i));
108            }
109        }
110    }
111
112    static void multiplyP8(int[] x, int[] output)
113    {
114        int lsw = x[3];
115        shiftRightN(x, 8, output);
116        for (int i = 7; i >= 0; --i)
117        {
118            if ((lsw & (1 << i)) != 0)
119            {
120                output[0] ^= (0xe1000000 >>> (7 - i));
121            }
122        }
123    }
124
125    static void shiftRight(byte[] block)
126    {
127        int i = 0;
128        int bit = 0;
129        for (;;)
130        {
131            int b = block[i] & 0xff;
132            block[i] = (byte) ((b >>> 1) | bit);
133            if (++i == 16)
134            {
135                break;
136            }
137            bit = (b & 1) << 7;
138        }
139    }
140
141    static void shiftRight(byte[] block, byte[] output)
142    {
143        int i = 0;
144        int bit = 0;
145        for (;;)
146        {
147            int b = block[i] & 0xff;
148            output[i] = (byte) ((b >>> 1) | bit);
149            if (++i == 16)
150            {
151                break;
152            }
153            bit = (b & 1) << 7;
154        }
155    }
156
157    static void shiftRight(int[] block)
158    {
159        int i = 0;
160        int bit = 0;
161        for (;;)
162        {
163            int b = block[i];
164            block[i] = (b >>> 1) | bit;
165            if (++i == 4)
166            {
167                break;
168            }
169            bit = b << 31;
170        }
171    }
172
173    static void shiftRight(int[] block, int[] output)
174    {
175        int i = 0;
176        int bit = 0;
177        for (;;)
178        {
179            int b = block[i];
180            output[i] = (b >>> 1) | bit;
181            if (++i == 4)
182            {
183                break;
184            }
185            bit = b << 31;
186        }
187    }
188
189    static void shiftRightN(int[] block, int n)
190    {
191        int i = 0;
192        int bits = 0;
193        for (;;)
194        {
195            int b = block[i];
196            block[i] = (b >>> n) | bits;
197            if (++i == 4)
198            {
199                break;
200            }
201            bits = b << (32 - n);
202        }
203    }
204
205    static void shiftRightN(int[] block, int n, int[] output)
206    {
207        int i = 0;
208        int bits = 0;
209        for (;;)
210        {
211            int b = block[i];
212            output[i] = (b >>> n) | bits;
213            if (++i == 4)
214            {
215                break;
216            }
217            bits = b << (32 - n);
218        }
219    }
220
221    static void xor(byte[] block, byte[] val)
222    {
223        for (int i = 15; i >= 0; --i)
224        {
225            block[i] ^= val[i];
226        }
227    }
228
229    static void xor(byte[] block, byte[] val, int off, int len)
230    {
231        while (len-- > 0)
232        {
233            block[len] ^= val[off + len];
234        }
235    }
236
237    static void xor(byte[] block, byte[] val, byte[] output)
238    {
239        for (int i = 15; i >= 0; --i)
240        {
241            output[i] = (byte)(block[i] ^ val[i]);
242        }
243    }
244
245    static void xor(int[] block, int[] val)
246    {
247        for (int i = 3; i >= 0; --i)
248        {
249            block[i] ^= val[i];
250        }
251    }
252
253    static void xor(int[] block, int[] val, int[] output)
254    {
255        for (int i = 3; i >= 0; --i)
256        {
257            output[i] = block[i] ^ val[i];
258        }
259    }
260}
261