<PackageReference Include="BouncyCastle.Cryptography" Version="2.4.0" />

SecT193Field

static class SecT193Field
using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Runtime.Intrinsics.X86; using System; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal static class SecT193Field { private const ulong M01 = 1; private const ulong M49 = 562949953421311; public static void Add(ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> 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]); } public static void AddBothTo(ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> 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]); } public static void AddExt(ReadOnlySpan<ulong> xx, ReadOnlySpan<ulong> yy, Span<ulong> zz) { zz[0] = (xx[0] ^ yy[0]); zz[1] = (xx[1] ^ yy[1]); zz[2] = (xx[2] ^ yy[2]); zz[3] = (xx[3] ^ yy[3]); zz[4] = (xx[4] ^ yy[4]); zz[5] = (xx[5] ^ yy[5]); zz[6] = (xx[6] ^ yy[6]); } public static void AddOne(ReadOnlySpan<ulong> x, Span<ulong> z) { z[0] = (x[0] ^ 1); z[1] = x[1]; z[2] = x[2]; z[3] = x[3]; } public static void AddTo(ReadOnlySpan<ulong> x, Span<ulong> z) { z[0] ^= x[0]; z[1] ^= x[1]; z[2] ^= x[2]; z[3] ^= x[3]; } public static ulong[] FromBigInteger(BigInteger x) { return Nat.FromBigInteger64(193, x); } public unsafe static void HalfTrace(ReadOnlySpan<ulong> x, Span<ulong> z) { Span<ulong> span = new Span<ulong>(stackalloc byte[64], 8); Nat256.Copy64(x, z); for (int i = 1; i < 193; i += 2) { ImplSquare(z, span); Reduce(span, z); ImplSquare(z, span); Reduce(span, z); AddTo(x, z); } } public unsafe static void Invert(ReadOnlySpan<ulong> x, Span<ulong> z) { if (Nat256.IsZero64(x)) throw new InvalidOperationException(); Span<ulong> span = new Span<ulong>(stackalloc byte[32], 4); Span<ulong> span2 = new Span<ulong>(stackalloc byte[32], 4); Square(x, span); SquareN(span, 1, span2); Multiply(span, span2, span); SquareN(span2, 1, span2); Multiply(span, span2, span); SquareN(span, 3, span2); Multiply(span, span2, span); SquareN(span, 6, span2); Multiply(span, span2, span); SquareN(span, 12, span2); Multiply(span, span2, span); SquareN(span, 24, span2); Multiply(span, span2, span); SquareN(span, 48, span2); Multiply(span, span2, span); SquareN(span, 96, span2); Multiply(span, span2, z); } public unsafe static void Multiply(ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> z) { Span<ulong> span = new Span<ulong>(stackalloc byte[64], 8); ImplMultiply(x, y, span); Reduce(span, z); } public unsafe static void MultiplyAddToExt(ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> zz) { Span<ulong> span = new Span<ulong>(stackalloc byte[64], 8); ImplMultiply(x, y, span); AddExt(zz, span, zz); } public static void MultiplyExt(ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> zz) { zz.Slice(0, 8).Fill(0); ImplMultiply(x, y, zz); } public static void Reduce(ReadOnlySpan<ulong> xx, Span<ulong> z) { ulong num = xx[0]; ulong num2 = xx[1]; ulong num3 = xx[2]; ulong num4 = xx[3]; ulong num5 = xx[4]; ulong num6 = xx[5]; ulong num7 = xx[6]; num3 ^= num7 << 63; num4 ^= ((num7 >> 1) ^ (num7 << 14)); num5 ^= num7 >> 50; num2 ^= num6 << 63; num3 ^= ((num6 >> 1) ^ (num6 << 14)); num4 ^= num6 >> 50; num ^= num5 << 63; num2 ^= ((num5 >> 1) ^ (num5 << 14)); num3 ^= num5 >> 50; ulong num8 = num4 >> 1; z[0] = (num ^ num8 ^ (num8 << 15)); z[1] = (num2 ^ (num8 >> 49)); z[2] = num3; z[3] = (num4 & 1); } public static void Reduce63(ulong[] z, int zOff) { ulong num = z[zOff + 3]; ulong num2 = num >> 1; z[zOff] ^= (num2 ^ (num2 << 15)); z[zOff + 1] ^= num2 >> 49; z[zOff + 3] = (num & 1); } public static void Sqrt(ReadOnlySpan<ulong> x, Span<ulong> z) { ulong even; ulong num = Interleave.Unshuffle(x[0], x[1], out even); ulong even2; ulong num2 = Interleave.Unshuffle(x[2], out even2); even2 ^= x[3] << 32; z[0] = (even ^ (num << 8)); z[1] = (even2 ^ (num2 << 8) ^ (num >> 56) ^ (num << 33)); z[2] = ((num2 >> 56) ^ (num2 << 33) ^ (num >> 31)); z[3] = num2 >> 31; } public unsafe static void Square(ReadOnlySpan<ulong> x, Span<ulong> z) { Span<ulong> span = new Span<ulong>(stackalloc byte[64], 8); ImplSquare(x, span); Reduce(span, z); } public unsafe static void SquareAddToExt(ReadOnlySpan<ulong> x, Span<ulong> zz) { Span<ulong> span = new Span<ulong>(stackalloc byte[64], 8); ImplSquare(x, span); AddExt(zz, span, zz); } public static void SquareExt(ReadOnlySpan<ulong> x, Span<ulong> zz) { ImplSquare(x, zz); } public unsafe static void SquareN(ReadOnlySpan<ulong> x, int n, Span<ulong> z) { Span<ulong> span = new Span<ulong>(stackalloc byte[64], 8); ImplSquare(x, span); Reduce(span, z); while (--n > 0) { ImplSquare(z, span); Reduce(span, z); } } public static uint Trace(ReadOnlySpan<ulong> x) { return (uint)((int)x[0] & 1); } private static void ImplCompactExt(Span<ulong> zz) { ulong num = zz[0]; ulong num2 = zz[1]; ulong num3 = zz[2]; ulong num4 = zz[3]; ulong num5 = zz[4]; ulong num6 = zz[5]; ulong num7 = zz[6]; ulong num8 = zz[7]; zz[0] = (num ^ (num2 << 49)); zz[1] = ((num2 >> 15) ^ (num3 << 34)); zz[2] = ((num3 >> 30) ^ (num4 << 19)); zz[3] = ((num4 >> 45) ^ (num5 << 4) ^ (num6 << 53)); zz[4] = ((num5 >> 60) ^ (num7 << 38) ^ (num6 >> 11)); zz[5] = ((num7 >> 26) ^ (num8 << 23)); zz[6] = num8 >> 41; zz[7] = 0; } private static void ImplExpand(ReadOnlySpan<ulong> x, Span<ulong> z) { ulong num = x[0]; ulong num2 = x[1]; ulong num3 = x[2]; ulong num4 = x[3]; z[0] = (num & 562949953421311); z[1] = (((num >> 49) ^ (num2 << 15)) & 562949953421311); z[2] = (((num2 >> 34) ^ (num3 << 30)) & 562949953421311); z[3] = ((num3 >> 19) ^ (num4 << 45)); } private unsafe static void ImplMultiply(ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> zz) { if (Org.BouncyCastle.Runtime.Intrinsics.X86.Pclmulqdq.IsEnabled) { Vector128<ulong> left = Vector128.Create(x[0], x[1]); Vector128<ulong> left2 = Vector128.CreateScalar(x[2]); Vector128<ulong> right = Vector128.Create(y[0], y[1]); Vector128<ulong> right2 = Vector128.CreateScalar(y[2]); Vector128<ulong> vector = System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left, right, 0); Vector128<ulong> vector2 = System.Runtime.Intrinsics.X86.Sse2.Xor(System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left, right, 1), System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left, right, 16)); Vector128<ulong> vector3 = System.Runtime.Intrinsics.X86.Sse2.Xor(System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left, right2, 0), System.Runtime.Intrinsics.X86.Sse2.Xor(System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left, right, 17), System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left2, right, 0))); Vector128<ulong> vector4 = System.Runtime.Intrinsics.X86.Sse2.Xor(System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left, right2, 1), System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left2, right, 16)); Vector128<ulong> vector5 = System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left2, right2, 0); ulong num = 0 - x[3]; ulong num2 = 0 - y[3]; zz[0] = vector.GetElement(0); zz[1] = (vector.GetElement(1) ^ vector2.GetElement(0)); zz[2] = (vector3.GetElement(0) ^ vector2.GetElement(1)); zz[3] = (vector3.GetElement(1) ^ vector4.GetElement(0) ^ (num & y[0]) ^ (x[0] & num2)); zz[4] = (vector5.GetElement(0) ^ vector4.GetElement(1) ^ (num & y[1]) ^ (x[1] & num2)); zz[5] = (vector5.GetElement(1) ^ (num & y[2]) ^ (x[2] & num2)); zz[6] = (num & y[3]); } else { ulong[] array = new ulong[4]; ulong[] array2 = new ulong[4]; ImplExpand(x, array); ImplExpand(y, array2); ulong[] array3 = new ulong[8]; ImplMulwAcc(array3, array[0], array2[0], zz.Slice(0, zz.Length)); ImplMulwAcc(array3, array[1], array2[1], zz.Slice(1, zz.Length - 1)); ImplMulwAcc(array3, array[2], array2[2], zz.Slice(2, zz.Length - 2)); ImplMulwAcc(array3, array[3], array2[3], zz.Slice(3, zz.Length - 3)); for (int num3 = 5; num3 > 0; num3--) { zz[num3] ^= zz[num3 - 1]; } ImplMulwAcc(array3, array[0] ^ array[1], array2[0] ^ array2[1], zz.Slice(1, zz.Length - 1)); ImplMulwAcc(array3, array[2] ^ array[3], array2[2] ^ array2[3], zz.Slice(3, zz.Length - 3)); for (int num4 = 7; num4 > 1; num4--) { zz[num4] ^= zz[num4 - 2]; } ulong num5 = array[0] ^ array[2]; ulong num6 = array[1] ^ array[3]; ulong num7 = array2[0] ^ array2[2]; ulong num8 = array2[1] ^ array2[3]; ImplMulwAcc(array3, num5 ^ num6, num7 ^ num8, zz.Slice(3, zz.Length - 3)); Span<ulong> span = new Span<ulong>(stackalloc byte[24], 3); ImplMulwAcc(array3, num5, num7, span.Slice(0, span.Length)); ImplMulwAcc(array3, num6, num8, span.Slice(1, span.Length - 1)); ulong num9 = span[0]; ulong num10 = span[1]; ulong num11 = span[2]; zz[2] ^= num9; zz[3] ^= (num9 ^ num10); zz[4] ^= (num11 ^ num10); zz[5] ^= num11; ImplCompactExt(zz); } } private static void ImplMulwAcc(Span<ulong> u, ulong x, ulong y, Span<ulong> z) { u[1] = y; u[2] = u[1] << 1; u[3] = (u[2] ^ y); u[4] = u[2] << 1; u[5] = (u[4] ^ y); u[6] = u[3] << 1; u[7] = (u[6] ^ y); uint num = (uint)x; ulong num2 = 0; ulong num3 = u[(int)(num & 7)] ^ (u[(int)((num >> 3) & 7)] << 3); int num4 = 36; do { num = (uint)(x >> num4); ulong num5 = u[(int)(num & 7)] ^ (u[(int)((num >> 3) & 7)] << 3) ^ (u[(int)((num >> 6) & 7)] << 6) ^ (u[(int)((num >> 9) & 7)] << 9) ^ (u[(int)((num >> 12) & 7)] << 12); num3 ^= num5 << num4; num2 ^= num5 >> -num4; } while ((num4 -= 15) > 0); z[0] ^= (num3 & 562949953421311); z[1] ^= ((num3 >> 49) ^ (num2 << 15)); } private static void ImplSquare(ReadOnlySpan<ulong> x, Span<ulong> zz) { zz[6] = (x[3] & 1); if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled) { zz[5] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x[2] >> 32, 6148914691236517205); zz[4] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x[2], 6148914691236517205); zz[3] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x[1] >> 32, 6148914691236517205); zz[2] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x[1], 6148914691236517205); zz[1] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x[0] >> 32, 6148914691236517205); zz[0] = System.Runtime.Intrinsics.X86.Bmi2.X64.ParallelBitDeposit(x[0], 6148914691236517205); } else Interleave.Expand64To128(x.Slice(0, 3), zz.Slice(0, 6)); } } }