diff --git a/crypto/aes.c b/crypto/aes.c index ec300cda0c..6c05d731f4 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -1322,6 +1322,65 @@ void aesenc_SB_SR_AK_genrev(AESState *r, const AESState *s, const AESState *k) aesenc_SB_SR_AK_swap(r, s, k, true); } +/* + * Perform InvMixColumns. + */ +static inline void +aesdec_IMC_swap(AESState *r, const AESState *st, bool swap) +{ + int swap_b = swap * 0xf; + int swap_w = swap * 0x3; + bool be = HOST_BIG_ENDIAN ^ swap; + uint32_t t; + + /* Note that AES_imc is encoded for big-endian. */ + t = (AES_imc[st->b[swap_b ^ 0x0]][0] ^ + AES_imc[st->b[swap_b ^ 0x1]][1] ^ + AES_imc[st->b[swap_b ^ 0x2]][2] ^ + AES_imc[st->b[swap_b ^ 0x3]][3]); + if (!be) { + t = bswap32(t); + } + r->w[swap_w ^ 0] = t; + + t = (AES_imc[st->b[swap_b ^ 0x4]][0] ^ + AES_imc[st->b[swap_b ^ 0x5]][1] ^ + AES_imc[st->b[swap_b ^ 0x6]][2] ^ + AES_imc[st->b[swap_b ^ 0x7]][3]); + if (!be) { + t = bswap32(t); + } + r->w[swap_w ^ 1] = t; + + t = (AES_imc[st->b[swap_b ^ 0x8]][0] ^ + AES_imc[st->b[swap_b ^ 0x9]][1] ^ + AES_imc[st->b[swap_b ^ 0xA]][2] ^ + AES_imc[st->b[swap_b ^ 0xB]][3]); + if (!be) { + t = bswap32(t); + } + r->w[swap_w ^ 2] = t; + + t = (AES_imc[st->b[swap_b ^ 0xC]][0] ^ + AES_imc[st->b[swap_b ^ 0xD]][1] ^ + AES_imc[st->b[swap_b ^ 0xE]][2] ^ + AES_imc[st->b[swap_b ^ 0xF]][3]); + if (!be) { + t = bswap32(t); + } + r->w[swap_w ^ 3] = t; +} + +void aesdec_IMC_gen(AESState *r, const AESState *st) +{ + aesdec_IMC_swap(r, st, false); +} + +void aesdec_IMC_genrev(AESState *r, const AESState *st) +{ + aesdec_IMC_swap(r, st, true); +} + /* * Perform InvSubBytes + InvShiftRows + AddRoundKey. */ diff --git a/host/include/generic/host/crypto/aes-round.h b/host/include/generic/host/crypto/aes-round.h index 1b82afc629..335ec3f11e 100644 --- a/host/include/generic/host/crypto/aes-round.h +++ b/host/include/generic/host/crypto/aes-round.h @@ -15,6 +15,8 @@ void aesenc_SB_SR_AK_accel(AESState *, const AESState *, const AESState *, bool) QEMU_ERROR("unsupported accel"); +void aesdec_IMC_accel(AESState *, const AESState *, bool) + QEMU_ERROR("unsupported accel"); void aesdec_ISB_ISR_AK_accel(AESState *, const AESState *, const AESState *, bool) QEMU_ERROR("unsupported accel"); diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h index 7d2be40a67..7be2cc0d8e 100644 --- a/include/crypto/aes-round.h +++ b/include/crypto/aes-round.h @@ -59,6 +59,24 @@ static inline void aesenc_SB_SR_AK(AESState *r, const AESState *st, } } +/* + * Perform InvMixColumns. + */ + +void aesdec_IMC_gen(AESState *ret, const AESState *st); +void aesdec_IMC_genrev(AESState *ret, const AESState *st); + +static inline void aesdec_IMC(AESState *r, const AESState *st, bool be) +{ + if (HAVE_AES_ACCEL) { + aesdec_IMC_accel(r, st, be); + } else if (HOST_BIG_ENDIAN == be) { + aesdec_IMC_gen(r, st); + } else { + aesdec_IMC_genrev(r, st); + } +} + /* * Perform InvSubBytes + InvShiftRows + AddRoundKey. */