From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 7F06AC79FA0 for ; Sun, 6 Sep 2026 17:11:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x3GOU-0003X4-Br; Sun, 06 Sep 2026 13:11:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x3GOS-0003Vm-Q0 for qemu-devel@nongnu.org; Sun, 06 Sep 2026 13:11:00 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x3GOP-00006v-La for qemu-devel@nongnu.org; Sun, 06 Sep 2026 13:11:00 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1788714657; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=VxMns5b/U2UBfJZRgiyQW37wk+fWiykanxOBnLBoJkI=; b=jHBbEIue3JexARdXE8UmtMglexaJN3MjigoRTsak72Yf5piUrwhDo3oHbmPo4DYChFMMfu TYzTGHyOSXqXGnc0pH5/4iD8mlCGmCzGzbuiZQr4K0lN3UbbAqRXoiDdusYGzdnQpuZ9bX usqp6AXGYhn9XFkiH+lgB6XRyjgpoFA= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-155-cZ6dJ2UbOkarsapf1N8DbQ-1; Sun, 06 Sep 2026 13:10:53 -0400 X-MC-Unique: cZ6dJ2UbOkarsapf1N8DbQ-1 X-Mimecast-MFC-AGG-ID: cZ6dJ2UbOkarsapf1N8DbQ_1788714652 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9800B1800D9D; Sun, 6 Sep 2026 17:10:52 +0000 (UTC) Received: from yukon.redhat.com (unknown [10.44.32.24]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id F23EE1955F06; Sun, 6 Sep 2026 17:10:50 +0000 (UTC) From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= To: qemu-arm@nongnu.org, qemu-devel@nongnu.org Cc: Jamin Lin , =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Subject: [PULL 11/40] tests/qtest/aspeed-acry-test: Add RSA ModExp tests Date: Sun, 6 Sep 2026 19:09:52 +0200 Message-ID: <20260906171021.26568-12-clg@redhat.com> In-Reply-To: <20260906171021.26568-1-clg@redhat.com> References: <20260906171021.26568-1-clg@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Received-SPF: pass client-ip=170.10.129.124; envelope-from=clg@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.01, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org From: Jamin Lin 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-bit and 4096-bit vectors are rsa_tv_template[2] and [3] from the Linux kernel crypto self-test suite (crypto/testmgr.h, v6.18). Signed-off-by: Jamin Lin Reviewed-by: Cédric Le Goater Link: https://lore.kernel.org/qemu-devel/20260901081531.898176-5-jamin_lin@aspeedtech.com Signed-off-by: Cédric Le Goater --- tests/qtest/aspeed-acry-test.c | 406 +++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 5 +- 2 files changed, 410 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 000000000000..ec348c220664 --- /dev/null +++ b/tests/qtest/aspeed-acry-test.c @@ -0,0 +1,406 @@ +/* + * 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_DMA_DATA BIT(1) +#define ACRY_TRIGGER_RSA_START BIT(0) +#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_DMA_MASK BIT(2) +#define ACRY_INT_MASK_RSA_ENG_MASK BIT(1) +#define ACRY_STATUS 0x3FC +#define ACRY_STATUS_RSA_DMA_DONE BIT(2) +#define ACRY_STATUS_RSA_ENG_DONE BIT(1) +#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) + +#define ACRY_BYTES_PER_DWORD 4 +#define ACRY_LANES_PER_BLOCK 4 +/* Each block holds 3 regions (exp, mod, data) of LANES_PER_BLOCK dwords. */ +#define ACRY_DWORDS_PER_BLOCK (3 * ACRY_LANES_PER_BLOCK) + +/* Dwords into each block where each operand's region starts. */ +#define ACRY_EXP_OFFSET (0 * ACRY_LANES_PER_BLOCK) +#define ACRY_MOD_OFFSET (1 * ACRY_LANES_PER_BLOCK) +#define ACRY_DATA_OFFSET (2 * ACRY_LANES_PER_BLOCK) + +/* + * 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, +}; + +/* + * Offset in the scattered buffer of byte 'op_byte' (0 = least significant) + * of the operand whose region starts 'region' dwords into each 12-dword + * block (0 = exp, 4 = mod, 8 = data). Reproduces the byte layout the ACRY + * engine mandates, so the test lays out its DMA input and decodes the + * result the same way the hardware does. + */ +static int acry_operand_offset(int region, int op_byte) +{ + int byte_in_dword; + int op_dword; + int offset; + int block; + int lane; + + op_dword = op_byte / ACRY_BYTES_PER_DWORD; + byte_in_dword = op_byte % ACRY_BYTES_PER_DWORD; + block = op_dword / ACRY_LANES_PER_BLOCK; + lane = op_dword % ACRY_LANES_PER_BLOCK; + + offset = (block * ACRY_DWORDS_PER_BLOCK + region + lane) + * ACRY_BYTES_PER_DWORD + byte_in_dword; + g_assert_cmpint(offset, <, ACRY_SRAM_SIZE); + + return offset; +} + +/* + * Write a big-endian (most significant byte first) bignum of 'be_len' bytes + * into the scattered buffer region 'region' (exp, mod, or data), placing + * significance level k at acry_operand_offset(region, k). + */ +static void put_bignum_be_bytes(uint8_t *buf, int region, + const uint8_t *be, int be_len) +{ + int be_index; + int offset; + 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--) { + offset = acry_operand_offset(region, k); + buf[offset] = 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 *buf, int region, + uint8_t *out_be, int be_len) +{ + int be_index; + int offset; + 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--) { + offset = acry_operand_offset(region, k); + out_be[be_index++] = buf[offset]; + } +} + +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), + }, +}; + +typedef struct AspeedACRYTest { + const char *machine; + uint64_t dram_addr; + uint64_t sram_addr; + uint64_t acry_addr; + int index; +} AspeedACRYTest; + +static void test_modexp_rsa(const void *opaque) +{ + const AspeedACRYTest *c = opaque; + const AspeedACRYModExp *t = &acry_modexp_tests[c->index]; + QCryptoAkCipherOptions opts = { + .alg = QCRYPTO_AK_CIPHER_ALGO_RSA, + .u.rsa.padding_alg = QCRYPTO_RSA_PADDING_ALGO_RAW, + }; + uint8_t dram_buf[ACRY_SRAM_SIZE] = { 0 }; + uint8_t sram_buf[ACRY_SRAM_SIZE] = { 0 }; + uint8_t result[ACRY_MAX_BYTES] = { 0 }; + QTestState *qts; + + if (!qcrypto_akcipher_supports(&opts)) { + g_test_skip("raw RSA not supported by the crypto backend"); + return; + } + + qts = qtest_init(c->machine); + + g_assert_cmpuint(t->c_len, <=, sizeof(result)); + + put_bignum_be_bytes(dram_buf, ACRY_EXP_OFFSET, t->e, t->e_len); + put_bignum_be_bytes(dram_buf, ACRY_MOD_OFFSET, t->n, t->n_len); + put_bignum_be_bytes(dram_buf, ACRY_DATA_OFFSET, t->m, t->m_len); + + qtest_memwrite(qts, c->dram_addr, dram_buf, sizeof(dram_buf)); + + qtest_writel(qts, c->acry_addr + ACRY_DMA_CMD, ACRY_DMA_CMD_DMEM_AHB); + qtest_writel(qts, c->acry_addr + ACRY_DMA_SRC, c->dram_addr); + qtest_writel(qts, c->acry_addr + ACRY_RSA_KEY_LEN, + ((uint32_t)(t->e_len * 8) << 16) | (uint32_t)(t->n_len * 8)); + qtest_writel(qts, c->acry_addr + ACRY_DMA_LEN, ACRY_SRAM_SIZE); + qtest_writel(qts, c->acry_addr + ACRY_INT_MASK, + ACRY_INT_MASK_RSA_ENG_MASK | ACRY_INT_MASK_RSA_DMA_MASK); + qtest_writel(qts, c->acry_addr + ACRY_DMA_CMD, ACRY_DMA_CMD_SRAM_MODE_RSA); + qtest_writel(qts, c->acry_addr + 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->acry_addr + ACRY_STATUS), ==, + ACRY_STATUS_RSA_DONE); + + qtest_memread(qts, c->sram_addr, sram_buf, sizeof(sram_buf)); + get_bignum_be_bytes(sram_buf, ACRY_DATA_OFFSET, 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->acry_addr + ACRY_STATUS, ACRY_STATUS_RSA_DONE); + g_assert_cmphex(qtest_readl(qts, c->acry_addr + ACRY_STATUS), ==, 0); + + qtest_quit(qts); +} + +static void aspeed_add_acry_tests(const char *prefix, const char *machine, + uint64_t acry_addr, uint64_t sram_addr, + uint64_t dram_addr) +{ + int i; + + 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->acry_addr = acry_addr; + t->sram_addr = sram_addr; + 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, 0x80001000); + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 17870e339b4c..6e7ffcdbd09c 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -230,7 +230,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'] @@ -402,6 +403,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.55.0