systemd/0631-tpm2-add-tpm2_get_pin_...

75 lines
3.0 KiB
Diff

From fd901d06e52786cfb2bd67919c72d05eab5a4c65 Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@ieee.org>
Date: Sat, 15 Jul 2023 08:30:40 -0400
Subject: [PATCH] tpm2: add tpm2_get_pin_auth()
Add function to calculate the hash digest for a provided pin, and also verify
that the final byte in the digest is not 0. This is required because the TPM
will always remove all trailing 0's from an auth value before using it.
Fixes: #27716
(cherry picked from commit f230572f56a34fd7269c5fda4fb92be5ee0ea281)
Related: RHEL-16182
---
src/shared/tpm2-util.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index cb05b2a01c..49e50a83ac 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -2795,6 +2795,34 @@ int tpm2_digest_many_digests(
return tpm2_digest_many(alg, digest, iovecs, n_data, extend);
}
+/* This hashes the provided pin into a digest value, but also verifies that the final byte is not 0, because
+ * the TPM specification Part 1 ("Architecture") section Authorization Values (subsection "Authorization Size
+ * Convention") states "Trailing octets of zero are to be removed from any string before it is used as an
+ * authValue". Since the TPM doesn't know if the auth value is a "string" or just a hash digest, any hash
+ * digest that randomly happens to end in 0 must have the final 0 changed, or the TPM will remove it before
+ * using the value in its HMAC calculations, resulting in failed HMAC checks. */
+static int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *ret_auth) {
+ TPM2B_AUTH auth = {};
+ int r;
+
+ assert(pin);
+ assert(ret_auth);
+
+ r = tpm2_digest_buffer(hash, &auth, pin, strlen(pin), /* extend= */ false);
+ if (r < 0)
+ return r;
+
+ assert(auth.size > 0);
+ if (auth.buffer[auth.size - 1] == 0) {
+ log_debug("authValue digest ends in 0 which the TPM will remove and cause HMAC authorization failures, adjusting.");
+ auth.buffer[auth.size - 1] = 0xff;
+ }
+
+ *ret_auth = TAKE_STRUCT(auth);
+
+ return 0;
+}
+
static int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *pin) {
TPM2B_AUTH auth = {};
TSS2_RC rc;
@@ -2808,7 +2836,7 @@ static int tpm2_set_auth(Tpm2Context *c, const Tpm2Handle *handle, const char *p
CLEANUP_ERASE(auth);
- r = tpm2_digest_buffer(TPM2_ALG_SHA256, &auth, pin, strlen(pin), /* extend= */ false);
+ r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &auth);
if (r < 0)
return r;
@@ -3955,7 +3983,7 @@ int tpm2_seal(Tpm2Context *c,
CLEANUP_ERASE(hmac_sensitive);
if (pin) {
- r = tpm2_digest_buffer(TPM2_ALG_SHA256, &hmac_sensitive.userAuth, pin, strlen(pin), /* extend= */ false);
+ r = tpm2_get_pin_auth(TPM2_ALG_SHA256, pin, &hmac_sensitive.userAuth);
if (r < 0)
return r;
}