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

AA: get_token API add runtime_data paramter #465

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion api-server-rest/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ $ curl http://127.0.0.1:8006/cdh/resource/default/key/1
$ curl http://127.0.0.1:8006/aa/evidence\?runtime_data\=xxxx
{"svn":"1","report_data":"eHh4eA=="}

$ curl http://127.0.0.1:8006/aa/token\?token_type\=kbs
$ curl http://127.0.0.1:8006/aa/token\?token_type\=kbs\?structured_runtime_data=xxx
{"token":"eyJhbGciOiJFi...","tee_keypair":"-----BEGIN... "}
```
3 changes: 2 additions & 1 deletion api-server-rest/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use utoipa::OpenApi;
get,
path = "/aa/token",
params(
("token_type" = String, Query, description = "Token Type")
("token_type" = String, Query, description = "Token Type"),
("structured_runtime_data" = Option<String>, Query, description = "Structured data in JSON format, which will be hashed as runtime data")
),
responses(
(status = 200, description = "success response",
Expand Down
10 changes: 10 additions & 0 deletions api-server-rest/openapi/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@
"schema": {
"type": "string"
}
},
{
"name": "structured_runtime_data",
"in": "query",
"description": "Structured data in JSON format, which will be hashed as runtime data",
"required": false,
"schema": {
"type": "string",
"nullable": true
}
}
],
"responses": {
Expand Down
1 change: 1 addition & 0 deletions api-server-rest/protos/attestation_agent.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ message GetEvidenceResponse {

message GetTokenRequest {
string TokenType = 1;
optional string StructuredRuntimeData = 2;
}

message GetTokenResponse {
Expand Down
13 changes: 11 additions & 2 deletions api-server-rest/src/aa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,12 @@ impl ApiHandler for AAClient {
match url_path {
AA_TOKEN_URL => match params.get("token_type") {
Some(token_type) => {
let default_structed_runtime_data = String::from("{}");
let structured_runtime_data = params
.get("structured_runtime_data")
.unwrap_or(&default_structed_runtime_data);
let results = self
.get_token(token_type)
.get_token(token_type, structured_runtime_data)
.await
.unwrap_or_else(|e| e.to_string().into());
return self.octet_stream_response(results);
Expand Down Expand Up @@ -95,9 +99,14 @@ impl AAClient {
})
}

pub async fn get_token(&self, token_type: &str) -> Result<Vec<u8>> {
pub async fn get_token(
&self,
token_type: &str,
structured_runtime_data: &str,
) -> Result<Vec<u8>> {
let req = GetTokenRequest {
TokenType: token_type.to_string(),
StructuredRuntimeData: Some(structured_runtime_data.to_string()),
..Default::default()
};
let res = self
Expand Down
34 changes: 27 additions & 7 deletions api-server-rest/src/ttrpc_proto/attestation_agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ pub struct GetTokenRequest {
// message fields
// @@protoc_insertion_point(field:attestation_agent.GetTokenRequest.TokenType)
pub TokenType: ::std::string::String,
// @@protoc_insertion_point(field:attestation_agent.GetTokenRequest.StructuredRuntimeData)
pub StructuredRuntimeData: ::std::option::Option<::std::string::String>,
// special fields
// @@protoc_insertion_point(special_field:attestation_agent.GetTokenRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
Expand All @@ -292,13 +294,18 @@ impl GetTokenRequest {
}

fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(1);
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"TokenType",
|m: &GetTokenRequest| { &m.TokenType },
|m: &mut GetTokenRequest| { &mut m.TokenType },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"StructuredRuntimeData",
|m: &GetTokenRequest| { &m.StructuredRuntimeData },
|m: &mut GetTokenRequest| { &mut m.StructuredRuntimeData },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<GetTokenRequest>(
"GetTokenRequest",
fields,
Expand All @@ -320,6 +327,9 @@ impl ::protobuf::Message for GetTokenRequest {
10 => {
self.TokenType = is.read_string()?;
},
18 => {
self.StructuredRuntimeData = ::std::option::Option::Some(is.read_string()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
Expand All @@ -335,6 +345,9 @@ impl ::protobuf::Message for GetTokenRequest {
if !self.TokenType.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.TokenType);
}
if let Some(v) = self.StructuredRuntimeData.as_ref() {
my_size += ::protobuf::rt::string_size(2, &v);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
Expand All @@ -344,6 +357,9 @@ impl ::protobuf::Message for GetTokenRequest {
if !self.TokenType.is_empty() {
os.write_string(1, &self.TokenType)?;
}
if let Some(v) = self.StructuredRuntimeData.as_ref() {
os.write_string(2, v)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
Expand All @@ -362,12 +378,14 @@ impl ::protobuf::Message for GetTokenRequest {

fn clear(&mut self) {
self.TokenType.clear();
self.StructuredRuntimeData = ::std::option::Option::None;
self.special_fields.clear();
}

fn default_instance() -> &'static GetTokenRequest {
static instance: GetTokenRequest = GetTokenRequest {
TokenType: ::std::string::String::new(),
StructuredRuntimeData: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
Expand Down Expand Up @@ -517,12 +535,14 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x17attestation_agent.proto\x12\x11attestation_agent\"6\n\x12GetEviden\
ceRequest\x12\x20\n\x0bRuntimeData\x18\x01\x20\x01(\x0cR\x0bRuntimeData\
\"1\n\x13GetEvidenceResponse\x12\x1a\n\x08Evidence\x18\x01\x20\x01(\x0cR\
\x08Evidence\"/\n\x0fGetTokenRequest\x12\x1c\n\tTokenType\x18\x01\x20\
\x01(\tR\tTokenType\"(\n\x10GetTokenResponse\x12\x14\n\x05Token\x18\x01\
\x20\x01(\x0cR\x05Token2\xcc\x01\n\x17AttestationAgentService\x12\\\n\
\x0bGetEvidence\x12%.attestation_agent.GetEvidenceRequest\x1a&.attestati\
on_agent.GetEvidenceResponse\x12S\n\x08GetToken\x12\".attestation_agent.\
GetTokenRequest\x1a#.attestation_agent.GetTokenResponseb\x06proto3\
\x08Evidence\"\x84\x01\n\x0fGetTokenRequest\x12\x1c\n\tTokenType\x18\x01\
\x20\x01(\tR\tTokenType\x129\n\x15StructuredRuntimeData\x18\x02\x20\x01(\
\tH\0R\x15StructuredRuntimeData\x88\x01\x01B\x18\n\x16_StructuredRuntime\
Data\"(\n\x10GetTokenResponse\x12\x14\n\x05Token\x18\x01\x20\x01(\x0cR\
\x05Token2\xcc\x01\n\x17AttestationAgentService\x12\\\n\x0bGetEvidence\
\x12%.attestation_agent.GetEvidenceRequest\x1a&.attestation_agent.GetEvi\
denceResponse\x12S\n\x08GetToken\x12\".attestation_agent.GetTokenRequest\
\x1a#.attestation_agent.GetTokenResponseb\x06proto3\
";

/// `FileDescriptorProto` object which was a source for this generated file
Expand Down
13 changes: 11 additions & 2 deletions attestation-agent/app/src/rpc/attestation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,12 @@ pub mod grpc {
debug!("Call AA to get token ...");

let token = attestation_agent
.get_token(&request.token_type)
.get_token(
&request.token_type,
&request
.structured_runtime_data
.unwrap_or_else(|| String::from("{}")),
)
.await
.map_err(|e| {
error!("Call AA to get token failed: {}", e);
Expand Down Expand Up @@ -186,7 +191,11 @@ pub mod ttrpc {
let mut attestation_agent = attestation_agent_mutex_clone.lock().await;

let token = attestation_agent
.get_token(&req.TokenType)
.get_token(
&req.TokenType,
&req.StructuredRuntimeData
.unwrap_or_else(|| String::from("{}")),
)
.await
.map_err(|e| {
error!("Call AA-KBC to get token failed: {}", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,8 @@ pub struct GetTokenRequest {
// message fields
// @@protoc_insertion_point(field:attestation_agent.GetTokenRequest.TokenType)
pub TokenType: ::std::string::String,
// @@protoc_insertion_point(field:attestation_agent.GetTokenRequest.StructuredRuntimeData)
pub StructuredRuntimeData: ::std::option::Option<::std::string::String>,
// special fields
// @@protoc_insertion_point(special_field:attestation_agent.GetTokenRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
Expand All @@ -292,13 +294,18 @@ impl GetTokenRequest {
}

fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(1);
let mut fields = ::std::vec::Vec::with_capacity(2);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>(
"TokenType",
|m: &GetTokenRequest| { &m.TokenType },
|m: &mut GetTokenRequest| { &mut m.TokenType },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"StructuredRuntimeData",
|m: &GetTokenRequest| { &m.StructuredRuntimeData },
|m: &mut GetTokenRequest| { &mut m.StructuredRuntimeData },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<GetTokenRequest>(
"GetTokenRequest",
fields,
Expand All @@ -320,6 +327,9 @@ impl ::protobuf::Message for GetTokenRequest {
10 => {
self.TokenType = is.read_string()?;
},
18 => {
self.StructuredRuntimeData = ::std::option::Option::Some(is.read_string()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
Expand All @@ -335,6 +345,9 @@ impl ::protobuf::Message for GetTokenRequest {
if !self.TokenType.is_empty() {
my_size += ::protobuf::rt::string_size(1, &self.TokenType);
}
if let Some(v) = self.StructuredRuntimeData.as_ref() {
my_size += ::protobuf::rt::string_size(2, &v);
}
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
Expand All @@ -344,6 +357,9 @@ impl ::protobuf::Message for GetTokenRequest {
if !self.TokenType.is_empty() {
os.write_string(1, &self.TokenType)?;
}
if let Some(v) = self.StructuredRuntimeData.as_ref() {
os.write_string(2, v)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}
Expand All @@ -362,12 +378,14 @@ impl ::protobuf::Message for GetTokenRequest {

fn clear(&mut self) {
self.TokenType.clear();
self.StructuredRuntimeData = ::std::option::Option::None;
self.special_fields.clear();
}

fn default_instance() -> &'static GetTokenRequest {
static instance: GetTokenRequest = GetTokenRequest {
TokenType: ::std::string::String::new(),
StructuredRuntimeData: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
Expand Down Expand Up @@ -1125,23 +1143,25 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x17attestation-agent.proto\x12\x11attestation_agent\"6\n\x12GetEviden\
ceRequest\x12\x20\n\x0bRuntimeData\x18\x01\x20\x01(\x0cR\x0bRuntimeData\
\"1\n\x13GetEvidenceResponse\x12\x1a\n\x08Evidence\x18\x01\x20\x01(\x0cR\
\x08Evidence\"/\n\x0fGetTokenRequest\x12\x1c\n\tTokenType\x18\x01\x20\
\x01(\tR\tTokenType\"(\n\x10GetTokenResponse\x12\x14\n\x05Token\x18\x01\
\x20\x01(\x0cR\x05Token\"v\n\x1fExtendRuntimeMeasurementRequest\x12\x16\
\n\x06Events\x18\x01\x20\x03(\x0cR\x06Events\x12)\n\rRegisterIndex\x18\
\x02\x20\x01(\x04H\0R\rRegisterIndex\x88\x01\x01B\x10\n\x0e_RegisterInde\
x\"\"\n\x20ExtendRuntimeMeasurementResponse\"K\n\x11InitDataPlaintext\
\x12\x18\n\x07Content\x18\x01\x20\x01(\x0cR\x07Content\x12\x1c\n\tAlgori\
thm\x18\x02\x20\x01(\tR\tAlgorithm\".\n\x14CheckInitDataRequest\x12\x16\
\n\x06Digest\x18\x01\x20\x01(\x0cR\x06Digest\"\x17\n\x15CheckInitDataRes\
ponse2\xb6\x03\n\x17AttestationAgentService\x12\\\n\x0bGetEvidence\x12%.\
attestation_agent.GetEvidenceRequest\x1a&.attestation_agent.GetEvidenceR\
esponse\x12S\n\x08GetToken\x12\".attestation_agent.GetTokenRequest\x1a#.\
attestation_agent.GetTokenResponse\x12\x83\x01\n\x18ExtendRuntimeMeasure\
ment\x122.attestation_agent.ExtendRuntimeMeasurementRequest\x1a3.attesta\
tion_agent.ExtendRuntimeMeasurementResponse\x12b\n\rCheckInitData\x12'.a\
ttestation_agent.CheckInitDataRequest\x1a(.attestation_agent.CheckInitDa\
taResponseb\x06proto3\
\x08Evidence\"\x84\x01\n\x0fGetTokenRequest\x12\x1c\n\tTokenType\x18\x01\
\x20\x01(\tR\tTokenType\x129\n\x15StructuredRuntimeData\x18\x02\x20\x01(\
\tH\0R\x15StructuredRuntimeData\x88\x01\x01B\x18\n\x16_StructuredRuntime\
Data\"(\n\x10GetTokenResponse\x12\x14\n\x05Token\x18\x01\x20\x01(\x0cR\
\x05Token\"v\n\x1fExtendRuntimeMeasurementRequest\x12\x16\n\x06Events\
\x18\x01\x20\x03(\x0cR\x06Events\x12)\n\rRegisterIndex\x18\x02\x20\x01(\
\x04H\0R\rRegisterIndex\x88\x01\x01B\x10\n\x0e_RegisterIndex\"\"\n\x20Ex\
tendRuntimeMeasurementResponse\"K\n\x11InitDataPlaintext\x12\x18\n\x07Co\
ntent\x18\x01\x20\x01(\x0cR\x07Content\x12\x1c\n\tAlgorithm\x18\x02\x20\
\x01(\tR\tAlgorithm\".\n\x14CheckInitDataRequest\x12\x16\n\x06Digest\x18\
\x01\x20\x01(\x0cR\x06Digest\"\x17\n\x15CheckInitDataResponse2\xb6\x03\n\
\x17AttestationAgentService\x12\\\n\x0bGetEvidence\x12%.attestation_agen\
t.GetEvidenceRequest\x1a&.attestation_agent.GetEvidenceResponse\x12S\n\
\x08GetToken\x12\".attestation_agent.GetTokenRequest\x1a#.attestation_ag\
ent.GetTokenResponse\x12\x83\x01\n\x18ExtendRuntimeMeasurement\x122.atte\
station_agent.ExtendRuntimeMeasurementRequest\x1a3.attestation_agent.Ext\
endRuntimeMeasurementResponse\x12b\n\rCheckInitData\x12'.attestation_age\
nt.CheckInitDataRequest\x1a(.attestation_agent.CheckInitDataResponseb\
\x06proto3\
";

/// `FileDescriptorProto` object which was a source for this generated file
Expand Down
16 changes: 12 additions & 4 deletions attestation-agent/lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ pub trait AttestationAPIs {
) -> Result<Vec<u8>>;

/// Get attestation Token
async fn get_token(&mut self, token_type: &str) -> Result<Vec<u8>>;
async fn get_token(
&mut self,
token_type: &str,
structured_runtime_data: &str,
) -> Result<Vec<u8>>;

/// Get TEE hardware signed evidence that includes the runtime data.
async fn get_evidence(&mut self, runtime_data: &[u8]) -> Result<Vec<u8>>;
Expand Down Expand Up @@ -190,7 +194,11 @@ impl AttestationAPIs for AttestationAgent {
}

#[allow(unreachable_code)]
async fn get_token(&mut self, _token_type: &str) -> Result<Vec<u8>> {
async fn get_token(
&mut self,
_token_type: &str,
_structured_runtime_data: &str,
) -> Result<Vec<u8>> {
let _uri = match self.config.as_ref() {
Some(c) => c.as_uri.clone(),
None => {
Expand All @@ -207,13 +215,13 @@ impl AttestationAPIs for AttestationAgent {
#[cfg(feature = "kbs")]
TokenType::Kbs => {
token::kbs::KbsTokenGetter::default()
.get_token(_uri)
.get_token(_uri, _structured_runtime_data)
.await?
}
#[cfg(feature = "coco_as")]
TokenType::CoCoAS => {
token::coco_as::CoCoASTokenGetter::default()
.get_token(_uri)
.get_token(_uri, _structured_runtime_data)
.await?
}
};
Expand Down
20 changes: 18 additions & 2 deletions attestation-agent/lib/src/token/coco_as.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,35 @@ use anyhow::*;
use async_trait::async_trait;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use base64::Engine;
use sha2::{Digest, Sha384};

#[derive(Default)]
pub struct CoCoASTokenGetter {}

#[async_trait]
impl GetToken for CoCoASTokenGetter {
async fn get_token(&self, as_uri: String) -> Result<Vec<u8>> {
async fn get_token(&self, as_uri: String, structured_runtime_data: &str) -> Result<Vec<u8>> {
let structured_value: serde_json::Value = serde_json::from_str(structured_runtime_data)
.context("Get Token Failed: Structured Runtime Data must be a JSON Map")?;

// TODO: Request AS to get Nonce and insert the Nonce into structured runtime data JSON Map.
Copy link
Member

@fitzthum fitzthum Feb 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even once the AS provides the nonce for the runtime data, how is the KBS supposed to verify the freshness? Normally in RCAR the KBS provides the nonce as part of the challenge, then the attestation must include the nonce. The KBS then insures that the nonce in the attestation matches the nonce that it chose for the challenge. The flow you have here isn't RCAR, it's just A, which I don't think is going to work. Even once you add an additional call to the AA to get a nonce, you still wouldn't be able to verify that the nonce was actually used.

I think we have a somewhat fundamental issue here. I think to be secure the protocol for connecting to the AS would need to look a lot more like RCAR. As in, the AA would return a token similarly to how a KBS would return a resource. I would envision

  1. request a token from the AS
  2. AS gives back a nonce
  3. AA sends the evidence
  4. AS checks the nonce (and the evidence) and returns a Token

One issue is that currently the AS is not stateful so I don't know how it would do step 4. Looking at the steps, this is basically exactly what the KBS does. So I wonder if we should really bother with replacing it.

cc: @Xynnn007

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. A challenge-response protocol like RCAR (which requires 4-round communication) would effciently prevent replay-attack in CoCoAS and I think @jialez0 will add that support inside CoCoAS later.

Another question is how we design the API of get_token().
Try to think about this: if we already had a challenge-response protocol in CoCoAS, the challenge-response protocol could be handled inside the CoCoAS' get_token() handler. The only reason why we need the API of get_token() to have extra runtime_data argument is to specify the TEE public key. This is somehow a complicated situation.

Overall, KBS and CoCoAS should be different separate component. We can embed the public key claims as runtime data to request CoCoAS to check integrity, but

  1. this requires the caller/user of AA to prepare the key pair manually
  2. the actual runtime data would be two parts. One is from the parameter runtime_data like the public key and the other is the nonce got from CoCoAS during the protocol logic inside get_token() function.

The reason why we face the delima is that we try to couple AS token's with KBS token.

AS token semantically means the endorsement of the evidence, and the claims against the reference values/policies are correct.

KBS token semantically means it is authorized to access specific resources. It is hard to say AS token have ability to work as an authorized token.

The coincidence is that they are the same now. TBO we now are using them without distinguishment, but it works fine so far regardless of the coupling.

My personal preference, in short term is

  1. Still have the extra runtime_data parameter to get_token().
  2. leave current coco-as token logic as what is implemented in this PR. This means this handler would support user-defined random runtime claims. The usage is defined by the caller.
  3. Adds another token type whose get_token() will support public key generation, handshake with CoCoAS, and return the token with format that KBS recognizes. The handler of this token will not care about the given runtime_data parameter. This seems like a workaround before we have a more clear boundary between KBS token and AS token.

In long term, we should carefully think about the authentication and authorization of attestation system, including

  1. The authentication and authorization flow of KBS resources based on attestation, where the independence of individual components can be maintained without coupling
  2. The format and usages of different token. Whether they can be used interchangeably? If so, how? If not, what is the boundary?

We'd better design this align with current standards without inventing new wheels. After initdata, we will have richer toolbox to achieve this.

does this make sense? @fitzthum @jialez0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right that we are conflating the KBS Token and the AS Token. I think we're also trying to split the RCAR protocol between three different parties. This is very confusing.

Since we already have a way to support a passport mode, I am hesitant to go forward with something that isn't clear. I know that the existing approach is not semantically correct, but otherwise it seems like it works.

Here is one way we could think about passport mode with only one KBS. Maybe we should think about the AS token not as something that can stand in for the KBS token, but as something that can stand in for evidence. There is one problem with this approach but generally I think it makes sense.

Basically, the AA would still go through a full RCAR flow with the KBS, but instead of providing hw evidence in the attestation, it would provide the AS token. Then instead of contacting the AS to verify the attestation, the KBS would use this AS token directly.

The issue here is that if the AS token were generated before connecting to the KBS, I'm not sure how we would bind it to the public key and nonce needed in the RCAR.

Anyway, enjoy the new year. Afterwards maybe we can try to draw some diagrams.


let hash_materials =
serde_json::to_vec(&structured_value).context("parse JSON structured data")?;
let mut hasher = Sha384::new();
hasher.update(hash_materials);
let structured_data_digest = hasher.finalize().to_vec();

let tee_type = attester::detect_tee_type();
let attester = attester::BoxedAttester::try_from(tee_type)?;
let evidence = attester.get_evidence(vec![]).await?;
let evidence = attester.get_evidence(structured_data_digest).await?;

let request_body = serde_json::json!({
"tee": serde_json::to_string(&tee_type)?,
"runtime_data": {
"structured": structured_value
},
"runtime_data_hash_algorithm": "sha384",
"evidence": URL_SAFE_NO_PAD.encode(evidence.as_bytes()),
});

Expand Down
Loading
Loading