QEMU-Devel 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 9/9] tests/qtest: Add ASPEED SBC ECDSA engine test
Date: Fri, 21 Aug 2026 03:20:49 +0000	[thread overview]
Message-ID: <20260821032036.1829294-10-jamin_lin@aspeedtech.com> (raw)
In-Reply-To: <20260821032036.1829294-1-jamin_lin@aspeedtech.com>

Add a qtest for the ASPEED secure boot controller ECDSA engine. It stages
the public key, signature and SHA-384 digest of a secp384r1 known-answer
vector (from the Linux kernel crypto self-test manager,
ecdsa_nist_p384_tv_template) into the SEC SRAM, triggers the engine's
verify command and checks the status register: a valid signature reports
done + pass, and a tampered signature reports done without pass.

The test is skipped when the crypto backend does not support ECDSA, via
qcrypto_akcipher_supports().

Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
---
 tests/qtest/aspeed-sbc-test.c | 193 ++++++++++++++++++++++++++++++++++
 tests/qtest/meson.build       |   2 +
 2 files changed, 195 insertions(+)
 create mode 100644 tests/qtest/aspeed-sbc-test.c

diff --git a/tests/qtest/aspeed-sbc-test.c b/tests/qtest/aspeed-sbc-test.c
new file mode 100644
index 0000000000..d67fe970e4
--- /dev/null
+++ b/tests/qtest/aspeed-sbc-test.c
@@ -0,0 +1,193 @@
+/*
+ * QTest testcase for the ASPEED Secure Boot Controller (SBC)
+ *
+ * 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"
+
+/* SBC register block */
+#define SBC_STATUS              0x014
+#define  SBC_ECDSA_VERIFY_PASS  BIT(21)
+#define  SBC_ECDSA_VERIFY_DONE  BIT(20)
+#define SBC_SEC_TRIGGER         0x0bc
+#define  SBC_ECDSA_CMD_TRIGGER  BIT(1)
+
+/*
+ * SEC SRAM operand offsets for a secp384r1 ECDSA verify. Every operand is a
+ * 48-byte big-endian integer.
+ */
+#define ECDSA_SRAM_QX   0x2080
+#define ECDSA_SRAM_QY   0x20c0
+#define ECDSA_SRAM_R    0x21c0
+#define ECDSA_SRAM_S    0x2200
+#define ECDSA_SRAM_M    0x2240
+
+/*
+ * ECDSA secp384r1 / SHA-384 known-answer vector from the Linux kernel crypto
+ * self-test manager (ecdsa_nist_p384_tv_template, sha384 entry in
+ * crypto/testmgr.h, v6.18), decoded into raw big-endian form: public key
+ * Qx || Qy, signature r || s and the SHA-384 message digest.
+ *
+ *   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/crypto/testmgr.h?h=v6.18
+ */
+static const uint8_t ecdsa_p384_pubkey[96] = {
+    /* Qx */
+    0x3a, 0x2f, 0x62, 0xe7, 0x1a, 0xcf, 0x24, 0xd0,
+    0x0b, 0x7c, 0xe0, 0xed, 0x46, 0x0a, 0x4f, 0x74,
+    0x16, 0x43, 0xe9, 0x1a, 0x25, 0x7c, 0x55, 0xff,
+    0xf0, 0x29, 0x68, 0x66, 0x20, 0x91, 0xf9, 0xdb,
+    0x2b, 0xf6, 0xb3, 0x6c, 0x54, 0x01, 0xca, 0xc7,
+    0x6a, 0x5c, 0x0d, 0xeb, 0x68, 0xd9, 0x3c, 0xf1,
+    /* Qy */
+    0x01, 0x74, 0x1f, 0xf9, 0x6c, 0xe5, 0x5b, 0x60,
+    0xe9, 0x7f, 0x5d, 0xb3, 0x12, 0x80, 0x2a, 0xd8,
+    0x67, 0x92, 0xc9, 0x0e, 0x4c, 0x4c, 0x6b, 0xa1,
+    0xb2, 0xa8, 0x1e, 0xac, 0x1c, 0x97, 0xd9, 0x21,
+    0x67, 0xe5, 0x1b, 0x5a, 0x52, 0x31, 0x68, 0xd6,
+    0xee, 0xf0, 0x19, 0xb0, 0x55, 0xed, 0x89, 0x9e,
+};
+
+static const uint8_t ecdsa_p384_signature[96] = {
+    /* r */
+    0x9b, 0x28, 0x68, 0xc0, 0xa1, 0xea, 0x8c, 0x50,
+    0xee, 0x2e, 0x62, 0x35, 0x46, 0xfa, 0x00, 0xd8,
+    0x2d, 0x7a, 0x91, 0x5f, 0x49, 0x2d, 0x22, 0x08,
+    0x29, 0xe6, 0xfb, 0xca, 0x8c, 0xd6, 0xb6, 0xb4,
+    0x3b, 0x1f, 0x07, 0x8f, 0x15, 0x02, 0xfe, 0x1d,
+    0xa2, 0xa4, 0xc8, 0xf2, 0xea, 0x9d, 0x11, 0x1f,
+    /* s */
+    0xfc, 0x50, 0xf6, 0x43, 0xbd, 0x50, 0x82, 0x0e,
+    0xbf, 0xe3, 0x75, 0x24, 0x49, 0xac, 0xfb, 0xc8,
+    0x71, 0xcd, 0x8f, 0x18, 0x99, 0xf0, 0x0f, 0x13,
+    0x44, 0x92, 0x8c, 0x86, 0x99, 0x65, 0xb3, 0x97,
+    0x96, 0x17, 0x04, 0xc9, 0x05, 0x77, 0xf1, 0x8e,
+    0xab, 0x8d, 0x4e, 0xde, 0xe6, 0x6d, 0x9b, 0x66,
+};
+
+static const uint8_t ecdsa_p384_dgst[48] = {
+    0x8d, 0xf2, 0xc0, 0xe9, 0xa8, 0xf3, 0x8e, 0x44,
+    0xc4, 0x8c, 0x1a, 0xa0, 0xb8, 0xd7, 0x17, 0xdf,
+    0xf2, 0x37, 0x1b, 0xc6, 0xe3, 0xf5, 0x62, 0xcc,
+    0x68, 0xf5, 0xd5, 0x0b, 0xbf, 0x73, 0x2b, 0xb1,
+    0xb0, 0x4c, 0x04, 0x00, 0x31, 0xab, 0xfe, 0xc8,
+    0xd6, 0x09, 0xc8, 0xf2, 0xea, 0xd3, 0x28, 0xff,
+};
+
+typedef struct AspeedSBCECDSA {
+    const char *name;
+    QCryptoCurveID curve_id;
+    const uint8_t *pubkey;
+    const uint8_t *signature;
+    const uint8_t *dgst;
+    size_t coord_len;
+} AspeedSBCECDSA;
+
+static const AspeedSBCECDSA sbc_ecdsa_tests[] = {
+    {
+        .name = "secp384r1",
+        .curve_id = QCRYPTO_CURVE_ID_SECP384R1,
+        .pubkey = ecdsa_p384_pubkey,
+        .signature = ecdsa_p384_signature,
+        .dgst = ecdsa_p384_dgst,
+        .coord_len = 48,
+    },
+};
+
+typedef struct AspeedSBCTest {
+    const char *machine;
+    uint32_t sec_addr;
+    uint64_t sram_addr;
+    int index;
+} AspeedSBCTest;
+
+static void sbc_ecdsa_stage(QTestState *qts, const AspeedSBCTest *c,
+                            const AspeedSBCECDSA *t)
+{
+    uint32_t len = t->coord_len;
+
+    qtest_memwrite(qts, c->sram_addr + ECDSA_SRAM_QX, t->pubkey, len);
+    qtest_memwrite(qts, c->sram_addr + ECDSA_SRAM_QY, t->pubkey + len, len);
+    qtest_memwrite(qts, c->sram_addr + ECDSA_SRAM_R, t->signature, len);
+    qtest_memwrite(qts, c->sram_addr + ECDSA_SRAM_S, t->signature + len, len);
+    qtest_memwrite(qts, c->sram_addr + ECDSA_SRAM_M, t->dgst, len);
+}
+
+/*
+ * Drive one ECDSA verify through the engine the way the firmware does:
+ * stage the operands in the SEC SRAM, trigger the command register and read
+ * back the done/pass bits in the status register.
+ */
+static void test_ecdsa_verify(const void *opaque)
+{
+    const AspeedSBCTest *c = opaque;
+    const AspeedSBCECDSA *t = &sbc_ecdsa_tests[c->index];
+    QTestState *qts = qtest_init(c->machine);
+    uint32_t status;
+    uint8_t bad;
+
+    /* A valid signature verifies */
+    sbc_ecdsa_stage(qts, c, t);
+    qtest_writel(qts, c->sec_addr + SBC_SEC_TRIGGER, SBC_ECDSA_CMD_TRIGGER);
+    status = qtest_readl(qts, c->sec_addr + SBC_STATUS);
+    g_assert_cmphex(status & (SBC_ECDSA_VERIFY_DONE | SBC_ECDSA_VERIFY_PASS),
+                    ==, SBC_ECDSA_VERIFY_DONE | SBC_ECDSA_VERIFY_PASS);
+
+    /* A tampered signature must fail */
+    bad = t->signature[0] ^ 0xff;
+    qtest_memwrite(qts, c->sram_addr + ECDSA_SRAM_R, &bad, 1);
+    qtest_writel(qts, c->sec_addr + SBC_SEC_TRIGGER, SBC_ECDSA_CMD_TRIGGER);
+    status = qtest_readl(qts, c->sec_addr + SBC_STATUS);
+    g_assert_cmphex(status & SBC_ECDSA_VERIFY_DONE, ==, SBC_ECDSA_VERIFY_DONE);
+    g_assert_cmphex(status & SBC_ECDSA_VERIFY_PASS, ==, 0);
+
+    qtest_quit(qts);
+}
+
+static void aspeed_add_sbc_ecdsa_tests(const char *prefix, const char *machine,
+                                       uint32_t sec_addr, uint64_t sram_addr)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(sbc_ecdsa_tests); i++) {
+        QCryptoAkCipherOptions opts = {
+            .alg = QCRYPTO_AK_CIPHER_ALGO_ECDSA,
+            .u.ecdsa.curve_id = sbc_ecdsa_tests[i].curve_id,
+        };
+        g_autofree char *path = NULL;
+        AspeedSBCTest *t;
+
+        if (!qcrypto_akcipher_supports(&opts)) {
+            g_printerr("# skip SBC ECDSA %s test: not supported by the crypto "
+                       "backend\n", sbc_ecdsa_tests[i].name);
+            continue;
+        }
+
+        path = g_strdup_printf("%s/sbc/ecdsa/%s", prefix,
+                               sbc_ecdsa_tests[i].name);
+        t = g_new0(AspeedSBCTest, 1);
+        t->machine = machine;
+        t->sec_addr = sec_addr;
+        t->sram_addr = sram_addr;
+        t->index = i;
+        qtest_add_data_func_full(path, t, test_ecdsa_verify, g_free);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    g_test_init(&argc, &argv, NULL);
+
+    aspeed_add_sbc_ecdsa_tests("ast1030", "-machine ast1030-evb",
+                               0x7e6f2000, 0x79000000);
+
+    aspeed_add_sbc_ecdsa_tests("ast1060", "-machine ast1060-evb",
+                               0x7e6f2000, 0x79000000);
+
+    return g_test_run();
+}
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index c58be94c25..13de12da02 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -223,6 +223,7 @@ qtests_aspeed = \
   ['aspeed-acry-test',
    'aspeed_gpio-test',
    'aspeed_hace-test',
+   'aspeed-sbc-test',
    'aspeed_scu-test',
    'aspeed_smc-test']
 qtests_aspeed64 = \
@@ -397,6 +398,7 @@ qtests = {
                        crypto],
   'aspeed_hace-test': [files('aspeed-hace-utils.c', 'aspeed_hace-test.c'),
                        crypto],
+  'aspeed-sbc-test': [files('aspeed-sbc-test.c'), crypto],
   'aspeed_smc-test': files('aspeed-smc-utils.c', 'aspeed_smc-test.c'),
   'ast2700-hace-test': [files('aspeed-hace-utils.c', 'ast2700-hace-test.c'),
                         crypto],
-- 
2.53.0


      parent reply	other threads:[~2026-08-21  3:21 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-21  3:20 [PATCH v2 0/9] Add ECDSA akcipher support and the ASPEED SBC ECDSA engine for AST10x0 Jamin Lin
2026-08-21  3:20 ` [PATCH v2 1/9] qapi/crypto: Add ECDSA algorithm and curve id Jamin Lin
2026-08-21  3:20 ` [PATCH v2 2/9] crypto/akcipher: Support ECDSA sign/verify with gcrypt Jamin Lin
2026-08-21  3:20 ` [PATCH v2 3/9] crypto/akcipher: Support ECDSA sign/verify with nettle Jamin Lin
2026-08-21  3:20 ` [PATCH v2 4/9] hw/arm/aspeed_ast10x0: Remove obsolete unimplemented SBC mapping Jamin Lin
2026-08-21  3:20 ` [PATCH v2 5/9] tests/crypto: Add ECDSA sign/verify tests Jamin Lin
2026-08-21  3:20 ` [PATCH v2 6/9] hw/misc/aspeed_sbc: Support the ECDSA verify command Jamin Lin
2026-08-21  3:20 ` [PATCH v2 7/9] hw/misc/aspeed_sbc: Increase register space to 0x1000 Jamin Lin
2026-08-21  3:20 ` [PATCH v2 8/9] hw/arm/aspeed_ast10x0: Wire SEC SRAM to the SBC model Jamin Lin
2026-08-21  3:20 ` 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=20260821032036.1829294-10-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