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 sext32_xlen(x) (target_ulong)(int32_t)(x)
30 static inline target_ulong
aes32_operation(target_ulong shamt
,
31 target_ulong rs1
, target_ulong rs2
,
34 uint8_t si
= rs2
>> shamt
;
40 mixed
= be32_to_cpu(AES_Te0
[si
]);
46 mixed
= be32_to_cpu(AES_Td0
[si
]);
48 mixed
= AES_isbox
[si
];
51 mixed
= rol32(mixed
, shamt
);
54 return sext32_xlen(res
);
57 target_ulong
HELPER(aes32esmi
)(target_ulong rs1
, target_ulong rs2
,
60 return aes32_operation(shamt
, rs1
, rs2
, true, true);
63 target_ulong
HELPER(aes32esi
)(target_ulong rs1
, target_ulong rs2
,
66 return aes32_operation(shamt
, rs1
, rs2
, true, false);
69 target_ulong
HELPER(aes32dsmi
)(target_ulong rs1
, target_ulong rs2
,
72 return aes32_operation(shamt
, rs1
, rs2
, false, true);
75 target_ulong
HELPER(aes32dsi
)(target_ulong rs1
, target_ulong rs2
,
78 return aes32_operation(shamt
, rs1
, rs2
, false, false);
81 static const AESState aes_zero
= { };
83 target_ulong
HELPER(aes64esm
)(target_ulong rs1
, target_ulong rs2
)
87 t
.d
[HOST_BIG_ENDIAN
] = rs1
;
88 t
.d
[!HOST_BIG_ENDIAN
] = rs2
;
89 aesenc_SB_SR_MC_AK(&t
, &t
, &aes_zero
, false);
90 return t
.d
[HOST_BIG_ENDIAN
];
93 target_ulong
HELPER(aes64es
)(target_ulong rs1
, target_ulong rs2
)
97 t
.d
[HOST_BIG_ENDIAN
] = rs1
;
98 t
.d
[!HOST_BIG_ENDIAN
] = rs2
;
99 aesenc_SB_SR_AK(&t
, &t
, &aes_zero
, false);
100 return t
.d
[HOST_BIG_ENDIAN
];
103 target_ulong
HELPER(aes64ds
)(target_ulong rs1
, target_ulong rs2
)
107 t
.d
[HOST_BIG_ENDIAN
] = rs1
;
108 t
.d
[!HOST_BIG_ENDIAN
] = rs2
;
109 aesdec_ISB_ISR_AK(&t
, &t
, &aes_zero
, false);
110 return t
.d
[HOST_BIG_ENDIAN
];
113 target_ulong
HELPER(aes64dsm
)(target_ulong rs1
, target_ulong rs2
)
118 * This instruction does not include a round key,
119 * so supply a zero to our primitive.
121 t
.d
[HOST_BIG_ENDIAN
] = rs1
;
122 t
.d
[!HOST_BIG_ENDIAN
] = rs2
;
123 aesdec_ISB_ISR_IMC_AK(&t
, &t
, &z
, false);
124 return t
.d
[HOST_BIG_ENDIAN
];
127 target_ulong
HELPER(aes64ks2
)(target_ulong rs1
, target_ulong rs2
)
131 uint32_t rs1_hi
= RS1
>> 32;
132 uint32_t rs2_lo
= RS2
;
133 uint32_t rs2_hi
= RS2
>> 32;
135 uint32_t r_lo
= (rs1_hi
^ rs2_lo
);
136 uint32_t r_hi
= (rs1_hi
^ rs2_lo
^ rs2_hi
);
137 target_ulong result
= ((uint64_t)r_hi
<< 32) | r_lo
;
142 target_ulong
HELPER(aes64ks1i
)(target_ulong rs1
, target_ulong rnum
)
145 static const uint8_t round_consts
[10] = {
146 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36
149 uint8_t enc_rnum
= rnum
;
150 uint32_t temp
= (RS1
>> 32) & 0xFFFFFFFF;
153 if (enc_rnum
!= 0xA) {
154 temp
= ror32(temp
, 8); /* Rotate right by 8 */
155 rc
.w
[0] = rc
.w
[1] = round_consts
[enc_rnum
];
158 t
.w
[0] = t
.w
[1] = t
.w
[2] = t
.w
[3] = temp
;
159 aesenc_SB_SR_AK(&t
, &t
, &rc
, false);
164 target_ulong
HELPER(aes64im
)(target_ulong rs1
)
168 t
.d
[HOST_BIG_ENDIAN
] = rs1
;
169 t
.d
[!HOST_BIG_ENDIAN
] = 0;
170 aesdec_IMC(&t
, &t
, false);
171 return t
.d
[HOST_BIG_ENDIAN
];
174 target_ulong
HELPER(sm4ed
)(target_ulong rs1
, target_ulong rs2
,
177 uint32_t sb_in
= (uint8_t)(rs2
>> shamt
);
178 uint32_t sb_out
= (uint32_t)sm4_sbox
[sb_in
];
180 uint32_t x
= sb_out
^ (sb_out
<< 8) ^ (sb_out
<< 2) ^ (sb_out
<< 18) ^
181 ((sb_out
& 0x3f) << 26) ^ ((sb_out
& 0xC0) << 10);
183 uint32_t rotl
= rol32(x
, shamt
);
185 return sext32_xlen(rotl
^ (uint32_t)rs1
);
188 target_ulong
HELPER(sm4ks
)(target_ulong rs1
, target_ulong rs2
,
191 uint32_t sb_in
= (uint8_t)(rs2
>> shamt
);
192 uint32_t sb_out
= sm4_sbox
[sb_in
];
194 uint32_t x
= sb_out
^ ((sb_out
& 0x07) << 29) ^ ((sb_out
& 0xFE) << 7) ^
195 ((sb_out
& 0x01) << 23) ^ ((sb_out
& 0xF8) << 13);
197 uint32_t rotl
= rol32(x
, shamt
);
199 return sext32_xlen(rotl
^ (uint32_t)rs1
);