Hi,

On 20/10/26 16:55, Stian Halseth wrote:
Implement the eight AES round instructions by using QEMU's shared
crypto/aes-round.h, gated behind the crypto CPU feature:
- AES_EROUND01/23 and last variants
- AES_DROUND01/23 and last variants

Based on OSA (Oracle SPARC Architecture) 2011, section 7.3:
AES Cryptographic Operations (4 operand)

Signed-off-by: Stian Halseth <[email protected]>
---
  target/sparc/crypto_helper.c | 85 ++++++++++++++++++++++++++++++++++++
  target/sparc/helper.h        |  8 ++++
  target/sparc/insns.decode    |  9 ++++
  target/sparc/meson.build     |  2 +-
  target/sparc/translate.c     | 16 +++++++
  5 files changed, 119 insertions(+), 1 deletion(-)
  create mode 100644 target/sparc/crypto_helper.c

Could we add tests (in tests/tcg, following commit 57b484e2d23
"target/riscv: fix RV32 fixed counter accesses" which uses the
debian-all-test-cross image -- where gcc-sparc64-linux-gnu is
available)? Actually we could put them in tests/tcg/multiarch/
as generic AES tests.


diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c
new file mode 100644
index 0000000000..87cc19b930
--- /dev/null
+++ b/target/sparc/crypto_helper.c
@@ -0,0 +1,85 @@
+/*
+ * SPARC crypto instructions for QEMU
+ *
+ * Based on Oracle SPARC Architecture 2011
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "exec/helper-proto.h"
+#include "crypto/aes-round.h"
+
+/*
+ * SPARC four-operand AES round (Section 7.3).
+ * s2:s3 holds the state in big-endian order; half selects output columns
+ * 0-1 or 2-3, and key supplies their round key.  dec selects decryption;
+ * last omits MixColumns/InvMixColumns.  Return the selected 64-bit half.

Please document the non-obvious invariant:

 * Note all 64-bit values (state and key) hold AES bytes in big-endian
 * order, i.e. the most significant byte is the first state byte.

+ */
+static uint64_t aes_round(uint64_t key, uint64_t s2, uint64_t s3,
+                          int half, bool dec, bool last)
+{
+    AESState st, rk = { 0 }, r;
+    const unsigned first = HOST_BIG_ENDIAN ? 0 : 1;
+    const unsigned out = first ^ half;
+
+    st.d[first] = s2;       /* columns 0-1 */
+    st.d[first ^ 1] = s3;   /* columns 2-3 */
+    rk.d[out] = key;

Nitpicking, maybe zero the other half explicitly here instead of { 0 }:

       rk.d[out ^ 1] = 0;

+
+    if (dec) {
+        if (last) {
+            aesdec_ISB_ISR_AK(&r, &st, &rk, true);
+        } else {
+            aesdec_ISB_ISR_AK_IMC(&r, &st, &rk, true);
+        }
+    } else {
+        if (last) {
+            aesenc_SB_SR_AK(&r, &st, &rk, true);
+        } else {
+            aesenc_SB_SR_MC_AK(&r, &st, &rk, true);
+        }
+    }
+
+    return r.d[out];
+}
Tested-by: Philippe Mathieu-Daudé <[email protected]>

Reply via email to