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 |
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
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. > + */
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?
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.
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.
> > > 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.
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.
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
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
> > > > > > > > + * 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
> 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?
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
> > 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 >
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
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).
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 --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");