IKVM11  11
Java SE 11 Virtual Machine for .NET
Loading...
Searching...
No Matches
AESCrypt_Arm.cs
Go to the documentation of this file.
1#if NET6_0_OR_GREATER
2
3using System;
5using System.Runtime.InteropServices;
6using System.Runtime.Intrinsics;
7using System.Runtime.Intrinsics.Arm;
8
10{
14 [SkipLocalsInit]
15 static class AESCrypt_Arm
16 {
20 public static bool IsSupported => Aes.IsSupported && AdvSimd.IsSupported;
21
30 [MethodImpl(MethodImplOptions.AggressiveInlining)]
31 public static void DecryptBlock(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key)
32 {
33 //ext\openjdk\hotspot\src\cpu\aarch64\vm\stubGenerator_aarch64.cpp:2606-2699
34 var keylen = key.Length;
35
36 var v0 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from));
37
38 // ld1(…, __ post(key, X)):
39 // ld1(v1, v2, …) was added with .NET 9 (AdvSimd.Arm64.Load_xVector128)
40 // Unrolled the Load-loop manually for .NET 6+
41 // post post-increments the pointer, and returns the previous location.
42
43 var v5 = Vector128Util.LoadUnsafe(in RefUtils.Post(ref key, 16));
44 v5 = AdvSimd.ReverseElement8(v5);
45
46 var (v1, v2, v3, v4) = Vector128Util.Load4xUnsafe(in RefUtils.Post(ref key, 64));
47 v1 = AdvSimd.ReverseElement8(v1);
48 v2 = AdvSimd.ReverseElement8(v2);
49 v3 = AdvSimd.ReverseElement8(v3);
50 v4 = AdvSimd.ReverseElement8(v4);
51 v0 = Aes.Decrypt(v0, v1.AsByte());
52 v0 = Aes.InverseMixColumns(v0);
53 v0 = Aes.Decrypt(v0, v2.AsByte());
54 v0 = Aes.InverseMixColumns(v0);
55 v0 = Aes.Decrypt(v0, v3.AsByte());
56 v0 = Aes.InverseMixColumns(v0);
57 v0 = Aes.Decrypt(v0, v4.AsByte());
58 v0 = Aes.InverseMixColumns(v0);
59
60 (v1, v2, v3, v4) = Vector128Util.Load4xUnsafe(in RefUtils.Post(ref key, 64));
61 v1 = AdvSimd.ReverseElement8(v1);
62 v2 = AdvSimd.ReverseElement8(v2);
63 v3 = AdvSimd.ReverseElement8(v3);
64 v4 = AdvSimd.ReverseElement8(v4);
65 v0 = Aes.Decrypt(v0, v1.AsByte());
66 v0 = Aes.InverseMixColumns(v0);
67 v0 = Aes.Decrypt(v0, v2.AsByte());
68 v0 = Aes.InverseMixColumns(v0);
69 v0 = Aes.Decrypt(v0, v3.AsByte());
70 v0 = Aes.InverseMixColumns(v0);
71 v0 = Aes.Decrypt(v0, v4.AsByte());
72 v0 = Aes.InverseMixColumns(v0);
73
74 (v1, v2) = Vector128Util.Load2xUnsafe(in RefUtils.Post(ref key, 32));
75 v1 = AdvSimd.ReverseElement8(v1);
76 v2 = AdvSimd.ReverseElement8(v2);
77
78 if (keylen == 44)
79 {
80 goto doLast;
81 }
82
83 v0 = Aes.Decrypt(v0, v1.AsByte());
84 v0 = Aes.InverseMixColumns(v0);
85 v0 = Aes.Decrypt(v0, v2.AsByte());
86 v0 = Aes.InverseMixColumns(v0);
87
88 (v1, v2) = Vector128Util.Load2xUnsafe(in RefUtils.Post(ref key, 32));
89 v1 = AdvSimd.ReverseElement8(v1);
90 v2 = AdvSimd.ReverseElement8(v2);
91
92 if (keylen == 52)
93 {
94 goto doLast;
95 }
96
97 v0 = Aes.Decrypt(v0, v1.AsByte());
98 v0 = Aes.InverseMixColumns(v0);
99 v0 = Aes.Decrypt(v0, v2.AsByte());
100 v0 = Aes.InverseMixColumns(v0);
101
102 (v1, v2) = Vector128Util.Load2xUnsafe(in RefUtils.Post(ref key, 32));
103 v1 = AdvSimd.ReverseElement8(v1);
104 v2 = AdvSimd.ReverseElement8(v2);
105
106 doLast:;
107
108 v0 = Aes.Decrypt(v0, v1.AsByte());
109 v0 = Aes.InverseMixColumns(v0);
110 v0 = Aes.Decrypt(v0, v2.AsByte());
111
112 v0 = AdvSimd.Xor(v0, v5.AsByte());
113
114 v0.CopyTo(to);
115 }
116
125 [MethodImpl(MethodImplOptions.AggressiveInlining)]
126 public static void EncryptBlock(ReadOnlySpan<byte> from, Span<byte> to, ReadOnlySpan<int> key)
127 {
128 //ext\openjdk\hotspot\src\cpu\aarch64\vm\stubGenerator_aarch64.cpp:2505-2597
129 var keylen = key.Length;
130
131 var v0 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(from));
132
133 // ld1(…, __ post(key, X)):
134 // ld1(v1, v2, …) was added with .NET 9 (AdvSimd.Arm64.Load_xVector128)
135 // After benchmarking Load_xVector128 is still slower than Load4xUnsafe here.
136 // post post-increments the pointer, and returns the previous location.
137
138 var (v1, v2, v3, v4) = Vector128Util.Load4xUnsafe(in RefUtils.Post(ref key, 64));
139 v1 = AdvSimd.ReverseElement8(v1);
140 v2 = AdvSimd.ReverseElement8(v2);
141 v3 = AdvSimd.ReverseElement8(v3);
142 v4 = AdvSimd.ReverseElement8(v4);
143 v0 = Aes.Encrypt(v0, v1.AsByte());
144 v0 = Aes.MixColumns(v0);
145 v0 = Aes.Encrypt(v0, v2.AsByte());
146 v0 = Aes.MixColumns(v0);
147 v0 = Aes.Encrypt(v0, v3.AsByte());
148 v0 = Aes.MixColumns(v0);
149 v0 = Aes.Encrypt(v0, v4.AsByte());
150 v0 = Aes.MixColumns(v0);
151
152 (v1, v2, v3, v4) = Vector128Util.Load4xUnsafe(in RefUtils.Post(ref key, 64));
153 v1 = AdvSimd.ReverseElement8(v1);
154 v2 = AdvSimd.ReverseElement8(v2);
155 v3 = AdvSimd.ReverseElement8(v3);
156 v4 = AdvSimd.ReverseElement8(v4);
157 v0 = Aes.Encrypt(v0, v1.AsByte());
158 v0 = Aes.MixColumns(v0);
159 v0 = Aes.Encrypt(v0, v2.AsByte());
160 v0 = Aes.MixColumns(v0);
161 v0 = Aes.Encrypt(v0, v3.AsByte());
162 v0 = Aes.MixColumns(v0);
163 v0 = Aes.Encrypt(v0, v4.AsByte());
164 v0 = Aes.MixColumns(v0);
165
166 (v1, v2) = Vector128Util.Load2xUnsafe(in RefUtils.Post(ref key, 32));
167 v1 = AdvSimd.ReverseElement8(v1);
168 v2 = AdvSimd.ReverseElement8(v2);
169
170 if (keylen == 44)
171 {
172 goto doLast;
173 }
174
175 v0 = Aes.Encrypt(v0, v1.AsByte());
176 v0 = Aes.MixColumns(v0);
177 v0 = Aes.Encrypt(v0, v2.AsByte());
178 v0 = Aes.MixColumns(v0);
179
180 (v1, v2) = Vector128Util.Load2xUnsafe(in RefUtils.Post(ref key, 32));
181 v1 = AdvSimd.ReverseElement8(v1);
182 v2 = AdvSimd.ReverseElement8(v2);
183
184 if (keylen == 52)
185 {
186 goto doLast;
187 }
188
189 v0 = Aes.Encrypt(v0, v1.AsByte());
190 v0 = Aes.MixColumns(v0);
191 v0 = Aes.Encrypt(v0, v2.AsByte());
192 v0 = Aes.MixColumns(v0);
193
194 (v1, v2) = Vector128Util.Load2xUnsafe(in RefUtils.Post(ref key, 32));
195 v1 = AdvSimd.ReverseElement8(v1);
196 v2 = AdvSimd.ReverseElement8(v2);
197
198 doLast:;
199
200 v0 = Aes.Encrypt(v0, v1.AsByte());
201 v0 = Aes.MixColumns(v0);
202 v0 = Aes.Encrypt(v0, v2.AsByte());
203
204 v1 = Vector128Util.LoadUnsafe(in MemoryMarshal.GetReference(key));
205 v1 = AdvSimd.ReverseElement8(v1);
206 v0 = AdvSimd.Xor(v0, v1.AsByte());
207
208 v0.CopyTo(to);
209 }
210 }
211}
212
213#endif