diff --git a/cosmwasm/packages/enclave-ffi-types/cbindgen.toml b/cosmwasm/packages/enclave-ffi-types/cbindgen.toml index 3d424415f..2b45b887d 100644 --- a/cosmwasm/packages/enclave-ffi-types/cbindgen.toml +++ b/cosmwasm/packages/enclave-ffi-types/cbindgen.toml @@ -32,6 +32,7 @@ style = "both" include = [ "UserSpaceBuffer", "EnclaveBuffer", + "NodeAuthResult", "Ctx", "InitResult", "HandleResult", diff --git a/cosmwasm/packages/enclave-ffi-types/src/lib.rs b/cosmwasm/packages/enclave-ffi-types/src/lib.rs index d2a494a16..fb1ad90a1 100644 --- a/cosmwasm/packages/enclave-ffi-types/src/lib.rs +++ b/cosmwasm/packages/enclave-ffi-types/src/lib.rs @@ -4,8 +4,8 @@ mod types; pub use types::{ - Ctx, EnclaveBuffer, EnclaveError, HandleResult, InitResult, OcallReturn, QueryResult, - UntrustedVmError, UserSpaceBuffer, + Ctx, EnclaveBuffer, EnclaveError, HandleResult, InitResult, NodeAuthResult, OcallReturn, + QueryResult, UntrustedVmError, UserSpaceBuffer, }; pub const ENCRYPTED_SEED_SIZE: usize = 48; diff --git a/cosmwasm/packages/enclave-ffi-types/src/types.rs b/cosmwasm/packages/enclave-ffi-types/src/types.rs index ccafa5448..c8e9953a1 100644 --- a/cosmwasm/packages/enclave-ffi-types/src/types.rs +++ b/cosmwasm/packages/enclave-ffi-types/src/types.rs @@ -108,6 +108,27 @@ pub enum EnclaveError { Unknown, } +/// This type represents the possible error conditions that can be encountered in the +/// enclave while authenticating a new node in the network. +/// cbindgen:prefix-with-name +#[repr(C)] +#[derive(Debug, Display, PartialEq, Eq)] +pub enum NodeAuthResult { + Success, + #[display(fmt = "Enclave received invalid inputs")] + InvalidInput, + #[display(fmt = "The provided certificate was invalid")] + InvalidCert, + #[display(fmt = "Writing to file system from the enclave failed")] + CantWriteToStorage, + #[display(fmt = "The public key in the certificate appears to be malformed")] + MalformedPublicKey, + #[display(fmt = "Encrypting the seed failed")] + SeedEncryptionFailed, + #[display(fmt = "Enclave panicked :( please file a bug report!")] + Panic, +} + /// This type holds a pointer to a VmError that is boxed on the untrusted side // `VmError` is the standard error type for the `cosmwasm-sgx-vm` layer. // During an ocall, we call into the original implementation of `db_read`, `db_write`, and `db_remove`. diff --git a/cosmwasm/packages/sgx-vm/src/attestation.rs b/cosmwasm/packages/sgx-vm/src/attestation.rs index 9839edeec..c50088c69 100644 --- a/cosmwasm/packages/sgx-vm/src/attestation.rs +++ b/cosmwasm/packages/sgx-vm/src/attestation.rs @@ -7,7 +7,7 @@ use log::*; use sgx_types::*; use sgx_types::{sgx_status_t, SgxResult}; -use enclave_ffi_types::ENCRYPTED_SEED_SIZE; +use enclave_ffi_types::{NodeAuthResult, ENCRYPTED_SEED_SIZE}; use crate::enclave::get_enclave; @@ -18,7 +18,7 @@ extern "C" { ) -> sgx_status_t; pub fn ecall_authenticate_new_node( eid: sgx_enclave_id_t, - retval: *mut sgx_status_t, + retval: *mut NodeAuthResult, cert: *const u8, cert_len: u32, seed: &mut [u8; ENCRYPTED_SEED_SIZE], @@ -122,7 +122,7 @@ pub extern "C" fn ocall_get_update_info( unsafe { sgx_report_attestation_status(platform_blob, enclave_trusted, update_info) } } -pub fn create_attestation_report_u() -> SgxResult { +pub fn create_attestation_report_u() -> SgxResult<()> { let enclave = get_enclave()?; let eid = enclave.geteid(); @@ -137,13 +137,15 @@ pub fn create_attestation_report_u() -> SgxResult { return Err(retval); } - Ok(sgx_status_t::SGX_SUCCESS) + Ok(()) } -pub fn untrusted_get_encrypted_seed(cert: &[u8]) -> SgxResult<[u8; ENCRYPTED_SEED_SIZE]> { +pub fn untrusted_get_encrypted_seed( + cert: &[u8], +) -> SgxResult> { let enclave = get_enclave()?; let eid = enclave.geteid(); - let mut retval = sgx_status_t::SGX_SUCCESS; + let mut retval = NodeAuthResult::Success; let mut seed = [0u8; ENCRYPTED_SEED_SIZE]; let status = unsafe { ecall_authenticate_new_node( @@ -159,8 +161,8 @@ pub fn untrusted_get_encrypted_seed(cert: &[u8]) -> SgxResult<[u8; ENCRYPTED_SEE return Err(status); } - if retval != sgx_status_t::SGX_SUCCESS { - return Err(retval); + if retval != NodeAuthResult::Success { + return Ok(Err(retval)); } if seed.is_empty() { @@ -168,7 +170,7 @@ pub fn untrusted_get_encrypted_seed(cert: &[u8]) -> SgxResult<[u8; ENCRYPTED_SEE return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } - Ok(seed) + Ok(Ok(seed)) } #[cfg(test)] diff --git a/cosmwasm/packages/sgx-vm/src/seed.rs b/cosmwasm/packages/sgx-vm/src/seed.rs index 9d75702fd..07490e545 100644 --- a/cosmwasm/packages/sgx-vm/src/seed.rs +++ b/cosmwasm/packages/sgx-vm/src/seed.rs @@ -27,8 +27,8 @@ extern "C" { ) -> sgx_status_t; } -pub fn untrusted_init_node(master_cert: &[u8], encrypted_seed: &[u8]) -> SgxResult { - debug!("Initializing enclave.."); +pub fn untrusted_init_node(master_cert: &[u8], encrypted_seed: &[u8]) -> SgxResult<()> { + info!("Initializing enclave.."); let enclave = get_enclave()?; debug!("Initialized enclave successfully!"); @@ -54,7 +54,7 @@ pub fn untrusted_init_node(master_cert: &[u8], encrypted_seed: &[u8]) -> SgxResu return Err(ret); } - Ok(sgx_status_t::SGX_SUCCESS) + Ok(()) } pub fn untrusted_key_gen() -> SgxResult<[u8; 32]> { diff --git a/cosmwasm/packages/wasmi-runtime/Enclave.edl b/cosmwasm/packages/wasmi-runtime/Enclave.edl index 5a8323674..56999e681 100644 --- a/cosmwasm/packages/wasmi-runtime/Enclave.edl +++ b/cosmwasm/packages/wasmi-runtime/Enclave.edl @@ -29,7 +29,7 @@ enclave { public sgx_status_t ecall_get_attestation_report(); - public sgx_status_t ecall_authenticate_new_node( + public NodeAuthResult ecall_authenticate_new_node( [in, count=cert_len] const uint8_t* cert, uintptr_t cert_len, [out, count=48] uint8_t* seed diff --git a/cosmwasm/packages/wasmi-runtime/src/registration/cert.rs b/cosmwasm/packages/wasmi-runtime/src/registration/cert.rs index b892456ca..2b368c8b6 100644 --- a/cosmwasm/packages/wasmi-runtime/src/registration/cert.rs +++ b/cosmwasm/packages/wasmi-runtime/src/registration/cert.rs @@ -300,10 +300,7 @@ pub fn verify_ra_cert(cert_der: &[u8]) -> SgxResult> { // 2. Verify quote status (mandatory field) - match verify_quote_status(report.sgx_quote_status) { - Ok(_) => (), - Err(e) => return Err(e), - } + verify_quote_status(report.sgx_quote_status)?; // verify certificate match SIGNING_METHOD { diff --git a/cosmwasm/packages/wasmi-runtime/src/registration/onchain.rs b/cosmwasm/packages/wasmi-runtime/src/registration/onchain.rs index 3c44bd8fa..e9cdd6417 100644 --- a/cosmwasm/packages/wasmi-runtime/src/registration/onchain.rs +++ b/cosmwasm/packages/wasmi-runtime/src/registration/onchain.rs @@ -2,9 +2,10 @@ /// These functions run on-chain and must be deterministic across all nodes /// use log::*; -use sgx_types::{sgx_status_t, SgxResult}; use std::panic; +use enclave_ffi_types::NodeAuthResult; + use crate::consts::ENCRYPTED_SEED_SIZE; use crate::crypto::PUBLIC_KEY_SIZE; use crate::storage::write_to_untrusted; @@ -32,24 +33,22 @@ pub unsafe extern "C" fn ecall_authenticate_new_node( cert: *const u8, cert_len: u32, seed: &mut [u8; ENCRYPTED_SEED_SIZE], -) -> sgx_status_t { +) -> NodeAuthResult { if let Err(_e) = validate_mut_ptr(seed.as_mut_ptr(), seed.len()) { - return sgx_status_t::SGX_ERROR_UNEXPECTED; + return NodeAuthResult::InvalidInput; } - if let Err(_e) = validate_const_ptr(cert, cert_len as usize) { - return sgx_status_t::SGX_ERROR_UNEXPECTED; + return NodeAuthResult::InvalidInput; } let cert_slice = std::slice::from_raw_parts(cert, cert_len as usize); - let result = panic::catch_unwind(|| -> SgxResult> { + let result = panic::catch_unwind(|| -> Result, NodeAuthResult> { // verify certificate, and return the public key in the extra data of the report let pk = verify_ra_cert(cert_slice).map_err(|verification_status| { error!("Error in validating certificate: {:?}", verification_status); - if let Err(write_status) = write_to_untrusted(cert_slice, "failed_cert.der") { - write_status - } else { - verification_status + match write_to_untrusted(cert_slice, "failed_cert.der") { + Err(_) => NodeAuthResult::CantWriteToStorage, + Ok(_) => NodeAuthResult::InvalidCert, } })?; @@ -59,7 +58,7 @@ pub unsafe extern "C" fn ecall_authenticate_new_node( "Got public key from certificate with the wrong size: {:?}", pk.len() ); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); + return Err(NodeAuthResult::MalformedPublicKey); } let mut target_public_key: [u8; 32] = [0u8; 32]; @@ -69,7 +68,8 @@ pub unsafe extern "C" fn ecall_authenticate_new_node( &target_public_key.to_vec() ); - let res: Vec = encrypt_seed(target_public_key)?; + let res: Vec = + encrypt_seed(target_public_key).map_err(|_| NodeAuthResult::SeedEncryptionFailed)?; Ok(res) }); @@ -78,12 +78,12 @@ pub unsafe extern "C" fn ecall_authenticate_new_node( match res { Ok(res) => { seed.copy_from_slice(&res); - sgx_status_t::SGX_SUCCESS + NodeAuthResult::Success } Err(e) => e, } } else { error!("Enclave call ecall_authenticate_new_node panic!"); - sgx_status_t::SGX_ERROR_UNEXPECTED + NodeAuthResult::Panic } } diff --git a/go-cosmwasm/src/error/rust.rs b/go-cosmwasm/src/error/rust.rs index e95f48b9d..067ee3ed8 100644 --- a/go-cosmwasm/src/error/rust.rs +++ b/go-cosmwasm/src/error/rust.rs @@ -35,6 +35,12 @@ pub enum Error { #[cfg(feature = "backtraces")] backtrace: snafu::Backtrace, }, + #[snafu(display("{}", msg))] + GoCwEnclaveError { + msg: String, + #[cfg(feature = "backtraces")] + backtrace: snafu::Backtrace, + }, } impl Error { @@ -60,6 +66,13 @@ impl Error { .build() } + pub fn enclave_err(msg: S) -> Self { + GoCwEnclaveError { + msg: msg.to_string(), + } + .build() + } + pub fn out_of_gas() -> Self { OutOfGas {}.build() } diff --git a/go-cosmwasm/src/lib.rs b/go-cosmwasm/src/lib.rs index 6037c6cdd..5afcb79da 100644 --- a/go-cosmwasm/src/lib.rs +++ b/go-cosmwasm/src/lib.rs @@ -29,7 +29,6 @@ use cosmwasm_sgx_vm::{ }; use ctor::ctor; -use log; use log::*; #[ctor] @@ -54,22 +53,28 @@ pub extern "C" fn get_encrypted_seed(cert: Buffer, err: Option<&mut Buffer>) -> debug!("Called get_encrypted_seed"); let cert_slice = match unsafe { cert.read() } { None => { - set_error(Error::vm_err("Attestation Certificate is empty"), err); + set_error(Error::empty_arg("attestation_cert"), err); return Buffer::default(); } Some(r) => r, }; - let result = match untrusted_get_encrypted_seed(cert_slice) { + info!("Hello from right before untrusted_get_encrypted_seed"); + match untrusted_get_encrypted_seed(cert_slice) { Err(e) => { - set_error(Error::vm_err(e.to_string()), err); - return Buffer::default(); + // An error happened in the SGX sdk. + set_error(Error::enclave_err(e.to_string()), err); + Buffer::default() } - Ok(r) => { + Ok(Err(e)) => { + // An error was returned from the enclave. + set_error(Error::enclave_err(e.to_string()), err); + Buffer::default() + } + Ok(Ok(seed)) => { clear_error(); - Buffer::from_vec(r.to_vec()) + Buffer::from_vec(seed.to_vec()) } - }; - return result; + } } #[no_mangle] @@ -77,7 +82,7 @@ pub extern "C" fn init_bootstrap(err: Option<&mut Buffer>) -> Buffer { info!("Hello from right before init_bootstrap"); match untrusted_init_bootstrap() { Err(e) => { - set_error(Error::vm_err(e.to_string()), err); + set_error(Error::enclave_err(e.to_string()), err); Buffer::default() } Ok(r) => { @@ -95,37 +100,35 @@ pub extern "C" fn init_node( ) -> bool { let pk_slice = match unsafe { master_cert.read() } { None => { - set_error(Error::vm_err("Public key is empty"), err); + set_error(Error::empty_arg("master_cert"), err); return false; } Some(r) => r, }; let encrypted_seed_slice = match unsafe { encrypted_seed.read() } { None => { - set_error(Error::vm_err("Encrypted seed is empty"), err); + set_error(Error::empty_arg("encrypted_seed"), err); return false; } Some(r) => r, }; - let result = match untrusted_init_node(pk_slice, encrypted_seed_slice) { + match untrusted_init_node(pk_slice, encrypted_seed_slice) { Ok(_) => { clear_error(); true } Err(e) => { - set_error(Error::vm_err(e.to_string()), err); + set_error(Error::enclave_err(e.to_string()), err); false } - }; - - result + } } #[no_mangle] pub extern "C" fn create_attestation_report(err: Option<&mut Buffer>) -> bool { if let Err(status) = create_attestation_report_u() { - set_error(Error::vm_err(status.to_string()), err); + set_error(Error::enclave_err(status.to_string()), err); return false; } clear_error(); @@ -465,7 +468,7 @@ fn do_query( pub extern "C" fn key_gen(err: Option<&mut Buffer>) -> Buffer { match untrusted_key_gen() { Err(e) => { - set_error(Error::vm_err(e.to_string()), err); + set_error(Error::enclave_err(e.to_string()), err); Buffer::default() } Ok(r) => {