From 04e1f30eedfe581c0c3b6bc6b6f5f76c65dc2c71 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 2 Jun 2023 01:49:21 -0700 Subject: [PATCH] crypto: Add aesenc_MC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a primitive for MixColumns. Acked-by: Daniel P. Berrangé Signed-off-by: Richard Henderson --- crypto/aes.c | 61 ++++++++++++++++++++ host/include/generic/host/crypto/aes-round.h | 2 + include/crypto/aes-round.h | 18 ++++++ 3 files changed, 81 insertions(+) diff --git a/crypto/aes.c b/crypto/aes.c index 90274c3706..ec300cda0c 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -28,6 +28,8 @@ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "qemu/osdep.h" +#include "qemu/bswap.h" +#include "qemu/bitops.h" #include "crypto/aes.h" #include "crypto/aes-round.h" @@ -1216,6 +1218,65 @@ static const u32 rcon[] = { 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; +/* + * Perform MixColumns. + */ +static inline void +aesenc_MC_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_mc_rot is encoded for little-endian. */ + t = ( AES_mc_rot[st->b[swap_b ^ 0x0]] ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0x1]], 8) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0x2]], 16) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0x3]], 24)); + if (be) { + t = bswap32(t); + } + r->w[swap_w ^ 0] = t; + + t = ( AES_mc_rot[st->b[swap_b ^ 0x4]] ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0x5]], 8) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0x6]], 16) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0x7]], 24)); + if (be) { + t = bswap32(t); + } + r->w[swap_w ^ 1] = t; + + t = ( AES_mc_rot[st->b[swap_b ^ 0x8]] ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0x9]], 8) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0xA]], 16) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0xB]], 24)); + if (be) { + t = bswap32(t); + } + r->w[swap_w ^ 2] = t; + + t = ( AES_mc_rot[st->b[swap_b ^ 0xC]] ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0xD]], 8) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0xE]], 16) ^ + rol32(AES_mc_rot[st->b[swap_b ^ 0xF]], 24)); + if (be) { + t = bswap32(t); + } + r->w[swap_w ^ 3] = t; +} + +void aesenc_MC_gen(AESState *r, const AESState *st) +{ + aesenc_MC_swap(r, st, false); +} + +void aesenc_MC_genrev(AESState *r, const AESState *st) +{ + aesenc_MC_swap(r, st, true); +} + /* * Perform SubBytes + ShiftRows + AddRoundKey. */ diff --git a/host/include/generic/host/crypto/aes-round.h b/host/include/generic/host/crypto/aes-round.h index c9b9d732f0..1b82afc629 100644 --- a/host/include/generic/host/crypto/aes-round.h +++ b/host/include/generic/host/crypto/aes-round.h @@ -9,6 +9,8 @@ #define HAVE_AES_ACCEL false #define ATTR_AES_ACCEL +void aesenc_MC_accel(AESState *, const AESState *, bool) + QEMU_ERROR("unsupported accel"); void aesenc_SB_SR_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 dcf098b97b..7d2be40a67 100644 --- a/include/crypto/aes-round.h +++ b/include/crypto/aes-round.h @@ -20,6 +20,24 @@ typedef union { #include "host/crypto/aes-round.h" +/* + * Perform MixColumns. + */ + +void aesenc_MC_gen(AESState *ret, const AESState *st); +void aesenc_MC_genrev(AESState *ret, const AESState *st); + +static inline void aesenc_MC(AESState *r, const AESState *st, bool be) +{ + if (HAVE_AES_ACCEL) { + aesenc_MC_accel(r, st, be); + } else if (HOST_BIG_ENDIAN == be) { + aesenc_MC_gen(r, st); + } else { + aesenc_MC_genrev(r, st); + } +} + /* * Perform SubBytes + ShiftRows + AddRoundKey. */