@@ -272,7 +272,7 @@ AES_Td3[x] = Si[x].[09, 0d, 0b, 0e];
AES_Td4[x] = Si[x].[01, 01, 01, 01];
*/
-static const uint32_t AES_Te0[256] = {
+const uint32_t AES_Te0[256] = {
0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
@@ -606,8 +606,7 @@ static const uint32_t AES_Te4[256] = {
0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
};
-
-static const uint32_t AES_Td0[256] = {
+const uint32_t AES_Td0[256] = {
0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
@@ -30,4 +30,11 @@ void AES_decrypt(const unsigned char *in, unsigned char *out,
extern const uint8_t AES_sbox[256];
extern const uint8_t AES_isbox[256];
+/*
+AES_Te0[x] = S [x].[02, 01, 01, 03];
+AES_Td0[x] = Si[x].[0e, 09, 0d, 0b];
+*/
+
+extern const uint32_t AES_Te0[256], AES_Td0[256];
+
#endif
@@ -25,29 +25,6 @@
#include "crypto/aes-round.h"
#include "crypto/sm4.h"
-#define AES_XTIME(a) \
- ((a << 1) ^ ((a & 0x80) ? 0x1b : 0))
-
-#define AES_GFMUL(a, b) (( \
- (((b) & 0x1) ? (a) : 0) ^ \
- (((b) & 0x2) ? AES_XTIME(a) : 0) ^ \
- (((b) & 0x4) ? AES_XTIME(AES_XTIME(a)) : 0) ^ \
- (((b) & 0x8) ? AES_XTIME(AES_XTIME(AES_XTIME(a))) : 0)) & 0xFF)
-
-static inline uint32_t aes_mixcolumn_byte(uint8_t x, bool fwd)
-{
- uint32_t u;
-
- if (fwd) {
- u = (AES_GFMUL(x, 3) << 24) | (x << 16) | (x << 8) |
- (AES_GFMUL(x, 2) << 0);
- } else {
- u = (AES_GFMUL(x, 0xb) << 24) | (AES_GFMUL(x, 0xd) << 16) |
- (AES_GFMUL(x, 0x9) << 8) | (AES_GFMUL(x, 0xe) << 0);
- }
- return u;
-}
-
#define sext32_xlen(x) (target_ulong)(int32_t)(x)
static inline target_ulong aes32_operation(target_ulong shamt,
@@ -62,18 +39,21 @@ static inline target_ulong aes32_operation(target_ulong shamt,
if (enc) {
so = AES_sbox[si];
if (mix) {
- mixed = aes_mixcolumn_byte(so, true);
+ mixed = AES_Te0[si];
} else {
mixed = so;
}
} else {
so = AES_isbox[si];
if (mix) {
- mixed = aes_mixcolumn_byte(so, false);
+ mixed = AES_Td0[si];
} else {
mixed = so;
}
}
+ if (!HOST_BIG_ENDIAN && mix) {
+ mixed = bswap32(mixed);
+ }
mixed = rol32(mixed, shamt);
res = rs1 ^ mixed;
The AES MixColumns and InvMixColumns operations are relatively expensive 4x4 matrix multiplications in GF(2^8), which is why C implementations usually rely on precomputed lookup tables rather than performing the calculations on demand. Given that we already carry those tables in QEMU, we can just grab the right value in the implementation of the RISC-V AES32 instructions. Note that the tables in question are permuted according to the respective Sbox, so we can omit the Sbox lookup as well in this case. Cc: Richard Henderson <richard.henderson@linaro.org> Cc: Philippe Mathieu-Daudé <philmd@linaro.org> Cc: Zewen Ye <lustrew@foxmail.com> Cc: Weiwei Li <liweiwei@iscas.ac.cn> Cc: Junqiang Wang <wangjunqiang@iscas.ac.cn> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> --- crypto/aes.c | 5 ++-- include/crypto/aes.h | 7 +++++ target/riscv/crypto_helper.c | 30 ++++---------------- 3 files changed, 14 insertions(+), 28 deletions(-)