Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

svsm: add SVSM VTPM Service Attestation #541

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

IT302
Copy link

@IT302 IT302 commented Nov 28, 2024

vTPM service attestation is described in section 8.3 of "Secure VM Service Module for SEV-SNP Guests, Publication #58019 Revision: 1.00 Issue Date: July 2023". It certifies the Endorsement Key (EK) of the vTPM by providing the TPMT_PUBLIC structure of the EK. This is crucial for downstream projects like Keylime, as the SVSM vTPM lacks an EK certificate found in physical TPMs to anchor trust.

The attestation is part of the SVSM Attestation Protocol and uses the SVSM_ATTEST_SINGLE_SERVICE call (see section 7 of the specifications). It is triggered by making an SVSM_ATTEST_SINGLE_SERVICE call with the GUID set to c476f1eb-0123-45a5-9641-b4e7dde5bfe3. The attestation code returns the VMPL0 attestation report and the vTPM Service Manifest Data Structure (TPMT_PUBLIC structure of the EK). The REPORT_DATA in the SNP attestation request is the SHA-512 digest of the input nonce and the vTPM Service Manifest Data Structure.

The vTPM initialization function was modified to generate an RSA 2048-bit EK from the TPM's Endorsement Primary Seed (EPS) and cache the public key as a TPMT_PUBLIC structure. This cached EK public key can be retrieved later for vTPM service attestation. The EK is created with the TCG default EK template (see Table 4 of the "TCG EK Credential Profile For TPM Family 2.0; Level 0 Version 2.5 Revision 2.0"). Since the EK is derived from the EPS, it can be recreated upstream at any time. For example, the same EK can be recreated in an OS using the TSS2 command "tpm2_createek -c ek.ctx -G rsa -u ek.pub" and compared against the one returned by vTPM service attestation.

vTPM service attestation as specified can only return one type of EK, so the implementation supports RSA 2048-bit EK as defined in Table 4 of the "TCG EK Credential Profile For TPM Family 2.0; Level 0 Version 2.5 Revision 2.0," which is the most common Trusted Computing Group(TCG) EK type.

Resolves #437, resolves #361

@IT302
Copy link
Author

IT302 commented Nov 28, 2024

We need this for our upcoming Keylime TEE enhancements. There is an OS level test script for testing the feature, https://github.com/hpe-security-lab/svsm-vtpm-test

@joergroedel joergroedel added the wait-for-review PR needs for approval by reviewers label Dec 5, 2024
@joergroedel joergroedel requested a review from cclaudio December 11, 2024 15:24
@joergroedel
Copy link
Member

@cclaudio can you please help to review this?

@cclaudio
Copy link
Member

Yes, I will review it today later.

@deeglaze
Copy link
Contributor

Attest single service doesn’t bind the fact that it’s a single service request, so it could be interpreted as a full attestation that just has one service, right? That could be a problem if you want to ensure a service is missing.

@tlendacky
Copy link
Contributor

Attest single service doesn’t bind the fact that it’s a single service request, so it could be interpreted as a full attestation that just has one service, right? That could be a problem if you want to ensure a service is missing.

The manifest output of a single service vs all services is different, with the all services call containing the all services manifest GUID.

@stefano-garzarella
Copy link
Member

@joergroedel can you approve the workflow?

Copy link
Member

@cclaudio cclaudio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @IT302, thank you for the PR. I have made some comments and requested a few changes.

With the ATTEST protocol implemented in the SVSM, we should be able to call it from guest userpsace through the configfs-tsm interface , see [1] for ABI specification and [2] for example. It would be great if we can test this PR through that interface.

[1] - https://github.com/coconut-svsm/linux/blob/svsm/Documentation/ABI/testing/configfs-tsm
[2] - coconut-svsm/linux@70e6f7e

@IT302
Copy link
Author

IT302 commented Dec 16, 2024

Hi @IT302, thank you for the PR. I have made some comments and requested a few changes.

With the ATTEST protocol implemented in the SVSM, we should be able to call it from guest userpsace through the configfs-tsm interface , see [1] for ABI specification and [2] for example. It would be great if we can test this PR through that interface.

[1] - https://github.com/coconut-svsm/linux/blob/svsm/Documentation/ABI/testing/configfs-tsm [2] - coconut-svsm/linux@70e6f7e

We’ve already tested the PR with the Linux configfs-tsm (check out the test script here: https://github.com/hpe-security-lab/svsm-vtpm-test). We’ve also successfully tested it with our Keylime TEE attester and verifier, and we’ll push those changes up once this PR is merged.

@joergroedel joergroedel added in-review PR is under active review and not yet approved and removed wait-for-review PR needs for approval by reviewers labels Dec 18, 2024
@gemini-15
Copy link

This PR does not seem to work on our end with the linux configfs-tsm tests that we've done.

While we are able to get the attestation report from the outblob file, the EK public key is not returned in the manifestblob. We also have no cert available on the auxblob file either.

The attestation report extracted from outblob doesn't contain the hashed EK pub key in the report_data either.

Some precisions about our build :

  • SVSM is built with debug/release and vTPM feature enabled (when using make). We use this PR version for SVSM
  • Linux kernel used is the coconut fork https://github.com/coconut-svsm/linux and the svsm branch (fd20cbd4a899fb4dd08479d0e110894c0db4f35f)
  • We specify the service_guid to the configfs to configure it for single service attest.

We are still investigating where the issue could come from. Also the example shown above https://github.com/hpe-security-lab/svsm-vtpm-test does not work. The configfs-tsm ABI testing does not include any svsm file as shown in the example. So it might be a different kernel that this PR was tested on.

Let me know if I may have missed something, and any support would be great

@tlendacky
Copy link
Contributor

We are still investigating where the issue could come from. Also the example shown above https://github.com/hpe-security-lab/svsm-vtpm-test does not work. The configfs-tsm ABI testing does not include any svsm file as shown in the example. So it might be a different kernel that this PR was tested on.

The referenced tool should be writing "svsm" into the "service_provider" file, not "1" into the "svsm" file (not sure if there are other changes needed). The tool needs to be updated to match the upstream TSM implementation as specified in the Documentation file.

@IT302
Copy link
Author

IT302 commented Jan 24, 2025

While we are able to get the attestation report from the outblob file, the EK public key is not returned in the manifestblob.

What is the VMPL of the attestation report from outblob?

@gemini-15
Copy link

We are still investigating where the issue could come from. Also the example shown above https://github.com/hpe-security-lab/svsm-vtpm-test does not work. The configfs-tsm ABI testing does not include any svsm file as shown in the example. So it might be a different kernel that this PR was tested on.

The referenced tool should be writing "svsm" into the "service_provider" file, not "1" into the "svsm" file (not sure if there are other changes needed). The tool needs to be updated to match the upstream TSM implementation as specified in the Documentation file.

Thanks for the quick response. It worked perfectly !

@gemini-15
Copy link

While we are able to get the attestation report from the outblob file, the EK public key is not returned in the manifestblob.

What is the VMPL of the attestation report from outblob?

The VMPL specified is 2

@IT302
Copy link
Author

IT302 commented Jan 24, 2025

While we are able to get the attestation report from the outblob file, the EK public key is not returned in the manifestblob.

What is the VMPL of the attestation report from outblob?

The VMPL specified is 2

It seems the attestation request is not being sent to SVSM. The PR/SVSM should only provide VMPL0 attestations, see https://github.com/coconut-svsm/svsm/blob/main/kernel/src/greq/services.rs#L28.

The VMPL2 attestation report must have come from outside SVSM, likely from the Linux . Are you using configfs-tsm directly or a tool like virtee snpguest? Can you ensure that the VMPL or privilege level is set to 0 when making an attestation request? See, #589

@gemini-15
Copy link

gemini-15 commented Jan 24, 2025

It seems the attestation request is not being sent to SVSM. The PR/SVSM should only provide VMPL0 attestations, see https://github.com/coconut-svsm/svsm/blob/main/kernel/src/greq/services.rs#L28.

The VMPL2 attestation report must have come from outside SVSM, likely from the Linux . Are you using configfs-tsm directly or a tool like virtee snpguest? Can you ensure that the VMPL or privilege level is set to 0 when making an attestation request? See, #589

I'm using configfs-tsm directly. And after checking here is a snippet of the attestation report returned:

AttestationReport { version: 2, guest_svn: 0, policy: GuestPolicy { .0: 196608, abi_minor: 0, abi_major: 0, smt_allowed: 1, migrate_ma_allowed: 0, debug_allowed: 0, single_socket_required: 0 }, family_id: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], image_id: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], vmpl: 0, sig_algo: 1, current_tcb: TcbVersion { bootloader: 7, tee: 0, _reserved: [0, 0, 0, 0], snp: 14, microcode: 72 }, plat_info: PlatformInfo { .0: 1, tsme_enabled: 1, smt_enabled: 0 }, _author_key_en: 0, _reserved_0: 0, report_data: [17, 65, 68, 123, 219, 76,...

The attestation report as you said is at VMPL 0, which is what we needed also. However, even if I specify the vmpl level at 2 in privlevel the attestation report sent back still is generated at VMPL0. Is this expected behavior?

@tlendacky
Copy link
Contributor

The attestation report as you said is at VMPL 0, which is what we needed also. However, even if I specify the vmpl level at 2 in privlevel the attestation report sent back still is generated at VMPL0. Is this expected behavior?

Yes. If you look at the SVSM specification, a VMPL level is not an input to the protocol and the SVSM will always set a VMPL of 0.

@IT302
Copy link
Author

IT302 commented Jan 27, 2025

@cclaudio @stefano-garzarella Could you please review the changes? I plan to squash everything into a single commit at the end of the review process.

@IT302
Copy link
Author

IT302 commented Feb 10, 2025

Hey @cclaudio @stefano-garzarella ,

Just a quick heads-up—I’ve made the requested changes on my PR. When you have a moment, could you take another look? Let me know if there’s anything else I need to fix.

Thanks

Geoffrey

@stefano-garzarella
Copy link
Member

@IT302 I'm really sorry, FOSDEM and FOSDEM-flu completely messed up my plans, I'll look into it as soon as possible these days!

@stefano-garzarella
Copy link
Member

@IT302 please can you squash fixup with the original commits, I find it hard to review. Also, can you resolve comments that you addressed (not sure if you can, GH is strange)

@IT302 IT302 force-pushed the feature/vtpm-attestation branch from 40e118a to d33d9ce Compare February 13, 2025 11:15
@IT302
Copy link
Author

IT302 commented Feb 13, 2025

@IT302 please can you squash fixup with the original commits, I find it hard to review. Also, can you resolve comments that you addressed (not sure if you can, GH is strange)

@stefano-garzarella Could you please take a look again? I have squashed the commits and resolved the comments. Thanks!

@cclaudio
Copy link
Member

I have made a few comments. Apart from that the PR looks good to me. Thanks.

vTPM service attestation is described in section 8.3 of "Secure VM
Service Module for SEV-SNP Guests, Publication #58019 Revision: 1.00
Issue Date: July 2023". It certifies the Endorsement Key (EK) of the
vTPM by providing the TPMT_PUBLIC structure of the EK. This is crucial
for downstream projects like Keylime, as the SVSM vTPM lacks an EK
certificate found in physical TPMs to anchor trust.

The attestation is part of the SVSM Attestation Protocol and uses the
SVSM_ATTEST_SINGLE_SERVICE call (see section 7 of the specifications).
It is triggered by making an SVSM_ATTEST_SINGLE_SERVICE call with the
GUID set to c476f1eb-0123-45a5-9641-b4e7dde5bfe3. The attestation code
returns the VMPL0 attestation report and the vTPM Service Manifest Data
Structure (TPMT_PUBLIC structure of the EK). The REPORT_DATA in the SNP
attestation request is the SHA-512 digest of the input nonce and the
vTPM Service Manifest Data Structure.

The vTPM initialization function was modified to generate an RSA
2048-bit EK from the TPM's Endorsement Primary Seed (EPS) and cache the
public key as a TPMT_PUBLIC structure. This cached EK public key can be
retrieved later for vTPM service attestation. The EK is created with
the TCG default EK template (see Table 4 of the "TCG EK Credential
Profile For TPM Family 2.0; Level 0 Version 2.5 Revision 2.0"). Since
the EK is derived from the EPS, it can be recreated upstream at any
time. For example, the same EK can be recreated in an OS using the TSS2
command "tpm2_createek -c ek.ctx -G rsa -u ek.pub" and compared against
the one returned by vTPM service attestation.

vTPM service attestation as specified can only return one type of EK, so
the implementation supports RSA 2048-bit EK as defined in Table 4 of
the "TCG EK Credential Profile For TPM Family 2.0; Level 0 Version 2.5
Revision 2.0," which is the most common Trusted Computing Group(TCG) EK
type.

Resolves coconut-svsm#437, resolves coconut-svsm#361

Signed-off-by: Geoffrey Ndu <[email protected]>
@IT302 IT302 force-pushed the feature/vtpm-attestation branch from d33d9ce to a24dca6 Compare February 15, 2025 12:15
Copy link
Member

@cclaudio cclaudio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@stefano-garzarella stefano-garzarella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@IT302 great work!
I left some comments, but I don't want to stop this PR, we can fix them later eventually.


// Extract the GUID from the Attest Single Service Operation structure.
// The GUID is used to determine the specific service to be attested.
// Currently, only the VTPM service with the GUID 0xebf176c4_2301a545_9641b4e7_dde5bfe3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Currently, only the VTPM service with the GUID 0xebf176c4_2301a545_9641b4e7_dde5bfe3
// Currently, only the vTPM service with the GUID 0xebf176c4_2301a545_9641b4e7_dde5bfe3

//
// 1. Manufacture it for the first time
// 2. Make sure it does not fail if it is re-manufactured
// 3. Teardown to indicate it needs to be manufactured
// 4. Manufacture it for the first time
// 5. Power it on indicating it requires startup. By default, OVMF will start
// and selftest it.
// 6. Selftest it
// 7. Start it up on for next step
// 8. Create RSA2004 EK and cache EKpub for VTPM service attestation requests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 8. Create RSA2004 EK and cache EKpub for VTPM service attestation requests
// 8. Create RSA2004 EK and cache EKpub for vTPM service attestation requests

Comment on lines +74 to +87
/// Create RSA 2048 Endorsement Key (EK) and cache the public key
///
/// This function creates an RSA 2048-bit Endorsement Key (EK) from the TPM's Endorsement
/// Primary Seed (EPS) and caches the public key as TMPT_PUBLIC structure. The cached EK
/// public key can be retrieved later and used to provide vTPM service attestation. The
/// EK is created with the TCG default EK template as shown in Table 4 of the "TCG EK
/// Credential Profile For TPM Family 2.0; Level 0 Version 2.5 Revision 2.0".
///
/// Since the EK is created from the EPS, following the TCG EK Credential Profile, the EK can
/// be recreated at any time. For example, one can recreate the same EK in an OS using TSS2
/// "tpm2_createek -c ek.ctx -G rsa -u ek.pub command".
///
/// Retrieve the EK public key with get_ekpub() function.
fn create_ek_rsa2048(&mut self) -> Result<(), SvsmReqError>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the current thread on the coconut mailing list, I hesitate to merge this in as the default key. Using the storage key template means requiring a more challenging make/activatecredential flow that weakens the cryptographic binding between the vTPM quote and the SEV-SNP attestation report around the service manifest.

Copy link
Author

@IT302 IT302 Feb 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think we should deviate from the norm for our default key. I am all for the efficiency of signing EKs, but there are key applications/scenarios where vTPMs may be associated with a human user, so per the TCG, one should use the privacy-preserving decryption EKs and MakeCredential/ActivateCredential flow. One example is Virtual Desktop Infrastructure (VDI), https://learn.microsoft.com/en-us/azure/virtual-desktop/whats-new#confidential-virtual-machines-and-trusted-launch-virtual-machines-are-now-generally-available-in-azure-virtual-desktop.

Also, some applications (like Keylime) expect a decryption EK. Perhaps, they can bind the decryption EK to the signing EK (using TPM2_Certify instead of MakeCredential/ActivateCredential) and bind the signing EK to the TEE attestation report. This is an additional step though and looks more complex than just using MakeCredential/ActivateCredential.

) -> Result<(), SvsmReqError> {
// Get manifest from the VTPM.
let manifest = vtpm_get_manifest()?;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should check that the requested version of the manifest is 0.

self.ekpub.clone().ok_or_else(SvsmReqError::invalid_request)
}

fn create_ek_rsa2048(&mut self) -> Result<(), SvsmReqError> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we instead have a prepopulation of nvdata such that 0x01c0_0004 gets populated with this template, and we can therefore have a simpler creation process that says to read the template at the NV handle and then create the primary key with empty PCR selection and passwords? This is the "low range" RSA EK template after all.

For Google's keys, we use 0x01c10001 for our AK RSA key template and 0x01c100003 for our AK ECC key template. We can more easily determine which keys we can can cache if we're requesting them by template NV index.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note that we can use the tpm_rs_base type definitions from github.com/tpm-rs/tpm-rs.git to marshal/unmarshal TPM types instead of all this munging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in-review PR is under active review and not yet approved
Projects
None yet
8 participants