FastGcmBlockCipherHelper.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR) && BESTHTTP_WITH_BURST && (NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER)
  2. using System;
  3. using static Unity.Burst.Intrinsics.X86.Sse2;
  4. using static Unity.Burst.Intrinsics.Arm.Neon;
  5. using System.Runtime.CompilerServices;
  6. using Unity.Burst;
  7. // https://github.com/sschoener/burst-simd-exercises/blob/main/Assets/Examples/2-sum-small-numbers-sse3/SumSmallNumbers_SSE3.cs
  8. namespace Best.HTTP.Shared.TLS.Crypto.Impl
  9. {
  10. [BurstCompile]
  11. internal sealed unsafe class FastGcmBlockCipherHelper
  12. {
  13. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  14. public static unsafe void DecryptBlock(ReadOnlySpan<byte> input, Span<byte> output, Span<byte> ctrBlock, Span<byte> S, int BlockSize)
  15. {
  16. fixed (byte* pInput = input)
  17. fixed (byte* pOutput = output)
  18. fixed (byte* pctrBlock = ctrBlock)
  19. fixed (byte* pS = S) {
  20. DecryptBlock_Impl(pInput, input.Length, pOutput, output.Length, pctrBlock, pS, BlockSize);
  21. }
  22. }
  23. [BurstCompile(CompileSynchronously = true)]
  24. private unsafe static void DecryptBlock_Impl([NoAlias] byte* pinput, int inLen, [NoAlias] byte* poutput, int outLen, [NoAlias] byte* pctrBlock, [NoAlias] byte* pS, int BlockSize)
  25. {
  26. #if !UNITY_ANDROID && !UNITY_IOS
  27. if (IsSse2Supported)
  28. {
  29. var vInput = loadu_si128(pinput);
  30. var vCtrBlock = loadu_si128(pctrBlock);
  31. var vS = loadu_si128(pS);
  32. vS = xor_si128(vS, vInput);
  33. vCtrBlock = xor_si128(vInput, vCtrBlock);
  34. storeu_si128(pS, vS);
  35. storeu_si128(poutput, vCtrBlock);
  36. }
  37. else
  38. #endif
  39. if (IsNeonSupported)
  40. {
  41. var vInput = vld1q_u8(pinput);
  42. var vCtrBlock = vld1q_u8(pctrBlock);
  43. var vS = vld1q_u8(pS);
  44. vS = veorq_u8(vS, vInput);
  45. vCtrBlock = veorq_u8(vInput, vCtrBlock);
  46. vst1q_u8(pS, vS);
  47. vst1q_u8(poutput, vCtrBlock);
  48. }
  49. else
  50. {
  51. Unity.Burst.CompilerServices.Hint.Assume(BlockSize == 16);
  52. for (int i = 0; i < BlockSize; i += 4)
  53. {
  54. byte c0 = pinput[i + 0];
  55. byte c1 = pinput[i + 1];
  56. byte c2 = pinput[i + 2];
  57. byte c3 = pinput[i + 3];
  58. pS[i + 0] ^= c0;
  59. pS[i + 1] ^= c1;
  60. pS[i + 2] ^= c2;
  61. pS[i + 3] ^= c3;
  62. poutput[i + 0] = (byte)(c0 ^ pctrBlock[i + 0]);
  63. poutput[i + 1] = (byte)(c1 ^ pctrBlock[i + 1]);
  64. poutput[i + 2] = (byte)(c2 ^ pctrBlock[i + 2]);
  65. poutput[i + 3] = (byte)(c3 ^ pctrBlock[i + 3]);
  66. }
  67. }
  68. }
  69. }
  70. }
  71. #endif