blob: 3031a444f84f49655c0253d716d4818f96d328fc [file] [log] [blame]
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];
}
}