Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1271380 > unrolled thread

[PATCH 2/2] keys, trusted: seal with a policy

Started byJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
First post2015-11-17 17:30 +0100
Last post2015-11-23 16:00 +0100
Articles 8 — 3 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH 2/2] keys, trusted: seal with a policy Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2015-11-17 17:30 +0100
    Re: [PATCH 2/2] keys, trusted: seal with a policy James Morris <jmorris@namei.org> - 2015-11-18 01:30 +0100
      Re: [PATCH 2/2] keys, trusted: seal with a policy Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2015-11-18 08:10 +0100
        Re: [PATCH 2/2] keys, trusted: seal with a policy James Morris <jmorris@namei.org> - 2015-11-20 03:40 +0100
    RE: [tpmdd-devel] [PATCH 2/2] keys, trusted: seal with a policy "Fuchs, Andreas" <andreas.fuchs@sit.fraunhofer.de> - 2015-11-19 12:10 +0100
      Re: [tpmdd-devel] [PATCH 2/2] keys, trusted: seal with a policy Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2015-11-20 16:00 +0100
    Re: [PATCH 2/2] keys, trusted: seal with a policy Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2015-11-21 20:00 +0100
    Re: [PATCH 2/2] keys, trusted: seal with a policy Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2015-11-23 16:00 +0100

#1271380 — [PATCH 2/2] keys, trusted: seal with a policy

FromJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Date2015-11-17 17:30 +0100
Subject[PATCH 2/2] keys, trusted: seal with a policy
Message-ID<qvRiO-7og-7@gated-at.bofh.it>
Support for sealing with a authorization policy.

Two new options for trusted keys:

* 'policydigest=': provide an auth policy digest for sealing.
* 'policyhandle=': provide a policy session handle for unsealing.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 Documentation/security/keys-trusted-encrypted.txt | 34 ++++++++++-------
 drivers/char/tpm/tpm2-cmd.c                       | 24 ++++++++++--
 include/keys/trusted-type.h                       |  3 ++
 security/keys/trusted.c                           | 46 ++++++++++++++++++++++-
 4 files changed, 87 insertions(+), 20 deletions(-)

diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt
index fd2565b..324ddf5 100644
--- a/Documentation/security/keys-trusted-encrypted.txt
+++ b/Documentation/security/keys-trusted-encrypted.txt
@@ -27,20 +27,26 @@ Usage:
     keyctl print keyid
 
     options:
-       keyhandle= ascii hex value of sealing key default 0x40000000 (SRK)
-       keyauth=	  ascii hex auth for sealing key default 0x00...i
-		  (40 ascii zeros)
-       blobauth=  ascii hex auth for sealed data default 0x00...
-		  (40 ascii zeros)
-       blobauth=  ascii hex auth for sealed data default 0x00...
-		  (40 ascii zeros)
-       pcrinfo=	  ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
-       pcrlock=	  pcr number to be extended to "lock" blob
-       migratable= 0|1 indicating permission to reseal to new PCR values,
-                   default 1 (resealing allowed)
-       hash=      hash algorithm name as a string. For TPM 1.x the only
-                  allowed value is sha1. For TPM 2.x the allowed values
-		  are sha1, sha256, sha384, sha512 and sm3-256.
+       keyhandle=    ascii hex value of sealing key default 0x40000000 (SRK)
+       keyauth=	     ascii hex auth for sealing key default 0x00...i
+                     (40 ascii zeros)
+       blobauth=     ascii hex auth for sealed data default 0x00...
+                     (40 ascii zeros)
+       blobauth=     ascii hex auth for sealed data default 0x00...
+                     (40 ascii zeros)
+       pcrinfo=	     ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
+       pcrlock=	     pcr number to be extended to "lock" blob
+       migratable=   0|1 indicating permission to reseal to new PCR values,
+                     default 1 (resealing allowed)
+       hash=         hash algorithm name as a string. For TPM 1.x the only
+                     allowed value is sha1. For TPM 2.x the allowed values
+                     are sha1, sha256, sha384, sha512 and sm3-256.
+       policydigest= digest for the authorization policy. must be calculated
+                     with the same hash algorithm as specified by the 'hash='
+                     option.
+       policyhandle= handle to an authorization policy session that defines the
+                     same policy and with the same hash algorithm as was used to
+                     seal the key.
 
 "keyctl print" returns an ascii hex copy of the sealed key, which is in standard
 TPM_STORED_DATA format.  The key length for new keys are always in bytes.
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index d9d0822..45a6340 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -478,12 +478,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
 	tpm_buf_append_u8(&buf, payload->migratable);
 
 	/* public */
-	tpm_buf_append_u16(&buf, 14);
+	if (options->policydigest)
+		tpm_buf_append_u16(&buf, 14 + options->digest_len);
+	else
+		tpm_buf_append_u16(&buf, 14);
 
 	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 */
+
+	/* policy */
+	if (options->policydigest) {
+		tpm_buf_append_u32(&buf, 0);
+		tpm_buf_append_u16(&buf, options->digest_len);
+		tpm_buf_append(&buf, options->policydigest,
+			       options->digest_len);
+	} else {
+		tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
+		tpm_buf_append_u16(&buf, 0);
+	}
+
+	/* public parameters */
 	tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
 	tpm_buf_append_u16(&buf, 0);
 
@@ -613,7 +627,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..2c3f9f7 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 digest_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 b5b0a55..b726a83 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}
 };
 
@@ -739,6 +743,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 	int res;
 	unsigned long handle;
 	unsigned long lock;
+	unsigned int policydigest_len;
 	int i;
 	int tpm2;
 
@@ -747,6 +752,8 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 		return tpm2;
 
 	opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
+	opt->digest_len = hash_digest_size[opt->hash];
+	policydigest_len = opt->digest_len;
 
 	while ((p = strsep(&c, " \t"))) {
 		if (*p == '\0' || *p == ' ' || *p == '\t')
@@ -802,6 +809,8 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 			for (i = 0; i < HASH_ALGO__LAST; i++) {
 				if (!strcmp(args[0].from, hash_algo_name[i])) {
 					opt->hash = i;
+					opt->digest_len =
+						hash_digest_size[opt->hash];
 					break;
 				}
 			}
@@ -812,10 +821,37 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
 				return -EINVAL;
 			}
 			break;
+		case Opt_policydigest:
+			if (!tpm2 ||
+			    strlen(args[0].from) != (2 * opt->digest_len))
+				return -EINVAL;
+			kfree(opt->policydigest);
+			opt->policydigest = kzalloc(opt->digest_len,
+						    GFP_KERNEL);
+			if (!opt->policydigest)
+				return -ENOMEM;
+			res = hex2bin(opt->policydigest, args[0].from,
+				      opt->digest_len);
+			if (res < 0)
+				return -EINVAL;
+			policydigest_len = opt->digest_len;
+			break;
+		case Opt_policyhandle:
+			if (!tpm2)
+				return -EINVAL;
+			res = kstrtoul(args[0].from, 16, &handle);
+			if (res < 0)
+				return -EINVAL;
+			opt->policyhandle = handle;
+			break;
 		default:
 			return -EINVAL;
 		}
 	}
+
+	if (opt->policydigest && policydigest_len != opt->digest_len)
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -904,6 +940,12 @@ static struct trusted_key_options *trusted_options_alloc(void)
 	return options;
 }
 
+static void trusted_options_free(struct trusted_key_options *options)
+{
+	kfree(options->policydigest);
+	kfree(options);
+}
+
 static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
 {
 	struct trusted_key_payload *p = NULL;
@@ -1010,7 +1052,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
@@ -1098,7 +1140,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;
 }
 
-- 
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1271765

FromJames Morris <jmorris@namei.org>
Date2015-11-18 01:30 +0100
Message-ID<qvYNk-3Of-15@gated-at.bofh.it>
In reply to#1271380
On Tue, 17 Nov 2015, Jarkko Sakkinen wrote:

>  			}
>  			break;
> +		case Opt_policydigest:
> +			if (!tpm2 ||
> +			    strlen(args[0].from) != (2 * opt->digest_len))
> +				return -EINVAL;
> +			kfree(opt->policydigest);
> +			opt->policydigest = kzalloc(opt->digest_len,
> +						    GFP_KERNEL);

Is it correct to kfree opt->policydigest here before allocating it?


> +			if (!opt->policydigest)
> +				return -ENOMEM;
> +			res = hex2bin(opt->policydigest, args[0].from,
> +				      opt->digest_len);
> +			if (res < 0)
> +				return -EINVAL;

Do you need to kfree it here on error?

-- 
James Morris
<jmorris@namei.org>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1271888

FromJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Date2015-11-18 08:10 +0100
Message-ID<qw52p-86c-5@gated-at.bofh.it>
In reply to#1271765
On Wed, Nov 18, 2015 at 11:21:01AM +1100, James Morris wrote:
> On Tue, 17 Nov 2015, Jarkko Sakkinen wrote:
> 
> >  			}
> >  			break;
> > +		case Opt_policydigest:
> > +			if (!tpm2 ||
> > +			    strlen(args[0].from) != (2 * opt->digest_len))
> > +				return -EINVAL;
> > +			kfree(opt->policydigest);
> > +			opt->policydigest = kzalloc(opt->digest_len,
> > +						    GFP_KERNEL);
> 
> Is it correct to kfree opt->policydigest here before allocating it?

I think so. The same option might be encountered multiple times.

I don't have the check for nulliy because opt is kzalloc'd and
checkpatch.pl complained that

WARNING: kfree(NULL) is safe and this check is probably not required
#20: FILE: security/keys/trusted.c:829:
+			if (opt->policydigest)
+				kfree(opt->policydigest);

> > +			if (!opt->policydigest)
> > +				return -ENOMEM;
> > +			res = hex2bin(opt->policydigest, args[0].from,
> > +				      opt->digest_len);
> > +			if (res < 0)
> > +				return -EINVAL;
> 
> Do you need to kfree it here on error?

trusted_options_free() will kfree it.

> -- 
> James Morris
> <jmorris@namei.org>

/Jarkko
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1273697

FromJames Morris <jmorris@namei.org>
Date2015-11-20 03:40 +0100
Message-ID<qwJMe-13l-11@gated-at.bofh.it>
In reply to#1271888
On Wed, 18 Nov 2015, Jarkko Sakkinen wrote:

> On Wed, Nov 18, 2015 at 11:21:01AM +1100, James Morris wrote:
> > On Tue, 17 Nov 2015, Jarkko Sakkinen wrote:
> > 
> > >  			}
> > >  			break;
> > > +		case Opt_policydigest:
> > > +			if (!tpm2 ||
> > > +			    strlen(args[0].from) != (2 * opt->digest_len))
> > > +				return -EINVAL;
> > > +			kfree(opt->policydigest);
> > > +			opt->policydigest = kzalloc(opt->digest_len,
> > > +						    GFP_KERNEL);
> > 
> > Is it correct to kfree opt->policydigest here before allocating it?
> 
> I think so. The same option might be encountered multiple times.

This would surely signify an error?


-- 
James Morris
<jmorris@namei.org>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1273034 — RE: [tpmdd-devel] [PATCH 2/2] keys, trusted: seal with a policy

From"Fuchs, Andreas" <andreas.fuchs@sit.fraunhofer.de>
Date2015-11-19 12:10 +0100
SubjectRE: [tpmdd-devel] [PATCH 2/2] keys, trusted: seal with a policy
Message-ID<qwvgd-8vD-9@gated-at.bofh.it>
In reply to#1271380
> ________________________________________
> From: Jarkko Sakkinen [jarkko.sakkinen@linux.intel.com]
> Sent: Tuesday, November 17, 2015 17:27
> 
> Support for sealing with a authorization policy.
> 
> Two new options for trusted keys:
> 
> * 'policydigest=': provide an auth policy digest for sealing.
> * 'policyhandle=': provide a policy session handle for unsealing.

Hi Jarkko,

just out of curiosity; when testing this, how did you calculate the blobauth parameter ?
Since its calculation requires the cpHash for the unseal()-command...
If you "predict" the cpHash in userSpace, this would mean that userspace needs to know the
kernels way of constructing the unseal()-command to the TPM, which in turn would make
this part of the ABI and require documentation before upstreaming, imho.

Cheers,
Andreas--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1274132 — Re: [tpmdd-devel] [PATCH 2/2] keys, trusted: seal with a policy

FromJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Date2015-11-20 16:00 +0100
SubjectRe: [tpmdd-devel] [PATCH 2/2] keys, trusted: seal with a policy
Message-ID<qwVkm-6h-17@gated-at.bofh.it>
In reply to#1273034
On Thu, Nov 19, 2015 at 10:59:57AM +0000, Fuchs, Andreas wrote:
> > ________________________________________
> > From: Jarkko Sakkinen [jarkko.sakkinen@linux.intel.com]
> > Sent: Tuesday, November 17, 2015 17:27
> > 
> > Support for sealing with a authorization policy.
> > 
> > Two new options for trusted keys:
> > 
> > * 'policydigest=': provide an auth policy digest for sealing.
> > * 'policyhandle=': provide a policy session handle for unsealing.
> 
> Hi Jarkko,
> 
> just out of curiosity; when testing this, how did you calculate the blobauth parameter ?
> Since its calculation requires the cpHash for the unseal()-command...
> If you "predict" the cpHash in userSpace, this would mean that userspace needs to know the
> kernels way of constructing the unseal()-command to the TPM, which in turn would make
> this part of the ABI and require documentation before upstreaming, imho.

Is this a comment about the patch? Have you actually read the source
code or where is this coming from? Please read the source code.

> Cheers,
> Andreas--

/Jarkko
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1274734

FromJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Date2015-11-21 20:00 +0100
Message-ID<qxlya-MF-5@gated-at.bofh.it>
In reply to#1271380
On Tue, Nov 17, 2015 at 06:27:22PM +0200, Jarkko Sakkinen wrote:
> Support for sealing with a authorization policy.
> 
> Two new options for trusted keys:
> 
> * 'policydigest=': provide an auth policy digest for sealing.
> * 'policyhandle=': provide a policy session handle for unsealing.

I think it is good to say a word about how to test this since the user
space supports is still lagging a bit (there's no way to do a "sticky"
handle in TSS2 yet).

I have my own low-level test scripts over here:

https://github.com/jsakkine/tpm2-scripts

Trivial example:

KEYHANDLE=$(sudo ./tpm2-root-key)
POLICYDIGEST=$(sudo ./tpm2-pcr-policy --pcr 16 --name-alg=sha256 --bank=sha1 --trial)
POLICYHANDLE=$(sudo ./tpm2-pcr-policy --pcr 16 --name-alg=sha256 --bank=sha1)

KEYID=$(keyctl add trusted kmk "new 32 keyhandle=$KEYHANDLE hash=sha256 policydigest=$POLICYDIGEST" @u)
keyctl pipe $KEYID
keyctl clear @u
keyctl add trusted kmk "load `cat blob.hex` keyhandle=$KEYHANDLE  policyhandle=0x03000000" @u
keyctl clear @u

sudo ./tpm2-flush $KEYHANDLE

/Jarkko
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1275461

FromJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Date2015-11-23 16:00 +0100
Message-ID<qy0KZ-3aB-9@gated-at.bofh.it>
In reply to#1271380
On Tue, Nov 17, 2015 at 06:27:22PM +0200, Jarkko Sakkinen wrote:
> Support for sealing with a authorization policy.
> 
> Two new options for trusted keys:
> 
> * 'policydigest=': provide an auth policy digest for sealing.
> * 'policyhandle=': provide a policy session handle for unsealing.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

This patch has been now peer tested by Colin Ian King. There's still one
thing that I'm thinking before daring to put this into pull request.
Should the option names reflect that they associate to the blob and not
to the root key?

My *guess* would be that it's not very common use case to seal primary
keys with policies (PCRs and so forth) and therefore I think these
names are fine.

[1] In TPM 2.0 there is no fixed root key in the chip. Instead tit
contains random seeds from which you can derive primary keys by using
the TPM2_CreatePrimary command. That's why we require for example
keyhandle as an explicit option when used with a TPM 2.0 chip.

/Jarkko

> ---
>  Documentation/security/keys-trusted-encrypted.txt | 34 ++++++++++-------
>  drivers/char/tpm/tpm2-cmd.c                       | 24 ++++++++++--
>  include/keys/trusted-type.h                       |  3 ++
>  security/keys/trusted.c                           | 46 ++++++++++++++++++++++-
>  4 files changed, 87 insertions(+), 20 deletions(-)
> 
> diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt
> index fd2565b..324ddf5 100644
> --- a/Documentation/security/keys-trusted-encrypted.txt
> +++ b/Documentation/security/keys-trusted-encrypted.txt
> @@ -27,20 +27,26 @@ Usage:
>      keyctl print keyid
>  
>      options:
> -       keyhandle= ascii hex value of sealing key default 0x40000000 (SRK)
> -       keyauth=	  ascii hex auth for sealing key default 0x00...i
> -		  (40 ascii zeros)
> -       blobauth=  ascii hex auth for sealed data default 0x00...
> -		  (40 ascii zeros)
> -       blobauth=  ascii hex auth for sealed data default 0x00...
> -		  (40 ascii zeros)
> -       pcrinfo=	  ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
> -       pcrlock=	  pcr number to be extended to "lock" blob
> -       migratable= 0|1 indicating permission to reseal to new PCR values,
> -                   default 1 (resealing allowed)
> -       hash=      hash algorithm name as a string. For TPM 1.x the only
> -                  allowed value is sha1. For TPM 2.x the allowed values
> -		  are sha1, sha256, sha384, sha512 and sm3-256.
> +       keyhandle=    ascii hex value of sealing key default 0x40000000 (SRK)
> +       keyauth=	     ascii hex auth for sealing key default 0x00...i
> +                     (40 ascii zeros)
> +       blobauth=     ascii hex auth for sealed data default 0x00...
> +                     (40 ascii zeros)
> +       blobauth=     ascii hex auth for sealed data default 0x00...
> +                     (40 ascii zeros)
> +       pcrinfo=	     ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
> +       pcrlock=	     pcr number to be extended to "lock" blob
> +       migratable=   0|1 indicating permission to reseal to new PCR values,
> +                     default 1 (resealing allowed)
> +       hash=         hash algorithm name as a string. For TPM 1.x the only
> +                     allowed value is sha1. For TPM 2.x the allowed values
> +                     are sha1, sha256, sha384, sha512 and sm3-256.
> +       policydigest= digest for the authorization policy. must be calculated
> +                     with the same hash algorithm as specified by the 'hash='
> +                     option.
> +       policyhandle= handle to an authorization policy session that defines the
> +                     same policy and with the same hash algorithm as was used to
> +                     seal the key.
>  
>  "keyctl print" returns an ascii hex copy of the sealed key, which is in standard
>  TPM_STORED_DATA format.  The key length for new keys are always in bytes.
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index d9d0822..45a6340 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -478,12 +478,26 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
>  	tpm_buf_append_u8(&buf, payload->migratable);
>  
>  	/* public */
> -	tpm_buf_append_u16(&buf, 14);
> +	if (options->policydigest)
> +		tpm_buf_append_u16(&buf, 14 + options->digest_len);
> +	else
> +		tpm_buf_append_u16(&buf, 14);
>  
>  	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 */
> +
> +	/* policy */
> +	if (options->policydigest) {
> +		tpm_buf_append_u32(&buf, 0);
> +		tpm_buf_append_u16(&buf, options->digest_len);
> +		tpm_buf_append(&buf, options->policydigest,
> +			       options->digest_len);
> +	} else {
> +		tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH);
> +		tpm_buf_append_u16(&buf, 0);
> +	}
> +
> +	/* public parameters */
>  	tpm_buf_append_u16(&buf, TPM2_ALG_NULL);
>  	tpm_buf_append_u16(&buf, 0);
>  
> @@ -613,7 +627,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..2c3f9f7 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 digest_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 b5b0a55..b726a83 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}
>  };
>  
> @@ -739,6 +743,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>  	int res;
>  	unsigned long handle;
>  	unsigned long lock;
> +	unsigned int policydigest_len;
>  	int i;
>  	int tpm2;
>  
> @@ -747,6 +752,8 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>  		return tpm2;
>  
>  	opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1;
> +	opt->digest_len = hash_digest_size[opt->hash];
> +	policydigest_len = opt->digest_len;
>  
>  	while ((p = strsep(&c, " \t"))) {
>  		if (*p == '\0' || *p == ' ' || *p == '\t')
> @@ -802,6 +809,8 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>  			for (i = 0; i < HASH_ALGO__LAST; i++) {
>  				if (!strcmp(args[0].from, hash_algo_name[i])) {
>  					opt->hash = i;
> +					opt->digest_len =
> +						hash_digest_size[opt->hash];
>  					break;
>  				}
>  			}
> @@ -812,10 +821,37 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>  				return -EINVAL;
>  			}
>  			break;
> +		case Opt_policydigest:
> +			if (!tpm2 ||
> +			    strlen(args[0].from) != (2 * opt->digest_len))
> +				return -EINVAL;
> +			kfree(opt->policydigest);
> +			opt->policydigest = kzalloc(opt->digest_len,
> +						    GFP_KERNEL);
> +			if (!opt->policydigest)
> +				return -ENOMEM;
> +			res = hex2bin(opt->policydigest, args[0].from,
> +				      opt->digest_len);
> +			if (res < 0)
> +				return -EINVAL;
> +			policydigest_len = opt->digest_len;
> +			break;
> +		case Opt_policyhandle:
> +			if (!tpm2)
> +				return -EINVAL;
> +			res = kstrtoul(args[0].from, 16, &handle);
> +			if (res < 0)
> +				return -EINVAL;
> +			opt->policyhandle = handle;
> +			break;
>  		default:
>  			return -EINVAL;
>  		}
>  	}
> +
> +	if (opt->policydigest && policydigest_len != opt->digest_len)
> +		return -EINVAL;
> +
>  	return 0;
>  }
>  
> @@ -904,6 +940,12 @@ static struct trusted_key_options *trusted_options_alloc(void)
>  	return options;
>  }
>  
> +static void trusted_options_free(struct trusted_key_options *options)
> +{
> +	kfree(options->policydigest);
> +	kfree(options);
> +}
> +
>  static struct trusted_key_payload *trusted_payload_alloc(struct key *key)
>  {
>  	struct trusted_key_payload *p = NULL;
> @@ -1010,7 +1052,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
> @@ -1098,7 +1140,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;
>  }
>  
> -- 
> 2.5.0
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web