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/aes-round.h" 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 } 106 107 static const AESState aes_zero = { }; 108 109 target_ulong HELPER(aes64esm)(target_ulong rs1, target_ulong rs2) 110 { 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]; 117 } 118 119 target_ulong HELPER(aes64es)(target_ulong rs1, target_ulong rs2) 120 { 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]; 127 } 128 129 target_ulong HELPER(aes64ds)(target_ulong rs1, target_ulong rs2) 130 { 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]; 137 } 138 139 target_ulong HELPER(aes64dsm)(target_ulong rs1, target_ulong rs2) 140 { 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]; 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 { 199 AESState t; 200 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]; 205 } 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 } 234 #undef sext32_xlen 235