* [PATCH v2 0/4] Basic trusted keys support for TPM 2.0
@ 2015-10-13 8:11 Jarkko Sakkinen
2015-10-13 8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Jarkko Sakkinen @ 2015-10-13 8:11 UTC (permalink / raw)
To: tpmdd-devel, linux-kernel
Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen,
open list:KEYS-TRUSTED, open list:KEYS-TRUSTED
Basic trusted keys support: auth value and SHA256.
v2:
* Removed all the changes that modify the existing functions to use
the new struct tpm_buf. These changes should be done separately from
this patch set as they require separate QA + review.
* 'keyhandle=' is now required for TPM2. Makes sense to always state
the sealing key because there's no any fixed keys on the chip (thanks
to Andreas Fuchs for this comment).
* I updated tpm_buf to a be heap based structure. Now there's one full
page of memory for variable sized messages. Also the stack is greatly
reduced.
Jarkko Sakkinen (4):
tpm: introduce tpm_buf
keys, trusted: move struct trusted_key_options to trusted-type.h
tpm: seal/unseal for TPM 2.0
keys, trusted: seal/unseal with TPM 2.0 chips
drivers/char/tpm/tpm-interface.c | 76 ++++++++++++
drivers/char/tpm/tpm.h | 110 +++++++++++++++++
drivers/char/tpm/tpm2-cmd.c | 250 ++++++++++++++++++++++++++++++++++++++-
include/keys/trusted-type.h | 14 ++-
include/linux/tpm.h | 26 ++++
security/keys/trusted.c | 36 +++++-
security/keys/trusted.h | 11 --
7 files changed, 507 insertions(+), 16 deletions(-)
--
2.5.0
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v2 1/4] tpm: introduce tpm_buf 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen @ 2015-10-13 8:11 ` Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen ` (5 subsequent siblings) 6 siblings, 0 replies; 10+ messages in thread From: Jarkko Sakkinen @ 2015-10-13 8:11 UTC (permalink / raw) To: tpmdd-devel, linux-kernel Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, Marcel Selhorst This patch introduces struct tpm_buf that provides a string buffer for constructing TPM commands. This allows to construct variable sized TPM commands. For the buffer a page is allocated and mapped, which limits maximum size to PAGE_SIZE. Variable sized TPM commands are needed in order to add algorithmic agility. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> --- drivers/char/tpm/tpm.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index f8319a0..df43979 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2015 Intel Corporation * * Authors: * Leendert van Doorn <leendert@watson.ibm.com> @@ -28,6 +29,7 @@ #include <linux/tpm.h> #include <linux/acpi.h> #include <linux/cdev.h> +#include <linux/highmem.h> enum tpm_const { TPM_MINOR = 224, /* officially assigned */ @@ -382,6 +384,101 @@ struct tpm_cmd_t { tpm_cmd_params params; } __packed; +/* A string buffer type for constructing TPM commands. This is based on the + * ideas of string buffer code in security/keys/trusted.h but is heap based + * in order to keep the stack usage minimal. + */ + +enum tpm_buf_flags { + TPM_BUF_OVERFLOW = BIT(0), +}; + +struct tpm_buf { + struct page *data_page; + unsigned int flags; + u8 *data; +}; + +static inline void tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +{ + struct tpm_input_header *head; + + buf->data_page = alloc_page(GFP_HIGHUSER); + if (!buf->data_page) + return -ENOMEM; + + buf->flags = 0; + buf->data = kmap(buf->data_page); + + head = (struct tpm_input_header *) buf->data; + + head->tag = cpu_to_be16(tag); + head->length = cpu_to_be32(sizeof(*head)); + head->ordinal = cpu_to_be32(ordinal); + + return 0; +} + +static inline void tpm_buf_destroy(struct tpm_buf *buf) +{ + kunmap(buf->data_page); + __free_page(buf->data_page); +} + +static inline u32 tpm_buf_length(struct tpm_buf *buf) +{ + struct tpm_input_header *head = (struct tpm_input_header *) buf->data; + + return be32_to_cpu(head->length); +} + +static inline u16 tpm_buf_tag(struct tpm_buf *buf) +{ + struct tpm_input_header *head = (struct tpm_input_header *) buf->data; + + return be16_to_cpu(head->tag); +} + +static inline void tpm_buf_append(struct tpm_buf *buf, + const unsigned char *new_data, + unsigned int new_len) +{ + struct tpm_input_header *head = (struct tpm_input_header *) buf->data; + u32 len = tpm_buf_length(buf); + + /* Return silently if overflow has already happened. */ + if (buf->flags & TPM_BUF_OVERFLOW) + return; + + if ((len + new_len) > PAGE_SIZE) { + WARN(1, "tpm_buf: overflow\n"); + buf->flags |= TPM_BUF_OVERFLOW; + return; + } + + memcpy(&buf->data[len], new_data, new_len); + head->length = cpu_to_be32(len + new_len); +} + +static inline void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value) +{ + tpm_buf_append(buf, &value, 1); +} + +static inline void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value) +{ + __be16 value2 = cpu_to_be16(value); + + tpm_buf_append(buf, (u8 *) &value2, 2); +} + +static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value) +{ + __be32 value2 = cpu_to_be32(value); + + tpm_buf_append(buf, (u8 *) &value2, 4); +} + extern struct class *tpm_class; extern dev_t tpm_devt; extern const struct file_operations tpm_fops; -- 2.5.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen @ 2015-10-13 8:11 ` Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen ` (4 subsequent siblings) 6 siblings, 0 replies; 10+ messages in thread From: Jarkko Sakkinen @ 2015-10-13 8:11 UTC (permalink / raw) To: tpmdd-devel, linux-kernel Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, David Safford, Mimi Zohar, David Howells, James Morris, Serge E. Hallyn, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED Moved struct trusted_key_options to trustes-type.h so that the fields can be accessed from drivers/char/tpm. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> --- include/keys/trusted-type.h | 12 ++++++++++++ security/keys/trusted.h | 11 ----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h index 56f82e5..c91651f 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -12,10 +12,12 @@ #include <linux/key.h> #include <linux/rcupdate.h> +#include <linux/tpm.h> #define MIN_KEY_SIZE 32 #define MAX_KEY_SIZE 128 #define MAX_BLOB_SIZE 320 +#define MAX_PCRINFO_SIZE 64 struct trusted_key_payload { struct rcu_head rcu; @@ -26,6 +28,16 @@ struct trusted_key_payload { unsigned char blob[MAX_BLOB_SIZE]; }; +struct trusted_key_options { + uint16_t keytype; + uint32_t keyhandle; + unsigned char keyauth[TPM_DIGEST_SIZE]; + unsigned char blobauth[TPM_DIGEST_SIZE]; + uint32_t pcrinfo_len; + unsigned char pcrinfo[MAX_PCRINFO_SIZE]; + int pcrlock; +}; + extern struct key_type key_type_trusted; #endif /* _KEYS_TRUSTED_TYPE_H */ diff --git a/security/keys/trusted.h b/security/keys/trusted.h index 3249fbd..ff001a5 100644 --- a/security/keys/trusted.h +++ b/security/keys/trusted.h @@ -2,7 +2,6 @@ #define __TRUSTED_KEY_H /* implementation specific TPM constants */ -#define MAX_PCRINFO_SIZE 64 #define MAX_BUF_SIZE 512 #define TPM_GETRANDOM_SIZE 14 #define TPM_OSAP_SIZE 36 @@ -36,16 +35,6 @@ enum { SRK_keytype = 4 }; -struct trusted_key_options { - uint16_t keytype; - uint32_t keyhandle; - unsigned char keyauth[SHA1_DIGEST_SIZE]; - unsigned char blobauth[SHA1_DIGEST_SIZE]; - uint32_t pcrinfo_len; - unsigned char pcrinfo[MAX_PCRINFO_SIZE]; - int pcrlock; -}; - #define TPM_DEBUG 0 #if TPM_DEBUG -- 2.5.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen @ 2015-10-13 8:11 ` Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen ` (3 subsequent siblings) 6 siblings, 0 replies; 10+ messages in thread From: Jarkko Sakkinen @ 2015-10-13 8:11 UTC (permalink / raw) To: tpmdd-devel, linux-kernel Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, Marcel Selhorst, David Safford, Mimi Zohar, David Howells, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED Added tpm_trusted_seal() and tpm_trusted_unseal() API for sealing trusted keys. This patch implements basic sealing and unsealing functionality for TPM 2.0: * Seal with a parent key using a 20 byte auth value. * Unseal with a parent key using a 20 byte auth value. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> --- drivers/char/tpm/tpm-interface.c | 76 ++++++++++++ drivers/char/tpm/tpm.h | 15 ++- drivers/char/tpm/tpm2-cmd.c | 250 ++++++++++++++++++++++++++++++++++++++- include/keys/trusted-type.h | 2 +- include/linux/tpm.h | 26 ++++ 5 files changed, 366 insertions(+), 3 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index e85d341..c50637d 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -666,6 +666,30 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) } /** + * tpm_is_tpm2 - is the chip a TPM2 chip? + * @chip_num: tpm idx # or ANY + * + * Returns < 0 on error, and 1 or 0 on success depending whether the chip + * is a TPM2 chip. + */ +int tpm_is_tpm2(u32 chip_num) +{ + struct tpm_chip *chip; + int rc; + + chip = tpm_chip_find_get(chip_num); + if (chip == NULL) + return -ENODEV; + + rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0; + + tpm_chip_put(chip); + + return rc; +} +EXPORT_SYMBOL_GPL(tpm_is_tpm2); + +/** * tpm_pcr_read - read a pcr value * @chip_num: tpm idx # or ANY * @pcr_idx: pcr idx to retrieve @@ -1021,6 +1045,58 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) } EXPORT_SYMBOL_GPL(tpm_get_random); +/** + * tpm_seal_trusted() - seal a trusted key + * @chip_num: A specific chip number for the request or TPM_ANY_NUM + * @options: authentication values and other options + * @payload: the key data in clear and encrypted form + * + * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips + * are supported. + */ +int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + struct tpm_chip *chip; + int rc; + + chip = tpm_chip_find_get(chip_num); + if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2)) + return -ENODEV; + + rc = tpm2_seal_trusted(chip, payload, options); + + tpm_chip_put(chip); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_seal_trusted); + +/** + * tpm_unseal_trusted() - unseal a trusted key + * @chip_num: A specific chip number for the request or TPM_ANY_NUM + * @options: authentication values and other options + * @payload: the key data in clear and encrypted form + * + * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips + * are supported. + */ +int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + struct tpm_chip *chip; + int rc; + + chip = tpm_chip_find_get(chip_num); + if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2)) + return -ENODEV; + + rc = tpm2_unseal_trusted(chip, payload, options); + + tpm_chip_put(chip); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_unseal_trusted); + static int __init tpm_init(void) { int rc; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index df43979..09aca509 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -90,6 +90,9 @@ enum tpm2_return_codes { enum tpm2_algorithms { TPM2_ALG_SHA1 = 0x0004, + TPM2_ALG_KEYEDHASH = 0x0008, + TPM2_ALG_SHA256 = 0x000B, + TPM2_ALG_NULL = 0x0010 }; enum tpm2_command_codes { @@ -97,6 +100,10 @@ enum tpm2_command_codes { TPM2_CC_SELF_TEST = 0x0143, TPM2_CC_STARTUP = 0x0144, TPM2_CC_SHUTDOWN = 0x0145, + TPM2_CC_CREATE = 0x0153, + TPM2_CC_LOAD = 0x0157, + TPM2_CC_UNSEAL = 0x015E, + TPM2_CC_FLUSH_CONTEXT = 0x0165, TPM2_CC_GET_CAPABILITY = 0x017A, TPM2_CC_GET_RANDOM = 0x017B, TPM2_CC_PCR_READ = 0x017E, @@ -399,7 +406,7 @@ struct tpm_buf { u8 *data; }; -static inline void tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) { struct tpm_input_header *head; @@ -525,6 +532,12 @@ static inline void tpm_remove_ppi(struct tpm_chip *chip) int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash); int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); +int tpm2_seal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options); +int tpm2_unseal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options); ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, const char *desc); diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 011909a..bd7039f 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Intel Corporation + * Copyright (C) 2014, 2015 Intel Corporation * * Authors: * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> @@ -16,6 +16,11 @@ */ #include "tpm.h" +#include <keys/trusted-type.h> + +enum tpm2_object_attributes { + TPM2_ATTR_USER_WITH_AUTH = BIT(6), +}; struct tpm2_startup_in { __be16 startup_type; @@ -381,6 +386,249 @@ static const struct tpm_input_header tpm2_get_tpm_pt_header = { }; /** + * Append TPMS_AUTH_COMMAND to the buffer. The buffer must be allocated with + * tpm_buf_alloc(). + * + * @param buf: an allocated tpm_buf instance + * @param nonce: the session nonce, may be NULL if not used + * @param nonce_len: the session nonce length, may be 0 if not used + * @param attributes: the session attributes + * @param hmac: the session HMAC or password, may be NULL if not used + * @param hmac_len: the session HMAC or password length, maybe 0 if not used + */ +static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle, + const u8 *nonce, u16 nonce_len, + u8 attributes, + const u8 *hmac, u16 hmac_len) +{ + tpm_buf_append_u32(buf, 9 + nonce_len + hmac_len); + tpm_buf_append_u32(buf, session_handle); + tpm_buf_append_u16(buf, nonce_len); + + if (nonce && nonce_len) + tpm_buf_append(buf, nonce, nonce_len); + + tpm_buf_append_u8(buf, attributes); + tpm_buf_append_u16(buf, hmac_len); + + if (hmac && hmac_len) + tpm_buf_append(buf, hmac, hmac_len); +} + +/** + * tpm2_seal_trusted() - seal a trusted key + * @chip_num: A specific chip number for the request or TPM_ANY_NUM + * @options: authentication values and other options + * @payload: the key data in clear and encrypted form + * + * Returns < 0 on error and 0 on success. + */ +int tpm2_seal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + unsigned int blob_len; + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, options->keyhandle); + tpm2_buf_append_auth(&buf, TPM2_RS_PW, + NULL /* nonce */, 0, + 0 /* session_attributes */, + options->keyauth /* hmac */, + TPM_DIGEST_SIZE); + + /* sensitive */ + tpm_buf_append_u16(&buf, 4 + TPM_DIGEST_SIZE + payload->key_len); + + tpm_buf_append_u16(&buf, TPM_DIGEST_SIZE); + tpm_buf_append(&buf, options->blobauth, TPM_DIGEST_SIZE); + tpm_buf_append_u16(&buf, payload->key_len); + tpm_buf_append(&buf, payload->key, payload->key_len); + + /* public */ + tpm_buf_append_u16(&buf, 14); + + tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); + tpm_buf_append_u16(&buf, TPM2_ALG_SHA256); + tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH); + tpm_buf_append_u16(&buf, 0); /* policy digest size */ + tpm_buf_append_u16(&buf, TPM2_ALG_NULL); + tpm_buf_append_u16(&buf, 0); + + /* outside info */ + tpm_buf_append_u16(&buf, 0); + + /* creation PCR */ + tpm_buf_append_u32(&buf, 0); + + if (buf.flags & TPM_BUF_OVERFLOW) { + rc = -E2BIG; + goto out; + } + + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data"); + if (rc) + goto out; + + blob_len = be32_to_cpup((__be32 *) &buf.data[TPM_HEADER_SIZE]); + if (blob_len > MAX_BLOB_SIZE) { + rc = -E2BIG; + goto out; + } + + memcpy(payload->blob, &buf.data[TPM_HEADER_SIZE + 4], blob_len); + payload->blob_len = blob_len; + +out: + tpm_buf_destroy(&buf); + + if (rc > 0) + rc = -EPERM; + + return rc; +} + +static int tpm2_load(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options, + u32 *blob_handle) +{ + struct tpm_buf buf; + unsigned int private_len; + unsigned int public_len; + unsigned int blob_len; + int rc; + + private_len = be16_to_cpup((__be16 *) &payload->blob[0]); + if (private_len > (payload->blob_len - 2)) + return -E2BIG; + + public_len = be16_to_cpup((__be16 *) &payload->blob[2 + private_len]); + blob_len = private_len + public_len + 4; + if (blob_len > payload->blob_len) + return -E2BIG; + + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, options->keyhandle); + tpm2_buf_append_auth(&buf, TPM2_RS_PW, + NULL /* nonce */, 0, + 0 /* session_attributes */, + options->keyauth /* hmac */, + TPM_DIGEST_SIZE); + + tpm_buf_append(&buf, payload->blob, blob_len); + + if (buf.flags & TPM_BUF_OVERFLOW) { + rc = -E2BIG; + goto out; + } + + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob"); + if (!rc) + *blob_handle = be32_to_cpup( + (__be32 *) &buf.data[TPM_HEADER_SIZE]); + +out: + tpm_buf_destroy(&buf); + + if (rc > 0) + rc = -EPERM; + + return rc; +} + +static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) +{ + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); + if (rc) { + dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n", + handle); + return; + } + + tpm_buf_append_u32(&buf, handle); + + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context"); + if (rc) + dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle, + rc); + + tpm_buf_destroy(&buf); +} + +static int tpm2_unseal(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options, + u32 blob_handle) +{ + struct tpm_buf buf; + int rc; + + rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); + if (rc) + return rc; + + tpm_buf_append_u32(&buf, blob_handle); + tpm2_buf_append_auth(&buf, TPM2_RS_PW, + NULL /* nonce */, 0, + 0 /* session_attributes */, + options->blobauth /* hmac */, + TPM_DIGEST_SIZE); + + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing"); + if (rc > 0) + rc = -EPERM; + + if (!rc) { + payload->key_len = be16_to_cpup( + (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); + + memcpy(payload->key, &buf.data[TPM_HEADER_SIZE + 6], + payload->key_len); + } + + tpm_buf_destroy(&buf); + return rc; +} + +/** + * tpm_unseal_trusted() - unseal a trusted key + * @chip_num: A specific chip number for the request or TPM_ANY_NUM + * @options: authentication values and other options + * @payload: the key data in clear and encrypted form + * + * Returns < 0 on error and 0 on success. + */ +int tpm2_unseal_trusted(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + u32 blob_handle; + int rc; + + rc = tpm2_load(chip, payload, options, &blob_handle); + if (rc) + return rc; + + rc = tpm2_unseal(chip, payload, options, blob_handle); + + tpm2_flush_context(chip, blob_handle); + + return rc; +} + +/** * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property * @chip: TPM chip to use. * @property_id: property ID. diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h index c91651f..f91ecd9 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -16,7 +16,7 @@ #define MIN_KEY_SIZE 32 #define MAX_KEY_SIZE 128 -#define MAX_BLOB_SIZE 320 +#define MAX_BLOB_SIZE 512 #define MAX_PCRINFO_SIZE 64 struct trusted_key_payload { diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 8350c53..706e63e 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -30,6 +30,8 @@ #define TPM_ANY_NUM 0xFFFF struct tpm_chip; +struct trusted_key_payload; +struct trusted_key_options; struct tpm_class_ops { const u8 req_complete_mask; @@ -46,11 +48,22 @@ struct tpm_class_ops { #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) +extern int tpm_is_tpm2(u32 chip_num); extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf); extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash); extern int tpm_send(u32 chip_num, void *cmd, size_t buflen); extern int tpm_get_random(u32 chip_num, u8 *data, size_t max); +extern int tpm_seal_trusted(u32 chip_num, + struct trusted_key_payload *payload, + struct trusted_key_options *options); +extern int tpm_unseal_trusted(u32 chip_num, + struct trusted_key_payload *payload, + struct trusted_key_options *options); #else +static inline int tpm_is_tpm2(u32 chip_num) +{ + return -ENODEV; +} static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) { return -ENODEV; } @@ -63,5 +76,18 @@ static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) { static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) { return -ENODEV; } + +static inline int tpm_seal_trusted(u32 chip_num, + struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + return -ENODEV; +} +static inline int tpm_unseal_trusted(u32 chip_num, + struct trusted_key_payload *payload, + struct trusted_key_options *options) +{ + return -ENODEV; +} #endif #endif -- 2.5.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen ` (2 preceding siblings ...) 2015-10-13 8:11 ` [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen @ 2015-10-13 8:11 ` Jarkko Sakkinen 2015-10-13 8:53 ` [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen ` (2 subsequent siblings) 6 siblings, 0 replies; 10+ messages in thread From: Jarkko Sakkinen @ 2015-10-13 8:11 UTC (permalink / raw) To: tpmdd-devel, linux-kernel Cc: peterhuewe, gregkh, jgunthorpe, Jarkko Sakkinen, David Safford, Mimi Zohar, David Howells, James Morris, Serge E. Hallyn, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED Call tpm_seal_trusted() and tpm_unseal_trusted() for TPM 2.0 chips. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Andreas Fuchs <andreas.fuchs@sit.fraunhofer.de> --- security/keys/trusted.c | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/security/keys/trusted.c b/security/keys/trusted.c index c0594cb..d3633cf 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -862,12 +862,19 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p, static struct trusted_key_options *trusted_options_alloc(void) { struct trusted_key_options *options; + int tpm2; + + tpm2 = tpm_is_tpm2(TPM_ANY_NUM); + if (tpm2 < 0) + return NULL; options = kzalloc(sizeof *options, GFP_KERNEL); if (options) { /* set any non-zero defaults */ options->keytype = SRK_keytype; - options->keyhandle = SRKHANDLE; + + if (!tpm2) + options->keyhandle = SRKHANDLE; } return options; } @@ -905,6 +912,11 @@ static int trusted_instantiate(struct key *key, int ret = 0; int key_cmd; size_t key_len; + int tpm2; + + tpm2 = tpm_is_tpm2(TPM_ANY_NUM); + if (tpm2 < 0) + return tpm2; if (datalen <= 0 || datalen > 32767 || !prep->data) return -EINVAL; @@ -932,12 +944,20 @@ static int trusted_instantiate(struct key *key, goto out; } + if (!options->keyhandle) { + ret = -EINVAL; + goto out; + } + dump_payload(payload); dump_options(options); switch (key_cmd) { case Opt_load: - ret = key_unseal(payload, options); + if (tpm2) + ret = tpm_unseal_trusted(TPM_ANY_NUM, payload, options); + else + ret = key_unseal(payload, options); dump_payload(payload); dump_options(options); if (ret < 0) @@ -950,7 +970,10 @@ static int trusted_instantiate(struct key *key, pr_info("trusted_key: key_create failed (%d)\n", ret); goto out; } - ret = key_seal(payload, options); + if (tpm2) + ret = tpm_seal_trusted(TPM_ANY_NUM, payload, options); + else + ret = key_seal(payload, options); if (ret < 0) pr_info("trusted_key: key_seal failed (%d)\n", ret); break; @@ -1018,6 +1041,13 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) kfree(new_p); goto out; } + + if (!new_o->keyhandle) { + ret = -EINVAL; + kfree(new_p); + goto out; + } + /* copy old key values, and reseal with new pcrs */ new_p->migratable = p->migratable; new_p->key_len = p->key_len; -- 2.5.0 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen ` (3 preceding siblings ...) 2015-10-13 8:11 ` [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen @ 2015-10-13 8:53 ` Jarkko Sakkinen 2015-10-13 17:41 ` Jason Gunthorpe 2015-10-16 16:21 ` David Howells 6 siblings, 0 replies; 10+ messages in thread From: Jarkko Sakkinen @ 2015-10-13 8:53 UTC (permalink / raw) To: tpmdd-devel, linux-kernel Cc: peterhuewe, gregkh, jgunthorpe, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED, kevin.strasser On Tue, Oct 13, 2015 at 11:11:21AM +0300, Jarkko Sakkinen wrote: > Basic trusted keys support: auth value and SHA256. > > v2: > > * Removed all the changes that modify the existing functions to use > the new struct tpm_buf. These changes should be done separately from > this patch set as they require separate QA + review. > * 'keyhandle=' is now required for TPM2. Makes sense to always state > the sealing key because there's no any fixed keys on the chip (thanks > to Andreas Fuchs for this comment). > * I updated tpm_buf to a be heap based structure. Now there's one full > page of memory for variable sized messages. Also the stack is greatly > reduced. The basic test that I did was: ID=$(keyctl add trusted kmk "new 32 keyhandle=0x80000000" @u) keyctl pipe $ID > blob.hex keyctl clear @u keyctl add trusted kmk "load `cat blob.hex` keyhandle=0x80000000" @u keyctl clear @u I also checked that the code fails with -EINVAL when keyhandle is not given. For generating a sealing key I used tpm2-root-key script from https://github.com/jsakkine/linux-tpm2 I think the code is in the shape that it is ready to be pulled but some tested-by's are needed. > Jarkko Sakkinen (4): > tpm: introduce tpm_buf > keys, trusted: move struct trusted_key_options to trusted-type.h > tpm: seal/unseal for TPM 2.0 > keys, trusted: seal/unseal with TPM 2.0 chips > > drivers/char/tpm/tpm-interface.c | 76 ++++++++++++ > drivers/char/tpm/tpm.h | 110 +++++++++++++++++ > drivers/char/tpm/tpm2-cmd.c | 250 ++++++++++++++++++++++++++++++++++++++- > include/keys/trusted-type.h | 14 ++- > include/linux/tpm.h | 26 ++++ > security/keys/trusted.c | 36 +++++- > security/keys/trusted.h | 11 -- > 7 files changed, 507 insertions(+), 16 deletions(-) > > -- > 2.5.0 > > -- > 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] 10+ messages in thread
* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen ` (4 preceding siblings ...) 2015-10-13 8:53 ` [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen @ 2015-10-13 17:41 ` Jason Gunthorpe 2015-10-13 19:25 ` Jarkko Sakkinen 2015-10-16 16:21 ` David Howells 6 siblings, 1 reply; 10+ messages in thread From: Jason Gunthorpe @ 2015-10-13 17:41 UTC (permalink / raw) To: Jarkko Sakkinen Cc: tpmdd-devel, linux-kernel, peterhuewe, gregkh, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED On Tue, Oct 13, 2015 at 11:11:21AM +0300, Jarkko Sakkinen wrote: > * I updated tpm_buf to a be heap based structure. Now there's one full > page of memory for variable sized messages. Also the stack is greatly > reduced. You may as well just use a skb then. Jason ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 2015-10-13 17:41 ` Jason Gunthorpe @ 2015-10-13 19:25 ` Jarkko Sakkinen 0 siblings, 0 replies; 10+ messages in thread From: Jarkko Sakkinen @ 2015-10-13 19:25 UTC (permalink / raw) To: Jason Gunthorpe Cc: tpmdd-devel, linux-kernel, peterhuewe, gregkh, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED On Tue, Oct 13, 2015 at 11:41:20AM -0600, Jason Gunthorpe wrote: > On Tue, Oct 13, 2015 at 11:11:21AM +0300, Jarkko Sakkinen wrote: > > > * I updated tpm_buf to a be heap based structure. Now there's one full > > page of memory for variable sized messages. Also the stack is greatly > > reduced. > > You may as well just use a skb then. struct sk_buff?? I think the structure that I've implemented is a good fit. It's simple to use and does exactly what we need. Can you elaborate what's the problem with tpm_buf? > Jason /Jarkko ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen ` (5 preceding siblings ...) 2015-10-13 17:41 ` Jason Gunthorpe @ 2015-10-16 16:21 ` David Howells 2015-10-16 18:30 ` Jarkko Sakkinen 6 siblings, 1 reply; 10+ messages in thread From: David Howells @ 2015-10-16 16:21 UTC (permalink / raw) To: Jarkko Sakkinen Cc: dhowells, tpmdd-devel, linux-kernel, peterhuewe, gregkh, jgunthorpe, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED Hi Jarkko, For some reason I don't see patch 1. David ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 2015-10-16 16:21 ` David Howells @ 2015-10-16 18:30 ` Jarkko Sakkinen 0 siblings, 0 replies; 10+ messages in thread From: Jarkko Sakkinen @ 2015-10-16 18:30 UTC (permalink / raw) To: David Howells Cc: tpmdd-devel, linux-kernel, peterhuewe, gregkh, jgunthorpe, open list:KEYS-TRUSTED, open list:KEYS-TRUSTED Hi On Fri, Oct 16, 2015 at 05:21:02PM +0100, David Howells wrote: > Hi Jarkko, > > For some reason I don't see patch 1. Weird. Well, maybe the best way to proceed is that I'll send the contents of for-peter-v44 branch for review. It's 9 patches in total, PPI, trusted keys and couple of bug fixes. > David /Jarkko ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2015-10-16 18:30 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-10-13 8:11 [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 1/4] tpm: introduce tpm_buf Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 2/4] keys, trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 3/4] tpm: seal/unseal for TPM 2.0 Jarkko Sakkinen 2015-10-13 8:11 ` [PATCH v2 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen 2015-10-13 8:53 ` [PATCH v2 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen 2015-10-13 17:41 ` Jason Gunthorpe 2015-10-13 19:25 ` Jarkko Sakkinen 2015-10-16 16:21 ` David Howells 2015-10-16 18:30 ` Jarkko Sakkinen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox