]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2: update test-tpm2 for tpm2_calculate_seal()
authorDan Streetman <ddstreet@ieee.org>
Tue, 3 Oct 2023 14:25:19 +0000 (10:25 -0400)
committerDan Streetman <ddstreet@ieee.org>
Tue, 7 Nov 2023 17:00:07 +0000 (12:00 -0500)
Add testing for tpm2_calculate_seal().

src/shared/tpm2-util.c
src/shared/tpm2-util.h
src/test/test-tpm2.c

index c69cc86c7bb13025d4551b40d9a3b34d2dc732d6..783a603e3d98b1603afe22d7306030fd3ef390c3 100644 (file)
@@ -4335,7 +4335,7 @@ int tpm2_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *r
  * objects are required, while the seed is optional. This is not a (publicly) standard format, this is
  * specific to how we currently store the sealed object. This 'blob' can be unmarshalled by
  * tpm2_unmarshal_blob(). */
-static int tpm2_marshal_blob(
+int tpm2_marshal_blob(
                 const TPM2B_PUBLIC *public,
                 const TPM2B_PRIVATE *private,
                 const TPM2B_ENCRYPTED_SECRET *seed,
@@ -4385,7 +4385,7 @@ static int tpm2_marshal_blob(
  * in the 'blob', while the seed is optional. This is not a (publicly) standard format, this is specific to
  * how we currently store the sealed object. This expects the 'blob' to have been created by
  * tpm2_marshal_blob(). */
-static int tpm2_unmarshal_blob(
+int tpm2_unmarshal_blob(
                 const void *blob,
                 size_t blob_size,
                 TPM2B_PUBLIC *ret_public,
index 88a836733e0fff267241e8fb92e781dd24c9d1bd..1243b596a51c8b48692eb928abd2eb4d0a55deb0 100644 (file)
@@ -128,6 +128,8 @@ int tpm2_create_loaded(Tpm2Context *c, const Tpm2Handle *parent, const Tpm2Handl
 int tpm2_load(Tpm2Context *c, const Tpm2Handle *parent, const Tpm2Handle *session, const TPM2B_PUBLIC *public, const TPM2B_PRIVATE *private, Tpm2Handle **ret_handle);
 int tpm2_marshal_nv_public(const TPM2B_NV_PUBLIC *nv_public, void **ret, size_t *ret_size);
 int tpm2_unmarshal_nv_public(const void *data, size_t size, TPM2B_NV_PUBLIC *ret_nv_public);
+int tpm2_marshal_blob(const TPM2B_PUBLIC *public, const TPM2B_PRIVATE *private, const TPM2B_ENCRYPTED_SECRET *seed, void **ret_blob, size_t *ret_blob_size);
+int tpm2_unmarshal_blob(const void *blob, size_t blob_size, TPM2B_PUBLIC *ret_public, TPM2B_PRIVATE *ret_private, TPM2B_ENCRYPTED_SECRET *ret_seed);
 
 bool tpm2_supports_alg(Tpm2Context *c, TPM2_ALG_ID alg);
 bool tpm2_supports_command(Tpm2Context *c, TPM2_CC command);
index 17973f50110491f7f6cff56e3e27eac8bd17bedb..0469625ab15c3af56d5300f32f773a3e2adc26b9 100644 (file)
@@ -1079,6 +1079,89 @@ static void check_get_or_create_srk(Tpm2Context *c) {
         assert_se(memcmp_nn(qname->name, qname->size, qname2->name, qname2->size) == 0);
 }
 
+#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3
+static void calculate_seal_and_unseal(
+                Tpm2Context *c,
+                TPM2_HANDLE parent_index,
+                const TPM2B_PUBLIC *parent_public) {
+
+        _cleanup_free_ char *secret_string = NULL;
+        assert_se(asprintf(&secret_string, "The classified documents are in room %x", parent_index) > 0);
+        size_t secret_size = strlen(secret_string) + 1;
+
+        _cleanup_free_ void *blob = NULL;
+        size_t blob_size = 0;
+        _cleanup_free_ void *serialized_parent = NULL;
+        size_t serialized_parent_size;
+        assert_se(tpm2_calculate_seal(
+                        parent_index,
+                        parent_public,
+                        /* attributes= */ NULL,
+                        secret_string, secret_size,
+                        /* policy= */ NULL,
+                        /* pin= */ NULL,
+                        /* ret_secret= */ NULL, /* ret_secret_size= */ 0,
+                        &blob, &blob_size,
+                        &serialized_parent, &serialized_parent_size) >= 0);
+
+        _cleanup_free_ void *unsealed_secret = NULL;
+        size_t unsealed_secret_size;
+        assert_se(tpm2_unseal(
+                        c,
+                        /* hash_pcr_mask= */ 0,
+                        /* pcr_bank= */ 0,
+                        /* pubkey= */ NULL, /* pubkey_size= */ 0,
+                        /* pubkey_pcr_mask= */ 0,
+                        /* signature= */ NULL,
+                        /* pin= */ NULL,
+                        /* pcrlock_policy= */ NULL,
+                        /* primary_alg= */ 0,
+                        blob, blob_size,
+                        /* known_policy_hash= */ NULL, /* known_policy_hash_size= */ 0,
+                        serialized_parent, serialized_parent_size,
+                        &unsealed_secret, &unsealed_secret_size) >= 0);
+
+        assert_se(memcmp_nn(secret_string, secret_size, unsealed_secret, unsealed_secret_size) == 0);
+
+        char unsealed_string[unsealed_secret_size];
+        assert_se(snprintf(unsealed_string, unsealed_secret_size, "%s", (char*) unsealed_secret) == (int) unsealed_secret_size - 1);
+        log_debug("Unsealed secret is: %s", unsealed_string);
+}
+
+static int check_calculate_seal(Tpm2Context *c) {
+        assert(c);
+        int r;
+
+        _cleanup_free_ TPM2B_PUBLIC *srk_public = NULL;
+        assert_se(tpm2_get_srk(c, NULL, &srk_public, NULL, NULL, NULL) >= 0);
+        calculate_seal_and_unseal(c, TPM2_SRK_HANDLE, srk_public);
+
+        TPMI_ALG_ASYM test_algs[] = { TPM2_ALG_RSA, TPM2_ALG_ECC, };
+        for (unsigned i = 0; i < ELEMENTSOF(test_algs); i++) {
+                TPMI_ALG_ASYM alg = test_algs[i];
+
+                TPM2B_PUBLIC template = { .size = sizeof(TPMT_PUBLIC), };
+                assert_se(tpm2_get_srk_template(alg, &template.publicArea) >= 0);
+
+                _cleanup_free_ TPM2B_PUBLIC *public = NULL;
+                _cleanup_(tpm2_handle_freep) Tpm2Handle *handle = NULL;
+                assert_se(tpm2_create_primary(c, NULL, &template, NULL, &public, &handle) >= 0);
+
+                /* Once our minimum libtss2-esys version is 2.4.0 or later, this can assume
+                 * tpm2_index_from_handle() should always work. */
+                TPM2_HANDLE index;
+                r = tpm2_index_from_handle(c, handle, &index);
+                if (r == -EOPNOTSUPP)
+                        return log_tests_skipped("libtss2-esys version too old to support tpm2_index_from_handle()");
+                assert_se(r >= 0);
+
+                calculate_seal_and_unseal(c, index, public);
+        }
+
+        return 0;
+}
+#endif /* HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 */
+
 static void check_seal_unseal_for_handle(Tpm2Context *c, TPM2_HANDLE handle) {
         TPM2B_DIGEST policy = TPM2B_DIGEST_MAKE(NULL, TPM2_SHA256_DIGEST_SIZE);
 
@@ -1153,6 +1236,7 @@ static void check_seal_unseal(Tpm2Context *c) {
 
 TEST_RET(tests_which_require_tpm) {
         _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
+        int r = 0;
 
         if (tpm2_context_new(NULL, &c) < 0)
                 return log_tests_skipped("Could not find TPM");
@@ -1164,7 +1248,11 @@ TEST_RET(tests_which_require_tpm) {
         check_get_or_create_srk(c);
         check_seal_unseal(c);
 
-        return 0;
+#if HAVE_OPENSSL && OPENSSL_VERSION_MAJOR >= 3 /* calculating sealed object requires openssl >= 3 */
+        r = check_calculate_seal(c);
+#endif
+
+        return r;
 }
 
 #endif /* HAVE_TPM2 */