Implement the AES key expansion instructions according to
OSA (Oracle SPARC Architecture) 2011 sections 7.3 and 7.4
and set the AES bit in the CFR.
4-operand form (7.3):
- AES_KEXPAND1
3-operand form (7.4):
- AES_KEXPAND0
- AES_KEXPAND2
Like the AES round instructions, they are gated behind the
crypto CPU feature and disabled for sparc32.
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Signed-off-by: Stian Halseth <[email protected]>
---
target/sparc/crypto_helper.c | 58 ++++++++++++++++++++++++++++++++++++
target/sparc/helper.h | 3 ++
target/sparc/insns.decode | 7 +++++
target/sparc/translate.c | 30 ++++++++++++++++++-
4 files changed, 97 insertions(+), 1 deletion(-)
diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c
index 7dd4dd5144..f04bd3569d 100644
--- a/target/sparc/crypto_helper.c
+++ b/target/sparc/crypto_helper.c
@@ -9,6 +9,7 @@
#include "qemu/osdep.h"
#include "exec/helper-proto.h"
#include "crypto/aes-round.h"
+#include "crypto/aes.h"
/*
* SPARC four-operand AES round (Section 7.3).
@@ -87,3 +88,60 @@ uint64_t helper_aes_dround23_l(uint64_t key, uint64_t s2,
uint64_t s3)
{
return aes_round(key, s2, s3, 1, true, true);
}
+
+/* Combine the transformed word with the two words in rs1. */
+static uint64_t aes_kexpand(uint64_t rs1, uint32_t t)
+{
+ uint32_t hi = (rs1 >> 32) ^ t;
+ uint32_t lo = (uint32_t)rs1 ^ hi;
+
+ return deposit64(lo, 32, 32, hi);
+}
+
+/* Apply the AES S-box to each byte, preserving byte positions. */
+static uint32_t aes_subword(uint32_t x)
+{
+ return ((uint32_t)AES_sbox[x >> 24] << 24) |
+ ((uint32_t)AES_sbox[(x >> 16) & 0xff] << 16) |
+ ((uint32_t)AES_sbox[(x >> 8) & 0xff] << 8) |
+ (uint32_t)AES_sbox[x & 0xff];
+}
+
+/*
+ * AES Cryptographic Operations 4-operand (Section 7.3)
+ * AES key expansion with RotWord, SubWord, and RCON.
+ */
+uint64_t helper_aes_kexpand1(uint64_t rs1, uint64_t rs2, uint32_t imm)
+{
+ static const uint8_t rcon[10] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10,
+ 0x20, 0x40, 0x80, 0x1b, 0x36,
+ };
+ uint32_t t = rol32((uint32_t)rs2, 8);
+
+ t = aes_subword(t);
+
+ if (imm < ARRAY_SIZE(rcon)) {
+ t ^= (uint32_t)rcon[imm] << 24;
+ }
+
+ return aes_kexpand(rs1, t);
+}
+
+/*
+ * AES Cryptographic Operations 3-operand (Section 7.4)
+ * AES key expansion with SubWord, without RotWord or RCON.
+ */
+uint64_t helper_aes_kexpand0(uint64_t rs1, uint64_t rs2)
+{
+ return aes_kexpand(rs1, aes_subword(rs2));
+}
+
+/*
+ * AES Cryptographic Operations 3-operand (Section 7.4)
+ * AES key expansion without SubWord, RotWord, or RCON.
+ */
+uint64_t helper_aes_kexpand2(uint64_t rs1, uint64_t rs2)
+{
+ return aes_kexpand(rs1, (uint32_t)rs2);
+}
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 9bfd643b09..685b89d9c5 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -130,6 +130,9 @@ DEF_HELPER_FLAGS_3(aes_eround01_l, TCG_CALL_NO_RWG_SE, i64,
i64, i64, i64)
DEF_HELPER_FLAGS_3(aes_eround23_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
DEF_HELPER_FLAGS_3(aes_dround01_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
DEF_HELPER_FLAGS_3(aes_dround23_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_2(aes_kexpand0, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_kexpand1, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
+DEF_HELPER_FLAGS_2(aes_kexpand2, TCG_CALL_NO_RWG_SE, i64, i64, i64)
#define VIS_CMPHELPER(name) \
DEF_HELPER_FLAGS_2(f##name##8, TCG_CALL_NO_RWG_SE, \
i64, i64, i64) \
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
index 99c9147e7d..96791c7658 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -86,6 +86,10 @@ CALL 01 i:s30
@d_d_d_d .. ..... ...... ..... ..... .... ..... \
&r_r_r_r rd=%dfp_rd rs1=%dfp_rs1 rs2=%dfp_rs2 rs3=%dfp_rs3
+&r_r_i_r rd rs1 imm rs2
+@d_d_i_d .. ..... ...... ..... imm:5 .... ..... \
+ &r_r_i_r rd=%dfp_rd rs1=%dfp_rs1 rs2=%dfp_rs2
+
{
[
STBAR_v9 10 00000 101000 01111 0 0000000000000
@@ -571,6 +575,8 @@ FCMPEq 10 000 cc:2 110101 ..... 0 0101 0111 ..... \
FPMAXU8 10 ..... 110110 ..... 1 0101 1101 ..... @d_d_d
FPMAXU16 10 ..... 110110 ..... 1 0101 1110 ..... @d_d_d
FPMAXU32 10 ..... 110110 ..... 1 0101 1111 ..... @d_d_d
+ AES_KEXPAND0 10 ..... 110110 ..... 1 0011 0000 ..... @d_d_d
+ AES_KEXPAND2 10 ..... 110110 ..... 1 0011 0001 ..... @d_d_d
FLCMPs 10 000 cc:2 110110 rs1:5 1 0101 0001 rs2:5
FLCMPd 10 000 cc:2 110110 ..... 1 0101 0010 ..... \
@@ -604,6 +610,7 @@ AES_EROUND01_L 10 ..... 011001 ..... ..... 0100 .....
@d_d_d_d
AES_EROUND23_L 10 ..... 011001 ..... ..... 0101 ..... @d_d_d_d
AES_DROUND01_L 10 ..... 011001 ..... ..... 0110 ..... @d_d_d_d
AES_DROUND23_L 10 ..... 011001 ..... ..... 0111 ..... @d_d_d_d
+AES_KEXPAND1 10 ..... 011001 ..... ..... 1000 ..... @d_d_i_d
##
## Major Opcode 11 -- load and store instructions
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 16907b1085..ad32b53cc3 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -109,6 +109,8 @@
# define gen_helper_aes_eround23_l ({ qemu_build_not_reached(); NULL; })
# define gen_helper_aes_dround01_l ({ qemu_build_not_reached(); NULL; })
# define gen_helper_aes_dround23_l ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_kexpand0 ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_kexpand2 ({ qemu_build_not_reached(); NULL; })
#endif
#define DISAS_EXIT DISAS_TARGET_0
@@ -3039,7 +3041,7 @@ TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd,
do_rdstrand_status)
static TCGv do_rdcfr(DisasContext *dc, TCGv dst)
{
- return tcg_constant_tl(0);
+ return tcg_constant_tl(CFR_AES);
}
TRANS(RDCFR, CRYPTO, do_rd_special, true, a->rd, do_rdcfr)
@@ -5434,6 +5436,32 @@ TRANS(AES_EROUND01_L, CRYPTO, do_dddd, a,
gen_helper_aes_eround01_l)
TRANS(AES_EROUND23_L, CRYPTO, do_dddd, a, gen_helper_aes_eround23_l)
TRANS(AES_DROUND01_L, CRYPTO, do_dddd, a, gen_helper_aes_dround01_l)
TRANS(AES_DROUND23_L, CRYPTO, do_dddd, a, gen_helper_aes_dround23_l)
+TRANS(AES_KEXPAND0, CRYPTO, do_ddd, a, gen_helper_aes_kexpand0)
+TRANS(AES_KEXPAND2, CRYPTO, do_ddd, a, gen_helper_aes_kexpand2)
+
+/* AES key expansion with RCON selected by the 5-bit immediate in imm */
+static bool trans_AES_KEXPAND1(DisasContext *dc, arg_r_r_i_r *a)
+{
+ #ifdef TARGET_SPARC64