RE: [tpmdd-devel] [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips

From: Fuchs, Andreas
Date: Mon Oct 05 2015 - 08:21:29 EST


That's why I propose to give the context-save-blob into the kernel. It does not require any TPM2_Load of the key-chain or TPM2_CreatePrimary prior to key usage.

BTW, in the current TSS2-model context-save-blobs are the preferred way for "moving/copying" loaded objects between two applications or threads. The TSS2 crew did not see any value in having a "libdrm-like" flink() call. Since you have to transfer the handle anyways, transferring those few bytes of blob are actually just as easy and management inside the daemon becomes way simple without flink()ing... ;-)

Regarding the in-kernel "minimal resource manager": AFAIK there is already a tpm-mutex inside the kernel. We could use that mutex and then have the algorithm:

- get_mutex(tpm)
- If TPM_has_no_empty_slots:
- tmpBlob0 = Context_Save(some_handle)
- context_Flush(some_handle)
- if TPM_has_one_empts_slot: /* also true if "no_empty_slots" above */
- tmpBlob1 = Context_Save(another_handle)
- context_Flush(another_handle)

- keyhandle = Context_Load(keyBlob)
- datahandle = Context_Load(dataBlob)
- unseal(datahanle, keyhandle)
- Context_Flush(keyhandle)
- Context_Flush(datahandle)

- if tmpBlob0:
- h1 = Context_Load(tmpBlob0)
- h2 = Context_Load(tmpBlob0)
- assert((h1 == some_handle && h2 == another_handle) || (h2 == some_handle && h1 == another_handle))
- Context_Flush(another_handle) /* This is needed to get the original handles guaranteed */
- if tmpBlob1:
- assert(another_handle == Context_Load(tmpBlob1))

- release_mutex(tpm)

We don't need anything more fancy than this. And it should even guarantee that the old values are still present after mutex_release, so (opposed to a full-blown resource-manager) we do not need to keep track and rewrite virtual handles inside the user-space commands.

IMHO, this should be lightweight enough even for the most embedded of applications, since the 2*2k blobs are only allocated on demand...

ChromeOS with 1.2 uses a forked patched TrouSerS, right ?
I don't know about 2.0 though...

Cheers,
Andreas

________________________________________
From: Jarkko Sakkinen [jarkko.sakkinen@xxxxxxxxxxxxxxx]
Sent: Monday, October 05, 2015 13:56
To: Fuchs, Andreas
Cc: tpmdd-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; David Howells; gregkh@xxxxxxxxxxxxxxxxxxx; open list:KEYS-TRUSTED; open list:KEYS-TRUSTED; James Morris; David Safford; akpm@xxxxxxxxxxxxxxxxxxxx; Serge E. Hallyn
Subject: Re: [tpmdd-devel] [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips

On Mon, Oct 05, 2015 at 09:00:48AM +0000, Fuchs, Andreas wrote:
> Hi Jarkko,
>
> /dev/tpm0 is single-open only. So if root wants to do anything there,
> you'd have to stop the tss-daemon first.
> Or do you see "keyctl magic" only happening in initrd ?
>
> I have to admit that I have no experience with the 1.2 trusted key
> features. Never used them. Is there software available that uses
> non-SRKs on 1.2 ? How did they solve the problem of a running
> TrouSerS-tcsd ?
> The main difference for 2.0 is the non-existence of the SRK. That's
> where I see the need for rethinking...

I see where you are getting and it is a valid queston.

In the long run solution would be to have an access broker in the kernel
so that you can open a separated context for transient handles if you
need one and have all the eviction/loading magic in the kernel. However,
this requires a lot of work, and for example for small single user
embedded systems you would anyway want to disable it by using some
compilation option (lets say CONFIG_TCG_TPM2_ACCESS_BROKER).

Your proposal would only partly fix the issue because you need
additional TPM2_Load in trusted.c in order to load the key before
executing TPM2_Unseal operation.

I'm not saying the solution is perfect but it works for notable coverage
of systems (especially in the IoT side) and it doesn't prevent to
implement access broker later on.

I would be interested to get feedback from ChromeOS developers on this
as they are using TPM quite extensively for user data encryption and
various other use cases.

> Cheers,
> Andreas

/Jarkko

> ________________________________________
> From: Jarkko Sakkinen [jarkko.sakkinen@xxxxxxxxxxxxxxx]
> Sent: Monday, October 05, 2015 10:37
> To: Fuchs, Andreas
> Cc: tpmdd-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; David Howells; gregkh@xxxxxxxxxxxxxxxxxxx; open list:KEYS-TRUSTED; open list:KEYS-TRUSTED; James Morris; David Safford; akpm@xxxxxxxxxxxxxxxxxxxx; Serge E. Hallyn
> Subject: Re: [tpmdd-devel] [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips
>
> On Sun, Oct 04, 2015 at 06:57:42PM +0000, Fuchs, Andreas wrote:
> > Hi Jarkko,
> >
> > thanks for the clearification...
> >
> > However, I'd recommend against doing so.
> >
> > Furthermore, if there is a resource-manager running in userspace,
> > applications only get virtual handles and TPM might be empty
> > actually...
> >
> > If that's what you're aiming for, I'd recommend passing the pointer to
> > a context-saved-blob and have the kernel load the key this way. That
> > ensures no problems with resource-manager and handle-mixups.
>
> TPM 1.x interface has the same race if you do not use the default value
> for the 'keyhandle' option.
>
> In practice a processs in TCB (or root) would do all the keyctl magic so
> I do not see huge issue here. It can be orchestrated by the
> OS/distribution. From my point of view you are over-engineering in wrong
> place.
>
> It would be easy to add a way to provide the sealing key as blob later
> on if the simple approach chosen would not be sufficient. I'm confident
> that for 99% of all real-world use cases the interface provided by the
> patch set is sufficient.
>
> > Cheers,
> > Andreas
>
> /Jarkko
>
> > From: Jarkko Sakkinen [jarkko.sakkinen@xxxxxxxxxxxxxxx]
> > Sent: Saturday, October 03, 2015 12:26
> > To: Fuchs, Andreas
> > Cc: tpmdd-devel@xxxxxxxxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; David Howells; gregkh@xxxxxxxxxxxxxxxxxxx; open list:KEYS-TRUSTED; open list:KEYS-TRUSTED; James Morris; David Safford; akpm@xxxxxxxxxxxxxxxxxxxx; Serge E. Hallyn
> > Subject: Re: [tpmdd-devel] [PATCH 4/4] keys, trusted: seal/unseal with TPM 2.0 chips
> >
> > On Sat, Oct 03, 2015 at 10:00:59AM +0000, Fuchs, Andreas wrote:
> > > Hi Jarkko,
> > >
> > > [snip]
> > >
> > > diff --git a/security/keys/trusted.h b/security/keys/trusted.h
> > > index ff001a5..fc32c47 100644
> > > --- a/security/keys/trusted.h
> > > +++ b/security/keys/trusted.h
> > > @@ -12,6 +12,13 @@
> > > #define TPM_RETURN_OFFSET 6
> > > #define TPM_DATA_OFFSET 10
> > >
> > > +/* Transient object handles start from 0x80000000 in TPM 2.0, which makes it
> > > + * a sane default.
> > > + */
> > > +
> > > +#define TPM1_SRKHANDLE 0x40000000
> > > +#define TPM2_SRKHANDLE 0x80000000
> > > +
> > > #define LOAD32(buffer, offset) (ntohl(*(uint32_t *)&buffer[offset]))
> > > #define LOAD32N(buffer, offset) (*(uint32_t *)&buffer[offset])
> > > #define LOAD16(buffer, offset) (ntohs(*(uint16_t *)&buffer[offset]))
> > >
> > > This TPM2_SRKHANDLE is unfortunately wrong.
> > >
> > > Transient handles are assigned and returned by the TPM following the
> > > commands TPM2_CreatePrimary, TPM2_LoadObject and TPM2_ContextLoad. You
> > > can only use transient handles as returned by the TPM in order to
> > > refer to the corresponding object created inside the TPM via these
> > > commands. They can never assumed to be constant. The fact that TPMs
> > > return 0x80000000 for the first loaded Object and 0x80000001 for the
> > > second is merely a coincidence... ;-)
> > >
> > > TPM2 also has no (single) SRK anymore. You have to create your own SRK
> > > / Storage Primary Keys via TPM2_CreatePrimary and use the transient
> > > handle returned from there. This however requires SH-authorization,
> > > usually via Policy IMHO, so not easy to manage. So IMHO, this might be
> > > something for the future but for the moment relying on a persistent
> > > key would be better...
> > >
> > > For persistent SRKs it should become a convention to have those
> > > around. Those handles start with 0x81000000 and the SRKs (or Storage
> > > primary Keys) shall live within 0x81000000 to 0x8100FFFF (see
> > > http://www.trustedcomputinggroup.org/resources/registry_of_reserved_tpm_20_handles_and_localities)
> > >
> > > I'd recommend to rely on the existence of a handle inside this range
> > > with an empty auth-value. So maybe install a persistent SRK to
> > > 0x81000000 via TPM2_EvictControl and then use this from within the
> > > kernel for anything following.
> > > P.S. You should check for the key's TPMA_OBJECT to have fixedTPM SET.
> > > I don't know if there is an actual test for owner-generated SRK
> > > testing. I'll ask around though...
> > >
> > > Note: you can query for handles in this range via
> > > TPM2_GetCapability(TPM_CAP_HANDLES, 0x81000000) and then look for
> > > fitting keys.
> > >
> > >
> > > Feel free to discuss other approaches.
> >
> > I'm fully aware of all what you said. My take was to use 0x800000000 as
> > a default value if you don't the handle ID explicitly in 'description'
> > parameter of the add_key() syscall.
> >
> > > Cheers,
> > > Andreas
> >
> > /Jarkko
> --
> To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/