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

Observations and Problems upon the RVPS ideas #1

Open
Xynnn007 opened this issue Jan 9, 2024 · 16 comments
Open

Observations and Problems upon the RVPS ideas #1

Xynnn007 opened this issue Jan 9, 2024 · 16 comments

Comments

@Xynnn007
Copy link

Xynnn007 commented Jan 9, 2024

Hi @thomas-fossati , thanks for the design and idea. I think this is also strongly related to thread confidential-containers/trustee#238.

Here are some understandings after reading. Please correct me if any is not right

  1. Solution of combination reference values is to bring in the concept of TE , which defines a specific set of claims (rv) that must be matched at the same time.
  2. Every TE has a relative key in RVPS for callers to index the intended TE. The key is in format like rvps:cca+realm:02c4.... How to get the key name? It is calculated by the black box KeyMinter , which receives parameters MediaType (a constant?), tee type E , and scheme-specific-id

Are these right?

Here are also some questions. Please forgive me for the sally questions:

  1. Which scheme-specific-id should be used when get the key from KeyMinter ?
    In https://github.com/thomas-fossati/rvps-ideas?tab=readme-ov-file#ingest-push-model step (5), does it mean that in Store the value of k[i] contains only one rv ?
@thomas-fossati
Copy link
Owner

hi @Xynnn007 !

Here are some understandings after reading. Please correct me if any is not right

  1. Solution of combination reference values is to bring in the concept of TE , which defines a specific set of claims (rv) that must be matched at the same time.

A target environment (TE) is what is "measured." A reference value (RV) comprises one or more measurements associated with a TE that need to be matched together against evidence.

  1. Every TE has a relative key in RVPS for callers to index the intended TE. The key is in format like rvps:cca+realm:02c4.... How to get the key name? It is calculated by the black box KeyMinter , which receives parameters MediaType (a constant?), tee type E , and scheme-specific-id

Each TE has a unique key that is constructed from an underlying identifier (either a class or an instance id) and further refined using namespacing parameters (at a minimum, the attestation scheme identifier).

Are these right?

Yes, you got the gist. I hope I haven't confused you with my inline annotations :-)

Here are also some questions.

  1. Which scheme-specific-id should be used when get the key from KeyMinter ?

This is a string that needs to be coordinated between verifier and RVPS. For example, for CCA realm TEs it could be "cca+realm".

In https://github.com/thomas-fossati/rvps-ideas?tab=readme-ov-file#ingest-push-model step (5), does it mean that in Store the value of k[i] contains only one rv ?

hmm I don't think that was my intention. Apologies for the confusion. k[i] could have one or more reference values. This is to cater for the possibility that a TE has more than one acceptable "shapes."

@Xynnn007
Copy link
Author

Thanks @thomas-fossati for the answers.

Let me try to summurize what is in my mind:

  1. Reference Value Provider/Software Supply Chain Owner publishes a manifest with different TEs and the integrity and authenticity of manifest is ensured by a signature.
  2. The manifest will then be "pushed" to the RVPS. Each TE will gain a key k[i], and the TE's expected measurement set rv[i] will be the value. k[i]->rv[i] will be insert to a key-value map, s.t. Store.
  3. When doing attestation, AS will use the intended TE's id TE_id, s.t. k[i] to query for the rv[i] to do comparation.

There is another problem. How to decide the TE_id by AS? In general, AS does not have any more contexts about the TE expect for tee type. This means that AS would get a bunch of TE_ids due to TEE type, the only parameter given?

@thomas-fossati
Copy link
Owner

Let me try to summurize what is in my mind:

Cool. I'll inline my notes.

  1. Reference Value Provider/Software Supply Chain Owner publishes a manifest with different TEs and the integrity and authenticity of manifest is ensured by a signature.

Yes. (A further check that is maybe worth making explicit is that the signer is someone known and also authorised to speak about the TEs in the manifest.)

  1. The manifest will then be "pushed" to the RVPS. Each TE will gain a key k[i], and the TE's expected measurement set rv[i] will be the value. k[i]->rv[i] will be insert to a key-value map, s.t. Store.

Yes.

  1. When doing attestation, AS will use the intended TE's id TE_id, s.t. k[i] to query for the rv[i] to do comparation.

Yes.

There is another problem. How to decide the TE_id by AS? In general, AS does not have any more contexts about the TE expect for tee type. This means that AS would get a bunch of TE_ids due to TEE type, the only parameter given?

AS should pass the TE identifier extracted from evidence, and pass it alongside the "TEE type" to the KeyMinter and get back the TE_id to use in the query.

@Xynnn007
Copy link
Author

Xynnn007 commented Jan 11, 2024

Nice. I think the proposal gives a good guide to handle compound measurements. However, I think we should think more about the last question, s.t.

There is another problem. How to decide the TE_id by AS? In general, AS does not have any more contexts about the TE expect for tee type. This means that AS would get a bunch of TE_ids due to TEE type, the only parameter given?

AS should pass the TE identifier extracted from evidence, and pass it alongside the "TEE type" to the KeyMinter and get back the TE_id to use in the query.

When I designed RVPS I met a similiar problem and I thought a lot about this, but did not get a perfect result. The reason is for different archs, we cannot ensure to have a claim in the evidence that has enough TE semantics. There are different conceptions.

  • TE. Reference values defined by the supply chain owner
  • TEE identity. The software identity defined by the system (e.g. CoCo), which is not equal to TE, but a TEE identity could point to a few optional TE_ids. I think this is what you meant? BTW, we do not want to handle the TEE identity things in AS.

There are two models for RVPS.

A client will directly query RVPS

There will be two roles, s.t. RVPS and the RVPS client. The data flow would be

RVPS client --> RVPS

This is ok and easy. The client itself can carry a TE_id

AS queries RVPS

This is critical.

There will be three roles, s.t. AS, RVPS and the AS client. The data flow would be

AS client --> AS <--> RVPS

This means that either the AS client or the AS should define the TE_id. The only parameter in current AS API corresponding to TE_id is the tee type. If we should provide a way for AS to set the TE_id, we should

  1. Add a new parameter TE_id to AS API
  2. Add a configuration for AS. The configuration is a mapping from tee to TE_ids.

If the parameter TE_id is set when calling AS API, use the TE_id to query RVPS; If not, use the one mapped by tee in the configuration file.

In this way, both RVPS and AS could have a relative "clean" API without functionality coupling. The next step is to handle the TEE identity in component like KBS. The whole path would roughly be

  1. Set the TEE identity to be registered by remote attestation and its expected TE_ids in KBS, which is preparation stage.
  2. KBS receives remote attestation request that would contain the requester's pending TEE identity.
  3. KBS delivers the TE_ids mapped from the pending TEE identity, the evidence to AS
  4. AS checks the evidence, and deliver the TE_ids to RVPS, then do the check
  5. KBS gets the returned value from AS, and decides whether the attestation will pass.

Another issue is that the TE_id is from the supply chain. That means the reference values might be update frequently (e.g. ~weeks), so the TE_id might need to support a mechanism similar to the indexing image on dockerhub, that is, using the latest tag to automatically relocate to the latest TE_id. Therefore, a possible suggestion is that the scheme-specific-id field of TE_id is preferably a long hash value, such as the hash of v[i]. When TE_id is set to rvps:<attestation-scheme-id>:latest when querying, RVPS will return the latest inserted v[i] with the same rvps:<attestation-scheme-id>.

Finally, even if we use RVPS to provide reference values, AS still has its own policy engine which can be used to define any reference values manually. This may be functionally overlapped, but still seems reasonable due to different scenarios.

I may have rambled a lot, but I hope that during the communication process we can gradually get closer to the final form.

@thomas-fossati
Copy link
Owner

The core idea beneath this proposal is that RVP and Attester synchronise on how to identify the Target Environment that is to be appraised.

To make a concrete example, Arm CCA evidence has two TEs:

  1. the "Platform" TE
  2. the "Realm" TE

The Platform TE has a compound identifier made of the "implementation" and "instance" identifiers.

For the Realm TE, the RIM claim can be used as an identifier.

Given that, the related RVs can be constructed using those IDs and associating the expected measurements.

I am not entirely familiar with AMD SEV-SNP and Intel TDX, but I'd have expected something similar would be available in their respective Evidence formats. For example, AMD's CHIP_ID seems similar to Arm's Platform TE id.

@Xynnn007
Copy link
Author

Xynnn007 commented Jan 12, 2024

I might get your point. The reference values might have two parts

  1. The "firmware" parts, s.t. Platform TE as you mentioned. For example, in Arm CCA, they are platform_token.impl_id, platform_token.inst_id, platform_token.sw_components, etc. These are often defined by the manufacturer. They reflect the "Platform Root of Trust" (PRoT for short ) of the TEE environment.
  2. The "content" parts, s.t. Realm TE as you mentioned. This means "what is injected into the TEE". In Arm CCA, they are "realm_token.rim", "realm_token.rem", etc. These are often defined by the concrete software stack running on TEE platform. For example in CoCo, we might have guest firmware for CCA, kernel for CCA and rootfs providing CCA attestation support etc.

Does this distinguishment make sense to you?

It makes sense that the verifier/validator (s.t. RVPS & AS) should know which firmware parts and content part TE should be used. In CCA we can use platform_token.impl_id, platform_token.inst_id as TE to look up firmware parts. Other platforms could also handle this correctly based on the similar way.

The problem lies in the content parts. We do not have a context of what "content"/software stack will be injected into the TEE. Although you mentioned in Arm CCA, RIM could be the identifier. However RIM (Realm Initial Measurements) actually means the digest of the initial contents and configurations of a Realm when just created. It is also a part that needs to be compared with the reference value. In #1 (comment), I just want to say that the TE_id of this part (content parts) depends on the real application scenario of Realm, so we might need some user space protocol to deliver. In CoCo, we ensure the realm will be used to run a virtual firmware, kernel and guest image (e.g. all for CCA), so it might be good to use KBS protocol to convey this TE_id.

@thomas-fossati
Copy link
Owner

thomas-fossati commented Jan 12, 2024

I might get your point. The reference values might have two parts

  1. The "firmware" parts, s.t. Platform TE as you mentioned. For example, in Arm CCA, they are platform_token.impl_id, platform_token.inst_id, platform_token.sw_components, etc. These are often defined by the manufacturer. They reflect the "Platform Root of Trust" (PRoT for short ) of the TEE environment.
  2. The "content" parts, s.t. Realm TE as you mentioned. This means "what is injected into the TEE". In Arm CCA, they are "realm_token.rim", "realm_token.rem", etc. These are often defined by the concrete software stack running on TEE platform. For example in CoCo, we might have guest firmware for CCA, kernel for CCA and rootfs providing CCA attestation support etc.

Does this distinguishment make sense to you?

💯 / 💯

It makes sense that the verifier/validator (s.t. RVPS & AS) should know which firmware parts and content part TE should be used. In CCA we can use platform_token.impl_id, platform_token.inst_id as TE to look up firmware parts. Other platforms could also handle this correctly based on the similar way.

cool

The problem lies in the content parts. We do not have a context of what "content"/software stack will be injected into the TEE. Although you mentioned in Arm CCA, RIM could be the identifier. However RIM (Realm Initial Measurements) actually means the digest of the initial contents and configurations of a Realm when just created. It is also a part that needs to be compared with the reference value.

true. There is no explicit TE_ID in Arm CCA for the Realm/content part. However, at least to a pretty decent degree of approximation, the measurement itself can be treated as an instance identifier, given its intrinsic entropy.

In #1 (comment), I just want to say that the TE_id of this part (content parts) depends on the real application scenario of Realm, so we might need some user space protocol to deliver. In CoCo, we ensure the realm will be used to run a virtual firmware, kernel and guest image (e.g. all for CCA), so it might be good to use KBS protocol to convey this TE_id.

I was not aware of this. It is certainly something worth exploring - do you have docs to share?

Though, depending on the KBS protocol would lock RVPS into the CoCo ecosystem, which may or may not be desirable -- e.g., AFAIU there have been recent talks in the community to ensure that the core building blocks can be reusable outside CoCo.

@Xynnn007
Copy link
Author

Xynnn007 commented Jan 12, 2024

Though, depending on the KBS protocol would lock RVPS into the CoCo ecosystem, which may or may not be desirable -- e.g., AFAIU there have been recent talks in the community to ensure that the core building blocks can be reusable outside CoCo.

The components are aimed to be used outside CoCo. Let me make it clear:

RVP & RVPS side.

There might be two typical roles as mentioned firmware parts owner and content part owner. The former could be like OEM. The latter could be like CoCo.

A typical firmware part TE_id could be something like

rvps:cca+platform:arm/version-1.0

I recommend that the scheme-specific-id part could be human readable. In this example, the arm/version-1.0 here might means that it is generated by arm and all the reference values are about version-1.0 platform.

and the core data of its content could be shown like (there might be some other metadata like the signer, the signature, the expire time, etc., which I does not list)

{
    "platform_token": {
        "impl_id": "...",
        "sw_components": "...",
        ...
    }
}

A typical content part TE_id could be like

rvps:cca+realm:confidential-containers/cca-stack:version-xxx

In this example, confidential-containers/cca-stack:version-xxx means that it is generated by confidential-containers and all the reference values are for cca-stack and with version version-xxx.

and its content could be shown like (there might also be some other metadata like the signer, the signature, the expire time, etc., which I does not list)

{
    "realm_token": {
        "rim": "...",
        "rem": "...",
        ...
    }
}

AS

The aim of AS is only to check the evidence's endorsement, and the content against the given policy and TE.

AS will directly connect to the RVPS. So, when doing attestation, TE_id will be one of the parameters. To make it simple, a request from a client could be like
CCA Token + TE_id + Policy_id

Another choice is AS would have a configuration that defines which TE_id to use for specific TEE platform. For example, it can set if CCA is being attested, then use rvps:cca+platform:arm/version-1.0 and rvps:cca+realm:confidential-containers/cca-stack:version-xxx as TE_id.

KBS

The aim of KBS is to perform KBS attestation protocol and provision the client permission to access resources.

We might need prepare some set-ups that tells which TE_id, policy id to be used when a client request comes.

To leverage initdata mechanism is a way for this (like perso in cca realm token)

Summary

In this way, the three components can be used separately. Let's just see what API they expose to understand what they are. You might not be familiar with all the components, but it does not matter as I just want to say they are relative independent and can surely be used outside CoCo.

  • RVPS: Verify the endorsement of referrence value and store reference value. Expose both register_reference_value(rv) -> TE and query_reference_value(TE) -> Rv
  • AS: Verify the evidence's endorsement, and do extra check against given TE_id and policy id. Expose attestation(evidence, TE_id, policy_id) API and other policy management APIs.
  • KBS: Perform KBS attestation protocol and store the confidential resources. Expose RCAR handshake API auth and attest.

@Xynnn007
Copy link
Author

Xynnn007 commented Jan 12, 2024

I was not aware of this. It is certainly something worth exploring - do you have docs to share?

If you mean what I said
'''
In CoCo, we ensure the realm will be used to run a virtual firmware, kernel and guest image (e.g. all for CCA), so it might be good to use KBS protocol to convey this TE_id
'''

Justin once gave a speech. See https://www.youtube.com/watch?v=_n9FxY3vxvs 15:44 the architecture diagram.

All architectures would have similar components.

@thomas-fossati
Copy link
Owner

Hi @Xynnn007 thanks for the detailed overview.

I have one comment on one of your main points, i.e., using human-readable TE identifiers.

I think this is great as long as humans are in the loop. However, I don't think this is desirable at the communication boundary between AS and RVPS. This is because AS deals in evidence payloads, and evidence has no notion of any human-readable aliasing. For example, CCA platform evidence only knows about the implementation ID it carries. Translating it to some kind of text string requires a trusted resolver in the loop, and therefore a new architectural dependency.

@Xynnn007
Copy link
Author

@thomas-fossati You are right. Firmware Parts could depend on e.g. impl id and instance id for Arm CCA platform token. However for Content Parts I imaged such a scenario:

CoCo community publishes a series of binaries to be deployed into the Realm for Arm platform, together with a shape manifest recording rvs.

A user needs to configure the CoCo-AS to correctly verify the TE that be equipmented with the binaries mentioned. One of the important things is to configure the TE_id.

Case 1: If we do not have a human readable string

The user browses CoCo’s homepage to find the corresponding release information about the TE_id. Copy and paste that into the configuration file.

Case 2: If we have a human readable string

The user also browses CoCo’s homepage to find the corresponding release information about the TE_id. Copy and paste that into the configuration file.

But furthermore, RVPS could also serve as a public service like dockerhub or sigstore.dev (well, just brainstorm) which maintains a lot of TE_ids and the rvs mapped. It could be queried with either a human readable string like

rvps:cca+realm:confidential-containers/cca-stack:v1.0.0

Or, a machine-readble one

rvps:cca+realm:abcdefg0123456789..

Just like an image in dockerhub can be indexed by either busybox:1.35.0 or busybox@sha256:ab4b55974af84ec0338b3b721db01931d3231115742e2dda607b7fdd6a23f925. The keys in human-readable and machine-readable is one-to-one.

In the absence of more actual user feedback and other opinions, I am ok with both (human-readable or no-must-human-readable) currently.

@thomas-fossati
Copy link
Owner

Hi @Xynnn007, thanks again for your continuous and fruitful engagement :-)

Your last comment has made me think that maybe I should step back a bit to reassess the first principles on which I've based my original proposal.

Recap:

To me, a Reference Value (RV) is a mirror image of Evidence that we ask the Verifier to reckon as describing a trustworthy environment.

Environments (both target and attesting) are defined in the RATS architecture as first-class objects, so it seemed like a good idea to be able to define such Environments while appraising them.

Now, one can observe that Evidence’s claims can be usually (*) partitioned into two categories: immutable and mutable.

(*) This is true for DICE, PSA and CCA platform, to cite a few.

The idea in my mind was to conceptualise the immutable claims as an “ID” of the environment to be appraised, and the mutable claims as the “measurements” of that environment.

Now, as you have aptly noticed, this mental model breaks down in the Realm case because there is no immutable claim that can be naturally promoted to an ID: in fact, all Realm claims are mutable.

So, instead of artificially promoting RIM as an “ephemeral” ID, as I did in my original proposal, it’s probably better to drop the TE_id idea altogether because it creates more confusion than order :-)

However, from a practical standpoint, when matching RV against Evidence we need to efficiently look up candidates from a potentially very big stash of RVs. Therefore, having some kind of lookup key looks like a necessity. So, I suggest we repurpose what I previously called "TE_id" to "RV lookup key" with visibility limited to RVSP and AS (i.e., without humans in the loop).

Re-scanning the original proposal, I reckon that just by renaming "TE_id" to "rv_key" (or similar) and adjusting the semantics accordingly, the whole architecture still stands.

If we need to add richer metadata to the RV, we can always recycle the "endorsed values" concept from CoRIM, where at the time the manifest is created, "endorsed values" pertaining to the specific CoCo workload (e.g., name, version, author, link into a transparency log, etc.) can be added alongside the expected RVs as extra info that AS could (if it wants to) add to the returned attestation result.

WDYT?

@Xynnn007
Copy link
Author

Thanks @thomas-fossati ! I think the abstraction of TE_id, manifest and rv are all great. We could keep the term TE_id as-is because it is descriptive enough -- just to me : )

I totally agree we should have some key like TE_id to refer to a set of reference values which need to be match altogether at the same time.

The problem is how to define the TE_id -- by information apart from the evidence itself, like a meaningful string, or by information that included inside the evidence, like impl id+instance id in Arm PAT.

I am willing and happy to be involved in the spec work. After that, we can start to do the refactoring upon RVPS.

@thomas-fossati
Copy link
Owner

The problem is how to define the TE_id -- by information apart from the evidence itself, like a meaningful string, or by information that included inside the evidence, like impl id+instance id in Arm PAT.

I think it's easier if it's evidence-based because then we can avoid depending on a new translation component.

I am willing and happy to be involved in the spec work. After that, we can start to do the refactoring upon RVPS.

Awesome, thanks! How should we continue this work? Is it OK to converge on a design here, or should we move it to the CoCo repo?

BTW, I wanted to make a couple of further additions to my original proposal, namely:

  1. a way to define "deny-lists" of explicitly prohibited measurements (x-ref-values), and
  2. a mechanism to attach metadata about an environment that can be added as "augmented claims" to an attestation result (endorsed-values)

@thomas-fossati
Copy link
Owner

  1. a way to define "deny-lists" of explicitly prohibited measurements (x-ref-values), and
  2. a mechanism to attach metadata about an environment that can be added as "augmented claims" to an attestation result (endorsed-values)

Done in b797d2d

@Xynnn007
Copy link
Author

See b797d2d#r137320391

Which makes me feel more that we should define a non-evidence-based TE_id

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants