1#if NETCOREAPP3_0_OR_GREATER
5using System.Runtime.InteropServices;
6using System.Runtime.Intrinsics;
7using System.Runtime.Intrinsics.X86;
16 static class AESCrypt_x86
22 public static bool IsSupported => Aes.IsSupported && Ssse3.IsSupported;
24 public static ReadOnlySpan<int> KeyShuffleMask => [0x00010203, 0x04050607, 0x08090a0b, 0x0c0d0e0f];
34 [MethodImpl(MethodImplOptions.AggressiveInlining)]
35 public static void DecryptBlock(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key)
38 Vector128<byte> xmm_temp1, xmm_temp2, xmm_temp3, xmm_temp4;
39 var xmm_key_shuf_mask = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask), 0).AsByte();
40 var xmm_result = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from));
42 xmm_temp1 = LoadKey(key, 0x10, xmm_key_shuf_mask);
43 xmm_temp2 = LoadKey(key, 0x20, xmm_key_shuf_mask);
44 xmm_temp3 = LoadKey(key, 0x30, xmm_key_shuf_mask);
45 xmm_temp4 = LoadKey(key, 0x40, xmm_key_shuf_mask);
47 xmm_result = Sse2.Xor(xmm_result, xmm_temp1);
48 xmm_result = Aes.Decrypt(xmm_result, xmm_temp2);
49 xmm_result = Aes.Decrypt(xmm_result, xmm_temp3);
50 xmm_result = Aes.Decrypt(xmm_result, xmm_temp4);
52 xmm_temp1 = LoadKey(key, 0x50, xmm_key_shuf_mask);
53 xmm_temp2 = LoadKey(key, 0x60, xmm_key_shuf_mask);
54 xmm_temp3 = LoadKey(key, 0x70, xmm_key_shuf_mask);
55 xmm_temp4 = LoadKey(key, 0x80, xmm_key_shuf_mask);
57 xmm_result = Aes.Decrypt(xmm_result, xmm_temp1);
58 xmm_result = Aes.Decrypt(xmm_result, xmm_temp2);
59 xmm_result = Aes.Decrypt(xmm_result, xmm_temp3);
60 xmm_result = Aes.Decrypt(xmm_result, xmm_temp4);
62 xmm_temp1 = LoadKey(key, 0x90, xmm_key_shuf_mask);
63 xmm_temp2 = LoadKey(key, 0xa0, xmm_key_shuf_mask);
64 xmm_temp3 = LoadKey(key, 0x00, xmm_key_shuf_mask);
71 xmm_result = Aes.Decrypt(xmm_result, xmm_temp1);
72 xmm_result = Aes.Decrypt(xmm_result, xmm_temp2);
74 xmm_temp1 = LoadKey(key, 0xb0, xmm_key_shuf_mask);
75 xmm_temp2 = LoadKey(key, 0xc0, xmm_key_shuf_mask);
82 xmm_result = Aes.Decrypt(xmm_result, xmm_temp1);
83 xmm_result = Aes.Decrypt(xmm_result, xmm_temp2);
85 xmm_temp1 = LoadKey(key, 0xd0, xmm_key_shuf_mask);
86 xmm_temp2 = LoadKey(key, 0xe0, xmm_key_shuf_mask);
89 xmm_result = Aes.Decrypt(xmm_result, xmm_temp1);
90 xmm_result = Aes.Decrypt(xmm_result, xmm_temp2);
91 xmm_result = Aes.DecryptLast(xmm_result, xmm_temp3);
92 xmm_result.CopyTo(to);
103 [MethodImpl(MethodImplOptions.AggressiveInlining)]
104 public static void EncryptBlock(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key)
107 Vector128<byte> xmm_temp1, xmm_temp2, xmm_temp3, xmm_temp4;
108 var xmm_key_shuf_mask = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask)).AsByte();
109 var xmm_result = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from));
111 xmm_temp1 = LoadKey(key, 0x00, xmm_key_shuf_mask);
112 xmm_result = Sse2.Xor(xmm_result, xmm_temp1);
114 xmm_temp1 = LoadKey(key, 0x10, xmm_key_shuf_mask);
115 xmm_temp2 = LoadKey(key, 0x20, xmm_key_shuf_mask);
116 xmm_temp3 = LoadKey(key, 0x30, xmm_key_shuf_mask);
117 xmm_temp4 = LoadKey(key, 0x40, xmm_key_shuf_mask);
119 xmm_result = Aes.Encrypt(xmm_result, xmm_temp1);
120 xmm_result = Aes.Encrypt(xmm_result, xmm_temp2);
121 xmm_result = Aes.Encrypt(xmm_result, xmm_temp3);
122 xmm_result = Aes.Encrypt(xmm_result, xmm_temp4);
124 xmm_temp1 = LoadKey(key, 0x50, xmm_key_shuf_mask);
125 xmm_temp2 = LoadKey(key, 0x60, xmm_key_shuf_mask);
126 xmm_temp3 = LoadKey(key, 0x70, xmm_key_shuf_mask);
127 xmm_temp4 = LoadKey(key, 0x80, xmm_key_shuf_mask);
129 xmm_result = Aes.Encrypt(xmm_result, xmm_temp1);
130 xmm_result = Aes.Encrypt(xmm_result, xmm_temp2);
131 xmm_result = Aes.Encrypt(xmm_result, xmm_temp3);
132 xmm_result = Aes.Encrypt(xmm_result, xmm_temp4);
134 xmm_temp1 = LoadKey(key, 0x90, xmm_key_shuf_mask);
135 xmm_temp2 = LoadKey(key, 0xa0, xmm_key_shuf_mask);
137 if (key.Length == 44)
142 xmm_result = Aes.Encrypt(xmm_result, xmm_temp1);
143 xmm_result = Aes.Encrypt(xmm_result, xmm_temp2);
145 xmm_temp1 = LoadKey(key, 0xb0, xmm_key_shuf_mask);
146 xmm_temp2 = LoadKey(key, 0xc0, xmm_key_shuf_mask);
148 if (key.Length == 52)
153 xmm_result = Aes.Encrypt(xmm_result, xmm_temp1);
154 xmm_result = Aes.Encrypt(xmm_result, xmm_temp2);
156 xmm_temp1 = LoadKey(key, 0xd0, xmm_key_shuf_mask);
157 xmm_temp2 = LoadKey(key, 0xe0, xmm_key_shuf_mask);
160 xmm_result = Aes.Encrypt(xmm_result, xmm_temp1);
161 xmm_result = Aes.EncryptLast(xmm_result, xmm_temp2);
162 xmm_result.CopyTo(to);
165 [MethodImpl(MethodImplOptions.AggressiveInlining)]
166 public static Vector128<byte> LoadKey(ReadOnlySpan<int> key, nuint offset, Vector128<byte>? shuffle_mask =
null)
168 var xmm_temp = Vector128Util.LoadUnsafe(in Unsafe.As<
int,
byte>(
ref MemoryMarshal.GetReference(key)), offset);
169 shuffle_mask ??= Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(KeyShuffleMask)).AsByte();
171 return Ssse3.Shuffle(xmm_temp, shuffle_mask.Value);