qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] target/riscv: Use existing lookup tables for MixColumns
@ 2023-07-31  8:40 Ard Biesheuvel
  2023-07-31 15:16 ` Richard Henderson
  2023-08-02 13:41 ` Alistair Francis
  0 siblings, 2 replies; 3+ messages in thread
From: Ard Biesheuvel @ 2023-07-31  8:40 UTC (permalink / raw)
  To: qemu-devel
  Cc: Ard Biesheuvel, Richard Henderson, Philippe Mathieu-Daudé,
	Zewen Ye, Weiwei Li, Junqiang Wang

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>
---
v2:
- ignore host endianness and use be32_to_cpu() unconditionally

 crypto/aes.c                 |  4 +--
 include/crypto/aes.h         |  7 ++++
 target/riscv/crypto_helper.c | 34 +++-----------------
 3 files changed, 13 insertions(+), 32 deletions(-)

diff --git a/crypto/aes.c b/crypto/aes.c
index 836d7d5c0bf1b392..df4362ac6022eac2 100644
--- a/crypto/aes.c
+++ b/crypto/aes.c
@@ -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,
@@ -607,7 +607,7 @@ static const uint32_t AES_Te4[256] = {
     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,
diff --git a/include/crypto/aes.h b/include/crypto/aes.h
index 709d4d226bfe158b..381f24c9022d2aa8 100644
--- a/include/crypto/aes.h
+++ b/include/crypto/aes.h
@@ -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
diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
index 99d85a618843e87e..4d65945429c6dcc4 100644
--- a/target/riscv/crypto_helper.c
+++ b/target/riscv/crypto_helper.c
@@ -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,
@@ -55,23 +32,20 @@ static inline target_ulong aes32_operation(target_ulong shamt,
                                            bool enc, bool mix)
 {
     uint8_t si = rs2 >> shamt;
-    uint8_t so;
     uint32_t mixed;
     target_ulong res;
 
     if (enc) {
-        so = AES_sbox[si];
         if (mix) {
-            mixed = aes_mixcolumn_byte(so, true);
+            mixed = be32_to_cpu(AES_Te0[si]);
         } else {
-            mixed = so;
+            mixed = AES_sbox[si];
         }
     } else {
-        so = AES_isbox[si];
         if (mix) {
-            mixed = aes_mixcolumn_byte(so, false);
+            mixed = be32_to_cpu(AES_Td0[si]);
         } else {
-            mixed = so;
+            mixed = AES_isbox[si];
         }
     }
     mixed = rol32(mixed, shamt);
-- 
2.39.2



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] target/riscv: Use existing lookup tables for MixColumns
  2023-07-31  8:40 [PATCH v2] target/riscv: Use existing lookup tables for MixColumns Ard Biesheuvel
@ 2023-07-31 15:16 ` Richard Henderson
  2023-08-02 13:41 ` Alistair Francis
  1 sibling, 0 replies; 3+ messages in thread
From: Richard Henderson @ 2023-07-31 15:16 UTC (permalink / raw)
  To: Ard Biesheuvel, qemu-devel
  Cc: Philippe Mathieu-Daudé, Zewen Ye, Weiwei Li, Junqiang Wang

On 7/31/23 01:40, Ard Biesheuvel wrote:
> 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>
> ---
> v2:
> - ignore host endianness and use be32_to_cpu() unconditionally

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] target/riscv: Use existing lookup tables for MixColumns
  2023-07-31  8:40 [PATCH v2] target/riscv: Use existing lookup tables for MixColumns Ard Biesheuvel
  2023-07-31 15:16 ` Richard Henderson
@ 2023-08-02 13:41 ` Alistair Francis
  1 sibling, 0 replies; 3+ messages in thread
From: Alistair Francis @ 2023-08-02 13:41 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: qemu-devel, Richard Henderson, Philippe Mathieu-Daudé,
	Zewen Ye, Weiwei Li, Junqiang Wang

On Mon, Jul 31, 2023 at 4:42 AM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> 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>

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
> v2:
> - ignore host endianness and use be32_to_cpu() unconditionally
>
>  crypto/aes.c                 |  4 +--
>  include/crypto/aes.h         |  7 ++++
>  target/riscv/crypto_helper.c | 34 +++-----------------
>  3 files changed, 13 insertions(+), 32 deletions(-)
>
> diff --git a/crypto/aes.c b/crypto/aes.c
> index 836d7d5c0bf1b392..df4362ac6022eac2 100644
> --- a/crypto/aes.c
> +++ b/crypto/aes.c
> @@ -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,
> @@ -607,7 +607,7 @@ static const uint32_t AES_Te4[256] = {
>      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,
> diff --git a/include/crypto/aes.h b/include/crypto/aes.h
> index 709d4d226bfe158b..381f24c9022d2aa8 100644
> --- a/include/crypto/aes.h
> +++ b/include/crypto/aes.h
> @@ -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
> diff --git a/target/riscv/crypto_helper.c b/target/riscv/crypto_helper.c
> index 99d85a618843e87e..4d65945429c6dcc4 100644
> --- a/target/riscv/crypto_helper.c
> +++ b/target/riscv/crypto_helper.c
> @@ -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,
> @@ -55,23 +32,20 @@ static inline target_ulong aes32_operation(target_ulong shamt,
>                                             bool enc, bool mix)
>  {
>      uint8_t si = rs2 >> shamt;
> -    uint8_t so;
>      uint32_t mixed;
>      target_ulong res;
>
>      if (enc) {
> -        so = AES_sbox[si];
>          if (mix) {
> -            mixed = aes_mixcolumn_byte(so, true);
> +            mixed = be32_to_cpu(AES_Te0[si]);
>          } else {
> -            mixed = so;
> +            mixed = AES_sbox[si];
>          }
>      } else {
> -        so = AES_isbox[si];
>          if (mix) {
> -            mixed = aes_mixcolumn_byte(so, false);
> +            mixed = be32_to_cpu(AES_Td0[si]);
>          } else {
> -            mixed = so;
> +            mixed = AES_isbox[si];
>          }
>      }
>      mixed = rol32(mixed, shamt);
> --
> 2.39.2
>
>


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-08-02 13:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-31  8:40 [PATCH v2] target/riscv: Use existing lookup tables for MixColumns Ard Biesheuvel
2023-07-31 15:16 ` Richard Henderson
2023-08-02 13:41 ` Alistair Francis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).