Skip to content

Commit 3713a5a

Browse files
committed
add allowed_tcb_statuses and allowed_advisory_ids option to attestation command
Signed-off-by: Jun Kimura <[email protected]>
1 parent 5cc698b commit 3713a5a

File tree

7 files changed

+108
-19
lines changed

7 files changed

+108
-19
lines changed

app/src/commands/attestation.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ use host::store::transaction::CommitStore;
1010
use remote_attestation::{
1111
dcap,
1212
dcap_pcs::client::PCSClient,
13+
dcap_quote_verifier::verifier::Status,
1314
dcap_simulation::{DCAP_SIM_ROOT_CA_PEM, DCAP_SIM_ROOT_KEY_PKCS8},
14-
dcap_utils::ValidatedPCSClient,
15+
dcap_utils::{QVResultAllowList, ValidatedPCSClient},
1516
ias, zkdcap, IASMode,
1617
};
1718
use remote_attestation::{
@@ -327,6 +328,7 @@ fn run_dcap_remote_attestation<E: EnclaveCommandAPI<S>, S: CommitStore>(
327328
enclave.get_key_manager(),
328329
Address::from_hex_string(&cmd.enclave_key)?,
329330
cmd.collateral_service.clone().into(),
331+
Default::default(),
330332
)?;
331333
Ok(())
332334
}
@@ -344,6 +346,18 @@ pub struct ZKDCAPRemoteAttestation {
344346
pub enclave_key: String,
345347
#[clap(flatten)]
346348
pub collateral_service: SgxCollateralService,
349+
#[clap(
350+
long = "allowed_tcb_statuses",
351+
value_delimiter = ',',
352+
help = "Allowed TCB status list"
353+
)]
354+
pub allowed_tcb_statuses: Vec<Status>,
355+
#[clap(
356+
long = "allowed_advisory_ids",
357+
value_delimiter = ',',
358+
help = "Allowed advisory ID list"
359+
)]
360+
pub allowed_advisory_ids: Vec<String>,
347361
#[clap(long = "program_path", help = "Path to the zkVM guest program")]
348362
pub program_path: Option<PathBuf>,
349363
#[clap(
@@ -421,6 +435,10 @@ fn run_zkdcap_remote_attestation<E: EnclaveCommandAPI<S>, S: CommitStore>(
421435
cmd.get_zkvm_program()?.as_ref(),
422436
cmd.disable_pre_execution,
423437
cmd.collateral_service.clone().into(),
438+
QVResultAllowList::new(
439+
cmd.allowed_tcb_statuses.clone(),
440+
cmd.allowed_advisory_ids.clone(),
441+
),
424442
)?;
425443
Ok(())
426444
}

modules/remote-attestation/src/dcap.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::dcap_utils::{DCAPRemoteAttestationResult, ValidatedPCSClient};
1+
use crate::dcap_utils::{DCAPRemoteAttestationResult, QVResultAllowList, ValidatedPCSClient};
22
use crate::errors::Error;
33
use anyhow::anyhow;
44
use attestation_report::QEType;
@@ -27,9 +27,16 @@ pub fn run_dcap_ra(
2727
key_manager: &EnclaveKeyManager,
2828
target_enclave_key: Address,
2929
pcs_client: ValidatedPCSClient,
30+
allow_list: QVResultAllowList,
3031
) -> Result<(), Error> {
3132
let current_time = Time::now();
32-
let result = dcap_ra(key_manager, target_enclave_key, current_time, pcs_client)?;
33+
let result = dcap_ra(
34+
key_manager,
35+
target_enclave_key,
36+
current_time,
37+
pcs_client,
38+
allow_list,
39+
)?;
3340

3441
key_manager
3542
.update_ra_quote(target_enclave_key, result.to_ra_quote().into())
@@ -44,6 +51,7 @@ pub(crate) fn dcap_ra(
4451
target_enclave_key: Address,
4552
current_time: Time,
4653
pcs_client: ValidatedPCSClient,
54+
allow_list: QVResultAllowList,
4755
) -> Result<DCAPRemoteAttestationResult, Error> {
4856
let ek_info = key_manager.load(target_enclave_key).map_err(|e| {
4957
Error::key_manager(
@@ -88,6 +96,13 @@ pub(crate) fn dcap_ra(
8896
output.status, output.advisory_ids, output.validity, output.min_tcb_evaluation_data_number,
8997
);
9098

99+
if let Some(false) = allow_list.is_allowed_tcb_status(output.status) {
100+
return Err(Error::tcb_status_not_allowed(output.status));
101+
}
102+
if let Some(false) = allow_list.is_allowed_advisory_ids(&output.advisory_ids) {
103+
return Err(Error::advisory_ids_not_allowed(output.advisory_ids.clone()));
104+
}
105+
91106
Ok(DCAPRemoteAttestationResult {
92107
raw_quote,
93108
output,

modules/remote-attestation/src/dcap_utils.rs

+33-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use attestation_report::DCAPQuote;
22
use dcap_pcs::client::PCSClient;
3-
use dcap_quote_verifier::verifier::QuoteVerificationOutput;
3+
use dcap_quote_verifier::verifier::{QuoteVerificationOutput, Status};
44
use dcap_quote_verifier::{collateral::QvCollateral, types::quotes::CertData};
55
use lcp_types::proto::lcp::service::enclave::v1::{QvCollateral as ProtoQvCollateral, Validity};
66
use std::ops::Deref;
@@ -61,6 +61,38 @@ impl Deref for ValidatedPCSClient {
6161
}
6262
}
6363

64+
/// A list of TCB statuses and advisory IDs that are allowed.
65+
#[derive(Debug, Clone, Default)]
66+
pub struct QVResultAllowList {
67+
pub tcb_statuses: Vec<Status>,
68+
pub advisory_ids: Vec<String>,
69+
}
70+
71+
impl QVResultAllowList {
72+
pub fn new(tcb_statuses: Vec<Status>, advisory_ids: Vec<String>) -> Self {
73+
Self {
74+
tcb_statuses,
75+
advisory_ids,
76+
}
77+
}
78+
79+
pub fn is_allowed_tcb_status(&self, tcb_status: Status) -> Option<bool> {
80+
if self.tcb_statuses.is_empty() {
81+
None
82+
} else {
83+
Some(self.tcb_statuses.contains(&tcb_status))
84+
}
85+
}
86+
87+
pub fn is_allowed_advisory_ids(&self, advisory_ids: &[String]) -> Option<bool> {
88+
if self.advisory_ids.is_empty() {
89+
None
90+
} else {
91+
Some(advisory_ids.iter().all(|id| self.advisory_ids.contains(id)))
92+
}
93+
}
94+
}
95+
6496
#[derive(Debug)]
6597
pub struct DCAPRemoteAttestationResult {
6698
pub raw_quote: Vec<u8>,

modules/remote-attestation/src/errors.rs

+27-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use attestation_report::QEType;
2+
use dcap_quote_verifier::verifier::Status;
23
use flex_error::*;
34
use lcp_types::Time;
45
use sgx_types::{sgx_quote3_error_t, sgx_status_t};
@@ -19,7 +20,7 @@ define_error! {
1920
descr: String,
2021
}
2122
|e| {
22-
format_args!("InvalidUtf8: bytes={:?} descr={}", e.bytes, e.descr)
23+
format_args!("Invalid utf8: bytes={:?} descr={}", e.bytes, e.descr)
2324
},
2425

2526
InvalidU32String {
@@ -28,7 +29,7 @@ define_error! {
2829
descr: String,
2930
}
3031
|e| {
31-
format_args!("InvalidU32String: string={} descr={}", e.string, e.descr)
32+
format_args!("Invalid u32 string: string={} descr={}", e.string, e.descr)
3233
},
3334

3435
Base64Decode {
@@ -43,7 +44,7 @@ define_error! {
4344
value: String,
4445
}
4546
|e| {
46-
format_args!("InvalidPercentDecode: value={}", e.value)
47+
format_args!("Invalid percent decode: value={}", e.value)
4748
},
4849

4950
IoError {
@@ -60,7 +61,7 @@ define_error! {
6061

6162
InvalidIasServerName
6263
|_| {
63-
format_args!("InvalidServerName")
64+
format_args!("Invalid IAS server name")
6465
},
6566

6667
HttpParseError
@@ -80,7 +81,7 @@ define_error! {
8081
status: reqwest::StatusCode,
8182
}
8283
|e| {
83-
format_args!("InvalidHTTPStatus: url={} status={}", e.url, e.status)
84+
format_args!("Invalid HTTP status: url={} status={}", e.url, e.status)
8485
},
8586

8687
Pem
@@ -95,15 +96,15 @@ define_error! {
9596
port: u16,
9697
}
9798
|e| {
98-
format_args!("CannotLookupAddress: host={} port={}", e.host, e.port)
99+
format_args!("Cannot lookup address: host={} port={}", e.host, e.port)
99100
},
100101

101102
TooOldReportTimestamp {
102103
now: Time,
103104
timestamp: Time
104105
}
105106
|e| {
106-
format_args!("TooOldReportTimestamp: the timestamp of the report is too old: now={:?} attestation_time={:?}", e.now, e.timestamp)
107+
format_args!("Too old report timestamp: the timestamp of the report is too old: now={:?} attestation_time={:?}", e.now, e.timestamp)
107108
},
108109

109110
AttestationReport
@@ -123,35 +124,35 @@ define_error! {
123124
descr: String
124125
}
125126
|e| {
126-
format_args!("UnexpectedIASReportResponse error: {}", e.descr)
127+
format_args!("Unexpected IAS Report response error: {}", e.descr)
127128
},
128129

129130
UnexpectedSigrlResponse {
130131
descr: String
131132
}
132133
|e| {
133-
format_args!("UnexpectedSigrlResponse error: {}", e.descr)
134+
format_args!("Unexpected sigrl response error: {}", e.descr)
134135
},
135136

136137
UnexpectedIasReportCertificateResponse {
137138
descr: String
138139
}
139140
|e| {
140-
format_args!("UnexpectedIASReportCertificateResponse error: {}", e.descr)
141+
format_args!("Unexpected IAS certificate response error: {}", e.descr)
141142
},
142143

143144
UnexpectedReport {
144145
descr: String
145146
}
146147
|e| {
147-
format_args!("UnexpectedReport error: {}", e.descr)
148+
format_args!("Unexpected report error: {}", e.descr)
148149
},
149150

150151
UnexpectedQuote {
151152
descr: String
152153
}
153154
|e| {
154-
format_args!("UnexpectedQuoteError: {}", e.descr)
155+
format_args!("Unexpected quote error: {}", e.descr)
155156
},
156157

157158
UnexpectedQeType {
@@ -162,6 +163,20 @@ define_error! {
162163
format_args!("Unexpected QE type: expected={:?} actual={:?}", e.expected, e.actual)
163164
},
164165

166+
TcbStatusNotAllowed {
167+
tcb_status: Status,
168+
}
169+
|e| {
170+
format_args!("TCB status Not allowed: tcb_status={:?}", e.tcb_status)
171+
},
172+
173+
AdvisoryIdsNotAllowed {
174+
advisory_ids: Vec<String>,
175+
}
176+
|e| {
177+
format_args!("Advisory Ids Not allowed: advisory_ids={:?}", e.advisory_ids)
178+
},
179+
165180
SgxError {
166181
status: sgx_status_t,
167182
descr: String

modules/remote-attestation/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub mod zkdcap;
1212

1313
pub use common::get_target_qe_info;
1414
pub use dcap_pcs;
15+
pub use dcap_quote_verifier;
1516
pub use ias_utils::{validate_qe_report, IASMode, IAS_HOSTNAME};
1617
#[cfg(feature = "sgx-sw")]
1718
pub use rsa;

modules/remote-attestation/src/zkdcap.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
dcap::dcap_ra,
33
dcap_simulation::{dcap_ra_simulation, DCAPRASimulationOpts},
4-
dcap_utils::{DCAPRemoteAttestationResult, ValidatedPCSClient},
4+
dcap_utils::{DCAPRemoteAttestationResult, QVResultAllowList, ValidatedPCSClient},
55
errors::Error,
66
};
77
use anyhow::anyhow;
@@ -34,6 +34,7 @@ pub fn run_zkdcap_ra(
3434
elf: &[u8],
3535
disable_pre_execution: bool,
3636
pcs_client: ValidatedPCSClient,
37+
allow_list: QVResultAllowList,
3738
) -> Result<(), Error> {
3839
let image_id = compute_image_id(elf)
3940
.map_err(|e| Error::anyhow(anyhow!("cannot compute image id: {}", e)))?;
@@ -43,7 +44,13 @@ pub fn run_zkdcap_ra(
4344
);
4445

4546
let current_time = Time::now();
46-
let res = dcap_ra(key_manager, target_enclave_key, current_time, pcs_client)?;
47+
let res = dcap_ra(
48+
key_manager,
49+
target_enclave_key,
50+
current_time,
51+
pcs_client,
52+
allow_list,
53+
)?;
4754

4855
zkdcap_ra(
4956
key_manager,

tests/integration/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ mod tests {
3838
use lcp_proto::protobuf::Protobuf;
3939
use lcp_types::{ClientId, Height};
4040
use log::*;
41-
use remote_attestation::dcap_utils::ValidatedPCSClient;
4241
use std::str::FromStr;
4342
use std::sync::{Arc, RwLock};
4443
use store::{host::HostStore, memory::MemStore};
@@ -227,6 +226,7 @@ mod tests {
227226
#[cfg(not(feature = "sgx-sw"))]
228227
{
229228
use remote_attestation::dcap_pcs::client::PCSClient;
229+
use remote_attestation::dcap_utils::ValidatedPCSClient;
230230
use remote_attestation::zkdcap::run_zkdcap_ra;
231231
use remote_attestation::zkvm::prover::Risc0ProverMode;
232232
use zkdcap_risc0::DCAP_QUOTE_VERIFIER_ELF;
@@ -259,6 +259,7 @@ mod tests {
259259
),
260260
None,
261261
),
262+
Default::default(),
262263
);
263264
assert!(res.is_ok(), "zkDCAP Remote Attestation Failed {:?}", res);
264265
}

0 commit comments

Comments
 (0)