On Thu, 2017-01-26 at 14:51 +0200, Jarkko Sakkinen wrote: [...] > > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h > > index c48255e..b77fc60 100644 > > --- a/drivers/char/tpm/tpm.h > > +++ b/drivers/char/tpm/tpm.h > > @@ -159,6 +159,8 @@ enum tpm2_cc_attrs { > > struct tpm_space { > > u32 context_tbl[3]; > > u8 *context_buf; > > + u32 session_tbl[6]; > > + u8 *session_buf; > > }; > > > > enum tpm_chip_flags { > > @@ -588,4 +590,5 @@ int tpm2_prepare_space(struct tpm_chip *chip, > > struct tpm_space *space, u32 cc, > > u8 *cmd); > > int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space > > *space, > > u32 cc, u8 *buf, size_t bufsiz); > > +void tpm2_flush_space(struct tpm_chip *chip, struct tpm_space > > *space); > > Why the extra parameter?
Because it was called from tpms-dev in release to flush all the sessions still active. At that point the work space is gone, so we have to call it with the real space. However, I realised that callsite didn't hold the tpm_mutex like it should and that we don't need to flush the contexts because they'll be guaranteed empty, so I added a new function tpm2_kill_space() that does this. > > #endif > > diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2 > > -space.c > > index 7fd2fc5..ba4310a 100644 > > --- a/drivers/char/tpm/tpm2-space.c > > +++ b/drivers/char/tpm/tpm2-space.c > > @@ -59,11 +59,16 @@ static int tpm2_load_context(struct tpm_chip > > *chip, u8 *buf, > > > > rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 4, > > TPM_TRANSMIT_UNLOCKED, NULL); > > + > > cruft Removed. [...] > > @@ -215,17 +265,20 @@ int tpm2_prepare_space(struct tpm_chip *chip, > > struct tpm_space *space, u32 cc, > > > > memcpy(&chip->work_space.context_tbl, &space->context_tbl, > > sizeof(space->context_tbl)); > > + memcpy(&chip->work_space.session_tbl, &space->session_tbl, > > + 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); > > For transient objects the rollback is straight forward and totally > predictable. Given that with sessions you always keep some > information in the TPM the rollback would be a bit more complicated. There is basically no rollback unless you really want to understand what the commands did. If we get a fault on the context save or load that isn't one we understand, like TPM_RC_HANDLE meaning the session won't load or TPM_RC_REFERENCE_H0 meaning the session no longer exists, then I think the only option is flushing everything. I'd like us to agree on a hard failure model: if we get some unexplained error during our context loads or saves, we should clear out the entire space (which would allow us to use pointers instead of copyring) but we don't. So we follow the soft failure. However, sessions will mostly fail to load after this with RPM_RC_HANDLE, so we get the equivalent of soft failure for transients and hard failure for sessions. > Now your code seems to just keep the previous session_buf, doesn't > it? Does that always work or not? Yes, after tpm_flush_space, the session memory is gone and all the sessions will refuse to load with RC_HANDLE, so we end up effectively clearing them out. It seemed better to do it this way than to try to special case all the session stuff. > PS. I have a high-level idea of attack vectors that are prevented by > having meta-data for session inside the TPM but can you point me to > the correct place in the TPM 2.0 specification that discusses about > this? The problem is replay. If I'm snooping your TPM commands and I capture your session context, if we don't have replay detection, I can re-load your session HMAC and replay your command because the session has the authorization or the encryption. The TPM designers thought the only way to avoid replay was to use a counter which was part of the session context which increments every time a session is saved. On loading you check that the counters match and fail if they don't. The only way to implement this is to keep a memory of the counter in the TPM, hence the annoying vestigial sessions. It's note 2 of the architecture Part 1 guide, chapter "15.4 Session Handles (MSO=02_16 and 03_16 )" James > > /Jarkko >