Link to previous cover letter:
https://lore.kernel.org/linux-integrity/[email protected]/
This is marked v6 instead of v5 because I did a v5 after feedback on v4
but didn't get around to posting it and then had to rework the whole of
the kernel space handling while I was on holiday. I also added the
documentation of how the whole thing works and the rationale for doing
it in tpm-security.rst (patch 11). The main reason for doing this now
is so we have something to discuss at Plumbers.
The new patch set implements the various splits requested, but the main
changes are that the kernel space is gone and is replaced by a context
save and restore of the generated null seed. This is easier to handle
than a full kernel space given the new threading for TPM spaces, but
conceptually it is still very like a space. I've also made whether
integrity and encryption is turned on a Kconfig option.
James
---
James Bottomley (12):
tpm-buf: move from static inlines to real functions
tpm-buf: add handling for TPM2B types
tpm-buf: add cursor based functions for response parsing
tpm2-space: export the context save and load commands
tpm2-sessions: Add full HMAC and encrypt/decrypt session handling
tpm-buf: add tpm_buf_parameters()
tpm2: add hmac checks to tpm2_pcr_extend()
tpm2: add session encryption protection to tpm2_get_random()
trusted keys: Add session encryption protection to the seal/unseal
path
tpm: add the null key name as a tpm2 sysfs variable
Documentation: add tpm-security.rst
tpm2-sessions: NOT FOR COMMITTING add sessions testing
Documentation/security/tpm/tpm-security.rst | 204 +++++
drivers/char/tpm/Kconfig | 11 +
drivers/char/tpm/Makefile | 4 +
drivers/char/tpm/tpm-buf.c | 202 +++++
drivers/char/tpm/tpm-chip.c | 1 +
drivers/char/tpm/tpm-sysfs.c | 27 +-
drivers/char/tpm/tpm.h | 117 +--
drivers/char/tpm/tpm2-cmd.c | 202 +++--
drivers/char/tpm/tpm2-sessions-test.c | 795 ++++++++++++++++++
drivers/char/tpm/tpm2-sessions.c | 1204 +++++++++++++++++++++++++++
drivers/char/tpm/tpm2-sessions.h | 138 +++
drivers/char/tpm/tpm2-space.c | 8 +-
include/linux/tpm.h | 29 +
13 files changed, 2787 insertions(+), 155 deletions(-)
create mode 100644 Documentation/security/tpm/tpm-security.rst
create mode 100644 drivers/char/tpm/tpm-buf.c
create mode 100644 drivers/char/tpm/tpm2-sessions-test.c
create mode 100644 drivers/char/tpm/tpm2-sessions.c
create mode 100644 drivers/char/tpm/tpm2-sessions.h
--
2.16.4
This runs through a preset sequence using sessions to demonstrate that
the session handling code functions. It does both HMAC, encryption
and decryption by testing an encrypted sealing operation with
authority and proving that the same sealed data comes back again via
an HMAC and response encryption. It also does policy unsealing which
mimics the more complex of the trusted key scenarios.
Signed-off-by: James Bottomley <[email protected]>
---
v3: add policy unseal testing with two sessions
v6: move to new null seed framework
---
drivers/char/tpm/Makefile | 2 +
drivers/char/tpm/tpm-chip.c | 1 +
drivers/char/tpm/tpm.h | 1 +
drivers/char/tpm/tpm2-cmd.c | 7 +
drivers/char/tpm/tpm2-sessions-test.c | 795 ++++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm2-sessions.c | 1 +
drivers/char/tpm/tpm2-sessions.h | 3 +-
7 files changed, 809 insertions(+), 1 deletion(-)
create mode 100644 drivers/char/tpm/tpm2-sessions-test.c
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 8f9e58317048..f6577c9e3138 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -35,3 +35,5 @@ obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o
+
+obj-m += tpm2-sessions-test.o
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 4838c6a9f0f2..5dda37047a71 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -252,6 +252,7 @@ struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip)
return NULL;
return chip;
}
+EXPORT_SYMBOL(tpm_find_get_ops);
/**
* tpm_dev_release() - free chip memory and the device number
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index c88eee6376e4..06f63874e833 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -117,6 +117,7 @@ enum tpm2_command_codes {
TPM2_CC_CONTEXT_LOAD = 0x0161,
TPM2_CC_CONTEXT_SAVE = 0x0162,
TPM2_CC_FLUSH_CONTEXT = 0x0165,
+ TPM2_CC_POLICY_COMMAND_CODE = 0x16c,
TPM2_CC_READ_PUBLIC = 0x0173,
TPM2_CC_START_AUTH_SESS = 0x0176,
TPM2_CC_VERIFY_SIGNATURE = 0x0177,
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 2c798f18282f..d4bbe19170d1 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -222,6 +222,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
tpm_buf_destroy(&buf);
return rc;
}
+EXPORT_SYMBOL_GPL(tpm2_pcr_read);
/**
* tpm2_pcr_extend() - extend a PCR value
@@ -269,6 +270,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
return rc;
}
+EXPORT_SYMBOL_GPL(tpm2_pcr_extend);
struct tpm2_get_random_out {
__be16 size;
@@ -353,6 +355,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
tpm_buf_destroy(&buf);
return err;
}
+EXPORT_SYMBOL_GPL(tpm2_get_random);
/**
* tpm2_flush_context() - execute a TPM2_FlushContext command
@@ -376,6 +379,7 @@ void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
tpm_transmit_cmd(chip, &buf, 0, "flushing context");
tpm_buf_destroy(&buf);
}
+EXPORT_SYMBOL_GPL(tpm2_flush_context);
/**
* tpm_buf_append_auth() - append TPMS_AUTH_COMMAND to the buffer.
@@ -406,6 +410,7 @@ void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
if (hmac && hmac_len)
tpm_buf_append(buf, hmac, hmac_len);
}
+EXPORT_SYMBOL_GPL(tpm2_buf_append_auth);
/**
* tpm2_seal_trusted() - seal the payload of a trusted key
@@ -532,6 +537,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
return rc;
}
+EXPORT_SYMBOL_GPL(tpm2_seal_trusted);
/**
* tpm2_load_cmd() - execute a TPM2_Load command
@@ -715,6 +721,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
tpm2_flush_context(chip, blob_handle);
return rc;
}
+EXPORT_SYMBOL_GPL(tpm2_unseal_trusted);
struct tpm2_get_cap_out {
u8 more_data;
diff --git a/drivers/char/tpm/tpm2-sessions-test.c b/drivers/char/tpm/tpm2-sessions-test.c
new file mode 100644
index 000000000000..834811ab3466
--- /dev/null
+++ b/drivers/char/tpm/tpm2-sessions-test.c
@@ -0,0 +1,795 @@
+/* run a set of tests of the sessions code */
+#include "tpm.h"
+#include "tpm2-sessions.h"
+
+#include <linux/random.h>
+
+#include <asm/unaligned.h>
+
+#include <crypto/aes.h>
+#include <crypto/hash.h>
+
+#include <keys/trusted-type.h>
+
+/* simple policy: command code must be TPM2_CC_UNSEAL */
+static u8 policy[] = {
+ 0xe6, 0x13, 0x13, 0x70, 0x76, 0x52, 0x4b, 0xde,
+ 0x48, 0x75, 0x33, 0x86, 0x58, 0x84, 0xe9, 0x73,
+ 0x2e, 0xbe, 0xe3, 0xaa, 0xcb, 0x09, 0x5d, 0x94,
+ 0xa6, 0xde, 0x49, 0x2e, 0xc0, 0x6c, 0x46, 0xfa,
+};
+
+static struct crypto_shash *sha256_hash;
+
+static int parse_create_primary(struct tpm_chip *chip, u8 *data, u32 *nullkey)
+{
+ struct tpm_header *head = (struct tpm_header *)data;
+ u16 len;
+ u32 tot_len = be32_to_cpu(head->length);
+ u32 val, parm_len;
+ const u8 *resp, *tmp;
+ SHASH_DESC_ON_STACK(desc, sha256_hash);
+
+ data += TPM_HEADER_SIZE;
+ /* we're starting after the header so adjust the length */
+ tot_len -= TPM_HEADER_SIZE;
+
+ resp = data;
+ *nullkey = tpm_get_inc_u32(&resp);
+ parm_len = tpm_get_inc_u32(&resp);
+ if (parm_len + 8 > tot_len)
+ return -EINVAL;
+ len = tpm_get_inc_u16(&resp);
+ tmp = resp;
+ /* now we have the public area, compute the name of the object */
+ desc->tfm = sha256_hash;
+ put_unaligned_be16(TPM_ALG_SHA256, chip->tpmkeyname);
+ crypto_shash_init(desc);
+ crypto_shash_update(desc, resp, len);
+ crypto_shash_final(desc, chip->tpmkeyname + 2);
+ /* validate the public key */
+ val = tpm_get_inc_u16(&tmp);
+ /* key type (must be what we asked for) */
+ if (val != TPM_ALG_ECC)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* name algorithm */
+ if (val != TPM_ALG_SHA256)
+ return -EINVAL;
+ val = tpm_get_inc_u32(&tmp);
+ /* object properties */
+ if (val != (TPM2_OA_NO_DA |
+ TPM2_OA_FIXED_TPM |
+ TPM2_OA_FIXED_PARENT |
+ TPM2_OA_SENSITIVE_DATA_ORIGIN |
+ TPM2_OA_USER_WITH_AUTH |
+ TPM2_OA_DECRYPT |
+ TPM2_OA_RESTRICTED))
+ return -EINVAL;
+ /* auth policy (empty) */
+ val = tpm_get_inc_u16(&tmp);
+ if (val != 0)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* symmetric key parameters */
+ if (val != TPM_ALG_AES)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* symmetric key length */
+ if (val != AES_KEYSIZE_128 * 8)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* symmetric encryption scheme */
+ if (val != TPM_ALG_CFB)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* signing scheme */
+ if (val != TPM_ALG_NULL)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* ECC Curve */
+ if (val != TPM2_ECC_NIST_P256)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* KDF Scheme */
+ if (val != TPM_ALG_NULL)
+ return -EINVAL;
+ val = tpm_get_inc_u16(&tmp);
+ /* x point */
+ if (val != 32)
+ return -EINVAL;
+ memcpy(chip->ec_point_x, tmp, val);
+ tmp += val;
+ val = tpm_get_inc_u16(&tmp);
+ if (val != 32)
+ return -EINVAL;
+ memcpy(chip->ec_point_y, tmp, val);
+ tmp += val;
+ resp += len;
+ /* should have exactly consumed the tpm2b public structure */
+ if (tmp != resp)
+ return -EINVAL;
+ if (resp - data > parm_len)
+ return -EINVAL;
+ /* creation data (skip) */
+ len = tpm_get_inc_u16(&resp);
+ resp += len;
+ if (resp - data > parm_len)
+ return -EINVAL;
+ /* creation digest (must be sha256) */
+ len = tpm_get_inc_u16(&resp);
+ resp += len;
+ if (len != SHA256_DIGEST_SIZE || resp - data > parm_len)
+ return -EINVAL;
+ /* TPMT_TK_CREATION follows */
+ /* tag, must be TPM_ST_CREATION (0x8021) */
+ val = tpm_get_inc_u16(&resp);
+ if (val != TPM2_ST_CREATION || resp - data > parm_len)
+ return -EINVAL;
+ /* hierarchy (must be NULL) */
+ val = tpm_get_inc_u32(&resp);
+ if (val != TPM2_RH_NULL || resp - data > parm_len)
+ return -EINVAL;
+ /* the ticket digest HMAC (might not be sha256) */
+ len = tpm_get_inc_u16(&resp);
+ resp += len;
+ if (resp - data > parm_len)
+ return -EINVAL;
+ /*
+ * finally we have the name, which is a sha256 digest plus a 2
+ * byte algorithm type
+ */
+ len = tpm_get_inc_u16(&resp);
+ if (resp + len - data != parm_len + 8)
+ return -EINVAL;
+ if (len != SHA256_DIGEST_SIZE + 2)
+ return -EINVAL;
+
+ if (memcmp(chip->tpmkeyname, resp, SHA256_DIGEST_SIZE + 2) != 0) {
+ printk("TPM NULL Seed name comparison failed\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy, u32 *handle)
+{
+ int rc;
+ struct tpm_buf buf;
+ struct tpm_buf template;
+
+ rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY);
+ if (rc)
+ return rc;
+
+ rc = tpm_buf_init_2b(&template);
+ if (rc) {
+ tpm_buf_destroy(&buf);
+ return rc;
+ }
+
+ /*
+ * create the template. Note: in order for userspace to
+ * verify the security of the system, it will have to create
+ * and certify this NULL primary, meaning all the template
+ * parameters will have to be identical, so conform exactly to
+ * the TCG TPM v2.0 Provisioning Guidance for the SRK ECC
+ * key
+ */
+
+ /* key type */
+ tpm_buf_append_u16(&template, TPM_ALG_ECC);
+ /* name algorithm */
+ tpm_buf_append_u16(&template, TPM_ALG_SHA256);
+ /* object properties */
+ tpm_buf_append_u32(&template, TPM2_OA_NO_DA |
+ TPM2_OA_FIXED_TPM |
+ TPM2_OA_FIXED_PARENT |
+ TPM2_OA_SENSITIVE_DATA_ORIGIN |
+ TPM2_OA_USER_WITH_AUTH |
+ TPM2_OA_DECRYPT |
+ TPM2_OA_RESTRICTED);
+ /* sauth policy (empty) */
+ tpm_buf_append_u16(&template, 0);
+
+ /* BEGIN parameters: key specific; for ECC*/
+ /* symmetric algorithm */
+ tpm_buf_append_u16(&template, TPM_ALG_AES);
+ /* bits for symmetric algorithm */
+ tpm_buf_append_u16(&template, 128);
+ /* algorithm mode (must be CFB) */
+ tpm_buf_append_u16(&template, TPM_ALG_CFB);
+ /* scheme (NULL means any scheme) */
+ tpm_buf_append_u16(&template, TPM_ALG_NULL);
+ /* ECC Curve ID */
+ tpm_buf_append_u16(&template, TPM2_ECC_NIST_P256);
+ /* KDF Scheme */
+ tpm_buf_append_u16(&template, TPM_ALG_NULL);
+ /* unique: key specific; for ECC it is two points */
+ tpm_buf_append_u16(&template, 0);
+ tpm_buf_append_u16(&template, 0);
+ /* END parameters */
+
+ /* primary handle */
+ tpm_buf_append_u32(&buf, hierarchy);
+ /* simple authorization for empty auth */
+ tpm2_buf_append_auth(&buf, TPM2_RS_PW, NULL, 0, 0, NULL, 0);
+ /* sensitive create size is 4 for two empty buffers */
+ tpm_buf_append_u16(&buf, 4);
+ /* sensitive create auth data (empty) */
+ tpm_buf_append_u16(&buf, 0);
+ /* sensitive create sensitive data (empty) */
+ tpm_buf_append_u16(&buf, 0);
+ /* the public template */
+ tpm_buf_append_2b(&buf, &template);
+ tpm_buf_destroy(&template);
+ /* outside info (empty) */
+ tpm_buf_append_u16(&buf, 0);
+ /* creation PCR (none) */
+ tpm_buf_append_u32(&buf, 0);
+
+ rc = tpm_transmit_cmd(chip, &buf, 0,
+ "attempting to create NULL primary");
+
+ if (rc == TPM2_RC_SUCCESS)
+ rc = parse_create_primary(chip, buf.data, handle);
+
+ tpm_buf_destroy(&buf);
+
+ return rc;
+}
+
+static u32 get_policy(struct tpm_chip *chip)
+{
+ struct tpm_buf buf;
+ u8 nonce[SHA256_DIGEST_SIZE];
+ u32 h;
+ int rc;
+
+ rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS);
+ if (rc)
+ return 0;
+
+ /* salt key */
+ tpm_buf_append_u32(&buf, TPM2_RH_NULL);
+ /* bind key */
+ tpm_buf_append_u32(&buf, TPM2_RH_NULL);
+ /* zero nonce */
+ memset(nonce, 0, sizeof(nonce));
+ tpm_buf_append_u16(&buf, sizeof(nonce));
+ tpm_buf_append(&buf, nonce, sizeof(nonce));
+ /* encrypted salt (empty) */
+ tpm_buf_append_u16(&buf, 0);
+ /* session type (HMAC, audit or policy) */
+ tpm_buf_append_u8(&buf, TPM2_SE_POLICY);
+ /* symmetric encryption parameters */
+ /* symmetric algorithm */
+ tpm_buf_append_u16(&buf, TPM_ALG_NULL);
+
+ /* hash algorithm for session */
+ tpm_buf_append_u16(&buf, TPM_ALG_SHA256);
+
+ rc = tpm_transmit_cmd(chip, &buf, 0, "start policy session");
+
+ h = get_unaligned_be32(&buf.data[TPM_HEADER_SIZE]);
+
+ tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS,
+ TPM2_CC_POLICY_COMMAND_CODE);
+ tpm_buf_append_u32(&buf, h);
+ tpm_buf_append_u32(&buf, TPM2_CC_UNSEAL);
+
+ rc = tpm_transmit_cmd(chip, &buf, 0, "start policy session");
+
+ tpm_buf_destroy(&buf);
+
+ dev_info(&chip->dev, "got policy session %08x\n", h);
+
+ return h;
+}
+
+int tpm2_sessions_test(void)
+{
+ struct tpm2_auth *auth;
+ struct tpm_buf buf, b1;
+ struct tpm_buf t2b;
+ struct tpm_chip *chip;
+ int rc;
+ char payload[MIN_KEY_SIZE+3];
+ char *password = "Passw0Rd";
+ const u8 *p;
+ u32 h, ps;
+ u8 name[34];
+ u16 len;
+ int ret = -EINVAL;
+ u32 nullkey = 0;
+ struct trusted_key_payload tkp;
+ struct trusted_key_options tko;
+ struct tpm_digest digest, extend[3];
+ u16 digest_len;
+ int i;
+ SHASH_DESC_ON_STACK(desc, sha256_hash);
+
+ chip = tpm_find_get_ops(NULL);
+ if (!chip)
+ return -ENODEV;
+
+ if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+ return -ENODEV;
+
+ sha256_hash = crypto_alloc_shash("sha256", 0, 0);
+
+ /* precursor: get a session */
+ rc = tpm2_start_auth_session(chip, &auth);
+
+ dev_info(&chip->dev, "TPM: start auth session returned %d\n", rc);
+
+ if (rc)
+ return -ENODEV;
+
+ /* first test: get random bytes from TPM */
+ dev_info(&chip->dev, "test 1: TPM random number generator\n");
+ rc = tpm2_get_random(chip, payload, sizeof(payload));
+ if (rc != sizeof(payload)) {
+ dev_err(&chip->dev, "tpm2_get_random failed: %d\n", rc);
+ goto out;
+ }
+ dev_info(&chip->dev, "test 1: PASS\n");
+
+ /*
+ * second test, seal random data protecting sensitive by
+ * encryption and also doing response encryption (not
+ * necessary) The encrypted payload has two components: an
+ * authorization password which must be presented on useal and
+ * the actual data (the random payload)
+ */
+ dev_info(&chip->dev, "test2: seal data and check tpm unsealing functions\n");
+ rc = tpm2_create_primary(chip, TPM2_RH_NULL, &nullkey);
+
+ if (rc != TPM2_RC_SUCCESS) {
+ dev_err(&chip->dev, "tpm2_create_primary failed: %d\n", rc);
+ goto out;
+ }
+
+ dev_info(&chip->dev, "NULL KEY at %08x\n", nullkey);
+
+ tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+ tpm_buf_append_name(&buf, auth, nullkey, chip->tpmkeyname);
+ /* close the session here, get a new one for next seal op */
+ tpm_buf_append_hmac_session(&buf, auth, TPM2_SA_DECRYPT
+ | TPM2_SA_ENCRYPT, NULL, 0);
+ /* sensitive */
+ tpm_buf_init_2b(&t2b);
+ /* the authorization */
+ tpm_buf_append_u16(&t2b, strlen(password));
+ tpm_buf_append(&t2b, password, strlen(password));
+ /* the payload */
+ tpm_buf_append_u16(&t2b, sizeof(payload) + 1);
+ tpm_buf_append(&t2b, payload, sizeof(payload));
+ /* the migrateable flag used by the TPM sealing functions */
+ tpm_buf_append_u8(&t2b, 0);
+ tpm_buf_append_2b(&buf, &t2b);
+ /* the public */
+ /* type */
+ tpm_buf_append_u16(&t2b, TPM_ALG_KEYEDHASH);
+ /* name hash */
+ tpm_buf_append_u16(&t2b, TPM_ALG_SHA256);
+ /* object properties */
+ tpm_buf_append_u32(&t2b, TPM2_OA_USER_WITH_AUTH | TPM2_OA_NO_DA);
+ /* auth policy (empty) */
+ tpm_buf_append_u16(&t2b, 0);
+ /* keyed hash parameters (we're null for a non-HMAC data blob) */
+ tpm_buf_append_u16(&t2b, TPM_ALG_NULL);
+ /* unique */
+ tpm_buf_append_u16(&t2b, 0);
+ tpm_buf_append_2b(&buf, &t2b);
+ /* outside info (also empty) */
+ tpm_buf_append_u16(&buf, 0);
+ /* creation PCR (empty) */
+ tpm_buf_append_u32(&buf, 0);
+ tpm_buf_fill_hmac_session(&buf, auth);
+ rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data");
+ rc = tpm_buf_check_hmac_response(&buf, auth, rc);
+ dev_info(&chip->dev, "TPM: sealing response returned %d\n", rc);
+ if (rc)
+ goto out;
+
+ /*
+ * now load the sealed object (we need the pub and priv parts
+ * returned from prior command
+ */
+ memset(&tkp, 0, sizeof(tkp));
+ memset(&tko, 0, sizeof(tko));
+
+ p = &buf.data[TPM_HEADER_SIZE];
+
+ tkp.blob_len = tpm_get_inc_u32(&p);
+ memcpy(tkp.blob, p, tkp.blob_len);
+ tko.keyhandle = nullkey;
+ strcpy(tko.blobauth, password);
+
+ rc = tpm2_unseal_trusted(chip, &tkp, &tko);
+ if (rc) {
+ dev_err(&chip->dev, "tpm2_unseal_trusted[password] returned %d\n", rc);
+ goto out;
+ }
+
+ if (tkp.key_len != sizeof(payload)) {
+ dev_err(&chip->dev, "tpm2_unseal_trusted[password] wrong unseal payload size %d != %ld",
+ tkp.key_len, sizeof(payload));
+ goto out;
+ }
+ if (memcmp(payload, tkp.key, tkp.key_len) != 0) {
+ dev_err(&chip->dev, "tpm2_unseal_trusted[password] Payload DID NOT compare correctly\n");
+ goto out;
+ }
+ dev_info(&chip->dev, "tpm2_unseal_trusted[password] returned correct data\n"
+ "test2: PASS\n");
+
+ /*
+ * third test, seal random data protecting sensitive by
+ * encryption and also doing response encryption (not
+ * necessary) The encrypted payload has two components: an
+ * authorization password which must be presented on useal and
+ * the actual data (the random payload)
+ *
+ * For this test use a policy to release the data testing that
+ * we can have two sessions
+ */
+
+ dev_info(&chip->dev, "test 3: seal to policy and test unseal\n");
+ rc = tpm2_get_random(chip, payload, sizeof(payload));
+ if (rc != sizeof(payload)) {
+ dev_err(&chip->dev, "tpm2_get_random failed: %d\n", rc);
+ goto out;
+ }
+
+ /* auth session should be closed, so get a new one */
+ rc = tpm2_start_auth_session(chip, &auth);
+ if (rc) {
+ dev_err(&chip->dev, "new auth session failed: %d\n", rc);
+ goto out;
+ }
+
+ tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE);
+ tpm_buf_append_name(&buf, auth, nullkey, chip->tpmkeyname);
+ tpm_buf_append_hmac_session(&buf, auth, TPM2_SA_DECRYPT
+ | TPM2_SA_ENCRYPT
+ | TPM2_SA_CONTINUE_SESSION, NULL, 0);
+ /* sensitive */
+ tpm_buf_init_2b(&t2b);
+ /* the authorization */
+ tpm_buf_append_u16(&t2b, 0);
+ /* the payload */
+ tpm_buf_append_u16(&t2b, sizeof(payload) + 1);
+ tpm_buf_append(&t2b, payload, sizeof(payload));
+ /* extra byte for migratability flag */
+ tpm_buf_append_u8(&t2b, 0);
+ tpm_buf_append_2b(&buf, &t2b);
+ /* the public */
+ /* type */
+ tpm_buf_append_u16(&t2b, TPM_ALG_KEYEDHASH);
+ /* name hash */
+ tpm_buf_append_u16(&t2b, TPM_ALG_SHA256);
+ /* object properties */
+ tpm_buf_append_u32(&t2b, TPM2_OA_NO_DA);
+ /* auth policy (specific to command code) */
+ tpm_buf_append_u16(&t2b, sizeof(policy));
+ tpm_buf_append(&t2b, policy, sizeof(policy));
+ /* keyed hash parameters (we're null for a non-HMAC data blob) */
+ tpm_buf_append_u16(&t2b, TPM_ALG_NULL);
+ /* unique */
+ tpm_buf_append_u16(&t2b, 0);
+ tpm_buf_append_2b(&buf, &t2b);
+ /* outside info (also empty) */
+ tpm_buf_append_u16(&buf, 0);
+ /* creation PCR (empty) */
+ tpm_buf_append_u32(&buf, 0);
+ tpm_buf_fill_hmac_session(&buf, auth);
+ rc = tpm_transmit_cmd(chip, &buf, 4, "policy sealing data");
+ rc = tpm_buf_check_hmac_response(&buf, auth, rc);
+ dev_info(&chip->dev, "policy sealing response returned %d\n", rc);
+ if (rc)
+ goto out;
+
+ /*
+ * now load the sealed object (we need the pub and priv parts
+ * returned from prior command
+ */
+ memset(&tkp, 0, sizeof(tkp));
+ memset(&tko, 0, sizeof(tko));
+
+ p = &buf.data[TPM_HEADER_SIZE];
+
+ /* now get a policy session */
+ ps = get_policy(chip);
+
+ tkp.blob_len = tpm_get_inc_u32(&p);
+ memcpy(tkp.blob, p, tkp.blob_len);
+ tko.keyhandle = nullkey;
+ tko.policyhandle = ps;
+
+ rc = tpm2_unseal_trusted(chip, &tkp, &tko);
+ if (rc) {
+ dev_err(&chip->dev, "tpm2_unseal_trusted[policy] returned %d\n", rc);
+ tpm2_flush_context(chip, ps);
+ goto out;
+ }
+
+ if (tkp.key_len != sizeof(payload)) {
+ dev_err(&chip->dev, "tpm2_unseal_trusted[policy] wrong unseal payload size %d != %ld",
+ tkp.key_len, sizeof(payload));
+ goto out;
+ }
+ if (memcmp(payload, tkp.key, tkp.key_len) != 0) {
+ dev_err(&chip->dev, "tpm2_unseal_trusted[policy] Payload DID NOT compare correctly\n");
+ goto out;
+ }
+ dev_info(&chip->dev, "tpm2_unseal_trusted[policy] returned correct data\n"
+ "test3: PASS\n");
+
+ /*
+ * test4: get the TPM routines to seal to a password and then
+ * do a manual unseal
+ */
+
+ dev_info(&chip->dev, "test4: seal using tpm2-cmd[password] and unseal manually\n");
+
+ memset(&tkp, 0, sizeof(tkp));
+ memset(&tko, 0, sizeof(tko));
+
+ tko.keyhandle = nullkey;
+ tko.hash = HASH_ALGO_SHA256;
+ tkp.key_len = sizeof(payload);
+ memcpy(tkp.key, payload, tkp.key_len);
+ strcpy(tko.blobauth, password);
+
+ rc = tpm2_seal_trusted(chip, &tkp, &tko);
+ if (rc) {
+ dev_err(&chip->dev, "tpm2_seal_trusted returned error: %d\n ", rc);
+ goto out;
+ }
+
+ /*
+ * now load the sealed object (we need the pub and priv parts
+ * returned from prior command. The blob from
+ * tpm2_seal_trusted is the entire return from the create, so
+ * only append the private and public parts
+ */
+ p = tkp.blob;
+ /* private len */
+ len = tpm_get_inc_u16(&p);
+ p += len;
+ /* add public len */
+ len += tpm_get_inc_u16(&p);
+ /* add 4 for the two length values */
+ len += 4;
+
+ tpm_buf_init(&b1, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+ /* parent */
+ tpm_buf_append_name(&b1, auth, nullkey, chip->tpmkeyname);
+ tpm_buf_append_hmac_session(&b1, auth, TPM2_SA_CONTINUE_SESSION,
+ NULL, 0);
+
+ tpm_buf_append(&b1, tkp.blob, len);
+
+ tpm_buf_fill_hmac_session(&b1, auth);
+ rc = tpm_transmit_cmd(chip, &b1, 4, "loading seal");
+ rc = tpm_buf_check_hmac_response(&b1, auth, rc);
+ dev_info(&chip->dev, "TPM: load response returned %d\n", rc);
+ if (rc)
+ goto out;
+ p = &b1.data[TPM_HEADER_SIZE];
+ h = tpm_get_inc_u32(&p);
+ dev_info(&chip->dev, "sealed data loaded at %08x\n", h);
+ /* skip over parameter size */
+ p += 4;
+ len = tpm_get_inc_u16(&p);
+ if (len != sizeof(name)) {
+ dev_err(&chip->dev, "Wrong name size %d\n", len);
+ goto out;
+ }
+ memcpy(name, p, len);
+ tpm_buf_destroy(&b1);
+ tpm_buf_destroy(&buf);
+
+ /*
+ * now unseal the data using the authority in a HMAC and
+ * protecting the returned unseal by encryption
+ */
+ tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+ tpm_buf_append_name(&buf, auth, h, name);
+ tpm_buf_append_hmac_session(&buf, auth,
+ TPM2_SA_ENCRYPT | TPM2_SA_CONTINUE_SESSION,
+ password, strlen(password));
+ tpm_buf_fill_hmac_session(&buf, auth);
+ rc = tpm_transmit_cmd(chip, &buf, 4, "unseal");
+ rc = tpm_buf_check_hmac_response(&buf, auth, rc);
+ tpm2_flush_context(chip, h);
+ dev_info(&chip->dev, "unseal returns %d\n", rc);
+ if (rc)
+ goto out;
+ p = &buf.data[TPM_HEADER_SIZE + 4];
+ len = tpm_get_inc_u16(&p);
+ if (len != sizeof(payload) + 1) {
+ dev_err(&chip->dev, "wrong unseal payload size %d != %ld",
+ len, sizeof(payload) + 1);
+ goto out;
+ }
+ if (memcmp(payload, p, sizeof(payload)) != 0) {
+ dev_err(&chip->dev, "Payload DID NOT compare correctly\n");
+ goto out;
+ }
+
+ dev_info(&chip->dev, "test4: PASS\n");
+
+ /*
+ * test5: get the TPM routines to seal to a policy and then
+ * do a manual unseal
+ */
+
+ dev_info(&chip->dev, "test5: seal using tpm2-cmd[policy] and unseal manually\n");
+
+ memset(&tkp, 0, sizeof(tkp));
+ memset(&tko, 0, sizeof(tko));
+
+ tko.keyhandle = nullkey;
+ tko.hash = HASH_ALGO_SHA256;
+ tkp.key_len = sizeof(payload);
+ memcpy(tkp.key, payload, tkp.key_len);
+ tko.policydigest_len = sizeof(policy);
+ memcpy(tko.policydigest, policy, tko.policydigest_len);
+
+ rc = tpm2_seal_trusted(chip, &tkp, &tko);
+ if (rc) {
+ dev_err(&chip->dev, "tpm2_seal_trusted returned error: %d\n ", rc);
+ goto out;
+ }
+
+ ps = get_policy(chip);
+ /*
+ * now load the sealed object (we need the pub and priv parts
+ * returned from prior command. The blob from
+ * tpm2_seal_trusted is the entire return from the create, so
+ * only append the private and public parts
+ */
+ p = tkp.blob;
+ /* private len */
+ len = tpm_get_inc_u16(&p);
+ p += len;
+ /* add public len */
+ len += tpm_get_inc_u16(&p);
+ /* add 4 for the two length values */
+ len += 4;
+
+ tpm_buf_init(&b1, TPM2_ST_SESSIONS, TPM2_CC_LOAD);
+ /* parent */
+ tpm_buf_append_name(&b1, auth, nullkey, chip->tpmkeyname);
+ tpm_buf_append_hmac_session(&b1, auth, TPM2_SA_CONTINUE_SESSION,
+ NULL, 0);
+
+ tpm_buf_append(&b1, tkp.blob, len);
+
+ tpm_buf_fill_hmac_session(&b1, auth);
+ rc = tpm_transmit_cmd(chip, &b1, 4, "loading seal");
+ rc = tpm_buf_check_hmac_response(&b1, auth, rc);
+ dev_info(&chip->dev, "TPM: load response returned %d\n", rc);
+ if (rc) {
+ tpm2_flush_context(chip, ps);
+ goto out;
+ }
+ p = &b1.data[TPM_HEADER_SIZE];
+ h = tpm_get_inc_u32(&p);
+ dev_info(&chip->dev, "sealed data loaded at %08x\n", h);
+ /* skip over parameter size */
+ p += 4;
+ len = tpm_get_inc_u16(&p);
+ if (len != sizeof(name)) {
+ dev_err(&chip->dev, "Wrong name size %d\n", len);
+ goto out;
+ }
+ memcpy(name, p, len);
+ tpm_buf_destroy(&b1);
+ tpm_buf_destroy(&buf);
+
+ /*
+ * now unseal the data using the authority in a HMAC and
+ * protecting the returned unseal by encryption
+ */
+ tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL);
+ tpm_buf_append_name(&buf, auth, h, name);
+ tpm2_buf_append_auth(&buf, ps, NULL, 0, 0, NULL, 0);
+ tpm_buf_append_hmac_session(&buf, auth, TPM2_SA_ENCRYPT,
+ NULL, 0);
+ tpm_buf_fill_hmac_session(&buf, auth);
+ rc = tpm_transmit_cmd(chip, &buf, 4, "unseal");
+ rc = tpm_buf_check_hmac_response(&buf, auth, rc);
+ tpm2_flush_context(chip, h);
+ dev_info(&chip->dev, "unseal returns %d\n", rc);
+ if (rc)
+ goto out;
+ p = &buf.data[TPM_HEADER_SIZE + 4];
+ len = tpm_get_inc_u16(&p);
+ if (len != sizeof(payload) + 1) {
+ dev_err(&chip->dev, "wrong unseal payload size %d != %ld",
+ len, sizeof(payload) + 1);
+ goto out;
+ }
+ if (memcmp(payload, p, sizeof(payload)) != 0) {
+ dev_err(&chip->dev, "Payload DID NOT compare correctly\n");
+ goto out;
+ }
+
+ dev_info(&chip->dev, "test5: PASS");
+
+ /*
+ * test6: extend PCR 16 with a random value and verify it
+ * comes back correctly
+ */
+
+ dev_info(&chip->dev, "test6: extend PCR 16");
+
+ digest.alg_id = TPM_ALG_SHA256;
+
+ rc = tpm2_pcr_read(chip, 16, &digest, &digest_len);
+ if (rc) {
+ dev_err(&chip->dev, "tpm2_pcr_read returns error: %d\n", rc);
+ goto out;
+ }
+ if (digest_len != SHA256_DIGEST_SIZE) {
+ dev_err(&chip->dev, "wrong digest size %d!=%d\n", digest_len,
+ SHA256_DIGEST_SIZE);
+ goto out;
+ }
+
+ for (i = 0; i < chip->nr_allocated_banks; i++) {
+ rc = tpm2_get_random(chip, extend[i].digest, SHA256_DIGEST_SIZE);
+ if (rc != SHA256_DIGEST_SIZE) {
+ dev_err(&chip->dev, "tpm2_get_random failed: %d\n", rc);
+ goto out;
+ }
+ extend[i].alg_id = chip->allocated_banks[i].alg_id;
+ }
+ rc = tpm2_pcr_extend(chip, 16, extend);
+ if (rc) {
+ dev_err(&chip->dev, "tpm2_pcr_extend failed: %d\n", rc);
+ goto out;
+ }
+
+ desc->tfm = sha256_hash;
+ crypto_shash_init(desc);
+ crypto_shash_update(desc, digest.digest, SHA256_DIGEST_SIZE);
+ crypto_shash_update(desc, extend[0].digest, SHA256_DIGEST_SIZE);
+ crypto_shash_final(desc, digest.digest);
+
+ extend[0].alg_id = TPM_ALG_SHA256;
+ rc = tpm2_pcr_read(chip, 16, &extend[0], &digest_len);
+ if (rc) {
+ dev_err(&chip->dev, "tpm2_pcr_read returns error: %d\n", rc);
+ goto out;
+ }
+ if (digest_len != SHA256_DIGEST_SIZE) {
+ dev_err(&chip->dev, "wrong digest size %d!=%d\n", digest_len,
+ SHA256_DIGEST_SIZE);
+ goto out;
+ }
+
+ if (memcmp(digest.digest, extend[0].digest, SHA256_DIGEST_SIZE) != 0) {
+ dev_err(&chip->dev, "Extend digest comparison failed\n");
+ goto out;
+ }
+
+ dev_info(&chip->dev, "All tests passed\n");
+ ret = 0;
+
+ out:
+ tpm2_flush_context(chip, nullkey);
+
+ tpm_put_ops(chip);
+
+ return ret;
+}
+
+module_init(tpm2_sessions_test);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c
index 7307f061e5df..8f50ad88c5ab 100644
--- a/drivers/char/tpm/tpm2-sessions.c
+++ b/drivers/char/tpm/tpm2-sessions.c
@@ -865,6 +865,7 @@ static int parse_start_auth_session(struct tpm2_auth *auth, const u8 *data)
* tpm2_start_auth_session - create a HMAC authentication session with the TPM
* @chip: the TPM chip structure to create the session with
* @authp: A pointer to an opaque tpm2_auth structure to be allocated
+ * @key: A pointer to return the NULL key or NULL if key should be flushed
*
* This function loads the NULL seed from its saved context and starts
* an authentication session on the null seed, allocates a tpm2_auth
diff --git a/drivers/char/tpm/tpm2-sessions.h b/drivers/char/tpm/tpm2-sessions.h
index ec245731edaf..23d62446dd71 100644
--- a/drivers/char/tpm/tpm2-sessions.h
+++ b/drivers/char/tpm/tpm2-sessions.h
@@ -45,7 +45,8 @@ void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle,
#ifdef CONFIG_TPM_BUS_SECURITY
-int tpm2_start_auth_session(struct tpm_chip *chip, struct tpm2_auth **authp);
+int tpm2_start_auth_session(struct tpm_chip *chip,
+ struct tpm2_auth **authp);
void tpm_buf_append_name(struct tpm_buf *buf, struct tpm2_auth *auth,
u32 handle, u8 *name);
void tpm_buf_append_hmac_session(struct tpm_buf *buf, struct tpm2_auth *auth,
--
2.16.4
It's very convenient when parsing responses to have a cursor you
simply move over the response extracting the data. Add such cursor
functions for the TPM unsigned integer types.
Signed-off-by: James Bottomley <[email protected]>
---
drivers/char/tpm/tpm-buf.c | 26 ++++++++++++++++++++++++++
drivers/char/tpm/tpm.h | 4 ++++
2 files changed, 30 insertions(+)
diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c
index 8c1ed8a14e01..553adb84b0ac 100644
--- a/drivers/char/tpm/tpm-buf.c
+++ b/drivers/char/tpm/tpm-buf.c
@@ -163,3 +163,29 @@ void tpm_buf_append_2b(struct tpm_buf *buf, struct tpm_buf *tpm2b)
}
EXPORT_SYMBOL_GPL(tpm_buf_append_2b);
+/* functions for unmarshalling data and moving the cursor */
+u8 tpm_get_inc_u8(const u8 **ptr)
+{
+ return *((*ptr)++);
+}
+EXPORT_SYMBOL_GPL(tpm_get_inc_u8);
+
+u16 tpm_get_inc_u16(const u8 **ptr)
+{
+ u16 val;
+
+ val = get_unaligned_be16(*ptr);
+ *ptr += sizeof(val);
+ return val;
+}
+EXPORT_SYMBOL_GPL(tpm_get_inc_u16);
+
+u32 tpm_get_inc_u32(const u8 **ptr)
+{
+ u32 val;
+
+ val = get_unaligned_be32(*ptr);
+ *ptr += sizeof(val);
+ return val;
+}
+EXPORT_SYMBOL_GPL(tpm_get_inc_u32);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 7627917db345..d942188debc9 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -302,6 +302,10 @@ void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value);
void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value);
void tpm_buf_append_2b(struct tpm_buf *buf, struct tpm_buf *tpm2b);
+u8 tpm_get_inc_u8(const u8 **ptr);
+u16 tpm_get_inc_u16(const u8 **ptr);
+u32 tpm_get_inc_u32(const u8 **ptr);
+
extern struct class *tpm_class;
extern struct class *tpmrm_class;
extern dev_t tpm_devt;
--
2.16.4
If some entity is snooping the TPM bus, they can see the random
numbers we're extracting from the TPM and do prediction attacks
against their consumers. Foil this attack by using response
encryption to prevent the attacker from seeing the random sequence.
Signed-off-by: James Bottomley <[email protected]>
---
v3: add error handling to sessions and redo to be outside loop
---
drivers/char/tpm/tpm2-cmd.c | 21 +++++++++++++++++----
1 file changed, 17 insertions(+), 4 deletions(-)
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 0012657d3617..572d05966b77 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -296,29 +296,40 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
int total = 0;
int retries = 5;
u8 *dest_ptr = dest;
+ struct tpm2_auth *auth;
if (!num_bytes || max > TPM_MAX_RNG_DATA)
return -EINVAL;
- err = tpm_buf_init(&buf, 0, 0);
+ err = tpm2_start_auth_session(chip, &auth);
if (err)
return err;
+ err = tpm_buf_init(&buf, 0, 0);
+ if (err) {
+ tpm2_end_auth_session(auth);
+ return err;
+ }
+
do {
- tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM);
+ tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM);
+ tpm_buf_append_hmac_session_opt(&buf, auth, TPM2_SA_ENCRYPT
+ | TPM2_SA_CONTINUE_SESSION,
+ NULL, 0);
tpm_buf_append_u16(&buf, num_bytes);
+ tpm_buf_fill_hmac_session(&buf, auth);
err = tpm_transmit_cmd(chip, &buf,
offsetof(struct tpm2_get_random_out,
buffer),
"attempting get random");
+ err = tpm_buf_check_hmac_response(&buf, auth, err);
if (err) {
if (err > 0)
err = -EIO;
goto out;
}
- out = (struct tpm2_get_random_out *)
- &buf.data[TPM_HEADER_SIZE];
+ out = (struct tpm2_get_random_out *)tpm_buf_parameters(&buf);
recd = min_t(u32, be16_to_cpu(out->size), num_bytes);
if (tpm_buf_length(&buf) <
TPM_HEADER_SIZE +
@@ -335,6 +346,8 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
} while (retries-- && total < max);
tpm_buf_destroy(&buf);
+ tpm2_end_auth_session(auth);
+
return total ? total : -EIO;
out:
tpm_buf_destroy(&buf);
--
2.16.4
On Mon, Sep 09, 2019 at 01:16:48PM +0100, James Bottomley wrote:
> Link to previous cover letter:
>
> https://lore.kernel.org/linux-integrity/[email protected]/
>
> This is marked v6 instead of v5 because I did a v5 after feedback on v4
> but didn't get around to posting it and then had to rework the whole of
> the kernel space handling while I was on holiday. I also added the
> documentation of how the whole thing works and the rationale for doing
> it in tpm-security.rst (patch 11). The main reason for doing this now
> is so we have something to discuss at Plumbers.
>
> The new patch set implements the various splits requested, but the main
> changes are that the kernel space is gone and is replaced by a context
> save and restore of the generated null seed. This is easier to handle
> than a full kernel space given the new threading for TPM spaces, but
> conceptually it is still very like a space. I've also made whether
> integrity and encryption is turned on a Kconfig option.
>
> James
So... is there a changelog for the revisions?
/Jarkko
On Tue, 2019-09-10 at 17:21 +0100, Jarkko Sakkinen wrote:
> On Mon, Sep 09, 2019 at 01:16:48PM +0100, James Bottomley wrote:
> > Link to previous cover letter:
> >
> > https://lore.kernel.org/linux-integrity/1540193596.3202.7.camel@Han
> > senPartnership.com/
> >
> > This is marked v6 instead of v5 because I did a v5 after feedback
> > on v4
> > but didn't get around to posting it and then had to rework the
> > whole of
> > the kernel space handling while I was on holiday. I also added the
> > documentation of how the whole thing works and the rationale for
> > doing
> > it in tpm-security.rst (patch 11). The main reason for doing this
> > now
> > is so we have something to discuss at Plumbers.
> >
> > The new patch set implements the various splits requested, but the
> > main
> > changes are that the kernel space is gone and is replaced by a
> > context
> > save and restore of the generated null seed. This is easier to
> > handle
> > than a full kernel space given the new threading for TPM spaces,
> > but
> > conceptually it is still very like a space. I've also made whether
> > integrity and encryption is turned on a Kconfig option.
> >
> > James
>
> So... is there a changelog for the revisions?
Well, yes, standard way: they're in the individual patches under the '-
--' prefixed with v6:
James
On Tue, Sep 10, 2019 at 05:21:32PM +0100, Jarkko Sakkinen wrote:
> On Mon, Sep 09, 2019 at 01:16:48PM +0100, James Bottomley wrote:
> > Link to previous cover letter:
> >
> > https://lore.kernel.org/linux-integrity/[email protected]/
> >
> > This is marked v6 instead of v5 because I did a v5 after feedback on v4
> > but didn't get around to posting it and then had to rework the whole of
> > the kernel space handling while I was on holiday. I also added the
> > documentation of how the whole thing works and the rationale for doing
> > it in tpm-security.rst (patch 11). The main reason for doing this now
> > is so we have something to discuss at Plumbers.
> >
> > The new patch set implements the various splits requested, but the main
> > changes are that the kernel space is gone and is replaced by a context
> > save and restore of the generated null seed. This is easier to handle
> > than a full kernel space given the new threading for TPM spaces, but
> > conceptually it is still very like a space. I've also made whether
> > integrity and encryption is turned on a Kconfig option.
> >
> > James
>
> So... is there a changelog for the revisions?
This also desperately needs a cover letter with the full rationale and
not just a link to an aged cover letter. I have bigger problems with the
form than the function ATM.
TPM's threat model does not cover hardware attacks. It is hardware
designed to give some protection against software attacks. If I were
sending these patches I would start to look for an angle from that
perspective.
/Jarkko
On Wed, Sep 11, 2019 at 09:42:49AM +0100, Jarkko Sakkinen wrote:
> On Tue, Sep 10, 2019 at 05:21:32PM +0100, Jarkko Sakkinen wrote:
> > On Mon, Sep 09, 2019 at 01:16:48PM +0100, James Bottomley wrote:
> > > Link to previous cover letter:
> > >
> > > https://lore.kernel.org/linux-integrity/[email protected]/
> > >
> > > This is marked v6 instead of v5 because I did a v5 after feedback on v4
> > > but didn't get around to posting it and then had to rework the whole of
> > > the kernel space handling while I was on holiday. I also added the
> > > documentation of how the whole thing works and the rationale for doing
> > > it in tpm-security.rst (patch 11). The main reason for doing this now
> > > is so we have something to discuss at Plumbers.
> > >
> > > The new patch set implements the various splits requested, but the main
> > > changes are that the kernel space is gone and is replaced by a context
> > > save and restore of the generated null seed. This is easier to handle
> > > than a full kernel space given the new threading for TPM spaces, but
> > > conceptually it is still very like a space. I've also made whether
> > > integrity and encryption is turned on a Kconfig option.
> > >
> > > James
> >
> > So... is there a changelog for the revisions?
>
> This also desperately needs a cover letter with the full rationale and
> not just a link to an aged cover letter. I have bigger problems with the
> form than the function ATM.
>
> TPM's threat model does not cover hardware attacks. It is hardware
> designed to give some protection against software attacks. If I were
> sending these patches I would start to look for an angle from that
> perspective.
The rationale can be essentially just that since there is often lots of
*software* running outside the CPU on different cores all around the HW
platform, this will add to defense in depth. I'm not looking for
anything more rockety sciency than that.
I think that was the key lesson from TPM Genie.
/Jarkko