diff options
Diffstat (limited to 'crypto/src/crypto/modes/gcm/GcmUtilities.cs')
-rw-r--r-- | crypto/src/crypto/modes/gcm/GcmUtilities.cs | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/crypto/src/crypto/modes/gcm/GcmUtilities.cs b/crypto/src/crypto/modes/gcm/GcmUtilities.cs index a239e9ec0..b2c74d7d0 100644 --- a/crypto/src/crypto/modes/gcm/GcmUtilities.cs +++ b/crypto/src/crypto/modes/gcm/GcmUtilities.cs @@ -140,6 +140,108 @@ namespace Org.BouncyCastle.Crypto.Modes.Gcm x.n1 = z1; } +#if NETCOREAPP3_0_OR_GREATER + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128<ulong> Load(byte[] x) + { + AsFieldElement(x, out FieldElement X); + return Vector128.Create(X.n1, X.n0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128<ulong> Multiply(Vector128<ulong> X, Vector128<ulong> Y) + { + MultiplyExt(X, Y, out var Z0, out var Z1, out var Z2); + return Reduce3(Z0, Z1, Z2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void MultiplyExt(Vector128<ulong> X, Vector128<ulong> Y, out Vector128<ulong> Z0, + out Vector128<ulong> Z1, out Vector128<ulong> Z2) + { + if (!Pclmulqdq.IsSupported) + throw new PlatformNotSupportedException(nameof(GcmUtilities.MultiplyExt)); + + Z0 = Pclmulqdq.CarrylessMultiply(X, Y, 0x00); + Z1 = Sse2.Xor(Pclmulqdq.CarrylessMultiply(X, Y, 0x01), + Pclmulqdq.CarrylessMultiply(X, Y, 0x10)); + Z2 = Pclmulqdq.CarrylessMultiply(X, Y, 0x11); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128<ulong> Reduce2(Vector128<ulong> Z0, Vector128<ulong> Z2) + { + ulong t3 = Z0.GetElement(0); + ulong t2 = Z0.GetElement(1); + ulong t1 = Z2.GetElement(0); + ulong t0 = Z2.GetElement(1); + + ulong z0 = (t0 << 1) | (t1 >> 63); + ulong z1 = (t1 << 1) | (t2 >> 63); + ulong z2 = (t2 << 1) | (t3 >> 63); + ulong z3 = (t3 << 1); + + Debug.Assert(z3 << 63 == 0); + + z1 ^= z3 ^ (z3 >> 1) ^ (z3 >> 2) ^ (z3 >> 7); +// z2 ^= (z3 << 63) ^ (z3 << 62) ^ (z3 << 57); + z2 ^= (z3 << 62) ^ (z3 << 57); + + z0 ^= z2 ^ (z2 >> 1) ^ (z2 >> 2) ^ (z2 >> 7); + z1 ^= (z2 << 63) ^ (z2 << 62) ^ (z2 << 57); + + return Vector128.Create(z1, z0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128<ulong> Reduce3(Vector128<ulong> Z0, Vector128<ulong> Z1, Vector128<ulong> Z2) + { + ulong t3 = Z0.GetElement(0); + ulong t2 = Z0.GetElement(1) ^ Z1.GetElement(0); + ulong t1 = Z2.GetElement(0) ^ Z1.GetElement(1); + ulong t0 = Z2.GetElement(1); + + ulong z0 = (t0 << 1) | (t1 >> 63); + ulong z1 = (t1 << 1) | (t2 >> 63); + ulong z2 = (t2 << 1) | (t3 >> 63); + ulong z3 = (t3 << 1); + + Debug.Assert(z3 << 63 == 0); + + z1 ^= z3 ^ (z3 >> 1) ^ (z3 >> 2) ^ (z3 >> 7); +// z2 ^= (z3 << 63) ^ (z3 << 62) ^ (z3 << 57); + z2 ^= (z3 << 62) ^ (z3 << 57); + + z0 ^= z2 ^ (z2 >> 1) ^ (z2 >> 2) ^ (z2 >> 7); + z1 ^= (z2 << 63) ^ (z2 << 62) ^ (z2 << 57); + + return Vector128.Create(z1, z0); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void Store(Vector128<ulong> X, byte[] z) + { + AsBytes(X.GetElement(1), X.GetElement(0), z); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector128<ulong> Square(Vector128<ulong> X) + { + SquareExt(X, out var Z0, out var Z2); + return Reduce2(Z0, Z2); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void SquareExt(Vector128<ulong> X, out Vector128<ulong> Z0, out Vector128<ulong> Z2) + { + if (!Pclmulqdq.IsSupported) + throw new PlatformNotSupportedException(nameof(GcmUtilities.SquareExt)); + + Z0 = Pclmulqdq.CarrylessMultiply(X, X, 0x00); + Z2 = Pclmulqdq.CarrylessMultiply(X, X, 0x11); + } +#endif + internal static void MultiplyP7(ref FieldElement x) { ulong x0 = x.n0, x1 = x.n1; |