diff mbox series

tpm: validate object type in tpm2_handle_mso()

Message ID 20240707010916.78918-1-jarkko@kernel.org (mailing list archive)
State New
Headers show
Series tpm: validate object type in tpm2_handle_mso() | expand

Commit Message

Jarkko Sakkinen July 7, 2024, 1:09 a.m. UTC
tpm2_handle_mso() lacks validation for the object type. Validate that
value is one of the allowed values in order to detect errors.

Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
---
 drivers/char/tpm/tpm2-sessions.c | 44 +++++++++++++++++++++++---------
 include/linux/tpm.h              | 22 ++++++++++++++--
 2 files changed, 52 insertions(+), 14 deletions(-)

Comments

Jarkko Sakkinen July 7, 2024, 10:14 a.m. UTC | #1
On Sun Jul 7, 2024 at 4:09 AM EEST, Jarkko Sakkinen wrote:
> tpm2_handle_mso() lacks validation for the object type. Validate that
> value is one of the allowed values in order to detect errors.
>
> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
> ---

Just something I spotted while fixing the other bug.

If an API that claims to return enum, the results would
better *only* be values from that enum.

Also this API is using alien acronym "MSO" for the enum
fields while the spec uses "HT".

BR, Jarkko
diff mbox series

Patch

diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index 907ac9956a78..95f38af605d7 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -419,6 +419,27 @@  void tpm_buf_append_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf,
 }
 EXPORT_SYMBOL(tpm_buf_append_hmac_session);
 
+static int tpm2_sha256_update_name(struct sha256_state *sctx, u32 handle, void *name)
+{
+	__be32 handle_be32;
+	int mso;
+
+	mso = tpm2_mso_handle(handle);
+	if (mso < 0)
+		return mso;
+
+	if (mso == TPM2_MSO_PERSISTENT || mso == TPM2_MSO_VOLATILE ||
+	    mso == TPM2_MSO_NVRAM) {
+		sha256_update(sctx, name, name_size(name));
+	} else {
+		handle_be32 = cpu_to_be32(handle);
+
+		sha256_update(sctx, (u8 *)&handle_be32, 4);
+	}
+
+	return 0;
+}
+
 /**
  * tpm_buf_fill_hmac_session() - finalize the session HMAC
  * @chip: the TPM chip structure
@@ -537,17 +558,10 @@  void tpm_buf_fill_hmac_session(struct tpm_chip *chip, struct tpm_buf *buf)
 	sha256_update(&sctx, (u8 *)&head->ordinal, sizeof(head->ordinal));
 	/* add the handle names */
 	for (i = 0; i < handles; i++) {
-		enum tpm2_mso_type mso = tpm2_handle_mso(auth->name_h[i]);
-
-		if (mso == TPM2_MSO_PERSISTENT ||
-		    mso == TPM2_MSO_VOLATILE ||
-		    mso == TPM2_MSO_NVRAM) {
-			sha256_update(&sctx, auth->name[i],
-				      name_size(auth->name[i]));
-		} else {
-			__be32 h = cpu_to_be32(auth->name_h[i]);
-
-			sha256_update(&sctx, (u8 *)&h, 4);
+		if (tpm2_sha256_update_name(&sctx, auth->name_h[i], auth->name[i]) < 0) {
+			dev_err(&chip->dev, "handle with an invalid MSO: 0x%08x\n",
+				auth->name_h[i]);
+			return;
 		}
 	}
 	if (offset_s != tpm_buf_length(buf))
@@ -635,9 +649,15 @@  static int tpm2_read_public(struct tpm_chip *chip, u32 handle, char *name)
 void tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf,
 			 u32 handle, u8 *name)
 {
-	enum tpm2_mso_type mso = tpm2_handle_mso(handle);
 	struct tpm2_auth *auth = chip->auth;
 	int slot;
+	int mso;
+
+	mso = tpm2_mso_handle(handle);
+	if (mso < 0) {
+		dev_err(&chip->dev, "handle with an invalid MSO: 0x%08x\n", handle);
+		return;
+	}
 
 	slot = (tpm_buf_length(buf) - TPM_HEADER_SIZE)/4;
 	if (slot >= AUTH_MAX_NAMES) {
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 21a67dc9efe8..478513cda698 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -304,9 +304,27 @@  enum tpm2_mso_type {
 	TPM2_MSO_PERSISTENT	= 0x81,
 };
 
-static inline enum tpm2_mso_type tpm2_handle_mso(u32 handle)
+/**
+ * tpm2_mso_handle() - Extract handle type from the handle
+ * @handle:	an object handle
+ *
+ * Return:
+ * * A value from &tpm_mso_type on success.
+ * * -EINVAL on failure.
+ */
+static inline int tpm2_mso_handle(u32 handle)
 {
-	return handle >> 24;
+	int mso = handle >> 24;
+
+	if (mso == TPM2_MSO_NVRAM ||
+	    mso == TPM2_MSO_SESSION ||
+	    mso == TPM2_MSO_POLICY ||
+	    mso == TPM2_MSO_PERMANENT ||
+	    mso == TPM2_MSO_VOLATILE ||
+	    mso == TPM2_MSO_PERSISTENT)
+		return mso;
+
+	return -EINVAL;
 }
 
 enum tpm2_capabilities {