All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC] tpm2-space: add handling for global session exhaustion
@ 2017-01-18 20:48 ` James Bottomley
  0 siblings, 0 replies; 53+ messages in thread
From: James Bottomley @ 2017-01-18 20:48 UTC (permalink / raw)
  To: tpmdd-devel; +Cc: linux-security-module, open list

In a TPM2, sessions can be globally exhausted once there are
TPM_PT_ACTIVE_SESSION_MAX of them (even if they're all context saved).
The Strategy for handling this is to keep a global count of all the
sessions along with their creation time.  Then if we see the TPM run
out of sessions (via the TPM_RC_SESSION_HANDLES) we first wait for one
to become free, but if it doesn't, we forcibly evict an existing one.
The eviction strategy waits until the current command is repeated to
evict the session which should guarantee there is an available slot.

On the force eviction case, we make sure that the victim session is at
least SESSION_TIMEOUT old (currently 2 seconds).  The wait queue for
session slots is a FIFO one, ensuring that once we run out of
sessions, everyone will get a session in a bounded time and once they
get one, they'll have SESSION_TIMEOUT to use it before it may be
subject to eviction.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index a625884..c959b09 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -164,6 +164,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
 
 	mutex_init(&chip->tpm_mutex);
 	init_rwsem(&chip->ops_sem);
+	init_waitqueue_head(&chip->session_wait);
 
 	chip->ops = ops;
 
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 9923daa..38cc21c 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -95,6 +95,7 @@ enum tpm2_return_codes {
 	TPM2_RC_HANDLE		= 0x008B,
 	TPM2_RC_INITIALIZE	= 0x0100, /* RC_VER1 */
 	TPM2_RC_DISABLED	= 0x0120,
+	TPM2_RC_SESSION_HANDLES	= 0x0905,
 	TPM2_RC_TESTING		= 0x090A, /* RC_WARN */
 };
 
@@ -136,7 +137,8 @@ enum tpm2_capabilities {
 };
 
 enum tpm2_properties {
-	TPM_PT_TOTAL_COMMANDS	= 0x0129,
+	TPM_PT_TOTAL_COMMANDS		= 0x0129,
+	TPM_PT_ACTIVE_SESSIONS_MAX	= 0x0111,
 };
 
 enum tpm2_startup_types {
@@ -160,8 +162,24 @@ struct tpm_space {
 	u8 *context_buf;
 	u32 session_tbl[6];
 	u8 *session_buf;
+	u32 reserved_handle;
 };
 
+#define TPM2_HANDLE_FORCE_EVICT 0xFFFFFFFF
+
+static inline void tpm2_session_force_evict(struct tpm_space *space)
+{
+	/* if reserved handle is not empty, we already have a
+	 * session for eviction, so no need to force one
+	 */
+	if (space->reserved_handle == 0)
+		space->reserved_handle = TPM2_HANDLE_FORCE_EVICT;
+}
+static inline bool tpm2_is_session_force_evict(struct tpm_space *space)
+{
+	return space->reserved_handle == TPM2_HANDLE_FORCE_EVICT;
+}
+
 enum tpm_chip_flags {
 	TPM_CHIP_FLAG_TPM2		= BIT(1),
 	TPM_CHIP_FLAG_IRQ		= BIT(2),
@@ -174,6 +192,12 @@ struct tpm_chip_seqops {
 	const struct seq_operations *seqops;
 };
 
+struct tpm_sessions {
+	struct tpm_space *space;
+	u32 handle;
+	unsigned long created;
+};
+
 struct tpm_chip {
 	struct device dev, devrm;
 	struct cdev cdev, cdevrm;
@@ -214,8 +238,12 @@ struct tpm_chip {
 #endif /* CONFIG_ACPI */
 
 	struct tpm_space work_space;
+	struct tpm_space *space;
 	u32 nr_commands;
 	u32 *cc_attrs_tbl;
+	struct tpm_sessions *sessions;
+	int max_sessions;
+	wait_queue_head_t session_wait;
 };
 
 #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
@@ -568,6 +596,13 @@ 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);
 void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
 			    unsigned int flags);
+static inline void tpm2_session_clear_reserved(struct tpm_chip *chip,
+					       struct tpm_space *space)
+{
+	if (space->reserved_handle && !tpm2_is_session_force_evict(space))
+		tpm2_flush_context_cmd(chip, space->reserved_handle, 0);
+	space->reserved_handle = 0;
+}
 int tpm2_seal_trusted(struct tpm_chip *chip,
 		      struct trusted_key_payload *payload,
 		      struct trusted_key_options *options);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index e1c1bbd..ac5c0a2 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -1007,6 +1007,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 {
 	struct tpm_buf buf;
 	u32 nr_commands;
+	u32 nr_sessions;
 	int rc;
 	int i;
 
@@ -1067,6 +1068,20 @@ int tpm2_auto_startup(struct tpm_chip *chip)
 	chip->nr_commands = nr_commands;
 	tpm_buf_destroy(&buf);
 
+	rc = tpm2_get_tpm_pt(chip, TPM_PT_ACTIVE_SESSIONS_MAX,
+			     &nr_sessions, NULL);
+	if (rc)
+		goto out;
+
+	if (nr_sessions > 256)
+		nr_sessions = 256;
+
+	chip->max_sessions = nr_sessions;
+	chip->sessions = devm_kzalloc(&chip->dev,
+				      nr_sessions * sizeof(*chip->sessions),
+				      GFP_KERNEL);
+	if (!chip->sessions)
+		rc = -ENOMEM;
 out:
 	if (rc > 0)
 		rc = -ENODEV;
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index 04c9431..42c8c84 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -34,6 +34,169 @@ struct tpm2_context {
 	__be16 blob_size;
 } __packed;
 
+static struct tpm_sessions *tpm2_session_chip_get(struct tpm_chip *chip)
+{
+	int i;
+
+	for (i = 0; i < chip->max_sessions; i++)
+		if (chip->sessions[i].space == NULL)
+			return &chip->sessions[i];
+
+	return NULL;
+}
+
+static struct tpm_sessions *tpm2_session_chip_find_oldest(struct tpm_chip *chip)
+{
+	struct tpm_sessions *sess = NULL;
+	int i;
+
+	for (i = 0; i < chip->max_sessions; i++) {
+		if (chip->sessions[i].space == NULL)
+			continue;
+
+		if (!sess || time_after(sess->created,
+					chip->sessions[i].created))
+			sess = &chip->sessions[i];
+	}
+
+	return sess;
+}
+
+static void tpm2_session_chip_add(struct tpm_chip *chip,
+				  struct tpm_space *space, u32 h)
+{
+	struct tpm_sessions *sess = tpm2_session_chip_get(chip);
+
+	sess->space = space;
+	sess->handle = h;
+	sess->created = jiffies;
+	dev_info(&chip->dev, "Added Session at %ld, handle %08x", sess - chip->sessions, h);
+}
+
+static void tpm2_session_chip_remove(struct tpm_chip *chip, u32 h)
+{
+	int i;
+
+	for (i = 0; i < chip->max_sessions; i++)
+		if (chip->sessions[i].handle == h)
+			break;
+	if (i == chip->max_sessions) {
+		dev_warn(&chip->dev, "Missing session %08x", h);
+		return;
+	}
+
+	memset(&chip->sessions[i], 0, sizeof(chip->sessions[i]));
+	dev_info(&chip->dev, "Removed session at %d\n", i);
+	wake_up(&chip->session_wait);
+}
+
+static int tpm2_session_forget(struct tpm_chip *chip, struct tpm_space *space,
+			       u32 handle)
+{
+	int i, j;
+	struct tpm2_context *ctx;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(space->session_tbl); i++) {
+		if (space->session_tbl[i] == 0)
+			continue;
+
+		ctx = (struct tpm2_context *)&space->session_buf[j];
+		j += sizeof(*ctx) + get_unaligned_be16(&ctx->blob_size);
+
+		if (space->session_tbl[i] != handle)
+			continue;
+
+		/* forget the session context */
+		memcpy(ctx, &space->session_buf[j], PAGE_SIZE - j);
+		tpm2_session_chip_remove(chip, handle);
+		space->session_tbl[i] = 0;
+		break;
+	}
+	if (i == ARRAY_SIZE(space->session_tbl))
+		return -EINVAL;
+	return 0;
+}
+
+static int tpm2_session_wait(struct tpm_chip *chip, struct tpm_space *space)
+{
+	int rc, failed;
+	struct tpm_sessions *sess;
+	const unsigned long min_timeout = msecs_to_jiffies(2000);
+	unsigned long timeout = min_timeout;
+	DEFINE_WAIT(wait);
+
+	for (failed = 0; ; ) {
+		prepare_to_wait(&chip->session_wait, &wait, TASK_INTERRUPTIBLE);
+
+		mutex_unlock(&chip->tpm_mutex);
+		rc = schedule_timeout_interruptible(timeout);
+		mutex_lock(&chip->tpm_mutex);
+
+		finish_wait(&chip->session_wait, &wait);
+
+		if (signal_pending(current))
+			/* got interrupted */
+			return -EINTR;
+
+		if (rc > 0 && !tpm2_is_session_force_evict(space))
+			/* got woken, so slot is free.  We don't
+			 * reserve the slot here because a) we can't
+			 * (no pending session in the TPM to evict)
+			 * and b) no-one is hogging sessions, so no
+			 * evidence of need.
+			 */
+			return 0;
+
+		/* timed out or victim required; select a victim
+		 * session to kill
+		 */
+		sess = tpm2_session_chip_find_oldest(chip);
+		if (sess == NULL) {
+			/* we get here when we can't create a session
+			 * but there are no listed active sessions
+			 * meaning they're all in various space
+			 * structures as victim sessions.  The wait
+			 * queue is a fair sequence, so we need to
+			 * wait a bit harder
+			 */
+			if (failed++ > 3)
+				break;
+			timeout *= 2;
+			dev_info(&chip->dev, "failed to get session, waiting for %us\n", jiffies_to_msecs(timeout)/1000);
+			continue;
+		}
+		/* is the victim old enough? */
+		timeout = jiffies - sess->created;
+		if (timeout > min_timeout)
+			break;
+		/* otherwise wait until the victim is old enough */
+		timeout = min_timeout - timeout;
+	}
+	if (sess == NULL)
+		/* still can't get a victim, give up */
+		return -EINVAL;
+
+	/* store the physical handle */
+	space->reserved_handle = sess->handle;
+	dev_info(&chip->dev, "Selecting handle %08x for eviction\n",
+		 space->reserved_handle);
+
+	/* cause a mapping failure if this session handle is
+	 * ever used in the victim space again
+	 */
+	tpm2_session_forget(chip, sess->space, sess->handle);
+	/* clear the session, but don't wake any other waiters */
+	memset(sess, 0, sizeof(*sess));
+	/* so now we have a saved physical handle but this handle is
+	 * still in the tpm.  After this we repeat the command, but
+	 * flush the handle once we obtain the tpm_mutex on the repeat
+	 * so, in theory, we should have a free handle to
+	 * re-execute
+	 */
+
+	return 0;
+}
+
 static int tpm2_context_save(struct tpm_chip *chip, u8 *area,
 			     int *offset, u32 handle)
 {
@@ -124,9 +287,9 @@ static int tpm2_session_find(struct tpm_space *space, u32 handle)
 	return i;
 }
 
-static int tpm2_session_add(struct tpm_chip *chip,
-			    struct tpm_space *space, u32 handle)
+static int tpm2_session_add(struct tpm_chip *chip, u32 handle)
 {
+	struct tpm_space *space = &chip->work_space;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++)
@@ -139,35 +302,11 @@ static int tpm2_session_add(struct tpm_chip *chip,
 	}
 
 	space->session_tbl[i] = handle;
+	tpm2_session_chip_add(chip, chip->space, handle);
 
 	return 0;
 }
 
-static int tpm2_session_forget(struct tpm_space *space, u32 handle)
-{
-	int i, j;
-	struct tpm2_context *ctx;
-
-	for (i = 0, j = 0; i < ARRAY_SIZE(space->session_tbl); i++) {
-		if (space->session_tbl[i] == 0)
-			continue;
-
-		ctx = (struct tpm2_context *)&space->session_buf[j];
-		j += sizeof(*ctx) + get_unaligned_be16(&ctx->blob_size);
-
-		if (space->session_tbl[i] != handle)
-			continue;
-
-		/* forget the session context */
-		memcpy(ctx, &space->session_buf[j], PAGE_SIZE - j);
-		space->session_tbl[i] = 0;
-		break;
-	}
-	if (i == ARRAY_SIZE(space->session_tbl))
-		return -EINVAL;
-	return 0;
-}
-
 /* if a space is active, emulate some commands */
 static int tpm2_intercept(struct tpm_chip *chip, u32 cc, u8 *buf, size_t bufsiz)
 {
@@ -187,7 +326,7 @@ static int tpm2_intercept(struct tpm_chip *chip, u32 cc, u8 *buf, size_t bufsiz)
 		/* let the TPM figure out and return the error */
 		return 0;
 
-	return tpm2_session_forget(space, handle);
+	return tpm2_session_forget(chip, space, handle);
 }
 
 void tpm2_flush_space(struct tpm_chip *chip, struct tpm_space *space)
@@ -200,10 +339,19 @@ void tpm2_flush_space(struct tpm_chip *chip, struct tpm_space *space)
 					       TPM_TRANSMIT_UNLOCKED);
 
 	for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) {
+		if (!space->session_tbl[i])
+			continue;
+
 		space->session_tbl[i] &= ~TPM2_HT_TAG_FOR_FLUSH;
-		if (space->session_tbl[i])
-			tpm2_flush_context_cmd(chip, space->session_tbl[i],
-					       TPM_TRANSMIT_UNLOCKED);
+		tpm2_session_chip_remove(chip, space->session_tbl[i]);
+		tpm2_flush_context_cmd(chip, space->session_tbl[i],
+				       TPM_TRANSMIT_UNLOCKED);
+	}
+	if (space->reserved_handle && !tpm2_is_session_force_evict(space)) {
+		tpm2_flush_context_cmd(chip, space->reserved_handle,
+				       TPM_TRANSMIT_UNLOCKED);
+		space->reserved_handle = 0;
+		/* subtlety here: if force evict is set, we don't clear it */
 	}
 }
 
@@ -264,11 +412,13 @@ static void tpm2_unmap_sessions(struct tpm_chip *chip, u32 rc)
 		if ((space->session_tbl[i] & TPM2_HT_TAG_FOR_FLUSH) !=
 		    TPM2_HT_TAG_FOR_FLUSH)
 			continue;
-		if (rc == TPM2_RC_SUCCESS)
+
+		/* for unsuccessful command, keep session */
+		space->session_tbl[i] &= ~TPM2_HT_TAG_FOR_FLUSH;
+		if (rc == TPM2_RC_SUCCESS) {
+			tpm2_session_chip_remove(chip, space->session_tbl[i]);
 			space->session_tbl[i] = 0;
-		else
-			/* for unsuccessful command, keep session */
-			space->session_tbl[i] &= ~TPM2_HT_TAG_FOR_FLUSH;
+		}
 	}
 }
 
@@ -387,6 +537,7 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space,
 	       sizeof(space->session_tbl));
 	memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
 	memcpy(chip->work_space.session_buf, space->session_buf, PAGE_SIZE);
+	chip->space = space;
 
 	rc = tpm2_intercept(chip, cc, buf, bufsiz);
 	if (rc)
@@ -400,16 +551,28 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space,
 	if (rc)
 		return rc;
 
+	if (space->reserved_handle && !tpm2_is_session_force_evict(space)) {
+		/* this is a trick to allow a previous command which
+		 * failed because it was out of handle space to
+		 * succeed.  The handle is still in the TPM, so now we
+		 * flush it under the tpm_mutex which should ensure we
+		 * can create a new one
+		 */
+		tpm2_flush_context_cmd(chip, space->reserved_handle,
+				       TPM_TRANSMIT_UNLOCKED);
+		space->reserved_handle = 0;
+	}
+
 	return 0;
 }
 
-static int tpm2_map_response(struct tpm_chip *chip, u32 cc, u8 *rsp, size_t len)
+static int tpm2_map_response(struct tpm_chip *chip, u32 cc, u8 *rsp, size_t len,
+			     u32 return_code)
 {
 	struct tpm_space *space = &chip->work_space;
 	u32 phandle, phandle_type;
 	u32 vhandle;
 	u32 attrs;
-	u32 return_code = get_unaligned_be32((__be32 *)&rsp[6]);
 	u16 tag = get_unaligned_be16((__be16 *)rsp);
 	int i;
 	int rc;
@@ -439,7 +602,7 @@ static int tpm2_map_response(struct tpm_chip *chip, u32 cc, u8 *rsp, size_t len)
 		return 0;
 
 	if (phandle_type != TPM2_HT_TRANSIENT)
-		return tpm2_session_add(chip, space, phandle);
+		return tpm2_session_add(chip, phandle);
 
 	/* Garbage collect a dead context. */
 	for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
@@ -521,11 +684,12 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
 		      u32 cc, u8 *buf, size_t bufsiz)
 {
 	int rc;
+	u32 return_code = get_unaligned_be32((__be32 *)&buf[6]);
 
 	if (!space)
 		return 0;
 
-	rc = tpm2_map_response(chip, cc, buf, bufsiz);
+	rc = tpm2_map_response(chip, cc, buf, bufsiz, return_code);
 	if (rc)
 		return rc;
 
@@ -539,6 +703,12 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
 	       sizeof(space->session_tbl));
 	memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
 	memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE);
+	chip->space = NULL;
+
+	if (return_code == TPM2_RC_SESSION_HANDLES) {
+		tpm2_session_wait(chip, space);
+		return -EAGAIN;
+	}
 
 	return 0;
 }
diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
index 12b6e34..b13b000 100644
--- a/drivers/char/tpm/tpms-dev.c
+++ b/drivers/char/tpm/tpms-dev.c
@@ -56,8 +56,23 @@ ssize_t tpms_write(struct file *file, const char __user *buf,
 {
 	struct file_priv *fpriv = file->private_data;
 	struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
+	int count = 0;
+	const int max_count = 3; /* number of retries */
+	int rc;
 
-	return tpm_common_write(file, buf, size, off, &priv->space);
+	for (count = 0; count < max_count; count++) {
+		rc = tpm_common_write(file, buf, size, off, &priv->space);
+		if (rc != -EAGAIN)
+			break;
+		if (count == max_count - 2)
+			/* second to last go around, force an eviction if
+			 * this go fails, so final go should succeed
+			 */
+			tpm2_session_force_evict(&priv->space);
+	}
+	tpm2_session_clear_reserved(fpriv->chip, &priv->space);
+
+	return rc;
 }
 
 const struct file_operations tpm_rm_fops = {

^ permalink raw reply related	[flat|nested] 53+ messages in thread
* Re: [tpmdd-devel] [RFC] tpm2-space: add handling for global session exhaustion
@ 2017-02-09  9:06 Dr. Greg Wettstein
  2017-02-09 15:19 ` Jarkko Sakkinen
                   ` (2 more replies)
  0 siblings, 3 replies; 53+ messages in thread
From: Dr. Greg Wettstein @ 2017-02-09  9:06 UTC (permalink / raw)
  To: Jarkko Sakkinen, James Bottomley
  Cc: Ken Goldman, tpmdd-devel, linux-security-module, linux-kernel

On Jan 30, 11:58pm, Jarkko Sakkinen wrote:
} Subject: Re: [tpmdd-devel] [RFC] tpm2-space: add handling for global sessi

Good morning, I hope the day is going well for everyone.

> I'm kind dilating to an opinion that we would leave this commit out
> from the first kernel release that will contain the resource manager
> with similar rationale as Jason gave me for whitelisting: get the
> basic stuff in and once it is used with some workloads whitelisting
> and exhaustion will take eventually the right form.
>
> How would you feel about this?

I wasn't able to locate the exact context to include but we noted with
interest Ken's comments about his need to support a model where a
client needs a TPM session for transaction purposes which can last a
highly variable amount of time.  That and concerns about command
white-listing, hardware denial of service and related issues tend to
underscore our concerns about how much TPM resource management should
go into the kernel.

Once an API is in the kernel we live with it forever.  Particularly
with respect to TPM2, our field experiences suggest it is way too
early to bake long term functionality into the kernel.

Referring back to Ken's comments about having 20+ clients waiting to
get access to the hardware.  Even with the focus in TPM2 on having it
be more of a cryptographic accelerator are we convinced that the
hardware is ever going to be fast enough for a model of having it
directly service large numbers of transactions in something like a
'cloud' model?

The industry has very solid userspace implementations of TPM2.  It
seems that with respect to resource management about all we would want
in the kernel is enough management to allow multiple privileged
userspace process to establish a root of trust for a TPM2 based
userspace instance with subsequent relinquishment of privilege.  At
that point one has the freedom to implement all sorts of policy.

Given the potential lifespan of these security technologies I think a
kernel design needs to factor in the availability of trusted execution
environment's such as SGX as well.  Politics aside, such environments
do have the ability to significantly modify the guarantees which can
be afforded to architectural models which focus on using the hardware
TPM as a root of trust for userspace implementations of 'TPM'
functionality and policy.

We can always add functionality to the kernel but we can never
subtract.  It is way too early to lock security architecture decisions
into the kernel.

> /Jarkko

Have a good weekend.

Greg

}-- End of excerpt from Jarkko Sakkinen

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"If I'd listened to customers, I'd have given them a faster horse."
                                -- Henry Ford

^ permalink raw reply	[flat|nested] 53+ messages in thread
* Re: [tpmdd-devel] [RFC] tpm2-space: add handling for global session exhaustion
@ 2017-02-10 10:03 Dr. Greg Wettstein
  2017-02-10 16:46 ` James Bottomley
  0 siblings, 1 reply; 53+ messages in thread
From: Dr. Greg Wettstein @ 2017-02-10 10:03 UTC (permalink / raw)
  To: James Bottomley, greg, Jarkko Sakkinen
  Cc: Ken Goldman, tpmdd-devel, linux-security-module, linux-kernel

On Feb 9, 11:24am, James Bottomley wrote:
} Subject: Re: [tpmdd-devel] [RFC] tpm2-space: add handling for global sessi

Good morning to everyone.

> On Thu, 2017-02-09 at 03:06 -0600, Dr. Greg Wettstein wrote:
> > Referring back to Ken's comments about having 20+ clients waiting to
> > get access to the hardware.  Even with the focus in TPM2 on having it
> > be more of a cryptographic accelerator are we convinced that the
> > hardware is ever going to be fast enough for a model of having it
> > directly service large numbers of transactions in something like a
> > 'cloud' model?

> It's already in use as such today:
> 
> https://tectonic.com/assets/pdf/TectonicTrustedComputing.pdf

We are familiar with this work.  I'm not sure, however, that this work
is representative of the notion of using TPM hardware to support a
transactional environment, particularly at the cloud/container level.

There is not a great deal of technical detail on the CoreOS integrity
architecture but it appears they are using TPM hardware to validate
container integrity.  I'm not sure this type of environment reflects
the ability of TPM hardware to support transactional throughputs in an
environment such as financial transaction processing.

Intel's Clear Container work cites the need to achieve container
startup times of 150 milliseconds and they are currently claiming 45
milliseconds as their optimal time.  This work was designed to
demonstrate the feasibility of providing virtual machine isolation
guarantees to containers and as such one of the mandates was to
achieve container start times comparable to standard namespaces.

I ran some very rough timing metrics on one of our Skylake development
systems with hardware TPM2 support.  Here are the elapsed times for
two common verification operations which I assume would be at the
heart of generating any type of reasonable integrity guarantee:

quote: 810 milliseconds
verify signature: 635 milliseconds

This is with the verifying key loaded into the chip.  The elapsed time
to load and validate a key into the chip averages 1200 milliseconds.
Since we are discussing a resource manager which would be shuttling
context into and out of the limited resource slots on the chip I
believe it is valid to consider this overhead as well.

This suggests that just a signature verification on the integrity of a
container is a factor of 4.2 times greater then a well accepted start
time metric for container technology.

Based on that I'm assuming that if TPM based integrity guarantees are
being implemented they are only on ingress of the container into the
cloud environment.  I'm assuming an alternate methodology must be in
place to protect against time of measurement/time of use issues.

Maybe people have better TPM2 hardware then what we have.  I was going
to run this on a Kaby Lake reference system but it appears that TXT is
causing some type of context depletion problems which we we need to
run down.

> We're also planning something like this in the IBM Cloud.

I assume if there is an expection of true transactional times you
either will have better hardware then current generation TPM2
technology.  Either that or I assume you will be using userspace
simulators anchored with a hardware TPM trust root.

Ken's reflection of having 21-22 competing transactions would appear
to have problematic latency issues given our measurements.

I influence engineering for a company which builds deterministically
modeled Linux platforms.  We've spent a lot of time considering TPM2
hardware bottlenecks since they constrain the rate at which we can
validate platform behavioral measurements.

We have a variation of this work which allows SGX OCALL's to validate
platform behavior in order to provide a broader TCB resource spectrum
to the enclave and hardware TPM performance is problematic there as
well.

> James

Have a good weekend.

Greg

}-- End of excerpt from James Bottomley

As always,
Dr. G.W. Wettstein, Ph.D.   Enjellic Systems Development, LLC.
4206 N. 19th Ave.           Specializing in information infra-structure
Fargo, ND  58102            development.
PH: 701-281-1686
FAX: 701-281-3949           EMAIL: greg@enjellic.com
------------------------------------------------------------------------------
"After being a technician for 2 years, I've discovered if people took
 care of their health with the same reckless abandon as their computers,
 half would be at the kitchen table on the phone with the hospital, trying
 to remove their appendix with a butter knife."
                                -- Brian Jones

-- 

^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2017-02-17 22:37 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-18 20:48 [RFC] tpm2-space: add handling for global session exhaustion James Bottomley
2017-01-18 20:48 ` James Bottomley
2017-01-19 12:25 ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-19 12:25   ` Jarkko Sakkinen
2017-01-19 12:41   ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-19 12:41     ` Jarkko Sakkinen
     [not found]     ` <20170119124101.nw7a7m735zhiivfo-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2017-01-27 21:20       ` Ken Goldman
2017-01-27 21:59         ` [tpmdd-devel] " James Bottomley
2017-01-27 21:59           ` James Bottomley
2017-01-19 12:59   ` [tpmdd-devel] " James Bottomley
2017-01-19 12:59     ` James Bottomley
2017-01-20 13:40     ` [tpmdd-devel] " Jarkko Sakkinen
     [not found] ` <1484772489.2396.2.camel-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
2017-01-27 21:42   ` Ken Goldman
2017-01-27 22:04     ` [tpmdd-devel] " James Bottomley
2017-01-27 22:04       ` James Bottomley
2017-01-27 23:35       ` [tpmdd-devel] " Jason Gunthorpe
2017-01-27 23:35         ` Jason Gunthorpe
2017-01-27 23:48         ` [tpmdd-devel] " James Bottomley
2017-01-27 23:48           ` James Bottomley
2017-01-30  0:52       ` Ken Goldman
2017-01-30  0:52         ` Ken Goldman
2017-01-30 16:04         ` [tpmdd-devel] " James Bottomley
2017-01-30 16:04           ` James Bottomley
2017-01-30 21:58           ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-30 21:58             ` Jarkko Sakkinen
2017-01-30 22:13             ` [tpmdd-devel] " James Bottomley
2017-01-30 22:13               ` James Bottomley
     [not found]               ` <1485814388.2518.28.camel-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
2017-01-30 22:46                 ` Ken Goldman
2017-02-10 17:22                 ` Kenneth Goldman
2017-01-31 13:31               ` [tpmdd-devel] " Jarkko Sakkinen
2017-01-31 13:31                 ` Jarkko Sakkinen
     [not found]           ` <1485792295.2518.23.camel-d9PhHud1JfjCXq6kfMZ53/egYHeGw8Jk@public.gmane.org>
2017-01-31 19:28             ` Ken Goldman
2017-01-31 19:55               ` [tpmdd-devel] " James Bottomley
2017-01-31 19:55                 ` James Bottomley
2017-02-09  9:06 [tpmdd-devel] " Dr. Greg Wettstein
2017-02-09 15:19 ` Jarkko Sakkinen
2017-02-09 19:04   ` Jason Gunthorpe
2017-02-09 19:29     ` James Bottomley
2017-02-09 21:54       ` Jason Gunthorpe
2017-02-10  8:48     ` Jarkko Sakkinen
2017-02-09 19:24 ` James Bottomley
2017-02-09 20:05 ` James Bottomley
2017-02-10 10:03 Dr. Greg Wettstein
2017-02-10 16:46 ` James Bottomley
2017-02-10 21:13   ` Kenneth Goldman
2017-02-14 14:38     ` [tpmdd-devel] " Dr. Greg Wettstein
2017-02-14 16:47       ` James Bottomley
     [not found]       ` <71dc0e80-6678-a124-9184-1f93c8532d09@linux.vnet.ibm.com>
2017-02-16 20:06         ` Dr. Greg Wettstein
2017-02-16 20:33           ` Jarkko Sakkinen
2017-02-17  9:56             ` Dr. Greg Wettstein
2017-02-17 12:37               ` Jarkko Sakkinen
2017-02-17 22:37                 ` Dr. Greg Wettstein
2017-02-12 20:29   ` Ken Goldman
2017-02-12 20:29     ` Ken Goldman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.