lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <4EB18138.6050400@polito.it>
Date:	Wed, 02 Nov 2011 18:43:20 +0100
From:	Roberto Sassu <roberto.sassu@...ito.it>
To:	linux-kernel@...r.kernel.org
Cc:	linux-kernel@...r.kernel.org
Subject: Re: [PATCH 2/2] trusted-key: added support for loading a key blob
 in the TPM

On 11/02/2011 06:26 PM, David Safford wrote:
> On Wed, 2011-11-02 at 13:41 +0100, Roberto Sassu wrote:
>> The new functions 'tpm_loadkey2', 'tpm_evictkey' and 'tpm_flushspecific'
>> allow to load/unload a TPM key whose blob is provided from the userspace
>> interface and to use it for sealing or unsealing the symmetric key.
>
> This looks like a nice extension.
> I'll test it out thoroughly, but for now here are a couple of
> minor initial suggestions...
>

Thanks, i will fix them and submit a new version of
the patches after receiving other comments.

Roberto Sassu


> dave
>
>>
>> Signed-off-by: Roberto Sassu<roberto.sassu@...ito.it>
>> ---
>>   Documentation/security/keys-trusted-encrypted.txt |    6 +-
>>   include/linux/tpm_command.h                       |    6 +
>>   security/keys/trusted.c                           |  203 ++++++++++++++++++++-
>>   security/keys/trusted.h                           |   27 +++-
>>   4 files changed, 234 insertions(+), 8 deletions(-)
>>
>> diff --git a/Documentation/security/keys-trusted-encrypted.txt b/Documentation/security/keys-trusted-encrypted.txt
>> index 5f50cca..afebb58 100644
>> --- a/Documentation/security/keys-trusted-encrypted.txt
>> +++ b/Documentation/security/keys-trusted-encrypted.txt
>> @@ -27,8 +27,10 @@ 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
>> +       keyhandle= ascii hex value of sealing key handle default 0x40000000 (SRK)
>> +       keyblob=   ascii hex value of sealing key blob (no default)
>> +       srkauth=   ascii hex auth for SRK key default 0x00...
>> +       keyauth=	  ascii hex auth for sealing key (not SRK) default 0x00...
>>   		  (40 ascii zeros)
>>          blobauth=  ascii hex auth for sealed data default 0x00...
>>   		  (40 ascii zeros)
>> diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h
>> index 727512e..e3348b7 100644
>> --- a/include/linux/tpm_command.h
>> +++ b/include/linux/tpm_command.h
>> @@ -15,7 +15,10 @@
>>   #define TPM_TAG_RSP_AUTH2_COMMAND       198
>>
>>   /* Command Ordinals */
>> +#define TPM_ORD_EVICTKEY                34
>> +#define TPM_ORD_FLUSHSPECIFIC          186
>>   #define TPM_ORD_GETRANDOM               70
>> +#define TPM_ORD_LOADKEY2                65
>>   #define TPM_ORD_OSAP                    11
>>   #define TPM_ORD_OIAP                    10
>>   #define TPM_ORD_SEAL                    23
>> @@ -24,5 +27,8 @@
>>   /* Other constants */
>>   #define SRKHANDLE                       0x40000000
>>   #define TPM_NONCE_SIZE                  20
>> +#define TPM_RT_KEY                      0x00000001
>> +#define TPM_TAG_KEY12                   0x0028
>> +#define TPM_BAD_ORDINAL                 10
>>
>>   #endif
>> diff --git a/security/keys/trusted.c b/security/keys/trusted.c
>> index 8777015..c332e3b 100644
>> --- a/security/keys/trusted.c
>> +++ b/security/keys/trusted.c
>> @@ -688,12 +688,118 @@ static int tpm_unseal(struct tpm_buf *tb,
>>   }
>>
>>   /*
>> + * Load a TPM key from the blob provided by userspace
>> + */
>> +static int tpm_loadkey2(struct tpm_buf *tb,
>> +			uint32_t keyhandle, unsigned char *keyauth,
>> +			const unsigned char *keyblob, int keybloblen,
>> +			uint32_t *newhandle)
>> +{
>> +	unsigned char nonceodd[TPM_NONCE_SIZE];
>> +	unsigned char enonce[TPM_NONCE_SIZE];
>> +	unsigned char authdata[SHA1_DIGEST_SIZE];
>> +	uint32_t authhandle = 0;
>> +	unsigned char cont = 0;
>> +	uint32_t ordinal;
>> +	int ret;
>> +
>> +	ordinal = htonl(TPM_ORD_LOADKEY2);
>> +
>> +	/* session for loading the key */
>> +	ret = oiap(tb,&authhandle, enonce);
>> +	if (ret<  0) {
>> +		pr_info("trusted_key: oiap failed (%d)\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	/* generate odd nonce */
>> +	ret = tpm_get_random(tb, nonceodd, TPM_NONCE_SIZE);
>> +	if (ret<  0) {
>> +		pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	/* calculate authorization HMAC value */
>> +	ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce,
>> +			   nonceodd, cont, sizeof(uint32_t),&ordinal,
>> +			   keybloblen, keyblob, 0, 0);
>> +	if (ret<  0)
>> +		return ret;
>> +
>> +	/* build the request buffer */
>> +	INIT_BUF(tb);
>> +	store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
>> +	store32(tb, TPM_LOADKEY2_SIZE + keybloblen);
>> +	store32(tb, TPM_ORD_LOADKEY2);
>> +	store32(tb, keyhandle);
>> +	storebytes(tb, keyblob, keybloblen);
>> +	store32(tb, authhandle);
>> +	storebytes(tb, nonceodd, TPM_NONCE_SIZE);
>> +	store8(tb, cont);
>> +	storebytes(tb, authdata, SHA1_DIGEST_SIZE);
>> +
>> +	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
>> +	if (ret<  0) {
>> +		pr_info("trusted_key: authhmac failed (%d)\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	ret = TSS_checkhmac1(tb->data, ordinal, nonceodd, keyauth,
>> +			     SHA1_DIGEST_SIZE, 0, 0);
>> +	if (ret<  0) {
>> +		pr_info("trusted_key: TSS_checkhmac1 failed (%d)\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	*newhandle = LOAD32(tb->data, TPM_DATA_OFFSET);
>> +	return 0;
>> +}
>> +
>> +/*
>> + * Execute the FlushSpecific TPM command
>> + */
>> +uint32_t tpm_flushspecific(struct tpm_buf *tb, uint32_t handle,
>> +			   uint32_t resourcetype)
>
> static?
>
>> +{
>> +	INIT_BUF(tb);
>> +	store16(tb, TPM_TAG_RQU_COMMAND);
>> +	store32(tb, TPM_FLUSHSPECIFIC_SIZE);
>> +	store32(tb, TPM_ORD_FLUSHSPECIFIC);
>> +	store32(tb, handle);
>> +	store32(tb, resourcetype);
>> +
>> +	return trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
>> +}
>> +
>> +/*
>> + * Evict a key from the TPM
>> + */
>> +uint32_t tpm_evictkey(struct tpm_buf *tb, uint32_t keyhandle)
>
> static?
>
>> +{
>> +	int ret;
>> +
>> +	INIT_BUF(tb);
>> +	store16(tb, TPM_TAG_RQU_COMMAND);
>> +	store32(tb, TPM_EVICTKEY_SIZE);
>> +	store32(tb, TPM_ORD_EVICTKEY);
>> +	store32(tb, keyhandle);
>> +
>> +	ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, sizeof tb->data);
>> +	if (ret<  0)
>> +		ret = tpm_flushspecific(tb, keyhandle, TPM_RT_KEY);
>> +
>> +	return ret;
>> +}
>> +
>> +/*
>>    * Have the TPM seal(encrypt) the symmetric key
>>    */
>>   static int key_seal(struct trusted_key_payload *p,
>>   		    struct trusted_key_options *o)
>>   {
>>   	struct tpm_buf *tb;
>> +	uint32_t keyhandle;
>> +	unsigned char *parentauth;
>>   	int ret;
>>
>>   	tb = kzalloc(sizeof *tb, GFP_KERNEL);
>> @@ -703,12 +809,40 @@ static int key_seal(struct trusted_key_payload *p,
>>   	/* include migratable flag at end of sealed key */
>>   	p->key[p->key_len] = p->migratable;
>>
>> -	ret = tpm_seal(tb, o->keytype, o->keyhandle, o->keyauth,
>> +	/* set default values */
>> +	keyhandle = o->keyhandle;
>> +	parentauth = o->srkauth;
>> +
>> +	if (o->keytype == SEAL_keytype) {
>> +		parentauth = o->keyauth;
>> +		if (o->keyblob_len>  0) {
>> +			ret = tpm_loadkey2(tb, SRKHANDLE, o->srkauth,
>> +					   o->keyblob, o->keyblob_len,
>> +					&keyhandle);
>> +			if (ret<  0) {
>> +				pr_info("trusted_key: loadkey2 failed (%d)\n",
>> +					ret);
>> +				goto out;
>> +			}
>> +
>> +			dump_tpm_key12_handle(keyhandle);
>> +		}
>> +	}
>> +
>> +	ret = tpm_seal(tb, o->keytype, keyhandle, parentauth,
>>   		       p->key, p->key_len + 1, p->blob,&p->blob_len,
>>   		       o->blobauth, o->pcrinfo, o->pcrinfo_len);
>>   	if (ret<  0)
>>   		pr_info("trusted_key: srkseal failed (%d)\n", ret);
>>
>> +	if (o->keyblob_len>  0) {
>> +		int evictret = tpm_evictkey(tb, keyhandle);
>> +
>> +		if (evictret<  0)
>> +			pr_info("trusted_key: evictkey failed (%d)\n",
>> +				evictret);
>> +	}
>> +out:
>>   	kfree(tb);
>>   	return ret;
>>   }
>> @@ -720,13 +854,33 @@ static int key_unseal(struct trusted_key_payload *p,
>>   		      struct trusted_key_options *o)
>>   {
>>   	struct tpm_buf *tb;
>> +	uint32_t keyhandle;
>> +	unsigned char *parentauth;
>>   	int ret;
>>
>>   	tb = kzalloc(sizeof *tb, GFP_KERNEL);
>>   	if (!tb)
>>   		return -ENOMEM;
>>
>> -	ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len,
>> +	/* set default values */
>> +	keyhandle = o->keyhandle;
>> +	parentauth = o->srkauth;
>> +
>> +	if (o->keytype == SEAL_keytype) {
>> +		parentauth = o->keyauth;
>> +		if (o->keyblob_len>  0) {
>> +			ret = tpm_loadkey2(tb, SRKHANDLE, o->srkauth,
>> +					   o->keyblob, o->keyblob_len,
>> +					&keyhandle);
>> +			if (ret<  0) {
>> +				pr_info("trusted_key: loadkey2 failed (%d)\n",
>> +					ret);
>> +				goto out;
>> +			}
>> +		}
>> +	}
>> +
>> +	ret = tpm_unseal(tb, keyhandle, parentauth, p->blob, p->blob_len,
>>   			 o->blobauth, p->key,&p->key_len);
>>   	if (ret<  0)
>>   		pr_info("trusted_key: srkunseal failed (%d)\n", ret);
>> @@ -734,14 +888,22 @@ static int key_unseal(struct trusted_key_payload *p,
>>   		/* pull migratable flag out of sealed key */
>>   		p->migratable = p->key[--p->key_len];
>>
>> +	if (o->keyblob_len>  0) {
>> +		int evictret = tpm_evictkey(tb, keyhandle);
>> +
>> +		if (evictret<  0)
>> +			pr_info("trusted_key: evictkey failed (%d)\n",
>> +				evictret);
>> +	}
>> +out:
>>   	kfree(tb);
>>   	return ret;
>>   }
>>
>>   enum {
>>   	Opt_err = -1,
>> -	Opt_new, Opt_load, Opt_update,
>> -	Opt_keyhandle, Opt_keyauth, Opt_blobauth,
>> +	Opt_new, Opt_load, Opt_update, Opt_srkauth,
>> +	Opt_keyhandle, Opt_keyblob, Opt_keyauth, Opt_blobauth,
>>   	Opt_pcrinfo, Opt_pcrlock, Opt_migratable
>>   };
>>
>> @@ -749,7 +911,9 @@ static const match_table_t key_tokens = {
>>   	{Opt_new, "new"},
>>   	{Opt_load, "load"},
>>   	{Opt_update, "update"},
>> +	{Opt_srkauth, "srkauth=%s"},
>>   	{Opt_keyhandle, "keyhandle=%s"},
>> +	{Opt_keyblob, "keyblob=%s"},
>>   	{Opt_keyauth, "keyauth=%s"},
>>   	{Opt_blobauth, "blobauth=%s"},
>>   	{Opt_pcrinfo, "pcrinfo=%s"},
>> @@ -768,6 +932,8 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   	int res;
>>   	unsigned long handle;
>>   	unsigned long lock;
>> +	uint16_t tpm_key_tag;
>> +	uint32_t value;
>>
>>   	while ((p = strsep(&c, " \t"))) {
>>   		if (*p == '\0' || *p == ' ' || *p == '\t')
>> @@ -788,6 +954,35 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
>>   			opt->keytype = SEAL_keytype;
>>   			opt->keyhandle = handle;
>>   			break;
>> +		case Opt_keyblob:
>> +			if (strlen(args[0].from)>= MAX_KEYBLOB_SIZE * 2)
>> +				return -EINVAL;
>> +			hex2bin(opt->keyblob, args[0].from, MAX_KEYBLOB_SIZE);
>> +			tpm_key_tag = LOAD16(opt->keyblob, 0);
>> +			if (tpm_key_tag != TPM_TAG_KEY12)
>> +				return -EINVAL;
>> +			opt->keytype = SEAL_keytype;
>> +			opt->keyblob_len = TPM_KEY12_EXPSIZE_OFFSET;
>> +			/* key exponent size */
>> +			value = LOAD32(opt->keyblob, opt->keyblob_len);
>> +			opt->keyblob_len += sizeof(uint32_t) + value;
>> +			/* PCRINFO size */
>> +			value = LOAD32(opt->keyblob, opt->keyblob_len);
>> +			opt->keyblob_len += sizeof(uint32_t) + value;
>> +			/* key length */
>> +			value = LOAD32(opt->keyblob, opt->keyblob_len);
>> +			opt->keyblob_len += sizeof(uint32_t) + value;
>> +			/* enc data size */
>> +			value = LOAD32(opt->keyblob, opt->keyblob_len);
>> +			opt->keyblob_len += sizeof(uint32_t) + value;
>> +			if (opt->keyblob_len>= MAX_KEYBLOB_SIZE)
>> +				return -EINVAL;
>> +			break;
>> +		case Opt_srkauth:
>> +			if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)
>> +				return -EINVAL;
>> +			hex2bin(opt->srkauth, args[0].from, SHA1_DIGEST_SIZE);
>> +			break;
>>   		case Opt_keyauth:
>>   			if (strlen(args[0].from) != 2 * SHA1_DIGEST_SIZE)
>>   				return -EINVAL;
>> diff --git a/security/keys/trusted.h b/security/keys/trusted.h
>> index 3249fbd..6a9f373 100644
>> --- a/security/keys/trusted.h
>> +++ b/security/keys/trusted.h
>> @@ -3,12 +3,16 @@
>>
>>   /* implementation specific TPM constants */
>>   #define MAX_PCRINFO_SIZE		64
>> -#define MAX_BUF_SIZE			512
>> +#define MAX_BUF_SIZE			1024
>> +#define MAX_KEYBLOB_SIZE		1024
>>   #define TPM_GETRANDOM_SIZE		14
>>   #define TPM_OSAP_SIZE			36
>>   #define TPM_OIAP_SIZE			10
>>   #define TPM_SEAL_SIZE			87
>>   #define TPM_UNSEAL_SIZE			104
>> +#define TPM_LOADKEY2_SIZE		59
>> +#define TPM_EVICTKEY_SIZE		14
>> +#define TPM_FLUSHSPECIFIC_SIZE		18
>>   #define TPM_SIZE_OFFSET			2
>>   #define TPM_RETURN_OFFSET		6
>>   #define TPM_DATA_OFFSET			10
>> @@ -17,6 +21,8 @@
>>   #define LOAD32N(buffer, offset)	(*(uint32_t *)&buffer[offset])
>>   #define LOAD16(buffer, offset)	(ntohs(*(uint16_t *)&buffer[offset]))
>>
>> +#define TPM_KEY12_EXPSIZE_OFFSET 31
>> +
>>   struct tpm_buf {
>>   	int len;
>>   	unsigned char data[MAX_BUF_SIZE];
>> @@ -39,6 +45,9 @@ enum {
>>   struct trusted_key_options {
>>   	uint16_t keytype;
>>   	uint32_t keyhandle;
>> +	uint32_t keyblob_len;
>> +	unsigned char keyblob[MAX_KEYBLOB_SIZE];
>> +	unsigned char srkauth[SHA1_DIGEST_SIZE];
>>   	unsigned char keyauth[SHA1_DIGEST_SIZE];
>>   	unsigned char blobauth[SHA1_DIGEST_SIZE];
>>   	uint32_t pcrinfo_len;
>> @@ -52,7 +61,12 @@ struct trusted_key_options {
>>   static inline void dump_options(struct trusted_key_options *o)
>>   {
>>   	pr_info("trusted_key: sealing key type %d\n", o->keytype);
>> -	pr_info("trusted_key: sealing key handle %0X\n", o->keyhandle);
>> +	if (o->keyblob_len>  0) {
>> +		pr_info("trusted_key: sealing key blob %d\n", o->keyblob_len);
>> +		print_hex_dump(KERN_INFO, "keyblob ", DUMP_PREFIX_NONE,
>> +			      16, 1, o->keyblob, o->keyblob_len, 0);
>> +	} else
>> +		pr_info("trusted_key: sealing key handle %0X\n", o->keyhandle);
>>   	pr_info("trusted_key: pcrlock %d\n", o->pcrlock);
>>   	pr_info("trusted_key: pcrinfo %d\n", o->pcrinfo_len);
>>   	print_hex_dump(KERN_INFO, "pcrinfo ", DUMP_PREFIX_NONE,
>> @@ -90,6 +104,11 @@ static inline void dump_tpm_buf(unsigned char *buf)
>>   	len = LOAD32(buf, TPM_SIZE_OFFSET);
>>   	print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 16, 1, buf, len, 0);
>>   }
>> +static inline void dump_tpm_key12_handle(uint32_t handle)
>> +{
>> +	print_hex_dump(KERN_INFO, "trusted-key: key handle ", DUMP_PREFIX_NONE,
>> +		       16, 1,&handle, 4, 0);
>> +}
>>   #else
>>   static inline void dump_options(struct trusted_key_options *o)
>>   {
>> @@ -106,6 +125,10 @@ static inline void dump_sess(struct osapsess *s)
>>   static inline void dump_tpm_buf(unsigned char *buf)
>>   {
>>   }
>> +
>> +static inline void dump_tpm_key12_handle(uint32_t handle)
>> +{
>> +}
>>   #endif
>>
>>   static inline void store8(struct tpm_buf *buf, const unsigned char value)
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@...r.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ