mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
target/mips: add Octeon AES COP2 helpers
Add helper support for the Octeon AES operation selectors. Direct register-transfer selectors do not need helpers; the ECB/CBC encrypt and decrypt operations consume the AES input, key, IV, and key-length state. AESRESINP is modeled as one architectural register bank; operation helpers consume the current AESRESINP block and write the result back to the same bank. Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-8-daef7a0d8b04@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
This commit is contained in:
committed by
Philippe Mathieu-Daudé
parent
e3ba2fd89c
commit
9bf93903f7
@@ -52,6 +52,10 @@ DEF_HELPER_2(octeon_cp2_mt_zuc_start, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_zuc_more, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_snow3g_start, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_snow3g_more, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_aes_enc_cbc1, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_aes_enc1, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_aes_dec_cbc1, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_aes_dec1, void, env, i64)
|
||||
|
||||
/* microMIPS functions */
|
||||
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
|
||||
|
||||
@@ -840,6 +840,151 @@ static void octeon_snow3g_more(MIPSOcteonCryptoState *crypto)
|
||||
octeon_snow3g_queue_result(crypto);
|
||||
}
|
||||
|
||||
static int octeon_aes_key_bits(const MIPSOcteonCryptoState *crypto)
|
||||
{
|
||||
enum {
|
||||
OCTEON_AES_KEYLEN_128 = 1,
|
||||
OCTEON_AES_KEYLEN_192 = 2,
|
||||
OCTEON_AES_KEYLEN_256 = 3,
|
||||
};
|
||||
|
||||
switch (crypto->aes_keylen) {
|
||||
case OCTEON_AES_KEYLEN_128:
|
||||
return 128;
|
||||
case OCTEON_AES_KEYLEN_192:
|
||||
return 192;
|
||||
case OCTEON_AES_KEYLEN_256:
|
||||
return 256;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void octeon_aes_load_key(const MIPSOcteonCryptoState *crypto,
|
||||
uint8_t *key, size_t keylen)
|
||||
{
|
||||
stq_be_p(key, crypto->aes_key[0]);
|
||||
stq_be_p(key + 8, crypto->aes_key[1]);
|
||||
if (keylen > 16) {
|
||||
stq_be_p(key + 16, crypto->aes_key[2]);
|
||||
}
|
||||
if (keylen > 24) {
|
||||
stq_be_p(key + 24, crypto->aes_key[3]);
|
||||
}
|
||||
}
|
||||
|
||||
static void octeon_aes_load_block(const uint64_t regs[2], uint8_t *block)
|
||||
{
|
||||
stq_be_p(block, regs[0]);
|
||||
stq_be_p(block + 8, regs[1]);
|
||||
}
|
||||
|
||||
static void octeon_aes_store_block(uint64_t regs[2], const uint8_t *block)
|
||||
{
|
||||
regs[0] = ldq_be_p(block);
|
||||
regs[1] = ldq_be_p(block + 8);
|
||||
}
|
||||
|
||||
static void octeon_aes_encrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
|
||||
{
|
||||
AES_KEY key;
|
||||
uint8_t in[16];
|
||||
uint8_t out[16];
|
||||
uint8_t iv[16];
|
||||
uint8_t raw_key[32] = {};
|
||||
int bits = octeon_aes_key_bits(crypto);
|
||||
|
||||
if (!bits) {
|
||||
return;
|
||||
}
|
||||
|
||||
octeon_aes_load_key(crypto, raw_key, bits / 8);
|
||||
octeon_aes_load_block(crypto->aes_resinp, in);
|
||||
if (cbc) {
|
||||
int i;
|
||||
|
||||
octeon_aes_load_block(crypto->aes_iv, iv);
|
||||
for (i = 0; i < sizeof(in); i++) {
|
||||
in[i] ^= iv[i];
|
||||
}
|
||||
}
|
||||
|
||||
AES_set_encrypt_key(raw_key, bits, &key);
|
||||
AES_encrypt(in, out, &key);
|
||||
octeon_aes_store_block(crypto->aes_resinp, out);
|
||||
if (cbc) {
|
||||
octeon_aes_store_block(crypto->aes_iv, out);
|
||||
}
|
||||
}
|
||||
|
||||
static void octeon_aes_decrypt_common(MIPSOcteonCryptoState *crypto, bool cbc)
|
||||
{
|
||||
AES_KEY key;
|
||||
uint8_t in[16];
|
||||
uint8_t out[16];
|
||||
uint8_t iv[16];
|
||||
uint8_t next_iv[16];
|
||||
uint8_t raw_key[32] = {};
|
||||
int bits = octeon_aes_key_bits(crypto);
|
||||
int i;
|
||||
|
||||
if (!bits) {
|
||||
return;
|
||||
}
|
||||
|
||||
octeon_aes_load_key(crypto, raw_key, bits / 8);
|
||||
octeon_aes_load_block(crypto->aes_resinp, in);
|
||||
if (cbc) {
|
||||
memcpy(next_iv, in, sizeof(next_iv));
|
||||
octeon_aes_load_block(crypto->aes_iv, iv);
|
||||
}
|
||||
|
||||
AES_set_decrypt_key(raw_key, bits, &key);
|
||||
AES_decrypt(in, out, &key);
|
||||
if (cbc) {
|
||||
for (i = 0; i < sizeof(out); i++) {
|
||||
out[i] ^= iv[i];
|
||||
}
|
||||
}
|
||||
|
||||
octeon_aes_store_block(crypto->aes_resinp, out);
|
||||
if (cbc) {
|
||||
octeon_aes_store_block(crypto->aes_iv, next_iv);
|
||||
}
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_aes_enc_cbc1(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
|
||||
|
||||
crypto->aes_resinp[1] = value;
|
||||
octeon_aes_encrypt_common(crypto, true);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_aes_enc1(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
|
||||
|
||||
crypto->aes_resinp[1] = value;
|
||||
octeon_aes_encrypt_common(crypto, false);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_aes_dec_cbc1(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
|
||||
|
||||
crypto->aes_resinp[1] = value;
|
||||
octeon_aes_decrypt_common(crypto, true);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_aes_dec1(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
|
||||
|
||||
crypto->aes_resinp[1] = value;
|
||||
octeon_aes_decrypt_common(crypto, false);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_snow3g_start(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
octeon_snow3g_start(&env->octeon_crypto, value);
|
||||
|
||||
Reference in New Issue
Block a user