Support the subfuctions PCKMO-Encrypt-AES-128-Key, PCKMO-Encrypt-AES-192-Key and PCKMO-Encrypt-AES-256-Key.
These subfunctions derive a protected key from an AES clear key by encrypting it with an internal AES wrapping key. More details can be found in the "z/Architecture Prinziples of Operation" document. Signed-off-by: Harald Freudenberger <[email protected]> Tested-by: Holger Dengler <[email protected]> Reviewed-by: Finn Callies <[email protected]> --- target/s390x/gen-features.c | 3 +++ target/s390x/tcg/cpacf.h | 4 +++ target/s390x/tcg/cpacf_aes.c | 45 ++++++++++++++++++++++++++++++++ target/s390x/tcg/crypto_helper.c | 21 +++++++++++++++ target/s390x/tcg/translate.c | 9 +++++-- 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index f9b1a40c7c..d3e69aaca6 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -934,6 +934,9 @@ static uint16_t qemu_MAX[] = { S390_FEAT_KMCTR_AES_256, S390_FEAT_PCC_XTS_AES_128, S390_FEAT_PCC_XTS_AES_256, + S390_FEAT_PCKMO_AES_128, + S390_FEAT_PCKMO_AES_192, + S390_FEAT_PCKMO_AES_256, }; /****** END FEATURE DEFS ******/ diff --git a/target/s390x/tcg/cpacf.h b/target/s390x/tcg/cpacf.h index df7f258443..7512c0ea4c 100644 --- a/target/s390x/tcg/cpacf.h +++ b/target/s390x/tcg/cpacf.h @@ -279,4 +279,8 @@ int cpacf_aes_xts(CPUS390XState *env, const int mmu_idx, uintptr_t ra, 0x0F, 0x0A, 0x0C, 0x0E, 0x0F, 0x0A, 0x0C, 0x0E, \ 0x0F, 0x0A, 0x0C, 0x0E, 0x0F, 0x0A, 0x0C, 0x0E } +/* from cpacf_aes.c */ +int cpacf_aes_pckmo(CPUS390XState *env, const int mmu_idx, uintptr_t ra, + uint64_t param_addr, uint8_t fc); + #endif /* S390X_CPACF_H */ diff --git a/target/s390x/tcg/cpacf_aes.c b/target/s390x/tcg/cpacf_aes.c index 6702006b66..37c616ca5c 100644 --- a/target/s390x/tcg/cpacf_aes.c +++ b/target/s390x/tcg/cpacf_aes.c @@ -500,3 +500,48 @@ static void decrypt_protkey(uint8_t *key, int keysize) key[i] ^= protkey_xor_pattern[i]; } } + +int cpacf_aes_pckmo(CPUS390XState *env, const int mmu_idx, uintptr_t ra, + uint64_t param_addr, uint8_t fc) +{ + const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx); + uint8_t key[32]; + int keysize, i; + uint64_t addr; + + switch (fc) { + case CPACF_PCKMO_ENC_AES_128_KEY: + keysize = 16; + break; + case CPACF_PCKMO_ENC_AES_192_KEY: + keysize = 24; + break; + case CPACF_PCKMO_ENC_AES_256_KEY: + keysize = 32; + break; + default: + g_assert_not_reached(); + } + + /* fetch key from param block */ + for (i = 0; i < keysize; i++) { + addr = wrap_address(env, param_addr + i); + key[i] = cpu_ldb_mmu(env, addr, oi, ra); + } + + /* 'derive' the protected key from the clear key */ + encrypt_clrkey(key, keysize); + + /* store the protected key into param block */ + for (i = 0; i < keysize; i++) { + addr = wrap_address(env, param_addr + i); + cpu_stb_mmu(env, addr, key[i], oi, ra); + } + /* followed by the fake wkvp */ + for (i = 0; i < sizeof(protkey_wkvp); i++) { + addr = wrap_address(env, param_addr + keysize + i); + cpu_stb_mmu(env, addr, protkey_wkvp[i], oi, ra); + } + + return 0; +} diff --git a/target/s390x/tcg/crypto_helper.c b/target/s390x/tcg/crypto_helper.c index 564f7fa243..08151e916f 100644 --- a/target/s390x/tcg/crypto_helper.c +++ b/target/s390x/tcg/crypto_helper.c @@ -192,6 +192,24 @@ static int cpacf_pcc(CPUS390XState *env, const int mmu_idx, uintptr_t ra, return rc; } +static int cpacf_pckmo(CPUS390XState *env, const int mmu_idx, uintptr_t ra, + uint8_t fc) +{ + int rc = 0; + + switch (fc) { + case CPACF_PCKMO_ENC_AES_128_KEY: + case CPACF_PCKMO_ENC_AES_192_KEY: + case CPACF_PCKMO_ENC_AES_256_KEY: + rc = cpacf_aes_pckmo(env, mmu_idx, ra, env->regs[1], fc); + break; + default: + tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra); + } + + return rc; +} + uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, uint32_t type) { @@ -251,6 +269,9 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, case S390_FEAT_TYPE_PCC: rc = cpacf_pcc(env, mmu_idx, ra, fc); break; + case S390_FEAT_TYPE_PCKMO: + rc = cpacf_pckmo(env, mmu_idx, ra, fc); + break; case S390_FEAT_TYPE_PPNO: rc = cpacf_ppno(env, mmu_idx, ra, r1, r2, r3, fc); break; diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index cef1b55149..d7a99e6c1e 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -2558,6 +2558,7 @@ static DisasJumpType op_msa(DisasContext *s, DisasOps *o) int r2 = have_field(s, r2) ? get_field(s, r2) : 0; int r3 = have_field(s, r3) ? get_field(s, r3) : 0; TCGv_i32 t_r1, t_r2, t_r3, type; + bool update_cc = true; switch (s->insn->data) { case S390_FEAT_TYPE_KMA: @@ -2589,8 +2590,10 @@ static DisasJumpType op_msa(DisasContext *s, DisasOps *o) gen_program_exception(s, PGM_SPECIFICATION); return DISAS_NORETURN; } - /* FALL THROUGH */ + break; case S390_FEAT_TYPE_PCKMO: + update_cc = false; + /* FALL THROUGH */ case S390_FEAT_TYPE_PCC: case S390_FEAT_TYPE_KDSA: break; @@ -2603,7 +2606,9 @@ static DisasJumpType op_msa(DisasContext *s, DisasOps *o) t_r3 = tcg_constant_i32(r3); type = tcg_constant_i32(s->insn->data); gen_helper_msa(cc_op, tcg_env, t_r1, t_r2, t_r3, type); - set_cc_static(s); + if (update_cc) { + set_cc_static(s); + } return DISAS_NEXT; } -- 2.43.0
