Skip to content

Commit

Permalink
Update to go-sev-guest v0.4.0 (google#271)
Browse files Browse the repository at this point in the history
This adds the ability for the test to run with a real sev-guest device,
not just a fake.

Signed-off-by: Dionna Glaze <dionnaglaze@google.com>

Signed-off-by: Dionna Glaze <dionnaglaze@google.com>
  • Loading branch information
deeglaze authored Dec 15, 2022
1 parent 8e530dc commit ea5407e
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 44 deletions.
9 changes: 4 additions & 5 deletions client/attest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

sgtest "github.com/google/go-sev-guest/testing"
testclient "github.com/google/go-sev-guest/testing/client"
"github.com/google/go-tpm-tools/internal/test"
pb "github.com/google/go-tpm-tools/proto/attest"
)
Expand Down Expand Up @@ -223,7 +224,7 @@ func TestSevSnpDevice(t *testing.T) {
copy(someNonce64[:], someNonce)
var nonce64 [64]byte
copy(nonce64[:], []byte("noncey business"))
sevTestDevice, err := sgtest.TcDevice([]sgtest.TestCase{
sevTestDevice, _, _, _ := testclient.GetSevGuest([]sgtest.TestCase{
{
Input: someNonce64,
Output: sgtest.TestRawReport(someNonce64),
Expand All @@ -232,10 +233,8 @@ func TestSevSnpDevice(t *testing.T) {
Input: nonce64,
Output: sgtest.TestRawReport(nonce64),
},
}, &sgtest.DeviceOptions{Now: time.Now()})
if err != nil {
t.Fatalf("failed to create test device: %v", err)
}
}, &sgtest.DeviceOptions{Now: time.Now()}, t)
defer sevTestDevice.Close()

testcases := []struct {
name string
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ go 1.19
require (
github.com/google/go-attestation v0.4.4-0.20220404204839-8820d49b18d9
github.com/google/go-cmp v0.5.7
github.com/google/go-sev-guest v0.2.6
github.com/google/go-sev-guest v0.4.1
github.com/google/go-tpm v0.3.3
github.com/google/logger v1.1.1
google.golang.org/protobuf v1.28.0
)

require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/certificate-transparency-go v1.1.2 // indirect
github.com/google/go-tspi v0.2.1-0.20190423175329-115dea689aad // indirect
github.com/google/logger v1.1.1 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/pborman/uuid v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down
5 changes: 3 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
Expand Down Expand Up @@ -320,8 +321,8 @@ github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOm
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE=
github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
github.com/google/go-sev-guest v0.2.6 h1:IH3neBTmwVXLX1OfYzI3vbUM8psEJ47y1xnwhsFDXcY=
github.com/google/go-sev-guest v0.2.6/go.mod h1:OMtBJPoT3rJO9HkA+ufUz4v/C71QJM4gf0IMz8dchPw=
github.com/google/go-sev-guest v0.4.1 h1:IjxtGAvzR+zSyAqMc1FWfYKCg1cwPkBly9+Xog3YMZc=
github.com/google/go-sev-guest v0.4.1/go.mod h1:UEi9uwoPbLdKGl1QHaq1G8pfCbQ4QP0swWX4J0k6r+Q=
github.com/google/go-tpm v0.1.2-0.20190725015402-ae6dd98980d4/go.mod h1:H9HbmUG2YgV/PHITkO7p6wxEEj/v5nlsVWIwumwH2NI=
github.com/google/go-tpm v0.3.0/go.mod h1:iVLWvrPp/bHeEkxTFi9WG6K9w0iy2yIszHwZGHPbzAw=
github.com/google/go-tpm v0.3.2/go.mod h1:j71sMBTfp3X5jPHz852ZOfQMUOf65Gb/Th8pRmp7fvg=
Expand Down
21 changes: 14 additions & 7 deletions server/verify_sev.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
spb "github.com/google/go-sev-guest/proto/sevsnp"
"github.com/google/go-sev-guest/validate"
sv "github.com/google/go-sev-guest/verify"
"github.com/google/go-sev-guest/verify/trust"
)

// VerifySnpOpts allows for customizing the functionality of VerifyAttestation's SEV-SNP verification.
Expand All @@ -15,21 +16,27 @@ type VerifySnpOpts struct {
// to verify a versioned chip endorsement key (VCEK) that signs attestation reports.
// If nil, falls back on go-sev-guest's embedded root certs. Maps a product name
// to an array of allowed roots.
TrustedRoots map[string][]*sv.AMDRootCerts
TrustedRoots map[string][]*trust.AMDRootCerts
// Allow the debug bit to be set (should only be used for testing).
AllowDebugTestOnly bool
// Getter is the object that will fetch files from URLs.
Getter trust.HTTPSGetter
}

// VerifySevSnpAttestation checks that the SEV-SNP attestation report matches expectations for the
// product.
func VerifySevSnpAttestation(attestation *spb.Attestation, opts *VerifySnpOpts) error {
// Check that the fields of the report are acceptable.
if err := validate.SnpAttestation(attestation, &validate.Options{
ReportData: opts.ReportData[:],
GuestPolicy: sabi.SnpPolicy{Debug: opts.AllowDebugTestOnly},
// Check that the report is signed by a valid AMD key. Do not check revocations. This must be
// done before validation to ensure the certificates are filled in by the verify library.
if err := sv.SnpAttestation(attestation, &sv.Options{
TrustedRoots: opts.TrustedRoots,
Getter: opts.Getter,
}); err != nil {
return err
}
// Check that the report is signed by a valid AMD key. Do not check revocations.
return sv.SnpAttestation(attestation, &sv.Options{TrustedRoots: opts.TrustedRoots})
// Check that the fields of the report are acceptable.
return validate.SnpAttestation(attestation, &validate.Options{
ReportData: opts.ReportData[:],
GuestPolicy: sabi.SnpPolicy{Debug: opts.AllowDebugTestOnly},
})
}
64 changes: 36 additions & 28 deletions server/verify_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,22 @@ import (
"fmt"
"hash"
"io"
"os"
"strings"
"testing"
"time"

"github.com/google/go-cmp/cmp"
sgtest "github.com/google/go-sev-guest/testing"
"github.com/google/go-sev-guest/verify"
testclient "github.com/google/go-sev-guest/testing/client"
"github.com/google/go-tpm-tools/cel"
"github.com/google/go-tpm-tools/client"
"github.com/google/go-tpm-tools/internal"
"github.com/google/go-tpm-tools/internal/test"
attestpb "github.com/google/go-tpm-tools/proto/attest"
"github.com/google/go-tpm/tpm2"
"github.com/google/go-tpm/tpmutil"
"github.com/google/logger"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/testing/protocmp"
)
Expand Down Expand Up @@ -59,6 +61,11 @@ func extendPCRsRandomly(rwc io.ReadWriteCloser, selpcr tpm2.PCRSelection) error
return nil
}

func TestMain(m *testing.M) {
logger.Init("TestLog", false, false, os.Stderr)
os.Exit(m.Run())
}

func TestVerifyHappyCases(t *testing.T) {
rwc := test.GetTPM(t)
defer client.CheckedClose(t, rwc)
Expand Down Expand Up @@ -206,12 +213,26 @@ func TestVerifyBasicAttestation(t *testing.T) {
}
defer ak.Close()

// When running on hardware, ak.Attest will collect an attestation report regardless of
// AttestOpts. We test the default behavior here by not passing in a device.
sevTestDevice, goodSnpRoot, _, kdsGetter := testclient.GetSevGuest(nil, &sgtest.DeviceOptions{}, t)
defer sevTestDevice.Close()

nonce := []byte("super secret nonce")
attestation, err := ak.Attest(client.AttestOpts{Nonce: nonce})
var nonce64 [64]byte
copy(nonce64[:], nonce)
attestation, err := ak.Attest(client.AttestOpts{
Nonce: nonce,
})
if err != nil {
t.Fatalf("failed to attest: %v", err)
}

teeopts := &VerifySnpOpts{
Getter: kdsGetter,
ReportData: nonce64,
TrustedRoots: goodSnpRoot,
}
if _, err := VerifyAttestation(attestation, VerifyOpts{
Nonce: nonce,
TrustedAKs: []crypto.PublicKey{ak.PublicKey()},
Expand All @@ -222,12 +243,14 @@ func TestVerifyBasicAttestation(t *testing.T) {
if _, err := VerifyAttestation(attestation, VerifyOpts{
Nonce: append(nonce, 0),
TrustedAKs: []crypto.PublicKey{ak.PublicKey()},
TEEOpts: teeopts,
}); err == nil {
t.Error("using the wrong nonce should make verification fail")
}

if _, err := VerifyAttestation(attestation, VerifyOpts{
Nonce: nonce,
Nonce: nonce,
TEEOpts: teeopts,
}); err == nil {
t.Error("using no trusted AKs should make verification fail")
}
Expand All @@ -239,6 +262,7 @@ func TestVerifyBasicAttestation(t *testing.T) {
if _, err := VerifyAttestation(attestation, VerifyOpts{
Nonce: nonce,
TrustedAKs: []crypto.PublicKey{priv.Public()},
TEEOpts: teeopts,
}); err == nil {
t.Error("using a random trusted AKs should make verification fail")
}
Expand Down Expand Up @@ -940,15 +964,13 @@ func TestVerifyAttestationWithSevSnp(t *testing.T) {
nonce := []byte("super secret nonce")
var nonce64 [64]byte
copy(nonce64[:], []byte("alternate secret nonce"))
sevTestDevice, err := sgtest.TcDevice([]sgtest.TestCase{
sevTestDevice, goodSnpRoot, badSnpRoot, kdsGetter := testclient.GetSevGuest([]sgtest.TestCase{
{
Input: nonce64,
Output: sgtest.TestRawReport(nonce64),
},
}, &sgtest.DeviceOptions{Now: time.Now()})
if err != nil {
t.Fatalf("failed to create test device: %v", err)
}
}, &sgtest.DeviceOptions{Now: time.Now()}, t)
defer sevTestDevice.Close()
attestation, err := ak.Attest(client.AttestOpts{
Nonce: nonce,
TEEDevice: &client.SevSnpDevice{Device: sevTestDevice},
Expand All @@ -958,15 +980,6 @@ func TestVerifyAttestationWithSevSnp(t *testing.T) {
t.Fatalf("failed to attest: %v", err)
}

goodSnpRoot := map[string][]*verify.AMDRootCerts{
"Milan": {
{
Product: "Milan",
AskX509: sevTestDevice.Signer.Ask,
ArkX509: sevTestDevice.Signer.Ark,
},
},
}
tcs := []struct {
name string
opts VerifyOpts
Expand All @@ -978,6 +991,7 @@ func TestVerifyAttestationWithSevSnp(t *testing.T) {
Nonce: nonce,
TrustedAKs: []crypto.PublicKey{ak.PublicKey()},
TEEOpts: &VerifySnpOpts{
Getter: kdsGetter,
ReportData: nonce64,
TrustedRoots: goodSnpRoot,
AllowDebugTestOnly: true,
Expand All @@ -990,6 +1004,7 @@ func TestVerifyAttestationWithSevSnp(t *testing.T) {
Nonce: nonce,
TrustedAKs: []crypto.PublicKey{ak.PublicKey()},
TEEOpts: &VerifySnpOpts{
Getter: kdsGetter,
ReportData: func() [64]byte {
var badNonce [64]byte
copy(badNonce[:], []byte("soooo baaad"))
Expand All @@ -1007,17 +1022,9 @@ func TestVerifyAttestationWithSevSnp(t *testing.T) {
Nonce: nonce,
TrustedAKs: []crypto.PublicKey{ak.PublicKey()},
TEEOpts: &VerifySnpOpts{
ReportData: nonce64,
TrustedRoots: map[string][]*verify.AMDRootCerts{
"Milan": {
{
Product: "Milan",
// Backwards, oops
AskX509: sevTestDevice.Signer.Ark,
ArkX509: sevTestDevice.Signer.Ask,
},
},
},
Getter: kdsGetter,
ReportData: nonce64,
TrustedRoots: badSnpRoot,
AllowDebugTestOnly: true,
},
},
Expand All @@ -1029,6 +1036,7 @@ func TestVerifyAttestationWithSevSnp(t *testing.T) {
Nonce: nonce,
TrustedAKs: []crypto.PublicKey{ak.PublicKey()},
TEEOpts: &VerifySnpOpts{
Getter: kdsGetter,
ReportData: nonce64,
TrustedRoots: goodSnpRoot,
},
Expand Down

0 comments on commit ea5407e

Please sign in to comment.