diff mbox series

[1/4] keys: Introduce tsm keys

Message ID 169057265801.180586.10867293237672839356.stgit@dwillia2-xfh.jf.intel.com (mailing list archive)
State New
Headers show
Series keys: Introduce a keys frontend for attestation reports | expand

Commit Message

Dan Williams July 28, 2023, 7:30 p.m. UTC
One of the common operations of a TSM (Trusted Security Module) is to
provide a way for a TVM (confidential computing guest execution
environment) to take a measurement of its run state and use that with a
key-exchange protocol to establish a shared secret with a third-party /
remote attestation agent. The concept is common across TSMs, but the
implementations are unfortunately vendor specific. While the industry
grapples with a common definition of this attestation format [1], Linux
need not make this problem worse by defining a new ABI per TSM that
wants to perform a similar operation. The current momentum has been to
invent new ioctl-ABI per TSM per function which at best is an abdication
of the kernel's responsibility to make common infrastructure concepts
share common ABI.

The proposal, targeted to conceptually work with TDX, SEV, COVE if not
more, is to define a new key type that produces a TSM common blob format
and moves the vendor specificity inside that envelope. The common Linux
definition is:

    "<hex encoded pubkey> <blob descriptor> <hex encoded attestation blob>"

This approach later allows for the standardization of the attestation
blob format without needing to change the Linux ABI. TSM specific
options are encoded in the frontend request format where the options
like SEV:vmpl (privilege level) can be specified and TSMs that do not
support them can decide to ignore them or fail if they are specified.
For now, "privlevel=" and "format=" are the only implemented options.

Example of establishing a tsm key and dumping the provider-specific
report:

    dd if=/dev/urandom of=pubkey bs=1 count=64
    keyctl add tsm tsm_test "auth $(xxd -p -c 0 < pubkey) privlevel=2" @u
    keyctl print 280877394 | awk '{ print $3 }' | xxd -p -c 0 -r | hexdump -C

Now, this patch ends up being a fairly simple custom-key format because
most of the follow-on work that happens after publishing a TSM-wrapped
public-key is performed by userspace. The TSM key is just one step in
establishing a shared secret that can be used to unlock other keys. For
example a user-key could be populated with the resulting shared secret
and that could be used as a master-key for an encrypted-key
(security/keys/encrypted-keys/encrypted.c).

While the discussion that led to this proposal hinted at a new
trusted-key (security/keys/trusted-keys/trusted_core.c) type rooted in
the TSM [2], more work is needed to fetch a secret from the TSM
directly. The trusted-key core expects a pre-established secure channel
to seal and unseal secrets locally. For that reason a "tsm" flavor
trusted-key is saved for follow on work. That will likely starting as a
wrapper around SNP_GET_DERIVED_KEY.

Link: http://lore.kernel.org/r/64961c3baf8ce_142af829436@dwillia2-xfh.jf.intel.com.notmuch [1]
Link: http://lore.kernel.org/r/CAAH4kHYLETfPk-sMD-QSJd0fJ7Qnt04FBwFuEkpnehB5U7D_yw@mail.gmail.com [2]
Cc: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Tested-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Cc: Dionna Amalie Glaze <dionnaglaze@google.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Samuel Ortiz <sameo@rivosinc.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 include/keys/tsm.h     |   71 ++++++++++++
 security/keys/Kconfig  |   12 ++
 security/keys/Makefile |    1 
 security/keys/tsm.c    |  282 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 366 insertions(+)
 create mode 100644 include/keys/tsm.h
 create mode 100644 security/keys/tsm.c

Comments

Jarkko Sakkinen July 28, 2023, 7:40 p.m. UTC | #1
On Fri Jul 28, 2023 at 7:30 PM UTC, Dan Williams wrote:
> One of the common operations of a TSM (Trusted Security Module) is to
> provide a way for a TVM (confidential computing guest execution
> environment) to take a measurement of its run state and use that with a
> key-exchange protocol to establish a shared secret with a third-party /
> remote attestation agent. The concept is common across TSMs, but the

This is obfuscated "white paper" alike language.

I have no idea what TSM's and TVM's are and I do not want to know. Even
confidential computing is useless buzzword in the context of providing
a key type for attestation.

I would replace "tsm" with "attestation".

BR, Jarkko
Peter Gonda July 31, 2023, 4:33 p.m. UTC | #2
On Fri, Jul 28, 2023 at 1:31 PM Dan Williams <dan.j.williams@intel.com> wrote:
>
> One of the common operations of a TSM (Trusted Security Module) is to
> provide a way for a TVM (confidential computing guest execution
> environment) to take a measurement of its run state and use that with a
> key-exchange protocol to establish a shared secret with a third-party /
> remote attestation agent. The concept is common across TSMs, but the
> implementations are unfortunately vendor specific. While the industry
> grapples with a common definition of this attestation format [1], Linux
> need not make this problem worse by defining a new ABI per TSM that
> wants to perform a similar operation. The current momentum has been to
> invent new ioctl-ABI per TSM per function which at best is an abdication
> of the kernel's responsibility to make common infrastructure concepts
> share common ABI.
>
> The proposal, targeted to conceptually work with TDX, SEV, COVE if not
> more, is to define a new key type that produces a TSM common blob format
> and moves the vendor specificity inside that envelope. The common Linux
> definition is:
>
>     "<hex encoded pubkey> <blob descriptor> <hex encoded attestation blob>"
>
> This approach later allows for the standardization of the attestation
> blob format without needing to change the Linux ABI. TSM specific
> options are encoded in the frontend request format where the options
> like SEV:vmpl (privilege level) can be specified and TSMs that do not
> support them can decide to ignore them or fail if they are specified.
> For now, "privlevel=" and "format=" are the only implemented options.
>
> Example of establishing a tsm key and dumping the provider-specific
> report:
>
>     dd if=/dev/urandom of=pubkey bs=1 count=64
>     keyctl add tsm tsm_test "auth $(xxd -p -c 0 < pubkey) privlevel=2" @u
>     keyctl print 280877394 | awk '{ print $3 }' | xxd -p -c 0 -r | hexdump -C

What is the purpose of this report? What does it prove to whom? I'm a
bit confused because it doesn't seem like there is an ability for a
remote party to participate in a challenge and response to introduce
any freshness into this protocol.

Also shouldn't the report have a little more context into the key we
are signing? For instance what type of public key is this? And what is
its purpose? In your example this isn't even a valid public key.

>
> Now, this patch ends up being a fairly simple custom-key format because
> most of the follow-on work that happens after publishing a TSM-wrapped
> public-key is performed by userspace. The TSM key is just one step in
> establishing a shared secret that can be used to unlock other keys. For
> example a user-key could be populated with the resulting shared secret
> and that could be used as a master-key for an encrypted-key
> (security/keys/encrypted-keys/encrypted.c).
>
> While the discussion that led to this proposal hinted at a new
> trusted-key (security/keys/trusted-keys/trusted_core.c) type rooted in
> the TSM [2], more work is needed to fetch a secret from the TSM
> directly. The trusted-key core expects a pre-established secure channel
> to seal and unseal secrets locally. For that reason a "tsm" flavor
> trusted-key is saved for follow on work. That will likely starting as a
> wrapper around SNP_GET_DERIVED_KEY.
>
> Link: http://lore.kernel.org/r/64961c3baf8ce_142af829436@dwillia2-xfh.jf.intel.com.notmuch [1]
> Link: http://lore.kernel.org/r/CAAH4kHYLETfPk-sMD-QSJd0fJ7Qnt04FBwFuEkpnehB5U7D_yw@mail.gmail.com [2]
> Cc: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> Tested-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> Cc: David Howells <dhowells@redhat.com>
> Cc: Jarkko Sakkinen <jarkko@kernel.org>
> Cc: Dionna Amalie Glaze <dionnaglaze@google.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Samuel Ortiz <sameo@rivosinc.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  include/keys/tsm.h     |   71 ++++++++++++
>  security/keys/Kconfig  |   12 ++
>  security/keys/Makefile |    1
>  security/keys/tsm.c    |  282 ++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 366 insertions(+)
>  create mode 100644 include/keys/tsm.h
>  create mode 100644 security/keys/tsm.c
>
> diff --git a/include/keys/tsm.h b/include/keys/tsm.h
> new file mode 100644
> index 000000000000..61a81017d8f5
> --- /dev/null
> +++ b/include/keys/tsm.h
> @@ -0,0 +1,71 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __TSM_H
> +#define __TSM_H
> +
> +#include <linux/types.h>
> +#include <linux/module.h>
> +
> +/*
> + * @TSM_DATA_MAX: a reasonable max with enough space for known attestation
> + * report formats. This mirrors the trusted/encrypted key blob max size.
> + */
> +#define TSM_DATA_MAX 32767
> +#define TSM_PUBKEY_MAX 64
> +#define TSM_FORMAT_MAX 16
> +
> +/**
> + * DOC: TSM Keys
> + *
> + * Trusted Security Module Keys are a common provider of blobs that
> + * facilitate key-exchange between a TVM (confidential computing guest)
> + * and an attestation service. A TSM key combines a user-defined blob

Are we limited to only doing key-exchanges between guests and
attestation services? What if some user would like to handle the
attestation verification without a service?

> + * (likely a public-key for a key-exchance protocol) with a signed

key-exchange

> + * attestation report. That combined blob is then used to obtain
> + * secrets provided by an agent that can validate the attestation
> + * report.
> + *
> + * A full implementation uses a tsm key to, for example, establish a

Should 'TSM' be capitalized everywhere? Or does it not matter?

> + * shared secret and then use that communication channel to instantiate
> + * other keys. The expectation is that the requester of the tsm key
> + * knows a priori the key-exchange protocol associated with the
> + * 'pubkey'.

Can we instead be very specific about what protocols and cryptography
are being used?

> + *
> + * The attestation report format is TSM provider specific, when / if a

I'm confused about the TSM terminology and what a TSM provider is. Is
TSM the confidential compute framework of the vendor? So for Intel
this is TDX, and the TSM provider is the SEAM module?

> + * standard materializes it is only a change to the auth_blob_desc
> + * member of 'struct tsm_key_payload', to convey that common format.
> + */
> +
> +/**
> + * struct tsm_key_payload - generic payload for vendor TSM blobs
> + * @privlevel: optional privilege level to associate with @pubkey
> + * @pubkey_len: how much of @pubkey is valid
> + * @pubkey: the public key-exchange blob to include in the attestation report
> + * @auth_blob_desc: base ascii descriptor of @auth_blob
> + * @auth_blob_format: for TSMs with multiple formats, extend @auth_blob_desc
> + * @auth_blob_len: TSM provider length of the array it publishes in @auth_blob
> + * @auth_blob: TSM specific attestation report blob
> + */
> +struct tsm_key_payload {
> +       int privlevel;
> +       size_t pubkey_len;
> +       u8 pubkey[TSM_PUBKEY_MAX];
> +       const char *auth_blob_desc;
> +       char auth_blob_format[TSM_FORMAT_MAX];
> +       size_t auth_blob_len;
> +       u8 *auth_blob;
> +};

How is freshness incorporated into the key exchange protocol? Wouldn't
we need to do a challenge response between each remote party that we
need to attest the provenance of @pubkey too?

> +
> +/*
> + * tsm_parse - parse the tsm request data
> + *
> + * input format: "auth <hex pubkey data> [options]"
> + *
> + * Checks for options and parses a hex blob of data to be wrapped by the
> + * TSM attestation format.
> + *
> + * options:
> + *     privlevel= integer for selecting the privelege level of the

privilege

> + *                request, if the platform TSM supports that concept. To
> + *                date only SEV accepts this option. Default 0.

SEV-SNP or just SNP? Plain SEV or SEV-ES doesn't actually support this
interface at all.


> + *     format=    string modifier for the format, if the platform TSM
> + *                supports multiple formats. To date only SEV accepts an
> + *                "extended" argument. Default "".
> + *
> + * On success returns 0, otherwise -EINVAL.
> + */
Dan Williams July 31, 2023, 5:48 p.m. UTC | #3
Peter Gonda wrote:
> On Fri, Jul 28, 2023 at 1:31 PM Dan Williams <dan.j.williams@intel.com> wrote:
> >
> > One of the common operations of a TSM (Trusted Security Module) is to
> > provide a way for a TVM (confidential computing guest execution
> > environment) to take a measurement of its run state and use that with a
> > key-exchange protocol to establish a shared secret with a third-party /
> > remote attestation agent. The concept is common across TSMs, but the
> > implementations are unfortunately vendor specific. While the industry
> > grapples with a common definition of this attestation format [1], Linux
> > need not make this problem worse by defining a new ABI per TSM that
> > wants to perform a similar operation. The current momentum has been to
> > invent new ioctl-ABI per TSM per function which at best is an abdication
> > of the kernel's responsibility to make common infrastructure concepts
> > share common ABI.
> >
> > The proposal, targeted to conceptually work with TDX, SEV, COVE if not
> > more, is to define a new key type that produces a TSM common blob format
> > and moves the vendor specificity inside that envelope. The common Linux
> > definition is:
> >
> >     "<hex encoded pubkey> <blob descriptor> <hex encoded attestation blob>"
> >
> > This approach later allows for the standardization of the attestation
> > blob format without needing to change the Linux ABI. TSM specific
> > options are encoded in the frontend request format where the options
> > like SEV:vmpl (privilege level) can be specified and TSMs that do not
> > support them can decide to ignore them or fail if they are specified.
> > For now, "privlevel=" and "format=" are the only implemented options.
> >
> > Example of establishing a tsm key and dumping the provider-specific
> > report:
> >
> >     dd if=/dev/urandom of=pubkey bs=1 count=64
> >     keyctl add tsm tsm_test "auth $(xxd -p -c 0 < pubkey) privlevel=2" @u
> >     keyctl print 280877394 | awk '{ print $3 }' | xxd -p -c 0 -r | hexdump -C
> 
> What is the purpose of this report? What does it prove to whom? I'm a
> bit confused because it doesn't seem like there is an ability for a
> remote party to participate in a challenge and response to introduce
> any freshness into this protocol.
> 
> Also shouldn't the report have a little more context into the key we
> are signing? For instance what type of public key is this? And what is
> its purpose? In your example this isn't even a valid public key.
> 
> >
> > Now, this patch ends up being a fairly simple custom-key format because
> > most of the follow-on work that happens after publishing a TSM-wrapped
> > public-key is performed by userspace. The TSM key is just one step in
> > establishing a shared secret that can be used to unlock other keys. For
> > example a user-key could be populated with the resulting shared secret
> > and that could be used as a master-key for an encrypted-key
> > (security/keys/encrypted-keys/encrypted.c).
> >
> > While the discussion that led to this proposal hinted at a new
> > trusted-key (security/keys/trusted-keys/trusted_core.c) type rooted in
> > the TSM [2], more work is needed to fetch a secret from the TSM
> > directly. The trusted-key core expects a pre-established secure channel
> > to seal and unseal secrets locally. For that reason a "tsm" flavor
> > trusted-key is saved for follow on work. That will likely starting as a
> > wrapper around SNP_GET_DERIVED_KEY.
> >
> > Link: http://lore.kernel.org/r/64961c3baf8ce_142af829436@dwillia2-xfh.jf.intel.com.notmuch [1]
> > Link: http://lore.kernel.org/r/CAAH4kHYLETfPk-sMD-QSJd0fJ7Qnt04FBwFuEkpnehB5U7D_yw@mail.gmail.com [2]
> > Cc: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> > Tested-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> > Cc: David Howells <dhowells@redhat.com>
> > Cc: Jarkko Sakkinen <jarkko@kernel.org>
> > Cc: Dionna Amalie Glaze <dionnaglaze@google.com>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Cc: Samuel Ortiz <sameo@rivosinc.com>
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > ---
> >  include/keys/tsm.h     |   71 ++++++++++++
> >  security/keys/Kconfig  |   12 ++
> >  security/keys/Makefile |    1
> >  security/keys/tsm.c    |  282 ++++++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 366 insertions(+)
> >  create mode 100644 include/keys/tsm.h
> >  create mode 100644 security/keys/tsm.c
> >
> > diff --git a/include/keys/tsm.h b/include/keys/tsm.h
> > new file mode 100644
> > index 000000000000..61a81017d8f5
> > --- /dev/null
> > +++ b/include/keys/tsm.h
> > @@ -0,0 +1,71 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +#ifndef __TSM_H
> > +#define __TSM_H
> > +
> > +#include <linux/types.h>
> > +#include <linux/module.h>
> > +
> > +/*
> > + * @TSM_DATA_MAX: a reasonable max with enough space for known attestation
> > + * report formats. This mirrors the trusted/encrypted key blob max size.
> > + */
> > +#define TSM_DATA_MAX 32767
> > +#define TSM_PUBKEY_MAX 64
> > +#define TSM_FORMAT_MAX 16
> > +
> > +/**
> > + * DOC: TSM Keys
> > + *
> > + * Trusted Security Module Keys are a common provider of blobs that
> > + * facilitate key-exchange between a TVM (confidential computing guest)
> > + * and an attestation service. A TSM key combines a user-defined blob
> 
> Are we limited to only doing key-exchanges between guests and
> attestation services? What if some user would like to handle the
> attestation verification without a service?

From the kernel perspective it does not matter, it is just marshalling
the quote data. I assume local attestation could be built around this,
but that's all user-space policy.

> 
> > + * (likely a public-key for a key-exchance protocol) with a signed
> 
> key-exchange

got it.

> 
> > + * attestation report. That combined blob is then used to obtain
> > + * secrets provided by an agent that can validate the attestation
> > + * report.
> > + *
> > + * A full implementation uses a tsm key to, for example, establish a
> 
> Should 'TSM' be capitalized everywhere? Or does it not matter?

Probably should be.

> > + * shared secret and then use that communication channel to instantiate
> > + * other keys. The expectation is that the requester of the tsm key
> > + * knows a priori the key-exchange protocol associated with the
> > + * 'pubkey'.
> 
> Can we instead be very specific about what protocols and cryptography
> are being used?

Again this is a contract to which the kernel is not a party. The
requester knows the significance of the user-data, and it knows where to
send the combined user-data plus quote to provision further secrets.

Not that I like that arrangement, but the kernel is not enabled by these
TSM implementations to know much more than "user-data in", "report out".

> 
> > + *
> > + * The attestation report format is TSM provider specific, when / if a
> 
> I'm confused about the TSM terminology and what a TSM provider is. Is
> TSM the confidential compute framework of the vendor? So for Intel
> this is TDX, and the TSM provider is the SEAM module?

Yes, I borrowed this term from the TDISP specification where the "Trusted
Security Module" is the overarching term for the confidential compute
infrastructure for the vendor. Yes, TDX + SEAM is a TSM and SEV-SNP +
PSP is a TSM.

> 
> > + * standard materializes it is only a change to the auth_blob_desc
> > + * member of 'struct tsm_key_payload', to convey that common format.
> > + */
> > +
> > +/**
> > + * struct tsm_key_payload - generic payload for vendor TSM blobs
> > + * @privlevel: optional privilege level to associate with @pubkey
> > + * @pubkey_len: how much of @pubkey is valid
> > + * @pubkey: the public key-exchange blob to include in the attestation report
> > + * @auth_blob_desc: base ascii descriptor of @auth_blob
> > + * @auth_blob_format: for TSMs with multiple formats, extend @auth_blob_desc
> > + * @auth_blob_len: TSM provider length of the array it publishes in @auth_blob
> > + * @auth_blob: TSM specific attestation report blob
> > + */
> > +struct tsm_key_payload {
> > +       int privlevel;
> > +       size_t pubkey_len;
> > +       u8 pubkey[TSM_PUBKEY_MAX];
> > +       const char *auth_blob_desc;
> > +       char auth_blob_format[TSM_FORMAT_MAX];
> > +       size_t auth_blob_len;
> > +       u8 *auth_blob;
> > +};
> 
> How is freshness incorporated into the key exchange protocol? Wouldn't
> we need to do a challenge response between each remote party that we
> need to attest the provenance of @pubkey too?

That's left to userspace.

> 
> > +
> > +/*
> > + * tsm_parse - parse the tsm request data
> > + *
> > + * input format: "auth <hex pubkey data> [options]"
> > + *
> > + * Checks for options and parses a hex blob of data to be wrapped by the
> > + * TSM attestation format.
> > + *
> > + * options:
> > + *     privlevel= integer for selecting the privelege level of the
> 
> privilege

got it.

> 
> > + *                request, if the platform TSM supports that concept. To
> > + *                date only SEV accepts this option. Default 0.
> 
> SEV-SNP or just SNP? Plain SEV or SEV-ES doesn't actually support this
> interface at all.

Yeah, I was using "SEV" as a shorthand for the AMD "TSM". So maybe just
"SNP" is appropriate?
Peter Gonda July 31, 2023, 6:14 p.m. UTC | #4
On Mon, Jul 31, 2023 at 11:48 AM Dan Williams <dan.j.williams@intel.com> wrote:
>
> Peter Gonda wrote:
> > On Fri, Jul 28, 2023 at 1:31 PM Dan Williams <dan.j.williams@intel.com> wrote:
> > >
> > > One of the common operations of a TSM (Trusted Security Module) is to
> > > provide a way for a TVM (confidential computing guest execution
> > > environment) to take a measurement of its run state and use that with a
> > > key-exchange protocol to establish a shared secret with a third-party /
> > > remote attestation agent. The concept is common across TSMs, but the
> > > implementations are unfortunately vendor specific. While the industry
> > > grapples with a common definition of this attestation format [1], Linux
> > > need not make this problem worse by defining a new ABI per TSM that
> > > wants to perform a similar operation. The current momentum has been to
> > > invent new ioctl-ABI per TSM per function which at best is an abdication
> > > of the kernel's responsibility to make common infrastructure concepts
> > > share common ABI.
> > >
> > > The proposal, targeted to conceptually work with TDX, SEV, COVE if not
> > > more, is to define a new key type that produces a TSM common blob format
> > > and moves the vendor specificity inside that envelope. The common Linux
> > > definition is:
> > >
> > >     "<hex encoded pubkey> <blob descriptor> <hex encoded attestation blob>"
> > >
> > > This approach later allows for the standardization of the attestation
> > > blob format without needing to change the Linux ABI. TSM specific
> > > options are encoded in the frontend request format where the options
> > > like SEV:vmpl (privilege level) can be specified and TSMs that do not
> > > support them can decide to ignore them or fail if they are specified.
> > > For now, "privlevel=" and "format=" are the only implemented options.
> > >
> > > Example of establishing a tsm key and dumping the provider-specific
> > > report:
> > >
> > >     dd if=/dev/urandom of=pubkey bs=1 count=64
> > >     keyctl add tsm tsm_test "auth $(xxd -p -c 0 < pubkey) privlevel=2" @u
> > >     keyctl print 280877394 | awk '{ print $3 }' | xxd -p -c 0 -r | hexdump -C
> >
> > What is the purpose of this report? What does it prove to whom? I'm a
> > bit confused because it doesn't seem like there is an ability for a
> > remote party to participate in a challenge and response to introduce
> > any freshness into this protocol.
> >
> > Also shouldn't the report have a little more context into the key we
> > are signing? For instance what type of public key is this? And what is
> > its purpose? In your example this isn't even a valid public key.
> >
> > >
> > > Now, this patch ends up being a fairly simple custom-key format because
> > > most of the follow-on work that happens after publishing a TSM-wrapped
> > > public-key is performed by userspace. The TSM key is just one step in
> > > establishing a shared secret that can be used to unlock other keys. For
> > > example a user-key could be populated with the resulting shared secret
> > > and that could be used as a master-key for an encrypted-key
> > > (security/keys/encrypted-keys/encrypted.c).
> > >
> > > While the discussion that led to this proposal hinted at a new
> > > trusted-key (security/keys/trusted-keys/trusted_core.c) type rooted in
> > > the TSM [2], more work is needed to fetch a secret from the TSM
> > > directly. The trusted-key core expects a pre-established secure channel
> > > to seal and unseal secrets locally. For that reason a "tsm" flavor
> > > trusted-key is saved for follow on work. That will likely starting as a
> > > wrapper around SNP_GET_DERIVED_KEY.
> > >
> > > Link: http://lore.kernel.org/r/64961c3baf8ce_142af829436@dwillia2-xfh.jf.intel.com.notmuch [1]
> > > Link: http://lore.kernel.org/r/CAAH4kHYLETfPk-sMD-QSJd0fJ7Qnt04FBwFuEkpnehB5U7D_yw@mail.gmail.com [2]
> > > Cc: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> > > Tested-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> > > Cc: David Howells <dhowells@redhat.com>
> > > Cc: Jarkko Sakkinen <jarkko@kernel.org>
> > > Cc: Dionna Amalie Glaze <dionnaglaze@google.com>
> > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > Cc: Samuel Ortiz <sameo@rivosinc.com>
> > > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > > ---
> > >  include/keys/tsm.h     |   71 ++++++++++++
> > >  security/keys/Kconfig  |   12 ++
> > >  security/keys/Makefile |    1
> > >  security/keys/tsm.c    |  282 ++++++++++++++++++++++++++++++++++++++++++++++++
> > >  4 files changed, 366 insertions(+)
> > >  create mode 100644 include/keys/tsm.h
> > >  create mode 100644 security/keys/tsm.c
> > >
> > > diff --git a/include/keys/tsm.h b/include/keys/tsm.h
> > > new file mode 100644
> > > index 000000000000..61a81017d8f5
> > > --- /dev/null
> > > +++ b/include/keys/tsm.h
> > > @@ -0,0 +1,71 @@
> > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > +#ifndef __TSM_H
> > > +#define __TSM_H
> > > +
> > > +#include <linux/types.h>
> > > +#include <linux/module.h>
> > > +
> > > +/*
> > > + * @TSM_DATA_MAX: a reasonable max with enough space for known attestation
> > > + * report formats. This mirrors the trusted/encrypted key blob max size.
> > > + */
> > > +#define TSM_DATA_MAX 32767
> > > +#define TSM_PUBKEY_MAX 64
> > > +#define TSM_FORMAT_MAX 16
> > > +
> > > +/**
> > > + * DOC: TSM Keys
> > > + *
> > > + * Trusted Security Module Keys are a common provider of blobs that
> > > + * facilitate key-exchange between a TVM (confidential computing guest)
> > > + * and an attestation service. A TSM key combines a user-defined blob
> >
> > Are we limited to only doing key-exchanges between guests and
> > attestation services? What if some user would like to handle the
> > attestation verification without a service?
>
> From the kernel perspective it does not matter, it is just marshalling
> the quote data. I assume local attestation could be built around this,
> but that's all user-space policy.

Makes sense. Can we tweak the language of these comments then?

>
> >
> > > + * (likely a public-key for a key-exchance protocol) with a signed
> >
> > key-exchange
>
> got it.
>
> >
> > > + * attestation report. That combined blob is then used to obtain
> > > + * secrets provided by an agent that can validate the attestation
> > > + * report.
> > > + *
> > > + * A full implementation uses a tsm key to, for example, establish a
> >
> > Should 'TSM' be capitalized everywhere? Or does it not matter?
>
> Probably should be.
>
> > > + * shared secret and then use that communication channel to instantiate
> > > + * other keys. The expectation is that the requester of the tsm key
> > > + * knows a priori the key-exchange protocol associated with the
> > > + * 'pubkey'.
> >
> > Can we instead be very specific about what protocols and cryptography
> > are being used?
>
> Again this is a contract to which the kernel is not a party. The
> requester knows the significance of the user-data, and it knows where to
> send the combined user-data plus quote to provision further secrets.
>
> Not that I like that arrangement, but the kernel is not enabled by these
> TSM implementations to know much more than "user-data in", "report out".

Can you explain why using this key API is better than the ioctl
version? Is there an overhead to adding keys? You could imagine some
userspace application that receives RPCs and does some attestation for
each one, would adding then deleting a huge number of keys present any
issues?

>
> >
> > > + *
> > > + * The attestation report format is TSM provider specific, when / if a
> >
> > I'm confused about the TSM terminology and what a TSM provider is. Is
> > TSM the confidential compute framework of the vendor? So for Intel
> > this is TDX, and the TSM provider is the SEAM module?
>
> Yes, I borrowed this term from the TDISP specification where the "Trusted
> Security Module" is the overarching term for the confidential compute
> infrastructure for the vendor. Yes, TDX + SEAM is a TSM and SEV-SNP +
> PSP is a TSM.

Thanks for the explanation.

>
> >
> > > + * standard materializes it is only a change to the auth_blob_desc
> > > + * member of 'struct tsm_key_payload', to convey that common format.
> > > + */
> > > +
> > > +/**
> > > + * struct tsm_key_payload - generic payload for vendor TSM blobs
> > > + * @privlevel: optional privilege level to associate with @pubkey
> > > + * @pubkey_len: how much of @pubkey is valid
> > > + * @pubkey: the public key-exchange blob to include in the attestation report
> > > + * @auth_blob_desc: base ascii descriptor of @auth_blob
> > > + * @auth_blob_format: for TSMs with multiple formats, extend @auth_blob_desc
> > > + * @auth_blob_len: TSM provider length of the array it publishes in @auth_blob
> > > + * @auth_blob: TSM specific attestation report blob
> > > + */
> > > +struct tsm_key_payload {
> > > +       int privlevel;
> > > +       size_t pubkey_len;
> > > +       u8 pubkey[TSM_PUBKEY_MAX];
> > > +       const char *auth_blob_desc;
> > > +       char auth_blob_format[TSM_FORMAT_MAX];
> > > +       size_t auth_blob_len;
> > > +       u8 *auth_blob;
> > > +};
> >
> > How is freshness incorporated into the key exchange protocol? Wouldn't
> > we need to do a challenge response between each remote party that we
> > need to attest the provenance of @pubkey too?
>
> That's left to userspace.

But you haven't allowed userspace to add any data into the quote other
than just the raw public key.

The current sevguest ioctl allows users to pass arbitrary userdata.
This would allow for some nonce to be included.

At a highlevel I'm not sure why this is better than each vendor having
their own driver. It doesn't seem that difficult for userspace to deal
with these systems given userspace will need to be written carefully
for these PKI protocols anyways.


>
> >
> > > + *                request, if the platform TSM supports that concept. To
> > > + *                date only SEV accepts this option. Default 0.
> >
> > SEV-SNP or just SNP? Plain SEV or SEV-ES doesn't actually support this
> > interface at all.
>
> Yeah, I was using "SEV" as a shorthand for the AMD "TSM". So maybe just
> "SNP" is appropriate?

I'm not sure what AMD prefers. I'll let them chime in.
Dan Williams July 31, 2023, 6:41 p.m. UTC | #5
Peter Gonda wrote:
> On Mon, Jul 31, 2023 at 11:48 AM Dan Williams <dan.j.williams@intel.com> wrote:
> >
> > Peter Gonda wrote:
> > > On Fri, Jul 28, 2023 at 1:31 PM Dan Williams <dan.j.williams@intel.com> wrote:
> > > >
> > > > One of the common operations of a TSM (Trusted Security Module) is to
> > > > provide a way for a TVM (confidential computing guest execution
> > > > environment) to take a measurement of its run state and use that with a
> > > > key-exchange protocol to establish a shared secret with a third-party /
> > > > remote attestation agent. The concept is common across TSMs, but the
> > > > implementations are unfortunately vendor specific. While the industry
> > > > grapples with a common definition of this attestation format [1], Linux
> > > > need not make this problem worse by defining a new ABI per TSM that
> > > > wants to perform a similar operation. The current momentum has been to
> > > > invent new ioctl-ABI per TSM per function which at best is an abdication
> > > > of the kernel's responsibility to make common infrastructure concepts
> > > > share common ABI.
> > > >
> > > > The proposal, targeted to conceptually work with TDX, SEV, COVE if not
> > > > more, is to define a new key type that produces a TSM common blob format
> > > > and moves the vendor specificity inside that envelope. The common Linux
> > > > definition is:
> > > >
> > > >     "<hex encoded pubkey> <blob descriptor> <hex encoded attestation blob>"
> > > >
> > > > This approach later allows for the standardization of the attestation
> > > > blob format without needing to change the Linux ABI. TSM specific
> > > > options are encoded in the frontend request format where the options
> > > > like SEV:vmpl (privilege level) can be specified and TSMs that do not
> > > > support them can decide to ignore them or fail if they are specified.
> > > > For now, "privlevel=" and "format=" are the only implemented options.
> > > >
> > > > Example of establishing a tsm key and dumping the provider-specific
> > > > report:
> > > >
> > > >     dd if=/dev/urandom of=pubkey bs=1 count=64
> > > >     keyctl add tsm tsm_test "auth $(xxd -p -c 0 < pubkey) privlevel=2" @u
> > > >     keyctl print 280877394 | awk '{ print $3 }' | xxd -p -c 0 -r | hexdump -C
> > >
> > > What is the purpose of this report? What does it prove to whom? I'm a
> > > bit confused because it doesn't seem like there is an ability for a
> > > remote party to participate in a challenge and response to introduce
> > > any freshness into this protocol.
> > >
> > > Also shouldn't the report have a little more context into the key we
> > > are signing? For instance what type of public key is this? And what is
> > > its purpose? In your example this isn't even a valid public key.
> > >
> > > >
> > > > Now, this patch ends up being a fairly simple custom-key format because
> > > > most of the follow-on work that happens after publishing a TSM-wrapped
> > > > public-key is performed by userspace. The TSM key is just one step in
> > > > establishing a shared secret that can be used to unlock other keys. For
> > > > example a user-key could be populated with the resulting shared secret
> > > > and that could be used as a master-key for an encrypted-key
> > > > (security/keys/encrypted-keys/encrypted.c).
> > > >
> > > > While the discussion that led to this proposal hinted at a new
> > > > trusted-key (security/keys/trusted-keys/trusted_core.c) type rooted in
> > > > the TSM [2], more work is needed to fetch a secret from the TSM
> > > > directly. The trusted-key core expects a pre-established secure channel
> > > > to seal and unseal secrets locally. For that reason a "tsm" flavor
> > > > trusted-key is saved for follow on work. That will likely starting as a
> > > > wrapper around SNP_GET_DERIVED_KEY.
> > > >
> > > > Link: http://lore.kernel.org/r/64961c3baf8ce_142af829436@dwillia2-xfh.jf.intel.com.notmuch [1]
> > > > Link: http://lore.kernel.org/r/CAAH4kHYLETfPk-sMD-QSJd0fJ7Qnt04FBwFuEkpnehB5U7D_yw@mail.gmail.com [2]
> > > > Cc: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> > > > Tested-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
> > > > Cc: David Howells <dhowells@redhat.com>
> > > > Cc: Jarkko Sakkinen <jarkko@kernel.org>
> > > > Cc: Dionna Amalie Glaze <dionnaglaze@google.com>
> > > > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > > > Cc: Samuel Ortiz <sameo@rivosinc.com>
> > > > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > > > ---
> > > >  include/keys/tsm.h     |   71 ++++++++++++
> > > >  security/keys/Kconfig  |   12 ++
> > > >  security/keys/Makefile |    1
> > > >  security/keys/tsm.c    |  282 ++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  4 files changed, 366 insertions(+)
> > > >  create mode 100644 include/keys/tsm.h
> > > >  create mode 100644 security/keys/tsm.c
> > > >
> > > > diff --git a/include/keys/tsm.h b/include/keys/tsm.h
> > > > new file mode 100644
> > > > index 000000000000..61a81017d8f5
> > > > --- /dev/null
> > > > +++ b/include/keys/tsm.h
> > > > @@ -0,0 +1,71 @@
> > > > +/* SPDX-License-Identifier: GPL-2.0 */
> > > > +#ifndef __TSM_H
> > > > +#define __TSM_H
> > > > +
> > > > +#include <linux/types.h>
> > > > +#include <linux/module.h>
> > > > +
> > > > +/*
> > > > + * @TSM_DATA_MAX: a reasonable max with enough space for known attestation
> > > > + * report formats. This mirrors the trusted/encrypted key blob max size.
> > > > + */
> > > > +#define TSM_DATA_MAX 32767
> > > > +#define TSM_PUBKEY_MAX 64
> > > > +#define TSM_FORMAT_MAX 16
> > > > +
> > > > +/**
> > > > + * DOC: TSM Keys
> > > > + *
> > > > + * Trusted Security Module Keys are a common provider of blobs that
> > > > + * facilitate key-exchange between a TVM (confidential computing guest)
> > > > + * and an attestation service. A TSM key combines a user-defined blob
> > >
> > > Are we limited to only doing key-exchanges between guests and
> > > attestation services? What if some user would like to handle the
> > > attestation verification without a service?
> >
> > From the kernel perspective it does not matter, it is just marshalling
> > the quote data. I assume local attestation could be built around this,
> > but that's all user-space policy.
> 
> Makes sense. Can we tweak the language of these comments then?

Will do.

> 
> >
> > >
> > > > + * (likely a public-key for a key-exchance protocol) with a signed
> > >
> > > key-exchange
> >
> > got it.
> >
> > >
> > > > + * attestation report. That combined blob is then used to obtain
> > > > + * secrets provided by an agent that can validate the attestation
> > > > + * report.
> > > > + *
> > > > + * A full implementation uses a tsm key to, for example, establish a
> > >
> > > Should 'TSM' be capitalized everywhere? Or does it not matter?
> >
> > Probably should be.
> >
> > > > + * shared secret and then use that communication channel to instantiate
> > > > + * other keys. The expectation is that the requester of the tsm key
> > > > + * knows a priori the key-exchange protocol associated with the
> > > > + * 'pubkey'.
> > >
> > > Can we instead be very specific about what protocols and cryptography
> > > are being used?
> >
> > Again this is a contract to which the kernel is not a party. The
> > requester knows the significance of the user-data, and it knows where to
> > send the combined user-data plus quote to provision further secrets.
> >
> > Not that I like that arrangement, but the kernel is not enabled by these
> > TSM implementations to know much more than "user-data in", "report out".
> 
> Can you explain why using this key API is better than the ioctl
> version? Is there an overhead to adding keys?

Setting aside that folks that have been involved in the Keyring
subsystem a lot longer than I are not keen on this usage [1], I expect
the overhead is negligible. Keys are already used in RPC scenarios and
can be destroyed immediately after being instantiated and read.

[1]: http://lore.kernel.org/r/c6576d1682b576ba47556478a98f397ed518a177.camel@HansenPartnership.com

> You could imagine some userspace application that receives RPCs and
> does some attestation for each one, would adding then deleting a huge
> number of keys present any issues?

I can imagine a lot of scenarios, but reading the SEV-SNP whitepaper it
seems to imply that this is a launch-time one-off report that
establishes a channel to convey other secrets. So my expectation is that
this interface is used to bootstrap a guest and never again. Are you
aware of a high frequency use case for these reports?```

> > > > + * The attestation report format is TSM provider specific, when / if a
> > >
> > > I'm confused about the TSM terminology and what a TSM provider is. Is
> > > TSM the confidential compute framework of the vendor? So for Intel
> > > this is TDX, and the TSM provider is the SEAM module?
> >
> > Yes, I borrowed this term from the TDISP specification where the "Trusted
> > Security Module" is the overarching term for the confidential compute
> > infrastructure for the vendor. Yes, TDX + SEAM is a TSM and SEV-SNP +
> > PSP is a TSM.
> 
> Thanks for the explanation.
> 
> >
> > >
> > > > + * standard materializes it is only a change to the auth_blob_desc
> > > > + * member of 'struct tsm_key_payload', to convey that common format.
> > > > + */
> > > > +
> > > > +/**
> > > > + * struct tsm_key_payload - generic payload for vendor TSM blobs
> > > > + * @privlevel: optional privilege level to associate with @pubkey
> > > > + * @pubkey_len: how much of @pubkey is valid
> > > > + * @pubkey: the public key-exchange blob to include in the attestation report
> > > > + * @auth_blob_desc: base ascii descriptor of @auth_blob
> > > > + * @auth_blob_format: for TSMs with multiple formats, extend @auth_blob_desc
> > > > + * @auth_blob_len: TSM provider length of the array it publishes in @auth_blob
> > > > + * @auth_blob: TSM specific attestation report blob
> > > > + */
> > > > +struct tsm_key_payload {
> > > > +       int privlevel;
> > > > +       size_t pubkey_len;
> > > > +       u8 pubkey[TSM_PUBKEY_MAX];
> > > > +       const char *auth_blob_desc;
> > > > +       char auth_blob_format[TSM_FORMAT_MAX];
> > > > +       size_t auth_blob_len;
> > > > +       u8 *auth_blob;
> > > > +};
> > >
> > > How is freshness incorporated into the key exchange protocol? Wouldn't
> > > we need to do a challenge response between each remote party that we
> > > need to attest the provenance of @pubkey too?
> >
> > That's left to userspace.
> 
> But you haven't allowed userspace to add any data into the quote other
> than just the raw public key.

That is not allowed by the SNP firmware interface. The only input is the
64-byte user-buffer that the SNP whitepaper calls a public-key.

> The current sevguest ioctl allows users to pass arbitrary userdata.
> This would allow for some nonce to be included.

It's not arbitrary user-data, it is only meant to a pubkey per the "VM
Launch and Attestation" section of the SNP whitepaper.

> At a highlevel I'm not sure why this is better than each vendor having
> their own driver. It doesn't seem that difficult for userspace to deal
> with these systems given userspace will need to be written carefully
> for these PKI protocols anyways.

The common facilities can still be made common. Namely, the interface to
take in a pubkey / user-data and the location to pull the report need
not have any vendor specificity.
Dionna Amalie Glaze July 31, 2023, 7:09 p.m. UTC | #6
>
> > You could imagine some userspace application that receives RPCs and
> > does some attestation for each one, would adding then deleting a huge
> > number of keys present any issues?
>
> I can imagine a lot of scenarios, but reading the SEV-SNP whitepaper it
> seems to imply that this is a launch-time one-off report that
> establishes a channel to convey other secrets. So my expectation is that
> this interface is used to bootstrap a guest and never again. Are you
> aware of a high frequency use case for these reports?```
>

Attestations may be requested by RPCs themselves when a service
decides to allow a user to present their own challenge nonces that
should be included in the hardware attestation. The "once at boot"
workflow only works for a specific type of application.

> > > >
> > > > How is freshness incorporated into the key exchange protocol? Wouldn't
> > > > we need to do a challenge response between each remote party that we
> > > > need to attest the provenance of @pubkey too?
> > >
> > > That's left to userspace.
> >
> > But you haven't allowed userspace to add any data into the quote other
> > than just the raw public key.
>
> That is not allowed by the SNP firmware interface. The only input is the
> 64-byte user-buffer that the SNP whitepaper calls a public-key.
>

The whitepaper presents a hypothetical usage of the attestation
facility. It is not prescriptive. With only 64 bytes, you're most
likely to be providing a nonce or a hash, and not a full public key.
Indeed, you may be presenting sha512(nonce || pubkey).

> > The current sevguest ioctl allows users to pass arbitrary userdata.
> > This would allow for some nonce to be included.
>
> It's not arbitrary user-data, it is only meant to a pubkey per the "VM
> Launch and Attestation" section of the SNP whitepaper.
>

It really is arbitrary. We've also been discussing including hashed
vTPM quotes to tie them to the hardware attestation. That's not
necessarily how it'll be used going forward, but the interface needs
to allow for this flexibility.

> > At a highlevel I'm not sure why this is better than each vendor having
> > their own driver. It doesn't seem that difficult for userspace to deal
> > with these systems given userspace will need to be written carefully
> > for these PKI protocols anyways.
>
> The common facilities can still be made common. Namely, the interface to
> take in a pubkey / user-data and the location to pull the report need
> not have any vendor specificity.

I can understand the desire to abstract now that there are 2
datapoints instead of 1, but given that you've said folks aren't keen
on this usage of the key system and developers of these drivers are
also not keen, maybe we should let there be some vendor specifics
until we have a better idea how this will work with more technologies?
RISC-V and ARM have attestation facilities coming, and it might be
hard to shoehorn all their capabilities into this as well.
Dan Williams July 31, 2023, 8:10 p.m. UTC | #7
Dionna Amalie Glaze wrote:
> >
> > > You could imagine some userspace application that receives RPCs and
> > > does some attestation for each one, would adding then deleting a huge
> > > number of keys present any issues?
> >
> > I can imagine a lot of scenarios, but reading the SEV-SNP whitepaper it
> > seems to imply that this is a launch-time one-off report that
> > establishes a channel to convey other secrets. So my expectation is that
> > this interface is used to bootstrap a guest and never again. Are you
> > aware of a high frequency use case for these reports?```
> >
> 
> Attestations may be requested by RPCs themselves when a service
> decides to allow a user to present their own challenge nonces that
> should be included in the hardware attestation. The "once at boot"
> workflow only works for a specific type of application.
> 
> > > > >
> > > > > How is freshness incorporated into the key exchange protocol? Wouldn't
> > > > > we need to do a challenge response between each remote party that we
> > > > > need to attest the provenance of @pubkey too?
> > > >
> > > > That's left to userspace.
> > >
> > > But you haven't allowed userspace to add any data into the quote other
> > > than just the raw public key.
> >
> > That is not allowed by the SNP firmware interface. The only input is the
> > 64-byte user-buffer that the SNP whitepaper calls a public-key.
> >
> 
> The whitepaper presents a hypothetical usage of the attestation
> facility. It is not prescriptive. With only 64 bytes, you're most
> likely to be providing a nonce or a hash, and not a full public key.
> Indeed, you may be presenting sha512(nonce || pubkey).
> 
> > > The current sevguest ioctl allows users to pass arbitrary userdata.
> > > This would allow for some nonce to be included.
> >
> > It's not arbitrary user-data, it is only meant to a pubkey per the "VM
> > Launch and Attestation" section of the SNP whitepaper.
> >
> 
> It really is arbitrary. We've also been discussing including hashed
> vTPM quotes to tie them to the hardware attestation. That's not
> necessarily how it'll be used going forward, but the interface needs
> to allow for this flexibility.

Yeah, my "it's not arbitrary" was too strong. What I meant is that Peter
seemed to be alluding to losing some ability to attach user-data to the
report in this new interface, and I was just pointing out that the same
ability to attach data is present in the proposal.

> > > At a highlevel I'm not sure why this is better than each vendor having
> > > their own driver. It doesn't seem that difficult for userspace to deal
> > > with these systems given userspace will need to be written carefully
> > > for these PKI protocols anyways.
> >
> > The common facilities can still be made common. Namely, the interface to
> > take in a pubkey / user-data and the location to pull the report need
> > not have any vendor specificity.
> 
> I can understand the desire to abstract now that there are 2
> datapoints instead of 1, but given that you've said folks aren't keen

s/folks/James/

Jarkko's concern I believe was more associated with my hand-waving about
trusted-keys.

> on this usage of the key system and developers of these drivers are
> also not keen, maybe we should let there be some vendor specifics
> until we have a better idea how this will work with more technologies?
> RISC-V and ARM have attestation facilities coming, and it might be
> hard to shoehorn all their capabilities into this as well.

No, the time to resolve that is now. SEV and TDX are the only ones I
have had the bandwidth to consider right now, but s390 has a thing and
the RISC-V thing seems to be at the point where they are willing to help
out here. This discomfort is the point. Linux has limited chances to
attack technical debt when it comes to ABI, and upstream acceptance is
that forcing function to collaborate.

I think the sysfs proposal is easy to stand up. At the same time I think
it will have challenges similar to the concern that James raised about
Keys becoming a blob transport layer. I.e. I am concerned Greg would
also have concerns with sysfs becoming a blob transport layer especially
if this not a "configure-once / configure-rarely" interface that would
be more amenable to sysfs. That's typical Linux, lets see the patches
and compare the approaches. I might still go the route of, as James
suggests, broaching the subject of Linux Keyring becoming a general
"blob-ring" facility.

Your response about how this might be used for high frequency RPC use
cases tends to bolster what I think Linux Keyring is better suited for
than sysfs. A common ioctl() ABI is a pain to deploy here without it
just unifying a bunch of vendor ioctls behind maybe one chardev which is
not much of a win / recipe for collaboration.

To me the discussion about how this is used and what is the role of Keys
is a useful community discussion. It is still too late to return to
per-vendor corners.
Jarkko Sakkinen Aug. 1, 2023, 6:01 p.m. UTC | #8
On Mon Jul 31, 2023 at 7:33 PM EEST, Peter Gonda wrote:
> What is the purpose of this report? What does it prove to whom? I'm a
> bit confused because it doesn't seem like there is an ability for a
> remote party to participate in a challenge and response to introduce
> any freshness into this protocol.
>
> Also shouldn't the report have a little more context into the key we
> are signing? For instance what type of public key is this? And what is
> its purpose? In your example this isn't even a valid public key.

Yeah, I agree.

It is pretty hard to even evaluate whether this should be in kernel or
could handled by the user space (perhaps with something less intrusive
added to the kernel).

With cover letter starting with not one but two three letter acronyms
that are not common vocabulary is already a red flag for me at least.

A lot more clarity is needed on what the heck this thing is anyway.

BR, Jarkko
Dan Williams Aug. 4, 2023, 2:40 a.m. UTC | #9
Jarkko Sakkinen wrote:
> On Mon Jul 31, 2023 at 7:33 PM EEST, Peter Gonda wrote:
> > What is the purpose of this report? What does it prove to whom? I'm a
> > bit confused because it doesn't seem like there is an ability for a
> > remote party to participate in a challenge and response to introduce
> > any freshness into this protocol.
> >
> > Also shouldn't the report have a little more context into the key we
> > are signing? For instance what type of public key is this? And what is
> > its purpose? In your example this isn't even a valid public key.
> 
> Yeah, I agree.
> 
> It is pretty hard to even evaluate whether this should be in kernel or
> could handled by the user space (perhaps with something less intrusive
> added to the kernel).
> 
> With cover letter starting with not one but two three letter acronyms
> that are not common vocabulary is already a red flag for me at least.
> 
> A lot more clarity is needed on what the heck this thing is anyway.

Apologies Jarkko, the assumption of this code was that because
drivers/virt/coco/sevguest.c was already exporting an ABI that put no
definition on the payload that this new key type would not need to
either.

However, your questioning proves the point that stashing security
relevant ABI in drivers/virt/coco/ is not a recipe to get worthwhile
review from security minded kernel practitioners.

So I can see why my explanation of "just do what sevguest was getting
away with" is not a great answer. Lets try again.

As mentioned in the AMD whitepaper [1]. Confidential computing has a use
case for a guest to prove to an attestation agent that it is running in
a valid configuration before that agent deploys other keys and secrets
to that VM to run a workload. One way to do that is to wrap a report of
the launch state of the VM with a public-key and if that report passes
validation use that key to send encrypted payloads back to the guest.

In this model the kernel is only a conduit to get 64-bytes of data
signed by the report, and the kernel need not have any requirements on
that data. That said, it could. That's where I would look to
recommendations from Dionna and James and others about what contract the
kernel *could*  enforce to ensure that best security practices are being
deployed.  I expect that also helps this implementation cross the
threshold from "blob store" to "key" as the Keyring expects.

[1]: Section "VM Launch & Attestation" https://www.amd.com/system/files/TechDocs/SEV-SNP-strengthening-vm-isolation-with-integrity-protection-and-more.pdf
Peter Gonda Aug. 4, 2023, 4:34 p.m. UTC | #10
> > >
> > > > > + * shared secret and then use that communication channel to instantiate
> > > > > + * other keys. The expectation is that the requester of the tsm key
> > > > > + * knows a priori the key-exchange protocol associated with the
> > > > > + * 'pubkey'.
> > > >
> > > > Can we instead be very specific about what protocols and cryptography
> > > > are being used?
> > >
> > > Again this is a contract to which the kernel is not a party. The
> > > requester knows the significance of the user-data, and it knows where to
> > > send the combined user-data plus quote to provision further secrets.
> > >
> > > Not that I like that arrangement, but the kernel is not enabled by these
> > > TSM implementations to know much more than "user-data in", "report out".
> >
> > Can you explain why using this key API is better than the ioctl
> > version? Is there an overhead to adding keys?
>
> Setting aside that folks that have been involved in the Keyring
> subsystem a lot longer than I are not keen on this usage [1], I expect
> the overhead is negligible. Keys are already used in RPC scenarios and
> can be destroyed immediately after being instantiated and read.

OK the overhead is negligible. But why is this any better?

To me this seems strictly worse to me as a user since I have much less
input into the hardware attestation which is one of the primary
benefits of confidential compute. I don't want the kernel limiting
what cryptographic algorithm I use, or limiting attestation reports to
signing pubkeys.

I understand having a proliferation of similar drivers may not be
ideal but given the hardware lift required to make confidential
compute happen will we really see too many?

>
> [1]: http://lore.kernel.org/r/c6576d1682b576ba47556478a98f397ed518a177.camel@HansenPartnership.com
Dionna Amalie Glaze Aug. 4, 2023, 4:37 p.m. UTC | #11
> In this model the kernel is only a conduit to get 64-bytes of data
> signed by the report, and the kernel need not have any requirements on
> that data. That said, it could. That's where I would look to
> recommendations from Dionna and James and others about what contract the
> kernel *could*  enforce to ensure that best security practices are being
> deployed.  I expect that also helps this implementation cross the
> threshold from "blob store" to "key" as the Keyring expects.
>

I believe there is no security best practice here yet to enforce.

Attestation reports are a power feature, just like a TPM. A TPM
doesn't place any restriction on the format for its nonce, and like
James said, there's already a special entry point for TPM-wrapped keys
in the key API. Users have access to TPM quotes through /dev/tpm0 and
can pass whatever nonce. I don't think we need to limit access to the
interface this hardware gives us because we're trying to avoid another
char device by saying a report is a key.

The coming addition of the SVSM to further isolate the guest and
provide extra "security devices" is also something to be aware of.
There will be a vTPM protocol and a new type of attestation that's
rooted to VMPL0 while Linux is still in VMPL3. I don't think this will
make sev-guest an unnecessary device though, since it's still
undecided how the TPM hierarchy can bind itself to the hardware in a
non-adhoc manner: there's no "attested TPM" spec to have something
between the null hierarchy and the more persistent attestation key
hierarchy. And TCG isn't in the business of specifying how to
virtualize the TPM technology, so we might have to manually link the
two together by getting the tpm quote and then doing a further binding
operation with the sev-guest device.

So, can we give unfettered access to the hardware through not a Key
API but an Attestation API, and for historical reasons allow vTPM to
be its own thing with extra commands? The SVSM could allow users to
have access to more commands than getting an attestation report, like
a virtual HSM separate from the TPM. We wouldn't be able to access it
without a SEV-SNP-specific device. Does that mean it can't be
upstreamed? Do all confidential computing technologies specifically
not differentiate themselves in their capabilities to all use the same
kernel API for interaction?
James Bottomley Aug. 4, 2023, 4:46 p.m. UTC | #12
On Fri, 2023-08-04 at 09:37 -0700, Dionna Amalie Glaze wrote:
[...]
> 
> The coming addition of the SVSM to further isolate the guest and
> provide extra "security devices" is also something to be aware of.
> There will be a vTPM protocol and a new type of attestation that's
> rooted to VMPL0 while Linux is still in VMPL3. I don't think this
> will make sev-guest an unnecessary device though, since it's still
> undecided how the TPM hierarchy can bind itself to the hardware in a
> non-adhoc manner: there's no "attested TPM" spec to have something
> between the null hierarchy and the more persistent attestation key
> hierarchy. And TCG isn't in the business of specifying how to
> virtualize the TPM technology, so we might have to manually link the
> two together by getting the tpm quote and then doing a further
> binding operation with the sev-guest device.

Just on this one, it's already specified in the latest SVSM doc:

https://lore.kernel.org/linux-coco/a2f31400-9e1c-c12a-ad7f-ea0265a12068@amd.com/

The Service Attestation Data on page 36-37.  It says TPMT_PUBLIC of the
EK.  However, what it doesn't say is *which* EK.  I already sent in a
comment saying it should be the TCG template for the P-256 curve EK.

So asking the SVSM to give you the attestation report for the VTPM
service binds the EK of the vTPM.

James
Dionna Amalie Glaze Aug. 4, 2023, 5:07 p.m. UTC | #13
>
> Just on this one, it's already specified in the latest SVSM doc:
>
> https://lore.kernel.org/linux-coco/a2f31400-9e1c-c12a-ad7f-ea0265a12068@amd.com/
>
> The Service Attestation Data on page 36-37.  It says TPMT_PUBLIC of the
> EK.  However, what it doesn't say is *which* EK.  I already sent in a
> comment saying it should be the TCG template for the P-256 curve EK.
>
> So asking the SVSM to give you the attestation report for the VTPM
> service binds the EK of the vTPM.
>

Yes, thanks. It sounds like you have to ask the SVSM to certify the EK
separately from asking the TPM for a quote. We can't rely entirely on
the TPM API and avoid a sev-guest device for talking to the SVSM. Or
are you saying the SVSM attestation report will get encoded in the
x.509 EK certificate that the TPM API returns, such as the report is
in a cert extension? I'm less clear on how TPM software would
interpret the Issuer of that cert.

> James
>
James Bottomley Aug. 4, 2023, 5:12 p.m. UTC | #14
On Fri, 2023-08-04 at 10:07 -0700, Dionna Amalie Glaze wrote:
> > 
> > Just on this one, it's already specified in the latest SVSM doc:
> > 
> > https://lore.kernel.org/linux-coco/a2f31400-9e1c-c12a-ad7f-ea0265a12068@amd.com/
> > 
> > The Service Attestation Data on page 36-37.  It says TPMT_PUBLIC of
> > the
> > EK.  However, what it doesn't say is *which* EK.  I already sent in
> > a
> > comment saying it should be the TCG template for the P-256 curve
> > EK.
> > 
> > So asking the SVSM to give you the attestation report for the VTPM
> > service binds the EK of the vTPM.
> > 
> 
> Yes, thanks. It sounds like you have to ask the SVSM to certify the
> EK separately from asking the TPM for a quote.

That's right.

>  We can't rely entirely on the TPM API and avoid a sev-guest device
> for talking to the SVSM.

Yes, you have to make a SVSM service attestation call initially to
validate the vTPM.

>  Or are you saying the SVSM attestation report will get encoded in
> the x.509 EK certificate that the TPM API returns, such as the report
> is in a cert extension? I'm less clear on how TPM software would
> interpret the Issuer of that cert.

There is no certificate.  It's more like the Google Cloud: the SVSM
vTPM has no EK cert, so you have to ask something else for validation
of the EK, in this case a service attestation quote from the SVSM which
confirms the binding of the current SVSM to the EK and then you use
that EK pub to verify the vTPM.

There's already experimental work to get this supported in Keylime, but
doing it properly involves making the registrar EK validation mechanism
pluggable.

James
Dan Williams Aug. 4, 2023, 10:24 p.m. UTC | #15
Peter Gonda wrote:
> > > >
> > > > > > + * shared secret and then use that communication channel to instantiate
> > > > > > + * other keys. The expectation is that the requester of the tsm key
> > > > > > + * knows a priori the key-exchange protocol associated with the
> > > > > > + * 'pubkey'.
> > > > >
> > > > > Can we instead be very specific about what protocols and cryptography
> > > > > are being used?
> > > >
> > > > Again this is a contract to which the kernel is not a party. The
> > > > requester knows the significance of the user-data, and it knows where to
> > > > send the combined user-data plus quote to provision further secrets.
> > > >
> > > > Not that I like that arrangement, but the kernel is not enabled by these
> > > > TSM implementations to know much more than "user-data in", "report out".
> > >
> > > Can you explain why using this key API is better than the ioctl
> > > version? Is there an overhead to adding keys?
> >
> > Setting aside that folks that have been involved in the Keyring
> > subsystem a lot longer than I are not keen on this usage [1], I expect
> > the overhead is negligible. Keys are already used in RPC scenarios and
> > can be destroyed immediately after being instantiated and read.
> 
> OK the overhead is negligible. But why is this any better?
> 
> To me this seems strictly worse to me as a user since I have much less
> input into the hardware attestation which is one of the primary
> benefits of confidential compute. I don't want the kernel limiting
> what cryptographic algorithm I use, or limiting attestation reports to
> signing pubkeys.

The current proposal on the table is not to have the kernel enforce
anything with respect to the format of the "pubkey" payload. The only
feedback so far I have seen about improving the semantics here is
enforce a nonce which the ioctl() interface just has to trust userspace
is handling and the Keyring approach can enforce a callout for that
input.

> I understand having a proliferation of similar drivers may not be
> ideal but given the hardware lift required to make confidential
> compute happen will we really see too many?

From my perspective this discussion has already been worth it as some
people were unaware that security relevant development had started under
drivers/virt/coco/. The details of the kernel/user contract are coming
into focus.

In general, the point at which to have these types of discussions is at
the 1 -> 2 implementation transition, to my knowledge we are already up
to 5 of these things (AMD, Intel, RISC-V, ARM, S390).
Dan Williams Aug. 5, 2023, 5:11 a.m. UTC | #16
Peter Gonda wrote:
[..]
> OK the overhead is negligible. But why is this any better?

I need to answer this directly. This is better because vendorA is forced
to collaborate with vendorB about instantiation options. No more "stick
new feature that might be duplicative in a siloed driver in
drivers/virt/coco/$vendor". This is better for the kernel.

Once standardization materialized this is already ahead of the game
providing a front end to instantiate that common format. This interface
choice forces ongoing community collaboration on how options are
presented. It takes a position that all existing options that sevguest
already exports are in scope and provides a place to have a discussion
about how and when to add more options. This is better for
collaboration.
diff mbox series

Patch

diff --git a/include/keys/tsm.h b/include/keys/tsm.h
new file mode 100644
index 000000000000..61a81017d8f5
--- /dev/null
+++ b/include/keys/tsm.h
@@ -0,0 +1,71 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __TSM_H
+#define __TSM_H
+
+#include <linux/types.h>
+#include <linux/module.h>
+
+/*
+ * @TSM_DATA_MAX: a reasonable max with enough space for known attestation
+ * report formats. This mirrors the trusted/encrypted key blob max size.
+ */
+#define TSM_DATA_MAX 32767
+#define TSM_PUBKEY_MAX 64
+#define TSM_FORMAT_MAX 16
+
+/**
+ * DOC: TSM Keys
+ *
+ * Trusted Security Module Keys are a common provider of blobs that
+ * facilitate key-exchange between a TVM (confidential computing guest)
+ * and an attestation service. A TSM key combines a user-defined blob
+ * (likely a public-key for a key-exchance protocol) with a signed
+ * attestation report. That combined blob is then used to obtain
+ * secrets provided by an agent that can validate the attestation
+ * report.
+ *
+ * A full implementation uses a tsm key to, for example, establish a
+ * shared secret and then use that communication channel to instantiate
+ * other keys. The expectation is that the requester of the tsm key
+ * knows a priori the key-exchange protocol associated with the
+ * 'pubkey'.
+ *
+ * The attestation report format is TSM provider specific, when / if a
+ * standard materializes it is only a change to the auth_blob_desc
+ * member of 'struct tsm_key_payload', to convey that common format.
+ */
+
+/**
+ * struct tsm_key_payload - generic payload for vendor TSM blobs
+ * @privlevel: optional privilege level to associate with @pubkey
+ * @pubkey_len: how much of @pubkey is valid
+ * @pubkey: the public key-exchange blob to include in the attestation report
+ * @auth_blob_desc: base ascii descriptor of @auth_blob
+ * @auth_blob_format: for TSMs with multiple formats, extend @auth_blob_desc
+ * @auth_blob_len: TSM provider length of the array it publishes in @auth_blob
+ * @auth_blob: TSM specific attestation report blob
+ */
+struct tsm_key_payload {
+	int privlevel;
+	size_t pubkey_len;
+	u8 pubkey[TSM_PUBKEY_MAX];
+	const char *auth_blob_desc;
+	char auth_blob_format[TSM_FORMAT_MAX];
+	size_t auth_blob_len;
+	u8 *auth_blob;
+};
+
+/*
+ * arch specific ops, only one is expected to be registered at a time
+ * i.e. only one of SEV, TDX, COVE, etc.
+ */
+struct tsm_key_ops {
+	const char *name;
+	struct module *module;
+	int (*auth_new)(struct tsm_key_payload *t, void *provider_data);
+};
+
+int register_tsm_provider(const struct tsm_key_ops *ops, void *provider_data);
+void unregister_tsm_provider(const struct tsm_key_ops *ops);
+
+#endif /* __TSM_H */
diff --git a/security/keys/Kconfig b/security/keys/Kconfig
index abb03a1b2a5c..f530cbd876fc 100644
--- a/security/keys/Kconfig
+++ b/security/keys/Kconfig
@@ -133,3 +133,15 @@  config KEY_NOTIFICATIONS
 	  on keys and keyrings on which the caller has View permission.
 	  This makes use of pipes to handle the notification buffer and
 	  provides KEYCTL_WATCH_KEY to enable/disable watches.
+
+config TSM_KEYS
+	tristate "TSM-based (Confidential Computing) keys"
+	help
+	  TSM (Trusted Security Module) key support arranges to convey a blob to
+	  a confidentiality and integrity protected virtual machine / guest
+	  (TVM). The blob instantiation flow involves submitting the measurement
+	  report of a TVM, obtained from the platform TSM, to a remote
+	  attestation service that only provides the key if the report passes
+	  validation. The report format is vendor specific and the validation is
+	  user policy, so this feature requires a /etc/request-key.conf handler
+	  for communicating with the remote attestation provider.
diff --git a/security/keys/Makefile b/security/keys/Makefile
index 5f40807f05b3..96972a4815d5 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -28,5 +28,6 @@  obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += keyctl_pkey.o
 # Key types
 #
 obj-$(CONFIG_BIG_KEYS) += big_key.o
+obj-$(CONFIG_TSM_KEYS) += tsm.o
 obj-$(CONFIG_TRUSTED_KEYS) += trusted-keys/
 obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys/
diff --git a/security/keys/tsm.c b/security/keys/tsm.c
new file mode 100644
index 000000000000..d9532319f819
--- /dev/null
+++ b/security/keys/tsm.c
@@ -0,0 +1,282 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2023 Intel Corporation. All rights reserved. */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/err.h>
+#include <linux/uuid.h>
+#include <linux/slab.h>
+#include <linux/rwsem.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/parser.h>
+#include <linux/cleanup.h>
+#include <linux/key-type.h>
+
+#include <keys/tsm.h>
+#include <keys/user-type.h>
+
+static struct tsm_provider {
+	const struct tsm_key_ops *ops;
+	void *data;
+} provider;
+static DECLARE_RWSEM(tsm_key_rwsem);
+
+static const struct tsm_key_ops *get_ops(void)
+{
+	down_read(&tsm_key_rwsem);
+	return provider.ops;
+}
+
+static void *get_data(void)
+{
+	lockdep_assert_held(&tsm_key_rwsem);
+	return provider.data;
+}
+
+static void put_ops(void)
+{
+	up_read(&tsm_key_rwsem);
+}
+
+int register_tsm_provider(const struct tsm_key_ops *ops,
+			  void *provider_data)
+{
+	const struct tsm_key_ops *conflict;
+	int rc;
+
+	down_write(&tsm_key_rwsem);
+	conflict = provider.ops;
+	if (conflict) {
+		pr_err("\"%s\" ops already registered\n", conflict->name);
+		rc = -EEXIST;
+		goto out;
+	}
+	try_module_get(ops->module);
+	provider.ops = ops;
+	provider.data = provider_data;
+	rc = 0;
+out:
+	up_write(&tsm_key_rwsem);
+	return rc;
+}
+EXPORT_SYMBOL_GPL(register_tsm_provider);
+
+void unregister_tsm_provider(const struct tsm_key_ops *ops)
+{
+	down_write(&tsm_key_rwsem);
+	provider.ops = NULL;
+	provider.data = NULL;
+	module_put(ops->module);
+	up_write(&tsm_key_rwsem);
+}
+EXPORT_SYMBOL_GPL(unregister_tsm_provider);
+
+enum {
+	Opt_err,
+	Opt_auth,
+	Opt_format,
+	Opt_privlevel,
+};
+
+static const match_table_t tsm_tokens = {
+	{ Opt_auth, "auth" },
+	{ Opt_privlevel, "privlevel=%s" },
+	{ Opt_format, "format=%s" },
+	{ Opt_err, NULL },
+};
+
+/*
+ * tsm_parse - parse the tsm request data
+ *
+ * input format: "auth <hex pubkey data> [options]"
+ *
+ * Checks for options and parses a hex blob of data to be wrapped by the
+ * TSM attestation format.
+ *
+ * options:
+ *     privlevel= integer for selecting the privelege level of the
+ *                request, if the platform TSM supports that concept. To
+ *                date only SEV accepts this option. Default 0.
+ *     format=    string modifier for the format, if the platform TSM
+ *                supports multiple formats. To date only SEV accepts an
+ *                "extended" argument. Default "".
+ *
+ * On success returns 0, otherwise -EINVAL.
+ */
+static int tsm_parse(char *input, struct tsm_key_payload *t)
+{
+	substring_t args[MAX_OPT_ARGS];
+	unsigned long optmask = 0;
+	unsigned int privlevel;
+	int token, rc;
+	char *p;
+
+	/* all tsm keys must start with "auth" as a placeholder command */
+	p = strsep(&input, " \t");
+	if (!p)
+		return -EINVAL;
+	token = match_token(p, tsm_tokens, args);
+	switch (token) {
+	case Opt_auth:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* next is the pubkey hex blob */
+	p = strsep(&input, " \t");
+	if (!p)
+		return -EINVAL;
+	t->pubkey_len = strlen(p) / 2;
+	if (t->pubkey_len > TSM_PUBKEY_MAX)
+		return -EINVAL;
+	rc = hex2bin(t->pubkey, p, t->pubkey_len);
+	if (rc < 0)
+		return -EINVAL;
+
+	/* last is zero or more options */
+	while ((p = strsep(&input, " \t"))) {
+		if (*p == '\0' || *p == ' ' || *p == '\t')
+			continue;
+		token = match_token(p, tsm_tokens, args);
+		/* each option can appear only once */
+		if (test_and_set_bit(token, &optmask))
+			return -EINVAL;
+		switch (token) {
+		case Opt_privlevel:
+			rc = kstrtouint(args[0].from, 16, &privlevel);
+			if (rc)
+				return rc;
+			t->privlevel = privlevel;
+			break;
+		case Opt_format:
+			if (strlen(args[0].from) >= TSM_FORMAT_MAX)
+				return -EINVAL;
+			strscpy(t->auth_blob_format, args[0].from,
+				TSM_FORMAT_MAX);
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int tsm_instantiate(struct key *key, struct key_preparsed_payload *prep)
+{
+	size_t datalen = prep->datalen;
+	const struct tsm_key_ops *ops;
+	int rc;
+
+	if (datalen <= 0 || datalen > TSM_DATA_MAX || !prep->data)
+		return -EINVAL;
+
+	char *datablob __free(kfree) =
+		kmemdup_nul(prep->data, datalen, GFP_KERNEL);
+	if (!datablob)
+		return -ENOMEM;
+
+	struct tsm_key_payload *t __free(kfree) =
+		kzalloc(sizeof(*t), GFP_KERNEL);
+	if (!t)
+		return -ENOMEM;
+
+	rc = tsm_parse(datablob, t);
+	if (rc < 0)
+		return rc;
+
+	ops = get_ops();
+	if (ops)
+		rc = ops->auth_new(t, get_data());
+	else
+		rc = -ENXIO;
+	put_ops();
+
+	if (rc)
+		return rc;
+
+	rc = key_payload_reserve(key, sizeof(*t) + t->auth_blob_len);
+	if (rc) {
+		kvfree(t->auth_blob);
+		return rc;
+	}
+
+	rcu_assign_keypointer(key, t);
+	no_free_ptr(t);
+	return 0;
+}
+
+/*
+ * tsm_read - format and copy out the tsm auth record
+ *
+ * The resulting datablob format is:
+ * <pubkey blob> <auth blob desc[:format]> <auth blob>
+ *
+ * On success, return to userspace the size of the formatted payload.
+ */
+static long tsm_read(const struct key *key, char *buffer, size_t buflen)
+{
+	size_t asciiblob_len, desc_len;
+	struct tsm_key_payload *t;
+	char *buf, *format = NULL;
+	const int nr_spaces = 2;
+
+	t = dereference_key_locked(key);
+
+	desc_len = strlen(t->auth_blob_desc);
+	if (t->auth_blob_format[0]) {
+		format = &t->auth_blob_format[0];
+		desc_len += strlen(format) + 1;
+	}
+
+	asciiblob_len =
+		t->pubkey_len * 2 + desc_len + t->auth_blob_len * 2 + nr_spaces;
+
+	if (!buffer || buflen < asciiblob_len)
+		return asciiblob_len;
+
+	buf = bin2hex(buffer, t->pubkey, t->pubkey_len);
+	if (format)
+		buf += sprintf(buf, " %s:%s ", t->auth_blob_desc, format);
+	else
+		buf += sprintf(buf, " %s ", t->auth_blob_desc);
+	buf = bin2hex(buf, t->auth_blob, t->auth_blob_len);
+
+	/* sanity check for future changes to this function */
+	WARN_ON_ONCE(buf - buffer != asciiblob_len);
+
+	return asciiblob_len;
+}
+
+static void tsm_destroy(struct key *key)
+{
+	struct tsm_key_payload *t = key->payload.data[0];
+
+	kvfree(t->auth_blob);
+	kfree(t);
+}
+
+static struct key_type key_type_tsm = {
+	.name = "tsm",
+	.instantiate = tsm_instantiate,
+	.destroy = tsm_destroy,
+	.describe = user_describe,
+	.read = tsm_read,
+};
+
+static int __init tsm_key_init(void)
+{
+	return register_key_type(&key_type_tsm);
+}
+module_init(tsm_key_init);
+
+static void __exit tsm_key_exit(void)
+{
+	unregister_key_type(&key_type_tsm);
+}
+module_exit(tsm_key_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports as Key payloads");