systemd/0632-tpm2-instead-of-adjust...

82 lines
4.0 KiB
Diff

From 7b0f212fe888bd03917de131ead35c4109cc723a Mon Sep 17 00:00:00 2001
From: Dan Streetman <ddstreet@ieee.org>
Date: Fri, 21 Jul 2023 11:23:22 -0400
Subject: [PATCH] tpm2: instead of adjusting authValue trailing 0(s), trim them
as required by tpm spec
To keep compatibility with any existing object authValues with trailing 0's,
change tpm2_get_pin_auth() to trim trailing 0's, which is what the TPM
implementation will do. This should retain compatibility with any existing
authValues that contain trailing 0's.
Note that any existing authValues with trailing 0's are unlikely to have worked
in the way that systemd uses them in object sealing, which is as a bind key for
the encryption (and policy) session. However, it is better to be compatible
with the TPM spec (and implementations) even if previously created objects that
are affected may not have worked.
Fixes: #28414
(cherry picked from commit 63477a71dfa39f0cb43854cb28df6606733063ef)
Related: RHEL-16182
---
src/shared/tpm2-util.c | 38 +++++++++++++++++++++++++++++++-------
1 file changed, 31 insertions(+), 7 deletions(-)
diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c
index 49e50a83ac..5bce39a994 100644
--- a/src/shared/tpm2-util.c
+++ b/src/shared/tpm2-util.c
@@ -2799,8 +2799,36 @@ int tpm2_digest_many_digests(
* 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. */
+ * digest that randomly happens to end in 0 must have the final 0(s) trimmed.
+ *
+ * This is required at 2 points. First, when setting the authValue during creation of new sealed objects, in
+ * tpm2_seal(). This only applies to newly created objects, of course. Second, when using a previously
+ * created sealed object that has an authValue set, we use the sealed objects as the session bind key. This
+ * requires calling SetAuth so tpm2-tss can correctly calculate the HMAC to use for the encryption session.
+ *
+ * TPM implementations will perform the trimming for any authValue for existing sealed objects, so the
+ * tpm2-tss library must also perform the trimming before HMAC calculation, but it does not yet; this bug is
+ * open to add the trimming: https://github.com/tpm2-software/tpm2-tss/issues/2664
+ *
+ * Until our minimum tpm2-tss version contains a fix for that bug, we must perform the trimming
+ * ourselves. Note that since we are trimming, which is exactly what a TPM implementation would do, this will
+ * work for both existing objects with a authValue ending in 0(s) as well as new sealed objects we create,
+ * which we will trim the 0(s) from before sending to the TPM.
+ */
+static void tpm2_trim_auth_value(TPM2B_AUTH *auth) {
+ bool trimmed = false;
+
+ assert(auth);
+
+ while (auth->size > 0 && auth->buffer[auth->size - 1] == 0) {
+ trimmed = true;
+ auth->size--;
+ }
+
+ if (trimmed)
+ log_debug("authValue ends in 0, trimming as required by the TPM2 specification Part 1 section 'HMAC Computation' authValue Note 2.");
+}
+
static int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *ret_auth) {
TPM2B_AUTH auth = {};
int r;
@@ -2812,11 +2840,7 @@ static int tpm2_get_pin_auth(TPMI_ALG_HASH hash, const char *pin, TPM2B_AUTH *re
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;
- }
+ tpm2_trim_auth_value(&auth);
*ret_auth = TAKE_STRUCT(auth);