diff --git a/kds/kds.go b/kds/kds.go index a39801b..7b44a91 100644 --- a/kds/kds.go +++ b/kds/kds.go @@ -539,6 +539,14 @@ type VCEKCert struct { TCB uint64 } +// VCEKCertProduct returns a VCEKCert with the product line set to productLine. +func VCEKCertProduct(productLine string) VCEKCert { + return VCEKCert{ + Product: productLine, // TODO(Issue#114): Remove + ProductLine: productLine, + } +} + // VLEKCert represents the attestation report components represented in a KDS VLEK certificate // request URL. type VLEKCert struct { @@ -787,23 +795,23 @@ func ProductName(product *pb.SevProduct) string { // // Deprecated: Use ParseProductLine func ParseProduct(productLine string) (pb.SevProduct_SevProductName, error) { - switch productLine { - case "Milan": - return pb.SevProduct_SEV_PRODUCT_MILAN, nil - case "Genoa": - return pb.SevProduct_SEV_PRODUCT_GENOA, nil - default: - return pb.SevProduct_SEV_PRODUCT_UNKNOWN, fmt.Errorf("unknown AMD SEV product: %q", productLine) + p, err := ParseProductLine(productLine) + if err != nil { + return pb.SevProduct_SEV_PRODUCT_UNKNOWN, nil } + return p.Name, nil } // ParseProductLine returns the SevProductName for a product name without the stepping suffix. func ParseProductLine(productLine string) (*pb.SevProduct, error) { - name, err := ParseProduct(productLine) - if err != nil { - return nil, err + switch productLine { + case "Milan": + return &pb.SevProduct{Name: pb.SevProduct_SEV_PRODUCT_MILAN}, nil + case "Genoa": + return &pb.SevProduct{Name: pb.SevProduct_SEV_PRODUCT_GENOA}, nil + default: + return nil, fmt.Errorf("unknown AMD SEV product: %q", productLine) } - return &pb.SevProduct{Name: name}, nil } // ParseProductName returns the KDS project input value, and the model, stepping numbers represented diff --git a/kds/kds_test.go b/kds/kds_test.go index cecbfac..01931d7 100644 --- a/kds/kds_test.go +++ b/kds/kds_test.go @@ -140,7 +140,12 @@ func TestParseVCEKCertURL(t *testing.T) { { name: "happy path", url: VCEKCertURL("Milan", hwid, TCBVersion(0)), - want: VCEKCert{Product: "Milan", ProductLine: "Milan", HWID: hwid, TCB: 0}, + want: func() VCEKCert { + c := VCEKCertProduct("Milan") + c.HWID = hwid + c.TCB = 0 + return c + }(), }, { name: "bad query format", diff --git a/proto/check.proto b/proto/check.proto index 083e82e..59c380f 100644 --- a/proto/check.proto +++ b/proto/check.proto @@ -58,7 +58,8 @@ message Policy { // RootOfTrust represents configuration for which hardware root of trust // certificates to use for verifying attestation report signatures. message RootOfTrust { - // The expected AMD product the attestation was collected from. Default "Milan". + // The expected AMD product the attestation was collected from. Default + // "Milan". string product = 1 [deprecated = true]; // Paths to CA bundles for the AMD product. diff --git a/proto/check/check.pb.go b/proto/check/check.pb.go index 39666e9..4735f0e 100644 --- a/proto/check/check.pb.go +++ b/proto/check/check.pb.go @@ -282,7 +282,8 @@ type RootOfTrust struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // The expected AMD product the attestation was collected from. Default "Milan". + // The expected AMD product the attestation was collected from. Default + // "Milan". // // Deprecated: Marked as deprecated in check.proto. Product string `protobuf:"bytes,1,opt,name=product,proto3" json:"product,omitempty"` diff --git a/verify/verify.go b/verify/verify.go index 6853bb3..93a710e 100644 --- a/verify/verify.go +++ b/verify/verify.go @@ -501,12 +501,10 @@ func decodeCerts(chain *spb.CertificateChain, key abi.ReportSigner, options *Opt return nil, nil, err } if len(roots) == 0 { - root := &trust.AMDRootCerts{ - Product: productLine, - // Require that the root matches embedded root certs. - AskSev: trust.DefaultRootCerts[productLine].AskSev, - ArkSev: trust.DefaultRootCerts[productLine].ArkSev, - } + root := trust.AMDRootCertsProduct(productLine) + // Require that the root matches embedded root certs. + root.AskSev = trust.DefaultRootCerts[productLine].AskSev + root.ArkSev = trust.DefaultRootCerts[productLine].ArkSev if err := root.Decode(chain.GetAskCert(), chain.GetArkCert()); err != nil { return nil, nil, err } diff --git a/verify/verify_test.go b/verify/verify_test.go index babe267..6919d17 100644 --- a/verify/verify_test.go +++ b/verify/verify_test.go @@ -79,14 +79,12 @@ func TestEmbeddedCertsAppendixB3Expectations(t *testing.T) { func TestFakeCertsKDSExpectations(t *testing.T) { signMu.Do(initSigner) trust.ClearProductCertCache() - root := &trust.AMDRootCerts{ - Product: test.GetProductLine(), - ProductCerts: &trust.ProductCerts{ - Ark: signer.Ark, - Ask: signer.Ask, - }, - // No ArkSev or AskSev intentionally for test certs. + root := trust.AMDRootCertsProduct(test.GetProductLine()) + root.ProductCerts = &trust.ProductCerts{ + Ark: signer.Ark, + Ask: signer.Ask, } + // No ArkSev or AskSev intentionally for test certs. if err := validateArkX509(root); err != nil { t.Errorf("fake ARK validation error: %v", err) } @@ -306,13 +304,14 @@ func TestKdsMetadataLogic(t *testing.T) { // won't get tested. options := &Options{ TrustedRoots: map[string][]*trust.AMDRootCerts{ - test.GetProductLine(): {&trust.AMDRootCerts{ - Product: test.GetProductLine(), - ProductCerts: &trust.ProductCerts{ + test.GetProductLine(): {func() *trust.AMDRootCerts { + r := trust.AMDRootCertsProduct(test.GetProductLine()) + r.ProductCerts = &trust.ProductCerts{ Ark: newSigner.Ark, Ask: newSigner.Ask, - }, - }}, + } + return r + }()}, }, Now: time.Date(1, time.January, 5, 0, 0, 0, 0, time.UTC), Product: abi.DefaultSevProduct(), @@ -374,12 +373,10 @@ func TestCRLRootValidity(t *testing.T) { }, Number: big.NewInt(1), } - root := &trust.AMDRootCerts{ - Product: test.GetProductLine(), - ProductCerts: &trust.ProductCerts{ - Ark: signer.Ark, - Ask: signer.Ask, - }, + root := trust.AMDRootCertsProduct(test.GetProductLine()) + root.ProductCerts = &trust.ProductCerts{ + Ark: signer.Ark, + Ask: signer.Ask, } // Now try signing a CRL with a different root that certifies Vcek with a different serial number. @@ -398,12 +395,10 @@ func TestCRLRootValidity(t *testing.T) { } // Finally try checking a VCEK that's signed by a revoked ASK. - root2 := &trust.AMDRootCerts{ - Product: test.GetProductLine(), - ProductCerts: &trust.ProductCerts{ - Ark: signer2.Ark, - Ask: signer2.Ask, - }, + root2 := trust.AMDRootCertsProduct(test.GetProductLine()) + root2.ProductCerts = &trust.ProductCerts{ + Ark: signer2.Ark, + Ask: signer2.Ask, } wantErr2 := "ASK was revoked at 2022-06-14 12:01:00 +0000 UTC" if err := VcekNotRevoked(root2, signer2.Vcek, &Options{Getter: g2}); !test.Match(err, wantErr2) {