1c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrompackage org.bouncycastle.crypto.modes.gcm;
2c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
3c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.util.Pack;
46e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstromimport org.bouncycastle.util.Arrays;
5c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
6c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromabstract class GCMUtil
7c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom{
86e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    static byte[] oneAsBytes()
96e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
106e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] tmp = new byte[16];
116e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        tmp[0] = (byte)0x80;
126e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return tmp;
136e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
146e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
156e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    static int[] oneAsInts()
166e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
176e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        int[] tmp = new int[4];
186e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        tmp[0] = 0x80000000;
196e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        return tmp;
206e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
216e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
22c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static int[] asInts(byte[] bs)
23c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
24c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int[] us = new int[4];
25c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        us[0] = Pack.bigEndianToInt(bs, 0);
26c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        us[1] = Pack.bigEndianToInt(bs, 4);
27c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        us[2] = Pack.bigEndianToInt(bs, 8);
28c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        us[3] = Pack.bigEndianToInt(bs, 12);
29c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        return us;
30c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
31c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
326e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    static void multiply(byte[] block, byte[] val)
336e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    {
346e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] tmp = Arrays.clone(block);
356e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        byte[] c = new byte[16];
366e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
376e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        for (int i = 0; i < 16; ++i)
386e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        {
396e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            byte bits = val[i];
406e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            for (int j = 7; j >= 0; --j)
416e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            {
426e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if ((bits & (1 << j)) != 0)
436e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
446e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    xor(c, tmp);
456e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
466e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
476e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                boolean lsb = (tmp[15] & 1) != 0;
486e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                shiftRight(tmp);
496e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                if (lsb)
506e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                {
516e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    // R = new byte[]{ 0xe1, ... };
526e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom//                    GCMUtil.xor(v, R);
536e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                    tmp[0] ^= (byte)0xe1;
546e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom                }
556e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom            }
566e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        }
576e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
586e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom        System.arraycopy(c, 0, block, 0, 16);
596e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom    }
606e736056d64d0e33b26cf9f7c4e351b496241fdeBrian Carlstrom
61c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    // P is the value with only bit i=1 set
62c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static void multiplyP(int[] x)
63c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
64c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        boolean lsb = (x[3] & 1) != 0;
65c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        shiftRight(x);
66c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        if (lsb)
67c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
68c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            // R = new int[]{ 0xe1000000, 0, 0, 0 };
69c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom//            xor(v, R);
70c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            x[0] ^= 0xe1000000;
71c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
72c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
73c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
74c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static void multiplyP8(int[] x)
75c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom//        for (int i = 8; i != 0; --i)
774c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom//        {
784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom//            multiplyP(x);
794c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom//        }
804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
814c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int lsw = x[3];
824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        shiftRightN(x, 8);
834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        for (int i = 7; i >= 0; --i)
84c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
854c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if ((lsw & (1 << i)) != 0)
864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                x[0] ^= (0xe1000000 >>> (7 - i));
884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
89c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
90c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
91c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
92c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static void shiftRight(byte[] block)
93c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
94c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int i = 0;
95c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int bit = 0;
96c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        for (;;)
97c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
98c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            int b = block[i] & 0xff;
99c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            block[i] = (byte) ((b >>> 1) | bit);
100c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (++i == 16)
101c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
102c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                break;
103c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
104c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            bit = (b & 1) << 7;
105c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
106c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
107c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
108c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static void shiftRight(int[] block)
109c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
110c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int i = 0;
111c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        int bit = 0;
112c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        for (;;)
113c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
114c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            int b = block[i];
115c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            block[i] = (b >>> 1) | bit;
116c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            if (++i == 4)
117c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            {
118c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom                break;
119c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            }
120c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            bit = b << 31;
121c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
122c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
123c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
1244c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    static void shiftRightN(int[] block, int n)
1254c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    {
1264c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int i = 0;
1274c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        int bits = 0;
1284c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        for (;;)
1294c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        {
1304c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            int b = block[i];
1314c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            block[i] = (b >>> n) | bits;
1324c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            if (++i == 4)
1334c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            {
1344c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom                break;
1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            }
1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom            bits = b << (32 - n);
1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom        }
1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom    }
1394c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom
140c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static void xor(byte[] block, byte[] val)
141c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
142c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        for (int i = 15; i >= 0; --i)
143c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
144c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            block[i] ^= val[i];
145c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
146c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
147c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom
148c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    static void xor(int[] block, int[] val)
149c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    {
150c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        for (int i = 3; i >= 0; --i)
151c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        {
152c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom            block[i] ^= val[i];
153c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom        }
154c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom    }
155c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom}
156