snp: ensure we never use ARK supplied by Issuer (#3025)

This commit is contained in:
Daniel Weiße 2024-05-13 20:43:20 +02:00 committed by Markus Rudy
parent d9dec5caa6
commit ec87c2ee06
3 changed files with 33 additions and 35 deletions

View file

@ -8,11 +8,11 @@ go_library(
visibility = ["//:__subpackages__"],
deps = [
"//internal/attestation",
"//internal/constants",
"@com_github_google_go_sev_guest//abi",
"@com_github_google_go_sev_guest//kds",
"@com_github_google_go_sev_guest//proto/sevsnp",
"@com_github_google_go_sev_guest//verify/trust",
"@com_github_google_go_tpm_tools//proto/attest",
],
)

View file

@ -15,11 +15,11 @@ import (
"fmt"
"github.com/edgelesssys/constellation/v2/internal/attestation"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/google/go-sev-guest/abi"
"github.com/google/go-sev-guest/kds"
spb "github.com/google/go-sev-guest/proto/sevsnp"
"github.com/google/go-sev-guest/verify/trust"
"github.com/google/go-tpm-tools/proto/attest"
)
// Product returns the SEV product info currently supported by Constellation's SNP attestation.
@ -39,6 +39,7 @@ type InstanceInfo struct {
// AttestationReport is the attestation report from the vTPM (NVRAM) of the CVM.
AttestationReport []byte
Azure *AzureInstanceInfo
GCP *attest.GCEInstanceInfo
}
// AzureInstanceInfo contains Azure specific information related to SNP attestation.
@ -95,7 +96,7 @@ func (a *InstanceInfo) addReportSigner(att *spb.Attestation, report *spb.Report,
// AttestationWithCerts returns a formatted version of the attestation report and its certificates from the instanceInfo.
// Certificates are retrieved in the following precedence:
// 1. ASK or ARK from issuer. On Azure: THIM. One AWS: not prefilled.
// 1. ASK from issuer. On Azure: THIM. One AWS: not prefilled. (Go to option 2) On GCP: prefilled.
// 2. ASK or ARK from fallbackCerts.
// 3. ASK or ARK from AMD KDS.
func (a *InstanceInfo) AttestationWithCerts(getter trust.HTTPSGetter,
@ -120,30 +121,28 @@ func (a *InstanceInfo) AttestationWithCerts(getter trust.HTTPSGetter,
return nil, fmt.Errorf("adding report signer: %w", err)
}
// If the certificate chain from THIM is present, parse it and format it.
ask, ark, err := a.ParseCertChain()
// If a certificate chain was pre-fetched by the Issuer, parse it and format it.
// Make sure to only use the ask, since using an ark from the Issuer would invalidate security guarantees.
ask, _, err := a.ParseCertChain()
if err != nil {
logger.Warn(fmt.Sprintf("Error parsing certificate chain: %v", err))
}
if ask != nil {
logger.Info("Using ASK certificate from Azure THIM")
logger.Info("Using ASK certificate from pre-fetched certificate chain")
att.CertificateChain.AskCert = ask.Raw
}
if ark != nil {
logger.Info("Using ARK certificate from Azure THIM")
att.CertificateChain.ArkCert = ark.Raw
}
// If a cached ASK or an ARK from the Constellation config is present, use it.
if att.CertificateChain.AskCert == nil && fallbackCerts.ask != nil {
logger.Info("Using cached ASK certificate")
att.CertificateChain.AskCert = fallbackCerts.ask.Raw
}
if att.CertificateChain.ArkCert == nil && fallbackCerts.ark != nil {
logger.Info(fmt.Sprintf("Using ARK certificate from %s", constants.ConfigFilename))
if fallbackCerts.ark != nil {
logger.Info("Using cached ARK certificate")
att.CertificateChain.ArkCert = fallbackCerts.ark.Raw
}
// Otherwise, retrieve it from AMD KDS.
// Otherwise, retrieve missing certificates from AMD KDS.
if att.CertificateChain.AskCert == nil || att.CertificateChain.ArkCert == nil {
logger.Info(fmt.Sprintf(
"Certificate chain not fully present (ARK present: %t, ASK present: %t), falling back to retrieving it from AMD KDS",

View file

@ -149,12 +149,24 @@ func TestAttestationWithCerts(t *testing.T) {
wantErr bool
}{
"success": {
report: defaultReport,
idkeydigest: "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1",
reportSigner: testdata.AzureThimVCEK,
certChain: testdata.CertChain,
fallbackCerts: CertificateChain{ark: testdataArk},
expectedArk: testdataArk,
expectedAsk: testdataAsk,
getter: newStubHTTPSGetter(&urlResponseMatcher{}, nil),
},
"ark only in pre-fetched cert-chain": {
report: defaultReport,
idkeydigest: "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1",
reportSigner: testdata.AzureThimVCEK,
certChain: testdata.CertChain,
expectedArk: testdataArk,
expectedAsk: testdataAsk,
getter: newStubHTTPSGetter(nil, assert.AnError),
wantErr: true,
},
"vlek success": {
report: vlekReport,
@ -173,9 +185,10 @@ func TestAttestationWithCerts(t *testing.T) {
),
},
"retrieve vcek": {
report: defaultReport,
idkeydigest: "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1",
certChain: testdata.CertChain,
report: defaultReport,
idkeydigest: "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1",
certChain: testdata.CertChain,
fallbackCerts: CertificateChain{ark: testdataArk},
getter: newStubHTTPSGetter(
&urlResponseMatcher{
vcekResponse: testdata.AmdKdsVCEK,
@ -205,25 +218,9 @@ func TestAttestationWithCerts(t *testing.T) {
idkeydigest: "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1",
reportSigner: testdata.AzureThimVCEK,
fallbackCerts: NewCertificateChain(exampleCert, exampleCert),
getter: newStubHTTPSGetter(
&urlResponseMatcher{},
nil,
),
expectedArk: exampleCert,
expectedAsk: exampleCert,
},
"use certchain with fallback certs": {
report: defaultReport,
idkeydigest: "57e229e0ffe5fa92d0faddff6cae0e61c926fc9ef9afd20a8b8cfcf7129db9338cbe5bf3f6987733a2bf65d06dc38fc1",
certChain: testdata.CertChain,
reportSigner: testdata.AzureThimVCEK,
fallbackCerts: NewCertificateChain(&x509.Certificate{}, &x509.Certificate{}),
getter: newStubHTTPSGetter(
&urlResponseMatcher{},
nil,
),
expectedArk: testdataArk,
expectedAsk: testdataAsk,
getter: newStubHTTPSGetter(&urlResponseMatcher{}, nil),
expectedArk: exampleCert,
expectedAsk: exampleCert,
},
"retrieve vcek and certchain": {
report: defaultReport,
@ -242,10 +239,12 @@ func TestAttestationWithCerts(t *testing.T) {
},
"report too short": {
report: defaultReport[:len(defaultReport)-100],
getter: newStubHTTPSGetter(nil, assert.AnError),
wantErr: true,
},
"corrupted report": {
report: defaultReport[10 : len(defaultReport)-10],
getter: newStubHTTPSGetter(nil, assert.AnError),
wantErr: true,
},
"certificate fetch error": {