diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-06-01 21:57:10 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-07-08 07:30:17 +0100 |
commit | 6b0a96ce3a405ef4676e1fa853f2c649dc25c2b4 (patch) | |
tree | d9883fd6861a69f1c87d30459983f14cb0242363 | |
parent | e20e14d2b15d5ad4fb0a640c95d7c1bc534d9fd7 (diff) |
crypto: Add aesenc_SB_SR_AK
Start adding infrastructure for accelerating guest AES.
Begin with a SubBytes + ShiftRows + AddRoundKey primitive.
Acked-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | crypto/aes.c | 46 | ||||
-rw-r--r-- | host/include/generic/host/crypto/aes-round.h | 16 | ||||
-rw-r--r-- | include/crypto/aes-round.h | 44 |
4 files changed, 107 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index d422ce50e3..1817cfc62f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3224,6 +3224,7 @@ M: Daniel P. Berrange <berrange@redhat.com> S: Maintained F: crypto/ F: include/crypto/ +F: host/include/*/host/crypto/ F: qapi/crypto.json F: tests/unit/test-crypto-* F: tests/bench/benchmark-crypto-* diff --git a/crypto/aes.c b/crypto/aes.c index e65c97e0c1..408d92b81f 100644 --- a/crypto/aes.c +++ b/crypto/aes.c @@ -29,6 +29,7 @@ */ #include "qemu/osdep.h" #include "crypto/aes.h" +#include "crypto/aes-round.h" typedef uint32_t u32; typedef uint8_t u8; @@ -1215,6 +1216,51 @@ static const u32 rcon[] = { 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ }; +/* + * Perform SubBytes + ShiftRows + AddRoundKey. + */ +static inline void +aesenc_SB_SR_AK_swap(AESState *ret, const AESState *st, + const AESState *rk, bool swap) +{ + const int swap_b = swap ? 15 : 0; + AESState t; + + t.b[swap_b ^ 0x0] = AES_sbox[st->b[swap_b ^ AES_SH(0x0)]]; + t.b[swap_b ^ 0x1] = AES_sbox[st->b[swap_b ^ AES_SH(0x1)]]; + t.b[swap_b ^ 0x2] = AES_sbox[st->b[swap_b ^ AES_SH(0x2)]]; + t.b[swap_b ^ 0x3] = AES_sbox[st->b[swap_b ^ AES_SH(0x3)]]; + t.b[swap_b ^ 0x4] = AES_sbox[st->b[swap_b ^ AES_SH(0x4)]]; + t.b[swap_b ^ 0x5] = AES_sbox[st->b[swap_b ^ AES_SH(0x5)]]; + t.b[swap_b ^ 0x6] = AES_sbox[st->b[swap_b ^ AES_SH(0x6)]]; + t.b[swap_b ^ 0x7] = AES_sbox[st->b[swap_b ^ AES_SH(0x7)]]; + t.b[swap_b ^ 0x8] = AES_sbox[st->b[swap_b ^ AES_SH(0x8)]]; + t.b[swap_b ^ 0x9] = AES_sbox[st->b[swap_b ^ AES_SH(0x9)]]; + t.b[swap_b ^ 0xa] = AES_sbox[st->b[swap_b ^ AES_SH(0xA)]]; + t.b[swap_b ^ 0xb] = AES_sbox[st->b[swap_b ^ AES_SH(0xB)]]; + t.b[swap_b ^ 0xc] = AES_sbox[st->b[swap_b ^ AES_SH(0xC)]]; + t.b[swap_b ^ 0xd] = AES_sbox[st->b[swap_b ^ AES_SH(0xD)]]; + t.b[swap_b ^ 0xe] = AES_sbox[st->b[swap_b ^ AES_SH(0xE)]]; + t.b[swap_b ^ 0xf] = AES_sbox[st->b[swap_b ^ AES_SH(0xF)]]; + + /* + * Perform the AddRoundKey with generic vectors. + * This may be expanded to either host integer or host vector code. + * The key and output endianness match, so no bswap required. + */ + ret->v = t.v ^ rk->v; +} + +void aesenc_SB_SR_AK_gen(AESState *r, const AESState *s, const AESState *k) +{ + aesenc_SB_SR_AK_swap(r, s, k, false); +} + +void aesenc_SB_SR_AK_genrev(AESState *r, const AESState *s, const AESState *k) +{ + aesenc_SB_SR_AK_swap(r, s, k, true); +} + /** * Expand the cipher key into the encryption key schedule. */ diff --git a/host/include/generic/host/crypto/aes-round.h b/host/include/generic/host/crypto/aes-round.h new file mode 100644 index 0000000000..c5d8066179 --- /dev/null +++ b/host/include/generic/host/crypto/aes-round.h @@ -0,0 +1,16 @@ +/* + * No host specific aes acceleration. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef GENERIC_HOST_CRYPTO_AES_ROUND_H +#define GENERIC_HOST_CRYPTO_AES_ROUND_H + +#define HAVE_AES_ACCEL false +#define ATTR_AES_ACCEL + +void aesenc_SB_SR_AK_accel(AESState *, const AESState *, + const AESState *, bool) + QEMU_ERROR("unsupported accel"); + +#endif /* GENERIC_HOST_CRYPTO_AES_ROUND_H */ diff --git a/include/crypto/aes-round.h b/include/crypto/aes-round.h new file mode 100644 index 0000000000..b85db1a30e --- /dev/null +++ b/include/crypto/aes-round.h @@ -0,0 +1,44 @@ +/* + * AES round fragments, generic version + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Copyright (C) 2023 Linaro, Ltd. + */ + +#ifndef CRYPTO_AES_ROUND_H +#define CRYPTO_AES_ROUND_H + +/* Hosts with acceleration will usually need a 16-byte vector type. */ +typedef uint8_t AESStateVec __attribute__((vector_size(16))); + +typedef union { + uint8_t b[16]; + uint32_t w[4]; + uint64_t d[2]; + AESStateVec v; +} AESState; + +#include "host/crypto/aes-round.h" + +/* + * Perform SubBytes + ShiftRows + AddRoundKey. + */ + +void aesenc_SB_SR_AK_gen(AESState *ret, const AESState *st, + const AESState *rk); +void aesenc_SB_SR_AK_genrev(AESState *ret, const AESState *st, + const AESState *rk); + +static inline void aesenc_SB_SR_AK(AESState *r, const AESState *st, + const AESState *rk, bool be) +{ + if (HAVE_AES_ACCEL) { + aesenc_SB_SR_AK_accel(r, st, rk, be); + } else if (HOST_BIG_ENDIAN == be) { + aesenc_SB_SR_AK_gen(r, st, rk); + } else { + aesenc_SB_SR_AK_genrev(r, st, rk); + } +} + +#endif /* CRYPTO_AES_ROUND_H */ |