From: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
To: tpmdd-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org
Cc: peterhuewe@gmx.de, gregkh@linuxfoundation.org,
jgunthorpe@obsidianresearch.com, akpm@linux-foundation.org,
mjg59@srcf.ucam.org,
Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>,
Marcel Selhorst <tpmdd@selhorst.net>,
David Safford <safford@us.ibm.com>,
Mimi Zohar <zohar@linux.vnet.ibm.com>,
David Howells <dhowells@redhat.com>,
linux-security-module@vger.kernel.org (open list:KEYS-TRUSTED),
keyrings@vger.kernel.org (open list:KEYS-TRUSTED)
Subject: [PATCH 3/4] tpm: seal/unseal for TPM 2.0
Date: Fri, 2 Oct 2015 11:38:17 +0300 [thread overview]
Message-ID: <1443775102-9727-4-git-send-email-jarkko.sakkinen@linux.intel.com> (raw)
In-Reply-To: <1443775102-9727-1-git-send-email-jarkko.sakkinen@linux.intel.com>
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 | 75 ++++++++++++++++
drivers/char/tpm/tpm.h | 14 +++
drivers/char/tpm/tpm2-cmd.c | 184 +++++++++++++++++++++++++++++++++++++++
include/keys/trusted-type.h | 2 +-
include/linux/tpm.h | 26 ++++++
5 files changed, 300 insertions(+), 1 deletion(-)
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e85d341..6dd4c74 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -666,6 +666,29 @@ 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 1 if 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 +1044,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 f04afb7..2d79939 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -88,6 +88,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 {
@@ -95,6 +98,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,
@@ -492,6 +499,13 @@ 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 0d55674..0986c96 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -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_pcr_read_in {
__be32 pcr_selects_cnt;
@@ -322,6 +327,185 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *res_buf, size_t max)
}
/**
+ * 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;
+
+ tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+ 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);
+
+ rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_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:
+ 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;
+
+ tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+ 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, payload->blob_len);
+
+ rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE, "loading blob");
+ if (!rc)
+ *blob_handle = be32_to_cpup(
+ (__be32 *) &buf.data[TPM_HEADER_SIZE]);
+
+ if (rc > 0)
+ rc = -EPERM;
+
+ return rc;
+}
+
+static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
+{
+ struct tpm_buf buf;
+ int rc;
+
+ tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
+ tpm_buf_append_u32(&buf, handle);
+
+ rc = tpm_transmit_cmd(chip, buf.data, TPM_BUF_SIZE, "flushing context");
+ if (rc)
+ dev_warn(chip->pdev, "0x%08x was not flushed\n", handle);
+}
+
+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;
+
+ tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+ 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, TPM_BUF_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);
+ }
+
+ 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 9a2c626..0224b21 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
next prev parent reply other threads:[~2015-10-02 8:38 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-02 8:38 [PATCH 0/4] Basic trusted keys support " Jarkko Sakkinen
2015-10-02 8:38 ` [PATCH 1/4] tpm: introduce struct tpm_buf Jarkko Sakkinen
2015-10-02 8:38 ` [PATCH 2/4] trusted: move struct trusted_key_options to trusted-type.h Jarkko Sakkinen
2015-10-02 8:38 ` Jarkko Sakkinen [this message]
2015-10-13 17:34 ` [PATCH 3/4] tpm: seal/unseal for TPM 2.0 Jason Gunthorpe
2015-10-13 19:49 ` Jarkko Sakkinen
2015-10-02 8:38 ` [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips Jarkko Sakkinen
2015-10-03 10:00 ` [tpmdd-devel] " Fuchs, Andreas
2015-10-03 10:26 ` Jarkko Sakkinen
2015-10-03 10:35 ` Jarkko Sakkinen
2015-10-04 18:57 ` Fuchs, Andreas
2015-10-05 8:37 ` Jarkko Sakkinen
2015-10-05 9:00 ` Fuchs, Andreas
2015-10-05 11:56 ` Jarkko Sakkinen
2015-10-05 12:20 ` Fuchs, Andreas
2015-10-05 13:17 ` Jarkko Sakkinen
2015-10-05 13:36 ` Fuchs, Andreas
2015-10-05 13:57 ` Jarkko Sakkinen
2015-10-05 14:13 ` Fuchs, Andreas
2015-10-05 14:28 ` Jarkko Sakkinen
2015-10-05 15:20 ` Arthur, Will C
2015-10-06 6:22 ` Fuchs, Andreas
2015-10-06 12:26 ` Jarkko Sakkinen
2015-10-06 13:16 ` Fuchs, Andreas
2015-10-06 15:05 ` Jarkko Sakkinen
2015-10-07 10:04 ` Fuchs, Andreas
2015-10-07 10:25 ` Jarkko Sakkinen
2015-10-07 10:32 ` Fuchs, Andreas
2015-10-07 11:15 ` Jarkko Sakkinen
-- strict thread matches above, loose matches on Subject: below --
2015-07-03 15:36 [PATCH 0/4] Basic trusted keys support for TPM 2.0 Jarkko Sakkinen
2015-07-03 15:36 ` [PATCH 3/4] tpm: seal/unseal " Jarkko Sakkinen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1443775102-9727-4-git-send-email-jarkko.sakkinen@linux.intel.com \
--to=jarkko.sakkinen@linux.intel.com \
--cc=akpm@linux-foundation.org \
--cc=dhowells@redhat.com \
--cc=gregkh@linuxfoundation.org \
--cc=jgunthorpe@obsidianresearch.com \
--cc=keyrings@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mjg59@srcf.ucam.org \
--cc=peterhuewe@gmx.de \
--cc=safford@us.ibm.com \
--cc=tpmdd-devel@lists.sourceforge.net \
--cc=tpmdd@selhorst.net \
--cc=zohar@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome