Implement the AES key expansion instructions according to OSA (Oracle SPARC Architecture) 2011 sections 7.3 and 7.4.
4 operand form (7.3): - AES_KEXPAND1 3 operand form (7.4): - AES_KEXPAND0 - AES_KEXPAND2 As the AES round instructions, they are gated behind the crypto CPU feature and disabled for sparc32. 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 | 28 +++++++++++++++++ 4 files changed, 96 insertions(+) diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c index 87cc19b930..5d2940b825 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). @@ -83,3 +84,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 ((uint64_t)hi << 32) | lo; +} + +/* 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 e6f8d87866..8cb405c8bd 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 @@ -5435,6 +5437,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 + TCGv_i64 dst, src1, src2; + + if (!avail_CRYPTO(dc)) { + return false; + } + if (gen_trap_ifnofpu(dc)) { + return true; + } + + dst = tcg_temp_new_i64(); + src1 = gen_load_fpr_D(dc, a->rs1); + src2 = gen_load_fpr_D(dc, a->rs2); + gen_helper_aes_kexpand1(dst, src1, src2, tcg_constant_i32(a->imm)); + gen_store_fpr_D(dc, a->rd, dst); + return advance_pc(dc); + #else + return false; + #endif +} static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a) { -- 2.43.0
