trustee icon indicating copy to clipboard operation
trustee copied to clipboard

AS & RVPS | Proposal for an attestation applied policy format

Open Xynnn007 opened this issue 9 months ago • 7 comments

Background

During a long time, we use Rego policy to check against parsed claims derived from a TEE evidence. Because of Rego's flexibility we did not talk about the topic so much. Now I raised some limitations of the rego workaround and propose a new format that hopefully could well fit the all typical cases in remote attestation, and also extensible for future profile.

Limitations of Current Rego Policy

  1. Does not support mask rule.

For some cases, the claim value is a bitmap. Different bit of the bitmap shows different things of the TEE. Like td_attributes in tdx's claims. Intel's profile for IETF RATS' CoRIM (carrier of reference values) defines similar rules for this. However, in rego it is hard to do bitwise operation.

  1. Restrictions upon the writing style of the policy

In current implementation, we assert that the policy would define a bool value named allow to explicit show the result of the policy. In other words, if the policy is not written with an allow value, the enforcement will always fail.

  1. Troubles when working together with RVPS

In current implementation, the reference value of a specified claim can be given in two ways:

  • Directly in the policy, just like the example rego does
  • Provide from RVPS. This is a little tricky. We now couple the code and policy to achieve this. In the policy we use data of OPA to carry reference values from RVPS. In code, we will always query every key inside the parsed claims from RVPS to get reference values, and make the results into a data for OPA.

In a more clear design mode, we should not query any claim keys from RVPS, but rely on some hints in the policy.

There is another topic of "Combined Reference Value" discussed here. This hints that the policy should give a way for users to both a)directly specify the reference value against concrete claims and b) use a TE_id. TE_id here could be linked to a bunch of reference value rules defined in a CoRIM or something else.

Some more information about TE_id. In RATS, we have defined Target Environment to refer to the environment to be attested. Thus some reference value carrier like CoRIM would define a list of values to be matched together against an evidence. it sounds like "hey, if you(the tee) want to match the target environment, you need to match all of the following match rules". The TE_id is the key to index such set of rules.

Proposed Rule Syntax

Based on the observations mentioned before, I want to share a draft of CoCoAS policy design. It support some typical rules.

Numeric Expressions

Syntax

("<claim-key>" <op> <value>)
  • <claim-key>: the key of the parsed claims defined in the doc. e.g. sgx.body.isv_svn
  • <op>: could be >, >=, ==, <=, <
  • <value>: i64 number

Note that once numeric operation is involved, the value of claim-key will be treated as a hex format of an integer number.

For example, ("sgx.body.isv_svn" > 16 means that only if "sgx.body.isv_svn") is greater than 16, this expression will be true.

Set Expressions

We now only define in rule for set.

Syntax

("<claim-key>" <op> <set>)
  • <claim-key>: the key of the parsed claims defined in the doc. e.g. sgx.body.isv_svn
  • <op>: could be in
  • <value>: a list of acceptable values.

For example, ("snp.measurement" in ["aabbcc", "ccbbaa"]) means that only if "snp.measurement" is "aabbcc" or "ccbbaa", the expression will be true.

Naive Assertion Expressions

Syntax

("<claim-key>" is <value>)
  • <claim-key>: the key of the parsed claims defined in the doc. e.g. sgx.body.isv_svn
  • is: the keyword
  • <value>: the expection value for the claim key

For example ("snp.measurement" is "aabbcc") means that only if "snp.measurement" is "aabbcc" the expression will be true.

Mask Expressions

Syntax

("<claim-key>" mask <mask> equ <value>)
  • <claim-key>: the key of the parsed claims defined in the doc. e.g. tdx.quote.body.td_attributes
  • mask: the keyword
  • <mask>: a mask to be applied onto the value of
  • equ: the keyword
  • <value>: the expected value after applying the mask

For example ("tdx.quote.body.td_attributes" mask "0x0000f0" equ "0x000010") means that only if "tdx.quote.body.td_attributes"'s value does a bitwise-and with 0x0000f0 and gets 0x000010, the expression will be true.

Logic Expressions

Different expressions could be combined using logic expressions.

Syntax

# And
(Expr1 and Expr2 [..and Exprn])

# Or
(Expr1 or Expr2 [..or Exprn])

# Not
(not Expr1)

For example (("tdx.quote.body.td_attributes" mask "0x0000f0" equ "0x000010") and ("tdx.quote.header.version" > 10))

Reference Value Link Expression

This is a special expression rule. This rule will trigger a query to RVPS for a given TE_id, and apply all the reference values upon the current evidence. If the rules of the TE_id all matches, the expression will be true.

Syntax

(with TE <TE_id>)
  • <TE_id>: The TE_id of an expected TE.

Full example with different combinations of rules

Here is an example that defines a rule of a combined attestation claim with both GPU and CPU. It asserts the GPU part should match TE_id gpu-nvidia:123456789 from RVPS. Then, for TDX and SNP it has different rules to check against different fields.

(with TE "gpu-nvidia:123456789")
and
(
  (
    ("tee_type" is "tdx")
    and
    ("tdx.quote.body.mr_td" in ["aa", "bb"])
    and
    ("tdx.quote.body.tcb_svn" > 10)
    and
    ("tdx.quote.body.seam_attributes" mask "0xffffffff" equ "0x00000000")
  )
  or
  (
    ("tee_type" is "snp")
    and
    ("snp.measurement" is "cc")
  )
)

Backup

In RVPS, we could store reference values in such a format too. As reference values are not only simple expected values to directly be matched, but also could involve some rules.

This is still a un-mature draft, please share any suggestions upon this.

Xynnn007 avatar May 24 '24 09:05 Xynnn007