From b35cd5993ed7951c0b69fcc2f1654e33c92f31a9 Mon Sep 17 00:00:00 2001 From: Dionna Glaze Date: Fri, 15 Mar 2024 16:02:05 +0000 Subject: [PATCH] Add fake signer support for extra certs --- testing/fake_certs.go | 58 ++++++++++++++++++++++++-------------- testing/fake_certs_test.go | 36 +++++++++++++++++++++++ 2 files changed, 73 insertions(+), 21 deletions(-) diff --git a/testing/fake_certs.go b/testing/fake_certs.go index 2a95a0d..233584f 100644 --- a/testing/fake_certs.go +++ b/testing/fake_certs.go @@ -103,12 +103,13 @@ func GetProduct(t testing.TB) *spb.SevProduct { // AmdSigner encapsulates a key and certificate chain following the format of AMD-SP's VCEK for // signing attestation reports. type AmdSigner struct { - Ark *x509.Certificate - Ask *x509.Certificate - Asvk *x509.Certificate - Vcek *x509.Certificate - Vlek *x509.Certificate - Keys *AmdKeys + Ark *x509.Certificate + Ask *x509.Certificate + Asvk *x509.Certificate + Vcek *x509.Certificate + Vlek *x509.Certificate + Extras map[string][]byte + Keys *AmdKeys // This identity does not match AMD's notion of an HWID. It is purely to combine expectations of // report data -> KDS URL construction for the fake KDS implementation. HWID [abi.ChipIDSize]byte @@ -189,11 +190,12 @@ type AmdSignerBuilder struct { HWID [abi.ChipIDSize]byte TCB kds.TCBVersion // Intermediate built certificates - Ark *x509.Certificate - Ask *x509.Certificate - Asvk *x509.Certificate - Vcek *x509.Certificate - Vlek *x509.Certificate + Ark *x509.Certificate + Ask *x509.Certificate + Asvk *x509.Certificate + Vcek *x509.Certificate + Vlek *x509.Certificate + Extras map[string][]byte } func (b *AmdSignerBuilder) productName() string { @@ -529,13 +531,14 @@ func (b *AmdSignerBuilder) TestOnlyCertChain() (*AmdSigner, error) { } } s := &AmdSigner{ - Ark: b.Ark, - Ask: b.Ask, - Asvk: b.Asvk, - Vcek: b.Vcek, - Vlek: b.Vlek, - Keys: b.Keys, - TCB: b.TCB, + Ark: b.Ark, + Ask: b.Ask, + Asvk: b.Asvk, + Vcek: b.Vcek, + Vlek: b.Vlek, + Keys: b.Keys, + Extras: b.Extras, + TCB: b.TCB, } copy(s.HWID[:], b.HWID[:]) return s, nil @@ -563,7 +566,9 @@ func DefaultTestOnlyCertChain(productName string, creationTime time.Time) (*AmdS // CertTableBytes outputs the certificates in AMD's ABI format. func (s *AmdSigner) CertTableBytes() ([]byte, error) { // Calculate the output size and the offset at which to copy each certificate. - headers := make([]abi.CertTableHeaderEntry, 6) // ARK, ASK, VCEK, VLEK, ASVK, NULL + const baseEntries = 6 // ARK, ASK, VCEK, VLEK, ASVK, NULL + entries := baseEntries + len(s.Extras) + headers := make([]abi.CertTableHeaderEntry, entries) headers[0].GUID = uuid.Parse(abi.ArkGUID) headers[0].Offset = uint32(len(headers) * abi.CertTableEntrySize) headers[0].Length = uint32(len(s.Ark.Raw)) @@ -584,9 +589,20 @@ func (s *AmdSigner) CertTableBytes() ([]byte, error) { headers[4].Offset = headers[3].Offset + headers[3].Length headers[4].Length = uint32(len(s.Asvk.Raw)) + index := 4 + blobs := [][]byte{s.Ark.Raw, s.Ask.Raw, s.Vcek.Raw, s.Vlek.Raw, s.Asvk.Raw} + for guid, data := range s.Extras { + prior := index + index++ + headers[index].GUID = uuid.Parse(guid) + headers[index].Offset = headers[prior].Offset + headers[prior].Length + headers[index].Length = uint32(len(data)) + blobs = append(blobs, data) + } + // Write out the headers and the certificates at the appropriate offsets. - result := make([]byte, headers[4].Offset+headers[4].Length) - for i, cert := range [][]byte{s.Ark.Raw, s.Ask.Raw, s.Vcek.Raw, s.Vlek.Raw, s.Asvk.Raw} { + result := make([]byte, headers[index].Offset+headers[index].Length) + for i, cert := range blobs { if err := (&headers[i]).Write(result[i*abi.CertTableEntrySize:]); err != nil { return nil, err } diff --git a/testing/fake_certs_test.go b/testing/fake_certs_test.go index 9cdc021..cbef4c9 100644 --- a/testing/fake_certs_test.go +++ b/testing/fake_certs_test.go @@ -15,6 +15,7 @@ package testing import ( + "bytes" "crypto/x509" "testing" "time" @@ -85,3 +86,38 @@ func TestCertificatesParse(t *testing.T) { t.Errorf("could not parse generated VCEK extensions: %v", err) } } + +func TestCertificatesExtras(t *testing.T) { + b := &AmdSignerBuilder{ + Extras: map[string][]byte{abi.ExtraPlatformInfoGUID: []byte("test")}, + } + s, err := b.TestOnlyCertChain() + if err != nil { + t.Fatal(err) + } + certBytes, err := s.CertTableBytes() + if err != nil { + t.Fatal(err) + } + entries, err := abi.ParseSnpCertTableHeader(certBytes) + if err != nil { + t.Fatal(err) + } + var hasXtra bool + if len(entries) != 6 { + t.Errorf("ParseSnpCertTableHeader(_) returned %d entries, want 6", len(entries)) + } + for _, entry := range entries { + if uuid.Equal(entry.GUID, uuid.Parse(abi.ExtraPlatformInfoGUID)) { + hasXtra = true + got := certBytes[entry.Offset : entry.Offset+entry.Length] + want := []byte("test") + if !bytes.Equal(got, want) { + t.Errorf("%v data is %v, want %v", abi.ExtraPlatformInfoGUID, got, want) + } + } + } + if !hasXtra { + t.Errorf("fake certs missing extra cert") + } +}