]>
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" | |
cad26538 | 25 | #include "crypto/aes-round.h" |
68d19b58 WL |
26 | #include "crypto/sm4.h" |
27 | ||
28 | #define AES_XTIME(a) \ | |
29 | ((a << 1) ^ ((a & 0x80) ? 0x1b : 0)) | |
30 | ||
31 | #define AES_GFMUL(a, b) (( \ | |
32 | (((b) & 0x1) ? (a) : 0) ^ \ | |
33 | (((b) & 0x2) ? AES_XTIME(a) : 0) ^ \ | |
34 | (((b) & 0x4) ? AES_XTIME(AES_XTIME(a)) : 0) ^ \ | |
35 | (((b) & 0x8) ? AES_XTIME(AES_XTIME(AES_XTIME(a))) : 0)) & 0xFF) | |
36 | ||
37 | static inline uint32_t aes_mixcolumn_byte(uint8_t x, bool fwd) | |
38 | { | |
39 | uint32_t u; | |
40 | ||
41 | if (fwd) { | |
42 | u = (AES_GFMUL(x, 3) << 24) | (x << 16) | (x << 8) | | |
43 | (AES_GFMUL(x, 2) << 0); | |
44 | } else { | |
45 | u = (AES_GFMUL(x, 0xb) << 24) | (AES_GFMUL(x, 0xd) << 16) | | |
46 | (AES_GFMUL(x, 0x9) << 8) | (AES_GFMUL(x, 0xe) << 0); | |
47 | } | |
48 | return u; | |
49 | } | |
50 | ||
51 | #define sext32_xlen(x) (target_ulong)(int32_t)(x) | |
52 | ||
53 | static inline target_ulong aes32_operation(target_ulong shamt, | |
54 | target_ulong rs1, target_ulong rs2, | |
55 | bool enc, bool mix) | |
56 | { | |
57 | uint8_t si = rs2 >> shamt; | |
58 | uint8_t so; | |
59 | uint32_t mixed; | |
60 | target_ulong res; | |
61 | ||
62 | if (enc) { | |
63 | so = AES_sbox[si]; | |
64 | if (mix) { | |
65 | mixed = aes_mixcolumn_byte(so, true); | |
66 | } else { | |
67 | mixed = so; | |
68 | } | |
69 | } else { | |
70 | so = AES_isbox[si]; | |
71 | if (mix) { | |
72 | mixed = aes_mixcolumn_byte(so, false); | |
73 | } else { | |
74 | mixed = so; | |
75 | } | |
76 | } | |
77 | mixed = rol32(mixed, shamt); | |
78 | res = rs1 ^ mixed; | |
79 | ||
80 | return sext32_xlen(res); | |
81 | } | |
82 | ||
83 | target_ulong HELPER(aes32esmi)(target_ulong rs1, target_ulong rs2, | |
84 | target_ulong shamt) | |
85 | { | |
86 | return aes32_operation(shamt, rs1, rs2, true, true); | |
87 | } | |
88 | ||
89 | target_ulong HELPER(aes32esi)(target_ulong rs1, target_ulong rs2, | |
90 | target_ulong shamt) | |
91 | { | |
92 | return aes32_operation(shamt, rs1, rs2, true, false); | |
93 | } | |
94 | ||
95 | target_ulong HELPER(aes32dsmi)(target_ulong rs1, target_ulong rs2, | |
96 | target_ulong shamt) | |
97 | { | |
98 | return aes32_operation(shamt, rs1, rs2, false, true); | |
99 | } | |
100 | ||
101 | target_ulong HELPER(aes32dsi)(target_ulong rs1, target_ulong rs2, | |
102 | target_ulong shamt) | |
103 | { | |
104 | return aes32_operation(shamt, rs1, rs2, false, false); | |
105 | } | |
9e33e175 | 106 | |
cad26538 RH |
107 | static const AESState aes_zero = { }; |
108 | ||
9e33e175 WL |
109 | target_ulong HELPER(aes64esm)(target_ulong rs1, target_ulong rs2) |
110 | { | |
274f3376 RH |
111 | AESState t; |
112 | ||
113 | t.d[HOST_BIG_ENDIAN] = rs1; | |
114 | t.d[!HOST_BIG_ENDIAN] = rs2; | |
115 | aesenc_SB_SR_MC_AK(&t, &t, &aes_zero, false); | |
116 | return t.d[HOST_BIG_ENDIAN]; | |
9e33e175 WL |
117 | } |
118 | ||
119 | target_ulong HELPER(aes64es)(target_ulong rs1, target_ulong rs2) | |
120 | { | |
cad26538 RH |
121 | AESState t; |
122 | ||
123 | t.d[HOST_BIG_ENDIAN] = rs1; | |
124 | t.d[!HOST_BIG_ENDIAN] = rs2; | |
125 | aesenc_SB_SR_AK(&t, &t, &aes_zero, false); | |
126 | return t.d[HOST_BIG_ENDIAN]; | |
9e33e175 WL |
127 | } |
128 | ||
129 | target_ulong HELPER(aes64ds)(target_ulong rs1, target_ulong rs2) | |
130 | { | |
7a70583a RH |
131 | AESState t; |
132 | ||
133 | t.d[HOST_BIG_ENDIAN] = rs1; | |
134 | t.d[!HOST_BIG_ENDIAN] = rs2; | |
135 | aesdec_ISB_ISR_AK(&t, &t, &aes_zero, false); | |
136 | return t.d[HOST_BIG_ENDIAN]; | |
9e33e175 WL |
137 | } |
138 | ||
139 | target_ulong HELPER(aes64dsm)(target_ulong rs1, target_ulong rs2) | |
140 | { | |
4ad6f9bf RH |
141 | AESState t, z = { }; |
142 | ||
143 | /* | |
144 | * This instruction does not include a round key, | |
145 | * so supply a zero to our primitive. | |
146 | */ | |
147 | t.d[HOST_BIG_ENDIAN] = rs1; | |
148 | t.d[!HOST_BIG_ENDIAN] = rs2; | |
149 | aesdec_ISB_ISR_IMC_AK(&t, &t, &z, false); | |
150 | return t.d[HOST_BIG_ENDIAN]; | |
9e33e175 WL |
151 | } |
152 | ||
153 | target_ulong HELPER(aes64ks2)(target_ulong rs1, target_ulong rs2) | |
154 | { | |
155 | uint64_t RS1 = rs1; | |
156 | uint64_t RS2 = rs2; | |
157 | uint32_t rs1_hi = RS1 >> 32; | |
158 | uint32_t rs2_lo = RS2; | |
159 | uint32_t rs2_hi = RS2 >> 32; | |
160 | ||
161 | uint32_t r_lo = (rs1_hi ^ rs2_lo); | |
162 | uint32_t r_hi = (rs1_hi ^ rs2_lo ^ rs2_hi); | |
163 | target_ulong result = ((uint64_t)r_hi << 32) | r_lo; | |
164 | ||
165 | return result; | |
166 | } | |
167 | ||
168 | target_ulong HELPER(aes64ks1i)(target_ulong rs1, target_ulong rnum) | |
169 | { | |
170 | uint64_t RS1 = rs1; | |
171 | static const uint8_t round_consts[10] = { | |
172 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 | |
173 | }; | |
174 | ||
175 | uint8_t enc_rnum = rnum; | |
176 | uint32_t temp = (RS1 >> 32) & 0xFFFFFFFF; | |
177 | uint8_t rcon_ = 0; | |
178 | target_ulong result; | |
179 | ||
180 | if (enc_rnum != 0xA) { | |
181 | temp = ror32(temp, 8); /* Rotate right by 8 */ | |
182 | rcon_ = round_consts[enc_rnum]; | |
183 | } | |
184 | ||
185 | temp = ((uint32_t)AES_sbox[(temp >> 24) & 0xFF] << 24) | | |
186 | ((uint32_t)AES_sbox[(temp >> 16) & 0xFF] << 16) | | |
187 | ((uint32_t)AES_sbox[(temp >> 8) & 0xFF] << 8) | | |
188 | ((uint32_t)AES_sbox[(temp >> 0) & 0xFF] << 0); | |
189 | ||
190 | temp ^= rcon_; | |
191 | ||
192 | result = ((uint64_t)temp << 32) | temp; | |
193 | ||
194 | return result; | |
195 | } | |
196 | ||
197 | target_ulong HELPER(aes64im)(target_ulong rs1) | |
198 | { | |
607a5f9d | 199 | AESState t; |
9e33e175 | 200 | |
607a5f9d RH |
201 | t.d[HOST_BIG_ENDIAN] = rs1; |
202 | t.d[!HOST_BIG_ENDIAN] = 0; | |
203 | aesdec_IMC(&t, &t, false); | |
204 | return t.d[HOST_BIG_ENDIAN]; | |
9e33e175 | 205 | } |
0976083d WL |
206 | |
207 | target_ulong HELPER(sm4ed)(target_ulong rs1, target_ulong rs2, | |
208 | target_ulong shamt) | |
209 | { | |
210 | uint32_t sb_in = (uint8_t)(rs2 >> shamt); | |
211 | uint32_t sb_out = (uint32_t)sm4_sbox[sb_in]; | |
212 | ||
213 | uint32_t x = sb_out ^ (sb_out << 8) ^ (sb_out << 2) ^ (sb_out << 18) ^ | |
214 | ((sb_out & 0x3f) << 26) ^ ((sb_out & 0xC0) << 10); | |
215 | ||
216 | uint32_t rotl = rol32(x, shamt); | |
217 | ||
218 | return sext32_xlen(rotl ^ (uint32_t)rs1); | |
219 | } | |
220 | ||
221 | target_ulong HELPER(sm4ks)(target_ulong rs1, target_ulong rs2, | |
222 | target_ulong shamt) | |
223 | { | |
224 | uint32_t sb_in = (uint8_t)(rs2 >> shamt); | |
225 | uint32_t sb_out = sm4_sbox[sb_in]; | |
226 | ||
227 | uint32_t x = sb_out ^ ((sb_out & 0x07) << 29) ^ ((sb_out & 0xFE) << 7) ^ | |
228 | ((sb_out & 0x01) << 23) ^ ((sb_out & 0xF8) << 13); | |
229 | ||
230 | uint32_t rotl = rol32(x, shamt); | |
231 | ||
232 | return sext32_xlen(rotl ^ (uint32_t)rs1); | |
233 | } | |
68d19b58 | 234 | #undef sext32_xlen |