Skip to content

Commit

Permalink
AA: add check_init_data API
Browse files Browse the repository at this point in the history
This api is used to check the current TEE evidence's initdata field,
like TDX's MRCONFIGID, SNP's HOSTDATA, etc. If the one inside evidence
is different from the one provided, the RPC will raise an error.

The operation of getting current TEE's evidence should be network
independent, because AA usually runs at an early stage of a guest, where
network is usually not prepared.

Signed-off-by: Xynnn007 <[email protected]>
  • Loading branch information
Xynnn007 committed Jan 29, 2024
1 parent 6fde922 commit 56a8067
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 8 deletions.
57 changes: 57 additions & 0 deletions attestation-agent/app/src/rpc/attestation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,35 @@ pub mod grpc {

Result::Ok(Response::new(reply))
}

async fn check_init_data(
&self,
request: Request<CheckInitDataRequest>,
) -> Result<Response<CheckInitDataResponse>, Status> {
let request = request.into_inner();

let attestation_agent_mutex_clone = Arc::clone(&ASYNC_ATTESTATION_AGENT);
let mut attestation_agent = attestation_agent_mutex_clone.lock().await;

debug!("Call AA to check init data ...");

attestation_agent
.check_init_data(request.init_data_digest, request.init_data_plaintext)
.await
.map_err(|e| {
error!("Call AA to check init data failed: {}", e);
Status::internal(format!(
"[ERROR:{}] AA check init data failed: {}",
AGENT_NAME, e
))
})?;

debug!("Extend runtime measurement successfully!");

let reply = ExtendRuntimeMeasurementResponse {};

Result::Ok(Response::new(reply))
}
}

pub async fn start_grpc_service(socket: SocketAddr) -> Result<()> {
Expand Down Expand Up @@ -236,6 +265,34 @@ pub mod ttrpc {
let reply = attestation_agent::ExtendRuntimeMeasurementResponse::new();
::ttrpc::Result::Ok(reply)
}

async fn check_init_data(
&self,
_ctx: &::ttrpc::r#async::TtrpcContext,
req: attestation_agent::CheckInitDataRequest,
) -> ::ttrpc::Result<attestation_agent::CheckInitDataResponse> {
debug!("Call AA to check initdata ...");

let attestation_agent_mutex_clone = ASYNC_ATTESTATION_AGENT.clone();
let mut attestation_agent = attestation_agent_mutex_clone.lock().await;

attestation_agent
.check_init_data(req.InitDataDigest, req.InitDataPlaintext)
.await
.map_err(|e| {
error!("Call AA to check initdata failed: {}", e);
let mut error_status = ::ttrpc::proto::Status::new();
error_status.set_code(Code::INTERNAL);
error_status.set_message(format!(
"[ERROR:{}] AA check initdata failed: {}",
AGENT_NAME, e
));
::ttrpc::Error::RpcStatus(error_status)
})?;

let reply = attestation_agent::CheckInitDataResponse::new();
::ttrpc::Result::Ok(reply)
}
}

pub fn start_ttrpc_service() -> Result<HashMap<String, Service>> {
Expand Down
4 changes: 4 additions & 0 deletions attestation-agent/attester/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ pub trait Attester {
) -> Result<()> {
bail!("Unimplemented")
}

async fn check_init_data(&mut self, _init_data: Vec<u8>) -> Result<()> {
bail!("Unimplemented");
}
}

// Detect which TEE platform the KBC running environment is.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,249 @@ impl ::protobuf::reflect::ProtobufValue for ExtendRuntimeMeasurementResponse {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}

// @@protoc_insertion_point(message:attestation_agent.CheckInitDataRequest)
#[derive(PartialEq,Clone,Default,Debug)]
pub struct CheckInitDataRequest {
// message fields
// @@protoc_insertion_point(field:attestation_agent.CheckInitDataRequest.InitDataDigest)
pub InitDataDigest: ::std::vec::Vec<u8>,
// @@protoc_insertion_point(field:attestation_agent.CheckInitDataRequest.InitDataPlaintext)
pub InitDataPlaintext: ::std::option::Option<::std::vec::Vec<u8>>,
// special fields
// @@protoc_insertion_point(special_field:attestation_agent.CheckInitDataRequest.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}

impl<'a> ::std::default::Default for &'a CheckInitDataRequest {
fn default() -> &'a CheckInitDataRequest {
<CheckInitDataRequest as ::protobuf::Message>::default_instance()
}
}

impl CheckInitDataRequest {
pub fn new() -> CheckInitDataRequest {
::std::default::Default::default()
}

fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
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::<_, _>(
"InitDataDigest",
|m: &CheckInitDataRequest| { &m.InitDataDigest },
|m: &mut CheckInitDataRequest| { &mut m.InitDataDigest },
));
fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>(
"InitDataPlaintext",
|m: &CheckInitDataRequest| { &m.InitDataPlaintext },
|m: &mut CheckInitDataRequest| { &mut m.InitDataPlaintext },
));
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<CheckInitDataRequest>(
"CheckInitDataRequest",
fields,
oneofs,
)
}
}

impl ::protobuf::Message for CheckInitDataRequest {
const NAME: &'static str = "CheckInitDataRequest";

fn is_initialized(&self) -> bool {
true
}

fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
10 => {
self.InitDataDigest = is.read_bytes()?;
},
18 => {
self.InitDataPlaintext = ::std::option::Option::Some(is.read_bytes()?);
},
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}

// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
if !self.InitDataDigest.is_empty() {
my_size += ::protobuf::rt::bytes_size(1, &self.InitDataDigest);
}
if let Some(v) = self.InitDataPlaintext.as_ref() {
my_size += ::protobuf::rt::bytes_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
}

fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
if !self.InitDataDigest.is_empty() {
os.write_bytes(1, &self.InitDataDigest)?;
}
if let Some(v) = self.InitDataPlaintext.as_ref() {
os.write_bytes(2, v)?;
}
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}

fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}

fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}

fn new() -> CheckInitDataRequest {
CheckInitDataRequest::new()
}

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

fn default_instance() -> &'static CheckInitDataRequest {
static instance: CheckInitDataRequest = CheckInitDataRequest {
InitDataDigest: ::std::vec::Vec::new(),
InitDataPlaintext: ::std::option::Option::None,
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}

impl ::protobuf::MessageFull for CheckInitDataRequest {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("CheckInitDataRequest").unwrap()).clone()
}
}

impl ::std::fmt::Display for CheckInitDataRequest {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}

impl ::protobuf::reflect::ProtobufValue for CheckInitDataRequest {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}

// @@protoc_insertion_point(message:attestation_agent.CheckInitDataResponse)
#[derive(PartialEq,Clone,Default,Debug)]
pub struct CheckInitDataResponse {
// special fields
// @@protoc_insertion_point(special_field:attestation_agent.CheckInitDataResponse.special_fields)
pub special_fields: ::protobuf::SpecialFields,
}

impl<'a> ::std::default::Default for &'a CheckInitDataResponse {
fn default() -> &'a CheckInitDataResponse {
<CheckInitDataResponse as ::protobuf::Message>::default_instance()
}
}

impl CheckInitDataResponse {
pub fn new() -> CheckInitDataResponse {
::std::default::Default::default()
}

fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData {
let mut fields = ::std::vec::Vec::with_capacity(0);
let mut oneofs = ::std::vec::Vec::with_capacity(0);
::protobuf::reflect::GeneratedMessageDescriptorData::new_2::<CheckInitDataResponse>(
"CheckInitDataResponse",
fields,
oneofs,
)
}
}

impl ::protobuf::Message for CheckInitDataResponse {
const NAME: &'static str = "CheckInitDataResponse";

fn is_initialized(&self) -> bool {
true
}

fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> {
while let Some(tag) = is.read_raw_tag_or_eof()? {
match tag {
tag => {
::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}

// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u64 {
let mut my_size = 0;
my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields());
self.special_fields.cached_size().set(my_size as u32);
my_size
}

fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> {
os.write_unknown_fields(self.special_fields.unknown_fields())?;
::std::result::Result::Ok(())
}

fn special_fields(&self) -> &::protobuf::SpecialFields {
&self.special_fields
}

fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields {
&mut self.special_fields
}

fn new() -> CheckInitDataResponse {
CheckInitDataResponse::new()
}

fn clear(&mut self) {
self.special_fields.clear();
}

fn default_instance() -> &'static CheckInitDataResponse {
static instance: CheckInitDataResponse = CheckInitDataResponse {
special_fields: ::protobuf::SpecialFields::new(),
};
&instance
}
}

impl ::protobuf::MessageFull for CheckInitDataResponse {
fn descriptor() -> ::protobuf::reflect::MessageDescriptor {
static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new();
descriptor.get(|| file_descriptor().message_by_package_relative_name("CheckInitDataResponse").unwrap()).clone()
}
}

impl ::std::fmt::Display for CheckInitDataResponse {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}

impl ::protobuf::reflect::ProtobufValue for CheckInitDataResponse {
type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage<Self>;
}

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\
Expand All @@ -765,13 +1008,18 @@ static file_descriptor_proto_data: &'static [u8] = b"\
\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\x20ExtendRuntimeMeasurementResponse2\xd2\x02\n\x17AttestationAge\
ntService\x12\\\n\x0bGetEvidence\x12%.attestation_agent.GetEvidenceReque\
st\x1a&.attestation_agent.GetEvidenceResponse\x12S\n\x08GetToken\x12\".a\
ttestation_agent.GetTokenRequest\x1a#.attestation_agent.GetTokenResponse\
\x12\x83\x01\n\x18ExtendRuntimeMeasurement\x122.attestation_agent.Extend\
RuntimeMeasurementRequest\x1a3.attestation_agent.ExtendRuntimeMeasuremen\
tResponseb\x06proto3\
x\"\"\n\x20ExtendRuntimeMeasurementResponse\"\x87\x01\n\x14CheckInitData\
Request\x12&\n\x0eInitDataDigest\x18\x01\x20\x01(\x0cR\x0eInitDataDigest\
\x121\n\x11InitDataPlaintext\x18\x02\x20\x01(\x0cH\0R\x11InitDataPlainte\
xt\x88\x01\x01B\x14\n\x12_InitDataPlaintext\"\x17\n\x15CheckInitDataResp\
onse2\xb6\x03\n\x17AttestationAgentService\x12\\\n\x0bGetEvidence\x12%.a\
ttestation_agent.GetEvidenceRequest\x1a&.attestation_agent.GetEvidenceRe\
sponse\x12S\n\x08GetToken\x12\".attestation_agent.GetTokenRequest\x1a#.a\
ttestation_agent.GetTokenResponse\x12\x83\x01\n\x18ExtendRuntimeMeasurem\
ent\x122.attestation_agent.ExtendRuntimeMeasurementRequest\x1a3.attestat\
ion_agent.ExtendRuntimeMeasurementResponse\x12b\n\rCheckInitData\x12'.at\
testation_agent.CheckInitDataRequest\x1a(.attestation_agent.CheckInitDat\
aResponseb\x06proto3\
";

/// `FileDescriptorProto` object which was a source for this generated file
Expand All @@ -789,13 +1037,15 @@ pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor {
file_descriptor.get(|| {
let generated_file_descriptor = generated_file_descriptor_lazy.get(|| {
let mut deps = ::std::vec::Vec::with_capacity(0);
let mut messages = ::std::vec::Vec::with_capacity(6);
let mut messages = ::std::vec::Vec::with_capacity(8);
messages.push(GetEvidenceRequest::generated_message_descriptor_data());
messages.push(GetEvidenceResponse::generated_message_descriptor_data());
messages.push(GetTokenRequest::generated_message_descriptor_data());
messages.push(GetTokenResponse::generated_message_descriptor_data());
messages.push(ExtendRuntimeMeasurementRequest::generated_message_descriptor_data());
messages.push(ExtendRuntimeMeasurementResponse::generated_message_descriptor_data());
messages.push(CheckInitDataRequest::generated_message_descriptor_data());
messages.push(CheckInitDataResponse::generated_message_descriptor_data());
let mut enums = ::std::vec::Vec::with_capacity(0);
::protobuf::reflect::GeneratedFileDescriptor::new_generated(
file_descriptor_proto(),
Expand Down
Loading

0 comments on commit 56a8067

Please sign in to comment.