From 73c42e91e0f7ed354f6158da2f7061451bb9139d Mon Sep 17 00:00:00 2001 From: Kartik Joshi Date: Thu, 15 Feb 2024 15:48:16 +0530 Subject: [PATCH] Verifier: Refactor errors in sgx module Fixes: #231 Signed-off-by: Kartik Joshi --- Cargo.lock | 2 + attestation-service/verifier/Cargo.toml | 2 + attestation-service/verifier/src/sgx/mod.rs | 65 +++++++++++++++------ 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4029bcd158..c195f6b94f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5275,6 +5275,7 @@ dependencies = [ "ear", "eventlog-rs", "hex", + "jsonwebkey", "jsonwebtoken", "kbs-types", "log", @@ -5288,6 +5289,7 @@ dependencies = [ "sgx-dcap-quoteverify-rs", "shadow-rs", "strum", + "thiserror", "tokio", "tonic-build", "veraison-apiclient", diff --git a/attestation-service/verifier/Cargo.toml b/attestation-service/verifier/Cargo.toml index 17480f34e5..ef0cd9df9c 100644 --- a/attestation-service/verifier/Cargo.toml +++ b/attestation-service/verifier/Cargo.toml @@ -16,6 +16,7 @@ cca-verifier = [ "ear", "jsonwebtoken", "veraison-apiclient" ] [dependencies] anyhow.workspace = true +thiserror.workspace = true asn1-rs = { version = "0.5.1", optional = true } async-trait.workspace = true az-snp-vtpm = { version = "0.5.2", default-features = false, features = ["verifier"], optional = true } @@ -29,6 +30,7 @@ codicon = { version = "3.0", optional = true } csv-rs = { git = "https://github.com/openanolis/csv-rs", rev = "b74aa8c", optional = true } eventlog-rs = { version = "0.1.3", optional = true } hex.workspace = true +jsonwebkey = "0.3.5" jsonwebtoken = { workspace = true, default-features = false, optional = true } kbs-types.workspace = true log.workspace = true diff --git a/attestation-service/verifier/src/sgx/mod.rs b/attestation-service/verifier/src/sgx/mod.rs index 6a355e5921..701be4ba4c 100644 --- a/attestation-service/verifier/src/sgx/mod.rs +++ b/attestation-service/verifier/src/sgx/mod.rs @@ -18,6 +18,7 @@ use sgx_dcap_quoteverify_rs::{ sgx_ql_qv_result_t, sgx_ql_qv_supplemental_t, tee_get_supplemental_data_version_and_size, tee_qv_get_collateral, tee_supp_data_descriptor_t, tee_verify_quote, }; +use thiserror::Error; use crate::{regularize_data, InitDataHash, ReportData}; @@ -41,6 +42,36 @@ struct SgxEvidence { #[derive(Debug, Default)] pub struct SgxVerifier {} +#[derive(Error, Debug)] +pub enum SgxError { + #[error("Deserialize Quote failed: {0}")] + FailedtoDeserializeQuote(String), + #[error("Sgx verifier error: {0}")] + SgxVerifierErr(String), + #[error("Parse SGX quote failed: {0}")] + ParseSgxQuote(String), + #[error("Evidence's identity verification error: {0}")] + EvidenceIdentityVerification(String), + #[error("REPORT_DATA is different from that in SGX Quote")] + ReportDataMismatch, + #[error("CONFIGID is different from that in SGX Quote")] + ConfigIdMismatch, + #[error("Base64 decode error: {0}")] + Base64Err(#[from] base64::DecodeError), + #[error("try from slice error: {0}")] + TryfromSlice(#[from] std::array::TryFromSliceError), + #[error("tee_get_quote_supplemental_data_size failed: {0}")] + TeeGetQuoteSupplemtalData(String), + #[error("Verification completed with Terminal result: {0}")] + QuoteVerificationResult(String), + #[error("generate_parsed_claims failed: {0}")] + GenerateParsedClaims(String), + #[error("ecdsa quote verification failed: {0}")] + ECDSAQuoteVerification(String), + #[error("anyhow error: {0}")] + Anyhow(#[from] anyhow::Error), +} + #[async_trait] impl Verifier for SgxVerifier { async fn evaluate( @@ -49,41 +80,41 @@ impl Verifier for SgxVerifier { expected_report_data: &ReportData, expected_init_data_hash: &InitDataHash, ) -> Result { - let tee_evidence = - serde_json::from_slice::(evidence).context("Deserialize Quote failed.")?; + let tee_evidence = serde_json::from_slice::(evidence) + .map_err(|err| SgxError::FailedtoDeserializeQuote(err.to_string()))?; debug!("TEE-Evidence: {:?}", &tee_evidence); verify_evidence(expected_report_data, expected_init_data_hash, tee_evidence) .await - .map_err(|e| anyhow!("SGX Verifier: {:?}", e)) + .map_err(|e| SgxError::SgxVerifierErr(e.to_string()).into()) } } -pub fn parse_sgx_quote(quote: &[u8]) -> Result { +pub fn parse_sgx_quote(quote: &[u8]) -> Result { let quote_body = "e[..QUOTE_SIZE]; quote_body .pread::(0) - .map_err(|e| anyhow!("Parse SGX quote failed: {:?}", e)) + .map_err(|e| SgxError::ParseSgxQuote(e.to_string())) } async fn verify_evidence( expected_report_data: &ReportData<'_>, expected_init_data_hash: &InitDataHash<'_>, evidence: SgxEvidence, -) -> Result { +) -> Result { let quote_bin = base64::engine::general_purpose::STANDARD.decode(evidence.quote)?; ecdsa_quote_verification("e_bin) .await - .context("Evidence's identity verification error.")?; + .map_err(|e| SgxError::EvidenceIdentityVerification(e.to_string()))?; let quote = parse_sgx_quote("e_bin)?; if let ReportData::Value(expected_report_data) = expected_report_data { debug!("Check the binding of REPORT_DATA."); let expected_report_data = regularize_data(expected_report_data, 64, "REPORT_DATA", "SGX"); if expected_report_data != quote.report_body.report_data { - bail!("REPORT_DATA is different from that in SGX Quote"); + return Err(SgxError::ReportDataMismatch); } } @@ -92,14 +123,15 @@ async fn verify_evidence( let expected_init_data_hash = regularize_data(expected_init_data_hash, 64, "CONFIGID", "SGX"); if expected_init_data_hash != quote.report_body.config_id { - bail!("CONFIGID is different from that in SGX Quote"); + return Err(SgxError::ConfigIdMismatch); } } claims::generate_parsed_claims(quote) + .map_err(|err| SgxError::GenerateParsedClaims(err.to_string())) } -async fn ecdsa_quote_verification(quote: &[u8]) -> Result<()> { +async fn ecdsa_quote_verification(quote: &[u8]) -> Result<(), SgxError> { let mut supp_data: sgx_ql_qv_supplemental_t = Default::default(); let mut supp_data_desc = tee_supp_data_descriptor_t { major_version: 0, @@ -122,10 +154,7 @@ async fn ecdsa_quote_verification(quote: &[u8]) -> Result<()> { warn!("Quote supplemental data size is different between DCAP QVL and QvE, please make sure you installed DCAP QVL and QvE from same release.") } } - Err(e) => bail!( - "tee_get_quote_supplemental_data_size failed: {:#04x}", - e as u32 - ), + Err(e) => return Err(SgxError::TeeGetQuoteSupplemtalData(format!("{:?}", e))), } // get collateral @@ -183,14 +212,14 @@ async fn ecdsa_quote_verification(quote: &[u8]) -> Result<()> { ); } _ => { - bail!( - "Verification completed with Terminal result: {:x}", + return Err(SgxError::QuoteVerificationResult(format!( + "{:?}", quote_verification_result as u32 - ); + ))) } } - Ok(()) + Ok(()).map_err(|err| SgxError::ECDSAQuoteVerification(err.to_string())) } #[cfg(test)]