From ba5a271dbb71edc1985b7d9f837d7904ad2a4529 Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@ieee.org>
Date: Fri, 16 Dec 2022 16:33:08 -0500
Subject: [PATCH] tpm2: add tpm2_get_policy_digest()

(cherry picked from commit 23b972d571650014ab5f22610da80a62f53f2245)

Related: RHEL-16182
---
 src/shared/tpm2-util.c | 99 ++++++++++++++++++++++++------------------
 1 file changed, 57 insertions(+), 42 deletions(-)

diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index c22a200a5c..b5eabb8159 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -476,6 +476,54 @@ void tpm2_pcr_mask_to_selection(uint32_t mask, uint16_t bank, TPML_PCR_SELECTION
         };
 }
 
+static void tpm2_log_debug_buffer(const void *buffer, size_t size, const char *msg) {
+        if (!DEBUG_LOGGING || !buffer || size == 0)
+                return;
+
+        _cleanup_free_ char *h = hexmem(buffer, size);
+        log_debug("%s: %s", msg ?: "Buffer", strna(h));
+}
+
+static void tpm2_log_debug_digest(const TPM2B_DIGEST *digest, const char *msg) {
+        if (digest)
+                tpm2_log_debug_buffer(digest->buffer, digest->size, msg ?: "Digest");
+}
+
+static int tpm2_get_policy_digest(
+                Tpm2Context *c,
+                const Tpm2Handle *session,
+                TPM2B_DIGEST **ret_policy_digest) {
+
+        TSS2_RC rc;
+
+        if (!DEBUG_LOGGING && !ret_policy_digest)
+                return 0;
+
+        assert(c);
+        assert(session);
+
+        log_debug("Acquiring policy digest.");
+
+        _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
+        rc = sym_Esys_PolicyGetDigest(
+                        c->esys_context,
+                        session->esys_handle,
+                        ESYS_TR_NONE,
+                        ESYS_TR_NONE,
+                        ESYS_TR_NONE,
+                        &policy_digest);
+        if (rc != TSS2_RC_SUCCESS)
+                return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
+                                       "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
+
+        tpm2_log_debug_digest(policy_digest, "Session policy digest");
+
+        if (ret_policy_digest)
+                *ret_policy_digest = TAKE_PTR(policy_digest);
+
+        return 0;
+}
+
 static unsigned find_nth_bit(uint32_t mask, unsigned n) {
         uint32_t bit = 1;
 
@@ -1100,7 +1148,6 @@ static int tpm2_make_policy_session(
                 .keyBits.aes = 128,
                 .mode.aes = TPM2_ALG_CFB,
         };
-        _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
         TSS2_RC rc;
         int r;
 
@@ -1237,16 +1284,9 @@ static int tpm2_make_policy_session(
 
                 /* Get the policy hash of the PCR policy */
                 _cleanup_(Esys_Freep) TPM2B_DIGEST *approved_policy = NULL;
-                rc = sym_Esys_PolicyGetDigest(
-                                c->esys_context,
-                                session->esys_handle,
-                                ESYS_TR_NONE,
-                                ESYS_TR_NONE,
-                                ESYS_TR_NONE,
-                                &approved_policy);
-                if (rc != TSS2_RC_SUCCESS)
-                        return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                               "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
+                r = tpm2_get_policy_digest(c, session, &approved_policy);
+                if (r < 0)
+                        return r;
 
                 /* When we are unlocking and have a signature, let's pass it to the TPM */
                 _cleanup_(Esys_Freep) TPMT_TK_VERIFIED *check_ticket_buffer = NULL;
@@ -1361,38 +1401,13 @@ static int tpm2_make_policy_session(
                                                sym_Tss2_RC_Decode(rc));
         }
 
-        if (DEBUG_LOGGING || ret_policy_digest) {
-                log_debug("Acquiring policy digest.");
-
-                rc = sym_Esys_PolicyGetDigest(
-                                c->esys_context,
-                                session->esys_handle,
-                                ESYS_TR_NONE,
-                                ESYS_TR_NONE,
-                                ESYS_TR_NONE,
-                                &policy_digest);
-
-                if (rc != TSS2_RC_SUCCESS)
-                        return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE),
-                                               "Failed to get policy digest from TPM: %s", sym_Tss2_RC_Decode(rc));
-
-                if (DEBUG_LOGGING) {
-                        _cleanup_free_ char *h = NULL;
-
-                        h = hexmem(policy_digest->buffer, policy_digest->size);
-                        if (!h)
-                                return log_oom();
-
-                        log_debug("Session policy digest: %s", h);
-                }
-        }
+        r = tpm2_get_policy_digest(c, session, ret_policy_digest);
+        if (r < 0)
+                return r;
 
         if (ret_session)
                 *ret_session = TAKE_PTR(session);
 
-        if (ret_policy_digest)
-                *ret_policy_digest = TAKE_PTR(policy_digest);
-
         if (ret_pcr_bank)
                 *ret_pcr_bank = pcr_bank;
 
@@ -1414,7 +1429,6 @@ int tpm2_seal(const char *device,
               uint16_t *ret_pcr_bank,
               uint16_t *ret_primary_alg) {
 
-        _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
         _cleanup_(Esys_Freep) TPM2B_PRIVATE *private = NULL;
         _cleanup_(Esys_Freep) TPM2B_PUBLIC *public = NULL;
         static const TPML_PCR_SELECTION creation_pcr = {};
@@ -1423,7 +1437,6 @@ int tpm2_seal(const char *device,
         TPM2B_SENSITIVE_CREATE hmac_sensitive;
         TPMI_ALG_PUBLIC primary_alg;
         TPM2B_PUBLIC hmac_template;
-        TPMI_ALG_HASH pcr_bank;
         usec_t start;
         TSS2_RC rc;
         int r;
@@ -1477,6 +1490,8 @@ int tpm2_seal(const char *device,
         if (r < 0)
                 return r;
 
+        _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
+        TPMI_ALG_HASH pcr_bank;
         r = tpm2_make_policy_session(
                         c,
                         primary,
@@ -1608,7 +1623,6 @@ int tpm2_unseal(const char *device,
                 size_t *ret_secret_size) {
 
         _cleanup_(Esys_Freep) TPM2B_SENSITIVE_DATA* unsealed = NULL;
-        _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
         _cleanup_(erase_and_freep) char *secret = NULL;
         TPM2B_PRIVATE private = {};
         TPM2B_PUBLIC public = {};
@@ -1708,6 +1722,7 @@ int tpm2_unseal(const char *device,
 
         for (unsigned i = RETRY_UNSEAL_MAX;; i--) {
                 _cleanup_tpm2_handle_ Tpm2Handle *policy_session = NULL;
+                _cleanup_(Esys_Freep) TPM2B_DIGEST *policy_digest = NULL;
                 r = tpm2_make_policy_session(
                                 c,
                                 primary,