Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AnyMrTd policy field #49

Merged
merged 1 commit into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions proto/checkconfig.proto
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ message TDQuoteBodyPolicy {
bytes mr_owner_config = 8; // should be 48 bytes
repeated bytes rtmrs = 9; // should be 48 * rtmrsCount
bytes report_data = 10; // should be 64 bytes
repeated bytes any_mr_td = 11; // each should be 48 bytes.
}

// RootOfTrust represents configuration for which hardware root of trust
Expand Down
58 changes: 34 additions & 24 deletions proto/checkconfig/checkconfig.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions proto/tdx/tdx.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 32 additions & 18 deletions validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ type TdQuoteBodyOptions struct {
Rtmrs [][]byte
// ReportData is the expected REPORT_DATA field. Must be nil or 64 bytes long. Not checked if nil.
ReportData []byte
// MrTd is any permitted MR_TD field. Must be nil or each entry 48 bytes long. Not checked if nil.
AnyMrTd [][]byte
}

func lengthCheck(name string, length int, value []byte) error {
Expand All @@ -93,12 +95,14 @@ func lengthCheck(name string, length int, value []byte) error {
return nil
}

func lengthCheckRtmr(name string, size int, length int, value [][]byte) error {
func lengthCheckMany(name string, constraint func(int) error, length int, value [][]byte) error {
if len(value) == 0 {
return nil
}
if len(value) != size {
return fmt.Errorf("option %q size is %d. Want %d", name, len(value), size)
if constraint != nil {
if err := constraint(len(value)); err != nil {
return err
}
}

for i := range value {
Expand All @@ -110,6 +114,12 @@ func lengthCheckRtmr(name string, size int, length int, value [][]byte) error {
}

func checkOptionsLengths(opts *Options) error {
eqConstraint := func(size int) error {
if size != rtmrsCount {
return fmt.Errorf("option 'rtmrs' size is %d. Want %d", size, rtmrsCount)
}
return nil
}
return multierr.Combine(
lengthCheck("mr_seam", abi.MrSeamSize, opts.TdQuoteBodyOptions.MrSeam),
lengthCheck("td_attributes", abi.TdAttributesSize, opts.TdQuoteBodyOptions.TdAttributes),
Expand All @@ -120,7 +130,8 @@ func checkOptionsLengths(opts *Options) error {
lengthCheck("mr_owner_config", abi.MrOwnerConfigSize, opts.TdQuoteBodyOptions.MrOwnerConfig),
lengthCheck("report_data", abi.ReportDataSize, opts.TdQuoteBodyOptions.ReportData),
lengthCheck("qe_vendor_id", abi.QeVendorIDSize, opts.HeaderOptions.QeVendorID),
lengthCheckRtmr("rtmrs", rtmrsCount, abi.RtmrSize, opts.TdQuoteBodyOptions.Rtmrs),
lengthCheckMany("rtmrs", eqConstraint, abi.RtmrSize, opts.TdQuoteBodyOptions.Rtmrs),
lengthCheckMany("any_mr_td", nil, abi.MrTdSize, opts.TdQuoteBodyOptions.AnyMrTd),
)
}

Expand Down Expand Up @@ -149,6 +160,7 @@ func PolicyToOptions(policy *ccpb.Policy) (*Options, error) {
MrOwnerConfig: policy.GetTdQuoteBodyPolicy().GetMrOwnerConfig(),
Rtmrs: policy.GetTdQuoteBodyPolicy().GetRtmrs(),
ReportData: policy.GetTdQuoteBodyPolicy().GetReportData(),
AnyMrTd: policy.GetTdQuoteBodyPolicy().GetAnyMrTd(),
},
}
if err := checkOptionsLengths(opts); err != nil {
Expand All @@ -165,24 +177,25 @@ func byteCheckRtmr(size int, given, required [][]byte) error {
if len(required) != rtmrsCount {
return fmt.Errorf("RTMR field size(%d) is not equal to expected size(4)", len(required))
}
for i := range required {
if len(required[i]) == 0 {
logger.V(1).Infof("Skipping validation check for RTMR[%d] field: input provided is nil", i+1)
continue
}
if len(required[i]) != size {
return fmt.Errorf("RTMR[%d] should be 48 bytes, found %d", i, len(required[i]))
for i, bs := range required {
if err := byteCheck("Rtmrs", fmt.Sprintf("RTMR[%d]", i+1), size, given[i], bs); err != nil {
return err
}
}
return nil
}

logger.V(2).Infof("Quote field RTMR[%d] value is %s, and expected value is %s", i+1, hex.EncodeToString(given[i]), hex.EncodeToString(required[i]))
if !bytes.Equal(required[i], given[i]) {
return fmt.Errorf("quote field RTMR[%d] is %s. Expect %s",
i, hex.EncodeToString(given[i]), hex.EncodeToString(required[i]))
func byteCheckAny(size int, given []byte, allowed [][]byte) error {
if len(allowed) == 0 {
logger.V(1).Info("Skipping validation check for MRTD field: input provided is nil")
return nil
}
for i, bs := range allowed {
if err := byteCheck("MrTd", fmt.Sprintf("AnyMrTd[%d]", i), size, given, bs); err == nil {
return nil
}

logger.V(1).Infof("Successfully validated RTMR[%d] field", i+1)
}
return nil
return fmt.Errorf("no value in AnyMrTd matched %s", hex.EncodeToString(given))
}

func byteCheck(option, field string, size int, given, required []byte) error {
Expand Down Expand Up @@ -215,6 +228,7 @@ func exactByteMatch(quote *pb.QuoteV4, opts *Options) error {
byteCheck("MrOwner", "MR_OWNER", abi.MrOwnerSize, quote.GetTdQuoteBody().GetMrOwner(), opts.TdQuoteBodyOptions.MrOwner),
byteCheck("MrOwnerConfig", "MR_OWNER_CONFIG", abi.MrOwnerConfigSize, quote.GetTdQuoteBody().GetMrOwnerConfig(), opts.TdQuoteBodyOptions.MrOwnerConfig),
byteCheckRtmr(abi.RtmrSize, givenRtmr, opts.TdQuoteBodyOptions.Rtmrs),
byteCheckAny(abi.MrTdSize, quote.GetTdQuoteBody().GetMrTd(), opts.TdQuoteBodyOptions.AnyMrTd),
byteCheck("ReportData", "REPORT_DATA", abi.ReportDataSize, quote.GetTdQuoteBody().GetReportData(), opts.TdQuoteBodyOptions.ReportData),
byteCheck("QeVendorID", "QE_VENDOR_ID", abi.QeVendorIDSize, quote.GetHeader().GetQeVendorId(), opts.HeaderOptions.QeVendorID),
)
Expand Down
19 changes: 19 additions & 0 deletions validate/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,25 @@ func TestTdxQuote(t *testing.T) {
},
wantErr: "quote field MR_TD",
},
{
name: "Test incorrect MR_TD of all incorrect",
quote: quote12345,
opts: &Options{
TdQuoteBodyOptions: TdQuoteBodyOptions{
AnyMrTd: [][]byte{make([]byte, abi.MrTdSize), make([]byte, abi.MrTdSize)},
},
},
wantErr: "no value in AnyMrTd matched",
},
{
name: "Test correct MR_TD of many incorrect",
quote: quote12345,
opts: &Options{
TdQuoteBodyOptions: TdQuoteBodyOptions{
AnyMrTd: [][]byte{make([]byte, abi.MrTdSize), make([]byte, abi.MrTdSize), mrTd},
},
},
},
{
name: "Test incorrect MR_CONFIG_ID",
quote: quote12345,
Expand Down
Loading