Skip to content

Commit 6583b01

Browse files
committed
Finish the KDS support v3 reports.
1 parent 6953342 commit 6583b01

File tree

10 files changed

+435
-138
lines changed

10 files changed

+435
-138
lines changed

abi/abi.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,9 @@ func SevProductFromCpuid1Eax(eax uint32) *pb.SevProduct {
984984
// MaskedCpuid1EaxFromSevProduct returns the Cpuid1Eax value expected from the given product
985985
// when masked with CpuidProductMask.
986986
func MaskedCpuid1EaxFromSevProduct(product *pb.SevProduct) uint32 {
987+
if product == nil {
988+
return 0
989+
}
987990
var family, model, stepping byte
988991
if product.MachineStepping != nil {
989992
stepping = byte(product.MachineStepping.Value & 0xf)

kds/kds.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,19 @@ var (
9999
"Genoa-B0": {Name: pb.SevProduct_SEV_PRODUCT_GENOA, MachineStepping: uint0},
100100
"Genoa-B1": {Name: pb.SevProduct_SEV_PRODUCT_GENOA, MachineStepping: uint1},
101101
"Genoa-B2": {Name: pb.SevProduct_SEV_PRODUCT_GENOA, MachineStepping: uint2},
102+
"Turin-B0": {Name: pb.SevProduct_SEV_PRODUCT_TURIN, MachineStepping: uint0},
103+
"Turin-B1": {Name: pb.SevProduct_SEV_PRODUCT_TURIN, MachineStepping: uint1},
102104
}
103105
milanSteppingVersions = []string{"B0", "B1"}
104106
genoaSteppingVersions = []string{"B0", "B1", "B2"}
107+
turinSteppingVersions = []string{"B0", "B1"}
108+
109+
// ProductLineCpuid associates the CPUID_1_EAX value (Stepping 0) to its AMD product name.
110+
ProductLineCpuid = map[uint32]string{
111+
0x00a00f10: "Milan",
112+
0x00a10f10: "Genoa",
113+
0x00b00f20: "Turin",
114+
}
105115
)
106116

107117
// TCBVersion is a 64-bit bitfield of different security patch levels of AMD firmware and microcode.
@@ -731,6 +741,8 @@ func ProductLine(product *pb.SevProduct) string {
731741
return "Milan"
732742
case pb.SevProduct_SEV_PRODUCT_GENOA:
733743
return "Genoa"
744+
case pb.SevProduct_SEV_PRODUCT_TURIN:
745+
return "Turin"
734746
default:
735747
return "Unknown"
736748
}
@@ -785,12 +797,22 @@ func ProductName(product *pb.SevProduct) string {
785797
if int(stepping) >= len(genoaSteppingVersions) {
786798
return "unmappedGenoaStepping"
787799
}
788-
return fmt.Sprintf("Milan-%s", genoaSteppingVersions[stepping])
800+
return fmt.Sprintf("Genoa-%s", genoaSteppingVersions[stepping])
801+
case pb.SevProduct_SEV_PRODUCT_TURIN:
802+
if int(stepping) >= len(turinSteppingVersions) {
803+
return "unmappedTurinStepping"
804+
}
805+
return fmt.Sprintf("Turin-%s", turinSteppingVersions[stepping])
789806
default:
790807
return "Unknown"
791808
}
792809
}
793810

811+
// ProductLineFromFms returns the product name used in the KDS endpoint to fetch VCEK certificates.
812+
func ProductLineFromFms(fms uint32) string {
813+
return ProductLine(abi.SevProductFromCpuid1Eax(fms))
814+
}
815+
794816
// ParseProduct returns the SevProductName for a product name without the stepping suffix.
795817
//
796818
// Deprecated: Use ParseProductLine
@@ -809,6 +831,8 @@ func ParseProductLine(productLine string) (*pb.SevProduct, error) {
809831
return &pb.SevProduct{Name: pb.SevProduct_SEV_PRODUCT_MILAN}, nil
810832
case "Genoa":
811833
return &pb.SevProduct{Name: pb.SevProduct_SEV_PRODUCT_GENOA}, nil
834+
case "Turin":
835+
return &pb.SevProduct{Name: pb.SevProduct_SEV_PRODUCT_TURIN}, nil
812836
default:
813837
return nil, fmt.Errorf("unknown AMD SEV product: %q", productLine)
814838
}

proto/fakekds.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ message Certificates {
2626
bytes chip_id = 1; // Should be 64 bytes
2727
map<uint64, bytes> tcb_certs = 2;
2828
string hostname = 3;
29+
uint32 fms = 4;
2930
}
3031
repeated ChipTCBCerts chip_certs = 1;
3132
}

proto/fakekds/fakekds.pb.go

Lines changed: 19 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

testing/client/client.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/google/go-sev-guest/client"
2323
test "github.com/google/go-sev-guest/testing"
2424
"github.com/google/go-sev-guest/verify/trust"
25+
"google.golang.org/protobuf/proto"
2526
)
2627

2728
// SkipUnmockableTestCase returns whether we have to skip a mocked failure test case on real hardware.
@@ -130,6 +131,17 @@ func GetSevQuoteProvider(tcs []test.TestCase, opts *test.DeviceOptions, tb testi
130131
},
131132
},
132133
},
134+
"Genoa": {
135+
{
136+
Product: "Genoa", // TODO(Issue#114): Remove
137+
ProductLine: "Genoa",
138+
ProductCerts: &trust.ProductCerts{
139+
Ask: sevQp.Device.Signer.Ask,
140+
Ark: sevQp.Device.Signer.Ark,
141+
Asvk: sevQp.Device.Signer.Asvk,
142+
},
143+
},
144+
},
133145
}
134146
badSnpRoot := map[string][]*trust.AMDRootCerts{
135147
"Milan": {
@@ -144,6 +156,18 @@ func GetSevQuoteProvider(tcs []test.TestCase, opts *test.DeviceOptions, tb testi
144156
},
145157
},
146158
},
159+
"Genoa": {
160+
{
161+
Product: "Genoa", // TODO(Issue#114): Remove
162+
ProductLine: "Genoa",
163+
ProductCerts: &trust.ProductCerts{
164+
// No ASK, oops.
165+
Ask: sevQp.Device.Signer.Ark,
166+
Ark: sevQp.Device.Signer.Ark,
167+
Asvk: sevQp.Device.Signer.Ark,
168+
},
169+
},
170+
},
147171
}
148172
fakekds, err := test.FakeKDSFromSigner(sevQp.Device.Signer)
149173
if err != nil {
@@ -152,6 +176,11 @@ func GetSevQuoteProvider(tcs []test.TestCase, opts *test.DeviceOptions, tb testi
152176
return sevQp, goodSnpRoot, badSnpRoot, fakekds
153177
}
154178

179+
// If requested to use a different product than on the machine, fail.
180+
if opts.Product != nil && !proto.Equal(abi.SevProduct(), opts.Product) {
181+
return nil, nil, nil, nil
182+
}
183+
155184
client, err := client.GetQuoteProvider()
156185
if err != nil {
157186
tb.Fatalf("Failed to open SEV guest device: %v", err)

testing/fake_certs.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ type AmdSigner struct {
110110
Keys *AmdKeys
111111
// This identity does not match AMD's notion of an HWID. It is purely to combine expectations of
112112
// report data -> KDS URL construction for the fake KDS implementation.
113-
HWID [abi.ChipIDSize]byte
114-
TCB kds.TCBVersion
113+
HWID [abi.ChipIDSize]byte
114+
TCB kds.TCBVersion
115+
Product *spb.SevProduct
115116
}
116117

117118
// AmdKeys encapsulates the key chain of ARK through ASK down to VCEK.

testing/fakekds.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"strings"
2424
"testing"
2525

26+
"github.com/google/go-sev-guest/abi"
2627
"github.com/google/go-sev-guest/kds"
2728
kpb "github.com/google/go-sev-guest/proto/fakekds"
2829
"github.com/google/go-sev-guest/verify/trust"
@@ -75,14 +76,14 @@ type RootBundle struct {
7576
type FakeKDS struct {
7677
Certs *kpb.Certificates
7778
// Two CERTIFICATE PEMs for ASK, then ARK or ASVK then ARK, per product
78-
RootBundles map[string]RootBundle
79+
RootBundles map[string]*RootBundle
7980
}
8081

8182
// FakeKDSFromFile returns a FakeKDS from a path to a serialized fakekds.Certificates message.
8283
func FakeKDSFromFile(path string) (*FakeKDS, error) {
8384
result := &FakeKDS{
8485
Certs: &kpb.Certificates{},
85-
RootBundles: map[string]RootBundle{
86+
RootBundles: map[string]*RootBundle{
8687
"Milan": {
8788
VcekBundle: string(trust.AskArkMilanVcekBytes),
8889
VlekBundle: string(trust.AskArkMilanVlekBytes),
@@ -110,14 +111,17 @@ func FakeKDSFromFile(path string) (*FakeKDS, error) {
110111
// AMD KDS REST API expectations.
111112
func FakeKDSFromSigner(signer *AmdSigner) (*FakeKDS, error) {
112113
certs := &kpb.Certificates{}
114+
rootBundles := map[string]*RootBundle{}
113115
certs.ChipCerts = []*kpb.Certificates_ChipTCBCerts{
114116
{
115117
ChipId: signer.HWID[:],
116118
TcbCerts: map[uint64][]byte{
117119
uint64(signer.TCB): signer.Vcek.Raw,
118120
},
121+
Fms: abi.MaskedCpuid1EaxFromSevProduct(signer.Product),
119122
},
120123
}
124+
productLine := kds.ProductLine(signer.Product)
121125

122126
b := &strings.Builder{}
123127
if err := multierr.Combine(
@@ -126,8 +130,7 @@ func FakeKDSFromSigner(signer *AmdSigner) (*FakeKDS, error) {
126130
); err != nil {
127131
return nil, fmt.Errorf("could not encode VCEK root certificates: %v", err)
128132
}
129-
vcekBundle := b.String()
130-
var vlekBundle string
133+
rootBundles[productLine] = &RootBundle{VcekBundle: b.String()}
131134
if signer.Asvk != nil {
132135
b := &strings.Builder{}
133136
if err := multierr.Combine(
@@ -136,15 +139,10 @@ func FakeKDSFromSigner(signer *AmdSigner) (*FakeKDS, error) {
136139
); err != nil {
137140
return nil, fmt.Errorf("could not encode VLEK root certificates: %v", err)
138141
}
139-
vlekBundle = b.String()
140-
}
141-
return &FakeKDS{
142-
Certs: certs,
143-
RootBundles: map[string]RootBundle{"Milan": {
144-
VcekBundle: vcekBundle,
145-
VlekBundle: vlekBundle,
146-
}},
147-
}, nil
142+
rootBundles[productLine].VlekBundle = b.String()
143+
}
144+
145+
return &FakeKDS{Certs: certs, RootBundles: rootBundles}, nil
148146
}
149147

150148
// FindChipTcbCerts returns the TcbCerts associated with the given chipID in the database if they
@@ -200,7 +198,7 @@ func GetKDS(t testing.TB) trust.HTTPSGetter {
200198
}
201199
fakeKds := &FakeKDS{
202200
Certs: &kpb.Certificates{},
203-
RootBundles: map[string]RootBundle{"Milan": {
201+
RootBundles: map[string]*RootBundle{"Milan": {
204202
VcekBundle: string(trust.AskArkMilanVcekBytes),
205203
VlekBundle: string(trust.AskArkMilanVlekBytes),
206204
},

0 commit comments

Comments
 (0)