All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: linux-integrity@vger.kernel.org
Cc: Mimi Zohar <zohar@linux.ibm.com>,
	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>,
	David Woodhouse <dwmw2@infradead.org>,
	keyrings@vger.kernel.org
Subject: [PATCH v4 9/9] security: keys: trusted: add password based authorizations to policy keys
Date: Mon, 30 Dec 2019 17:38:02 +0000	[thread overview]
Message-ID: <20191230173802.8731-10-James.Bottomley@HansenPartnership.com> (raw)
In-Reply-To: <20191230173802.8731-1-James.Bottomley@HansenPartnership.com>

TPM 2.0 has a trick where you can turn off the usual HMAC password
session requirement using TPM2_PolicyPassword, so everywhere we see a
TPM2_PolicyAuthValue (which does require HMAC password), we replace
with the TPM2_PolicyPassword command instead.  This allows us to use
passwords with TPM 2.0 trusted keys that also have a policy.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 include/linux/tpm.h                       |  1 +
 security/keys/trusted-keys/tpm2-policy.c  | 16 ++++++++++++++-
 security/keys/trusted-keys/trusted_tpm2.c | 34 ++++++++++++++++++++++++++++++-
 3 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index e32e9728adce..5026a06977e1 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -233,6 +233,7 @@ enum tpm2_command_codes {
 	TPM2_CC_PCR_EXTEND	        = 0x0182,
 	TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185,
 	TPM2_CC_HASH_SEQUENCE_START     = 0x0186,
+	TPM2_CC_POLICY_PASSWORD		= 0x018c,
 	TPM2_CC_CREATE_LOADED           = 0x0191,
 	TPM2_CC_LAST		        = 0x0193, /* Spec 1.36 */
 };
diff --git a/security/keys/trusted-keys/tpm2-policy.c b/security/keys/trusted-keys/tpm2-policy.c
index 3c7a8e6c84c8..2c93197edf2b 100644
--- a/security/keys/trusted-keys/tpm2-policy.c
+++ b/security/keys/trusted-keys/tpm2-policy.c
@@ -193,7 +193,8 @@ int tpm2_generate_policy_digest(struct tpm2_policies *pols,
 			policy = digest;
 			len = *plen;
 		}
-		crypto_shash_update(sdesc, policy, len);
+		if (len)
+			crypto_shash_update(sdesc, policy, len);
 		/* now output the intermediate to the policydigest */
 		crypto_shash_final(sdesc, policydigest);
 
@@ -316,6 +317,16 @@ int tpm2_get_policy_session(struct tpm_chip *chip, struct tpm2_policies *pols,
 		u32 cmd = pols->code[i];
 		struct tpm_buf buf;
 
+		if (cmd = TPM2_CC_POLICY_AUTHVALUE)
+			/*
+			 * both PolicyAuthValue and PolicyPassword
+			 * hash to the same thing, but one triggers
+			 * HMAC authentication and the other simple
+			 * authentication.  Since we have no HMAC
+			 * code, we're choosing the simple
+			 */
+			cmd = TPM2_CC_POLICY_PASSWORD;
+
 		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, cmd);
 		if (rc)
 			return rc;
@@ -357,6 +368,9 @@ int tpm2_get_policy_session(struct tpm_chip *chip, struct tpm2_policies *pols,
 		}
 		default:
 			failure = "unknown policy";
+			if (pols->len[i])
+				tpm_buf_append(&buf, pols->policies[i],
+					       pols->len[i]);
 			break;
 		}
 		rc = tpm_send(chip, buf.data, tpm_buf_length(&buf));
diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 1f039b39aa7f..169846fde5f7 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -244,6 +244,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 	u32 flags;
 	int i;
 	int rc;
+	static const int POLICY_SIZE = 2 * PAGE_SIZE;
 
 	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
 		if (options->hash = tpm2_hash_map[i].crypto_id) {
@@ -264,7 +265,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		/* 4 array len, 2 hash alg */
 		const int len = 4 + 2 + options->pcrinfo_len;
 
-		pols = kmalloc(sizeof(*pols) + len, GFP_KERNEL);
+		pols = kmalloc(POLICY_SIZE, GFP_KERNEL);
 		if (!pols)
 			return -ENOMEM;
 
@@ -285,6 +286,37 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		return -EINVAL;
 	}
 
+	/*
+	 * if we already have a policy, we have to add authorization
+	 * to it.  If we don't, we can simply follow the usual
+	 * non-policy route.
+	 */
+	if (options->blobauth_len != 0 && payload->policies) {
+		struct tpm2_policies *pols;
+		static u8 *scratch;
+		int i;
+		bool found = false;
+
+		pols = payload->policies;
+
+		/* make sure it's not already in policy */
+		for (i = 0; i < pols->count; i++) {
+			if (pols->code[i] = TPM2_CC_POLICY_AUTHVALUE) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			i = pols->count++;
+			scratch = pols->policies[i - 1] + pols->len[i - 1];
+			/* the TPM2_PolicyPassword command has no payload */
+			pols->policies[i] = scratch;
+			pols->len[i] = 0;
+			pols->code[i] = TPM2_CC_POLICY_AUTHVALUE;
+		}
+	}
+
 	if (payload->policies) {
 		rc = tpm2_generate_policy_digest(payload->policies,
 						 options->hash,
-- 
2.16.4

WARNING: multiple messages have this Message-ID (diff)
From: James Bottomley <James.Bottomley@HansenPartnership.com>
To: linux-integrity@vger.kernel.org
Cc: Mimi Zohar <zohar@linux.ibm.com>,
	Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>,
	David Woodhouse <dwmw2@infradead.org>,
	keyrings@vger.kernel.org
Subject: [PATCH v4 9/9] security: keys: trusted: add password based authorizations to policy keys
Date: Mon, 30 Dec 2019 09:38:02 -0800	[thread overview]
Message-ID: <20191230173802.8731-10-James.Bottomley@HansenPartnership.com> (raw)
In-Reply-To: <20191230173802.8731-1-James.Bottomley@HansenPartnership.com>

TPM 2.0 has a trick where you can turn off the usual HMAC password
session requirement using TPM2_PolicyPassword, so everywhere we see a
TPM2_PolicyAuthValue (which does require HMAC password), we replace
with the TPM2_PolicyPassword command instead.  This allows us to use
passwords with TPM 2.0 trusted keys that also have a policy.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
---
 include/linux/tpm.h                       |  1 +
 security/keys/trusted-keys/tpm2-policy.c  | 16 ++++++++++++++-
 security/keys/trusted-keys/trusted_tpm2.c | 34 ++++++++++++++++++++++++++++++-
 3 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index e32e9728adce..5026a06977e1 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -233,6 +233,7 @@ enum tpm2_command_codes {
 	TPM2_CC_PCR_EXTEND	        = 0x0182,
 	TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185,
 	TPM2_CC_HASH_SEQUENCE_START     = 0x0186,
+	TPM2_CC_POLICY_PASSWORD		= 0x018c,
 	TPM2_CC_CREATE_LOADED           = 0x0191,
 	TPM2_CC_LAST		        = 0x0193, /* Spec 1.36 */
 };
diff --git a/security/keys/trusted-keys/tpm2-policy.c b/security/keys/trusted-keys/tpm2-policy.c
index 3c7a8e6c84c8..2c93197edf2b 100644
--- a/security/keys/trusted-keys/tpm2-policy.c
+++ b/security/keys/trusted-keys/tpm2-policy.c
@@ -193,7 +193,8 @@ int tpm2_generate_policy_digest(struct tpm2_policies *pols,
 			policy = digest;
 			len = *plen;
 		}
-		crypto_shash_update(sdesc, policy, len);
+		if (len)
+			crypto_shash_update(sdesc, policy, len);
 		/* now output the intermediate to the policydigest */
 		crypto_shash_final(sdesc, policydigest);
 
@@ -316,6 +317,16 @@ int tpm2_get_policy_session(struct tpm_chip *chip, struct tpm2_policies *pols,
 		u32 cmd = pols->code[i];
 		struct tpm_buf buf;
 
+		if (cmd == TPM2_CC_POLICY_AUTHVALUE)
+			/*
+			 * both PolicyAuthValue and PolicyPassword
+			 * hash to the same thing, but one triggers
+			 * HMAC authentication and the other simple
+			 * authentication.  Since we have no HMAC
+			 * code, we're choosing the simple
+			 */
+			cmd = TPM2_CC_POLICY_PASSWORD;
+
 		rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, cmd);
 		if (rc)
 			return rc;
@@ -357,6 +368,9 @@ int tpm2_get_policy_session(struct tpm_chip *chip, struct tpm2_policies *pols,
 		}
 		default:
 			failure = "unknown policy";
+			if (pols->len[i])
+				tpm_buf_append(&buf, pols->policies[i],
+					       pols->len[i]);
 			break;
 		}
 		rc = tpm_send(chip, buf.data, tpm_buf_length(&buf));
diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c
index 1f039b39aa7f..169846fde5f7 100644
--- a/security/keys/trusted-keys/trusted_tpm2.c
+++ b/security/keys/trusted-keys/trusted_tpm2.c
@@ -244,6 +244,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 	u32 flags;
 	int i;
 	int rc;
+	static const int POLICY_SIZE = 2 * PAGE_SIZE;
 
 	for (i = 0; i < ARRAY_SIZE(tpm2_hash_map); i++) {
 		if (options->hash == tpm2_hash_map[i].crypto_id) {
@@ -264,7 +265,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		/* 4 array len, 2 hash alg */
 		const int len = 4 + 2 + options->pcrinfo_len;
 
-		pols = kmalloc(sizeof(*pols) + len, GFP_KERNEL);
+		pols = kmalloc(POLICY_SIZE, GFP_KERNEL);
 		if (!pols)
 			return -ENOMEM;
 
@@ -285,6 +286,37 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 		return -EINVAL;
 	}
 
+	/*
+	 * if we already have a policy, we have to add authorization
+	 * to it.  If we don't, we can simply follow the usual
+	 * non-policy route.
+	 */
+	if (options->blobauth_len != 0 && payload->policies) {
+		struct tpm2_policies *pols;
+		static u8 *scratch;
+		int i;
+		bool found = false;
+
+		pols = payload->policies;
+
+		/* make sure it's not already in policy */
+		for (i = 0; i < pols->count; i++) {
+			if (pols->code[i] == TPM2_CC_POLICY_AUTHVALUE) {
+				found = true;
+				break;
+			}
+		}
+
+		if (!found) {
+			i = pols->count++;
+			scratch = pols->policies[i - 1] + pols->len[i - 1];
+			/* the TPM2_PolicyPassword command has no payload */
+			pols->policies[i] = scratch;
+			pols->len[i] = 0;
+			pols->code[i] = TPM2_CC_POLICY_AUTHVALUE;
+		}
+	}
+
 	if (payload->policies) {
 		rc = tpm2_generate_policy_digest(payload->policies,
 						 options->hash,
-- 
2.16.4


  parent reply	other threads:[~2019-12-30 17:38 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-12-30 17:37 [PATCH v4 0/9] TPM 2.0 trusted keys with attached policy James Bottomley
2019-12-30 17:37 ` James Bottomley
2019-12-30 17:37 ` [PATCH v4 1/9] lib: add asn.1 encoder James Bottomley
2019-12-30 17:37   ` James Bottomley
2020-01-06 18:09   ` Jarkko Sakkinen
2020-01-06 18:09     ` Jarkko Sakkinen
2020-01-07  0:17     ` James Bottomley
2020-01-07  0:17       ` James Bottomley
2019-12-30 17:37 ` [PATCH v4 2/9] oid_registry: Add TCG defined OIDS for TPM keys James Bottomley
2019-12-30 17:37   ` James Bottomley
2019-12-30 17:37 ` [PATCH v4 3/9] security: keys: trusted fix tpm2 authorizations James Bottomley
2019-12-30 17:37   ` James Bottomley
2020-01-06 21:45   ` Jarkko Sakkinen
2020-01-06 21:45     ` Jarkko Sakkinen
2020-01-06 21:48     ` Jarkko Sakkinen
2020-01-06 21:48       ` Jarkko Sakkinen
2020-01-07  1:08     ` James Bottomley
2020-01-07  1:08       ` James Bottomley
2020-01-08 16:19       ` Jarkko Sakkinen
2020-01-08 16:19         ` Jarkko Sakkinen
2019-12-30 17:37 ` [PATCH v4 4/9] security: keys: trusted: use ASN.1 tpm2 key format for the blobs James Bottomley
2019-12-30 17:37   ` James Bottomley
2020-01-06 21:53   ` Jarkko Sakkinen
2020-01-06 21:53     ` Jarkko Sakkinen
2019-12-30 17:37 ` [PATCH v4 5/9] security: keys: trusted: Make sealed key properly interoperable James Bottomley
2019-12-30 17:37   ` James Bottomley
2020-01-06 21:58   ` Jarkko Sakkinen
2020-01-06 21:58     ` Jarkko Sakkinen
2019-12-30 17:37 ` [PATCH v4 6/9] security: keys: trusted: add PCR policy to TPM2 keys James Bottomley
2019-12-30 17:37   ` James Bottomley
2019-12-30 17:38 ` [PATCH v4 7/9] security: keys: trusted: add ability to specify arbitrary policy James Bottomley
2019-12-30 17:38   ` James Bottomley
2019-12-30 17:38 ` [PATCH v4 8/9] security: keys: trusted: implement counter/timer policy James Bottomley
2019-12-30 17:38   ` James Bottomley
2019-12-30 17:38 ` James Bottomley [this message]
2019-12-30 17:38   ` [PATCH v4 9/9] security: keys: trusted: add password based authorizations to policy keys James Bottomley
2019-12-31 16:05 ` [PATCH v4 0/9] TPM 2.0 trusted keys with attached policy Jarkko Sakkinen
2019-12-31 16:05   ` Jarkko Sakkinen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191230173802.8731-10-James.Bottomley@HansenPartnership.com \
    --to=james.bottomley@hansenpartnership.com \
    --cc=dwmw2@infradead.org \
    --cc=jarkko.sakkinen@linux.intel.com \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-integrity@vger.kernel.org \
    --cc=zohar@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.