diff --git a/crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs b/crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs
index 98049e1db..5660a1f84 100644
--- a/crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs
+++ b/crypto/src/crypto/modes/gcm/BasicGcmExponentiator.cs
@@ -4,37 +4,37 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Modes.Gcm
{
- public class BasicGcmExponentiator
- : IGcmExponentiator
- {
- private byte[] x;
+ public class BasicGcmExponentiator
+ : IGcmExponentiator
+ {
+ private uint[] x;
- public void Init(byte[] x)
- {
- this.x = Arrays.Clone(x);
- }
+ public void Init(byte[] x)
+ {
+ this.x = GcmUtilities.AsUints(x);
+ }
- public void ExponentiateX(long pow, byte[] output)
- {
- // Initial value is little-endian 1
- byte[] y = GcmUtilities.OneAsBytes();
+ public void ExponentiateX(long pow, byte[] output)
+ {
+ // Initial value is little-endian 1
+ uint[] y = GcmUtilities.OneAsUints();
- 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);
- }
+ if (pow > 0)
+ {
+ uint[] 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);
- }
- }
+ GcmUtilities.AsBytes(y, output);
+ }
+ }
}
diff --git a/crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs b/crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs
index 85e3ac9b1..eb89383fb 100644
--- a/crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs
+++ b/crypto/src/crypto/modes/gcm/BasicGcmMultiplier.cs
@@ -1,22 +1,22 @@
using System;
-using Org.BouncyCastle.Utilities;
-
namespace Org.BouncyCastle.Crypto.Modes.Gcm
{
- public class BasicGcmMultiplier
- : IGcmMultiplier
- {
- private byte[] H;
+ public class BasicGcmMultiplier
+ : IGcmMultiplier
+ {
+ private uint[] H;
- public void Init(byte[] H)
- {
- this.H = Arrays.Clone(H);
- }
+ public void Init(byte[] H)
+ {
+ this.H = GcmUtilities.AsUints(H);
+ }
public void MultiplyH(byte[] x)
- {
- GcmUtilities.Multiply(x, H);
- }
- }
+ {
+ uint[] t = GcmUtilities.AsUints(x);
+ GcmUtilities.Multiply(t, H);
+ GcmUtilities.AsBytes(t, x);
+ }
+ }
}
diff --git a/crypto/src/crypto/modes/gcm/GcmUtilities.cs b/crypto/src/crypto/modes/gcm/GcmUtilities.cs
index 71e63c8fd..0f241035f 100644
--- a/crypto/src/crypto/modes/gcm/GcmUtilities.cs
+++ b/crypto/src/crypto/modes/gcm/GcmUtilities.cs
@@ -7,6 +7,31 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm
{
internal abstract class GcmUtilities
{
+ private const uint E1 = 0xe1000000;
+ private const ulong E1L = (ulong)E1 << 32;
+
+ private static uint[] GenerateLookup()
+ {
+ uint[] lookup = new uint[256];
+
+ for (int c = 0; c < 256; ++c)
+ {
+ uint 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 readonly uint[] LOOKUP = GenerateLookup();
+
internal static byte[] OneAsBytes()
{
byte[] tmp = new byte[16];
@@ -21,6 +46,16 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm
return tmp;
}
+ internal static byte[] AsBytes(uint[] x)
+ {
+ return Pack.UInt32_To_BE(x);
+ }
+
+ internal static void AsBytes(uint[] x, byte[] z)
+ {
+ Pack.UInt32_To_BE(x, z, 0);
+ }
+
internal static uint[] AsUints(byte[] bs)
{
uint[] output = new uint[4];
@@ -33,56 +68,55 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm
Pack.BE_To_UInt32(bs, 0, output);
}
- internal static void Multiply(byte[] block, byte[] val)
+ internal static void Multiply(byte[] x, byte[] y)
{
- byte[] tmp = Arrays.Clone(block);
- byte[] c = new byte[16];
+ uint[] t1 = GcmUtilities.AsUints(x);
+ uint[] t2 = GcmUtilities.AsUints(y);
+ GcmUtilities.Multiply(t1, t2);
+ GcmUtilities.AsBytes(t1, x);
+ }
- for (int i = 0; i < 16; ++i)
+ internal static void Multiply(uint[] x, uint[] y)
+ {
+ uint r00 = x[0], r01 = x[1], r02 = x[2], r03 = x[3];
+ uint r10 = 0, r11 = 0, r12 = 0, r13 = 0;
+
+ for (int i = 0; i < 4; ++i)
{
- byte bits = val[i];
- for (int j = 7; j >= 0; --j)
+ int bits = (int)y[i];
+ for (int j = 0; j < 32; ++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;
- }
+ uint m1 = (uint)(bits >> 31); bits <<= 1;
+ r10 ^= (r00 & m1);
+ r11 ^= (r01 & m1);
+ r12 ^= (r02 & m1);
+ r13 ^= (r03 & m1);
+
+ uint m2 = (uint)((int)(r03 << 31) >> 8);
+ r03 = (r03 >> 1) | (r02 << 63);
+ r02 = (r02 >> 1) | (r01 << 63);
+ r01 = (r01 >> 1) | (r00 << 63);
+ r00 = (r00 >> 1) ^ (m2 & E1);
}
}
- Array.Copy(c, 0, block, 0, 16);
+ x[0] = r10;
+ x[1] = r11;
+ x[2] = r12;
+ x[3] = r13;
}
// 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;
- }
+ uint m = (uint)((int)ShiftRight(x) >> 8);
+ x[0] ^= (m & E1);
}
- internal static void MultiplyP(uint[] x, uint[] output)
+ internal static void MultiplyP(uint[] x, uint[] z)
{
- bool lsb = (x[3] & 1) != 0;
- ShiftRight(x, output);
- if (lsb)
- {
- output[0] ^= 0xe1000000;
- }
+ uint m = (uint)((int)ShiftRight(x, z) >> 8);
+ z[0] ^= (m & E1);
}
internal static void MultiplyP8(uint[] x)
@@ -92,146 +126,128 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm
// 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 MultiplyP8(uint[] x, uint[] output)
- {
- uint lsw = x[3];
- ShiftRightN(x, 8, output);
- for (int i = 7; i >= 0; --i)
- {
- if ((lsw & (1 << i)) != 0)
- {
- output[0] ^= (0xe1000000 >> (7 - i));
- }
- }
+ uint c = ShiftRightN(x, 8);
+ x[0] ^= LOOKUP[c >> 24];
}
- internal static void ShiftRight(byte[] block)
+ internal static void MultiplyP8(uint[] x, uint[] y)
{
- 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);
- }
+ uint c = ShiftRightN(x, 8, y);
+ y[0] ^= LOOKUP[c >> 24];
}
- static void ShiftRight(byte[] block, byte[] output)
+ internal static uint ShiftRight(uint[] x)
{
- int i = 0;
- byte bit = 0;
- for (;;)
- {
- byte b = block[i];
- output[i] = (byte)((b >> 1) | bit);
- if (++i == 16) break;
- bit = (byte)(b << 7);
- }
+ uint b = x[0];
+ x[0] = b >> 1;
+ uint 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;
}
- internal static void ShiftRight(uint[] block)
+ internal static uint ShiftRight(uint[] x, uint[] z)
{
- int i = 0;
- uint bit = 0;
- for (; ; )
- {
- uint b = block[i];
- block[i] = (b >> 1) | bit;
- if (++i == 4) break;
- bit = b << 31;
- }
+ uint b = x[0];
+ z[0] = b >> 1;
+ uint 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;
}
- internal static void ShiftRight(uint[] block, uint[] output)
+ internal static uint ShiftRightN(uint[] x, int n)
{
- int i = 0;
- uint bit = 0;
- for (; ; )
- {
- uint b = block[i];
- output[i] = (b >> 1) | bit;
- if (++i == 4) break;
- bit = b << 31;
- }
+ uint b = x[0]; int nInv = 32 - n;
+ x[0] = b >> n;
+ uint 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;
}
- internal static void ShiftRightN(uint[] block, int n)
+ internal static uint ShiftRightN(uint[] x, int n, uint[] z)
{
- int i = 0;
- uint bit = 0;
- for (; ; )
- {
- uint b = block[i];
- block[i] = (b >> n) | bit;
- if (++i == 4) break;
- bit = b << (32 - n);
- }
+ uint b = x[0]; int nInv = 32 - n;
+ z[0] = b >> n;
+ uint 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;
}
- internal static void ShiftRightN(uint[] block, int n, uint[] output)
+ internal static void Xor(byte[] x, byte[] y)
{
int i = 0;
- uint bit = 0;
- for (; ; )
- {
- uint b = block[i];
- output[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)
+ do
{
- block[i] ^= val[i];
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
}
+ while (i < 16);
}
- internal static void Xor(byte[] block, byte[] val, int off, int len)
+ internal static void Xor(byte[] x, byte[] y, int yOff, int yLen)
{
- while (--len >= 0)
+ while (--yLen >= 0)
{
- block[len] ^= val[off + len];
+ x[yLen] ^= y[yOff + yLen];
}
}
- internal static void Xor(byte[] block, byte[] val, byte[] output)
+ internal static void Xor(byte[] x, byte[] y, byte[] z)
{
- for (int i = 15; i >= 0; --i)
+ int i = 0;
+ do
{
- output[i] = (byte)(block[i] ^ val[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;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
}
+ while (i < 16);
}
- internal static void Xor(uint[] block, uint[] val)
+ internal static void Xor(uint[] x, uint[] y)
{
- for (int i = 3; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ x[2] ^= y[2];
+ x[3] ^= y[3];
}
- internal static void Xor(uint[] block, uint[] val, uint[] output)
+ internal static void Xor(uint[] x, uint[] y, uint[] z)
{
- for (int i = 3; i >= 0; --i)
- {
- output[i] = block[i] ^ val[i];
- }
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
}
}
}
diff --git a/crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs b/crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs
index 44933bba7..e649d6770 100644
--- a/crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs
+++ b/crypto/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs
@@ -5,48 +5,47 @@ using Org.BouncyCastle.Utilities;
namespace Org.BouncyCastle.Crypto.Modes.Gcm
{
- public class Tables1kGcmExponentiator
- : IGcmExponentiator
- {
+ public class Tables1kGcmExponentiator
+ : IGcmExponentiator
+ {
// A lookup table of the power-of-two powers of 'x'
// - lookupPowX2[i] = x^(2^i)
private IList lookupPowX2;
public void Init(byte[] x)
- {
- if (lookupPowX2 != null && Arrays.AreEqual(x, (byte[])lookupPowX2[0]))
- {
+ {
+ uint[] y = GcmUtilities.AsUints(x);
+ if (lookupPowX2 != null && Arrays.AreEqual(y, (uint[])lookupPowX2[0]))
return;
- }
lookupPowX2 = Platform.CreateArrayList(8);
- lookupPowX2.Add(Arrays.Clone(x));
- }
+ lookupPowX2.Add(y);
+ }
- public void ExponentiateX(long pow, byte[] output)
- {
- byte[] y = GcmUtilities.OneAsBytes();
+ public void ExponentiateX(long pow, byte[] output)
+ {
+ uint[] y = GcmUtilities.OneAsUints();
int bit = 0;
while (pow > 0)
{
if ((pow & 1L) != 0)
{
EnsureAvailable(bit);
- GcmUtilities.Multiply(y, (byte[])lookupPowX2[bit]);
+ GcmUtilities.Multiply(y, (uint[])lookupPowX2[bit]);
}
++bit;
pow >>= 1;
}
- Array.Copy(y, 0, output, 0, 16);
- }
+ GcmUtilities.AsBytes(y, output);
+ }
private void EnsureAvailable(int bit)
{
int count = lookupPowX2.Count;
if (count <= bit)
{
- byte[] tmp = (byte[])lookupPowX2[count - 1];
+ uint[] tmp = (uint[])lookupPowX2[count - 1];
do
{
tmp = Arrays.Clone(tmp);
diff --git a/crypto/src/util/Arrays.cs b/crypto/src/util/Arrays.cs
index 27fd18d6d..8614baead 100644
--- a/crypto/src/util/Arrays.cs
+++ b/crypto/src/util/Arrays.cs
@@ -339,6 +339,11 @@ namespace Org.BouncyCastle.Utilities
return data == null ? null : (int[])data.Clone();
}
+ internal static uint[] Clone(uint[] data)
+ {
+ return data == null ? null : (uint[])data.Clone();
+ }
+
public static long[] Clone(long[] data)
{
return data == null ? null : (long[])data.Clone();
|