Skip to content

Commit

Permalink
Support DCAP RA (#2869)
Browse files Browse the repository at this point in the history
* remove println

* consider prod too

* add RA_METHOD

* temporarily ignore tcb check

* lenient tcb level

* use Intel for default dcap provider

* same change for bc

* patch Makefile

---------

Co-authored-by: BillyWooo <thedreamofbilly@gmail.com>
  • Loading branch information
Kailai-Wang and BillyWooo committed Jul 10, 2024
1 parent 9eda63d commit c758c30
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 68 deletions.
7 changes: 4 additions & 3 deletions bitacross-worker/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ SGX_PRODUCTION ?= 0
######## Worker Feature Settings ########
# Set offchain-worker as default feature mode
WORKER_MODE ?= offchain-worker
RA_METHOD ?=

SKIP_WASM_BUILD = 1
# include the build settings from rust-sgx-sdk
Expand Down Expand Up @@ -76,17 +77,17 @@ ifeq ($(SGX_PRODUCTION), 1)
SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.production.xml"
SGX_SIGN_KEY = $(SGX_COMMERCIAL_KEY)
SGX_SIGN_PASSFILE = $(SGX_PASSFILE)
WORKER_FEATURES := --features=link-binary,$(WORKER_MODE),$(WORKER_FEATURES),$(ADDITIONAL_FEATURES)
WORKER_FEATURES := --features=link-binary,$(WORKER_MODE),$(RA_METHOD),$(WORKER_FEATURES),$(ADDITIONAL_FEATURES)
else
SGX_ENCLAVE_MODE = "Development Mode"
SGX_ENCLAVE_CONFIG = "enclave-runtime/Enclave.config.xml"
SGX_SIGN_KEY = "enclave-runtime/Enclave_private.pem"
SGX_SIGN_PASSFILE = ""
WORKER_FEATURES := --features=default,development,link-binary,$(WORKER_MODE),$(WORKER_FEATURES),$(ADDITIONAL_FEATURES)
WORKER_FEATURES := --features=default,development,link-binary,$(WORKER_MODE),$(RA_METHOD),$(WORKER_FEATURES),$(ADDITIONAL_FEATURES)
ADDITIONAL_FEATURES := development
endif

CLIENT_FEATURES = --features=$(WORKER_MODE),$(ADDITIONAL_FEATURES)
CLIENT_FEATURES = --features=$(WORKER_MODE),$(RA_METHOD),$(ADDITIONAL_FEATURES)

# check if running on Jenkins
ifdef BUILD_ID
Expand Down
3 changes: 2 additions & 1 deletion bitacross-worker/core-primitives/types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ pub mod storage;

pub use itp_sgx_runtime_primitives::types::*;
pub use litentry_primitives::{
AttestationType, DecryptableRequest, Enclave, EnclaveFingerprint, MrEnclave, WorkerType,
AttestationType, DcapProvider, DecryptableRequest, Enclave, EnclaveFingerprint, MrEnclave,
WorkerType,
};
pub use sp_core::{crypto::AccountId32 as AccountId, H256};

Expand Down
4 changes: 2 additions & 2 deletions bitacross-worker/enclave-runtime/src/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use itp_settings::worker::MR_ENCLAVE_SIZE;
use itp_sgx_crypto::{
ed25519_derivation::DeriveEd25519, key_repository::AccessKey, Error as SgxCryptoError,
};
use itp_types::{AttestationType, OpaqueCall, WorkerType};
use itp_types::{AttestationType, DcapProvider, OpaqueCall, WorkerType};
use itp_utils::write_slice_and_whitespace_pad;
use litentry_primitives::WorkerMode;
use log::*;
Expand Down Expand Up @@ -328,7 +328,7 @@ pub fn generate_dcap_ra_extrinsic_from_quote_internal(

let shielding_pubkey = get_shielding_pubkey()?;
let vc_pubkey = get_vc_pubkey()?;
let attestation_type = AttestationType::Dcap(Default::default()); // skip_ra should be false here already
let attestation_type = AttestationType::Dcap(DcapProvider::Intel); // skip_ra should be false here already

let call = OpaqueCall::from_tuple(&(
call_ids,
Expand Down
2 changes: 1 addition & 1 deletion bitacross-worker/litentry/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ use itp_sgx_crypto::ShieldingCryptoDecrypt;
use litentry_hex_utils::hex_encode;
use log::error;
pub use pallet_teebag::{
decl_rsa_request, extract_tcb_info_from_raw_dcap_quote, AttestationType, Enclave,
decl_rsa_request, extract_tcb_info_from_raw_dcap_quote, AttestationType, DcapProvider, Enclave,
EnclaveFingerprint, MrEnclave, ShardIdentifier, SidechainBlockNumber, WorkerMode, WorkerType,
};
pub use parentchain_primitives::{
Expand Down
2 changes: 1 addition & 1 deletion local-setup/py/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def setup_working_dir(source_dir: str, target_dir: str, worker_bin: str):
target_dir: the working directory of the worker to be run.
"""

optional = ["key.txt", "spid.txt"]
optional = ["key.txt", "spid.txt", "key_production.txt", "spid_production.txt"]

for file in optional:
source = f"{source_dir}/{file}"
Expand Down
5 changes: 4 additions & 1 deletion pallets/teebag/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ pub mod pallet {
InvalidAttestationType,
/// The enclave cannot attest, because its building mode is not allowed.
InvalidSgxMode,
/// The specified dcap provider is not yet supported
DcapProviderNotSupported,
/// The enclave doesn't exist.
EnclaveNotExist,
/// The enclave identifier doesn't exist.
Expand Down Expand Up @@ -479,7 +481,8 @@ pub mod pallet {
enclave.last_seen_timestamp = report.timestamp;
enclave.sgx_build_mode = report.build_mode;
},
AttestationType::Dcap(_) => {
AttestationType::Dcap(provider) => {
ensure!(provider == DcapProvider::Intel, Error::<T>::DcapProviderNotSupported);
let report = Self::verify_dcap(&sender, attestation)?;
enclave.mrenclave = report.mr_enclave;
enclave.last_seen_timestamp = report.timestamp;
Expand Down
7 changes: 6 additions & 1 deletion pallets/teebag/src/sgx_verify/collateral.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ impl TcbLevelFull {
pub fn is_valid(&self) -> bool {
// A possible extension would be to also verify that the advisory_ids list is empty,
// but I think this could also lead to all TcbLevels being invalid
self.tcb_status == "UpToDate" || self.tcb_status == "SWHardeningNeeded"
//
// Litentry: be more lenient with it
self.tcb_status == "UpToDate" ||
self.tcb_status == "SWHardeningNeeded" ||
self.tcb_status == "ConfigurationNeeded" ||
self.tcb_status == "ConfigurationAndSWHardeningNeeded"
}
}

Expand Down
50 changes: 4 additions & 46 deletions pallets/teebag/src/sgx_verify/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,6 @@ pub struct SgxReportBody {

impl SgxReportBody {
pub fn sgx_build_mode(&self) -> SgxBuildMode {
#[cfg(test)]
println!("attributes flag : {:x}", self.attributes.flags);
if self.attributes.flags & SGX_FLAGS_DEBUG == SGX_FLAGS_DEBUG {
SgxBuildMode::Debug
} else {
Expand Down Expand Up @@ -545,9 +543,6 @@ pub fn verify_dcap_quote(
let quote: DcapQuote =
Decode::decode(&mut dcap_quote_clone).map_err(|_| "Failed to decode attestation report")?;

#[cfg(test)]
println!("{:?}", quote);

ensure!(quote.header.version == 3, "Only support for version 3");
ensure!(quote.header.attestation_key_type == 2, "Only support for ECDSA-256");
ensure!(
Expand Down Expand Up @@ -643,10 +638,6 @@ pub fn verify_dcap_quote(
pub fn verify_ias_report(cert_der: &[u8]) -> Result<SgxReport, &'static str> {
// Before we reach here, the runtime already verified the extrinsic is properly signed by the
// extrinsic sender Hence, we skip: EphemeralKey::try_from(cert)?;

#[cfg(test)]
println!("verifyRA: start verifying RA cert");

let cert = CertDer(cert_der);
let netscape = NetscapeComment::try_from(cert)?;
let sig_cert_der = webpki::types::CertificateDer::from(netscape.sig_cert.as_slice());
Expand Down Expand Up @@ -691,9 +682,6 @@ fn parse_report(netscape: &NetscapeComment) -> Result<SgxReport, &'static str> {
.try_into()
.map_err(|_| "Error converting report.timestamp to u64")?;

#[cfg(test)]
println!("verifyRA attestation timestamp [unix epoch]: {}", ra_timestamp);

// get quote status (mandatory field)
let ra_status = match &attn_report["isvEnclaveQuoteStatus"] {
Value::String(quote_status) => match quote_status.as_ref() {
Expand All @@ -706,32 +694,18 @@ fn parse_report(netscape: &NetscapeComment) -> Result<SgxReport, &'static str> {
_ => return Err("Failed to fetch isvEnclaveQuoteStatus from attestation report"),
};

#[cfg(test)]
println!("verifyRA attestation status is: {:?}", ra_status);
// parse quote body
if let Value::String(quote_raw) = &attn_report["isvEnclaveQuoteBody"] {
let quote = match base64::decode(quote_raw) {
Ok(q) => q,
Err(_) => return Err("Quote Decoding Error"),
};
#[cfg(test)]
println!("Quote read. len={}", quote.len());
// TODO: lack security check here
let sgx_quote: SgxQuote = match Decode::decode(&mut &quote[..]) {
Ok(q) => q,
Err(_) => return Err("could not decode quote"),
};

#[cfg(test)]
{
println!("sgx quote version = {}", sgx_quote.version);
println!("sgx quote signature type = {}", sgx_quote.sign_type);
//println!("sgx quote report_data = {:?}", sgx_quote.report_body.report_data.d[..32]);
println!("sgx quote mr_enclave = {:x?}", sgx_quote.report_body.mr_enclave);
println!("sgx quote mr_signer = {:x?}", sgx_quote.report_body.mr_signer);
println!("sgx quote report_data = {:x?}", sgx_quote.report_body.report_data.d.to_vec());
}

let mut xt_signer_array = [0u8; 32];
xt_signer_array.copy_from_slice(&sgx_quote.report_body.report_data.d[..32]);
Ok(SgxReport {
Expand All @@ -754,16 +728,8 @@ pub fn verify_signature(
signature_algorithm: &dyn webpki::types::SignatureVerificationAlgorithm,
) -> Result<(), &'static str> {
match entity_cert.verify_signature(signature_algorithm, data, signature) {
Ok(()) => {
#[cfg(test)]
println!("IAS signature is valid");
Ok(())
},
Err(_e) => {
#[cfg(test)]
println!("RSA Signature ERROR: {}", _e);
Err("bad signature")
},
Ok(()) => Ok(()),
Err(_e) => Err("bad signature"),
}
}

Expand All @@ -780,16 +746,8 @@ pub fn verify_server_cert(
webpki::KeyUsage::server_auth(),
None,
) {
Ok(()) => {
#[cfg(test)]
println!("CA is valid");
Ok(())
},
Err(_e) => {
#[cfg(test)]
println!("CA ERROR: {}", _e);
Err("CA verification failed")
},
Ok(()) => Ok(()),
Err(_e) => Err("CA verification failed"),
}
}

Expand Down
2 changes: 0 additions & 2 deletions pallets/teebag/src/sgx_verify/netscape_comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ impl<'a> TryFrom<CertDer<'a>> for NetscapeComment<'a> {

offset += 12; // 11 + TAG (0x04)

#[cfg(test)]
println!("netscape");
// Obtain Netscape Comment length
let len = length_from_raw_data(cert_der, &mut offset)?;
// Obtain Netscape Comment
Expand Down
Loading

0 comments on commit c758c30

Please sign in to comment.