Skip to content

Commit 9a1ad2b

Browse files
authored
Merge pull request #94 from deeglaze/coverage
Add product utility unit tests
2 parents 7cb961f + 8da1394 commit 9a1ad2b

File tree

5 files changed

+130
-13
lines changed

5 files changed

+130
-13
lines changed

abi/abi_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ import (
2121
"strings"
2222
"testing"
2323

24+
"github.com/google/go-cmp/cmp"
2425
spb "github.com/google/go-sev-guest/proto/sevsnp"
2526
"github.com/pborman/uuid"
2627
"google.golang.org/protobuf/encoding/prototext"
28+
"google.golang.org/protobuf/testing/protocmp"
29+
"google.golang.org/protobuf/types/known/wrapperspb"
2730
)
2831

2932
var emptyReport = `
@@ -267,3 +270,50 @@ func TestCertTableProto(t *testing.T) {
267270
t.Fatalf("Extras[%q] = %v, want %v", extraGUID, gotExtra, extraraw)
268271
}
269272
}
273+
274+
func TestSevProduct(t *testing.T) {
275+
oldCpuid := cpuid
276+
defer func() { cpuid = oldCpuid }()
277+
tcs := []struct {
278+
eax uint32
279+
want *spb.SevProduct
280+
}{
281+
{
282+
eax: 0x00a00f10,
283+
want: &spb.SevProduct{
284+
Name: spb.SevProduct_SEV_PRODUCT_MILAN,
285+
MachineStepping: &wrapperspb.UInt32Value{Value: 0}},
286+
},
287+
{
288+
eax: 0x00a00f11,
289+
want: &spb.SevProduct{
290+
Name: spb.SevProduct_SEV_PRODUCT_MILAN,
291+
MachineStepping: &wrapperspb.UInt32Value{Value: 1}},
292+
},
293+
{
294+
eax: 0x00a10f10,
295+
want: &spb.SevProduct{
296+
Name: spb.SevProduct_SEV_PRODUCT_GENOA,
297+
MachineStepping: &wrapperspb.UInt32Value{Value: 0}},
298+
},
299+
{
300+
eax: 0x00a10f12,
301+
want: &spb.SevProduct{
302+
Name: spb.SevProduct_SEV_PRODUCT_GENOA,
303+
MachineStepping: &wrapperspb.UInt32Value{Value: 2}},
304+
},
305+
{
306+
eax: 0x0b010f0,
307+
want: &spb.SevProduct{
308+
Name: spb.SevProduct_SEV_PRODUCT_UNKNOWN,
309+
MachineStepping: &wrapperspb.UInt32Value{Value: 0}},
310+
},
311+
}
312+
for _, tc := range tcs {
313+
cpuid = func(op uint32) (uint32, uint32, uint32, uint32) { return tc.eax, 0, 0, 0 }
314+
got := SevProduct()
315+
if diff := cmp.Diff(got, tc.want, protocmp.Transform()); diff != "" {
316+
t.Errorf("SevProduct() = %+v, want %+v. Diff: %s", got, tc.want, diff)
317+
}
318+
}
319+
}

kds/kds.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,9 @@ func preEndorsementKeyCertificateExtensions(cert *x509.Certificate) (*Extensions
406406
// VcekCertificateExtensions returns the x509v3 extensions from the KDS specification of a VCEK
407407
// certificate interpreted into a struct type.
408408
func VcekCertificateExtensions(cert *x509.Certificate) (*Extensions, error) {
409+
if cert == nil {
410+
return nil, fmt.Errorf("cert cannot be nil")
411+
}
409412
exts, err := preEndorsementKeyCertificateExtensions(cert)
410413
if err != nil {
411414
return nil, err
@@ -422,6 +425,9 @@ func VcekCertificateExtensions(cert *x509.Certificate) (*Extensions, error) {
422425
// VlekCertificateExtensions returns the x509v3 extensions from the KDS specification of a VLEK
423426
// certificate interpreted into a struct type.
424427
func VlekCertificateExtensions(cert *x509.Certificate) (*Extensions, error) {
428+
if cert == nil {
429+
return nil, fmt.Errorf("cert cannot be nil")
430+
}
425431
exts, err := preEndorsementKeyCertificateExtensions(cert)
426432
if err != nil {
427433
return nil, err

kds/kds_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,30 @@ func TestProductName(t *testing.T) {
218218
},
219219
want: "badstepping",
220220
},
221+
{
222+
name: "unknown milan stepping",
223+
input: &pb.SevProduct{
224+
Name: pb.SevProduct_SEV_PRODUCT_MILAN,
225+
MachineStepping: &wrapperspb.UInt32Value{Value: 15},
226+
},
227+
want: "unmappedMilanStepping",
228+
},
229+
{
230+
name: "unknown genoa stepping",
231+
input: &pb.SevProduct{
232+
Name: pb.SevProduct_SEV_PRODUCT_GENOA,
233+
MachineStepping: &wrapperspb.UInt32Value{Value: 15},
234+
},
235+
want: "unmappedGenoaStepping",
236+
},
237+
{
238+
name: "unknown",
239+
input: &pb.SevProduct{
240+
Name: pb.SevProduct_SEV_PRODUCT_UNKNOWN,
241+
MachineStepping: &wrapperspb.UInt32Value{Value: 15},
242+
},
243+
want: "Unknown",
244+
},
221245
}
222246
for _, tc := range tcs {
223247
t.Run(tc.name, func(t *testing.T) {
@@ -266,6 +290,12 @@ func TestParseProductName(t *testing.T) {
266290
Name: pb.SevProduct_SEV_PRODUCT_GENOA,
267291
},
268292
},
293+
{
294+
name: "Unhandled report signer",
295+
input: "ignored",
296+
key: abi.NoneReportSigner,
297+
wantErr: "internal: unhandled reportSigner",
298+
},
269299
}
270300
for _, tc := range tcs {
271301
t.Run(tc.name, func(t *testing.T) {

verify/verify.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ func checkProductName(got, want *spb.SevProduct, key abi.ReportSigner) error {
456456
return fmt.Errorf("stepping value in VCEK certificate should not be nil")
457457
}
458458
if got.MachineStepping.Value != want.MachineStepping.Value {
459-
return fmt.Errorf("%v cert product stepping number %02X is not %02X",
459+
return fmt.Errorf("%v cert product stepping number 0x%X is not 0x%X",
460460
key, got.MachineStepping.Value, want.MachineStepping.Value)
461461
}
462462
}
@@ -659,11 +659,6 @@ func SnpAttestation(attestation *spb.Attestation, options *Options) error {
659659
if err := fillInAttestation(attestation, options); err != nil {
660660
return err
661661
}
662-
// Pass along the expected product information for VcekDER. fillInAttestation will ensure
663-
// that this is a noop if options.Product began as non-nil.
664-
if err := updateProductExpectation(&options.Product, attestation.Product); err != nil {
665-
return err
666-
}
667662

668663
report := attestation.GetReport()
669664
info, err := abi.ParseSignerInfo(report.GetSignerInfo())
@@ -778,6 +773,23 @@ func GetAttestationFromReport(report *spb.Report, options *Options) (*spb.Attest
778773
if err := fillInAttestation(result, options); err != nil {
779774
return nil, err
780775
}
776+
// Attempt to fill in the product field of the attestation. Don't error at this
777+
// point since this is not validation.
778+
info, _ := abi.ParseSignerInfo(report.SignerInfo)
779+
var exts *kds.Extensions
780+
parse := func(der []byte) *x509.Certificate {
781+
out, _ := x509.ParseCertificate(der)
782+
return out
783+
}
784+
switch info.SigningKey {
785+
case abi.VcekReportSigner:
786+
exts, _ = kds.VcekCertificateExtensions(parse(result.CertificateChain.VcekCert))
787+
case abi.VlekReportSigner:
788+
exts, _ = kds.VlekCertificateExtensions(parse(result.CertificateChain.VlekCert))
789+
}
790+
if exts != nil {
791+
result.Product, _ = kds.ParseProductName(exts.ProductName, info.SigningKey)
792+
}
781793
return result, nil
782794
}
783795

verify/verify_test.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -557,13 +557,32 @@ func TestRealAttestationVerification(t *testing.T) {
557557
"https://kdsintf.amd.com/vcek/v1/Milan/3ac3fe21e13fb0990eb28a802e3fb6a29483a6b0753590c951bdd3b8e53786184ca39e359669a2b76a1936776b564ea464cdce40c05f63c9b610c5068b006b5d?blSPL=2&teeSPL=0&snpSPL=5&ucodeSPL=68": testdata.VcekBytes,
558558
},
559559
)
560-
if err := RawSnpReport(testdata.AttestationBytes, &Options{
561-
Getter: getter,
562-
Product: &pb.SevProduct{
563-
Name: pb.SevProduct_SEV_PRODUCT_MILAN,
564-
MachineStepping: &wrapperspb.UInt32Value{Value: 0},
565-
}}); err != nil {
566-
t.Error(err)
560+
tcs := []struct {
561+
name string
562+
product *pb.SevProduct
563+
wantErr string
564+
}{
565+
{
566+
name: "happy path",
567+
product: &pb.SevProduct{
568+
Name: pb.SevProduct_SEV_PRODUCT_MILAN,
569+
MachineStepping: &wrapperspb.UInt32Value{Value: 0},
570+
},
571+
},
572+
{
573+
name: "bad vcek stepping",
574+
product: &pb.SevProduct{
575+
Name: pb.SevProduct_SEV_PRODUCT_MILAN,
576+
MachineStepping: &wrapperspb.UInt32Value{Value: 12},
577+
},
578+
wantErr: "expected product stepping 12, got 0",
579+
},
580+
}
581+
for _, tc := range tcs {
582+
opts := &Options{Getter: getter, Product: tc.product}
583+
if err := RawSnpReport(testdata.AttestationBytes, opts); !test.Match(err, tc.wantErr) {
584+
t.Errorf("RawSnpReport(_, %+v) = %v errored unexpectedly. Want %q", opts, err, tc.wantErr)
585+
}
567586
}
568587
}
569588

0 commit comments

Comments
 (0)