]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
tpm2: add tpm2_marshal_blob() and tpm2_unmarshal_blob()
authorDan Streetman <ddstreet@ieee.org>
Wed, 28 Jun 2023 15:46:31 +0000 (11:46 -0400)
committerDan Streetman <ddstreet@ieee.org>
Fri, 29 Sep 2023 14:14:28 +0000 (10:14 -0400)
Add functions to marshal and unmarshal our 'blob' object.

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

index 9cab153e45f24d99dde69acd840c815574188bf1..0aca94e74bc44f06a9ea79862e0e3f57803cf95d 100644 (file)
@@ -3752,6 +3752,79 @@ int tpm2_tpm2b_public_from_pem(const void *pem, size_t pem_size, TPM2B_PUBLIC *r
 #endif
 }
 
+/* Marshal the public and private objects into a single nonstandard 'blob'. 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(). */
+int tpm2_marshal_blob(
+                const TPM2B_PUBLIC *public,
+                const TPM2B_PRIVATE *private,
+                void **ret_blob,
+                size_t *ret_blob_size) {
+
+        TSS2_RC rc;
+
+        assert(public);
+        assert(private);
+        assert(ret_blob);
+        assert(ret_blob_size);
+
+        size_t max_size = sizeof(*private) + sizeof(*public);
+
+        _cleanup_free_ void *blob = malloc(max_size);
+        if (!blob)
+                return log_oom_debug();
+
+        size_t blob_size = 0;
+        rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
+        if (rc != TSS2_RC_SUCCESS)
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
+                                       "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
+
+        rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
+        if (rc != TSS2_RC_SUCCESS)
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
+                                       "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
+
+        *ret_blob = TAKE_PTR(blob);
+        *ret_blob_size = blob_size;
+
+        return 0;
+}
+
+/* Unmarshal the 'blob' into public and private objects. 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(). */
+int tpm2_unmarshal_blob(
+                const void *blob,
+                size_t blob_size,
+                TPM2B_PUBLIC *ret_public,
+                TPM2B_PRIVATE *ret_private) {
+
+        TSS2_RC rc;
+
+        assert(blob);
+        assert(ret_public);
+        assert(ret_private);
+
+        TPM2B_PRIVATE private = {};
+        size_t offset = 0;
+        rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
+        if (rc != TSS2_RC_SUCCESS)
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
+                                       "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
+
+        TPM2B_PUBLIC public = {};
+        rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
+        if (rc != TSS2_RC_SUCCESS)
+                return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
+                                       "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
+
+        *ret_public = public;
+        *ret_private = private;
+
+        return 0;
+}
+
 int tpm2_seal(Tpm2Context *c,
               const TPM2B_DIGEST *policy,
               const char *pin,
@@ -3889,21 +3962,10 @@ int tpm2_seal(Tpm2Context *c,
         log_debug("Marshalling private and public part of HMAC key.");
 
         _cleanup_free_ void *blob = NULL;
-        size_t max_size = sizeof(*private) + sizeof(*public), blob_size = 0;
-
-        blob = malloc0(max_size);
-        if (!blob)
-                return log_oom();
-
-        rc = sym_Tss2_MU_TPM2B_PRIVATE_Marshal(private, blob, max_size, &blob_size);
-        if (rc != TSS2_RC_SUCCESS)
-                return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                       "Failed to marshal private key: %s", sym_Tss2_RC_Decode(rc));
-
-        rc = sym_Tss2_MU_TPM2B_PUBLIC_Marshal(public, blob, max_size, &blob_size);
-        if (rc != TSS2_RC_SUCCESS)
-                return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                       "Failed to marshal public key: %s", sym_Tss2_RC_Decode(rc));
+        size_t blob_size;
+        r = tpm2_marshal_blob(public, private, &blob, &blob_size);
+        if (r < 0)
+                return log_error_errno(r, "Could not create sealed blob: %m");
 
         /* serialize the key for storage in the LUKS header. A deserialized ESYS_TR provides both
          * the raw TPM handle as well as the object name. The object name is used to verify that
@@ -3994,22 +4056,11 @@ int tpm2_unseal(const char *device,
 
         usec_t start = now(CLOCK_MONOTONIC);
 
-        log_debug("Unmarshalling private part of HMAC key.");
-
-        TPM2B_PRIVATE private = {};
-        size_t offset = 0;
-        rc = sym_Tss2_MU_TPM2B_PRIVATE_Unmarshal(blob, blob_size, &offset, &private);
-        if (rc != TSS2_RC_SUCCESS)
-                return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                       "Failed to unmarshal private key: %s", sym_Tss2_RC_Decode(rc));
-
-        log_debug("Unmarshalling public part of HMAC key.");
-
-        TPM2B_PUBLIC public = {};
-        rc = sym_Tss2_MU_TPM2B_PUBLIC_Unmarshal(blob, blob_size, &offset, &public);
-        if (rc != TSS2_RC_SUCCESS)
-                return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                       "Failed to unmarshal public key: %s", sym_Tss2_RC_Decode(rc));
+        TPM2B_PUBLIC public;
+        TPM2B_PRIVATE private;
+        r = tpm2_unmarshal_blob(blob, blob_size, &public, &private);
+        if (r < 0)
+                return log_error_errno(r, "Could not extract parts from blob: %m");
 
         _cleanup_(tpm2_context_unrefp) Tpm2Context *c = NULL;
         r = tpm2_context_new(device, &c);
index 35bcd62759f8d1c424954baae5647f678a102c7f..b0d587eb5f0c81d0b87e881dc7fc45bcaf019e1c 100644 (file)
@@ -180,6 +180,9 @@ int tpm2_calculate_policy_authorize(const TPM2B_PUBLIC *public, const TPM2B_DIGE
 int tpm2_calculate_policy_pcr(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, TPM2B_DIGEST *digest);
 int tpm2_calculate_sealing_policy(const Tpm2PCRValue *pcr_values, size_t n_pcr_values, const TPM2B_PUBLIC *public, bool use_pin, TPM2B_DIGEST *digest);
 
+int tpm2_marshal_blob(const TPM2B_PUBLIC *public, const TPM2B_PRIVATE *private, 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);
+
 int tpm2_seal(Tpm2Context *c, const TPM2B_DIGEST *policy, const char *pin, void **ret_secret, size_t *ret_secret_size, void **ret_blob, size_t *ret_blob_size, uint16_t *ret_primary_alg, void **ret_srk_buf, size_t *ret_srk_buf_size);
 int tpm2_unseal(const char *device, uint32_t hash_pcr_mask, uint16_t pcr_bank, const void *pubkey, size_t pubkey_size, uint32_t pubkey_pcr_mask, JsonVariant *signature, const char *pin, uint16_t primary_alg, const void *blob, size_t blob_size, const void *policy_hash, size_t policy_hash_size, const void *srk_buf, size_t srk_buf_size, void **ret_secret, size_t *ret_secret_size);