IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
CipherBlockChaining_x86.cs
Go to the documentation of this file.
1#if NETCOREAPP3_0_OR_GREATER
2
3using System;
5using System.Runtime.InteropServices;
6using System.Runtime.Intrinsics;
7using System.Runtime.Intrinsics.X86;
8
10{
11
15 [SkipLocalsInit]
16 static class CipherBlockChaining_x86
17 {
18
19 const int AESBlockSize = 16;
20
24 public static bool IsSupported => AESCrypt_x86.IsSupported;
25
37 [MethodImpl(MethodImplOptions.AggressiveInlining)]
38 public static int DecryptAESCrypt(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key, Span<byte> rvec, int length)
39 {
40 const int XMM_REG_NUM_KEY_FIRST = 2;
41 const int XMM_REG_NUM_KEY_LAST = 7;
42 const nuint FIRST_NON_REG_KEY_offset = 0x70;
43
44 var xmm_key_shuf_mask = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(AESCrypt_x86.KeyShuffleMask)).AsByte();
45
46 Span<Vector128<byte>> xmm_key = stackalloc Vector128<byte>[6];
47 ref Vector128<byte> xmm_key_first = ref MemoryMarshal.GetReference(xmm_key);
48
49 for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x10; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
50 {
51 xmm_key[as_XMMRegister(rnum)] = AESCrypt_x86.LoadKey(key, (nuint)offset, xmm_key_shuf_mask);
52 offset += 0x10;
53 }
54
55 ref byte prev_block_cipher_ptr = ref MemoryMarshal.GetReference(rvec);
56
57 if (key.Length != 44)
58 {
59 goto key_192_256;
60 }
61
62 nuint pos = 0;
63 singleBlock_loopTop_128:
64 if (length == 0)
65 {
66 goto exit;
67 }
68
69 var xmm_result = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from), pos);
70 xmm_result = Sse2.Xor(xmm_result, xmm_key_first);
71 for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
72 {
73 xmm_result = Aes.Decrypt(xmm_result, xmm_key[as_XMMRegister(rnum)]);
74 }
75
76 for (var key_offset = FIRST_NON_REG_KEY_offset; key_offset <= 0xa0; key_offset += 0x10)
77 {
78 xmm_result = AesDecKey(xmm_result, key, key_offset);
79 }
80
81 var xmm_temp = AESCrypt_x86.LoadKey(key, 0x00);
82 xmm_result = Aes.DecryptLast(xmm_result, xmm_temp);
83 xmm_temp = Vector128Util.LoadUnsafe(in prev_block_cipher_ptr);
84 xmm_result = Sse2.Xor(xmm_result, xmm_temp);
85 xmm_result.StoreUnsafe(ref MemoryMarshal.GetReference(to), pos);
86 prev_block_cipher_ptr = ref Unsafe.Add(ref MemoryMarshal.GetReference(from), pos);
87 pos += AESBlockSize;
88 length -= AESBlockSize;
89 goto singleBlock_loopTop_128;
90
91 exit:;
92 Unsafe.CopyBlockUnaligned(ref MemoryMarshal.GetReference(rvec), ref prev_block_cipher_ptr, 16);
93 return (int)pos;
94
95 key_192_256:;
96 if (key.Length != 52)
97 {
98 goto key_256;
99 }
100
101 pos = 0;
102 singleBlock_loopTop_192:;
103 xmm_result = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from), pos);
104 xmm_result = Sse2.Xor(xmm_result, xmm_key_first);
105 for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
106 {
107 xmm_result = Aes.Decrypt(xmm_result, xmm_key[as_XMMRegister(rnum)]);
108 }
109
110 for (var key_offset = FIRST_NON_REG_KEY_offset; key_offset <= 0xc0; key_offset += 0x10)
111 {
112 xmm_result = AesDecKey(xmm_result, key, key_offset);
113 }
114
115 xmm_temp = AESCrypt_x86.LoadKey(key, 0x00);
116 xmm_result = Aes.DecryptLast(xmm_result, xmm_temp);
117 xmm_temp = Vector128Util.LoadUnsafe(in prev_block_cipher_ptr);
118 xmm_result = Sse2.Xor(xmm_result, xmm_temp);
119 xmm_result.StoreUnsafe(ref MemoryMarshal.GetReference(to), pos);
120 prev_block_cipher_ptr = ref Unsafe.Add(ref MemoryMarshal.GetReference(from), pos); pos += AESBlockSize;
121 length -= AESBlockSize;
122 if (length != 0)
123 {
124 goto singleBlock_loopTop_192;
125 }
126
127 goto exit;
128
129 key_256:;
130 pos = 0;
131 singleBlock_loopTop_256:;
132 xmm_result = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from), pos);
133 xmm_result = Sse2.Xor(xmm_result, xmm_key_first);
134 for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
135 {
136 xmm_result = Aes.Decrypt(xmm_result, xmm_key[as_XMMRegister(rnum)]);
137 }
138
139 for (var key_offset = FIRST_NON_REG_KEY_offset; key_offset <= 0xe0; key_offset += 0x10)
140 {
141 xmm_result = AesDecKey(xmm_result, key, key_offset);
142 }
143
144 xmm_temp = AESCrypt_x86.LoadKey(key, 0x00);
145 xmm_result = Aes.DecryptLast(xmm_result, xmm_temp);
146 xmm_temp = Vector128Util.LoadUnsafe(in prev_block_cipher_ptr);
147 xmm_result = Sse2.Xor(xmm_result, xmm_temp);
148 xmm_result.StoreUnsafe(ref MemoryMarshal.GetReference(to), pos);
149 prev_block_cipher_ptr = ref Unsafe.Add(ref MemoryMarshal.GetReference(from), pos); pos += AESBlockSize;
150 length -= AESBlockSize;
151 if (length != 0)
152 {
153 goto singleBlock_loopTop_256;
154 }
155
156 goto exit;
157 }
158
170 [MethodImpl(MethodImplOptions.AggressiveInlining)]
171 public static int EncryptAESCrypt(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key, Span<byte> rvec, int length)
172 {
173 // ext\openjdk\hotspot\src\cpu\x86\vm\stubGenerator_x86_32.cpp:2410-2549
174 var xmm_key_shuf_mask = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(AESCrypt_x86.KeyShuffleMask)).AsByte();
175
176 const int XMM_REG_NUM_KEY_FIRST = 2;
177 const int XMM_REG_NUM_KEY_LAST = 7;
178
179 Span<Vector128<byte>> xmm_key = stackalloc Vector128<byte>[6];
180 ref Vector128<byte> xmm_key0 = ref MemoryMarshal.GetReference(xmm_key);
181 for (int rnum = XMM_REG_NUM_KEY_FIRST, offset = 0x00; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
182 {
183 xmm_key[as_XMMRegister(rnum)] = AESCrypt_x86.LoadKey(key, (nuint)offset, xmm_key_shuf_mask);
184 offset += 0x10;
185 }
186
187 var xmm_result = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(rvec));
188
189 if (key.Length != 44)
190 {
191 goto key_192_256;
192 }
193
194 nuint pos = 0;
195 loopTop_128:;
196 var xmm_temp = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from), pos);
197 xmm_result = Sse2.Xor(xmm_result, xmm_temp);
198 xmm_result = Sse2.Xor(xmm_result, xmm_key0);
199 for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
200 {
201 xmm_result = Aes.Encrypt(xmm_result, xmm_key[as_XMMRegister(rnum)]);
202 }
203
204 for (int key_offset = 0x60; key_offset <= 0x90; key_offset += 0x10)
205 {
206 xmm_result = AesEncKey(xmm_result, key, (nuint)key_offset);
207 }
208
209 xmm_temp = AESCrypt_x86.LoadKey(key, 0xa0);
210 xmm_result = Aes.EncryptLast(xmm_result, xmm_temp);
211 xmm_result.StoreUnsafe(ref MemoryMarshal.GetReference(to), pos);
212 pos += AESBlockSize;
213 length -= AESBlockSize;
214 if (length != 0)
215 {
216 goto loopTop_128;
217 }
218
219 exit:
220 xmm_result.StoreUnsafe(ref MemoryMarshal.GetReference(rvec));
221 return (int)pos;
222
223 key_192_256:;
224 if (key.Length != 52)
225 {
226 goto key_256;
227 }
228
229 pos = 0;
230 loopTop_192:;
231 xmm_temp = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from), pos);
232 xmm_result = Sse2.Xor(xmm_result, xmm_temp);
233 xmm_result = Sse2.Xor(xmm_result, xmm_key0);
234 for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
235 {
236 xmm_result = Aes.Encrypt(xmm_result, xmm_key[as_XMMRegister(rnum)]);
237 }
238
239 for (nuint key_offset = 0x60; key_offset <= 0xb0; key_offset += 0x10)
240 {
241 xmm_result = AesEncKey(xmm_result, key, key_offset);
242 }
243
244 xmm_temp = AESCrypt_x86.LoadKey(key, 0xc0);
245 xmm_result = Aes.EncryptLast(xmm_result, xmm_temp);
246 xmm_result.StoreUnsafe(ref MemoryMarshal.GetReference(to), pos);
247 pos += AESBlockSize;
248 length -= AESBlockSize;
249 if (length != 0)
250 {
251 goto loopTop_192;
252 }
253
254 goto exit;
255
256 key_256:;
257 pos = 0;
258 loopTop_256:
259 xmm_temp = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from), pos);
260 xmm_result = Sse2.Xor(xmm_result, xmm_temp);
261 xmm_result = Sse2.Xor(xmm_result, xmm_key0);
262 for (int rnum = XMM_REG_NUM_KEY_FIRST + 1; rnum <= XMM_REG_NUM_KEY_LAST; rnum++)
263 {
264 xmm_result = Aes.Encrypt(xmm_result, xmm_key[as_XMMRegister(rnum)]);
265 }
266
267 for (nuint key_offset = 0x60; key_offset <= 0xd0; key_offset += 0x10)
268 {
269 xmm_result = AesEncKey(xmm_result, key, key_offset);
270 }
271
272 xmm_temp = AESCrypt_x86.LoadKey(key, 0xe0);
273 xmm_result = Aes.EncryptLast(xmm_result, xmm_temp);
274 xmm_result.StoreUnsafe(ref MemoryMarshal.GetReference(to), pos);
275 pos += AESBlockSize;
276 length -= AESBlockSize;
277 if (length != 0)
278 {
279 goto loopTop_256;
280 }
281
282 goto exit;
283 }
284
285 static Vector128<byte> AesDecKey(Vector128<byte> xmmdst, ReadOnlySpan<int> key, nuint offset, Vector128<byte>? xmm_shuf_mask = null)
286 {
287 return Aes.Decrypt(xmmdst, AESCrypt_x86.LoadKey(key, offset, xmm_shuf_mask));
288 }
289
290 static Vector128<byte> AesEncKey(Vector128<byte> xmmdst, ReadOnlySpan<int> key, nuint offset, Vector128<byte>? xmm_shuf_mask = null)
291 {
292 return Aes.Encrypt(xmmdst, AESCrypt_x86.LoadKey(key, offset, xmm_shuf_mask));
293 }
294
295 static int as_XMMRegister(int @in) => @in - 2;
296
297 }
298
299}
300
301#endif