]>
Commit | Line | Data |
---|---|---|
68d19b58 WL |
1 | /* |
2 | * RISC-V Crypto Emulation Helpers for QEMU. | |
3 | * | |
4 | * Copyright (c) 2021 Ruibo Lu, luruibo2000@163.com | |
5 | * Copyright (c) 2021 Zewen Ye, lustrew@foxmail.com | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms and conditions of the GNU General Public License, | |
9 | * version 2 or later, as published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
14 | * more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License along with | |
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #include "qemu/osdep.h" | |
21 | #include "cpu.h" | |
22 | #include "exec/exec-all.h" | |
23 | #include "exec/helper-proto.h" | |
24 | #include "crypto/aes.h" | |
25 | #include "crypto/sm4.h" | |
26 | ||
27 | #define AES_XTIME(a) \ | |
28 | ((a << 1) ^ ((a & 0x80) ? 0x1b : 0)) | |
29 | ||
30 | #define AES_GFMUL(a, b) (( \ | |
31 | (((b) & 0x1) ? (a) : 0) ^ \ | |
32 | (((b) & 0x2) ? AES_XTIME(a) : 0) ^ \ | |
33 | (((b) & 0x4) ? AES_XTIME(AES_XTIME(a)) : 0) ^ \ | |
34 | (((b) & 0x8) ? AES_XTIME(AES_XTIME(AES_XTIME(a))) : 0)) & 0xFF) | |
35 | ||
36 | static inline uint32_t aes_mixcolumn_byte(uint8_t x, bool fwd) | |
37 | { | |
38 | uint32_t u; | |
39 | ||
40 | if (fwd) { | |
41 | u = (AES_GFMUL(x, 3) << 24) | (x << 16) | (x << 8) | | |
42 | (AES_GFMUL(x, 2) << 0); | |
43 | } else { | |
44 | u = (AES_GFMUL(x, 0xb) << 24) | (AES_GFMUL(x, 0xd) << 16) | | |
45 | (AES_GFMUL(x, 0x9) << 8) | (AES_GFMUL(x, 0xe) << 0); | |
46 | } | |
47 | return u; | |
48 | } | |
49 | ||
50 | #define sext32_xlen(x) (target_ulong)(int32_t)(x) | |
51 | ||
52 | static inline target_ulong aes32_operation(target_ulong shamt, | |
53 | target_ulong rs1, target_ulong rs2, | |
54 | bool enc, bool mix) | |
55 | { | |
56 | uint8_t si = rs2 >> shamt; | |
57 | uint8_t so; | |
58 | uint32_t mixed; | |
59 | target_ulong res; | |
60 | ||
61 | if (enc) { | |
62 | so = AES_sbox[si]; | |
63 | if (mix) { | |
64 | mixed = aes_mixcolumn_byte(so, true); | |
65 | } else { | |
66 | mixed = so; | |
67 | } | |
68 | } else { | |
69 | so = AES_isbox[si]; | |
70 | if (mix) { | |
71 | mixed = aes_mixcolumn_byte(so, false); | |
72 | } else { | |
73 | mixed = so; | |
74 | } | |
75 | } | |
76 | mixed = rol32(mixed, shamt); | |
77 | res = rs1 ^ mixed; | |
78 | ||
79 | return sext32_xlen(res); | |
80 | } | |
81 | ||
82 | target_ulong HELPER(aes32esmi)(target_ulong rs1, target_ulong rs2, | |
83 | target_ulong shamt) | |
84 | { | |
85 | return aes32_operation(shamt, rs1, rs2, true, true); | |
86 | } | |
87 | ||
88 | target_ulong HELPER(aes32esi)(target_ulong rs1, target_ulong rs2, | |
89 | target_ulong shamt) | |
90 | { | |
91 | return aes32_operation(shamt, rs1, rs2, true, false); | |
92 | } | |
93 | ||
94 | target_ulong HELPER(aes32dsmi)(target_ulong rs1, target_ulong rs2, | |
95 | target_ulong shamt) | |
96 | { | |
97 | return aes32_operation(shamt, rs1, rs2, false, true); | |
98 | } | |
99 | ||
100 | target_ulong HELPER(aes32dsi)(target_ulong rs1, target_ulong rs2, | |
101 | target_ulong shamt) | |
102 | { | |
103 | return aes32_operation(shamt, rs1, rs2, false, false); | |
104 | } | |
9e33e175 WL |
105 | |
106 | #define BY(X, I) ((X >> (8 * I)) & 0xFF) | |
107 | ||
108 | #define AES_SHIFROWS_LO(RS1, RS2) ( \ | |
109 | (((RS1 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \ | |
110 | (((RS2 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \ | |
111 | (((RS2 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \ | |
112 | (((RS1 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0)) | |
113 | ||
114 | #define AES_INVSHIFROWS_LO(RS1, RS2) ( \ | |
115 | (((RS2 >> 24) & 0xFF) << 56) | (((RS2 >> 48) & 0xFF) << 48) | \ | |
116 | (((RS1 >> 8) & 0xFF) << 40) | (((RS1 >> 32) & 0xFF) << 32) | \ | |
117 | (((RS1 >> 56) & 0xFF) << 24) | (((RS2 >> 16) & 0xFF) << 16) | \ | |
118 | (((RS2 >> 40) & 0xFF) << 8) | (((RS1 >> 0) & 0xFF) << 0)) | |
119 | ||
120 | #define AES_MIXBYTE(COL, B0, B1, B2, B3) ( \ | |
121 | BY(COL, B3) ^ BY(COL, B2) ^ AES_GFMUL(BY(COL, B1), 3) ^ \ | |
122 | AES_GFMUL(BY(COL, B0), 2)) | |
123 | ||
124 | #define AES_MIXCOLUMN(COL) ( \ | |
125 | AES_MIXBYTE(COL, 3, 0, 1, 2) << 24 | \ | |
126 | AES_MIXBYTE(COL, 2, 3, 0, 1) << 16 | \ | |
127 | AES_MIXBYTE(COL, 1, 2, 3, 0) << 8 | AES_MIXBYTE(COL, 0, 1, 2, 3) << 0) | |
128 | ||
129 | #define AES_INVMIXBYTE(COL, B0, B1, B2, B3) ( \ | |
130 | AES_GFMUL(BY(COL, B3), 0x9) ^ AES_GFMUL(BY(COL, B2), 0xd) ^ \ | |
131 | AES_GFMUL(BY(COL, B1), 0xb) ^ AES_GFMUL(BY(COL, B0), 0xe)) | |
132 | ||
133 | #define AES_INVMIXCOLUMN(COL) ( \ | |
134 | AES_INVMIXBYTE(COL, 3, 0, 1, 2) << 24 | \ | |
135 | AES_INVMIXBYTE(COL, 2, 3, 0, 1) << 16 | \ | |
136 | AES_INVMIXBYTE(COL, 1, 2, 3, 0) << 8 | \ | |
137 | AES_INVMIXBYTE(COL, 0, 1, 2, 3) << 0) | |
138 | ||
139 | static inline target_ulong aes64_operation(target_ulong rs1, target_ulong rs2, | |
140 | bool enc, bool mix) | |
141 | { | |
142 | uint64_t RS1 = rs1; | |
143 | uint64_t RS2 = rs2; | |
144 | uint64_t result; | |
145 | uint64_t temp; | |
146 | uint32_t col_0; | |
147 | uint32_t col_1; | |
148 | ||
149 | if (enc) { | |
150 | temp = AES_SHIFROWS_LO(RS1, RS2); | |
151 | temp = (((uint64_t)AES_sbox[(temp >> 0) & 0xFF] << 0) | | |
152 | ((uint64_t)AES_sbox[(temp >> 8) & 0xFF] << 8) | | |
153 | ((uint64_t)AES_sbox[(temp >> 16) & 0xFF] << 16) | | |
154 | ((uint64_t)AES_sbox[(temp >> 24) & 0xFF] << 24) | | |
155 | ((uint64_t)AES_sbox[(temp >> 32) & 0xFF] << 32) | | |
156 | ((uint64_t)AES_sbox[(temp >> 40) & 0xFF] << 40) | | |
157 | ((uint64_t)AES_sbox[(temp >> 48) & 0xFF] << 48) | | |
158 | ((uint64_t)AES_sbox[(temp >> 56) & 0xFF] << 56)); | |
159 | if (mix) { | |
160 | col_0 = temp & 0xFFFFFFFF; | |
161 | col_1 = temp >> 32; | |
162 | ||
163 | col_0 = AES_MIXCOLUMN(col_0); | |
164 | col_1 = AES_MIXCOLUMN(col_1); | |
165 | ||
166 | result = ((uint64_t)col_1 << 32) | col_0; | |
167 | } else { | |
168 | result = temp; | |
169 | } | |
170 | } else { | |
171 | temp = AES_INVSHIFROWS_LO(RS1, RS2); | |
172 | temp = (((uint64_t)AES_isbox[(temp >> 0) & 0xFF] << 0) | | |
173 | ((uint64_t)AES_isbox[(temp >> 8) & 0xFF] << 8) | | |
174 | ((uint64_t)AES_isbox[(temp >> 16) & 0xFF] << 16) | | |
175 | ((uint64_t)AES_isbox[(temp >> 24) & 0xFF] << 24) | | |
176 | ((uint64_t)AES_isbox[(temp >> 32) & 0xFF] << 32) | | |
177 | ((uint64_t)AES_isbox[(temp >> 40) & 0xFF] << 40) | | |
178 | ((uint64_t)AES_isbox[(temp >> 48) & 0xFF] << 48) | | |
179 | ((uint64_t)AES_isbox[(temp >> 56) & 0xFF] << 56)); | |
180 | if (mix) { | |
181 | col_0 = temp & 0xFFFFFFFF; | |
182 | col_1 = temp >> 32; | |
183 | ||
184 | col_0 = AES_INVMIXCOLUMN(col_0); | |
185 | col_1 = AES_INVMIXCOLUMN(col_1); | |
186 | ||
187 | result = ((uint64_t)col_1 << 32) | col_0; | |
188 | } else { | |
189 | result = temp; | |
190 | } | |
191 | } | |
192 | ||
193 | return result; | |
194 | } | |
195 | ||
196 | target_ulong HELPER(aes64esm)(target_ulong rs1, target_ulong rs2) | |
197 | { | |
198 | return aes64_operation(rs1, rs2, true, true); | |
199 | } | |
200 | ||
201 | target_ulong HELPER(aes64es)(target_ulong rs1, target_ulong rs2) | |
202 | { | |
203 | return aes64_operation(rs1, rs2, true, false); | |
204 | } | |
205 | ||
206 | target_ulong HELPER(aes64ds)(target_ulong rs1, target_ulong rs2) | |
207 | { | |
208 | return aes64_operation(rs1, rs2, false, false); | |
209 | } | |
210 | ||
211 | target_ulong HELPER(aes64dsm)(target_ulong rs1, target_ulong rs2) | |
212 | { | |
213 | return aes64_operation(rs1, rs2, false, true); | |
214 | } | |
215 | ||
216 | target_ulong HELPER(aes64ks2)(target_ulong rs1, target_ulong rs2) | |
217 | { | |
218 | uint64_t RS1 = rs1; | |
219 | uint64_t RS2 = rs2; | |
220 | uint32_t rs1_hi = RS1 >> 32; | |
221 | uint32_t rs2_lo = RS2; | |
222 | uint32_t rs2_hi = RS2 >> 32; | |
223 | ||
224 | uint32_t r_lo = (rs1_hi ^ rs2_lo); | |
225 | uint32_t r_hi = (rs1_hi ^ rs2_lo ^ rs2_hi); | |
226 | target_ulong result = ((uint64_t)r_hi << 32) | r_lo; | |
227 | ||
228 | return result; | |
229 | } | |
230 | ||
231 | target_ulong HELPER(aes64ks1i)(target_ulong rs1, target_ulong rnum) | |
232 | { | |
233 | uint64_t RS1 = rs1; | |
234 | static const uint8_t round_consts[10] = { | |
235 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 | |
236 | }; | |
237 | ||
238 | uint8_t enc_rnum = rnum; | |
239 | uint32_t temp = (RS1 >> 32) & 0xFFFFFFFF; | |
240 | uint8_t rcon_ = 0; | |
241 | target_ulong result; | |
242 | ||
243 | if (enc_rnum != 0xA) { | |
244 | temp = ror32(temp, 8); /* Rotate right by 8 */ | |
245 | rcon_ = round_consts[enc_rnum]; | |
246 | } | |
247 | ||
248 | temp = ((uint32_t)AES_sbox[(temp >> 24) & 0xFF] << 24) | | |
249 | ((uint32_t)AES_sbox[(temp >> 16) & 0xFF] << 16) | | |
250 | ((uint32_t)AES_sbox[(temp >> 8) & 0xFF] << 8) | | |
251 | ((uint32_t)AES_sbox[(temp >> 0) & 0xFF] << 0); | |
252 | ||
253 | temp ^= rcon_; | |
254 | ||
255 | result = ((uint64_t)temp << 32) | temp; | |
256 | ||
257 | return result; | |
258 | } | |
259 | ||
260 | target_ulong HELPER(aes64im)(target_ulong rs1) | |
261 | { | |
262 | uint64_t RS1 = rs1; | |
263 | uint32_t col_0 = RS1 & 0xFFFFFFFF; | |
264 | uint32_t col_1 = RS1 >> 32; | |
265 | target_ulong result; | |
266 | ||
267 | col_0 = AES_INVMIXCOLUMN(col_0); | |
268 | col_1 = AES_INVMIXCOLUMN(col_1); | |
269 | ||
270 | result = ((uint64_t)col_1 << 32) | col_0; | |
271 | ||
272 | return result; | |
273 | } | |
0976083d WL |
274 | |
275 | target_ulong HELPER(sm4ed)(target_ulong rs1, target_ulong rs2, | |
276 | target_ulong shamt) | |
277 | { | |
278 | uint32_t sb_in = (uint8_t)(rs2 >> shamt); | |
279 | uint32_t sb_out = (uint32_t)sm4_sbox[sb_in]; | |
280 | ||
281 | uint32_t x = sb_out ^ (sb_out << 8) ^ (sb_out << 2) ^ (sb_out << 18) ^ | |
282 | ((sb_out & 0x3f) << 26) ^ ((sb_out & 0xC0) << 10); | |
283 | ||
284 | uint32_t rotl = rol32(x, shamt); | |
285 | ||
286 | return sext32_xlen(rotl ^ (uint32_t)rs1); | |
287 | } | |
288 | ||
289 | target_ulong HELPER(sm4ks)(target_ulong rs1, target_ulong rs2, | |
290 | target_ulong shamt) | |
291 | { | |
292 | uint32_t sb_in = (uint8_t)(rs2 >> shamt); | |
293 | uint32_t sb_out = sm4_sbox[sb_in]; | |
294 | ||
295 | uint32_t x = sb_out ^ ((sb_out & 0x07) << 29) ^ ((sb_out & 0xFE) << 7) ^ | |
296 | ((sb_out & 0x01) << 23) ^ ((sb_out & 0xF8) << 13); | |
297 | ||
298 | uint32_t rotl = rol32(x, shamt); | |
299 | ||
300 | return sext32_xlen(rotl ^ (uint32_t)rs1); | |
301 | } | |
68d19b58 | 302 | #undef sext32_xlen |