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

SecT131Field

static class SecT131Field
using Org.BouncyCastle.Math.Raw; using Org.BouncyCastle.Runtime.Intrinsics; using Org.BouncyCastle.Runtime.Intrinsics.X86; using System; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; namespace Org.BouncyCastle.Math.EC.Custom.Sec { internal static class SecT131Field { private const ulong M03 = 7; private const ulong M44 = 17592186044415; private static readonly ulong[] ROOT_Z = new ulong[3] { 2791191049453778211, 2791191049453778402, 6 }; 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]); } 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]); } 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]); } public static void AddOne(ReadOnlySpan<ulong> x, Span<ulong> z) { z[0] = (x[0] ^ 1); z[1] = x[1]; z[2] = x[2]; } public static void AddTo(ReadOnlySpan<ulong> x, Span<ulong> z) { z[0] ^= x[0]; z[1] ^= x[1]; z[2] ^= x[2]; } public static ulong[] FromBigInteger(BigInteger x) { return Nat.FromBigInteger64(131, x); } public unsafe static void HalfTrace(ReadOnlySpan<ulong> x, Span<ulong> z) { Span<ulong> span = new Span<ulong>(stackalloc byte[40], 5); Nat192.Copy64(x, z); for (int i = 1; i < 131; 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 (Nat192.IsZero64(x)) throw new InvalidOperationException(); Span<ulong> span = new Span<ulong>(stackalloc byte[24], 3); Span<ulong> span2 = new Span<ulong>(stackalloc byte[24], 3); Square(x, span); Multiply(span, x, span); SquareN(span, 2, span2); Multiply(span2, span, span2); SquareN(span2, 4, span); Multiply(span, span2, span); SquareN(span, 8, span2); Multiply(span2, span, span2); SquareN(span2, 16, span); Multiply(span, span2, span); SquareN(span, 32, span2); Multiply(span2, span, span2); Square(span2, span2); Multiply(span2, x, span2); SquareN(span2, 65, span); Multiply(span, span2, span); Square(span, 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) { 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]; num2 ^= ((num5 << 61) ^ (num5 << 63)); num3 ^= ((num5 >> 3) ^ (num5 >> 1) ^ num5 ^ (num5 << 5)); num4 ^= num5 >> 59; num ^= ((num4 << 61) ^ (num4 << 63)); num2 ^= ((num4 >> 3) ^ (num4 >> 1) ^ num4 ^ (num4 << 5)); num3 ^= num4 >> 59; ulong num6 = num3 >> 3; z[0] = (num ^ num6 ^ (num6 << 2) ^ (num6 << 3) ^ (num6 << 8)); z[1] = (num2 ^ (num6 >> 56)); z[2] = (num3 & 7); } public static void Reduce61(ulong[] z, int zOff) { ulong num = z[zOff + 2]; ulong num2 = num >> 3; z[zOff] ^= (num2 ^ (num2 << 2) ^ (num2 << 3) ^ (num2 << 8)); z[zOff + 1] ^= num2 >> 56; z[zOff + 2] = (num & 7); } public unsafe static void Sqrt(ReadOnlySpan<ulong> x, Span<ulong> z) { Span<ulong> span = new Span<ulong>(stackalloc byte[24], 3); span[0] = Interleave.Unshuffle(x[0], x[1], out ulong even); span[1] = Interleave.Unshuffle(x[2], out ulong even2); Multiply(span, ROOT_Z, z); z[0] ^= even; z[1] ^= even2; } public unsafe static void Square(ReadOnlySpan<ulong> x, Span<ulong> z) { Span<ulong> span = new Span<ulong>(stackalloc byte[40], 5); 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[40], 5); 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[40], 5); 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] ^ (x[1] >> 59) ^ (x[2] >> 1)) & 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]; zz[0] = (num ^ (num2 << 44)); zz[1] = ((num2 >> 20) ^ (num3 << 24)); zz[2] = ((num3 >> 40) ^ (num4 << 4) ^ (num5 << 48)); zz[3] = ((num4 >> 60) ^ (num6 << 28) ^ (num5 >> 16)); zz[4] = num6 >> 36; zz[5] = 0; } private static void ImplMultiply(ReadOnlySpan<ulong> x, ReadOnlySpan<ulong> y, Span<ulong> zz) { if (Org.BouncyCastle.Runtime.Intrinsics.X86.Pclmulqdq.IsEnabled && Vector.IsPackedLittleEndian) { 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> value = System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left, right, 0); Vector128<ulong> value2 = 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> value3 = 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> value4 = 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> left3 = System.Runtime.Intrinsics.X86.Pclmulqdq.CarrylessMultiply(left2, right2, 0); value = System.Runtime.Intrinsics.X86.Sse2.Xor(value, System.Runtime.Intrinsics.X86.Sse2.ShiftLeftLogical128BitLane(value2, 8)); value3 = System.Runtime.Intrinsics.X86.Sse2.Xor(value3, System.Runtime.Intrinsics.X86.Sse2.ShiftRightLogical128BitLane(value2, 8)); value3 = System.Runtime.Intrinsics.X86.Sse2.Xor(value3, System.Runtime.Intrinsics.X86.Sse2.ShiftLeftLogical128BitLane(value4, 8)); left3 = System.Runtime.Intrinsics.X86.Sse2.Xor(left3, System.Runtime.Intrinsics.X86.Sse2.ShiftRightLogical128BitLane(value4, 8)); Span<byte> span = MemoryMarshal.AsBytes(zz); MemoryMarshal.Write(span.Slice(0, 16), ref value); MemoryMarshal.Write(span.Slice(16, 16), ref value3); zz[4] = left3.ToScalar(); } else { ulong num = x[0]; ulong num2 = x[1]; ulong num3 = x[2]; num3 = (((num2 >> 24) ^ (num3 << 40)) & 17592186044415); num2 = (((num >> 44) ^ (num2 << 20)) & 17592186044415); num &= 17592186044415; ulong num4 = y[0]; ulong num5 = y[1]; ulong num6 = y[2]; num6 = (((num5 >> 24) ^ (num6 << 40)) & 17592186044415); num5 = (((num4 >> 44) ^ (num5 << 20)) & 17592186044415); num4 &= 17592186044415; Span<ulong> u = zz; Span<ulong> span2 = new ulong[10]; ImplMulw(u, num, num4, span2.Slice(0, span2.Length)); ImplMulw(u, num3, num6, span2.Slice(2, span2.Length - 2)); ulong num7 = num ^ num2 ^ num3; ulong num8 = num4 ^ num5 ^ num6; ImplMulw(u, num7, num8, span2.Slice(4, span2.Length - 4)); ulong num9 = (num2 << 1) ^ (num3 << 2); ulong num10 = (num5 << 1) ^ (num6 << 2); ImplMulw(u, num ^ num9, num4 ^ num10, span2.Slice(6, span2.Length - 6)); ImplMulw(u, num7 ^ num9, num8 ^ num10, span2.Slice(8, span2.Length - 8)); ulong num11 = span2[6] ^ span2[8]; ulong num12 = span2[7] ^ span2[9]; ulong num13 = (num11 << 1) ^ span2[6]; ulong num14 = num11 ^ (num12 << 1) ^ span2[7]; ulong num15 = num12; ulong num16 = span2[0]; ulong num17 = span2[1] ^ span2[0] ^ span2[4]; ulong num18 = span2[1] ^ span2[5]; ulong num19 = num16 ^ num13 ^ (span2[2] << 4) ^ (span2[2] << 1); ulong num20 = num17 ^ num14 ^ (span2[3] << 4) ^ (span2[3] << 1); ulong num21 = num18 ^ num15; num20 ^= num19 >> 44; num19 &= 17592186044415; num21 ^= num20 >> 44; num20 &= 17592186044415; num19 = ((num19 >> 1) ^ ((num20 & 1) << 43)); num20 = ((num20 >> 1) ^ ((num21 & 1) << 43)); num21 >>= 1; num19 ^= num19 << 1; num19 ^= num19 << 2; num19 ^= num19 << 4; num19 ^= num19 << 8; num19 ^= num19 << 16; num19 ^= num19 << 32; num19 &= 17592186044415; num20 ^= num19 >> 43; num20 ^= num20 << 1; num20 ^= num20 << 2; num20 ^= num20 << 4; num20 ^= num20 << 8; num20 ^= num20 << 16; num20 ^= num20 << 32; num20 &= 17592186044415; num21 ^= num20 >> 43; num21 ^= num21 << 1; num21 ^= num21 << 2; num21 ^= num21 << 4; num21 ^= num21 << 8; num21 ^= num21 << 16; num21 ^= num21 << 32; zz[0] = num16; zz[1] = (num17 ^ num19 ^ span2[2]); zz[2] = (num18 ^ num20 ^ num19 ^ span2[3]); zz[3] = (num21 ^ num20); zz[4] = (num21 ^ span2[2]); zz[5] = span2[3]; ImplCompactExt(zz); } } private static void ImplMulw(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) ^ (u[(int)((num >> 6) & 7)] << 6) ^ (u[(int)((num >> 9) & 7)] << 9) ^ (u[(int)((num >> 12) & 7)] << 12); int num4 = 30; 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 & 17592186044415); z[1] ^= ((num3 >> 44) ^ (num2 << 20)); } private static void ImplSquare(ReadOnlySpan<ulong> x, Span<ulong> zz) { zz[4] = Interleave.Expand8to16((byte)x[2]); if (Org.BouncyCastle.Runtime.Intrinsics.X86.Bmi2.X64.IsEnabled) { 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, 2), zz.Slice(0, 4)); } } }