| package org.bouncycastle.crypto.modes.gcm; |
| |
| import org.bouncycastle.crypto.util.Pack; |
| import org.bouncycastle.util.Arrays; |
| |
| abstract class GCMUtil |
| { |
| private static final int E1 = 0xe1000000; |
| private static final byte E1B = (byte)0xe1; |
| private static final long E1L = (E1 & 0xFFFFFFFFL) << 24; |
| |
| private static int[] generateLookup() |
| { |
| int[] lookup = new int[256]; |
| |
| for (int c = 0; c < 256; ++c) |
| { |
| int v = 0; |
| for (int i = 7; i >= 0; --i) |
| { |
| if ((c & (1 << i)) != 0) |
| { |
| v ^= (E1 >>> (7 - i)); |
| } |
| } |
| lookup[c] = v; |
| } |
| |
| return lookup; |
| } |
| |
| private static final int[] LOOKUP = generateLookup(); |
| |
| static byte[] oneAsBytes() |
| { |
| byte[] tmp = new byte[16]; |
| tmp[0] = (byte)0x80; |
| return tmp; |
| } |
| |
| static int[] oneAsInts() |
| { |
| int[] tmp = new int[4]; |
| tmp[0] = 1 << 31; |
| return tmp; |
| } |
| |
| static long[] oneAsLongs() |
| { |
| long[] tmp = new long[2]; |
| tmp[0] = 1L << 63; |
| return tmp; |
| } |
| |
| static byte[] asBytes(int[] x) |
| { |
| byte[] z = new byte[16]; |
| Pack.intToBigEndian(x, z, 0); |
| return z; |
| } |
| |
| static void asBytes(int[] x, byte[] z) |
| { |
| Pack.intToBigEndian(x, z, 0); |
| } |
| |
| static byte[] asBytes(long[] x) |
| { |
| byte[] z = new byte[16]; |
| Pack.longToBigEndian(x, z, 0); |
| return z; |
| } |
| |
| static void asBytes(long[] x, byte[] z) |
| { |
| Pack.longToBigEndian(x, z, 0); |
| } |
| |
| static int[] asInts(byte[] x) |
| { |
| int[] z = new int[4]; |
| Pack.bigEndianToInt(x, 0, z); |
| return z; |
| } |
| |
| static void asInts(byte[] x, int[] z) |
| { |
| Pack.bigEndianToInt(x, 0, z); |
| } |
| |
| static long[] asLongs(byte[] x) |
| { |
| long[] z = new long[2]; |
| Pack.bigEndianToLong(x, 0, z); |
| return z; |
| } |
| |
| static void asLongs(byte[] x, long[] z) |
| { |
| Pack.bigEndianToLong(x, 0, z); |
| } |
| |
| static void multiply(byte[] x, byte[] y) |
| { |
| byte[] r0 = Arrays.clone(x); |
| byte[] r1 = new byte[16]; |
| |
| for (int i = 0; i < 16; ++i) |
| { |
| byte bits = y[i]; |
| for (int j = 7; j >= 0; --j) |
| { |
| if ((bits & (1 << j)) != 0) |
| { |
| xor(r1, r0); |
| } |
| |
| if (shiftRight(r0) != 0) |
| { |
| r0[0] ^= E1B; |
| } |
| } |
| } |
| |
| System.arraycopy(r1, 0, x, 0, 16); |
| } |
| |
| static void multiply(int[] x, int[] y) |
| { |
| int[] r0 = Arrays.clone(x); |
| int[] r1 = new int[4]; |
| |
| for (int i = 0; i < 4; ++i) |
| { |
| int bits = y[i]; |
| for (int j = 31; j >= 0; --j) |
| { |
| if ((bits & (1 << j)) != 0) |
| { |
| xor(r1, r0); |
| } |
| |
| if (shiftRight(r0) != 0) |
| { |
| r0[0] ^= E1; |
| } |
| } |
| } |
| |
| System.arraycopy(r1, 0, x, 0, 4); |
| } |
| |
| static void multiply(long[] x, long[] y) |
| { |
| long[] r0 = new long[]{ x[0], x[1] }; |
| long[] r1 = new long[2]; |
| |
| for (int i = 0; i < 2; ++i) |
| { |
| long bits = y[i]; |
| for (int j = 63; j >= 0; --j) |
| { |
| if ((bits & (1L << j)) != 0) |
| { |
| xor(r1, r0); |
| } |
| |
| if (shiftRight(r0) != 0) |
| { |
| r0[0] ^= E1L; |
| } |
| } |
| } |
| |
| x[0] = r1[0]; |
| x[1] = r1[1]; |
| } |
| |
| // P is the value with only bit i=1 set |
| static void multiplyP(int[] x) |
| { |
| if (shiftRight(x) != 0) |
| { |
| x[0] ^= E1; |
| } |
| } |
| |
| static void multiplyP(int[] x, int[] y) |
| { |
| if (shiftRight(x, y) != 0) |
| { |
| y[0] ^= E1; |
| } |
| } |
| |
| // P is the value with only bit i=1 set |
| static void multiplyP8(int[] x) |
| { |
| // for (int i = 8; i != 0; --i) |
| // { |
| // multiplyP(x); |
| // } |
| |
| int c = shiftRightN(x, 8); |
| x[0] ^= LOOKUP[c >>> 24]; |
| } |
| |
| static void multiplyP8(int[] x, int[] y) |
| { |
| int c = shiftRightN(x, 8, y); |
| y[0] ^= LOOKUP[c >>> 24]; |
| } |
| |
| static byte shiftRight(byte[] x) |
| { |
| // int c = 0; |
| // for (int i = 0; i < 16; ++i) |
| // { |
| // int b = x[i] & 0xff; |
| // x[i] = (byte)((b >>> 1) | c); |
| // c = (b & 1) << 7; |
| // } |
| // return (byte)c; |
| |
| int i = 0, c = 0; |
| do |
| { |
| int b = x[i] & 0xff; |
| x[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| b = x[i] & 0xff; |
| x[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| b = x[i] & 0xff; |
| x[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| b = x[i] & 0xff; |
| x[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| } |
| while (i < 16); |
| return (byte)c; |
| } |
| |
| static byte shiftRight(byte[] x, byte[] z) |
| { |
| // int c = 0; |
| // for (int i = 0; i < 16; ++i) |
| // { |
| // int b = x[i] & 0xff; |
| // z[i] = (byte) ((b >>> 1) | c); |
| // c = (b & 1) << 7; |
| // } |
| // return (byte) c; |
| |
| int i = 0, c = 0; |
| do |
| { |
| int b = x[i] & 0xff; |
| z[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| b = x[i] & 0xff; |
| z[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| b = x[i] & 0xff; |
| z[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| b = x[i] & 0xff; |
| z[i++] = (byte)((b >>> 1) | c); |
| c = (b & 1) << 7; |
| } |
| while (i < 16); |
| return (byte)c; |
| } |
| |
| static int shiftRight(int[] x) |
| { |
| // int c = 0; |
| // for (int i = 0; i < 4; ++i) |
| // { |
| // int b = x[i]; |
| // x[i] = (b >>> 1) | c; |
| // c = b << 31; |
| // } |
| // return c; |
| |
| int b = x[0]; |
| x[0] = b >>> 1; |
| int c = b << 31; |
| b = x[1]; |
| x[1] = (b >>> 1) | c; |
| c = b << 31; |
| b = x[2]; |
| x[2] = (b >>> 1) | c; |
| c = b << 31; |
| b = x[3]; |
| x[3] = (b >>> 1) | c; |
| return b << 31; |
| } |
| |
| static int shiftRight(int[] x, int[] z) |
| { |
| // int c = 0; |
| // for (int i = 0; i < 4; ++i) |
| // { |
| // int b = x[i]; |
| // z[i] = (b >>> 1) | c; |
| // c = b << 31; |
| // } |
| // return c; |
| |
| int b = x[0]; |
| z[0] = b >>> 1; |
| int c = b << 31; |
| b = x[1]; |
| z[1] = (b >>> 1) | c; |
| c = b << 31; |
| b = x[2]; |
| z[2] = (b >>> 1) | c; |
| c = b << 31; |
| b = x[3]; |
| z[3] = (b >>> 1) | c; |
| return b << 31; |
| } |
| |
| static long shiftRight(long[] x) |
| { |
| long b = x[0]; |
| x[0] = b >>> 1; |
| long c = b << 63; |
| b = x[1]; |
| x[1] = (b >>> 1) | c; |
| return b << 63; |
| } |
| |
| static long shiftRight(long[] x, long[] z) |
| { |
| long b = x[0]; |
| z[0] = b >>> 1; |
| long c = b << 63; |
| b = x[1]; |
| z[1] = (b >>> 1) | c; |
| return b << 63; |
| } |
| |
| static int shiftRightN(int[] x, int n) |
| { |
| // int c = 0, nInv = 32 - n; |
| // for (int i = 0; i < 4; ++i) |
| // { |
| // int b = x[i]; |
| // x[i] = (b >>> n) | c; |
| // c = b << nInv; |
| // } |
| // return c; |
| |
| int b = x[0], nInv = 32 - n; |
| x[0] = b >>> n; |
| int c = b << nInv; |
| b = x[1]; |
| x[1] = (b >>> n) | c; |
| c = b << nInv; |
| b = x[2]; |
| x[2] = (b >>> n) | c; |
| c = b << nInv; |
| b = x[3]; |
| x[3] = (b >>> n) | c; |
| return b << nInv; |
| } |
| |
| static int shiftRightN(int[] x, int n, int[] z) |
| { |
| // int c = 0, nInv = 32 - n; |
| // for (int i = 0; i < 4; ++i) |
| // { |
| // int b = x[i]; |
| // z[i] = (b >>> n) | c; |
| // c = b << nInv; |
| // } |
| // return c; |
| |
| int b = x[0], nInv = 32 - n; |
| z[0] = b >>> n; |
| int c = b << nInv; |
| b = x[1]; |
| z[1] = (b >>> n) | c; |
| c = b << nInv; |
| b = x[2]; |
| z[2] = (b >>> n) | c; |
| c = b << nInv; |
| b = x[3]; |
| z[3] = (b >>> n) | c; |
| return b << nInv; |
| } |
| |
| static void xor(byte[] x, byte[] y) |
| { |
| int i = 0; |
| do |
| { |
| x[i] ^= y[i]; ++i; |
| x[i] ^= y[i]; ++i; |
| x[i] ^= y[i]; ++i; |
| x[i] ^= y[i]; ++i; |
| } |
| while (i < 16); |
| } |
| |
| static void xor(byte[] x, byte[] y, int yOff, int yLen) |
| { |
| while (yLen-- > 0) |
| { |
| x[yLen] ^= y[yOff + yLen]; |
| } |
| } |
| |
| static void xor(byte[] x, byte[] y, byte[] z) |
| { |
| int i = 0; |
| do |
| { |
| z[i] = (byte)(x[i] ^ y[i]); ++i; |
| z[i] = (byte)(x[i] ^ y[i]); ++i; |
| z[i] = (byte)(x[i] ^ y[i]); ++i; |
| z[i] = (byte)(x[i] ^ y[i]); ++i; |
| } |
| while (i < 16); |
| } |
| |
| static void xor(int[] x, int[] y) |
| { |
| x[0] ^= y[0]; |
| x[1] ^= y[1]; |
| x[2] ^= y[2]; |
| x[3] ^= y[3]; |
| } |
| |
| static void xor(int[] x, int[] y, int[] z) |
| { |
| z[0] = x[0] ^ y[0]; |
| z[1] = x[1] ^ y[1]; |
| z[2] = x[2] ^ y[2]; |
| z[3] = x[3] ^ y[3]; |
| } |
| |
| static void xor(long[] x, long[] y) |
| { |
| x[0] ^= y[0]; |
| x[1] ^= y[1]; |
| } |
| |
| static void xor(long[] x, long[] y, long[] z) |
| { |
| z[0] = x[0] ^ y[0]; |
| z[1] = x[1] ^ y[1]; |
| } |
| } |