Skip to content

Commit

Permalink
fixup! attestation: use SNP-based attestation for AWS SNP
Browse files Browse the repository at this point in the history
  • Loading branch information
derpsteb committed Nov 20, 2023
1 parent f25a4c0 commit c22c3fd
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 22 deletions.
2 changes: 1 addition & 1 deletion internal/attestation/aws/snp/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func newDecodeError(err error) *decodeError {
}

func (e *decodeError) Error() string {
return fmt.Sprintf("error decoding public key: %v", e.inner)
return fmt.Sprintf("decoding public key: %v", e.inner)
}

func (e *decodeError) Unwrap() error {
Expand Down
4 changes: 2 additions & 2 deletions internal/attestation/aws/snp/issuer.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func NewIssuer(log attestation.Logger) *Issuer {
func getAttestationKey(tpm io.ReadWriter) (*tpmclient.Key, error) {
tpmAk, err := client.AttestationKeyRSA(tpm)
if err != nil {
return nil, fmt.Errorf("error creating RSA Endorsement key: %w", err)
return nil, fmt.Errorf("creating RSA Endorsement key: %w", err)
}

return tpmAk, nil
Expand All @@ -60,7 +60,7 @@ func getAttestationKey(tpm io.ReadWriter) (*tpmclient.Key, error) {
func getInstanceInfo(_ context.Context, tpm io.ReadWriteCloser, _ []byte) ([]byte, error) {
tpmAk, err := client.AttestationKeyRSA(tpm)
if err != nil {
return nil, fmt.Errorf("error creating RSA Endorsement key: %w", err)
return nil, fmt.Errorf("creating RSA Endorsement key: %w", err)
}

encoded, err := x509.MarshalPKIXPublicKey(tpmAk.PublicKey())
Expand Down
5 changes: 4 additions & 1 deletion internal/attestation/aws/snp/testdata/testdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import _ "embed"
//go:embed report.txt
var SNPReport string

// Valid VLEK for SNPReport.
// AKDigest holds the AK digest embedded in SNPReport.REPORT_DATA.
const AKDigest = "032635613c8e331fa29e096371910fe6a1f69383dda02c9461400a70b66d87a3da5dd863002522be43afc34f2c233989bd6e401e351d10d7cc800d6f5dfcf019"

// VLEK for SNPReport.
//
//go:embed vlek.pem
var VLEK []byte
Expand Down
9 changes: 7 additions & 2 deletions internal/attestation/aws/snp/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,13 @@ func sha512sum(key crypto.PublicKey) ([64]byte, error) {
return sha512.Sum512(pub), nil
}

// Validate a given SNP report.
// snpReportValidator validates a given SNP report.
type snpReportValidator interface {
validate(attestation vtpm.AttestationDocument, ask *x509.Certificate, ark *x509.Certificate, ak [64]byte, config *config.AWSSEVSNP, log attestation.Logger) error
}

// Validation logic for the AWS SNP implementation.
// awsValidator implements the validation for AWS SNP attestation.
// The properties exist for unittesting.
type awsValidator struct {
verifier reportVerifier
validator reportValidator
Expand Down Expand Up @@ -169,6 +170,10 @@ func (a *awsValidator) validate(attestation vtpm.AttestationDocument, ask *x509.
},
VMPL: new(int), // Checks that Virtual Machine Privilege Level (VMPL) is 0.
// This checks that the reported LaunchTCB version is equal or greater than the minimum specified in the config.
// We don't specify Options.MinimumTCB as it only restricts the allowed TCB for Current_ and Reported_TCB.
// Because we allow Options.ProvisionalFirmware, there is not security gained in also checking Current_ and Reported_TCB.
// We always have to check Launch_TCB as this value indicated the smallest TCB version a VM has seen during
// it's lifetime.
MinimumLaunchTCB: kds.TCBParts{
BlSpl: config.BootloaderVersion.Value, // Bootloader
TeeSpl: config.TEEVersion.Value, // TEE (Secure OS)
Expand Down
17 changes: 5 additions & 12 deletions internal/attestation/aws/snp/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,8 @@ import (
"github.com/stretchr/testify/require"
)

const (
// validAKDigest is the AK hash of the public key embedded in 'reportValid'.
validAKDigest = "032635613c8e331fa29e096371910fe6a1f69383dda02c9461400a70b66d87a3da5dd863002522be43afc34f2c233989bd6e401e351d10d7cc800d6f5dfcf019"
)

func TestGetTrustedKey(t *testing.T) {
validator := &Validator{ask: nil, ark: nil, reportValidator: stubawsValidator{}}
validator := func() *Validator { return &Validator{ask: nil, ark: nil, reportValidator: stubawsValidator{}} }
testCases := map[string]struct {
akPub []byte
info []byte
Expand Down Expand Up @@ -71,7 +66,7 @@ func TestGetTrustedKey(t *testing.T) {
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
assert := assert.New(t)
out, err := validator.getTrustedKey(
out, err := validator().getTrustedKey(
context.Background(),
vtpm.AttestationDocument{
Attestation: &attest.Attestation{
Expand Down Expand Up @@ -105,8 +100,6 @@ func TestValidateSNPReport(t *testing.T) {
certs, err := loadCerts(testdata.CertChain)
require.NoError(err)
ark := certs[1]
certs, err = loadCerts(testdata.CertChain)
require.NoError(err)
ask := certs[0]

// reportTransformer unpacks the base64 encoded report, applies the given transformations and re-encodes it.
Expand All @@ -130,13 +123,13 @@ func TestValidateSNPReport(t *testing.T) {
wantErr bool
}{
"success": {
ak: validAKDigest,
ak: testdata.AKDigest,
report: testdata.SNPReport,
verifier: &reportVerifierImpl{},
validator: &reportValidatorImpl{},
},
"invalid report data": {
ak: validAKDigest,
ak: testdata.AKDigest,
report: reportTransformer(testdata.SNPReport, func(r *spb.Report) {
r.ReportData = make([]byte, 64)
}),
Expand All @@ -145,7 +138,7 @@ func TestValidateSNPReport(t *testing.T) {
wantErr: true,
},
"invalid report signature": {
ak: validAKDigest,
ak: testdata.AKDigest,
report: reportTransformer(testdata.SNPReport, func(r *spb.Report) { r.Signature[0]++ }),
verifier: &reportVerifierImpl{},
validator: &reportValidatorImpl{},
Expand Down
4 changes: 1 addition & 3 deletions internal/attestation/snp/snp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import (
"github.com/stretchr/testify/require"
)

const vlekReport = "02000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000300000000000ace0300000000000000040000000000000044a93ab043ad14ece9bfa97305d95302c9cc6ed95e17efaf7348ed7a7603e1ca89d12758e089d2abcf5a4dd16a99e3cb4cba8f0b8e8cb8eac3e926f1d2b5cfecc2c84b9364fc9f0f54b04534768c860c6e0e386ad98b96e8b98eca46ac8971d05c531ba48373f054c880cfd1f4a0a84e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008c5d6770df734a203cd061a3698e702caed25e7f744dc060eb9dcba0f2e4bdb2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300000000000a73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000a7301360100013601000300000000000a73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b9853dac65f127574c6a578c11885e1887d4c7ae446237d4273715dd8c05cfe4bd49facc1392f2ca7354c8f0d34d65500000000000000000000000000000000000000000000000004013481e9c6a6bb112818aeba3bd178d788dedf62600b8c7892a8d3df4d880265010e7d833201156364a001e62f47b570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

// TestParseCertChain tests the parsing of the certificate chain.
func TestParseCertChain(t *testing.T) {
defaultCertChain := testdata.CertChain
Expand Down Expand Up @@ -130,7 +128,7 @@ func TestParseVCEK(t *testing.T) {
// TestAttestationWithCerts tests the basic unmarshalling of the attestation report and the ASK / ARK precedence.
func TestAttestationWithCerts(t *testing.T) {
defaultReport := testdata.AttestationReport
vlekReport, err := hex.DecodeString(vlekReport)
vlekReport, err := hex.DecodeString(testdata.AttestationReportVLEK)
require.NoError(t, err)
testdataArk, testdataAsk := mustCertChainToPem(t, testdata.CertChain)
testdataArvk, testdataAsvk := mustCertChainToPem(t, testdata.VlekCertChain)
Expand Down
5 changes: 4 additions & 1 deletion internal/attestation/snp/testdata/testdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ package testdata

import _ "embed"

// AttestationBytes is an example attestation report from a Constellation VM.
// AttestationReport is an example attestation report from a Constellation VM.
//
//go:embed attestation.bin
var AttestationReport []byte

// AttestationReportVLEK is an example attestation report signed by a VLEK.
const AttestationReportVLEK = "02000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000300000000000ace0300000000000000040000000000000044a93ab043ad14ece9bfa97305d95302c9cc6ed95e17efaf7348ed7a7603e1ca89d12758e089d2abcf5a4dd16a99e3cb4cba8f0b8e8cb8eac3e926f1d2b5cfecc2c84b9364fc9f0f54b04534768c860c6e0e386ad98b96e8b98eca46ac8971d05c531ba48373f054c880cfd1f4a0a84e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008c5d6770df734a203cd061a3698e702caed25e7f744dc060eb9dcba0f2e4bdb2ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0300000000000a73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000a7301360100013601000300000000000a73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b9853dac65f127574c6a578c11885e1887d4c7ae446237d4273715dd8c05cfe4bd49facc1392f2ca7354c8f0d34d65500000000000000000000000000000000000000000000000004013481e9c6a6bb112818aeba3bd178d788dedf62600b8c7892a8d3df4d880265010e7d833201156364a001e62f47b570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

// AzureThimVCEK is an example VCEK certificate (PEM, as returned from Azure THIM) for the AttestationReport.
//
//go:embed vcek.pem
Expand Down

0 comments on commit c22c3fd

Please sign in to comment.