Skip to content

Commit

Permalink
chore: adds security relevant validation logic to the DCAP attestation
Browse files Browse the repository at this point in the history
  • Loading branch information
Frieder Paape committed Oct 10, 2024
1 parent ec9d224 commit 699749f
Showing 1 changed file with 66 additions and 19 deletions.
85 changes: 66 additions & 19 deletions tdx/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ package tdx
import (
"context"
"encoding/json"
"errors"
"encoding/hex"
"fmt"

"github.com/flashbots/cvm-reverse-proxy/internal/attestation"
"github.com/flashbots/cvm-reverse-proxy/internal/attestation/measurements"
"github.com/flashbots/cvm-reverse-proxy/internal/attestation/variant"
"github.com/flashbots/cvm-reverse-proxy/internal/config"

"github.com/google/go-tdx-guest/verify"
"github.com/google/go-tdx-guest/abi"
"github.com/google/go-tdx-guest/validate"
"github.com/google/go-tdx-guest/verify"
ccpb "github.com/google/go-tdx-guest/proto/checkconfig"
pb "github.com/google/go-tdx-guest/proto/tdx"
)

Expand All @@ -43,6 +45,14 @@ func NewValidator(cfg *config.QEMUTDX, log attestation.Logger) *Validator {
}
}

func hexToBytes(hexString string) []byte {
bytes, err := hex.DecodeString(hexString)
if err != nil {
panic(err)
}
return bytes
}

// Validate validates the given attestation document using TDX attestation.
func (v *Validator) Validate(ctx context.Context, attDocRaw []byte, nonce []byte) (userData []byte, err error) {
v.log.Info("Validating attestation document")
Expand All @@ -62,35 +72,72 @@ func (v *Validator) Validate(ctx context.Context, attDocRaw []byte, nonce []byte
return nil, fmt.Errorf("writing quote to disk: %w", err)
}

// TCP Level
options := &verify.Options{CheckRevocations: true, GetCollateral: true}
if err := verify.RawTdxQuote(attDoc.RawQuote, options); err != nil {
return nil, fmt.Errorf("verifying TDX quote: %w", err)
// Report data
extraData := attestation.MakeExtraData(attDoc.UserData, nonce)
// Ensure extraData is at least 64 bytes
if len(extraData) < 64 {
padding := make([]byte, 64-len(extraData))
extraData = append(extraData, padding...)
}

// Assign the values of the flags to the corresponding proto fields
config := &ccpb.Config{
RootOfTrust: &ccpb.RootOfTrust{
CheckCrl: true,
GetCollateral: true,
},
Policy: &ccpb.Policy{
HeaderPolicy: &ccpb.HeaderPolicy{
MinimumQeSvn: 0,
MinimumPceSvn: 0,
QeVendorId: hexToBytes("939a7233f79c4ca9940a0db3957f0607"),
},
TdQuoteBodyPolicy: &ccpb.TDQuoteBodyPolicy{
TdAttributes: hexToBytes("0000001000000000"),
Xfam: hexToBytes("e700060000000000"),
MrConfigId: hexToBytes("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
MrOwner: hexToBytes("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
MrOwnerConfig: hexToBytes("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
ReportData: extraData,
MrTd: v.expected[0].Expected,
Rtmrs: [][]byte{
v.expected[1].Expected,
v.expected[2].Expected,
v.expected[3].Expected,
v.expected[4].Expected,
},
},
},
}

// config.Policy.TdQuoteBodyPolicy.MinimumTeeTcbSvn="" // skipping MinimumTeeTcbSvn as this is part of tcbinfo
// considering skipping MRSEAM, the tdx module can only be provided by intel and there's already trust here. Also the TDX module svn is part of the tcbinfo check
// yet still we might want to add a check for it at some point
// config.Policy.TdQuoteBodyPolicy.MrSeam="bf70f5c1c2c1610bf2ddad348a88ebf6a550256e949e52122c743dc97cde50ccafad2fc5927d150f307fba3b8ca21872"

quote, err := convertRawQuote(attDoc.RawQuote)
if err != nil {
return nil, fmt.Errorf("could not get quote from raw doc: %v", err)
}

// Report data
extraData := attestation.MakeExtraData(attDoc.UserData, nonce)
if !attestation.CompareExtraData(quote.TdQuoteBody.ReportData[:], extraData) {
return nil, fmt.Errorf("report data in TDX quote does not match provided nonce")
// TCP Level
options, err := verify.RootOfTrustToOptions(config.RootOfTrust)
if err != nil {
return nil, fmt.Errorf("converting root of trust to options: %w", err)
}

tdMeasure, err := parseDcapTDXAttestationMeasurements(quote)
if err != nil {
return nil, fmt.Errorf("could not parse DCAP attestation measurements: %v", err)
if err := verify.TdxQuote(quote, options); err != nil {
return nil, fmt.Errorf("verifying TDX quote: %w", err)
}

// Verify the quote against the expected measurements.
warnings, errs := v.expected.Compare(tdMeasure)
for _, warning := range warnings {
v.log.Warn(warning)
// validate quote fields defined in policy
opts, err := validate.PolicyToOptions(config.Policy)
if err != nil {
return nil, fmt.Errorf("converting policy to options: %v", err)
}
if len(errs) > 0 {
return nil, fmt.Errorf("measurement validation failed:\n%w", errors.Join(errs...))

if err := validate.TdxQuote(quote, opts); err != nil {
return nil, fmt.Errorf("error validating the TDX Quote: %v", err)
}

return attDoc.UserData, nil
Expand Down

0 comments on commit 699749f

Please sign in to comment.