* [PATCH 1/2] trusted-key: allow overwriting the migratable flag @ 2011-11-02 12:41 Roberto Sassu 2011-11-02 12:41 ` [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM Roberto Sassu 2011-11-02 16:58 ` [PATCH 1/2] trusted-key: allow overwriting the migratable flag David Safford 0 siblings, 2 replies; 8+ messages in thread From: Roberto Sassu @ 2011-11-02 12:41 UTC (permalink / raw) To: keyrings Cc: linux-security-module, linux-kernel, safford, zohar, dhowells, jmorris, Roberto Sassu [-- Attachment #1: Type: text/plain, Size: 823 bytes --] The migratable should be modifiable during the key update() method. This allows for example to update a migratable trusted key, wrapped by a TPM key, to a a non-migratable one sealed under the SRK with a PCR set. Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> --- security/keys/trusted.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-) diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 0c33e2e..8777015 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -1036,7 +1036,6 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) goto out; } /* copy old key values, and reseal with new pcrs */ - new_p->migratable = p->migratable; new_p->key_len = p->key_len; memcpy(new_p->key, p->key, p->key_len); dump_payload(p); -- 1.7.6.4 [-- Attachment #2: smime.p7s --] [-- Type: application/x-pkcs7-signature, Size: 2061 bytes --] ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM 2011-11-02 12:41 [PATCH 1/2] trusted-key: allow overwriting the migratable flag Roberto Sassu @ 2011-11-02 12:41 ` Roberto Sassu 2011-11-02 17:26 ` David Safford 2011-11-02 16:58 ` [PATCH 1/2] trusted-key: allow overwriting the migratable flag David Safford 1 sibling, 1 reply; 8+ messages in thread From: Roberto Sassu @ 2011-11-02 12:41 UTC (permalink / raw) To: keyrings Cc: linux-security-module, linux-kernel, safford, zohar, dhowells, jmorris, Roberto Sassu [-- Attachment #1: Type: text/plain, Size: 12736 bytes --] 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. Signed-off-by: Roberto Sassu <roberto.sassu@polito.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) +{ + 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) +{ + 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) -- 1.7.6.4 [-- Attachment #2: smime.p7s --] [-- Type: application/x-pkcs7-signature, Size: 2061 bytes --] ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM 2011-11-02 12:41 ` [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM Roberto Sassu @ 2011-11-02 17:26 ` David Safford 2011-11-02 17:43 ` Roberto Sassu 0 siblings, 1 reply; 8+ messages in thread From: David Safford @ 2011-11-02 17:26 UTC (permalink / raw) To: Roberto Sassu Cc: keyrings, linux-security-module, linux-kernel, zohar, dhowells, jmorris 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... dave > > Signed-off-by: Roberto Sassu <roberto.sassu@polito.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) ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM 2011-11-02 17:26 ` David Safford @ 2011-11-02 17:43 ` Roberto Sassu 2011-11-03 12:12 ` Roberto Sassu 0 siblings, 1 reply; 8+ messages in thread From: Roberto Sassu @ 2011-11-02 17:43 UTC (permalink / raw) To: David Safford Cc: keyrings, linux-security-module, linux-kernel, zohar, dhowells, jmorris 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@polito.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@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM 2011-11-02 17:43 ` Roberto Sassu @ 2011-11-03 12:12 ` Roberto Sassu 0 siblings, 0 replies; 8+ messages in thread From: Roberto Sassu @ 2011-11-03 12:12 UTC (permalink / raw) Cc: David Safford, keyrings, linux-security-module, linux-kernel, zohar, dhowells, jmorris On 11/02/2011 06:43 PM, Roberto Sassu wrote: > 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... >> > Hi Dave i've just discovered another issue in the patches. MAX_KEYBLOB_SIZE should not be equal to MAX_BUF_SIZE, because otherwise a buffer overflow may occur in the allocated 'tpm_buf' structure during the tpm_loadkey2() function. So, in the new patches i've set: #define MAX_KEYBLOB_SIZE ( MAX_BUF_SIZE - TPM_LOADKEY2_SIZE ) and i've fixed the checks in getoptions() ------ if (strlen(args[0].from) > MAX_KEYBLOB_SIZE * 2) ------ ------ if (opt->keyblob_len > MAX_KEYBLOB_SIZE) ------ by replacing '>=' with '>'. Roberto Sassu > 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@polito.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@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> > > -- > To unsubscribe from this list: send the line "unsubscribe > linux-security-module" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] trusted-key: allow overwriting the migratable flag 2011-11-02 12:41 [PATCH 1/2] trusted-key: allow overwriting the migratable flag Roberto Sassu 2011-11-02 12:41 ` [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM Roberto Sassu @ 2011-11-02 16:58 ` David Safford 2011-11-02 17:37 ` Roberto Sassu 1 sibling, 1 reply; 8+ messages in thread From: David Safford @ 2011-11-02 16:58 UTC (permalink / raw) To: Roberto Sassu Cc: keyrings, linux-security-module, linux-kernel, zohar, dhowells, jmorris On Wed, 2011-11-02 at 13:41 +0100, Roberto Sassu wrote: > The migratable should be modifiable during the key update() method. This > allows for example to update a migratable trusted key, wrapped by a TPM > key, to a a non-migratable one sealed under the SRK with a PCR set. > > Signed-off-by: Roberto Sassu <roberto.sassu@polito.it> I can see a use case for updating a migratable key to a non-migratable one - such as keeping a migratable master on a flash drive, and keeping only the non-migratable copy on-line. I certainly don't want the ability to change a non-migratable to migratable, as that would defeat the entire purpose of non-migratable. I don't think this patch actually does either, though. > --- > security/keys/trusted.c | 1 - > 1 files changed, 0 insertions(+), 1 deletions(-) > > diff --git a/security/keys/trusted.c b/security/keys/trusted.c > index 0c33e2e..8777015 100644 > --- a/security/keys/trusted.c > +++ b/security/keys/trusted.c > @@ -1036,7 +1036,6 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) > goto out; > } > /* copy old key values, and reseal with new pcrs */ > - new_p->migratable = p->migratable; Taking out this line appears only to remove a redundant assignment. We can only get here if the old key is already migratable, and the earlier trusted_payload_alloc() initializes the new copy to migratable by default. I don't see how the flag can be changed with this patch. Perhaps I'm missing something or this was just the start, and there is more to come? dave > new_p->key_len = p->key_len; > memcpy(new_p->key, p->key, p->key_len); > dump_payload(p); ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] trusted-key: allow overwriting the migratable flag 2011-11-02 16:58 ` [PATCH 1/2] trusted-key: allow overwriting the migratable flag David Safford @ 2011-11-02 17:37 ` Roberto Sassu 2011-11-02 17:46 ` David Safford 0 siblings, 1 reply; 8+ messages in thread From: Roberto Sassu @ 2011-11-02 17:37 UTC (permalink / raw) To: David Safford Cc: keyrings, linux-security-module, linux-kernel, zohar, dhowells, jmorris On 11/02/2011 05:58 PM, David Safford wrote: > On Wed, 2011-11-02 at 13:41 +0100, Roberto Sassu wrote: >> The migratable should be modifiable during the key update() method. This >> allows for example to update a migratable trusted key, wrapped by a TPM >> key, to a a non-migratable one sealed under the SRK with a PCR set. >> >> Signed-off-by: Roberto Sassu<roberto.sassu@polito.it> > > I can see a use case for updating a migratable key to a non-migratable > one - such as keeping a migratable master on a flash drive, and keeping > only the non-migratable copy on-line. I certainly don't want the > ability to change a non-migratable to migratable, as that would defeat > the entire purpose of non-migratable. > > I don't think this patch actually does either, though. > >> --- >> security/keys/trusted.c | 1 - >> 1 files changed, 0 insertions(+), 1 deletions(-) >> >> diff --git a/security/keys/trusted.c b/security/keys/trusted.c >> index 0c33e2e..8777015 100644 >> --- a/security/keys/trusted.c >> +++ b/security/keys/trusted.c >> @@ -1036,7 +1036,6 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) >> goto out; >> } >> /* copy old key values, and reseal with new pcrs */ >> - new_p->migratable = p->migratable; > > Taking out this line appears only to remove a redundant assignment. > We can only get here if the old key is already migratable, and the > earlier trusted_payload_alloc() initializes the new copy to > migratable by default. I don't see how the flag can be changed > with this patch. Perhaps I'm missing something or this was just > the start, and there is more to come? > Hi Dave i think this line should be removed because it overwrites the assignment made in datablob_parse() -> getoptions(). You can see this behaviour by executing the following commands: 1) keyctl add trusted kmk "new 32" @u 2) keyctl update $(keyctl search @u trusted kmk) "update migratable=0" 3) keyctl update $(keyctl search @u trusted kmk) "update migratable=0" The third operation should fail because of the lines at the begin of trusted_update(): --------- if (!p->migratable) return -EPERM; --------- but instead, without the patch, it is performed successfully. Thanks Roberto Sassu > dave > >> new_p->key_len = p->key_len; >> memcpy(new_p->key, p->key, p->key_len); >> dump_payload(p); > > -- > To unsubscribe from this list: send the line "unsubscribe linux-security-module" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] trusted-key: allow overwriting the migratable flag 2011-11-02 17:37 ` Roberto Sassu @ 2011-11-02 17:46 ` David Safford 0 siblings, 0 replies; 8+ messages in thread From: David Safford @ 2011-11-02 17:46 UTC (permalink / raw) To: Roberto Sassu Cc: keyrings, linux-security-module, linux-kernel, zohar, dhowells, jmorris On Wed, 2011-11-02 at 18:37 +0100, Roberto Sassu wrote: > On 11/02/2011 05:58 PM, David Safford wrote: > > On Wed, 2011-11-02 at 13:41 +0100, Roberto Sassu wrote: > >> The migratable should be modifiable during the key update() method. This > >> allows for example to update a migratable trusted key, wrapped by a TPM > >> key, to a a non-migratable one sealed under the SRK with a PCR set. > >> > >> Signed-off-by: Roberto Sassu<roberto.sassu@polito.it> > > > > I can see a use case for updating a migratable key to a non-migratable > > one - such as keeping a migratable master on a flash drive, and keeping > > only the non-migratable copy on-line. I certainly don't want the > > ability to change a non-migratable to migratable, as that would defeat > > the entire purpose of non-migratable. > > > > I don't think this patch actually does either, though. > > > >> --- > >> security/keys/trusted.c | 1 - > >> 1 files changed, 0 insertions(+), 1 deletions(-) > >> > >> diff --git a/security/keys/trusted.c b/security/keys/trusted.c > >> index 0c33e2e..8777015 100644 > >> --- a/security/keys/trusted.c > >> +++ b/security/keys/trusted.c > >> @@ -1036,7 +1036,6 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) > >> goto out; > >> } > >> /* copy old key values, and reseal with new pcrs */ > >> - new_p->migratable = p->migratable; > > > > Taking out this line appears only to remove a redundant assignment. > > We can only get here if the old key is already migratable, and the > > earlier trusted_payload_alloc() initializes the new copy to > > migratable by default. I don't see how the flag can be changed > > with this patch. Perhaps I'm missing something or this was just > > the start, and there is more to come? > > > > Hi Dave > > i think this line should be removed because it overwrites > the assignment made in datablob_parse() -> getoptions(). > > You can see this behaviour by executing the following commands: > > 1) keyctl add trusted kmk "new 32" @u > 2) keyctl update $(keyctl search @u trusted kmk) "update migratable=0" > 3) keyctl update $(keyctl search @u trusted kmk) "update migratable=0" > > The third operation should fail because of the lines at the > begin of trusted_update(): > > --------- > if (!p->migratable) > return -EPERM; > --------- > > but instead, without the patch, it is performed successfully. > > Thanks > > Roberto Sassu Sorry - you are absolutely correct. The patch looks good, and it is safe, as it allows only migratable -> non-migratable updates. Give me a day to test both... dave > > > dave > > > >> new_p->key_len = p->key_len; > >> memcpy(new_p->key, p->key, p->key_len); > >> dump_payload(p); > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-security-module" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-11-03 12:12 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2011-11-02 12:41 [PATCH 1/2] trusted-key: allow overwriting the migratable flag Roberto Sassu 2011-11-02 12:41 ` [PATCH 2/2] trusted-key: added support for loading a key blob in the TPM Roberto Sassu 2011-11-02 17:26 ` David Safford 2011-11-02 17:43 ` Roberto Sassu 2011-11-03 12:12 ` Roberto Sassu 2011-11-02 16:58 ` [PATCH 1/2] trusted-key: allow overwriting the migratable flag David Safford 2011-11-02 17:37 ` Roberto Sassu 2011-11-02 17:46 ` David Safford
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox