summaryrefslogtreecommitdiff
path: root/tests/unit
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2026-09-07 13:33:12 +0100
committerPeter Maydell <peter.maydell@linaro.org>2026-09-07 13:33:12 +0100
commit35500e5c41aec76cde59befe750600dac7a9e37a (patch)
tree108af14ab7700f9c29bc0b7ba8f513fbc5bace8a /tests/unit
parent61e537b7ef2f8b899827c72126cada6161e5803d (diff)
parent1c05d7e94da04129ea16147074fe73158fb85ff9 (diff)
downloadqemu-master.tar.gz
qemu-master.zip
Merge tag 'pull-aspeed-20260906' of https://github.com/legoater/qemu into stagingHEADmaster
aspeed queue: * Fixes AST2600 SCU protection key registers on reset * Fixes I2C byte latching for SMBus block reads * Hardens EHCI get_dwords()/put_dwords() with DMA error checking * Adds a second random number generator to the AST2600 SCU * Adds the ASPEED ACRY RSA accelerator model with ModExp qtest coverage * Adds ECDSA sign/verify support to the QEMU crypto akcipher layer (gcrypt, nettle backends) with tests * Adds ECDSA verify command to the ASPEED SBC model with qtest coverage * Adds the ASPEED UDC (USB Device Controller) with gadget device and programmable endpoint DMA, wired on the AST2600 * Reworks the TMP105 temperature sensor: Resettable reset, fault queue enforcement, TMP75/TMP175/LM75B variants, and qtest coverage * Adds the Facebook SanMiguel BMC machine with EEPROM data * Uses real TMP75/LM75B models on the Catalina and Fuji boards * Adds optional device tree model checking to functional boot tests # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmqdnl8ACgkQUaNDx8/7 # 7KGMzxAAgxO09nzutoyjvMRK+Tydd65h9TNxZTC68jzUjacGfU9Y+1+1OcgU25D1 # EUorhMrAGMe22zZ6Q6048HjBmw/xRxt4QB6A5CGIroSgVqQH6NAFalZz5jeCwZrm # HMk2UAzf0/2euBAXRUFEtK/RpfdrSe1kNXcRX2lWkt5HdjfZJxcM/TmOtLl0vDDU # BUMbmXLWvnv/W8OLiVmGwP8ufGey2HL2dsLn2Fs9riFF1ZUaJGFkKxEc7ApF6tOr # 0YaY84lainh21Bp+IjXaV2Al8XCyyHpWKFrEYLEm9P3FfMEebIZbJu8he20cidiw # R5LIgHpb6FcUZvVcfWyAfYK1+yRQDrL9PMQ8OdbiUgtW1WnvqSyQES4GWx55OmPc # TSRDodPnETxF26n43ruIWdIGa6umgieT891UrI3CsCYc7JpSpujCgMiob6sLWjFD # h65DNECnSl3qkK8kIneEhUK9MVIX62YskqAWkIF7rwy+Af7QkCcWuMKTGIpC+a/l # H7SjxPWwy1XW9B+4dhF3teYxqb8iETM0BQwr2ZuAp3mbB/YkTMaIj5TfUpiGrClz # RdkSc2njjqbeyQZSTV1P+M8cpWBYiHRJNhx58rH6qIpH6ATSZZAym6XCZV2wZDtU # VJ7TwnOObQMogMp/9iThUd4jEtCcmEp1dxXF/KKXADso6EU6+Do= # =sX4J # -----END PGP SIGNATURE----- # gpg: Signature made Sun Sep 6 18:09:51 2026 BST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full] # gpg: aka "Cédric Le Goater <clg@kaod.org>" [full] # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-aspeed-20260906' of https://github.com/legoater/qemu: (40 commits) tests/functional: aspeed: optionally check the device tree model on boot hw/arm: fuji: use the real TMP75 and LM75B temperature sensors hw/arm: catalina: use the real TMP75 model hw/arm: sanmiguel: populate EEPROM data hw/arm: sanmiguel: add Facebook SanMiguel BMC machine tests/qtest: tmp105: cover shutdown clearing the ALERT across variants tests/qtest: tmp105: cover one-shot and fault-queue write immunity tests/qtest: tmp105: cover the TMP75, TMP175 and LM75B variants tests/qtest: tmp105: cover the ALERT fault queue hw/sensor: tmp105: add TMP75, TMP175 and LM75B variants hw/arm: aspeed: guard board-local temperature-sensor aliases hw/sensor: tmp105: describe the temperature property hw/sensor: tmp105: enforce the configurable fault queue hw/sensor: tmp105: implement Resettable reset hw/sensor: tmp105: name the parent object field parent_obj hw/sensor: tmp105: make device state private to the implementation hw/arm/aspeed_ast2600: Wire up the UDC hw/usb/aspeed-udc: Add programmable endpoint DMA transfers hw/usb/aspeed-udc: Add ASPEED UDC gadget USB device hw/usb/aspeed-udc: Add ASPEED UDC device controller ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'tests/unit')
-rw-r--r--tests/unit/test-crypto-akcipher.c236
1 files changed, 236 insertions, 0 deletions
diff --git a/tests/unit/test-crypto-akcipher.c b/tests/unit/test-crypto-akcipher.c
index 53c2211ba8..fb1a6163e9 100644
--- a/tests/unit/test-crypto-akcipher.c
+++ b/tests/unit/test-crypto-akcipher.c
@@ -658,6 +658,117 @@ static const uint8_t rsa_public_key_extra_elem[] = {
0x02, 0x06, 0xe1, 0x22, 0xdb, 0xe1, 0x22, 0xdb,
};
+/*
+ * ECDSA known-answer vectors from RFC 6979 (Deterministic ECDSA), message
+ * "sample", decoded into raw big-endian form. The same key pair drives both
+ * the verify test (against the RFC's known signature) and the sign round-trip
+ * test:
+ * - private key: the scalar d (curve size)
+ * - public key: Qx || Qy (2 * curve size)
+ * - dgst: the message digest (curve size)
+ * - signature: r || s (2 * curve size)
+ *
+ * prime256v1 / SHA-256 (RFC 6979 A.2.5):
+ */
+static const uint8_t ecdsa_p256_privkey[32] = {
+ 0xc9, 0xaf, 0xa9, 0xd8, 0x45, 0xba, 0x75, 0x16,
+ 0x6b, 0x5c, 0x21, 0x57, 0x67, 0xb1, 0xd6, 0x93,
+ 0x4e, 0x50, 0xc3, 0xdb, 0x36, 0xe8, 0x9b, 0x12,
+ 0x7b, 0x8a, 0x62, 0x2b, 0x12, 0x0f, 0x67, 0x21,
+};
+
+static const uint8_t ecdsa_p256_pubkey[64] = {
+ 0x60, 0xfe, 0xd4, 0xba, 0x25, 0x5a, 0x9d, 0x31,
+ 0xc9, 0x61, 0xeb, 0x74, 0xc6, 0x35, 0x6d, 0x68,
+ 0xc0, 0x49, 0xb8, 0x92, 0x3b, 0x61, 0xfa, 0x6c,
+ 0xe6, 0x69, 0x62, 0x2e, 0x60, 0xf2, 0x9f, 0xb6,
+ 0x79, 0x03, 0xfe, 0x10, 0x08, 0xb8, 0xbc, 0x99,
+ 0xa4, 0x1a, 0xe9, 0xe9, 0x56, 0x28, 0xbc, 0x64,
+ 0xf2, 0xf1, 0xb2, 0x0c, 0x2d, 0x7e, 0x9f, 0x51,
+ 0x77, 0xa3, 0xc2, 0x94, 0xd4, 0x46, 0x22, 0x99,
+};
+
+static const uint8_t ecdsa_p256_dgst[32] = {
+ 0xaf, 0x2b, 0xdb, 0xe1, 0xaa, 0x9b, 0x6e, 0xc1,
+ 0xe2, 0xad, 0xe1, 0xd6, 0x94, 0xf4, 0x1f, 0xc7,
+ 0x1a, 0x83, 0x1d, 0x02, 0x68, 0xe9, 0x89, 0x15,
+ 0x62, 0x11, 0x3d, 0x8a, 0x62, 0xad, 0xd1, 0xbf,
+};
+
+static const uint8_t ecdsa_p256_signature[64] = {
+ 0xef, 0xd4, 0x8b, 0x2a, 0xac, 0xb6, 0xa8, 0xfd,
+ 0x11, 0x40, 0xdd, 0x9c, 0xd4, 0x5e, 0x81, 0xd6,
+ 0x9d, 0x2c, 0x87, 0x7b, 0x56, 0xaa, 0xf9, 0x91,
+ 0xc3, 0x4d, 0x0e, 0xa8, 0x4e, 0xaf, 0x37, 0x16,
+ 0xf7, 0xcb, 0x1c, 0x94, 0x2d, 0x65, 0x7c, 0x41,
+ 0xd4, 0x36, 0xc7, 0xa1, 0xb6, 0xe2, 0x9f, 0x65,
+ 0xf3, 0xe9, 0x00, 0xdb, 0xb9, 0xaf, 0xf4, 0x06,
+ 0x4d, 0xc4, 0xab, 0x2f, 0x84, 0x3a, 0xcd, 0xa8,
+};
+
+/* secp384r1 / SHA-384 (RFC 6979 A.2.6): */
+static const uint8_t ecdsa_p384_privkey[48] = {
+ 0x6b, 0x9d, 0x3d, 0xad, 0x2e, 0x1b, 0x8c, 0x1c,
+ 0x05, 0xb1, 0x98, 0x75, 0xb6, 0x65, 0x9f, 0x4d,
+ 0xe2, 0x3c, 0x3b, 0x66, 0x7b, 0xf2, 0x97, 0xba,
+ 0x9a, 0xa4, 0x77, 0x40, 0x78, 0x71, 0x37, 0xd8,
+ 0x96, 0xd5, 0x72, 0x4e, 0x4c, 0x70, 0xa8, 0x25,
+ 0xf8, 0x72, 0xc9, 0xea, 0x60, 0xd2, 0xed, 0xf5,
+};
+
+static const uint8_t ecdsa_p384_pubkey[96] = {
+ 0xec, 0x3a, 0x4e, 0x41, 0x5b, 0x4e, 0x19, 0xa4,
+ 0x56, 0x86, 0x18, 0x02, 0x9f, 0x42, 0x7f, 0xa5,
+ 0xda, 0x9a, 0x8b, 0xc4, 0xae, 0x92, 0xe0, 0x2e,
+ 0x06, 0xaa, 0xe5, 0x28, 0x6b, 0x30, 0x0c, 0x64,
+ 0xde, 0xf8, 0xf0, 0xea, 0x90, 0x55, 0x86, 0x60,
+ 0x64, 0xa2, 0x54, 0x51, 0x54, 0x80, 0xbc, 0x13,
+ 0x80, 0x15, 0xd9, 0xb7, 0x2d, 0x7d, 0x57, 0x24,
+ 0x4e, 0xa8, 0xef, 0x9a, 0xc0, 0xc6, 0x21, 0x89,
+ 0x67, 0x08, 0xa5, 0x93, 0x67, 0xf9, 0xdf, 0xb9,
+ 0xf5, 0x4c, 0xa8, 0x4b, 0x3f, 0x1c, 0x9d, 0xb1,
+ 0x28, 0x8b, 0x23, 0x1c, 0x3a, 0xe0, 0xd4, 0xfe,
+ 0x73, 0x44, 0xfd, 0x25, 0x33, 0x26, 0x47, 0x20,
+};
+
+static const uint8_t ecdsa_p384_dgst[48] = {
+ 0x9a, 0x90, 0x83, 0x50, 0x5b, 0xc9, 0x22, 0x76,
+ 0xae, 0xc4, 0xbe, 0x31, 0x26, 0x96, 0xef, 0x7b,
+ 0xf3, 0xbf, 0x60, 0x3f, 0x4b, 0xbd, 0x38, 0x11,
+ 0x96, 0xa0, 0x29, 0xf3, 0x40, 0x58, 0x53, 0x12,
+ 0x31, 0x3b, 0xca, 0x4a, 0x9b, 0x5b, 0x89, 0x0e,
+ 0xfe, 0xe4, 0x2c, 0x77, 0xb1, 0xee, 0x25, 0xfe,
+};
+
+static const uint8_t ecdsa_p384_signature[96] = {
+ 0x94, 0xed, 0xbb, 0x92, 0xa5, 0xec, 0xb8, 0xaa,
+ 0xd4, 0x73, 0x6e, 0x56, 0xc6, 0x91, 0x91, 0x6b,
+ 0x3f, 0x88, 0x14, 0x06, 0x66, 0xce, 0x9f, 0xa7,
+ 0x3d, 0x64, 0xc4, 0xea, 0x95, 0xad, 0x13, 0x3c,
+ 0x81, 0xa6, 0x48, 0x15, 0x2e, 0x44, 0xac, 0xf9,
+ 0x6e, 0x36, 0xdd, 0x1e, 0x80, 0xfa, 0xbe, 0x46,
+ 0x99, 0xef, 0x4a, 0xeb, 0x15, 0xf1, 0x78, 0xce,
+ 0xa1, 0xfe, 0x40, 0xdb, 0x26, 0x03, 0x13, 0x8f,
+ 0x13, 0x0e, 0x74, 0x0a, 0x19, 0x62, 0x45, 0x26,
+ 0x20, 0x3b, 0x63, 0x51, 0xd0, 0xa3, 0xa9, 0x4f,
+ 0xa3, 0x29, 0xc1, 0x45, 0x78, 0x6e, 0x67, 0x9e,
+ 0x7b, 0x82, 0xc7, 0x1a, 0x38, 0x62, 0x8a, 0xc8,
+};
+
+typedef struct QCryptoECDSATestData QCryptoECDSATestData;
+struct QCryptoECDSATestData {
+ const char *path;
+ QCryptoCurveID curve_id;
+ const uint8_t *priv_key;
+ size_t priv_key_len;
+ const uint8_t *pub_key;
+ size_t pub_key_len;
+ const uint8_t *dgst;
+ size_t dlen;
+ const uint8_t *signature;
+ size_t slen;
+};
+
typedef struct QCryptoRSAKeyTestData QCryptoRSAKeyTestData;
struct QCryptoRSAKeyTestData {
const char *path;
@@ -969,6 +1080,120 @@ static void test_rsakey(const void *opaque)
g_assert(qcrypto_akcipher_max_dgst_len(key) == data->exp_key_len);
}
+static QCryptoECDSATestData ecdsa_test_data[] = {
+ {
+ .path = "/crypto/akcipher/ecdsa-prime256v1",
+ .curve_id = QCRYPTO_CURVE_ID_PRIME256V1,
+ .priv_key = ecdsa_p256_privkey,
+ .priv_key_len = sizeof(ecdsa_p256_privkey),
+ .pub_key = ecdsa_p256_pubkey,
+ .pub_key_len = sizeof(ecdsa_p256_pubkey),
+ .dgst = ecdsa_p256_dgst,
+ .dlen = sizeof(ecdsa_p256_dgst),
+ .signature = ecdsa_p256_signature,
+ .slen = sizeof(ecdsa_p256_signature),
+ },
+ {
+ .path = "/crypto/akcipher/ecdsa-secp384r1",
+ .curve_id = QCRYPTO_CURVE_ID_SECP384R1,
+ .priv_key = ecdsa_p384_privkey,
+ .priv_key_len = sizeof(ecdsa_p384_privkey),
+ .pub_key = ecdsa_p384_pubkey,
+ .pub_key_len = sizeof(ecdsa_p384_pubkey),
+ .dgst = ecdsa_p384_dgst,
+ .dlen = sizeof(ecdsa_p384_dgst),
+ .signature = ecdsa_p384_signature,
+ .slen = sizeof(ecdsa_p384_signature),
+ },
+ /* Add more curves here as they gain backend support. */
+};
+
+static void test_ecdsa_verify(const void *opaque)
+{
+ const QCryptoECDSATestData *data = opaque;
+ QCryptoAkCipherOptions opt = {
+ .alg = QCRYPTO_AK_CIPHER_ALGO_ECDSA,
+ .u.ecdsa = {
+ .curve_id = data->curve_id,
+ },
+ };
+ g_autoptr(QCryptoAkCipher) pub_key = NULL;
+ g_autofree uint8_t *signature = NULL;
+ g_autofree uint8_t *dgst = NULL;
+
+ if (!qcrypto_akcipher_supports(&opt)) {
+ g_test_skip("ECDSA is not supported by the crypto backend");
+ return;
+ }
+
+ pub_key = qcrypto_akcipher_new(&opt, QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC,
+ data->pub_key, data->pub_key_len,
+ &error_abort);
+ g_assert(pub_key != NULL);
+ g_assert(qcrypto_akcipher_max_signature_len(pub_key) == data->slen);
+ g_assert(qcrypto_akcipher_max_dgst_len(pub_key) == data->dlen);
+
+ /* A valid signature must verify. */
+ g_assert(qcrypto_akcipher_verify(pub_key, data->signature, data->slen,
+ data->dgst, data->dlen,
+ &error_abort) == 0);
+
+ /* A tampered signature must fail (error is expected, so ignore it). */
+ signature = g_memdup2(data->signature, data->slen);
+ signature[0]++;
+ g_assert(qcrypto_akcipher_verify(pub_key, signature, data->slen,
+ data->dgst, data->dlen, NULL) != 0);
+
+ /* A tampered digest must also fail. */
+ dgst = g_memdup2(data->dgst, data->dlen);
+ dgst[0]++;
+ g_assert(qcrypto_akcipher_verify(pub_key, data->signature, data->slen,
+ dgst, data->dlen, NULL) != 0);
+}
+
+static void test_ecdsa_sign(const void *opaque)
+{
+ const QCryptoECDSATestData *data = opaque;
+ QCryptoAkCipherOptions opt = {
+ .alg = QCRYPTO_AK_CIPHER_ALGO_ECDSA,
+ .u.ecdsa = {
+ .curve_id = data->curve_id,
+ },
+ };
+ g_autoptr(QCryptoAkCipher) priv_key = NULL;
+ g_autoptr(QCryptoAkCipher) pub_key = NULL;
+ g_autofree uint8_t *signature = NULL;
+ int slen;
+
+ if (!qcrypto_akcipher_supports(&opt)) {
+ g_test_skip("ECDSA is not supported by the crypto backend");
+ return;
+ }
+
+ priv_key = qcrypto_akcipher_new(&opt, QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE,
+ data->priv_key, data->priv_key_len,
+ &error_abort);
+ g_assert(priv_key != NULL);
+
+ /*
+ * Sign the digest.
+ * ECDSA signatures are randomized so only length is fixed.
+ */
+ slen = qcrypto_akcipher_max_signature_len(priv_key);
+ signature = g_new0(uint8_t, slen);
+ g_assert(qcrypto_akcipher_sign(priv_key, data->dgst, data->dlen,
+ signature, slen, &error_abort) == slen);
+
+ /* The freshly produced signature must verify with the public key. */
+ pub_key = qcrypto_akcipher_new(&opt, QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC,
+ data->pub_key, data->pub_key_len,
+ &error_abort);
+ g_assert(pub_key != NULL);
+ g_assert(qcrypto_akcipher_verify(pub_key, signature, slen,
+ data->dgst, data->dlen,
+ &error_abort) == 0);
+}
+
int main(int argc, char **argv)
{
size_t i;
@@ -985,6 +1210,17 @@ int main(int argc, char **argv)
&rsakey_test_data[i],
test_rsakey);
}
+ for (i = 0; i < G_N_ELEMENTS(ecdsa_test_data); i++) {
+ g_autofree char *verify_path =
+ g_strdup_printf("%s-verify", ecdsa_test_data[i].path);
+ g_autofree char *sign_path =
+ g_strdup_printf("%s-sign", ecdsa_test_data[i].path);
+
+ g_test_add_data_func(verify_path, &ecdsa_test_data[i],
+ test_ecdsa_verify);
+ g_test_add_data_func(sign_path, &ecdsa_test_data[i],
+ test_ecdsa_sign);
+ }
return g_test_run();
}