[tpmdd-devel,RFC] tpm: seal with a policy
diff mbox

Message ID 1446306824-25175-1-git-send-email-jarkko.sakkinen@linux.intel.com
State New
Headers show

Commit Message

Jarkko Sakkinen Oct. 31, 2015, 3:53 p.m. UTC
Support for sealing with a policy.

Two new options for trusted keys:

* 'policydigest=': provide a policydigest for the seal operation.
* 'policyhandle=': provide handle for a policy session for unsealing.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/Kconfig    |  1 +
 drivers/char/tpm/tpm2-cmd.c | 20 +++++++++++++++++---
 include/keys/trusted-type.h |  3 +++
 security/keys/trusted.c     | 26 ++++++++++++++++++++++++--
 4 files changed, 45 insertions(+), 5 deletions(-)

Comments

Mimi Zohar Nov. 2, 2015, 12:48 p.m. UTC | #1
On Sat, 2015-10-31 at 17:53 +0200, Jarkko Sakkinen wrote:
> Support for sealing with a policy.
> 
> Two new options for trusted keys:
> 
> * 'policydigest=': provide a policydigest for the seal operation.
> * 'policyhandle=': provide handle for a policy session for unsealing.

Please expand the patch description explaining the motivation for these
new options.  In what cases are they needed?  Are they system or session
policies? 

Mimi

> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
>  drivers/char/tpm/Kconfig    |  1 +
>  drivers/char/tpm/tpm2-cmd.c | 20 +++++++++++++++++---
>  include/keys/trusted-type.h |  3 +++
>  security/keys/trusted.c     | 26 ++++++++++++++++++++++++--
>  4 files changed, 45 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
> index 3b84a8b..bd86261 100644
> --- a/drivers/char/tpm/Kconfig
> +++ b/drivers/char/tpm/Kconfig
> @@ -6,6 +6,7 @@ menuconfig TCG_TPM
>  	tristate "TPM Hardware Support"
>  	depends on HAS_IOMEM
>  	select SECURITYFS
> +	select CRYPTO_HASH_INFO
>  	---help---
>  	  If you have a TPM security chip in your system, which
>  	  implements the Trusted Computing Group's specification,
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index b08a0b4..6f567c3 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -463,6 +463,9 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
>  			return -EINVAL;
>  	}
> 
> +	if (options->policydigest_len > hash_digest_size[options->hash])
> +		return -EINVAL;
> +
>  	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
>  	if (rc)
>  		return rc;
> @@ -488,8 +491,17 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
> 
>  	tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
>  	tpm_buf_append_u16(&buf, hash);
> -	tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
> -	tpm_buf_append_u16(&buf, 0); /* policy digest size */
> +
> +	if (options->policydigest_len) {
> +		tpm_buf_append_u32(&buf, 0);
> +		tpm_buf_append_u16(&buf, options->policydigest_len);
> +		tpm_buf_append(&buf, options->policydigest,
> +			       options->policydigest_len);
> +	} else {
> +		tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
> +		tpm_buf_append_u16(&buf, 0);
> +	}
> +
>  	tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
>  	tpm_buf_append_u16(&buf, 0);
> 
> @@ -617,7 +629,9 @@ static int tpm2_unseal(struct tpm_chip *chip,
>  		return rc;
> 
>  	tpm_buf_append_u32(&buf, blob_handle);
> -	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
> +	tpm2_buf_append_auth(&buf,
> +			     options->policyhandle ?
> +			     options->policyhandle : TPM2_RS_PW,
>  			     NULL /* nonce */, 0,
>  			     0 /* session_attributes */,
>  			     options->blobauth /* hmac */,
> diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
> index a6a1008..e4beeca 100644
> --- a/include/keys/trusted-type.h
> +++ b/include/keys/trusted-type.h
> @@ -37,6 +37,9 @@ struct trusted_key_options {
>  	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
>  	int pcrlock;
>  	uint32_t hash;
> +	uint32_t policydigest_len;
> +	unsigned char *policydigest;
> +	uint32_t policyhandle;
>  };
> 
>  extern struct key_type key_type_trusted;
> diff --git a/security/keys/trusted.c b/security/keys/trusted.c
> index 7a87bcd..ea043ff 100644
> --- a/security/keys/trusted.c
> +++ b/security/keys/trusted.c
> @@ -713,6 +713,8 @@ enum {
>  	Opt_keyhandle, Opt_keyauth, Opt_blobauth,
>  	Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
>  	Opt_hash,
> +	Opt_policydigest,
> +	Opt_policyhandle,
>  };
> 
>  static const match_table_t key_tokens = {
> @@ -726,6 +728,8 @@ static const match_table_t key_tokens = {
>  	{Opt_pcrlock, "pcrlock=%s"},
>  	{Opt_migratable, "migratable=%s"},
>  	{Opt_hash, "hash=%s"},
> +	{Opt_policydigest, "policydigest=%s"},
> +	{Opt_policyhandle, "policyhandle=%s"},
>  	{Opt_err, NULL}
>  };
> 
> @@ -804,6 +808,17 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>  			if (i == HASH_ALGO__LAST ||
>  			    (!res && i != HASH_ALGO_SHA1))
>  				return -EINVAL;
> +		case Opt_policydigest:
> +			opt->policydigest_len = strlen(args[0].from);
> +			opt->policydigest = kstrdup(args[0].from, GFP_KERNEL);
> +			if (!opt->policydigest)
> +				return -ENOMEM;
> +			break;
> +		case Opt_policyhandle:
> +			res = kstrtoul(args[0].from, 16, &handle);
> +			if (res < 0)
> +				return -EINVAL;
> +			opt->policyhandle = handle;
>  			break;
>  		default:
>  			return -EINVAL;
> @@ -897,6 +912,13 @@ static struct trusted_key_options *trusted_options_alloc(void)
>  	return options;
>  }
> 
> +static void trusted_options_free(struct trusted_key_options *options)
> +{
> +	if (options->policydigest)
> +		kfree(options->policydigest);
> +	kfree(options);
> +}
> +
>  static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
>  {
>  	struct trusted_key_payload *p = NULL;
> @@ -1003,7 +1025,7 @@ static int trusted_instantiate(struct key *key,
>  		ret = pcrlock(options->pcrlock);
>  out:
>  	kfree(datablob);
> -	kfree(options);
> +	trusted_options_free(options);
>  	if (!ret)
>  		rcu_assign_keypointer(key, payload);
>  	else
> @@ -1091,7 +1113,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
>  	call_rcu(&p->rcu, trusted_rcu_free);
>  out:
>  	kfree(datablob);
> -	kfree(new_o);
> +	trusted_options_free(new_o);
>  	return ret;
>  }
> 



------------------------------------------------------------------------------
Jarkko Sakkinen Nov. 2, 2015, 5:44 p.m. UTC | #2
On Mon, Nov 02, 2015 at 07:48:42AM -0500, Mimi Zohar wrote:
> On Sat, 2015-10-31 at 17:53 +0200, Jarkko Sakkinen wrote:
> > Support for sealing with a policy.
> > 
> > Two new options for trusted keys:
> > 
> > * 'policydigest=': provide a policydigest for the seal operation.
> > * 'policyhandle=': provide handle for a policy session for unsealing.
> 
> Please expand the patch description explaining the motivation for these
> new options.  In what cases are they needed?  Are they system or session
> policies? 

They are session policies. By using TPM2 commands you can specify
conditions in which unseal should work like auth value, PCRs, localities
and so forth and combine these with logical connectors.

I'll think about this and write proper documentation.

> Mimi

/Jarkko

------------------------------------------------------------------------------

Patch
diff mbox

diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 3b84a8b..bd86261 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -6,6 +6,7 @@  menuconfig TCG_TPM
 	tristate "TPM Hardware Support"
 	depends on HAS_IOMEM
 	select SECURITYFS
+	select CRYPTO_HASH_INFO
 	---help---
 	  If you have a TPM security chip in your system, which
 	  implements the Trusted Computing Group's specification,
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index b08a0b4..6f567c3 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -463,6 +463,9 @@  int tpm2_seal_trusted(struct tpm_chip *chip,
 			return -EINVAL;
 	}
 
+	if (options->policydigest_len > hash_digest_size[options->hash])
+		return -EINVAL;
+
 	rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
 	if (rc)
 		return rc;
@@ -488,8 +491,17 @@  int tpm2_seal_trusted(struct tpm_chip *chip,
 
 	tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH);
 	tpm_buf_append_u16(&buf, hash);
-	tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
-	tpm_buf_append_u16(&buf, 0); /* policy digest size */
+
+	if (options->policydigest_len) {
+		tpm_buf_append_u32(&buf, 0);
+		tpm_buf_append_u16(&buf, options->policydigest_len);
+		tpm_buf_append(&buf, options->policydigest,
+			       options->policydigest_len);
+	} else {
+		tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
+		tpm_buf_append_u16(&buf, 0);
+	}
+
 	tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
 	tpm_buf_append_u16(&buf, 0);
 
@@ -617,7 +629,9 @@  static int tpm2_unseal(struct tpm_chip *chip,
 		return rc;
 
 	tpm_buf_append_u32(&buf, blob_handle);
-	tpm2_buf_append_auth(&buf, TPM2_RS_PW,
+	tpm2_buf_append_auth(&buf,
+			     options->policyhandle ?
+			     options->policyhandle : TPM2_RS_PW,
 			     NULL /* nonce */, 0,
 			     0 /* session_attributes */,
 			     options->blobauth /* hmac */,
diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
index a6a1008..e4beeca 100644
--- a/include/keys/trusted-type.h
+++ b/include/keys/trusted-type.h
@@ -37,6 +37,9 @@  struct trusted_key_options {
 	unsigned char pcrinfo[MAX_PCRINFO_SIZE];
 	int pcrlock;
 	uint32_t hash;
+	uint32_t policydigest_len;
+	unsigned char *policydigest;
+	uint32_t policyhandle;
 };
 
 extern struct key_type key_type_trusted;
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 7a87bcd..ea043ff 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -713,6 +713,8 @@  enum {
 	Opt_keyhandle, Opt_keyauth, Opt_blobauth,
 	Opt_pcrinfo, Opt_pcrlock, Opt_migratable,
 	Opt_hash,
+	Opt_policydigest,
+	Opt_policyhandle,
 };
 
 static const match_table_t key_tokens = {
@@ -726,6 +728,8 @@  static const match_table_t key_tokens = {
 	{Opt_pcrlock, "pcrlock=%s"},
 	{Opt_migratable, "migratable=%s"},
 	{Opt_hash, "hash=%s"},
+	{Opt_policydigest, "policydigest=%s"},
+	{Opt_policyhandle, "policyhandle=%s"},
 	{Opt_err, NULL}
 };
 
@@ -804,6 +808,17 @@  static int getoptions(char *c, struct trusted_key_payload *pay,
 			if (i == HASH_ALGO__LAST ||
 			    (!res && i != HASH_ALGO_SHA1))
 				return -EINVAL;
+		case Opt_policydigest:
+			opt->policydigest_len = strlen(args[0].from);
+			opt->policydigest = kstrdup(args[0].from, GFP_KERNEL);
+			if (!opt->policydigest)
+				return -ENOMEM;
+			break;
+		case Opt_policyhandle:
+			res = kstrtoul(args[0].from, 16, &handle);
+			if (res < 0)
+				return -EINVAL;
+			opt->policyhandle = handle;
 			break;
 		default:
 			return -EINVAL;
@@ -897,6 +912,13 @@  static struct trusted_key_options *trusted_options_alloc(void)
 	return options;
 }
 
+static void trusted_options_free(struct trusted_key_options *options)
+{
+	if (options->policydigest)
+		kfree(options->policydigest);
+	kfree(options);
+}
+
 static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
 {
 	struct trusted_key_payload *p = NULL;
@@ -1003,7 +1025,7 @@  static int trusted_instantiate(struct key *key,
 		ret = pcrlock(options->pcrlock);
 out:
 	kfree(datablob);
-	kfree(options);
+	trusted_options_free(options);
 	if (!ret)
 		rcu_assign_keypointer(key, payload);
 	else
@@ -1091,7 +1113,7 @@  static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
 	call_rcu(&p->rcu, trusted_rcu_free);
 out:
 	kfree(datablob);
-	kfree(new_o);
+	trusted_options_free(new_o);
 	return ret;
 }