From 5e7e4e9dc9b02b394d256b888b473bdabc9a460f Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Apr 2024 18:14:19 +0000 Subject: [PATCH 1/6] SgxFile migration: supporting large files --- cosmwasm/enclaves/shared/utils/src/storage.rs | 117 ++++++++++++++++-- 1 file changed, 105 insertions(+), 12 deletions(-) diff --git a/cosmwasm/enclaves/shared/utils/src/storage.rs b/cosmwasm/enclaves/shared/utils/src/storage.rs index e33e3d583..1bcff41a2 100644 --- a/cosmwasm/enclaves/shared/utils/src/storage.rs +++ b/cosmwasm/enclaves/shared/utils/src/storage.rs @@ -2,9 +2,11 @@ use crate::results::UnwrapOrSgxErrorUnexpected; use core::mem; use core::ptr::null; +use log::*; use log::{error, info}; use std::io::{Read, Write}; use std::path::Path; +use std::ptr; use std::sgxfs::SgxFile; use std::slice; @@ -71,6 +73,7 @@ pub struct FileMdPlain { const FILE_MD_ENCRYPTED_DATA_SIZE: usize = 3072; const FILE_MD_ENCRYPTED_FILENAME_SIZE: usize = 260; +const FILE_MD_ENCRYPTED_DATA_NODES: usize = 96; #[repr(packed)] pub struct FileMdEncrypted { @@ -94,29 +97,49 @@ pub struct FileMd { pub padding: [u8; 610], } +#[repr(packed)] +pub struct FileDataKeys { + pub key: [u8; 16], + pub gmac: [u8; 16], +} + +#[repr(packed)] +pub struct FileMhtNode { + pub data: [FileDataKeys; FILE_MD_ENCRYPTED_DATA_NODES], + pub lower_nodes: [FileDataKeys; 32], +} + pub fn unseal_file_from_2_17( s_path: &str, should_check_fname: bool, ) -> Result, sgx_status_t> { let mut file = match File::open(s_path) { Ok(f) => f, - Err(_) => { - return Err(/*e*/ sgx_status_t::SGX_ERROR_UNEXPECTED); + Err(e) => { + warn!("Failed to open file: {}", e); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } }; let mut bytes = Vec::new(); - if file.read_to_end(&mut bytes).is_err() { - return Err(/*e*/ sgx_status_t::SGX_ERROR_UNEXPECTED); + if let Err(e) = file.read_to_end(&mut bytes) { + warn!("Failed to read file: {}", e); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } if bytes.len() < mem::size_of::() { + warn!("file too small"); return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } unsafe { let p_md = bytes.as_mut_ptr() as *const FileMd; + if (*p_md).plain.update_flag > 0 { + warn!("file left in recovery mode, unsupported"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); // we don't support recovery + } + let mut key_request = sgx_key_request_t { key_name: sgx_types::SGX_KEYSELECT_SEAL, key_policy: sgx_types::SGX_KEYPOLICY_MRSIGNER, @@ -135,6 +158,7 @@ pub fn unseal_file_from_2_17( let mut st = sgx_get_key(&key_request, &mut cur_key); if sgx_status_t::SGX_SUCCESS != st { + warn!("gen key failed"); return Err(st); } @@ -164,17 +188,10 @@ pub fn unseal_file_from_2_17( ); if sgx_status_t::SGX_SUCCESS != st { + // warn!("decrypt file md failed"); return Err(st); } - let ret_size = std::ptr::read_unaligned(std::ptr::addr_of!(md_decr.size)) as usize; - if ret_size > FILE_MD_ENCRYPTED_DATA_SIZE { - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); - } - - bytes.resize(ret_size, 0); - bytes.copy_from_slice(slice::from_raw_parts(md_decr.data.as_ptr(), ret_size)); - if should_check_fname { let raw_path = s_path.as_bytes(); @@ -204,6 +221,82 @@ pub fn unseal_file_from_2_17( return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH); } } + + let ret_size = std::ptr::read_unaligned(std::ptr::addr_of!(md_decr.size)) as usize; + + if ret_size <= FILE_MD_ENCRYPTED_DATA_SIZE { + bytes.resize(ret_size, 0); + bytes.copy_from_slice(slice::from_raw_parts(md_decr.data.as_ptr(), ret_size)); + } else { + let node_size = mem::size_of::(); // 4K + + let num_nodes = (ret_size - FILE_MD_ENCRYPTED_DATA_SIZE + node_size - 1) / node_size; + if num_nodes > FILE_MD_ENCRYPTED_DATA_NODES { + warn!("too many nodes, indirect files not supported"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); + } + + let size_required = mem::size_of::() + node_size * (num_nodes + 1); + if bytes.len() < size_required { + warn!("file too short"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); + } + + let mut bytes_src = bytes; + bytes = Vec::new(); + bytes.resize(FILE_MD_ENCRYPTED_DATA_SIZE + node_size * num_nodes, 7); // allocate with padding + + let mut offs_dst = FILE_MD_ENCRYPTED_DATA_SIZE; + + ptr::copy_nonoverlapping(md_decr.data.as_ptr(), bytes.as_mut_ptr(), offs_dst); + + // Decode mht node + let p_mht_node = bytes_src + .as_mut_ptr() + .offset(mem::size_of::() as isize) + as *mut FileMhtNode; + + st = sgx_rijndael128GCM_decrypt( + &md_decr.mht_key, + p_mht_node as *const u8, + mem::size_of::() as u32, + p_mht_node as *mut uint8_t, + p_iv.as_ptr() as *const u8, + 12, + null(), + 0, + &md_decr.mht_gmac, + ); + if sgx_status_t::SGX_SUCCESS != st { + return Err(st); + } + + let mut offs_src = mem::size_of::() + node_size; + + for i_node in 0..num_nodes { + let keys = &(*p_mht_node).data[i_node]; + + st = sgx_rijndael128GCM_decrypt( + &keys.key, + bytes_src.as_ptr().offset(offs_src as isize), + node_size as u32, + bytes.as_mut_ptr().offset(offs_dst as isize), + p_iv.as_ptr() as *const u8, + 12, + null(), + 0, + &keys.gmac, + ); + if sgx_status_t::SGX_SUCCESS != st { + return Err(st); + } + + offs_src += node_size; + offs_dst += node_size; + } + + bytes.resize(ret_size, 0); // truncate the padding + } }; Ok(bytes) From 60b7d7418b7ab0aeab7207042336cb91cc232750 Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Apr 2024 21:04:08 +0000 Subject: [PATCH 2/6] SgxFile migration - more flexible, no error if file already converted --- cosmwasm/enclaves/shared/utils/src/storage.rs | 152 ++++++++++-------- 1 file changed, 85 insertions(+), 67 deletions(-) diff --git a/cosmwasm/enclaves/shared/utils/src/storage.rs b/cosmwasm/enclaves/shared/utils/src/storage.rs index 1bcff41a2..99d913321 100644 --- a/cosmwasm/enclaves/shared/utils/src/storage.rs +++ b/cosmwasm/enclaves/shared/utils/src/storage.rs @@ -75,6 +75,40 @@ const FILE_MD_ENCRYPTED_DATA_SIZE: usize = 3072; const FILE_MD_ENCRYPTED_FILENAME_SIZE: usize = 260; const FILE_MD_ENCRYPTED_DATA_NODES: usize = 96; +#[repr(packed)] +pub struct FileDataKeyAndMac { + pub key: [u8; 16], + pub gmac: [u8; 16], +} + +impl FileDataKeyAndMac { + unsafe fn decrypt_once( + &self, + p_src: *const uint8_t, + src_len: uint32_t, + p_dst: *mut uint8_t, + p_iv: &[u8; 12], + ) -> Result<(), sgx_status_t> { + let res = sgx_rijndael128GCM_decrypt( + &self.key, + p_src, + src_len, + p_dst, + p_iv.as_ptr(), + 12, + null(), + 0, + &self.gmac, + ); + + if sgx_status_t::SGX_SUCCESS != res { + return Err(res); + } + + Ok(()) + } +} + #[repr(packed)] pub struct FileMdEncrypted { pub clean_filename: [u8; FILE_MD_ENCRYPTED_FILENAME_SIZE], @@ -84,8 +118,7 @@ pub struct FileMdEncrypted { pub mc_uuid: [u8; 16], pub mc_value: u32, - pub mht_key: [u8; 16], - pub mht_gmac: [u8; 16], + pub root_mht: FileDataKeyAndMac, pub data: [u8; FILE_MD_ENCRYPTED_DATA_SIZE], } @@ -97,16 +130,10 @@ pub struct FileMd { pub padding: [u8; 610], } -#[repr(packed)] -pub struct FileDataKeys { - pub key: [u8; 16], - pub gmac: [u8; 16], -} - #[repr(packed)] pub struct FileMhtNode { - pub data: [FileDataKeys; FILE_MD_ENCRYPTED_DATA_NODES], - pub lower_nodes: [FileDataKeys; 32], + pub data: [FileDataKeyAndMac; FILE_MD_ENCRYPTED_DATA_NODES], + pub lower_nodes: [FileDataKeyAndMac; 32], } pub fn unseal_file_from_2_17( @@ -154,12 +181,17 @@ pub fn unseal_file_from_2_17( key_request.cpu_svn.svn = (*p_md).plain.cpu_svn; key_request.key_id.id = (*p_md).plain.key_id; - let mut cur_key: sgx_key_128bit_t = sgx_key_128bit_t::default(); + let mut cur_key_mac = FileDataKeyAndMac { + key: sgx_key_128bit_t::default(), + gmac: (*p_md).plain.meta_data_gmac, + }; - let mut st = sgx_get_key(&key_request, &mut cur_key); - if sgx_status_t::SGX_SUCCESS != st { - warn!("gen key failed"); - return Err(st); + match sgx_get_key(&key_request, &mut cur_key_mac.key) { + sgx_status_t::SGX_SUCCESS => {} + err_code => { + warn!("gen key failed"); + return Err(err_code); + } } let /* mut */ md_decr: FileMdEncrypted = FileMdEncrypted { @@ -167,29 +199,23 @@ pub fn unseal_file_from_2_17( size: 0, mc_uuid: [0; 16], mc_value: 0, - mht_key: [0; 16], - mht_gmac: [0; 16], - - data: [0; 3072], + root_mht: FileDataKeyAndMac{ + key: [0; 16], + gmac: [0; 16], + }, + data: [0; FILE_MD_ENCRYPTED_DATA_SIZE], }; let p_iv: [u8; 12] = [0; 12]; - st = sgx_rijndael128GCM_decrypt( - &cur_key, + if let Err(e) = cur_key_mac.decrypt_once( std::ptr::addr_of!((*p_md).encr) as *const u8, mem::size_of::() as u32, std::ptr::addr_of!(md_decr) as *mut uint8_t, - p_iv.as_ptr() as *const u8, - 12, - null(), - 0, - &(*p_md).plain.meta_data_gmac, - ); - - if sgx_status_t::SGX_SUCCESS != st { - // warn!("decrypt file md failed"); - return Err(st); + &p_iv, + ) { + warn!("decrypt file md failed"); + return Err(e); } if should_check_fname { @@ -256,19 +282,13 @@ pub fn unseal_file_from_2_17( .offset(mem::size_of::() as isize) as *mut FileMhtNode; - st = sgx_rijndael128GCM_decrypt( - &md_decr.mht_key, + if let Err(e) = md_decr.root_mht.decrypt_once( p_mht_node as *const u8, mem::size_of::() as u32, p_mht_node as *mut uint8_t, - p_iv.as_ptr() as *const u8, - 12, - null(), - 0, - &md_decr.mht_gmac, - ); - if sgx_status_t::SGX_SUCCESS != st { - return Err(st); + &p_iv, + ) { + return Err(e); } let mut offs_src = mem::size_of::() + node_size; @@ -276,19 +296,13 @@ pub fn unseal_file_from_2_17( for i_node in 0..num_nodes { let keys = &(*p_mht_node).data[i_node]; - st = sgx_rijndael128GCM_decrypt( - &keys.key, + if let Err(e) = keys.decrypt_once( bytes_src.as_ptr().offset(offs_src as isize), node_size as u32, bytes.as_mut_ptr().offset(offs_dst as isize), - p_iv.as_ptr() as *const u8, - 12, - null(), - 0, - &keys.gmac, - ); - if sgx_status_t::SGX_SUCCESS != st { - return Err(st); + &p_iv, + ) { + return Err(e); } offs_src += node_size; @@ -307,26 +321,30 @@ pub fn migrate_file_from_2_17_safe( should_check_fname: bool, ) -> Result<(), sgx_status_t> { if Path::new(s_path).exists() { - let data = match unseal_file_from_2_17(s_path, should_check_fname) { - Ok(x) => x, - Err(e) => { - error!("Couldn't unseal file {}, {}", s_path, e); - return Err(e); + if SgxFile::open(s_path).is_ok() { + info!("File {} is already converted", s_path); + } else { + let data = match unseal_file_from_2_17(s_path, should_check_fname) { + Ok(x) => x, + Err(e) => { + error!("Couldn't unseal file {}, {}", s_path, e); + return Err(e); + } + }; + + let s_path_bkp = s_path.to_string() + ".bkp"; + if let Err(e) = fs::copy(s_path, &s_path_bkp) { + error!("Couldn't backup {} into {}, {}", s_path, s_path_bkp, e); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } - }; - let s_path_bkp = s_path.to_string() + ".bkp"; - if let Err(e) = fs::copy(s_path, &s_path_bkp) { - error!("Couldn't backup {} into {}, {}", s_path, s_path_bkp, e); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); - } + if let Err(e) = seal(data.as_slice(), s_path) { + error!("Couldn't RE-seal file {}, {}", s_path, e); + return Err(e); + } - if let Err(e) = seal(data.as_slice(), s_path) { - error!("Couldn't RE-seal file {}, {}", s_path, e); - return Err(e); + info!("File {} successfully RE-sealed", s_path); } - - info!("File {} successfully RE-sealed", s_path); } else { info!("File {} doesn't exist, skipping", s_path); } From 8e10b25a24fe2605988306b55d12687887df84d5 Mon Sep 17 00:00:00 2001 From: valdok Date: Wed, 17 Apr 2024 21:56:13 +0000 Subject: [PATCH 3/6] build fix (Clippy) --- cosmwasm/enclaves/shared/utils/src/storage.rs | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/cosmwasm/enclaves/shared/utils/src/storage.rs b/cosmwasm/enclaves/shared/utils/src/storage.rs index 99d913321..60c827030 100644 --- a/cosmwasm/enclaves/shared/utils/src/storage.rs +++ b/cosmwasm/enclaves/shared/utils/src/storage.rs @@ -208,15 +208,12 @@ pub fn unseal_file_from_2_17( let p_iv: [u8; 12] = [0; 12]; - if let Err(e) = cur_key_mac.decrypt_once( + cur_key_mac.decrypt_once( std::ptr::addr_of!((*p_md).encr) as *const u8, mem::size_of::() as u32, std::ptr::addr_of!(md_decr) as *mut uint8_t, &p_iv, - ) { - warn!("decrypt file md failed"); - return Err(e); - } + )?; if should_check_fname { let raw_path = s_path.as_bytes(); @@ -277,33 +274,27 @@ pub fn unseal_file_from_2_17( ptr::copy_nonoverlapping(md_decr.data.as_ptr(), bytes.as_mut_ptr(), offs_dst); // Decode mht node - let p_mht_node = bytes_src - .as_mut_ptr() - .offset(mem::size_of::() as isize) - as *mut FileMhtNode; + let p_mht_node = + bytes_src.as_mut_ptr().add(mem::size_of::()) as *mut FileMhtNode; - if let Err(e) = md_decr.root_mht.decrypt_once( + md_decr.root_mht.decrypt_once( p_mht_node as *const u8, mem::size_of::() as u32, p_mht_node as *mut uint8_t, &p_iv, - ) { - return Err(e); - } + )?; let mut offs_src = mem::size_of::() + node_size; for i_node in 0..num_nodes { let keys = &(*p_mht_node).data[i_node]; - if let Err(e) = keys.decrypt_once( - bytes_src.as_ptr().offset(offs_src as isize), + keys.decrypt_once( + bytes_src.as_ptr().add(offs_src), node_size as u32, - bytes.as_mut_ptr().offset(offs_dst as isize), + bytes.as_mut_ptr().add(offs_dst), &p_iv, - ) { - return Err(e); - } + )?; offs_src += node_size; offs_dst += node_size; From 23dbdbd3a780f163053f7a63708cb3b41b138306 Mon Sep 17 00:00:00 2001 From: valdok Date: Thu, 18 Apr 2024 12:32:26 +0000 Subject: [PATCH 4/6] SgxFile migration: removed size limit --- cosmwasm/enclaves/shared/utils/src/storage.rs | 355 ++++++++++++------ 1 file changed, 232 insertions(+), 123 deletions(-) diff --git a/cosmwasm/enclaves/shared/utils/src/storage.rs b/cosmwasm/enclaves/shared/utils/src/storage.rs index 60c827030..9064d0be3 100644 --- a/cosmwasm/enclaves/shared/utils/src/storage.rs +++ b/cosmwasm/enclaves/shared/utils/src/storage.rs @@ -73,7 +73,8 @@ pub struct FileMdPlain { const FILE_MD_ENCRYPTED_DATA_SIZE: usize = 3072; const FILE_MD_ENCRYPTED_FILENAME_SIZE: usize = 260; -const FILE_MD_ENCRYPTED_DATA_NODES: usize = 96; +const FILE_NODE_DATA_NODES: usize = 96; +const FILE_NODE_CHILD_NODES: usize = 32; #[repr(packed)] pub struct FileDataKeyAndMac { @@ -87,8 +88,9 @@ impl FileDataKeyAndMac { p_src: *const uint8_t, src_len: uint32_t, p_dst: *mut uint8_t, - p_iv: &[u8; 12], ) -> Result<(), sgx_status_t> { + let p_iv: [u8; 12] = [0; 12]; + let res = sgx_rijndael128GCM_decrypt( &self.key, p_src, @@ -132,61 +134,123 @@ pub struct FileMd { #[repr(packed)] pub struct FileMhtNode { - pub data: [FileDataKeyAndMac; FILE_MD_ENCRYPTED_DATA_NODES], - pub lower_nodes: [FileDataKeyAndMac; 32], + pub data: [FileDataKeyAndMac; FILE_NODE_DATA_NODES], + pub lower_nodes: [FileDataKeyAndMac; FILE_NODE_CHILD_NODES], } -pub fn unseal_file_from_2_17( - s_path: &str, - should_check_fname: bool, -) -> Result, sgx_status_t> { - let mut file = match File::open(s_path) { - Ok(f) => f, - Err(e) => { - warn!("Failed to open file: {}", e); +pub struct MigrationContext { + pub m_inp: Vec, + pub m_res: Vec, +} + +impl MigrationContext { + pub unsafe fn proceed_from_2_17( + &mut self, + s_path: &str, + should_check_fname: bool, + ) -> Result<(), sgx_status_t> { + if self.m_inp.len() < mem::size_of::() { + warn!("file too small"); return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } - }; - - let mut bytes = Vec::new(); - if let Err(e) = file.read_to_end(&mut bytes) { - warn!("Failed to read file: {}", e); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); - } - if bytes.len() < mem::size_of::() { - warn!("file too small"); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); - } - - unsafe { - let p_md = bytes.as_mut_ptr() as *const FileMd; + let p_md = self.m_inp.as_mut_ptr() as *mut FileMd; if (*p_md).plain.update_flag > 0 { warn!("file left in recovery mode, unsupported"); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); // we don't support recovery + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } + let md_key = self.get_md_key(&*p_md)?; + + let p_md_encr = std::ptr::addr_of_mut!((*p_md).encr); + + md_key.decrypt_once( + p_md_encr as *const u8, + mem::size_of::() as u32, + p_md_encr as *mut uint8_t, + )?; + + if should_check_fname { + MigrationContext::verify_filename(&*p_md_encr, s_path)?; + } + + //let ret_size = (*p_md_encr).size as usize; + let ret_size = std::ptr::read_unaligned(std::ptr::addr_of!((*p_md_encr).size)) as usize; + + if ret_size <= FILE_MD_ENCRYPTED_DATA_SIZE { + self.allocate_res(ret_size, ret_size, &*p_md_encr); + } else { + let node_size = mem::size_of::(); // 4K + + let mut data_nodes = + (ret_size - FILE_MD_ENCRYPTED_DATA_SIZE + node_size - 1) / node_size; + let mht_nodes = (data_nodes + FILE_NODE_DATA_NODES - 1) / FILE_NODE_DATA_NODES; + + let size_required = mem::size_of::() + node_size * (data_nodes + mht_nodes); + if self.m_inp.len() < size_required { + warn!("file too short"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); + } + + // allocate with padding + self.allocate_res( + FILE_MD_ENCRYPTED_DATA_SIZE + node_size * data_nodes, + FILE_MD_ENCRYPTED_DATA_SIZE, + &*p_md_encr, + ); + + let mut offs_dst = FILE_MD_ENCRYPTED_DATA_SIZE; + let mut offs_src = mem::size_of::(); + + let mut p_mk_0 = std::ptr::addr_of_mut!((*p_md_encr).root_mht); + let mut p_mk_1 = p_mk_0.add(1); + + loop { + + let chunk = if data_nodes <= FILE_NODE_DATA_NODES { data_nodes } else { FILE_NODE_DATA_NODES }; + + let p_mht_node = self.process_mht_node(&(*p_mk_0), &mut offs_src, &mut offs_dst, chunk)?; + + if chunk == data_nodes { + break; + } + + ptr::copy_nonoverlapping((*p_mht_node).lower_nodes.as_ptr(), p_mk_1, FILE_NODE_CHILD_NODES); + + p_mk_0 = p_mk_0.add(1); + p_mk_1 = p_mk_1.add(FILE_NODE_CHILD_NODES); + + data_nodes -= chunk; + } + + self.m_res.resize(ret_size, 0); // truncate the padding + } + + Ok(()) + } + + unsafe fn get_md_key(&self, md: &FileMd) -> Result { let mut key_request = sgx_key_request_t { key_name: sgx_types::SGX_KEYSELECT_SEAL, key_policy: sgx_types::SGX_KEYPOLICY_MRSIGNER, misc_mask: sgx_types::TSEAL_DEFAULT_MISCMASK, - isv_svn: (*p_md).plain.isv_svn, + isv_svn: md.plain.isv_svn, ..Default::default() }; key_request.attribute_mask.flags = sgx_types::TSEAL_DEFAULT_FLAGSMASK; key_request.attribute_mask.xfrm = 0x0; - key_request.cpu_svn.svn = (*p_md).plain.cpu_svn; - key_request.key_id.id = (*p_md).plain.key_id; + key_request.cpu_svn.svn = md.plain.cpu_svn; + key_request.key_id.id = md.plain.key_id; - let mut cur_key_mac = FileDataKeyAndMac { + let mut ret = FileDataKeyAndMac { key: sgx_key_128bit_t::default(), - gmac: (*p_md).plain.meta_data_gmac, + gmac: md.plain.meta_data_gmac, }; - match sgx_get_key(&key_request, &mut cur_key_mac.key) { + match sgx_get_key(&key_request, &mut ret.key) { sgx_status_t::SGX_SUCCESS => {} err_code => { warn!("gen key failed"); @@ -194,117 +258,107 @@ pub fn unseal_file_from_2_17( } } - let /* mut */ md_decr: FileMdEncrypted = FileMdEncrypted { - clean_filename: [0; FILE_MD_ENCRYPTED_FILENAME_SIZE], - size: 0, - mc_uuid: [0; 16], - mc_value: 0, - root_mht: FileDataKeyAndMac{ - key: [0; 16], - gmac: [0; 16], - }, - data: [0; FILE_MD_ENCRYPTED_DATA_SIZE], - }; - - let p_iv: [u8; 12] = [0; 12]; - - cur_key_mac.decrypt_once( - std::ptr::addr_of!((*p_md).encr) as *const u8, - mem::size_of::() as u32, - std::ptr::addr_of!(md_decr) as *mut uint8_t, - &p_iv, - )?; - - if should_check_fname { - let raw_path = s_path.as_bytes(); - - let mut fname0: usize = 0; - for (i, ch) in raw_path.iter().enumerate() { - if *ch == b'/' { - fname0 = i + 1; - } - } - - let file_name_len = raw_path.len() - fname0; + Ok(ret) + } - if file_name_len > FILE_MD_ENCRYPTED_FILENAME_SIZE { - return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH); - } + unsafe fn verify_filename(md: &FileMdEncrypted, s_path: &str) -> Result<(), sgx_status_t> { + let raw_path = s_path.as_bytes(); - if (file_name_len < FILE_MD_ENCRYPTED_FILENAME_SIZE) - && (md_decr.clean_filename[file_name_len] != 0) - { - return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH); + let mut fname0: usize = 0; + for (i, ch) in raw_path.iter().enumerate() { + if *ch == b'/' { + fname0 = i + 1; } + } - let src_name = slice::from_raw_parts(&raw_path[fname0], file_name_len); - let dst_name = slice::from_raw_parts(&md_decr.clean_filename[0], file_name_len); + let file_name_len = raw_path.len() - fname0; - if src_name != dst_name { - return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH); - } + if file_name_len > FILE_MD_ENCRYPTED_FILENAME_SIZE { + return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH); } - let ret_size = std::ptr::read_unaligned(std::ptr::addr_of!(md_decr.size)) as usize; - - if ret_size <= FILE_MD_ENCRYPTED_DATA_SIZE { - bytes.resize(ret_size, 0); - bytes.copy_from_slice(slice::from_raw_parts(md_decr.data.as_ptr(), ret_size)); - } else { - let node_size = mem::size_of::(); // 4K + if (file_name_len < FILE_MD_ENCRYPTED_FILENAME_SIZE) + && (md.clean_filename[file_name_len] != 0) + { + return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH); + } - let num_nodes = (ret_size - FILE_MD_ENCRYPTED_DATA_SIZE + node_size - 1) / node_size; - if num_nodes > FILE_MD_ENCRYPTED_DATA_NODES { - warn!("too many nodes, indirect files not supported"); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); - } + let src_name = slice::from_raw_parts(&raw_path[fname0], file_name_len); + let dst_name = slice::from_raw_parts(&md.clean_filename[0], file_name_len); - let size_required = mem::size_of::() + node_size * (num_nodes + 1); - if bytes.len() < size_required { - warn!("file too short"); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); - } + if src_name != dst_name { + return Err(sgx_status_t::SGX_ERROR_FILE_NAME_MISMATCH); + } - let mut bytes_src = bytes; - bytes = Vec::new(); - bytes.resize(FILE_MD_ENCRYPTED_DATA_SIZE + node_size * num_nodes, 7); // allocate with padding + Ok(()) + } - let mut offs_dst = FILE_MD_ENCRYPTED_DATA_SIZE; + unsafe fn allocate_res(&mut self, size: usize, size_from_md: usize, md: &FileMdEncrypted) { + self.m_res.resize(size, 0); + ptr::copy_nonoverlapping(md.data.as_ptr(), self.m_res.as_mut_ptr(), size_from_md); + } - ptr::copy_nonoverlapping(md_decr.data.as_ptr(), bytes.as_mut_ptr(), offs_dst); + unsafe fn process_mht_node( + &mut self, + parent_km: &FileDataKeyAndMac, + offs_src: &mut usize, + offs_dst: &mut usize, + num_nodes: usize, + ) -> Result<*const FileMhtNode, sgx_status_t> { + // Decode mht node + let node_size = mem::size_of::(); // 4K + + let p_mht_node = self.m_inp.as_mut_ptr().add(*offs_src) as *mut FileMhtNode; + *offs_src += mem::size_of::(); + + parent_km.decrypt_once( + p_mht_node as *const u8, + mem::size_of::() as u32, + p_mht_node as *mut uint8_t, + )?; - // Decode mht node - let p_mht_node = - bytes_src.as_mut_ptr().add(mem::size_of::()) as *mut FileMhtNode; + for i_node in 0..num_nodes { + let km = &(*p_mht_node).data[i_node]; - md_decr.root_mht.decrypt_once( - p_mht_node as *const u8, - mem::size_of::() as u32, - p_mht_node as *mut uint8_t, - &p_iv, + km.decrypt_once( + self.m_inp.as_ptr().add(*offs_src), + node_size as u32, + self.m_res.as_mut_ptr().add(*offs_dst), )?; - let mut offs_src = mem::size_of::() + node_size; - - for i_node in 0..num_nodes { - let keys = &(*p_mht_node).data[i_node]; - - keys.decrypt_once( - bytes_src.as_ptr().add(offs_src), - node_size as u32, - bytes.as_mut_ptr().add(offs_dst), - &p_iv, - )?; + *offs_src += node_size; + *offs_dst += node_size; + } - offs_src += node_size; - offs_dst += node_size; - } + Ok(p_mht_node) + } +} - bytes.resize(ret_size, 0); // truncate the padding +pub fn unseal_file_from_2_17( + s_path: &str, + should_check_fname: bool, +) -> Result, sgx_status_t> { + let mut file = match File::open(s_path) { + Ok(f) => f, + Err(e) => { + warn!("Failed to open file: {}", e); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } }; - Ok(bytes) + let mut mctx = MigrationContext { + m_inp: Vec::new(), + m_res: Vec::new(), + }; + + if let Err(e) = file.read_to_end(&mut mctx.m_inp) { + warn!("Failed to read file: {}", e); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); + } + + unsafe { mctx.proceed_from_2_17(s_path, should_check_fname) }?; + + Ok(mctx.m_res) } pub fn migrate_file_from_2_17_safe( @@ -342,3 +396,58 @@ pub fn migrate_file_from_2_17_safe( Ok(()) } + + +/* +pub fn test_migration_once(size: usize) { + println!("Testing SGX migration, size={}", size); + + let mut data: Vec = Vec::new(); + data.reserve(size); + + for i in 0..size { + data.push(((i * 17) % 251) as u8); + } + + { + let mut f = match SgxFile::create("large_file") { + Ok(file) => file, + Err(_) => { + return; + } + }; + + if f.write_all(&data).is_err() { + return; + } + } + + let data2 = match unseal_file_from_2_17("large_file", true) { + Ok(d) => d, + Err(e) => { + println!("Unseal failed: {}", e); + return; + } + }; + + if data.as_slice() == data2.as_slice() { + println!("match"); + } else { + println!("MIS-match"); + } +} + +pub fn test_migration() { + test_migration_once(0); + test_migration_once(19); + test_migration_once(500); + test_migration_once(3072); + test_migration_once(3073); // indirect + test_migration_once(20000); + test_migration_once(3072 + 96 * 4096 - 100); + test_migration_once(3072 + 96 * 4096); + test_migration_once(3072 + 96 * 4096 + 100); // 2nd-order + test_migration_once(3072 + 96 * 4096 * 33); // max 2nd-order + test_migration_once(50000000); // huge +} +*/ From 8842429bde0bb2ace215b6a2c2902bd6749921e3 Mon Sep 17 00:00:00 2001 From: valdok Date: Thu, 18 Apr 2024 13:23:59 +0000 Subject: [PATCH 5/6] build fix (Clippy) --- cosmwasm/enclaves/shared/utils/src/storage.rs | 117 +++++++++++------- 1 file changed, 71 insertions(+), 46 deletions(-) diff --git a/cosmwasm/enclaves/shared/utils/src/storage.rs b/cosmwasm/enclaves/shared/utils/src/storage.rs index 9064d0be3..f2bebab7c 100644 --- a/cosmwasm/enclaves/shared/utils/src/storage.rs +++ b/cosmwasm/enclaves/shared/utils/src/storage.rs @@ -144,7 +144,7 @@ pub struct MigrationContext { } impl MigrationContext { - pub unsafe fn proceed_from_2_17( + pub fn proceed_from_2_17( &mut self, s_path: &str, should_check_fname: bool, @@ -154,6 +154,14 @@ impl MigrationContext { return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } + return unsafe { self.proceed_internal(s_path, should_check_fname) }; + } + + unsafe fn proceed_internal( + &mut self, + s_path: &str, + should_check_fname: bool, + ) -> Result<(), sgx_status_t> { let p_md = self.m_inp.as_mut_ptr() as *mut FileMd; if (*p_md).plain.update_flag > 0 { @@ -181,50 +189,7 @@ impl MigrationContext { if ret_size <= FILE_MD_ENCRYPTED_DATA_SIZE { self.allocate_res(ret_size, ret_size, &*p_md_encr); } else { - let node_size = mem::size_of::(); // 4K - - let mut data_nodes = - (ret_size - FILE_MD_ENCRYPTED_DATA_SIZE + node_size - 1) / node_size; - let mht_nodes = (data_nodes + FILE_NODE_DATA_NODES - 1) / FILE_NODE_DATA_NODES; - - let size_required = mem::size_of::() + node_size * (data_nodes + mht_nodes); - if self.m_inp.len() < size_required { - warn!("file too short"); - return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); - } - - // allocate with padding - self.allocate_res( - FILE_MD_ENCRYPTED_DATA_SIZE + node_size * data_nodes, - FILE_MD_ENCRYPTED_DATA_SIZE, - &*p_md_encr, - ); - - let mut offs_dst = FILE_MD_ENCRYPTED_DATA_SIZE; - let mut offs_src = mem::size_of::(); - - let mut p_mk_0 = std::ptr::addr_of_mut!((*p_md_encr).root_mht); - let mut p_mk_1 = p_mk_0.add(1); - - loop { - - let chunk = if data_nodes <= FILE_NODE_DATA_NODES { data_nodes } else { FILE_NODE_DATA_NODES }; - - let p_mht_node = self.process_mht_node(&(*p_mk_0), &mut offs_src, &mut offs_dst, chunk)?; - - if chunk == data_nodes { - break; - } - - ptr::copy_nonoverlapping((*p_mht_node).lower_nodes.as_ptr(), p_mk_1, FILE_NODE_CHILD_NODES); - - p_mk_0 = p_mk_0.add(1); - p_mk_1 = p_mk_1.add(FILE_NODE_CHILD_NODES); - - data_nodes -= chunk; - } - - self.m_res.resize(ret_size, 0); // truncate the padding + self.process_all_mht_nodes(ret_size, &mut *p_md_encr)?; } Ok(()) @@ -298,6 +263,66 @@ impl MigrationContext { ptr::copy_nonoverlapping(md.data.as_ptr(), self.m_res.as_mut_ptr(), size_from_md); } + unsafe fn process_all_mht_nodes( + &mut self, + ret_size: usize, + md: &mut FileMdEncrypted, + ) -> Result<(), sgx_status_t> { + let node_size = mem::size_of::(); // 4K + + let mut data_nodes = (ret_size - FILE_MD_ENCRYPTED_DATA_SIZE + node_size - 1) / node_size; + let mht_nodes = (data_nodes + FILE_NODE_DATA_NODES - 1) / FILE_NODE_DATA_NODES; + + let size_required = mem::size_of::() + node_size * (data_nodes + mht_nodes); + if self.m_inp.len() < size_required { + warn!("file too short"); + return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); + } + + // allocate with padding + self.allocate_res( + FILE_MD_ENCRYPTED_DATA_SIZE + node_size * data_nodes, + FILE_MD_ENCRYPTED_DATA_SIZE, + &md, + ); + + let mut offs_dst = FILE_MD_ENCRYPTED_DATA_SIZE; + let mut offs_src = mem::size_of::(); + + let mut p_mk_0 = std::ptr::addr_of_mut!(md.root_mht); + let mut p_mk_1 = p_mk_0.add(1); + + loop { + let chunk = if data_nodes <= FILE_NODE_DATA_NODES { + data_nodes + } else { + FILE_NODE_DATA_NODES + }; + + let p_mht_node = + self.process_mht_node(&(*p_mk_0), &mut offs_src, &mut offs_dst, chunk)?; + + if chunk == data_nodes { + break; + } + + ptr::copy_nonoverlapping( + (*p_mht_node).lower_nodes.as_ptr(), + p_mk_1, + FILE_NODE_CHILD_NODES, + ); + + p_mk_0 = p_mk_0.add(1); + p_mk_1 = p_mk_1.add(FILE_NODE_CHILD_NODES); + + data_nodes -= chunk; + } + + self.m_res.resize(ret_size, 0); // truncate the padding + + Ok(()) + } + unsafe fn process_mht_node( &mut self, parent_km: &FileDataKeyAndMac, @@ -356,7 +381,7 @@ pub fn unseal_file_from_2_17( return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } - unsafe { mctx.proceed_from_2_17(s_path, should_check_fname) }?; + mctx.proceed_from_2_17(s_path, should_check_fname)?; Ok(mctx.m_res) } From f810f96d7ad9cce7a96d96fc5cb6c367672e51e2 Mon Sep 17 00:00:00 2001 From: valdok Date: Thu, 18 Apr 2024 14:10:46 +0000 Subject: [PATCH 6/6] build fix (Clippy) WIP(2) --- cosmwasm/enclaves/shared/utils/src/storage.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cosmwasm/enclaves/shared/utils/src/storage.rs b/cosmwasm/enclaves/shared/utils/src/storage.rs index f2bebab7c..702db98b9 100644 --- a/cosmwasm/enclaves/shared/utils/src/storage.rs +++ b/cosmwasm/enclaves/shared/utils/src/storage.rs @@ -154,7 +154,7 @@ impl MigrationContext { return Err(sgx_status_t::SGX_ERROR_UNEXPECTED); } - return unsafe { self.proceed_internal(s_path, should_check_fname) }; + unsafe { self.proceed_internal(s_path, should_check_fname) } } unsafe fn proceed_internal( @@ -283,7 +283,7 @@ impl MigrationContext { self.allocate_res( FILE_MD_ENCRYPTED_DATA_SIZE + node_size * data_nodes, FILE_MD_ENCRYPTED_DATA_SIZE, - &md, + md, ); let mut offs_dst = FILE_MD_ENCRYPTED_DATA_SIZE;