From 85e6d710e4df840d673d19e81b37d97042fd6419 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 7 Mar 2018 08:56:16 -0500 Subject: [PATCH] target/arm: implement SM4 instructions This implements emulation of the new SM4 instructions that have been added as an optional extension to the ARMv8 Crypto Extensions in ARM v8.2. Backports commit b6577bcd251ca0d57ae1de149e3c706b38f21587 from qemu --- qemu/aarch64.h | 2 + qemu/aarch64eb.h | 2 + qemu/arm.h | 2 + qemu/armeb.h | 2 + qemu/header_gen.py | 2 + qemu/m68k.h | 2 + qemu/mips.h | 2 + qemu/mips64.h | 2 + qemu/mips64el.h | 2 + qemu/mipsel.h | 2 + qemu/powerpc.h | 2 + qemu/sparc.h | 2 + qemu/sparc64.h | 2 + qemu/target/arm/cpu.h | 1 + qemu/target/arm/crypto_helper.c | 103 ++++++++++++++++++++++++++++++++ qemu/target/arm/helper.h | 3 + qemu/target/arm/translate-a64.c | 8 +++ qemu/x86_64.h | 2 + 18 files changed, 143 insertions(+) diff --git a/qemu/aarch64.h b/qemu/aarch64.h index d72cd6c6..bc3daabc 100644 --- a/qemu/aarch64.h +++ b/qemu/aarch64.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_aarch64 #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_aarch64 #define helper_crypto_sm3tt helper_crypto_sm3tt_aarch64 +#define helper_crypto_sm4e helper_crypto_sm4e_aarch64 +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_aarch64 #define helper_dc_zva helper_dc_zva_aarch64 #define helper_div_i32 helper_div_i32_aarch64 #define helper_div_i64 helper_div_i64_aarch64 diff --git a/qemu/aarch64eb.h b/qemu/aarch64eb.h index e501720d..1708493a 100644 --- a/qemu/aarch64eb.h +++ b/qemu/aarch64eb.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_aarch64eb #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_aarch64eb #define helper_crypto_sm3tt helper_crypto_sm3tt_aarch64eb +#define helper_crypto_sm4e helper_crypto_sm4e_aarch64eb +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_aarch64eb #define helper_dc_zva helper_dc_zva_aarch64eb #define helper_div_i32 helper_div_i32_aarch64eb #define helper_div_i64 helper_div_i64_aarch64eb diff --git a/qemu/arm.h b/qemu/arm.h index 991dd10e..a0f1a3be 100644 --- a/qemu/arm.h +++ b/qemu/arm.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_arm #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_arm #define helper_crypto_sm3tt helper_crypto_sm3tt_arm +#define helper_crypto_sm4e helper_crypto_sm4e_arm +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_arm #define helper_dc_zva helper_dc_zva_arm #define helper_div_i32 helper_div_i32_arm #define helper_div_i64 helper_div_i64_arm diff --git a/qemu/armeb.h b/qemu/armeb.h index 399654fa..28709639 100644 --- a/qemu/armeb.h +++ b/qemu/armeb.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_armeb #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_armeb #define helper_crypto_sm3tt helper_crypto_sm3tt_armeb +#define helper_crypto_sm4e helper_crypto_sm4e_armeb +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_armeb #define helper_dc_zva helper_dc_zva_armeb #define helper_div_i32 helper_div_i32_armeb #define helper_div_i64 helper_div_i64_armeb diff --git a/qemu/header_gen.py b/qemu/header_gen.py index ad4437f0..ed65006b 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -1610,6 +1610,8 @@ symbols = ( 'helper_crypto_sm3partw1', 'helper_crypto_sm3partw2', 'helper_crypto_sm3tt', + 'helper_crypto_sm4e', + 'helper_crypto_sm4ekey', 'helper_dc_zva', 'helper_div_i32', 'helper_div_i64', diff --git a/qemu/m68k.h b/qemu/m68k.h index ae5895b5..a44e5967 100644 --- a/qemu/m68k.h +++ b/qemu/m68k.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_m68k #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_m68k #define helper_crypto_sm3tt helper_crypto_sm3tt_m68k +#define helper_crypto_sm4e helper_crypto_sm4e_m68k +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_m68k #define helper_dc_zva helper_dc_zva_m68k #define helper_div_i32 helper_div_i32_m68k #define helper_div_i64 helper_div_i64_m68k diff --git a/qemu/mips.h b/qemu/mips.h index a3f481fa..b8f2a70a 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_mips #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_mips #define helper_crypto_sm3tt helper_crypto_sm3tt_mips +#define helper_crypto_sm4e helper_crypto_sm4e_mips +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_mips #define helper_dc_zva helper_dc_zva_mips #define helper_div_i32 helper_div_i32_mips #define helper_div_i64 helper_div_i64_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 7a903589..e727e4ef 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_mips64 #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_mips64 #define helper_crypto_sm3tt helper_crypto_sm3tt_mips64 +#define helper_crypto_sm4e helper_crypto_sm4e_mips64 +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_mips64 #define helper_dc_zva helper_dc_zva_mips64 #define helper_div_i32 helper_div_i32_mips64 #define helper_div_i64 helper_div_i64_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index 8c8db03e..da3c5e7b 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_mips64el #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_mips64el #define helper_crypto_sm3tt helper_crypto_sm3tt_mips64el +#define helper_crypto_sm4e helper_crypto_sm4e_mips64el +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_mips64el #define helper_dc_zva helper_dc_zva_mips64el #define helper_div_i32 helper_div_i32_mips64el #define helper_div_i64 helper_div_i64_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 3729631d..f4529b54 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_mipsel #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_mipsel #define helper_crypto_sm3tt helper_crypto_sm3tt_mipsel +#define helper_crypto_sm4e helper_crypto_sm4e_mipsel +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_mipsel #define helper_dc_zva helper_dc_zva_mipsel #define helper_div_i32 helper_div_i32_mipsel #define helper_div_i64 helper_div_i64_mipsel diff --git a/qemu/powerpc.h b/qemu/powerpc.h index 87d98d92..99d39bf8 100644 --- a/qemu/powerpc.h +++ b/qemu/powerpc.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_powerpc #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_powerpc #define helper_crypto_sm3tt helper_crypto_sm3tt_powerpc +#define helper_crypto_sm4e helper_crypto_sm4e_powerpc +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_powerpc #define helper_dc_zva helper_dc_zva_powerpc #define helper_div_i32 helper_div_i32_powerpc #define helper_div_i64 helper_div_i64_powerpc diff --git a/qemu/sparc.h b/qemu/sparc.h index a1511c5d..8f619ccd 100644 --- a/qemu/sparc.h +++ b/qemu/sparc.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_sparc #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_sparc #define helper_crypto_sm3tt helper_crypto_sm3tt_sparc +#define helper_crypto_sm4e helper_crypto_sm4e_sparc +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_sparc #define helper_dc_zva helper_dc_zva_sparc #define helper_div_i32 helper_div_i32_sparc #define helper_div_i64 helper_div_i64_sparc diff --git a/qemu/sparc64.h b/qemu/sparc64.h index 53e084df..ecf31053 100644 --- a/qemu/sparc64.h +++ b/qemu/sparc64.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_sparc64 #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_sparc64 #define helper_crypto_sm3tt helper_crypto_sm3tt_sparc64 +#define helper_crypto_sm4e helper_crypto_sm4e_sparc64 +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_sparc64 #define helper_dc_zva helper_dc_zva_sparc64 #define helper_div_i32 helper_div_i32_sparc64 #define helper_div_i64 helper_div_i64_sparc64 diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 5a40209d..1b3baa32 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -1320,6 +1320,7 @@ enum arm_features { ARM_FEATURE_V8_SHA512, /* implements SHA512 part of v8 Crypto Extensions */ ARM_FEATURE_V8_SHA3, /* implements SHA3 part of v8 Crypto Extensions */ ARM_FEATURE_V8_SM3, /* implements SM3 part of v8 Crypto Extensions */ + ARM_FEATURE_V8_SM4, /* implements SM4 part of v8 Crypto Extensions */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/qemu/target/arm/crypto_helper.c b/qemu/target/arm/crypto_helper.c index 14c54acf..579ed25b 100644 --- a/qemu/target/arm/crypto_helper.c +++ b/qemu/target/arm/crypto_helper.c @@ -675,3 +675,106 @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2, rd[0] = d.l[0]; rd[1] = d.l[1]; } + +static uint8_t const sm4_sbox[] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48, +}; + +void HELPER(crypto_sm4e)(void *vd, void *vn) +{ + uint64_t *rd = vd; + uint64_t *rn = vn; + union CRYPTO_STATE d; + union CRYPTO_STATE n; + uint32_t t, i; + + d.l[0] = rd[0]; + d.l[1] = rd[1]; + + n.l[0] = rn[0]; + n.l[1] = rn[1]; + + for (i = 0; i < 4; i++) { + t = CR_ST_WORD(d, (i + 1) % 4) ^ + CR_ST_WORD(d, (i + 2) % 4) ^ + CR_ST_WORD(d, (i + 3) % 4) ^ + CR_ST_WORD(n, i); + + t = sm4_sbox[t & 0xff] | + sm4_sbox[(t >> 8) & 0xff] << 8 | + sm4_sbox[(t >> 16) & 0xff] << 16 | + sm4_sbox[(t >> 24) & 0xff] << 24; + + CR_ST_WORD(d, i) ^= t ^ rol32(t, 2) ^ rol32(t, 10) ^ rol32(t, 18) ^ + rol32(t, 24); + } + + rd[0] = d.l[0]; + rd[1] = d.l[1]; +} + +void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm) +{ + uint64_t *rd = vd; + uint64_t *rn = vn; + uint64_t *rm = vm; + union CRYPTO_STATE d; + union CRYPTO_STATE n; + union CRYPTO_STATE m; + uint32_t t, i; + + n.l[0] = rn[0]; + n.l[1] = rn[1]; + + m.l[0] = rm[0]; + m.l[1] = rm[1]; + + d = n; + for (i = 0; i < 4; i++) { + t = CR_ST_WORD(d, (i + 1) % 4) ^ + CR_ST_WORD(d, (i + 2) % 4) ^ + CR_ST_WORD(d, (i + 3) % 4) ^ + CR_ST_WORD(m, i); + + t = sm4_sbox[t & 0xff] | + sm4_sbox[(t >> 8) & 0xff] << 8 | + sm4_sbox[(t >> 16) & 0xff] << 16 | + sm4_sbox[(t >> 24) & 0xff] << 24; + + CR_ST_WORD(d, i) ^= t ^ rol32(t, 13) ^ rol32(t, 23); + } + + rd[0] = d.l[0]; + rd[1] = d.l[1]; +} diff --git a/qemu/target/arm/helper.h b/qemu/target/arm/helper.h index 6e318df9..b0bfc092 100644 --- a/qemu/target/arm/helper.h +++ b/qemu/target/arm/helper.h @@ -545,6 +545,9 @@ DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32) DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) +DEF_HELPER_FLAGS_2(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr) +DEF_HELPER_FLAGS_3(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr) + DEF_HELPER_FLAGS_3(crc32_arm, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_2(dc_zva, void, env, i64) diff --git a/qemu/target/arm/translate-a64.c b/qemu/target/arm/translate-a64.c index fce83a09..7f2d0538 100644 --- a/qemu/target/arm/translate-a64.c +++ b/qemu/target/arm/translate-a64.c @@ -11788,6 +11788,10 @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn) feature = ARM_FEATURE_V8_SM3; genfn = gen_helper_crypto_sm3partw2; break; + case 2: /* SM4EKEY */ + feature = ARM_FEATURE_V8_SM4; + genfn = gen_helper_crypto_sm4ekey; + break; default: unallocated_encoding(s); return; @@ -11862,6 +11866,10 @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn) feature = ARM_FEATURE_V8_SHA512; genfn = gen_helper_crypto_sha512su0; break; + case 1: /* SM4E */ + feature = ARM_FEATURE_V8_SM4; + genfn = gen_helper_crypto_sm4e; + break; default: unallocated_encoding(s); return; diff --git a/qemu/x86_64.h b/qemu/x86_64.h index 1c695cef..aa16eea6 100644 --- a/qemu/x86_64.h +++ b/qemu/x86_64.h @@ -1604,6 +1604,8 @@ #define helper_crypto_sm3partw1 helper_crypto_sm3partw1_x86_64 #define helper_crypto_sm3partw2 helper_crypto_sm3partw2_x86_64 #define helper_crypto_sm3tt helper_crypto_sm3tt_x86_64 +#define helper_crypto_sm4e helper_crypto_sm4e_x86_64 +#define helper_crypto_sm4ekey helper_crypto_sm4ekey_x86_64 #define helper_dc_zva helper_dc_zva_x86_64 #define helper_div_i32 helper_div_i32_x86_64 #define helper_div_i64 helper_div_i64_x86_64