Git Product home page Git Product logo

go-sev-guest's Introduction

SEV Guest

This project offers libraries for a simple wrapper around the /dev/sev-guest device in Linux, as well as a library for attestation verification of fundamental components of an attestation report.

This project is split into two complementary roles. The first role is producing an attestation report, and the second is checking an attestation report. The client library produces reports, the verify library verifies reports' signatures and key certificates, and the validate library checks non-signature report fields against a user-provided policy.

client

This library should be used within the confidential workload to collect an attestation report along with requisite certificates.

Your main interactions with it will be to open the device, get an attestation report with your provided 64 bytes of user data (typically a nonce or a hash of a public key), and then close the device. For convenience, the attestation with its associated certificates can be collected in a wire-transmittable protocol buffer format.

func OpenDevice() (*LinuxDevice, error)

This function creates a file descriptor to the /dev/sev-guest device and returns an object that has methods encapsulating commands to the device. When done, remember to Close() the device.

func GetExtendedReport(d Device, reportData [64]byte) (*pb.Attestation, error)

This function takes an object implementing the Device interface (e.g., a LinuxDevice) and returns the protocol buffer representation of the attestation report and associated certificates. The report will be associated with VM privilege level 0. You can provide a different privilege level as the third argument to GetExtendedReportAtVmpl.

You can use GetRawExtendedReport or GetRawExtendedReportAtVmpl to get the AMD SEV-SNP API formatted report and certificate table, or just GetReport, GetReportAtVmpl, GetRawReport, or GetRawReportAtVmpl to avoid fetching the certificate table.

func GetDerivedKeyAcknowledgingItsLimitations(d Device, request *SnpDerivedKeyReq) ([]byte, error)

This function uses the /dev/sev-guest command for requesting a key derived from data that is measured at VM launch time, with the additional ability to continue to generate the same key as at earlier TCB and GuestSVN values.

This function's name is selected to discourage its use in a Cloud setting. See LIMITATIONS.md.

func (d Device) Close() error

Closes the device.

func (d Device) Product() *spb.SevProduct

Returns a representation of CPU info relevant to the AMD SEV product version.

verify

This library will check the signature and basic well-formedness properties of an attestation report and certificate chain. The requirements for report well-formedness comes from the AMD SEV-SNP API specification, and the requirements for certificate well-formedness come from the AMD Key Distribution Service (KDS) specification.

This library embeds AMD's root and SEV intermediate keys (AMD source) for the KDS product_name=Milan cert_chain in the AMD SEV certificate format to cross check against any certificate chain that it's sent. The SEV certificate format is defined in an appendix of the AMD SEV API specification.

func SnpAttestation(attestation *spb.Attestation, options *Options) error

This function verifies that the attestation has a valid signature and certificate chain, and optionally checks the certificate revocation list (CRL). At time of writing, the CRL is empty. From discussions with AMD, we expect the CRL to never contain a VCEK or ARK, and only in a very rare circumstance contain the ASK (intermediate signing key). The default option is to not check the CRL.

Example expected invocation:

verify.SnpAttestation(myAttestation, verify.DefaultOptions())

Options type

This type contains three fields:

  • CheckRevocations bool: if true, then SnpAttestation will download the certificate revocation list (CRL) and check for revocations.
  • Getter HTTPSGetter: must be non-nil if CheckRevocations is true.
  • TrustedRoots map[string][]*AMDRootCerts: if nil, uses the library's embedded certificates. Maps a product name to all allowed root certifications for that product (e.g., Milan).

The HTTPSGetter interface consists of a single method Get(url string) ([]byte, error) that should return the body of the HTTPS response.

AMDRootCerts type

This type has 6 fields, the first 3 of which are mandatory:

  • Product string: the name of the product this bundle is for (e.g., "Milan").
  • AskX509 *x509.Certificate: an X.509 representation of the AMD SEV Signer intermediate key (ASK)'s certificate.
  • ArkX509 *x509.Certificate: an X.509 representation of the AMD SEV Root key (ARK)'s certificate.
  • AskSev *abi.AskCert: if non-nil, will cross-check with AskX509. Represents the information present in the AMD SEV certificate format for the ASK.
  • ArkSev *abi.AskCert: if non-nil, will cross-check with ArkX509. Represents the information present in the AMD SEV certificate format for the ARK.
  • CRL *x509.RevocationList: the certificate revocation list signed by the ARK. Will be populated if SnpAttestation is called with CheckRevocations: true.

validate

This library checks fields of an attestation report according to a policy provided by the user. The policy is represented with the Options type, which specifies which fields to check, what their exact values should be, or whether the field should be within a given bound.

func SnpAttestation(attestation *spb.Attestation, options *Options) error

Not to be confused with verify.SnpAttestation for checking certificates and signatures, the validate.SnpAttestation function is more open-ended about what reports are acceptable. It's up to the user of the library to set the parameters of acceptable values with the options argument.

The Option type

An instance of the Option type is a simple validation policy for non-signature fields of an attestation report.

The fields that either can be skipped or must match the given value exactly are:

  • ReportData for the REPORT_DATA field
  • HostData for the HOST_DATA field
  • ImageID for the IMAGE_ID field
  • FamilyID for the FAMILY_ID field
  • ReportID for the FEPORT_ID field
  • ReportIDMA for the REPORT_ID_MA field
  • Measurement for the MEASUREMENT field

The fields that provide a minimum acceptable value are:

  • MinimumBuild for the minimum build number for the AMD secure processor firmware.
  • RequireAuthorKey for whether AUTHOR_KEY_EN can be 0 or 1 (false), or just 1 (true).
  • RequireIDBlock for whether IDBlock fields can be anything (false) or must validate (true) against the Trusted family of options.

The fields that provide a maximum acceptable value are:

  • GuestPolicy: each true field of GuestPolicy is permission for an attestation report's POLICY corresponding bit to be set.
  • PermitProvisionalFirmware: if false, the minimum TCB and API values are equal to the reported values. If true, the maximum TCB and API values are the reported values.
  • PlatformInfo: each true field of PlatformInfo is permission for the attestation report's PLATFORM_INFO corresponding bit to be set.

Finally, the fields for trusting IDBlock signers. Both ID keys and Author keys have x.509 certificate and SEV-SNP hash format inputs for usability. The x.509 certificates will be converted to their corresponding SEV-SNP API format and appended to the corresponding KeyHashes array. Only certificates for ECSDA P-384 public keys are considered. All other certificates are quietly ignored.

  • TrustedAuthorKeys: x.509 certificates for author keys that are trusted to endorse an attestation report. If the report's author key is trusted, then the identity key it signed is implicitly trusted.
  • TrustedAuthorKeyHashes: An array of SHA-384 hashes of the SEV-SNP API format for an ECDSA public key. Has the same validation behavior as TrustedAuthorKeys.
  • TrustedIDKeys: x.509 certificates for identity keys that are trusted to endorse an attestation report. If the report's identity key is explicitly trusted, then its author key does not need to be trusted.
  • TrustedIDKeyHashes: An array of SHA-384 hashes of the SEV-SNP API format for an ECDSA public key. Has the same validation behavior as TrustedIDKeys.
  • Product: A replacement or supplemental SevProduct value to use for a given attestation or report. If nil, uses the information present in the attestation proto, or provides a default Milan-B0 value.

License

go-sev-guest is released under the Apache 2.0 license.

Copyright 2022 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Links

Disclaimers

This is not an officially supported Google product.

go-sev-guest's People

Contributors

datosh avatar deeglaze avatar derpsteb avatar laisky avatar marc-orr avatar msanft avatar wdsun1008 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-sev-guest's Issues

AMD KDS is queried with wrong TCB version

The library currently uses the CurrentTCB values of a report when querying the AMD KDS for the VCEK certificate, as opposed to the AMD SEV-SNP ABI spec, which says:

The firmware maintains a TCB_VERSION called the ReportedTcb. ReportedTcb is used to derive
the VCEK that signs the attestation report.

vcekURL := kds.VCEKCertURL(product, report.GetChipId(), kds.TCBVersion(report.GetCurrentTcb()))

When ReportedTCB != CurrentTCB, this results in a signature verification error when checking the report's signature with the VCEK certificate's public key here:

if err := vcek.CheckSignature(x509.ECDSAWithSHA384, abi.SignedComponent(report), der); err != nil {
return fmt.Errorf("report signature verification error: %v", err)

Remove KDS clock skew when KDS back-dates certs

I reported the issue that #44 works around to AMD. They said they'll change KDS's behavior, but it may take a few months given everything else going on. Once the back-dating is in, we shouldn't need the skew behavior in PR44. We should keep the API signature changes though.

Malfunctioning SEV-SNP device results in nil-pointer exception

Hey there!

If abi.SevProduct() is called in a guest with a malfunctioning SEV-SNP device, this results in the cpuid() call to error with a nil-pointer exception as follows (line numbers based on v0.8.0 this library):

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x411ded9]
goroutine 170 [running]:
github.com/google/go-sev-guest/abi.SevProduct()
external/com_github_google_go_sev_guest/abi/abi.go:810 +0x19
github.com/google/go-sev-guest/client.(*LinuxDevice).Product(0xc00068c580?)
external/com_github_google_go_sev_guest/client/client_linux.go:124 +0xf
github.com/google/go-sev-guest/client.GetExtendedReportAtVmpl({0x15728d0, 0xc000c59a10}, {0xca, 0xcb, 0x75, 0x2, 0xfd, 0x96, 0x8, 0x32, ...}, ...)
external/com_github_google_go_sev_guest/client/client.go:180 +0xf9
github.com/google/go-sev-guest/client.GetExtendedReport(...)
external/com_github_google_go_sev_guest/client/client.go:186

While I still need to figure out what in cpuid exactly causes this failure (haven't got to read into the spec of CPUID yet), I think an easy approach would be to recover from the panic and return an error in that case that could be passed on to the caller, which would lead to an early failure and thus be my personal favorite. Otherwise, falling back to the DefaultSevProduct might be an option too if the function's signature should be kept as is.

Feel free to let me know your thoughts on this and I will be happy to implement it!

Is there a plan to support the legacy SEV report handling?

Hi there,

In addition to SEV-SNP, the legacy SEV also produces a guest report, even though it's coming from the hypervisor. The report from the legacy SEV can be obtained from ATTESTATION ioctl from the hypervisor, and it contains a signature from PEK. Is there a plan to support the validate and verify for the legacy SEV report in this project?

Global certificate cache cause flaky tests

In the trust package, there is a certificate cache in the global state:

productCertCache map[string]*ProductCerts

This causes tests with multiple test cases to be flaky, as potential errors are not reached if a successful request was cached before and ClearProductCertCache() was not called. The certificate cache should rather be scoped to an object, implementing GetProductChain() as a method. If you are fine with this, I will implement it.

Remove self-throttling after 6.1 incorporates x86/urgent fixes

Liunx kernel 6.1 incorporates @pgonda's IV reuse crypto fix, which deletes the VMPCK when the host VMM returns any error. The x86/urgent follow-up to retry commands when throttled to avoid deleting the VMPCK is not in 6.1 yet.

While not a panacea, we can self-throttle in this library as a workaround until that throttling awareness fix is in.

TCB validation logic looks flawed

	min, err := kds.ComposeTCBParts(options.MinimumTCB)
	if err != nil {
		return fmt.Errorf("option MinimumTCB error: %v", err)
	}
	if kds.TCBVersion(report.GetCurrentTcb()) < min {
		return fmt.Errorf("firmware's current TCB %x is less than required %x",
			report.GetCurrentTcb(), min)
	}

This treats the TCB_VERSION as a single number instead of an array of lower bounds for each kind of SPL. This means the accidental position of one SPL can mask a version mismatch in a lower order version. For example, [2, 1] is greater than [1, 3], but you don't want to allow a lower SPL for the number on the right because the number on the left is higher.

We should treat the minimum TCB_VERSION as a piecewise minimum.

generating ID_BLOCK

do we have a tool to generate an id block?

unfortunately i can't really figure out the structure from the sev doc.

as far as i understand this

r.IdKeyDigest = clone(data[0xE0:0x110])

is the result of secure processor already doing its thing with the idblock and not the input format

Verify guest report

How verify function needs to be run by having the binary report and which files should be provided, can you provide the example command?

Build fails on GOARCH=386

For some reason, github.com/google/go-tpm-tools depends on this package and causes build to fail on 32bits architectures:

../../go/pkg/mod/github.com/google/[email protected]/abi/amdsp.go:105:53: cannot use 0x100000000 (untyped int constant 4294967296) as SevFirmwareStatus value in constant declaration (overflows)

This is blocking the whole build and is a bit problematic.

A way to fix this is to modify https://github.com/google/go-sev-guest/blob/main/abi/amdsp.go#L21C1-L21C27

type SevFirmwareStatus int

To

type SevFirmwareStatus int64

I tested with GOARCH=386 go build ./... and confirmed there are no other issues preventing building this repository.

Improve error when fetching certificates

Hey ๐Ÿ‘‹

I was trying to use 0.7.0 in order to verify an SNP attestation report on AWS. I know now that VLEK is used instead of VCEK and found #67. I will comment there as well once I played around with it :)

While using 0.7.0 I got a somewhat confusing error. The error I got was timeout while downloading the VCEK. So I wasted quite a bit of time debugging (non existing network issues). What was actually happening is that the library was trying to fetch https://kdsintf.amd.com/vcek/v1/Milan/00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000?blSPL=3&teeSPL=0&snpSPL=10&ucodeSPL=207 and AMD correctly responded with 404. Currently everything >300 is handled the same. I think we could narrow down the status code a bit and / or inform users about the underlying error while retrying.

AMD seems to honor the status codes documented in Chapter 4.1. So we could test for HTTP 429 and error early otherwise?

Let me know what you think. I am open to put in a PR as well.

ProductName: Unknown

Hi,there.

d.Product() returns product name SevProduct_SEV_PRODUCT_UNKNOWN while I'm using model Milan for sure. Do i need to run a command like snphost import to set CPU id value for my guests?

Certificate chain gets overwritten when attesting

Currently, GetAttestationFromReport doesn't allow specifying a certificate chain, and fillInAttestation is private. Does this have any particular reason? Otherwise, one is not allowed to specify a partially present certificate chain (e.g. only ARK) and have the rest filled in. While changing adding an additional parameter to GetAttestationFromReport would be a breaking change, an additional method could be added (e.g. GetAttestationFromReportAndCertChain) to take both a report and a cert chain and fill in only the missing certificates, or the fillInAttestation method could be made public.

// GetAttestationFromReport uses AMD's Key Distribution Service (KDS) to download the certificate
// chain for the VCEK that supposedly signed the given report, and returns the Attestation
// representation of their combination. If getter is nil, uses Golang's http.Get.
func GetAttestationFromReport(report *spb.Report, options *Options) (*spb.Attestation, error) {
result := &spb.Attestation{
Report: report,
CertificateChain: &spb.CertificateChain{},
}
if err := fillInAttestation(result, options); err != nil {
return nil, err
}
return result, nil
}

Distribute binaries with new releases

We should be able to use Github actions to build the attest/check CLI tools and include them in their own release tarball. While it's not a signed package in a Google-endorsed package repository, it's something to reduce the cost of adoption.

Deeply nested SNP Report type

Hey,

currently the Report type does not parse the nested types it includes. For example the TCB versions included are parsed as uint64 and require another function to parse the included data from the field.

How do you feel about accepting a contribution that would change the existing Report type to a nested type that includes subtypes like TCBParts? It seems to me like this would change the layout of the lib in a few places, hence the question.

Best,
Otto

Dependency glog leaks go routine

Using go-tpm-tools/client introduces go-sev-guest/abi as dependency. This in turn depends on glog which leaks as shown below. Sadly, glog is also unmaintained, so there's no way for us to provide a fix. Is it possible to replace glog with klog? The interface seems to be similar.

goleak: Errors on successful test run: found unexpected goroutines:
[Goroutine 19 in state chan receive, with github.com/golang/glog.(*loggingT).flushDaemon on top of the stack:
goroutine 19 [chan receive]:
github.com/golang/glog.(*loggingT).flushDaemon(0x0?)
	/home/euler/go/pkg/mod/github.com/golang/[email protected]/glog.go:882 +0x6a
created by github.com/golang/glog.init.0
	/home/euler/go/pkg/mod/github.com/golang/[email protected]/glog.go:410 +0x1bf

error querying certificate length: invalid argument

Im getting the below error when trying to obtain the report for the device using GetExtendedReport. What could be causing this?

error querying certificate length: invalid argument

So far Ive done client.OpenDevice() under the /dev/sev path to get the device. Then tried to call client.GetExtendedReport(device, reportData) which returns the above error.

About func GetExtendedReport()

Hi @deeglaze, I'm currently trying to embed this repo to my snp attestation workflow. When using GetExtendedReport(), it seems that i should first set ark/ask/vcek on host platform. So I have the following questions:

  1. How to get vcek on host? Since chip_id and tcb_version are required to derive vcek from amd sev kds. As far as I know, they are presented in attestation report, but the report cannot be directly accessed by host.
  2. How to set ark/ask/vcek on host? Is there any tool available now?(I found a rust repo snphost)

Implement VLEK support

The VLEK key type was added in the API revision of November 2022 (primarily an AWS-requested feature), but we don't have proper support for the key type in our KDS cert validation or in the change to the 32-bits that include AUTHOR_KEY_EN. This issue should be closed when we have fake SEV device VLEK support, unit tests, cert chain proto representation of the cert type, and ensure that VLEK/VCEK keys are only acceptable for report types that embed that key type in the report.

While we could pun the VCEK field with the VLEK, it's not the cleanest solution. I think I'd prefer separate fields in the certificate chain representation.

Product unclear from attestation report

When there are more SEV-SNP products than just "Milan", we'll need a way to determine what kind of machine produced an attestation report. This can either be deduced from the guest context at collection time through CPUID, an a priori option at verification time, or some unknown third option where we can determine the product from attestation report contents itself. This will be useful for collecting certificates from the KDS using just an attestation report.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.