]>
git.proxmox.com Git - mirror_qemu.git/blob - target/riscv/crypto_helper.c
2 * RISC-V Crypto Emulation Helpers for QEMU.
4 * Copyright (c) 2021 Ruibo Lu, luruibo2000@163.com
5 * Copyright (c) 2021 Zewen Ye, lustrew@foxmail.com
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.
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
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/>.
20 #include "qemu/osdep.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"
28 #define AES_XTIME(a) \
29 ((a << 1) ^ ((a & 0x80) ? 0x1b : 0))
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)
37 static inline uint32_t aes_mixcolumn_byte(uint8_t x
, bool fwd
)
42 u
= (AES_GFMUL(x
, 3) << 24) | (x
<< 16) | (x
<< 8) |
43 (AES_GFMUL(x
, 2) << 0);
45 u
= (AES_GFMUL(x
, 0xb) << 24) | (AES_GFMUL(x
, 0xd) << 16) |
46 (AES_GFMUL(x
, 0x9) << 8) | (AES_GFMUL(x
, 0xe) << 0);
51 #define sext32_xlen(x) (target_ulong)(int32_t)(x)
53 static inline target_ulong
aes32_operation(target_ulong shamt
,
54 target_ulong rs1
, target_ulong rs2
,
57 uint8_t si
= rs2
>> shamt
;
65 mixed
= aes_mixcolumn_byte(so
, true);
72 mixed
= aes_mixcolumn_byte(so
, false);
77 mixed
= rol32(mixed
, shamt
);
80 return sext32_xlen(res
);
83 target_ulong
HELPER(aes32esmi
)(target_ulong rs1
, target_ulong rs2
,
86 return aes32_operation(shamt
, rs1
, rs2
, true, true);
89 target_ulong
HELPER(aes32esi
)(target_ulong rs1
, target_ulong rs2
,
92 return aes32_operation(shamt
, rs1
, rs2
, true, false);
95 target_ulong
HELPER(aes32dsmi
)(target_ulong rs1
, target_ulong rs2
,
98 return aes32_operation(shamt
, rs1
, rs2
, false, true);
101 target_ulong
HELPER(aes32dsi
)(target_ulong rs1
, target_ulong rs2
,
104 return aes32_operation(shamt
, rs1
, rs2
, false, false);
107 static const AESState aes_zero
= { };
109 target_ulong
HELPER(aes64esm
)(target_ulong rs1
, target_ulong rs2
)
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
];
119 target_ulong
HELPER(aes64es
)(target_ulong rs1
, target_ulong rs2
)
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
];
129 target_ulong
HELPER(aes64ds
)(target_ulong rs1
, target_ulong rs2
)
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
];
139 target_ulong
HELPER(aes64dsm
)(target_ulong rs1
, target_ulong rs2
)
144 * This instruction does not include a round key,
145 * so supply a zero to our primitive.
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
];
153 target_ulong
HELPER(aes64ks2
)(target_ulong rs1
, target_ulong rs2
)
157 uint32_t rs1_hi
= RS1
>> 32;
158 uint32_t rs2_lo
= RS2
;
159 uint32_t rs2_hi
= RS2
>> 32;
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
;
168 target_ulong
HELPER(aes64ks1i
)(target_ulong rs1
, target_ulong rnum
)
171 static const uint8_t round_consts
[10] = {
172 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
175 uint8_t enc_rnum
= rnum
;
176 uint32_t temp
= (RS1
>> 32) & 0xFFFFFFFF;
180 if (enc_rnum
!= 0xA) {
181 temp
= ror32(temp
, 8); /* Rotate right by 8 */
182 rcon_
= round_consts
[enc_rnum
];
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);
192 result
= ((uint64_t)temp
<< 32) | temp
;
197 target_ulong
HELPER(aes64im
)(target_ulong rs1
)
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
];
207 target_ulong
HELPER(sm4ed
)(target_ulong rs1
, target_ulong rs2
,
210 uint32_t sb_in
= (uint8_t)(rs2
>> shamt
);
211 uint32_t sb_out
= (uint32_t)sm4_sbox
[sb_in
];
213 uint32_t x
= sb_out
^ (sb_out
<< 8) ^ (sb_out
<< 2) ^ (sb_out
<< 18) ^
214 ((sb_out
& 0x3f) << 26) ^ ((sb_out
& 0xC0) << 10);
216 uint32_t rotl
= rol32(x
, shamt
);
218 return sext32_xlen(rotl
^ (uint32_t)rs1
);
221 target_ulong
HELPER(sm4ks
)(target_ulong rs1
, target_ulong rs2
,
224 uint32_t sb_in
= (uint8_t)(rs2
>> shamt
);
225 uint32_t sb_out
= sm4_sbox
[sb_in
];
227 uint32_t x
= sb_out
^ ((sb_out
& 0x07) << 29) ^ ((sb_out
& 0xFE) << 7) ^
228 ((sb_out
& 0x01) << 23) ^ ((sb_out
& 0xF8) << 13);
230 uint32_t rotl
= rol32(x
, shamt
);
232 return sext32_xlen(rotl
^ (uint32_t)rs1
);