5using System.Runtime.InteropServices;
6using System.Runtime.Intrinsics;
7using System.Runtime.Intrinsics.Arm;
15 static class GHASH_Arm64
17 private static ReadOnlySpan<long> P => [0x87, 0x87];
22 public static bool IsSupported => BitConverter.IsLittleEndian && Aes.IsSupported && AdvSimd.Arm64.IsSupported;
33 [MethodImpl(MethodImplOptions.AggressiveInlining)]
34 public static void ProcessBlocks(Span<long> state, ReadOnlySpan<long> subH, ReadOnlySpan<byte> data,
int blocks)
37 var vzr = Vector128<byte>.Zero;
39 var v0 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(state));
40 var v1 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(subH));
41 v0 = AdvSimd.ReverseElement8(v0);
42 v0 = AdvSimd.Arm64.ReverseElementBits(v0.AsByte()).AsInt64();
43 v1 = AdvSimd.ReverseElement8(v1);
44 v1 = AdvSimd.Arm64.ReverseElementBits(v1.AsByte()).AsInt64();
46 var v26 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(P));
48 var v16 = AdvSimd.ExtractVector128(v1.AsByte(), v1.AsByte(), 0x08).AsInt64();
49 v16 = AdvSimd.Xor(v16, v1);
53 var v2 = Vector128Util.LoadUnsafe(in RefUtils.Post(
ref data, 0x10));
54 v2 = AdvSimd.Arm64.ReverseElementBits(v2);
55 v2 = AdvSimd.Xor(v0.AsByte(), v2);
57 (var v5, var v7) = GHashMultiply(v1, v2, v16);
58 v0 = GHashReduce(v5, v7, v26, vzr);
66 v1 = AdvSimd.ReverseElement8(v0);
67 v1 = AdvSimd.Arm64.ReverseElementBits(v1.AsByte()).AsInt64();
71 [MethodImpl(MethodImplOptions.AggressiveInlining)]
72 private static (Vector128<long> Lower, Vector128<long> Upper) GHashMultiply(Vector128<long> a, Vector128<byte> b, Vector128<long> a1_xor_a0)
75 var tmp1 = AdvSimd.ExtractVector128(b, b, 0x08);
76 var result_hi = Aes.PolynomialMultiplyWideningUpper(b.AsInt64(), a);
77 tmp1 = AdvSimd.Xor(tmp1, b);
78 var result_lo = Aes.PolynomialMultiplyWideningLower(b.GetLower().AsInt64(), a.GetLower());
79 var tmp2 = Aes.PolynomialMultiplyWideningLower(tmp1.GetLower().AsInt64(), a1_xor_a0.GetLower());
81 var tmp4 = AdvSimd.ExtractVector128(result_lo.AsByte(), result_hi.AsByte(), 0x08);
82 var tmp3 = AdvSimd.Xor(result_hi, result_lo);
83 tmp2 = AdvSimd.Xor(tmp2, tmp4.AsInt64());
84 tmp2 = AdvSimd.Xor(tmp2, tmp3);
86 result_hi = AdvSimd.Arm64.InsertSelectedScalar(result_hi, 0, tmp2, 1);
87 result_lo = AdvSimd.Arm64.InsertSelectedScalar(result_lo, 1, tmp2, 0);
89 return (result_lo, result_hi);
92 [MethodImpl(MethodImplOptions.AggressiveInlining)]
93 private static Vector128<long> GHashReduce(Vector128<long> lo, Vector128<long> hi, Vector128<long> p, Vector128<byte> z)
96 var t0 = Aes.PolynomialMultiplyWideningUpper(hi, p);
97 var t1 = AdvSimd.ExtractVector128(t0.AsByte(), z, 8);
98 hi = AdvSimd.Xor(hi, t1.AsInt64());
99 t1 = AdvSimd.ExtractVector128(z, t0.AsByte(), 8);
100 lo = AdvSimd.Xor(lo, t1.AsInt64());
101 t0 = Aes.PolynomialMultiplyWideningLower(hi.GetLower(), p.GetLower());
102 return AdvSimd.Xor(lo, t0);