From: Jamin Lin <jamin_lin@aspeedtech.com>
To: "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>,
"Fabiano Rosas" <farosas@suse.de>,
"Laurent Vivier" <lvivier@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"open list:ASPEED BMCs" <qemu-arm@nongnu.org>,
"open list:All patches CC here" <qemu-devel@nongnu.org>
Cc: Jamin Lin <jamin_lin@aspeedtech.com>, Troy Lee <troy_lee@aspeedtech.com>
Subject: [PATCH v1 5/5] tests/qtest/aspeed-acry-test: Add RSA ModExp tests
Date: Thu, 13 Aug 2026 06:24:07 +0000 [thread overview]
Message-ID: <20260813062359.425268-6-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20260813062359.425268-1-jamin_lin@aspeedtech.com>
Add qtest cases exercising the AST2600 ACRY RSA ModExp engine end to
end. Each case lays out the exponent, modulus and message in the
scattered SRAM byte layout the engine expects, triggers the
engine, checks that both completion bits (RSA_ENG_DONE and
RSA_DMA_DONE) are asserted together in the status register, reads the
result back from the result SRAM, and checks the status bits clear
afterwards.
Comparing the result against a known-answer ciphertext
also validates the SRAM byte mapping end to end.
The cases cover raw (unpadded) public-exponent RSA, c = m^e mod n -
exactly what the "rsa" akcipher transform backed by the ACRY FW
performs, since PKCS1 padding is applied by a separate template
layered on top in Linux, not by the ACRY hardware. QEMU's akcipher
backend only implements raw RSA via libgcrypt, so the tests skip
rather than fail when the build lacks it.
The 2048- and 4096-bit vectors are rsa_tv_template[2] and [3] from the
Linux kernel crypto self-test suite (crypto/testmgr.h, v6.18); the
4096-bit one matches the sha512,rsa4096 key size the FW uses.
Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
tests/qtest/aspeed-acry-test.c | 408 +++++++++++++++++++++++++++++++++
tests/qtest/meson.build | 5 +-
2 files changed, 412 insertions(+), 1 deletion(-)
create mode 100644 tests/qtest/aspeed-acry-test.c
diff --git a/tests/qtest/aspeed-acry-test.c b/tests/qtest/aspeed-acry-test.c
new file mode 100644
index 0000000000..a774844701
--- /dev/null
+++ b/tests/qtest/aspeed-acry-test.c
@@ -0,0 +1,408 @@
+/*
+ * QTest testcase for the ASPEED ACRY Engine
+ *
+ * Copyright (C) 2026 ASPEED Technology Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "qemu/bitops.h"
+#include "crypto/akcipher.h"
+
+#define ACRY_TRIGGER 0x000
+#define ACRY_TRIGGER_RSA_START BIT(0)
+#define ACRY_TRIGGER_RSA_DMA_DATA BIT(1)
+#define ACRY_DMA_CMD 0x048
+#define ACRY_DMA_CMD_DMEM_AHB BIT(8)
+#define ACRY_DMA_CMD_SRAM_MODE_RSA (0x3 << 4)
+#define ACRY_DMA_SRC 0x04C
+#define ACRY_DMA_LEN 0x050
+#define ACRY_RSA_KEY_LEN 0x058
+#define ACRY_INT_MASK 0x3F8
+#define ACRY_INT_MASK_RSA_ENG_MASK BIT(1)
+#define ACRY_INT_MASK_RSA_DMA_MASK BIT(2)
+#define ACRY_STATUS 0x3FC
+#define ACRY_STATUS_RSA_ENG_DONE BIT(1)
+#define ACRY_STATUS_RSA_DMA_DONE BIT(2)
+#define ACRY_STATUS_RSA_DONE (ACRY_STATUS_RSA_ENG_DONE | \
+ ACRY_STATUS_RSA_DMA_DONE)
+
+#define ACRY_DATA_MAX_LEN 0x800
+#define ACRY_SRAM_SIZE (3 * ACRY_DATA_MAX_LEN)
+#define ACRY_MAX_BITS 4096
+#define ACRY_MAX_BYTES (ACRY_MAX_BITS / 8)
+
+/*
+ * Raw (unpadded) RSA known-answer vectors: c = m^e mod n with
+ * e = 0x10001 (65537) - exactly what the "rsa" akcipher transform backed by
+ * the ACRY FW computes. PKCS1 padding is a separate "pkcs1pad(rsa)" template
+ * layered on top in Linux, not done by the ACRY hardware.
+ *
+ * rsa2048_* and rsa4096_* are from the Linux kernel crypto/testmgr.h (v6.18),
+ * rsa_tv_template[2] and [3]. Grep that file's own comment to find them:
+ *
+ * RSA test vectors. Borrowed from openSSL.
+ *
+ * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/crypto/testmgr.h?h=v6.18
+ *
+ * There the modulus n is DER-encoded in the .key field (not a raw field), the
+ * ciphertext is .c, and every entry reuses the same 8-byte .m message.
+ */
+/* rsa_tv_template[].m, shared by every entry */
+static const uint8_t rsa_m[8] = {
+ 0x54, 0x85, 0x9B, 0x34, 0x2C, 0x49, 0xEA, 0x2A,
+};
+/* public exponent e = 65537, DER-encoded in every .key */
+static const uint8_t rsa_e[3] = { 0x01, 0x00, 0x01 };
+
+/* rsa_tv_template[2].key, modulus n */
+static const uint8_t rsa2048_n[256] = {
+ 0xDB, 0x10, 0x1A, 0xC2, 0xA3, 0xF1, 0xDC, 0xFF, 0x13, 0x6B, 0xED, 0x44,
+ 0xDF, 0xF0, 0x02, 0x6D, 0x13, 0xC7, 0x88, 0xDA, 0x70, 0x6B, 0x54, 0xF1,
+ 0xE8, 0x27, 0xDC, 0xC3, 0x0F, 0x99, 0x6A, 0xFA, 0xC6, 0x67, 0xFF, 0x1D,
+ 0x1E, 0x3C, 0x1D, 0xC1, 0xB5, 0x5F, 0x6C, 0xC0, 0xB2, 0x07, 0x3A, 0x6D,
+ 0x41, 0xE4, 0x25, 0x99, 0xAC, 0xFC, 0xD2, 0x0F, 0x02, 0xD3, 0xD1, 0x54,
+ 0x06, 0x1A, 0x51, 0x77, 0xBD, 0xB6, 0xBF, 0xEA, 0xA7, 0x5C, 0x06, 0xA9,
+ 0x5D, 0x69, 0x84, 0x45, 0xD7, 0xF5, 0x05, 0xBA, 0x47, 0xF0, 0x1B, 0xD7,
+ 0x2B, 0x24, 0xEC, 0xCB, 0x9B, 0x1B, 0x10, 0x8D, 0x81, 0xA0, 0xBE, 0xB1,
+ 0x8C, 0x33, 0xE4, 0x36, 0xB8, 0x43, 0xEB, 0x19, 0x2A, 0x81, 0x8D, 0xDE,
+ 0x81, 0x0A, 0x99, 0x48, 0xB6, 0xF6, 0xBC, 0xCD, 0x49, 0x34, 0x3A, 0x8F,
+ 0x26, 0x94, 0xE3, 0x28, 0x82, 0x1A, 0x7C, 0x8F, 0x59, 0x9F, 0x45, 0xE8,
+ 0x5D, 0x1A, 0x45, 0x76, 0x04, 0x56, 0x05, 0xA1, 0xD0, 0x1B, 0x8C, 0x77,
+ 0x6D, 0xAF, 0x53, 0xFA, 0x71, 0xE2, 0x67, 0xE0, 0x9A, 0xFE, 0x03, 0xA9,
+ 0x85, 0xD2, 0xC9, 0xAA, 0xBA, 0x2A, 0xBC, 0xF4, 0xA0, 0x08, 0xF5, 0x13,
+ 0x98, 0x13, 0x5D, 0xF0, 0xD9, 0x33, 0x34, 0x2A, 0x61, 0xC3, 0x89, 0x55,
+ 0xF0, 0xAE, 0x1A, 0x9C, 0x22, 0xEE, 0x19, 0x05, 0x8D, 0x32, 0xFE, 0xEC,
+ 0x9C, 0x84, 0xBA, 0xB7, 0xF9, 0x6C, 0x3A, 0x4F, 0x07, 0xFC, 0x45, 0xEB,
+ 0x12, 0xE5, 0x7B, 0xFD, 0x55, 0xE6, 0x29, 0x69, 0xD1, 0xC2, 0xE8, 0xB9,
+ 0x78, 0x59, 0xF6, 0x79, 0x10, 0xC6, 0x4E, 0xEB, 0x6A, 0x5E, 0xB9, 0x9A,
+ 0xC7, 0xC4, 0x5B, 0x63, 0xDA, 0xA3, 0x3F, 0x5E, 0x92, 0x7A, 0x81, 0x5E,
+ 0xD6, 0xB0, 0xE2, 0x62, 0x8F, 0x74, 0x26, 0xC2, 0x0C, 0xD3, 0x9A, 0x17,
+ 0x47, 0xE6, 0x8E, 0xAB,
+};
+/* rsa_tv_template[2].c */
+static const uint8_t rsa2048_c[256] = {
+ 0xB2, 0x97, 0x76, 0xB4, 0xAE, 0x3E, 0x38, 0x3C, 0x7E, 0x64, 0x1F, 0xCC,
+ 0xA2, 0x7F, 0xF6, 0xBE, 0xCF, 0x49, 0xBC, 0x48, 0xD3, 0x6C, 0x8F, 0x0A,
+ 0x0E, 0xC1, 0x73, 0xBD, 0x7B, 0x55, 0x79, 0x36, 0x0E, 0xA1, 0x87, 0x88,
+ 0xB9, 0x2C, 0x90, 0xA6, 0x53, 0x5E, 0xE9, 0xEF, 0xC4, 0xE2, 0x4D, 0xDD,
+ 0xF7, 0xA6, 0x69, 0x82, 0x3F, 0x56, 0xA4, 0x7B, 0xFB, 0x62, 0xE0, 0xAE,
+ 0xB8, 0xD3, 0x04, 0xB3, 0xAC, 0x5A, 0x15, 0x2A, 0xE3, 0x19, 0x9B, 0x03,
+ 0x9A, 0x0B, 0x41, 0xDA, 0x64, 0xEC, 0x0A, 0x69, 0xFC, 0xF2, 0x10, 0x92,
+ 0xF3, 0xC1, 0xBF, 0x84, 0x7F, 0xFD, 0x2C, 0xAE, 0xC8, 0xB5, 0xF6, 0x41,
+ 0x70, 0xC5, 0x47, 0x03, 0x8A, 0xF8, 0xFF, 0x6F, 0x3F, 0xD2, 0x6F, 0x09,
+ 0xB4, 0x22, 0xF3, 0x30, 0xBE, 0xA9, 0x85, 0xCB, 0x9C, 0x8D, 0xF9, 0x8F,
+ 0xEB, 0x32, 0x91, 0xA2, 0x25, 0x84, 0x8F, 0xF5, 0xDC, 0xC7, 0x06, 0x9C,
+ 0x2D, 0xE5, 0x11, 0x2C, 0x09, 0x09, 0x87, 0x09, 0xA9, 0xF6, 0x33, 0x73,
+ 0x90, 0xF1, 0x60, 0xF2, 0x65, 0xDD, 0x30, 0xA5, 0x66, 0xCE, 0x62, 0x7B,
+ 0xD0, 0xF8, 0x2D, 0x3D, 0x19, 0x82, 0x77, 0xE3, 0x0A, 0x5F, 0x75, 0x2F,
+ 0x8E, 0xB1, 0xE5, 0xE8, 0x91, 0x35, 0x1B, 0x3B, 0x33, 0xB7, 0x66, 0x92,
+ 0xD1, 0xF2, 0x8E, 0x6F, 0xE5, 0x75, 0x0C, 0xAD, 0x36, 0xFB, 0x4E, 0xD0,
+ 0x66, 0x61, 0xBD, 0x49, 0xFE, 0xF4, 0x1A, 0xA2, 0x2B, 0x49, 0xFE, 0x03,
+ 0x4C, 0x74, 0x47, 0x8D, 0x9A, 0x66, 0xB2, 0x49, 0x46, 0x4D, 0x77, 0xEA,
+ 0x33, 0x4D, 0x6B, 0x3C, 0xB4, 0x49, 0x4A, 0xC6, 0x7D, 0x3D, 0xB5, 0xB9,
+ 0x56, 0x41, 0x15, 0x67, 0x0F, 0x94, 0x3C, 0x93, 0x65, 0x27, 0xE0, 0x21,
+ 0x5D, 0x59, 0xC3, 0x62, 0xD5, 0xA6, 0xDA, 0x38, 0x26, 0x22, 0x5E, 0x34,
+ 0x1C, 0x94, 0xAF, 0x98,
+};
+
+/* rsa_tv_template[3].key, modulus n */
+static const uint8_t rsa4096_n[512] = {
+ 0xC3, 0x8B, 0x55, 0x7B, 0x73, 0x4D, 0xFF, 0xE9, 0x9B, 0xC6, 0xDC, 0x67,
+ 0x3C, 0xB4, 0x8E, 0xA0, 0x86, 0xED, 0xF2, 0xB9, 0x50, 0x5C, 0x54, 0x5C,
+ 0xBA, 0xE4, 0xA1, 0xB2, 0xA7, 0xAE, 0x2F, 0x1B, 0x7D, 0xF1, 0xFB, 0xAC,
+ 0x79, 0xC5, 0xDF, 0x1A, 0x00, 0xC9, 0xB2, 0xC1, 0x61, 0x25, 0x33, 0xE6,
+ 0x9C, 0xE9, 0xCF, 0xD6, 0x27, 0xC4, 0x4E, 0x44, 0x30, 0x44, 0x5E, 0x08,
+ 0xA1, 0x87, 0x52, 0xCC, 0x6B, 0x97, 0x70, 0x8C, 0xBC, 0xA5, 0x06, 0x31,
+ 0x0C, 0xD4, 0x2F, 0xD5, 0x7D, 0x26, 0x24, 0xA2, 0xE2, 0xAC, 0x78, 0xF4,
+ 0x53, 0x14, 0xCE, 0xF7, 0x19, 0x2E, 0xD7, 0xF7, 0xE6, 0x0C, 0xB9, 0x56,
+ 0x7F, 0x0B, 0xF1, 0xB1, 0xE2, 0x43, 0x70, 0xBD, 0x86, 0x1D, 0xA1, 0xCC,
+ 0x2B, 0x19, 0x08, 0x76, 0xEF, 0x91, 0xAC, 0xBF, 0x20, 0x24, 0x0D, 0x38,
+ 0xC0, 0x89, 0xB8, 0x9A, 0x70, 0xB3, 0x64, 0xD9, 0x8F, 0x80, 0x41, 0x10,
+ 0x5B, 0x9F, 0xB1, 0xCB, 0x76, 0x43, 0x00, 0x21, 0x25, 0x36, 0xD4, 0x19,
+ 0xFC, 0x55, 0x95, 0x10, 0xE4, 0x26, 0x74, 0x98, 0x2C, 0xD9, 0xBD, 0x0B,
+ 0x2B, 0x04, 0xC2, 0xAC, 0x82, 0x38, 0xB4, 0xDD, 0x4C, 0x04, 0x7E, 0x51,
+ 0x36, 0x40, 0x1E, 0x0B, 0xC4, 0x7C, 0x25, 0xDD, 0x4B, 0xB2, 0xE7, 0x20,
+ 0x0A, 0x57, 0xF9, 0xB4, 0x94, 0xC3, 0x08, 0x33, 0x22, 0x6F, 0x8B, 0x48,
+ 0xDB, 0x03, 0x68, 0x5A, 0x5B, 0xBA, 0xAE, 0xF3, 0xAD, 0xCF, 0xC3, 0x6D,
+ 0xBA, 0xF1, 0x28, 0x67, 0x7E, 0x6C, 0x79, 0x07, 0xDE, 0xFC, 0xED, 0xE7,
+ 0x96, 0xE3, 0x6C, 0xE0, 0x2C, 0x87, 0xF8, 0x02, 0x01, 0x28, 0x38, 0x43,
+ 0x21, 0x53, 0x84, 0x69, 0x75, 0x78, 0x15, 0x7E, 0xEE, 0xD2, 0x1B, 0xB9,
+ 0x23, 0x40, 0xA8, 0x86, 0x1E, 0x38, 0x83, 0xB2, 0x73, 0x1D, 0x53, 0xFB,
+ 0x9E, 0x2A, 0x8A, 0xB2, 0x75, 0x35, 0x01, 0xC3, 0xC3, 0xC4, 0x94, 0xE8,
+ 0x84, 0x86, 0x64, 0x81, 0xF4, 0x42, 0xAA, 0x3C, 0x0E, 0xD6, 0x4F, 0xBC,
+ 0x0A, 0x09, 0x2D, 0xE7, 0x1B, 0xD4, 0x10, 0xA8, 0x54, 0xEA, 0x89, 0x84,
+ 0x8A, 0xCB, 0xF7, 0x5A, 0x3C, 0xCA, 0x76, 0x08, 0x29, 0x62, 0xB4, 0x6A,
+ 0x22, 0xDF, 0x14, 0x95, 0x71, 0xFD, 0xB6, 0x86, 0x39, 0xB8, 0x8B, 0xF8,
+ 0x91, 0x7F, 0x38, 0xAA, 0x14, 0xCD, 0xE5, 0xF5, 0x1D, 0xC2, 0x6D, 0x53,
+ 0x69, 0x52, 0x84, 0x7F, 0xA3, 0x1A, 0x5E, 0x26, 0x04, 0x83, 0x06, 0x73,
+ 0x52, 0x56, 0xCF, 0x76, 0x26, 0xC9, 0xDD, 0x75, 0xD7, 0xFC, 0xF4, 0x69,
+ 0xD8, 0x7B, 0x55, 0xB7, 0x68, 0x13, 0x53, 0xB9, 0xE7, 0x89, 0xC3, 0xE8,
+ 0xD6, 0x6E, 0xA7, 0x6D, 0xEA, 0x81, 0xFD, 0xC4, 0xB7, 0x05, 0x5A, 0xB7,
+ 0x41, 0x0A, 0x23, 0x8E, 0x03, 0x8A, 0x1C, 0xAE, 0xD3, 0x1E, 0xCE, 0xE3,
+ 0x5E, 0xFC, 0x19, 0x4A, 0xEE, 0x61, 0x9B, 0x8E, 0xE5, 0xE5, 0xDD, 0x85,
+ 0xF9, 0x41, 0xEC, 0x14, 0x53, 0x92, 0xF7, 0xDD, 0x06, 0x85, 0x02, 0x91,
+ 0xE3, 0xEB, 0x6C, 0x43, 0x03, 0xB1, 0x36, 0x7B, 0x89, 0x5A, 0xA8, 0xEB,
+ 0xFC, 0xD5, 0xA8, 0x35, 0xDC, 0x81, 0xD9, 0x5C, 0xBD, 0xCA, 0xDC, 0x9B,
+ 0x98, 0x0B, 0x06, 0x5D, 0x0C, 0x5B, 0xEE, 0xF3, 0xD5, 0xCC, 0x57, 0xC9,
+ 0x71, 0x2F, 0x90, 0x3B, 0x3C, 0xF0, 0x8E, 0x4E, 0x35, 0x48, 0xAE, 0x63,
+ 0x74, 0xA9, 0xFC, 0x72, 0x75, 0x8E, 0x34, 0xA8, 0xF2, 0x1F, 0xEA, 0xDF,
+ 0x3A, 0x37, 0x2D, 0xE5, 0x39, 0x39, 0xF8, 0x57, 0x58, 0x3C, 0x04, 0xFE,
+ 0x87, 0x06, 0x98, 0xBC, 0x7B, 0xD3, 0x21, 0x36, 0x60, 0x25, 0x54, 0xA7,
+ 0x3D, 0xFA, 0x91, 0xCC, 0xA8, 0x0B, 0x92, 0x8E, 0xB4, 0xF7, 0x06, 0xFF,
+ 0x1E, 0x95, 0xCB, 0x07, 0x76, 0x97, 0x3B, 0x9D,
+};
+/* rsa_tv_template[3].c */
+static const uint8_t rsa4096_c[512] = {
+ 0x5C, 0xCE, 0x9C, 0xD7, 0x9A, 0x9E, 0xA1, 0xFE, 0x7A, 0x82, 0x3C, 0x68,
+ 0x27, 0x98, 0xE3, 0x5D, 0xD5, 0xD7, 0x07, 0x29, 0xF5, 0xFB, 0xC3, 0x1A,
+ 0x7F, 0x63, 0x1E, 0x62, 0x31, 0x3B, 0x19, 0x87, 0x79, 0x4F, 0xEC, 0x7B,
+ 0xF3, 0xCB, 0xEA, 0x9B, 0x95, 0x52, 0x3A, 0x40, 0xE5, 0x87, 0x7B, 0x72,
+ 0xD1, 0x72, 0xC9, 0xFB, 0x54, 0x63, 0xD8, 0xC9, 0xD7, 0x2C, 0xFC, 0x7B,
+ 0xC3, 0x14, 0x1E, 0xBC, 0x18, 0xB4, 0x34, 0xA1, 0xBF, 0x14, 0xB1, 0x37,
+ 0x31, 0x6E, 0xF0, 0x1B, 0x35, 0x19, 0x54, 0x07, 0xF7, 0x99, 0xEC, 0x3E,
+ 0x63, 0xE2, 0xCD, 0x61, 0x28, 0x65, 0xC3, 0xCD, 0xB1, 0x38, 0x36, 0xA5,
+ 0xB2, 0xD7, 0xB0, 0xDC, 0x1F, 0xF5, 0xEF, 0x19, 0xC7, 0x53, 0x32, 0x2D,
+ 0x1C, 0x26, 0xDA, 0xE4, 0x0D, 0xD6, 0x90, 0x7E, 0x28, 0xD8, 0xDC, 0xE4,
+ 0x61, 0x05, 0xD2, 0x25, 0x90, 0x01, 0xD3, 0x96, 0x6D, 0xA6, 0xCF, 0x58,
+ 0x20, 0xBB, 0x03, 0xF4, 0x01, 0xBC, 0x79, 0xB9, 0x18, 0xD8, 0xB8, 0xBA,
+ 0xBD, 0x93, 0xFC, 0xF2, 0x62, 0x5D, 0x8C, 0x66, 0x1E, 0x0E, 0x84, 0x59,
+ 0x93, 0xDD, 0xE2, 0x93, 0xA2, 0x62, 0x7D, 0x08, 0x82, 0x7A, 0xDD, 0xFC,
+ 0xB8, 0xBC, 0xC5, 0x4F, 0x9C, 0x4E, 0xBF, 0xB4, 0xFC, 0xF4, 0xC5, 0x01,
+ 0xE8, 0x00, 0x70, 0x4D, 0x28, 0x26, 0xCC, 0x2E, 0xFE, 0x0E, 0x58, 0x41,
+ 0x8B, 0xEC, 0xAF, 0x7C, 0x4B, 0x54, 0xD0, 0xA0, 0x64, 0xF9, 0x32, 0xF4,
+ 0x2E, 0x47, 0x65, 0x0A, 0x67, 0x88, 0x39, 0x3A, 0xDB, 0xB2, 0xDB, 0x7B,
+ 0xB5, 0xF6, 0x17, 0xA8, 0xD9, 0xC6, 0x5E, 0x28, 0x13, 0x82, 0x8A, 0x99,
+ 0xDB, 0x60, 0x08, 0xA5, 0x23, 0x37, 0xFA, 0x88, 0x90, 0x31, 0xC8, 0x9D,
+ 0x8F, 0xEC, 0xFB, 0x85, 0x9F, 0xB1, 0xCE, 0xA6, 0x24, 0x50, 0x46, 0x44,
+ 0x47, 0xCB, 0x65, 0xD1, 0xDF, 0xC0, 0xB1, 0x6C, 0x90, 0x1F, 0x99, 0x8E,
+ 0x4D, 0xD5, 0x9E, 0x31, 0x07, 0x66, 0x87, 0xDF, 0x01, 0xAA, 0x56, 0x3C,
+ 0x71, 0xE0, 0x2B, 0x6F, 0x67, 0x3B, 0x23, 0xED, 0xC2, 0xBD, 0x03, 0x30,
+ 0x79, 0x76, 0x02, 0x10, 0x10, 0x98, 0x85, 0x8A, 0xFF, 0xFD, 0x0B, 0xDA,
+ 0xA5, 0xD9, 0x32, 0x48, 0x02, 0xA0, 0x0B, 0xB9, 0x2A, 0x8A, 0x18, 0xCA,
+ 0xC6, 0x8F, 0x3F, 0xBB, 0x16, 0xB2, 0xAA, 0x98, 0x27, 0xE3, 0x60, 0x43,
+ 0xED, 0x15, 0x70, 0xD4, 0x57, 0x15, 0xFE, 0x19, 0xD4, 0x9B, 0x13, 0x78,
+ 0x8A, 0xF7, 0x21, 0xF1, 0xA2, 0xA2, 0x2D, 0xB3, 0x09, 0xCF, 0x44, 0x91,
+ 0x6E, 0x08, 0x3A, 0x30, 0x81, 0x3E, 0x90, 0x93, 0x8A, 0x67, 0x33, 0x00,
+ 0x59, 0x54, 0x9A, 0x25, 0xD3, 0x49, 0x8E, 0x9F, 0xC1, 0x4B, 0xE5, 0x86,
+ 0xF3, 0x50, 0x4C, 0xBC, 0xC5, 0xD3, 0xF5, 0x3A, 0x54, 0xE1, 0x36, 0x3F,
+ 0xE2, 0x5A, 0xB4, 0x37, 0xC0, 0xEB, 0x70, 0x35, 0xEC, 0xF6, 0xB7, 0xE8,
+ 0x44, 0x3B, 0x7B, 0xF3, 0xF1, 0xF2, 0x1E, 0xDB, 0x60, 0x7D, 0xD5, 0xBE,
+ 0xF0, 0x71, 0x34, 0x90, 0x4C, 0xCB, 0xD4, 0x35, 0x51, 0xC7, 0xDD, 0xD8,
+ 0xC9, 0x81, 0xF5, 0x5D, 0x57, 0x46, 0x2C, 0xB1, 0x7B, 0x9B, 0xAA, 0xCB,
+ 0xD1, 0x22, 0x25, 0x49, 0x44, 0xA3, 0xD4, 0x6B, 0x29, 0x7B, 0xD8, 0xB2,
+ 0x07, 0x93, 0xBF, 0x3D, 0x52, 0x49, 0x84, 0x79, 0xEF, 0xB8, 0xE5, 0xC4,
+ 0xAD, 0xCA, 0xA8, 0xC6, 0xF6, 0xA6, 0x76, 0x70, 0x5B, 0x0B, 0xE5, 0x83,
+ 0xC6, 0x0E, 0xEF, 0x55, 0xF2, 0xE7, 0xFF, 0x04, 0xEA, 0xE6, 0x13, 0xBE,
+ 0x40, 0xE1, 0x40, 0x45, 0x48, 0x66, 0x75, 0x31, 0xAE, 0x35, 0x64, 0x91,
+ 0x11, 0x6F, 0xDA, 0xEE, 0x26, 0x86, 0x45, 0x6F, 0x0B, 0xD5, 0x9F, 0x03,
+ 0xB1, 0x65, 0x5B, 0xDB, 0xA4, 0xE4, 0xF9, 0x45,
+};
+
+/*
+ * Build the ACRY SRAM byte-offset lookup tables: exp_map[k] / mod_map[k] /
+ * data_map[k] give the offset in the scattered buffer of byte k
+ * (k = 0 = least significant) of the exponent / modulus / data. This is the
+ * byte layout the ACRY engine mandates, so the test lays out its DMA input
+ * and decodes the result buffer the same way the hardware does.
+ */
+static void acry_sram_mapping(uint32_t *exp_map, uint32_t *mod_map,
+ uint32_t *data_map)
+{
+ int byte_in_dword;
+ int block_base;
+ int op_dword;
+ int op_byte;
+ int block;
+ int lane;
+
+ for (op_byte = 0; op_byte < ACRY_DATA_MAX_LEN; op_byte++) {
+ op_dword = op_byte / 4;
+ byte_in_dword = op_byte % 4;
+ block = op_dword / 4;
+ lane = op_dword % 4;
+ block_base = block * 12;
+
+ /* exp starts each block; mod is +4 dwords, data +8 dwords. */
+ data_map[op_byte] = (block_base + 8 + lane) * 4 + byte_in_dword;
+ if (op_byte < ACRY_MAX_BYTES) {
+ exp_map[op_byte] = (block_base + 0 + lane) * 4 + byte_in_dword;
+ mod_map[op_byte] = (block_base + 4 + lane) * 4 + byte_in_dword;
+ }
+ }
+}
+
+/*
+ * Write a big-endian (most significant byte first) bignum of 'be_len'
+ * bytes into the region addressed by 'map' (exponent, modulus, or data),
+ * where map[k] gives the position in the scattered buffer of the
+ * byte at significance level k (k = 0 is the least significant byte).
+ */
+static void put_bignum_be_bytes(uint8_t *buf, const uint32_t *map,
+ const uint8_t *be, int be_len)
+{
+ int be_index;
+ int k;
+
+ /* be[0] (MSB) maps to the highest level; be_index walks up from 0. */
+ be_index = 0;
+ for (k = be_len - 1; k >= 0; k--) {
+ buf[map[k]] = be[be_index++];
+ }
+}
+
+/* Inverse of put_bignum_be_bytes(): gather a big-endian bignum back out. */
+static void get_bignum_be_bytes(const uint8_t *sram, const uint32_t *map,
+ uint8_t *out_be, int be_len)
+{
+ int be_index;
+ int k;
+
+ /* Inverse of put_bignum_be_bytes(): highest level -> out_be[0] (MSB). */
+ be_index = 0;
+ for (k = be_len - 1; k >= 0; k--) {
+ out_be[be_index++] = sram[map[k]];
+ }
+}
+
+typedef struct AspeedACRYModExp {
+ const char *name;
+ const uint8_t *n;
+ size_t n_len;
+ const uint8_t *e;
+ size_t e_len;
+ const uint8_t *m;
+ size_t m_len;
+ const uint8_t *c;
+ size_t c_len;
+} AspeedACRYModExp;
+
+static const AspeedACRYModExp acry_modexp_tests[] = {
+ {
+ .name = "modexp_rsa2048",
+ .n = rsa2048_n,
+ .n_len = sizeof(rsa2048_n),
+ .e = rsa_e,
+ .e_len = sizeof(rsa_e),
+ .m = rsa_m,
+ .m_len = sizeof(rsa_m),
+ .c = rsa2048_c,
+ .c_len = sizeof(rsa2048_c),
+ },
+ {
+ .name = "modexp_rsa4096",
+ .n = rsa4096_n,
+ .n_len = sizeof(rsa4096_n),
+ .e = rsa_e,
+ .e_len = sizeof(rsa_e),
+ .m = rsa_m,
+ .m_len = sizeof(rsa_m),
+ .c = rsa4096_c,
+ .c_len = sizeof(rsa4096_c),
+ },
+};
+
+/*
+ * One registered ACRY test: per-machine location (register base, result SRAM
+ * base, DRAM scratch) plus an index into acry_modexp_tests[]. Passed as the
+ * qtest_add_data_func_full() data pointer.
+ */
+typedef struct AspeedACRYTest {
+ const char *machine;
+ uint64_t dram_addr;
+ uint32_t sram_base;
+ uint32_t base;
+ int index;
+} AspeedACRYTest;
+
+static void test_modexp_rsa(const void *opaque)
+{
+ const AspeedACRYTest *c = opaque;
+ const AspeedACRYModExp *t = &acry_modexp_tests[c->index];
+ QTestState *qts = qtest_init(c->machine);
+ uint32_t data_map[ACRY_DATA_MAX_LEN];
+ uint8_t buf[ACRY_SRAM_SIZE] = { 0 };
+ uint32_t exp_map[ACRY_MAX_BYTES];
+ uint32_t mod_map[ACRY_MAX_BYTES];
+ uint8_t result[ACRY_MAX_BYTES];
+ uint8_t sram[ACRY_SRAM_SIZE];
+
+ g_assert_cmpuint(t->c_len, <=, sizeof(result));
+
+ acry_sram_mapping(exp_map, mod_map, data_map);
+
+ put_bignum_be_bytes(buf, exp_map, t->e, t->e_len);
+ put_bignum_be_bytes(buf, mod_map, t->n, t->n_len);
+ put_bignum_be_bytes(buf, data_map, t->m, t->m_len);
+
+ qtest_memwrite(qts, c->dram_addr, buf, sizeof(buf));
+
+ qtest_writel(qts, c->base + ACRY_DMA_CMD, ACRY_DMA_CMD_DMEM_AHB);
+ qtest_writel(qts, c->base + ACRY_DMA_SRC, c->dram_addr);
+ qtest_writel(qts, c->base + ACRY_RSA_KEY_LEN,
+ ((uint32_t)(t->e_len * 8) << 16) | (uint32_t)(t->n_len * 8));
+ qtest_writel(qts, c->base + ACRY_DMA_LEN, ACRY_SRAM_SIZE);
+ qtest_writel(qts, c->base + ACRY_INT_MASK,
+ ACRY_INT_MASK_RSA_ENG_MASK | ACRY_INT_MASK_RSA_DMA_MASK);
+ qtest_writel(qts, c->base + ACRY_DMA_CMD, ACRY_DMA_CMD_SRAM_MODE_RSA);
+ qtest_writel(qts, c->base + ACRY_TRIGGER,
+ ACRY_TRIGGER_RSA_START | ACRY_TRIGGER_RSA_DMA_DATA);
+
+ /* Completion requires both RSA_ENG_DONE and RSA_DMA_DONE to be asserted. */
+ g_assert_cmphex(qtest_readl(qts, c->base + ACRY_STATUS), ==,
+ ACRY_STATUS_RSA_DONE);
+
+ qtest_memread(qts, c->sram_base, sram, sizeof(sram));
+ get_bignum_be_bytes(sram, data_map, result, t->c_len);
+ g_assert_cmpmem(result, t->c_len, t->c, t->c_len);
+
+ /* Clear IRQ status and check it is deasserted */
+ qtest_writel(qts, c->base + ACRY_STATUS, ACRY_STATUS_RSA_DONE);
+ g_assert_cmphex(qtest_readl(qts, c->base + ACRY_STATUS), ==, 0);
+
+ qtest_quit(qts);
+}
+
+static void aspeed_add_acry_tests(const char *prefix, const char *machine,
+ uint32_t base, uint32_t sram_base,
+ uint64_t dram_addr)
+{
+ QCryptoAkCipherOptions opts = {
+ .alg = QCRYPTO_AK_CIPHER_ALGO_RSA,
+ .u.rsa.padding_alg = QCRYPTO_RSA_PADDING_ALGO_RAW,
+ };
+ int i;
+
+ if (!qcrypto_akcipher_supports(&opts)) {
+ g_printerr("# skip ACRY tests: raw RSA not supported by the crypto "
+ "backend\n");
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(acry_modexp_tests); i++) {
+ g_autofree char *path = NULL;
+ AspeedACRYTest *t;
+
+ path = g_strdup_printf("%s/acry/%s", prefix,
+ acry_modexp_tests[i].name);
+ t = g_new0(AspeedACRYTest, 1);
+ t->machine = machine;
+ t->base = base;
+ t->sram_base = sram_base;
+ t->dram_addr = dram_addr;
+ t->index = i;
+ qtest_add_data_func_full(path, t, test_modexp_rsa, g_free);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ g_test_init(&argc, &argv, NULL);
+
+ aspeed_add_acry_tests("ast2600", "-machine ast2600-evb",
+ 0x1e6fa000, 0x1e710000, 0x80000000 + 0x1000);
+
+ return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index f7c7d06620..c58be94c25 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -220,7 +220,8 @@ qtests_npcm7xx = \
qtests_npcm8xx = \
['npcm_gmac-test']
qtests_aspeed = \
- ['aspeed_gpio-test',
+ ['aspeed-acry-test',
+ 'aspeed_gpio-test',
'aspeed_hace-test',
'aspeed_scu-test',
'aspeed_smc-test']
@@ -392,6 +393,8 @@ if get_option('replication').allowed()
endif
qtests = {
+ 'aspeed-acry-test': [files('aspeed-acry-test.c'),
+ crypto],
'aspeed_hace-test': [files('aspeed-hace-utils.c', 'aspeed_hace-test.c'),
crypto],
'aspeed_smc-test': files('aspeed-smc-utils.c', 'aspeed_smc-test.c'),
--
2.43.0
prev parent reply other threads:[~2026-08-13 6:25 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-13 6:24 [PATCH v1 0/5] Add ASPEED ACRY RSA model for the AST2600 Jamin Lin
2026-08-13 6:24 ` [PATCH v1 1/5] hw/misc/aspeed_acry: Add ASPEED ACRY model Jamin Lin
2026-08-13 6:24 ` [PATCH v1 2/5] hw/arm/aspeed_ast2600: Introduce the ACRY SRAM Jamin Lin
2026-08-13 6:24 ` [PATCH v1 3/5] hw/arm/aspeed_soc: Add the ACRY model to AspeedSoCState Jamin Lin
2026-08-13 6:24 ` [PATCH v1 4/5] hw/arm/aspeed_ast2600: Wire up the ACRY model Jamin Lin
2026-08-13 6:24 ` Jamin Lin [this message]
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=20260813062359.425268-6-jamin_lin@aspeedtech.com \
--to=jamin_lin@aspeedtech.com \
--cc=andrew@codeconstruct.com.au \
--cc=clg@kaod.org \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.