@@ -191,6 +191,11 @@ type Options struct {
191191 // If nil, embedded certificate will be used
192192 TrustedRoots * x509.CertPool
193193
194+ // EvaluationDataNumber for TCB info that should be requested from PCS.
195+ // If this is non-zero and verification succeeds, the TCB info was at EvaluationDataNumber or newer.
196+ // If GetCollateral is false, the TCBInfo will not be fetched and thus the number is not checked.
197+ EvaluationDataNumber int
198+
194199 chain * PCKCertificateChain
195200 collateral * Collateral
196201 pckCertExtensions * pcs.PckExtensions
@@ -391,11 +396,15 @@ func getPckCrl(ctx context.Context, ca string, getter trust.HTTPSGetter, collate
391396 return nil
392397}
393398
394- func getTcbInfo (ctx context.Context , fmspc string , getter trust.HTTPSGetter , collateral * Collateral ) error {
399+ func getTcbInfo (ctx context.Context , fmspc string , getter trust.HTTPSGetter , collateral * Collateral , evaluationDataNumber int ) error {
395400 tcbInfoURL := pcs .TcbInfoURL (fmspc )
401+ if evaluationDataNumber > 0 {
402+ tcbInfoURL = pcs .TcbInfoURLTcbInfoURLWithEvaluationDataNumber (fmspc , evaluationDataNumber )
403+ }
396404 logger .V (2 ).Info ("Getting TCB Info: " , tcbInfoURL )
397405 header , body , err := trust .GetWith (ctx , getter , tcbInfoURL )
398406 if err != nil {
407+ // TODO(burgerdev): 410 means evaluationDataNumber is too old, but the HTTPSGetter interface does not allow inspection of the return code.
399408 return & trust.AttestationRecreationErr {
400409 Msg : fmt .Sprintf ("could not receive tcbInfo response: %v" , err ),
401410 }
@@ -417,6 +426,17 @@ func getTcbInfo(ctx context.Context, fmspc string, getter trust.HTTPSGetter, col
417426 }
418427 }
419428
429+ // According to the docs [1], if we explicitly requested an evaluation number and the request
430+ // succeeded, the response should contain exactly that number. If there's a mismatch, we're
431+ // either dealing with a non-compliant PCS or being MITM'd.
432+ //
433+ // [1]: https://api.portal.trustedservices.intel.com/content/documentation.html#pcs-tcb-info-tdx-v4
434+ if evaluationDataNumber > 0 && collateral .TdxTcbInfo .TcbInfo .TcbEvaluationDataNumber < evaluationDataNumber {
435+ return & trust.AttestationRecreationErr {
436+ Msg : fmt .Sprintf ("PCS responded with an outdated TcbEvaluationDataNumber (got %d, requested %d)" , collateral .TdxTcbInfo .TcbInfo .TcbEvaluationDataNumber , evaluationDataNumber ),
437+ }
438+ }
439+
420440 tcbInfoRawBody , err := bodyToRawMessage (tcbInfoPhrase , body )
421441 if err != nil {
422442 return & trust.AttestationRecreationErr {
@@ -494,7 +514,7 @@ func obtainCollateral(ctx context.Context, fmspc string, ca string, options *Opt
494514 }
495515 collateral := & Collateral {}
496516 logger .V (1 ).Info ("Getting TCB Info API response from the Intel PCS" )
497- if err := getTcbInfo (ctx , fmspc , getter , collateral ); err != nil {
517+ if err := getTcbInfo (ctx , fmspc , getter , collateral , options . EvaluationDataNumber ); err != nil {
498518 return nil , fmt .Errorf ("unable to receive tcbInfo: %v" , err )
499519 }
500520 logger .V (1 ).Info ("Successfully received TCB Info API response from the Intel PCS" )
0 commit comments