summary refs log tree commit diff
path: root/Crypto/src/crypto/modes/gcm
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/crypto/modes/gcm')
-rw-r--r--Crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs40
-rw-r--r--Crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs20
-rw-r--r--Crypto/src/crypto/modes/gcm/GcmUtilities.cs149
-rw-r--r--Crypto/src/crypto/modes/gcm/IGcmExponentiator.cs10
-rw-r--r--Crypto/src/crypto/modes/gcm/IGcmMultiplier.cs10
-rw-r--r--Crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs44
-rw-r--r--Crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs64
-rw-r--r--Crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs90
8 files changed, 427 insertions, 0 deletions
diff --git a/Crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs b/Crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs
new file mode 100644

index 000000000..98049e1db --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs
@@ -0,0 +1,40 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class BasicGcmExponentiator + : IGcmExponentiator + { + private byte[] x; + + public void Init(byte[] x) + { + this.x = Arrays.Clone(x); + } + + public void ExponentiateX(long pow, byte[] output) + { + // Initial value is little-endian 1 + byte[] y = GcmUtilities.OneAsBytes(); + + if (pow > 0) + { + byte[] powX = Arrays.Clone(x); + do + { + if ((pow & 1L) != 0) + { + GcmUtilities.Multiply(y, powX); + } + GcmUtilities.Multiply(powX, powX); + pow >>= 1; + } + while (pow > 0); + } + + Array.Copy(y, 0, output, 0, 16); + } + } +} diff --git a/Crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs b/Crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs new file mode 100644
index 000000000..4076de990 --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs
@@ -0,0 +1,20 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class BasicGcmMultiplier + : IGcmMultiplier + { + private byte[] H; + + public void Init(byte[] H) + { + this.H = (byte[])H.Clone(); + } + + public void MultiplyH(byte[] x) + { + GcmUtilities.Multiply(x, H); + } + } +} diff --git a/Crypto/src/crypto/modes/gcm/GcmUtilities.cs b/Crypto/src/crypto/modes/gcm/GcmUtilities.cs new file mode 100644
index 000000000..8da125641 --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/GcmUtilities.cs
@@ -0,0 +1,149 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + internal abstract class GcmUtilities + { + internal static byte[] OneAsBytes() + { + byte[] tmp = new byte[16]; + tmp[0] = 0x80; + return tmp; + } + + internal static uint[] OneAsUints() + { + uint[] tmp = new uint[4]; + tmp[0] = 0x80000000; + return tmp; + } + + internal static uint[] AsUints(byte[] bs) + { + uint[] us = new uint[4]; + us[0] = Pack.BE_To_UInt32(bs, 0); + us[1] = Pack.BE_To_UInt32(bs, 4); + us[2] = Pack.BE_To_UInt32(bs, 8); + us[3] = Pack.BE_To_UInt32(bs, 12); + return us; + } + + internal static void Multiply(byte[] block, byte[] val) + { + byte[] tmp = Arrays.Clone(block); + byte[] c = new byte[16]; + + for (int i = 0; i < 16; ++i) + { + byte bits = val[i]; + for (int j = 7; j >= 0; --j) + { + if ((bits & (1 << j)) != 0) + { + Xor(c, tmp); + } + + bool lsb = (tmp[15] & 1) != 0; + ShiftRight(tmp); + if (lsb) + { + // R = new byte[]{ 0xe1, ... }; + //GCMUtilities.Xor(tmp, R); + tmp[0] ^= (byte)0xe1; + } + } + } + + Array.Copy(c, 0, block, 0, 16); + } + + // P is the value with only bit i=1 set + internal static void MultiplyP(uint[] x) + { + bool lsb = (x[3] & 1) != 0; + ShiftRight(x); + if (lsb) + { + // R = new uint[]{ 0xe1000000, 0, 0, 0 }; + //Xor(v, R); + x[0] ^= 0xe1000000; + } + } + + internal static void MultiplyP8(uint[] x) + { +// for (int i = 8; i != 0; --i) +// { +// MultiplyP(x); +// } + + uint lsw = x[3]; + ShiftRightN(x, 8); + for (int i = 7; i >= 0; --i) + { + if ((lsw & (1 << i)) != 0) + { + x[0] ^= (0xe1000000 >> (7 - i)); + } + } + } + + internal static void ShiftRight(byte[] block) + { + int i = 0; + byte bit = 0; + for (;;) + { + byte b = block[i]; + block[i] = (byte)((b >> 1) | bit); + if (++i == 16) break; + bit = (byte)(b << 7); + } + } + + internal static void ShiftRight(uint[] block) + { + int i = 0; + uint bit = 0; + for (;;) + { + uint b = block[i]; + block[i] = (b >> 1) | bit; + if (++i == 4) break; + bit = b << 31; + } + } + + internal static void ShiftRightN(uint[] block, int n) + { + int i = 0; + uint bit = 0; + for (;;) + { + uint b = block[i]; + block[i] = (b >> n) | bit; + if (++i == 4) break; + bit = b << (32 - n); + } + } + + internal static void Xor(byte[] block, byte[] val) + { + for (int i = 15; i >= 0; --i) + { + block[i] ^= val[i]; + } + } + + internal static void Xor(uint[] block, uint[] val) + { + for (int i = 3; i >= 0; --i) + { + block[i] ^= val[i]; + } + } + } +} diff --git a/Crypto/src/crypto/modes/gcm/IGcmExponentiator.cs b/Crypto/src/crypto/modes/gcm/IGcmExponentiator.cs new file mode 100644
index 000000000..5b4ce9d7a --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/IGcmExponentiator.cs
@@ -0,0 +1,10 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public interface IGcmExponentiator + { + void Init(byte[] x); + void ExponentiateX(long pow, byte[] output); + } +} diff --git a/Crypto/src/crypto/modes/gcm/IGcmMultiplier.cs b/Crypto/src/crypto/modes/gcm/IGcmMultiplier.cs new file mode 100644
index 000000000..ec7b906ee --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/IGcmMultiplier.cs
@@ -0,0 +1,10 @@ +using System; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public interface IGcmMultiplier + { + void Init(byte[] H); + void MultiplyH(byte[] x); + } +} diff --git a/Crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs b/Crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs new file mode 100644
index 000000000..9425a3d9d --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs
@@ -0,0 +1,44 @@ +using System; + +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class Tables1kGcmExponentiator + : IGcmExponentiator + { + // A lookup table of the power-of-two powers of 'x' + private byte[][] lookupPowX2 = new byte[64][]; + + public void Init(byte[] x) + { + lookupPowX2[0] = GcmUtilities.OneAsBytes(); + lookupPowX2[1] = Arrays.Clone(x); + + for (int i = 2; i != 64; ++i) + { + byte[] tmp = Arrays.Clone(lookupPowX2[i - 1]); + GcmUtilities.Multiply(tmp, tmp); + lookupPowX2[i] = tmp; + } + } + + public void ExponentiateX(long pow, byte[] output) + { + byte[] y = GcmUtilities.OneAsBytes(); + int powX2 = 1; + + while (pow > 0) + { + if ((pow & 1L) != 0) + { + GcmUtilities.Multiply(y, lookupPowX2[powX2]); + } + ++powX2; + pow >>= 1; + } + + Array.Copy(y, 0, output, 0, 16); + } + } +} diff --git a/Crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs b/Crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs new file mode 100644
index 000000000..f089dfe8d --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs
@@ -0,0 +1,64 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class Tables64kGcmMultiplier + : IGcmMultiplier + { + private readonly uint[][][] M = new uint[16][][]; + + public void Init(byte[] H) + { + M[0] = new uint[256][]; + M[0][0] = new uint[4]; + M[0][128] = GcmUtilities.AsUints(H); + for (int j = 64; j >= 1; j >>= 1) + { + uint[] tmp = (uint[])M[0][j + j].Clone(); + GcmUtilities.MultiplyP(tmp); + M[0][j] = tmp; + } + for (int i = 0;;) + { + for (int j = 2; j < 256; j += j) + { + for (int k = 1; k < j; ++k) + { + uint[] tmp = (uint[])M[i][j].Clone(); + GcmUtilities.Xor(tmp, M[i][k]); + M[i][j + k] = tmp; + } + } + + if (++i == 16) return; + + M[i] = new uint[256][]; + M[i][0] = new uint[4]; + for (int j = 128; j > 0; j >>= 1) + { + uint[] tmp = (uint[])M[i - 1][j].Clone(); + GcmUtilities.MultiplyP8(tmp); + M[i][j] = tmp; + } + } + } + + public void MultiplyH(byte[] x) + { + uint[] z = new uint[4]; + for (int i = 0; i != 16; ++i) + { + //GcmUtilities.Xor(z, M[i][x[i]]); + uint[] m = M[i][x[i]]; + z[0] ^= m[0]; + z[1] ^= m[1]; + z[2] ^= m[2]; + z[3] ^= m[3]; + } + + Pack.UInt32_To_BE(z, x, 0); + } + } +} diff --git a/Crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs b/Crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs new file mode 100644
index 000000000..91d58fab8 --- /dev/null +++ b/Crypto/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs
@@ -0,0 +1,90 @@ +using System; + +using Org.BouncyCastle.Crypto.Utilities; + +namespace Org.BouncyCastle.Crypto.Modes.Gcm +{ + public class Tables8kGcmMultiplier + : IGcmMultiplier + { + private readonly uint[][][] M = new uint[32][][]; + + public void Init(byte[] H) + { + M[0] = new uint[16][]; + M[1] = new uint[16][]; + M[0][0] = new uint[4]; + M[1][0] = new uint[4]; + M[1][8] = GcmUtilities.AsUints(H); + + for (int j = 4; j >= 1; j >>= 1) + { + uint[] tmp = (uint[])M[1][j + j].Clone(); + GcmUtilities.MultiplyP(tmp); + M[1][j] = tmp; + } + + { + uint[] tmp = (uint[])M[1][1].Clone(); + GcmUtilities.MultiplyP(tmp); + M[0][8] = tmp; + } + + for (int j = 4; j >= 1; j >>= 1) + { + uint[] tmp = (uint[])M[0][j + j].Clone(); + GcmUtilities.MultiplyP(tmp); + M[0][j] = tmp; + } + + for (int i = 0;;) + { + for (int j = 2; j < 16; j += j) + { + for (int k = 1; k < j; ++k) + { + uint[] tmp = (uint[])M[i][j].Clone(); + GcmUtilities.Xor(tmp, M[i][k]); + M[i][j + k] = tmp; + } + } + + if (++i == 32) return; + + if (i > 1) + { + M[i] = new uint[16][]; + M[i][0] = new uint[4]; + for(int j = 8; j > 0; j >>= 1) + { + uint[] tmp = (uint[])M[i - 2][j].Clone(); + GcmUtilities.MultiplyP8(tmp); + M[i][j] = tmp; + } + } + } + } + + public void MultiplyH(byte[] x) + { + uint[] z = new uint[4]; + for (int i = 15; i >= 0; --i) + { + //GcmUtilities.Xor(z, M[i + i][x[i] & 0x0f]); + uint[] m = M[i + i][x[i] & 0x0f]; + z[0] ^= m[0]; + z[1] ^= m[1]; + z[2] ^= m[2]; + z[3] ^= m[3]; + //GcmUtilities.Xor(z, M[i + i + 1][(x[i] & 0xf0) >> 4]); + m = M[i + i + 1][(x[i] & 0xf0) >> 4]; + z[0] ^= m[0]; + z[1] ^= m[1]; + z[2] ^= m[2]; + z[3] ^= m[3]; + } + + Pack.UInt32_To_BE(z, x, 0); + } + } +}