[PATCH v3 08/10] tests: Use ML-DSA-87 operations to caused large TPM transfers with CRB

Arun Menon posted 10 patches 1 day, 4 hours ago
Maintainers: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Yanan Wang <wangyanan55@huawei.com>, Zhao Liu <zhao1.liu@intel.com>, Stefan Berger <stefanb@linux.vnet.ibm.com>, "Michael S. Tsirkin" <mst@redhat.com>, Igor Mammedov <imammedo@redhat.com>, Ani Sinha <anisinha@redhat.com>, Fabiano Rosas <farosas@suse.de>, Laurent Vivier <lvivier@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>
[PATCH v3 08/10] tests: Use ML-DSA-87 operations to caused large TPM transfers with CRB
Posted by Arun Menon 1 day, 4 hours ago
From: Stefan Berger <stefanb@linux.ibm.com>

To test large data transfers (receiving and sending) that make us of a CRB
chunked transfer, create an ML-DSA-87 key and sign some data with it and
receive the 4627 bytes signature. After this send the signature back to the
TPM to have the TPM verify the signature.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Arun Menon <armenon@redhat.com>
---
 tests/qtest/tpm-crb-swtpm-test.c |  5 +-
 tests/qtest/tpm-tests.c          | 96 ++++++++++++++++++++++++++++++++
 tests/qtest/tpm-tests.h          |  4 ++
 tests/qtest/tpm-util.c           | 37 ++++++++++++
 tests/qtest/tpm-util.h           |  2 +
 5 files changed, 142 insertions(+), 2 deletions(-)

diff --git a/tests/qtest/tpm-crb-swtpm-test.c b/tests/qtest/tpm-crb-swtpm-test.c
index 050c7b0c1f..541fd58133 100644
--- a/tests/qtest/tpm-crb-swtpm-test.c
+++ b/tests/qtest/tpm-crb-swtpm-test.c
@@ -37,8 +37,9 @@ static void tpm_crb_chunk_swtpm_test(const void *data)
 {
     const TestState *ts = data;
 
-    tpm_test_swtpm_test(ts->src_tpm_path, tpm_util_crb_chunk_transfer,
-                        "tpm-crb", NULL);
+    tpm_test_swtpm_large_tx_test(ts->src_tpm_path,
+                                 tpm_util_crb_chunk_transfer,
+                                 "tpm-crb", NULL);
 }
 
 static void tpm_crb_swtpm_migration_test(const void *data)
diff --git a/tests/qtest/tpm-tests.c b/tests/qtest/tpm-tests.c
index f71d882990..21811f3a2e 100644
--- a/tests/qtest/tpm-tests.c
+++ b/tests/qtest/tpm-tests.c
@@ -13,6 +13,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "system/tpm_util.h"
 #include <glib/gstdio.h>
 
 #include "libqtest-single.h"
@@ -130,3 +131,98 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
     g_unlink(src_tpm_addr->u.q_unix.path);
     qapi_free_SocketAddress(src_tpm_addr);
 }
+
+void tpm_test_swtpm_large_tx_test(const char *src_tpm_path, tx_func *tx,
+                                  const char *ifmodel,
+                                  const char *machine_options)
+{
+    unsigned char signature[2 + 2 + 4627]; /* TPMT_SIGNATURE */
+    unsigned char response[8192];
+    unsigned char request[8192];
+    SocketAddress *addr = NULL;
+    GError *error = NULL;
+    char *args = NULL;
+    GPid swtpm_pid;
+    QTestState *s;
+    gboolean succ;
+
+    if (tpm_test_swtpm_skip()) {
+        return;
+    }
+
+    /* Large transfers based on ML-DSA operations required default-v2 profile */
+    if (!tpm_util_swtpm_has_profile("default-v2", "ml-dsa")) {
+        return;
+    }
+
+    succ = tpm_util_swtpm_start(src_tpm_path, &swtpm_pid, &addr, "default-v2",
+                                &error);
+    g_assert_true(succ);
+
+    args = g_strdup_printf(
+        "%s "
+        "-chardev socket,id=chr,path=%s "
+        "-tpmdev emulator,id=dev,chardev=chr "
+        "-device %s,tpmdev=dev",
+        machine_options ? : "", addr->u.q_unix.path, ifmodel);
+
+    s = qtest_start(args);
+    g_free(args);
+
+    tpm_util_startup(s, tx);
+
+    static const unsigned char tpm_createprimary_mldsa[] =
+        "\x80\x02\x00\x00\x00\x38\x00\x00\x01\x31\x40\x00\x00\x07\x00\x00"
+        "\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00"
+        "\x00\x00\x0f\x00\xa1\x00\x0b\x00\x04\x04\x72\x00\x00\x00\x03\x00"
+        "\x00\x00\x00\x00\x00\x00\x00\x00";
+    tx(s, tpm_createprimary_mldsa, sizeof(tpm_createprimary_mldsa),
+       response, sizeof(response));
+    g_assert_cmpint(tpm_cmd_get_errcode(response), ==, 0);
+    g_assert_cmpint(tpm_cmd_get_size(response), ==, 2831);
+
+    static const unsigned char tpm_signsequencestart[] =
+        "\x80\x01\x00\x00\x00\x12\x00\x00\x01\xaa\x80\x00\x00\x00\x00\x00"
+        "\x00\x00";
+    tx(s, tpm_signsequencestart, sizeof(tpm_signsequencestart),
+       response, sizeof(response));
+    g_assert_cmpint(tpm_cmd_get_errcode(response), ==, 0);
+    g_assert_cmpint(tpm_cmd_get_size(response), ==, 14);
+
+    /* Complete sequence and get signature */
+    static const unsigned char tpm_signsequencecomplete[] =
+        "\x80\x02\x00\x00\x00\x2a\x00\x00\x01\xa4\x80\x00\x00\x01\x80\x00"
+        "\x00\x00\x00\x00\x00\x12\x40\x00\x00\x09\x00\x00\x00\x00\x00\x40"
+        "\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00";
+    tx(s, tpm_signsequencecomplete, sizeof(tpm_signsequencecomplete),
+       response, sizeof(response));
+    g_assert_cmpint(tpm_cmd_get_errcode(response), ==, 0);
+    g_assert_cmpint(tpm_cmd_get_size(response), ==, 4655);
+
+    /* TPMT_SIGNATURE found at offset 14 */
+    memcpy(signature, &response[14], sizeof(signature));
+
+    static const unsigned char tpm_verifysequencestart[] =
+        "\x80\x01\x00\x00\x00\x14\x00\x00\x01\xa9\x80\x00\x00\x00\x00\x00"
+        "\x00\x00\x00\x00";
+    tx(s, tpm_verifysequencestart, sizeof(tpm_verifysequencestart),
+       response, sizeof(response));
+    g_assert_cmpint(tpm_cmd_get_errcode(response), ==, 0);
+    g_assert_cmpint(tpm_cmd_get_size(response), ==, 14);
+
+    /* TPM2_VerifySequenceComplete */
+    memcpy(request,
+           "\x80\x02\x00\x00\x12\x36\x00\x00\x01\xa3\x80\x00\x00\x01\x80\x00"
+           "\x00\x00\x00\x00\x00\x09\x40\x00\x00\x09\x00\x00\x00\x00\x00",
+           31);
+    memcpy(&request[31], signature, sizeof(signature));
+    tx(s, request, 31 + sizeof(signature), response, sizeof(response));
+    g_assert_cmpint(tpm_cmd_get_errcode(response), ==, 0);
+    g_assert_cmpint(tpm_cmd_get_size(response), ==, 27);
+
+    qtest_end();
+    tpm_util_swtpm_kill(swtpm_pid);
+
+    g_unlink(addr->u.q_unix.path);
+    qapi_free_SocketAddress(addr);
+}
diff --git a/tests/qtest/tpm-tests.h b/tests/qtest/tpm-tests.h
index 07ba60d26e..6993ce40dc 100644
--- a/tests/qtest/tpm-tests.h
+++ b/tests/qtest/tpm-tests.h
@@ -24,4 +24,8 @@ void tpm_test_swtpm_migration_test(const char *src_tpm_path,
                                    const char *ifmodel,
                                    const char *machine_options);
 
+void tpm_test_swtpm_large_tx_test(const char *src_tpm_path, tx_func *tx,
+                                  const char *ifmodel,
+                                  const char *machine_options);
+
 #endif /* TESTS_TPM_TESTS_H */
diff --git a/tests/qtest/tpm-util.c b/tests/qtest/tpm-util.c
index 24243065c1..6163f5a533 100644
--- a/tests/qtest/tpm-util.c
+++ b/tests/qtest/tpm-util.c
@@ -209,6 +209,43 @@ bool tpm_util_swtpm_has_tpm2(void)
     return has_tpm2;
 }
 
+bool tpm_util_swtpm_has_profile(const char *profilename,
+                                const char *content)
+{
+    bool has_profile = false;
+    char *out = NULL;
+    static const char *argv[] = {
+        "swtpm", "socket", "--tpm2", "--print-profiles", NULL
+    };
+
+    if (!tpm_util_swtpm_has_tpm2()) {
+        return false;
+    }
+
+    if (!g_spawn_sync(NULL /* working_dir */,
+                      (char **)argv,
+                      NULL /* envp */,
+                      G_SPAWN_SEARCH_PATH,
+                      NULL /* child_setup */,
+                      NULL /* user_data */,
+                      &out,
+                      NULL /* err */,
+                      NULL /* exit_status */,
+                      NULL)) {
+        return false;
+    }
+
+    if (strstr(out, profilename)) {
+        has_profile = true;
+    }
+    if (has_profile && content && strstr(out, content) == NULL) {
+        has_profile = false;
+    }
+
+    g_free(out);
+    return has_profile;
+}
+
 gboolean tpm_util_swtpm_start(const char *path, GPid *pid,
                               SocketAddress **addr, const char *profilename,
                               GError **error)
diff --git a/tests/qtest/tpm-util.h b/tests/qtest/tpm-util.h
index ca2d7d173f..90790f30db 100644
--- a/tests/qtest/tpm-util.h
+++ b/tests/qtest/tpm-util.h
@@ -39,6 +39,8 @@ void tpm_util_pcrread(QTestState *s, tx_func *tx,
                       const unsigned char *exp_resp, size_t exp_resp_size);
 
 bool tpm_util_swtpm_has_tpm2(void);
+bool tpm_util_swtpm_has_profile(const char *profilename,
+                                const char *content);
 
 gboolean tpm_util_swtpm_start(const char *path, GPid *pid,
                               SocketAddress **addr, const char *profilename,
-- 
2.53.0