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

attestation: use go-sev-guest library #2269

Merged
merged 64 commits into from
Sep 21, 2023
Merged

Conversation

msanft
Copy link
Contributor

@msanft msanft commented Aug 21, 2023

Context

We want to use the go-sev-guest library to have an easily maintainable interface to the verification / validation of SEV-SNP attestation reports. (For now on Azure only due to deviations in the attestation processes of the CSPs)

Proposed change(s)

  • Provide a 1:1-translation of our current custom attestation strategy to a go-sev-guest policy. However, there are checks which a) we currently perform but do not seem to be expressable in a go-sev-guest policy or b) are automatically performed by go-sev-guest but not currently done by us. Below lists all occurances of those cases. -> See the sections below for how our previous checks are covered by which checks from go-sev-guest
  • @reviewers: In addition to carefully reviewing the code, please pay special attention to the checks listed below and if they make sense and are restrictive enough.

Checks we currently do but can't be expressed in go-sev-guest

  • CommittedTCB >= TCB specified in Config:
    if !report.CommittedTCB.isVersion(v.config.BootloaderVersion.Value, v.config.TEEVersion.Value, v.config.SNPVersion.Value, v.config.MicrocodeVersion.Value) {
    return &versionError{"COMMITTED_TCB", report.CommittedTCB}
    }

covered by "LaunchTCB >= Minimum LaunchTCB". This implies that the config now defines the minimum launchTCB. This probably makes more sense. Since this was never documented I think we can silently change this. The new verification is more permissive with SVNs that are newer the the configured, which is good (more robust). ~ @derpsteb

fine to remove. This is unnecessarily restrictive. Can't remember why it's there. ~ @derpsteb

we should set PermitProvisionalFirmware to true so this check is kept. I currently don't see a reason why we would want to prevent this. It should improve robustness during firmware upgrades imo. ~ @derpsteb

  • MAA checks depending on EnforcementPolicy set in the Constellation config:
    hasExpectedIDKeyDigest := false
    for _, digest := range v.config.FirmwareSignerConfig.AcceptedKeyDigests {
    if bytes.Equal(digest, report.IDKeyDigest[:]) {
    hasExpectedIDKeyDigest = true
    break
    }
    }
    if !hasExpectedIDKeyDigest {
    switch v.config.FirmwareSignerConfig.EnforcementPolicy {
    case idkeydigest.MAAFallback:
    v.log.Infof(
    "configured idkeydigests %x don't contain reported idkeydigest %x, falling back to MAA validation",
    v.config.FirmwareSignerConfig.AcceptedKeyDigests,
    report.IDKeyDigest[:],
    )
    return v.maa.validateToken(ctx, v.config.FirmwareSignerConfig.MAAURL, maaToken, extraData)
    case idkeydigest.WarnOnly:
    v.log.Warnf(
    "configured idkeydigests %x don't contain reported idkeydigest %x",
    v.config.FirmwareSignerConfig.AcceptedKeyDigests,
    report.IDKeyDigest[:],
    )
    default:
    return &idKeyError{report.IDKeyDigest[:], v.config.FirmwareSignerConfig.AcceptedKeyDigests}
    }
    }

    Might be achievable by ignoring the go-sev-guest IdKey hash check if EnforcementPolicy is MaaFallback or WarnOnly and performing a custom check after. (See current idea of an implementation in the PR)

we need to keep this. ~ @derpsteb
-> @msanft : implement custom check after go-sev-guest validation

  • TCB in VCEK == CommittedTCB
    // validateVCEKExtensions checks that the certificate extension values in cert match the values described in report.
    func validateVCEKExtensions(cert *x509.Certificate, report snpAttestationReport) error {

    This might be replaced by the CurrentTCB >= TCB specified in VCEK check mentioned below.

Re 5.: I agree that this should be replaced with "CurrentTCB >= TCB specified in VCEK". The current check is overly restrictive. ~ @derpsteb

Checks we didn't do before but are automatically done by go-sev-guest

Checklist

  • Add labels (e.g., for changelog category)
  • Is PR title adequate for changelog?
  • Link to Milestone

@netlify
Copy link

netlify bot commented Aug 21, 2023

Deploy Preview for constellation-docs canceled.

Name Link
🔨 Latest commit ed7e78d
🔍 Latest deploy log https://app.netlify.com/sites/constellation-docs/deploys/6501d85e6954e10008896758

Copy link
Member

Choose a reason for hiding this comment

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

Ideally, we can drop all of our own SNP report validation (including VCEK verification) except for MAA and maybe IDKey.

Regarding TCB version checks, @derpsteb and @katexochen should know best if the TCB version checks of the library are good to replace ours.

Regarding IDKey, the implementation may be simpler if we never use the library for it and just keep our current check. What do you think @msanft ?

Copy link
Contributor Author

@msanft msanft Aug 23, 2023

Choose a reason for hiding this comment

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

Ideally, we can drop all of our own SNP report validation (including VCEK verification) except for MAA and maybe IDKey.

Yes, I think this is the main point of adopting the library now.

Regarding IDKey, the implementation may be simpler if we never use the library for it and just keep our current check.

I think so too. Double-checking with the library has no obvious advantages to me while making the code harder to read.

@derpsteb
Copy link
Member

I didn't check the code yet as the pipeline is still failing and this is still a draft.

Regarding the TCB checks.
From "Checks we currently do but can't be expressed in go-sev-guest":
re 1.: fine to remove. covered by "LaunchTCB >= Minimum LaunchTCB". This implies that the config now defines the minimum launchTCB. This probably makes more sense. Since this was never documented I think we can silently change this. The new verification is more permissive with SVNs that are newer the the configured, which is good (more robust).

re 2.: fine to remove. This is unnecessarily restrictive. Can't remember why it's there.

re 3.: we should set PermitProvisionalFirmware to true so this check is kept. I currently don't see a reason why we would want to prevent this. It should improve robustness during firmware upgrades imo.

re 4.: we need to keep this.

Regarding the checks that we gain: seems like a good addition to me. I always read the AMD docs in a way that suggests that the PSP firmware enforces these conditions and that a attestation verifier wouldn't have to check them. But this isn't stated anywhere. Better to have them. 👍

@derpsteb
Copy link
Member

Re 5.: I agree that this should be replaced with "CurrentTCB >= TCB specified in VCEK". The current check is overly restrictive.

@msanft
Copy link
Contributor Author

msanft commented Aug 30, 2023

latest update: Both unit test TestTrustedKeyFromSNP and manual test with an actual cluster report the following error:

verifying SNP attestation: report signature verification error: x509: ECDSA verification failure

of which I don't know why they report it yet. If anyone has ideas to debug this, please let me know.
To reproduce it, just run the corresponding unit test (TestTrustedKeyFromSNP)

This passage in the library produces the error:
https://github.com/google/go-sev-guest/blob/14ac50e9ffcc05cd1d12247b710c65093beedb58/verify/verify.go#L447-L449

@thomasten
Copy link
Member

To me it seems that the report and the vcek just don't match. Please try using the vcek and chain that the issuer is getting from Azure THIM instead of downloading it from AMD.
If this turns out to work, let's discuss pros and cons of both ways.

@msanft
Copy link
Contributor Author

msanft commented Aug 31, 2023

needs google/go-sev-guest#73

@msanft msanft added this to the v2.11.0 milestone Sep 1, 2023
@msanft msanft added the feature This introduces new functionality label Sep 1, 2023
@msanft msanft marked this pull request as ready for review September 1, 2023 07:09
@msanft
Copy link
Contributor Author

msanft commented Sep 1, 2023

One other bug I need to track down:

A test with an actual cluster returns:

Error: init call: rpc error: code = Unavailable desc = connection error: desc = "transport: authentication handshake failed: validating attestation public key: verifying SNP attestation: report signature verification error: x509: ECDSA verification failure"

If I print the report that is being verified in the above trace it works when checking it "manually" in my test environment with the following snippet:

report, err := abi.ReportToProto(testdata.AttestationReport)
if err != nil {
	panic(err)
}

fmt.Println("Report HWID:", hex.EncodeToString(report.GetChipId()))
fmt.Println("TCB level:", kds.DecomposeTCBVersion(kds.TCBVersion(report.GetCurrentTcb())))

attestation, err := verify.GetAttestationFromReport(report, &verify.Options{})
if err != nil {
	panic(err)
}

err = verify.SnpAttestation(attestation, &verify.Options{})
if err != nil {
	panic(err)
}

I assume that either somewhere in the build process, the pseudo-version of go-sev-guest (including our patch) isn't being respected, or I make some silly mistake at another point

@msanft
Copy link
Contributor Author

msanft commented Sep 1, 2023

^ Possibly caused by an indirect dependency on v0.6.1 of go-sev-guest in our hack folder

internal/attestation/azure/snp/validator.go Outdated Show resolved Hide resolved
internal/attestation/azure/snp/validator.go Outdated Show resolved Hide resolved
internal/attestation/azure/snp/validator.go Outdated Show resolved Hide resolved
internal/attestation/azure/snp/validator.go Outdated Show resolved Hide resolved
internal/attestation/azure/snp/validator.go Outdated Show resolved Hide resolved
internal/attestation/azure/snp/validator.go Outdated Show resolved Hide resolved
@msanft
Copy link
Contributor Author

msanft commented Sep 1, 2023

^ Possibly caused by an indirect dependency on v0.6.1 of go-sev-guest in our hack folder

Correcting this fixed it.

@msanft msanft requested a review from malt3 as a code owner September 1, 2023 09:44
@msanft msanft force-pushed the feat/attestation/go-sev-attestation branch from feb3a83 to e40fc65 Compare September 1, 2023 10:16
@github-actions
Copy link
Contributor

github-actions bot commented Sep 1, 2023

Coverage report

Package Old New Trend
cli/internal/cmd 55.10% 55.10% ↔️
internal/attestation/azure/snp 10.60% 46.90% ↗️

@msanft
Copy link
Contributor Author

msanft commented Sep 1, 2023

We also probably want to use the AMD root certificate from the config instead of the one embedded in the go-sev-guest library.

@msanft msanft force-pushed the feat/attestation/go-sev-attestation branch from 8018765 to f482515 Compare September 6, 2023 06:37
@msanft msanft force-pushed the feat/attestation/go-sev-attestation branch from 68db255 to 474367c Compare September 13, 2023 08:10
Signed-off-by: Moritz Sanft <[email protected]>
cli/internal/cmd/verify.go Outdated Show resolved Hide resolved
cli/internal/cmd/verify.go Outdated Show resolved Hide resolved
@msanft msanft force-pushed the feat/attestation/go-sev-attestation branch from 0c8ed62 to 85515c2 Compare September 13, 2023 15:37
Copy link
Member

@thomasten thomasten left a comment

Choose a reason for hiding this comment

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

Thanks!

Copy link
Member

@derpsteb derpsteb left a comment

Choose a reason for hiding this comment

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

LGTM. I didn't do another deep dive as I am unde the impression Thomas and Paul already did that. I think it's great that you extended the unittests.

@msanft msanft requested a review from 3u13r September 20, 2023 10:24
Copy link
Member

@3u13r 3u13r left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -77,10 +77,10 @@ require (
github.com/go-playground/universal-translator v0.18.1
github.com/go-playground/validator/v10 v10.14.1
github.com/golang-jwt/jwt/v5 v5.0.0
github.com/google/go-sev-guest v0.6.1
github.com/google/go-sev-guest v0.8.0
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
github.com/google/go-sev-guest v0.8.0
github.com/google/go-sev-guest v0.9.0

v0.9.0 was released 2 days ago

@msanft
Copy link
Contributor Author

msanft commented Sep 21, 2023

One last E2E run, merging afterwards if successful

@msanft msanft merged commit 3ed001f into main Sep 21, 2023
12 checks passed
@msanft msanft deleted the feat/attestation/go-sev-attestation branch September 21, 2023 12:08
derpsteb pushed a commit that referenced this pull request Oct 2, 2023
* wip: switch to  attestation

* add extra comments

Signed-off-by: Moritz Sanft <[email protected]>

* MAA checks

Signed-off-by: Moritz Sanft <[email protected]>

* use provided functions to parse report / cert chain

Signed-off-by: Moritz Sanft <[email protected]>

* replace `CommitedTCB` check with `LaunchTCB` check

Signed-off-by: Moritz Sanft <[email protected]>

* remove debug check

Signed-off-by: Moritz Sanft <[email protected]>

* remove `LaunchTCB` == `CommitedTCB` check

Signed-off-by: Moritz Sanft <[email protected]>

* custom IdKeyDigests check

Signed-off-by: Moritz Sanft <[email protected]>

* basic test of report parsing from instance info

Signed-off-by: Moritz Sanft <[email protected]>

* retrieve VCEK from AMD KDS

Signed-off-by: Moritz Sanft <[email protected]>

* remove VCEK from `azureInstanceInfo`

Signed-off-by: Moritz Sanft <[email protected]>

* use `go-sev-guest` TCB version type

Signed-off-by: Moritz Sanft <[email protected]>

* fix validation parsing test

Signed-off-by: Moritz Sanft <[email protected]>

* fix error message

* fix comment

Signed-off-by: Moritz Sanft <[email protected]>

* remove certificate chain from `instanceInfo`

Signed-off-by: Moritz Sanft <[email protected]>

* add test for idkeydigest check

Signed-off-by: Moritz Sanft <[email protected]>

* update buildfiles

Signed-off-by: Moritz Sanft <[email protected]>

* wip: update tests

Signed-off-by: Moritz Sanft <[email protected]>

* update buildfiles

Signed-off-by: Moritz Sanft <[email protected]>

* [remove] debug prints

Signed-off-by: Moritz Sanft <[email protected]>

* wip: fix tests

Signed-off-by: Moritz Sanft <[email protected]>

* wip: fix tests

Signed-off-by: Moritz Sanft <[email protected]>

* fix tests, do some clean-up

Signed-off-by: Moritz Sanft <[email protected]>

* add test case for fetching error

Signed-off-by: Moritz Sanft <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Daniel Weiße <[email protected]>

* correct `hack` dependency

Signed-off-by: Moritz Sanft <[email protected]>

* fix id key check

Signed-off-by: Moritz Sanft <[email protected]>

* [remove] comment out wip unit tests

Signed-off-by: Moritz Sanft <[email protected]>

* add missing newline

Signed-off-by: Moritz Sanft <[email protected]>

* switch to released version of `go-sev-guest`

Signed-off-by: Moritz Sanft <[email protected]>

* add constructor test

Signed-off-by: Moritz Sanft <[email protected]>

* add VMPL check

Signed-off-by: Moritz Sanft <[email protected]>

* add test assertions

Signed-off-by: Moritz Sanft <[email protected]>

* update buildfiles

Signed-off-by: Moritz Sanft <[email protected]>

* switch to pseudoversion

Signed-off-by: Moritz Sanft <[email protected]>

* use fork with windows fix

Signed-off-by: Moritz Sanft <[email protected]>

* fix linter checks

Signed-off-by: Moritz Sanft <[email protected]>

* use data from THIM

Signed-off-by: Moritz Sanft <[email protected]>

* update embeds

Signed-off-by: Moritz Sanft <[email protected]>

* verify against ARK in config

Signed-off-by: Moritz Sanft <[email protected]>

* invalid ASK

Signed-off-by: Moritz Sanft <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: 3u13r <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: 3u13r <[email protected]>

* nits

Signed-off-by: Moritz Sanft <[email protected]>

* remove unnecessary checks

Signed-off-by: Moritz Sanft <[email protected]>

* refactoring

Signed-off-by: Moritz Sanft <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Thomas Tendyck <[email protected]>

* use upstream library with pseudoversion

Signed-off-by: Moritz Sanft <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Paul Meyer <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Paul Meyer <[email protected]>

* Update internal/attestation/azure/snp/validator.go

Co-authored-by: Paul Meyer <[email protected]>

* simplify control flow

Signed-off-by: Moritz Sanft <[email protected]>

* fix return error

Signed-off-by: Moritz Sanft <[email protected]>

* fix VCEK test

Signed-off-by: Moritz Sanft <[email protected]>

* tidy

Signed-off-by: Moritz Sanft <[email protected]>

* revert unintentional changes

Signed-off-by: Moritz Sanft <[email protected]>

* use new upstream release

Signed-off-by: Moritz Sanft <[email protected]>

* fix removed AuthorKeyEn field

Signed-off-by: Moritz Sanft <[email protected]>

* fix verification report printing

Signed-off-by: Moritz Sanft <[email protected]>

---------

Signed-off-by: Moritz Sanft <[email protected]>
Co-authored-by: Daniel Weiße <[email protected]>
Co-authored-by: Thomas Tendyck <[email protected]>
Co-authored-by: 3u13r <[email protected]>
Co-authored-by: Paul Meyer <[email protected]>
@malt3 malt3 added no changelog Change won't be listed in release changelog and removed feature This introduces new functionality labels Oct 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no changelog Change won't be listed in release changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants