diff --git a/pcs/pcs.go b/pcs/pcs.go index c991641..8f7d763 100644 --- a/pcs/pcs.go +++ b/pcs/pcs.go @@ -223,6 +223,16 @@ const ( TcbComponentStatusRevoked TcbComponentStatus = "Revoked" ) +// CollateralUpdate represents the `update` query parameter of the Intel PCS API service +type CollateralUpdate string + +const ( + // CollateralUpdateStandard represents the standard access channel to updated collateral provided as part of a TCB recovery event + CollateralUpdateStandard CollateralUpdate = "standard" + // CollateralUpdateEarly represents the early access channel to updated collaterals provided as part of a TCB recovery event + CollateralUpdateEarly CollateralUpdate = "early" +) + // UnmarshalJSON for TcbComponentStatus maps tcb status to corresponding valid strings func (st *TcbComponentStatus) UnmarshalJSON(s []byte) error { unquotedStatus, err := strconv.Unquote(string(s)) @@ -475,11 +485,11 @@ func PckCrlURL(ca string) string { } // TcbInfoURL returns the Intel PCS URL for retrieving TCB Info -func TcbInfoURL(fmspc string) string { - return fmt.Sprintf("%s/tcb?fmspc=%s", TdxBaseURL, fmspc) +func TcbInfoURL(fmspc string, update CollateralUpdate) string { + return fmt.Sprintf("%s/tcb?fmspc=%s&update=%s", TdxBaseURL, fmspc, update) } // QeIdentityURL returns the Intel PCS URL for retrieving QE identity -func QeIdentityURL() string { - return fmt.Sprintf("%s/qe/identity", TdxBaseURL) +func QeIdentityURL(update CollateralUpdate) string { + return fmt.Sprintf("%s/qe/identity?update=%s", TdxBaseURL, update) } diff --git a/pcs/pcs_test.go b/pcs/pcs_test.go index 44769a9..a885ca4 100644 --- a/pcs/pcs_test.go +++ b/pcs/pcs_test.go @@ -28,17 +28,58 @@ func TestPckCrlURL(t *testing.T) { } func TestTcbInfoURL(t *testing.T) { - want := TdxBaseURL + "/tcb?fmspc=50806f000000" fmspcBytes := []byte{80, 128, 111, 0, 0, 0} fmspc := hex.EncodeToString(fmspcBytes) - if got := TcbInfoURL(fmspc); got != want { - t.Errorf("TcbInfoURL(%q) = %q. Expected %q", fmspc, got, want) + + testCases := []struct { + name string + updateChannel CollateralUpdate + wantUrl string + }{ + { + name: "success with standard access", + updateChannel: CollateralUpdateStandard, + wantUrl: TdxBaseURL + "/tcb?fmspc=50806f000000&update=standard", + }, + { + name: "success with early access", + updateChannel: CollateralUpdateEarly, + wantUrl: TdxBaseURL + "/tcb?fmspc=50806f000000&update=early", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if got := TcbInfoURL(fmspc, tc.updateChannel); got != tc.wantUrl { + t.Errorf("TcbInfoURL(%q) = %q. Expected %q", fmspc, got, tc.wantUrl) + } + }) } } func TestQeIdentityURL(t *testing.T) { - want := TdxBaseURL + "/qe/identity" - if got := QeIdentityURL(); got != want { - t.Errorf("QEIdentityURL() = %q. Expected %q", got, want) + testCases := []struct { + name string + updateChannel CollateralUpdate + wantUrl string + }{ + { + name: "success with standard access", + updateChannel: CollateralUpdateStandard, + wantUrl: TdxBaseURL + "/qe/identity?update=standard", + }, + { + name: "success with early access", + updateChannel: CollateralUpdateEarly, + wantUrl: TdxBaseURL + "/qe/identity?update=early", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if got := QeIdentityURL(tc.updateChannel); got != tc.wantUrl { + t.Errorf("QEIdentityURL() = %q. Expected %q", got, tc.wantUrl) + } + }) } } diff --git a/testing/test_cases.go b/testing/test_cases.go index 1ff512e..a0076ee 100644 --- a/testing/test_cases.go +++ b/testing/test_cases.go @@ -50,11 +50,19 @@ var QeIdentityHeader = map[string][]string{ // TestGetter is a local getter tied to the included sample quote var TestGetter = &Getter{ Responses: map[string]HTTPResponse{ - "https://api.trustedservices.intel.com/tdx/certification/v4/qe/identity": { + "https://api.trustedservices.intel.com/tdx/certification/v4/qe/identity?update=standard": { Header: QeIdentityHeader, Body: testdata.QeIdentityBody, }, - "https://api.trustedservices.intel.com/tdx/certification/v4/tcb?fmspc=50806f000000": { + "https://api.trustedservices.intel.com/tdx/certification/v4/qe/identity?update=early": { + Header: QeIdentityHeader, + Body: testdata.QeIdentityBody, + }, + "https://api.trustedservices.intel.com/tdx/certification/v4/tcb?fmspc=50806f000000&update=standard": { + Header: TcbInfoHeader, + Body: testdata.TcbInfoBody, + }, + "https://api.trustedservices.intel.com/tdx/certification/v4/tcb?fmspc=50806f000000&update=early": { Header: TcbInfoHeader, Body: testdata.TcbInfoBody, }, diff --git a/verify/verify.go b/verify/verify.go index 4228a84..f1bd983 100644 --- a/verify/verify.go +++ b/verify/verify.go @@ -181,6 +181,8 @@ type Options struct { CheckRevocations bool // GetCollateral set to true if the verifier should retrieve the collaterals from the network using PCS. GetCollateral bool + // CollateralUpdate specifies the update channel used when retrieving the collaterals from PCS. + CollateralUpdate pcs.CollateralUpdate // Getter takes a URL and returns the body of its contents. By default uses http.Get and returns the header and body Getter trust.HTTPSGetter // Now is a time set at which to verify the validity of certificates and collaterals. If unset, uses defaultTimeset(). @@ -389,8 +391,8 @@ func getPckCrl(ca string, getter trust.HTTPSGetter, collateral *Collateral) erro return nil } -func getTcbInfo(fmspc string, getter trust.HTTPSGetter, collateral *Collateral) error { - tcbInfoURL := pcs.TcbInfoURL(fmspc) +func getTcbInfo(fmspc string, update pcs.CollateralUpdate, getter trust.HTTPSGetter, collateral *Collateral) error { + tcbInfoURL := pcs.TcbInfoURL(fmspc, update) logger.V(2).Info("Getting TCB Info: ", tcbInfoURL) header, body, err := getter.Get(tcbInfoURL) if err != nil { @@ -425,8 +427,8 @@ func getTcbInfo(fmspc string, getter trust.HTTPSGetter, collateral *Collateral) return nil } -func getQeIdentity(getter trust.HTTPSGetter, collateral *Collateral) error { - qeIdentityURL := pcs.QeIdentityURL() +func getQeIdentity(update pcs.CollateralUpdate, getter trust.HTTPSGetter, collateral *Collateral) error { + qeIdentityURL := pcs.QeIdentityURL(update) logger.V(2).Info("Getting QE Identity: ", qeIdentityURL) header, body, err := getter.Get(qeIdentityURL) if err != nil { @@ -490,15 +492,19 @@ func obtainCollateral(fmspc string, ca string, options *Options) (*Collateral, e if getter == nil { getter = trust.DefaultHTTPSGetter() } + update := options.CollateralUpdate + if update == "" { + update = pcs.CollateralUpdateStandard + } collateral := &Collateral{} logger.V(1).Info("Getting TCB Info API response from the Intel PCS") - if err := getTcbInfo(fmspc, getter, collateral); err != nil { + if err := getTcbInfo(fmspc, update, getter, collateral); err != nil { return nil, fmt.Errorf("unable to receive tcbInfo: %v", err) } logger.V(1).Info("Successfully received TCB Info API response from the Intel PCS") logger.V(1).Info("Getting QE Identity API response from the Intel PCS") - if err := getQeIdentity(getter, collateral); err != nil { + if err := getQeIdentity(update, getter, collateral); err != nil { return nil, fmt.Errorf("unable to receive QeIdentity: %v", err) } logger.V(1).Info("Successfully received QE Identity API response from the Intel PCS") diff --git a/verify/verify_test.go b/verify/verify_test.go index 243e60c..f2fefae 100644 --- a/verify/verify_test.go +++ b/verify/verify_test.go @@ -379,23 +379,62 @@ func TestGetTcbInfo(t *testing.T) { fmspc := hex.EncodeToString(fmspcBytes) collateral := &Collateral{} - if err := getTcbInfo(fmspc, getter, collateral); err != nil { - t.Error(err) + + testCases := []struct { + name string + updateChannel pcs.CollateralUpdate + }{ + { + name: "success with standard access", + updateChannel: pcs.CollateralUpdateStandard, + }, + { + name: "success with early access", + updateChannel: pcs.CollateralUpdateEarly, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if err := getTcbInfo(fmspc, tc.updateChannel, getter, collateral); err != nil { + t.Error(err) + } + }) } } func TestGetQeIdentity(t *testing.T) { getter := testcases.TestGetter collateral := &Collateral{} - if err := getQeIdentity(getter, collateral); err != nil { - t.Error(err) + + testCases := []struct { + name string + updateChannel pcs.CollateralUpdate + }{ + { + name: "success with standard access", + updateChannel: pcs.CollateralUpdateStandard, + }, + { + name: "success with early access", + updateChannel: pcs.CollateralUpdateEarly, + }, } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if err := getQeIdentity(tc.updateChannel, getter, collateral); err != nil { + t.Error(err) + } + }) + } + } func TestGetRootCRL(t *testing.T) { getter := testcases.TestGetter collateral := &Collateral{} - if err := getQeIdentity(getter, collateral); err != nil { + if err := getQeIdentity(pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } @@ -474,7 +513,7 @@ func TestVerifyUsingTcbInfoV4(t *testing.T) { fmspc := hex.EncodeToString(fmspcBytes) collateral := &Collateral{} - if err := getTcbInfo(fmspc, getter, collateral); err != nil { + if err := getTcbInfo(fmspc, pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } anyQuote, err := abi.QuoteToProto(testdata.RawQuote) @@ -524,7 +563,7 @@ func TestNegativeVerifyUsingTcbInfoV4(t *testing.T) { fmspc := hex.EncodeToString(fmspcBytes) collateral := &Collateral{} - if err := getTcbInfo(fmspc, getter, collateral); err != nil { + if err := getTcbInfo(fmspc, pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } anyQuote, err := abi.QuoteToProto(testdata.RawQuote) @@ -580,7 +619,7 @@ func TestVerifyUsingQeIdentityV4(t *testing.T) { getter := testcases.TestGetter collateral := &Collateral{} - if err := getQeIdentity(getter, collateral); err != nil { + if err := getQeIdentity(pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } anyQuote, err := abi.QuoteToProto(testdata.RawQuote) @@ -604,7 +643,7 @@ func TestNegativeVerifyUsingQeIdentityV4(t *testing.T) { getter := testcases.TestGetter collateral := &Collateral{} - if err := getQeIdentity(getter, collateral); err != nil { + if err := getQeIdentity(pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } anyQuote, err := abi.QuoteToProto(testdata.RawQuote) @@ -657,7 +696,7 @@ func TestNegativeTcbInfoTcbStatusV4(t *testing.T) { fmspc := hex.EncodeToString(fmspcBytes) collateral := &Collateral{} - if err := getTcbInfo(fmspc, getter, collateral); err != nil { + if err := getTcbInfo(fmspc, pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } anyQuote, err := abi.QuoteToProto(testdata.RawQuote) @@ -706,7 +745,7 @@ func TestNegativeCheckQeStatusV4(t *testing.T) { getter := testcases.TestGetter collateral := &Collateral{} - if err := getQeIdentity(getter, collateral); err != nil { + if err := getQeIdentity(pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } anyQuote, err := abi.QuoteToProto(testdata.RawQuote) @@ -750,7 +789,7 @@ func TestValidateCRL(t *testing.T) { if err := getPckCrl(ca, getter, collateral); err != nil { t.Fatal(err) } - if err := getQeIdentity(getter, collateral); err != nil { + if err := getQeIdentity(pcs.CollateralUpdateStandard, getter, collateral); err != nil { t.Fatal(err) } if err := getRootCrl(getter, collateral); err != nil {