QEMU-Arm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Jamin Lin <jamin_lin@aspeedtech.com>
To: "Daniel P. Berrangé" <berrange@redhat.com>,
	"Cédric Le Goater" <clg@kaod.org>,
	"Peter Maydell" <peter.maydell@linaro.org>,
	"Steven Lee" <steven_lee@aspeedtech.com>,
	"Troy Lee" <leetroy@gmail.com>,
	"Kane Chen" <kane_chen@aspeedtech.com>,
	"Andrew Jeffery" <andrew@codeconstruct.com.au>,
	"Joel Stanley" <joel@jms.id.au>, "Eric Blake" <eblake@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Fabiano Rosas" <farosas@suse.de>,
	"Laurent Vivier" <lvivier@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"open list:All patches CC here" <qemu-devel@nongnu.org>,
	"open list:ASPEED BMCs" <qemu-arm@nongnu.org>
Cc: Jamin Lin <jamin_lin@aspeedtech.com>, Troy Lee <troy_lee@aspeedtech.com>
Subject: [PATCH v2 04/17] hw/misc/aspeed_hace: Support the CTR mode for the crypto command
Date: Wed, 15 Jul 2026 03:33:19 +0000	[thread overview]
Message-ID: <20260715033311.1648424-5-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20260715033311.1648424-1-jamin_lin@aspeedtech.com>

The AST2600, AST1030 and later crypto engines add AES/DES/3DES CTR mode
(HACE10[6:4] = 0b100) on top of the ECB/CBC modes shared with the
AST2500. Decode the CTR selection, round the working buffers up to a
whole block so the stream-like final block is still processed a block at
a time, and write the counter advanced by the number of blocks consumed
back to the context buffer so the driver can continue across requests.

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
 hw/misc/aspeed_hace.c | 50 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 45 insertions(+), 5 deletions(-)

diff --git a/hw/misc/aspeed_hace.c b/hw/misc/aspeed_hace.c
index 3d3f1fc8dd..09d0515271 100644
--- a/hw/misc/aspeed_hace.c
+++ b/hw/misc/aspeed_hace.c
@@ -42,6 +42,7 @@
 #define  CRYPT_CMD_OP_MODE_MASK     (0x7 << 4)
 #define  CRYPT_CMD_ECB              (0x0 << 4)
 #define  CRYPT_CMD_CBC              (0x1 << 4)
+#define  CRYPT_CMD_CTR              (0x4 << 4)
 /* AES key length HACE10[3:2] */
 #define  CRYPT_CMD_AES_KEY_LEN_MASK (0x3 << 2)
 #define  CRYPT_CMD_AES256           (0x2 << 2)
@@ -589,6 +590,9 @@ static bool crypt_decode_cmd(uint32_t cmd, QCryptoCipherAlgo *alg,
     case CRYPT_CMD_CBC:
         *mode = QCRYPTO_CIPHER_MODE_CBC;
         break;
+    case CRYPT_CMD_CTR:
+        *mode = QCRYPTO_CIPHER_MODE_CTR;
+        break;
     default:
         return false;
     }
@@ -652,6 +656,22 @@ static bool crypt_prepare_sg(AspeedHACEState *s, uint64_t addr,
     return copied == len;
 }
 
+/*
+ * Add @add to the big-endian counter block @ctr (@len bytes) in place, so the
+ * CTR mode counter can be advanced by the number of blocks just consumed.
+ */
+static void crypt_be_add(uint8_t *ctr, size_t len, uint64_t add)
+{
+    size_t i = len;
+
+    while (i > 0 && add) {
+        i--;
+        add += ctr[i];
+        ctr[i] = add & 0xff;
+        add >>= 8;
+    }
+}
+
 /*
  * Perform an AES/DES/3DES ECB/CBC operation. The source and destination are
  * either single contiguous buffers (direct access mode) or scatter-gather
@@ -677,6 +697,7 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
     uint64_t dst_addr;
     size_t iv_offset;
     size_t blocklen;
+    size_t buf_len;
     size_t keylen;
     bool status;
 
@@ -729,8 +750,14 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
         return;
     }
 
-    src_buf = g_malloc0(len);
-    dst_buf = g_malloc0(len);
+    /*
+     * Round the working buffers up to a whole block. Block modes are already
+     * block-aligned; the stream-like CTR mode may leave a partial final block
+     * that the engine still processes a full block at a time.
+     */
+    buf_len = QEMU_ALIGN_UP(len, blocklen);
+    src_buf = g_malloc0(buf_len);
+    dst_buf = g_malloc0(buf_len);
 
     /* Gather the source into the bounce buffer, per the selected mode. */
     src_addr = s->regs[R_CRYPT_SRC];
@@ -751,7 +778,7 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
     }
 
     if (encrypt) {
-        if (qcrypto_cipher_encrypt(cipher, src_buf, dst_buf, len,
+        if (qcrypto_cipher_encrypt(cipher, src_buf, dst_buf, buf_len,
                                    &local_err) < 0) {
             qemu_log_mask(LOG_GUEST_ERROR, "%s: encrypt failed: %s\n",
                           __func__, error_get_pretty(local_err));
@@ -759,7 +786,7 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
             return;
         }
     } else {
-        if (qcrypto_cipher_decrypt(cipher, src_buf, dst_buf, len,
+        if (qcrypto_cipher_decrypt(cipher, src_buf, dst_buf, buf_len,
                                    &local_err) < 0) {
             qemu_log_mask(LOG_GUEST_ERROR, "%s: decrypt failed: %s\n",
                           __func__, error_get_pretty(local_err));
@@ -792,13 +819,26 @@ static void do_crypt_operation(AspeedHACEState *s, uint32_t cmd)
          * output when encrypting, or of the input when decrypting. Write it
          * back as the IV for the next request.
          */
-        next_iv = (encrypt ? dst_buf : src_buf) + len - blocklen;
+        next_iv = (encrypt ? dst_buf : src_buf) + buf_len - blocklen;
         if (address_space_write(&s->dram_as, ctx_addr + iv_offset,
                                 MEMTXATTRS_UNSPECIFIED, next_iv, blocklen)) {
             qemu_log_mask(LOG_GUEST_ERROR,
                           "%s: Failed to write IV, addr=0x%" HWADDR_PRIx "\n",
                           __func__, ctx_addr + iv_offset);
         }
+    } else if (mode == QCRYPTO_CIPHER_MODE_CTR) {
+        /*
+         * CTR chains on the counter, which advances by one per block. Add the
+         * number of blocks processed (buf_len / blocklen) and write it back.
+         */
+        crypt_be_add(ctx + iv_offset, blocklen, buf_len / blocklen);
+        if (address_space_write(&s->dram_as, ctx_addr + iv_offset,
+                                MEMTXATTRS_UNSPECIFIED, ctx + iv_offset,
+                                blocklen)) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "%s: Failed to write IV, addr=0x%" HWADDR_PRIx "\n",
+                          __func__, ctx_addr + iv_offset);
+        }
     }
 }
 
-- 
2.43.0


  parent reply	other threads:[~2026-07-15  3:35 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-15  3:33 [PATCH v2 00/17] Support the ASPEED HACE crypto command Jamin Lin
2026-07-15  3:33 ` [PATCH v2 01/17] hw/misc/aspeed_hace: Support the crypto command in direct access mode Jamin Lin
2026-07-15  3:33 ` [PATCH v2 02/17] tests/qtest/aspeed-hace: Test the crypto command on the AST2500 Jamin Lin
2026-07-15  3:33 ` [PATCH v2 03/17] hw/misc/aspeed_hace: Support scatter-gather mode for the crypto command Jamin Lin
2026-07-15  3:33 ` Jamin Lin [this message]
2026-07-15  3:33 ` [PATCH v2 05/17] tests/qtest/aspeed-hace: Test the crypto command on the AST2600 Jamin Lin
2026-07-15  3:33 ` [PATCH v2 06/17] tests/qtest/aspeed-hace: Test the crypto command on the AST1030 Jamin Lin
2026-07-15  3:33 ` [PATCH v2 07/17] crypto/cipher: Add GCM to QCryptoCipherMode Jamin Lin
2026-07-15  4:51   ` Markus Armbruster
2026-07-15  3:33 ` [PATCH v2 08/17] crypto/cipher: Add setaad/gettag for AEAD modes Jamin Lin
2026-07-15  3:33 ` [PATCH v2 09/17] crypto/cipher-gcrypt: Implement AES-GCM Jamin Lin
2026-07-15  3:33 ` [PATCH v2 10/17] crypto/cipher-nettle: " Jamin Lin
2026-07-15  3:33 ` [PATCH v2 11/17] crypto/cipher-gnutls: " Jamin Lin
2026-07-15  3:33 ` [PATCH v2 12/17] tests/unit/test-crypto-cipher: Test AES-GCM mode Jamin Lin
2026-07-15  3:33 ` [PATCH v2 13/17] hw/misc/aspeed_hace: Support 64-bit DMA for the crypto command Jamin Lin
2026-07-15  3:33 ` [PATCH v2 14/17] hw/misc/aspeed_hace: Support the AES-GCM mode " Jamin Lin
2026-07-15  3:33 ` [PATCH v2 15/17] hw/misc/aspeed_hace: Enable the crypto command on the AST2700 Jamin Lin
2026-07-15  3:33 ` [PATCH v2 16/17] tests/qtest/aspeed-hace: Test " Jamin Lin
2026-07-15  3:33 ` [PATCH v2 17/17] tests/functional/aarch64/test_aspeed_ast2700: Drop the AST2700 crypto self-test workaround Jamin Lin
2026-07-20  5:51   ` Cédric Le Goater
2026-07-20  5:57     ` Jamin Lin
2026-07-20  6:29       ` Cédric Le Goater

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260715033311.1648424-5-jamin_lin@aspeedtech.com \
    --to=jamin_lin@aspeedtech.com \
    --cc=andrew@codeconstruct.com.au \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=clg@kaod.org \
    --cc=eblake@redhat.com \
    --cc=farosas@suse.de \
    --cc=joel@jms.id.au \
    --cc=kane_chen@aspeedtech.com \
    --cc=leetroy@gmail.com \
    --cc=lvivier@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=steven_lee@aspeedtech.com \
    --cc=troy_lee@aspeedtech.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox