Skip to content

Commit

Permalink
Verifier: Add IBM Secure Execution verifier driver framework
Browse files Browse the repository at this point in the history
* Verifier: Add IBM Secure Execution verifier driver framework

Signed-off-by: Qi Feng Huo <[email protected]>

* kbs/attestation: support attestation service to generate Challenge

Related to #162 .1  This commit allows the Challenge step in RCAR
handshake to be generated due to backend attestation service. For
typical attestation services, a nonce will be generated.

This commit also covers IBM SE + CoCoAS case. In this case, CoCoAS must
be accessed to get a challenge which is specificly used by IBM SE.

Signed-off-by: Xynnn007 <[email protected]>

---------

Signed-off-by: Qi Feng Huo <[email protected]>
Signed-off-by: Xynnn007 <[email protected]>
Co-authored-by: Xynnn007 <[email protected]>
  • Loading branch information
Qi Feng Huo and Xynnn007 committed Jun 11, 2024
1 parent 290fd0e commit 7dbd42f
Show file tree
Hide file tree
Showing 19 changed files with 711 additions and 38 deletions.
86 changes: 80 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ clap = { version = "4", features = ["derive"] }
config = "0.13.3"
env_logger = "0.10.0"
hex = "0.4.3"
kbs-types = "0.5.3"
kbs-types = "0.6.0"
jsonwebtoken = { version = "9", default-features = false }
log = "0.4.17"
prost = "0.11.0"
regorus = { version = "0.1.5", default-features = false, features = ["regex", "base64", "time"] }
rstest = "0.18.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.89"
serde_with = { version = "1.11.0", features = ["base64"] }
serial_test = "0.9.0"
sha2 = "0.10"
shadow-rs = "0.19.0"
Expand All @@ -46,4 +47,4 @@ thiserror = "1.0"
tokio = { version = "1.23.0", features = ["full"] }
tempfile = "3.4.0"
tonic = "0.8.1"
tonic-build = "0.8.0"
tonic-build = "0.8.0"
3 changes: 3 additions & 0 deletions attestation-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Today, the AS can validate evidence from the following TEEs:
- Hygon CSV
- Intel TDX with vTPM on Azure
- AMD SEV-SNP with vTPM on Azure
- IBM Secure Execution (SE)

# Overview
```
Expand Down Expand Up @@ -80,6 +81,7 @@ Please refer to the individual verifiers for the specific format of the evidence
- Azure TDX vTPM: [Evidence](./verifier/src/az_tdx_vtpm/mod.rs)
- Arm CCA: [CcaEvidence](./verifier/src/cca/mod.rs)
- Hygon CSV: [CsvEvidence](./verifier/src/csv/mod.rs)
- IBM Secure Execution (SE) [(SeEvidence)](./verifier/src/se/mod.rs)

## Output

Expand Down Expand Up @@ -132,6 +134,7 @@ Supported Verifier Drivers:
- `azsnpvtpm`: Verifier Driver for Azure vTPM based on SNP (Azure SNP vTPM)
- `cca`: Verifier Driver for Confidential Compute Architecture (Arm CCA).
- `csv`: Verifier Driver for China Security Virtualization (Hygon CSV).
- `se`: Verifier Driver for IBM Secure Execution (SE).

### Policy Engine

Expand Down
1 change: 1 addition & 0 deletions attestation-service/attestation-service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ az-tdx-vtpm-verifier = [ "verifier/az-tdx-vtpm-verifier" ]
snp-verifier = [ "verifier/snp-verifier" ]
csv-verifier = [ "verifier/csv-verifier" ]
cca-verifier = [ "verifier/cca-verifier" ]
se-verifier = [ "verifier/se-verifier" ]

# Only for testing and CI
rvps-builtin = [ "reference-value-provider-service" ]
Expand Down
39 changes: 38 additions & 1 deletion attestation-service/attestation-service/src/bin/grpc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ use tonic::transport::Server;
use tonic::{Request, Response, Status};

use crate::as_api::attestation_service_server::{AttestationService, AttestationServiceServer};
use crate::as_api::{AttestationRequest, AttestationResponse, SetPolicyRequest, SetPolicyResponse};
use crate::as_api::{
AttestationRequest, AttestationResponse, ChallengeRequest, ChallengeResponse, SetPolicyRequest,
SetPolicyResponse,
};

use crate::rvps_api::reference_value_provider_service_server::{
ReferenceValueProviderService, ReferenceValueProviderServiceServer,
Expand All @@ -37,6 +40,7 @@ fn to_kbs_tee(tee: &str) -> anyhow::Result<Tee> {
"azsnpvtpm" => Tee::AzSnpVtpm,
"cca" => Tee::Cca,
"aztdxvtpm" => Tee::AzTdxVtpm,
"se" => Tee::Se,
other => bail!("Unsupported TEE type: {other}"),
};

Expand Down Expand Up @@ -195,6 +199,39 @@ impl AttestationService for Arc<RwLock<AttestationServer>> {
let res = AttestationResponse { attestation_token };
Ok(Response::new(res))
}

async fn get_attestation_challenge(
&self,
request: Request<ChallengeRequest>,
) -> Result<Response<ChallengeResponse>, Status> {
let request: ChallengeRequest = request.into_inner();
info!("get_attestation_challenge API called.");
debug!("get_attestation_challenge: {request:#?}");

let inner_tee = request
.inner
.get("tee")
.ok_or(Status::aborted("Error parse inner_tee tee"))?;
let tee_params = request
.inner
.get("tee_params")
.map_or(Err(Status::aborted("Error parse inner_tee tee_params")), Ok)?;
let tee = to_kbs_tee(&inner_tee)
.map_err(|e| Status::aborted(format!("Error parse TEE type: {e}")))?;

let attestation_challenge = self
.read()
.await
.attestation_service
.generate_supplemental_challenge(tee, tee_params.clone())
.await
.map_err(|e| Status::aborted(format!("Challenge: {e:?}")))?;

let res = ChallengeResponse {
attestation_challenge,
};
Ok(Response::new(res))
}
}

#[tonic::async_trait]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use strum::{AsRefStr, EnumString};
use thiserror::Error;
use tokio::sync::RwLock;

use crate::restful::{attestation, get_policies, set_policy};
use crate::restful::{attestation, get_challenge, get_policies, set_policy};

mod restful;

Expand Down Expand Up @@ -48,6 +48,9 @@ enum WebApi {

#[strum(serialize = "/policy")]
Policy,

#[strum(serialize = "/challenge")]
Challenge,
}

#[derive(Error, Debug)]
Expand Down Expand Up @@ -100,6 +103,7 @@ async fn main() -> Result<(), RestfulError> {
.route(web::post().to(set_policy))
.route(web::get().to(get_policies)),
)
.service(web::resource(WebApi::Challenge.as_ref()).route(web::post().to(get_challenge)))
.app_data(web::Data::clone(&attestation_service))
});

Expand Down
43 changes: 41 additions & 2 deletions attestation-service/attestation-service/src/bin/restful/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::Arc;
use std::{collections::HashMap, sync::Arc};

use actix_web::{body::BoxBody, web, HttpRequest, HttpResponse, ResponseError};
use anyhow::{bail, Context};
use anyhow::{anyhow, bail, Context};
use attestation_service::{AttestationService, HashAlgorithm};
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
use kbs_types::Tee;
Expand Down Expand Up @@ -44,6 +44,14 @@ pub struct AttestationRequest {
policy_ids: Vec<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ChallengeRequest {
// ChallengeRequest uses HashMap to pass variables like:
// tee, tee_params etc
#[serde(flatten)]
inner: HashMap<String, String>,
}

#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum Data {
Expand All @@ -62,6 +70,7 @@ fn to_tee(tee: &str) -> anyhow::Result<Tee> {
"csv" => Tee::Csv,
"sample" => Tee::Sample,
"aztdxvtpm" => Tee::AzTdxVtpm,
"se" => Tee::Se,
other => bail!("tee `{other} not supported`"),
};

Expand Down Expand Up @@ -179,6 +188,36 @@ pub async fn set_policy(
Ok(HttpResponse::Ok().body(""))
}

/// This handler uses json extractor
pub async fn get_challenge(
request: web::Json<ChallengeRequest>,
cocoas: web::Data<Arc<RwLock<AttestationService>>>,
) -> Result<HttpResponse> {
info!("get_challenge API called.");
let request: ChallengeRequest = request.into_inner();

debug!("get_challenge: {request:#?}");
let inner_tee = request
.inner
.get("tee")
.as_ref()
.map(|s| s.as_str())
.ok_or(anyhow!("Failed to get inner tee"))?;
let tee_params = request
.inner
.get("tee_params")
.ok_or(anyhow!("Failed to get inner tee_params"))?;

let tee = to_tee(inner_tee)?;
let challenge = cocoas
.read()
.await
.generate_supplemental_challenge(tee, tee_params.to_string())
.await
.context("generate challenge")?;
Ok(HttpResponse::Ok().body(challenge))
}

/// GET /policy
/// GET /policy/{policy_id}
///
Expand Down
11 changes: 11 additions & 0 deletions attestation-service/attestation-service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,17 @@ impl AttestationService {
pub async fn register_reference_value(&mut self, message: &str) -> Result<()> {
self.rvps.verify_and_extract(message).await
}

pub async fn generate_supplemental_challenge(
&self,
tee: Tee,
tee_parameters: String,
) -> Result<String> {
let verifier = verifier::to_verifier(&tee)?;
verifier
.generate_supplemental_challenge(tee_parameters)
.await
}
}

/// Get the expected init/runtime data and potential claims due to the given input
Expand Down
Loading

0 comments on commit 7dbd42f

Please sign in to comment.