This is an automated email from the ASF dual-hosted git repository. rduan pushed a commit to branch v2.0.0-preview in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git
commit 37297011ce744062ba1c70d4390776f56b4729f1 Author: volcano <[email protected]> AuthorDate: Fri Sep 2 20:40:47 2022 +0800 Improve SGX Protected FS --- sgx_protected_fs/tfs/src/capi.rs | 70 +++++++++++++++++++++-- sgx_protected_fs/tfs/src/fs.rs | 92 ++++++++++++++++++++++++------- sgx_protected_fs/tfs/src/sys/file/mod.rs | 18 ++++-- sgx_protected_fs/tfs/src/sys/file/node.rs | 2 +- sgx_protected_fs/tfs/src/sys/file/open.rs | 34 +++++++++++- sgx_protected_fs/tfs/src/sys/metadata.rs | 11 ---- sgx_protected_fs/tfs/src/sys/mod.rs | 6 +- sgx_protected_fs/tfs/src/sys/node.rs | 4 +- sgx_protected_fs/ufs/src/lib.rs | 8 ++- 9 files changed, 199 insertions(+), 46 deletions(-) diff --git a/sgx_protected_fs/tfs/src/capi.rs b/sgx_protected_fs/tfs/src/capi.rs index 595f9224..39d93c45 100644 --- a/sgx_protected_fs/tfs/src/capi.rs +++ b/sgx_protected_fs/tfs/src/capi.rs @@ -37,11 +37,19 @@ pub unsafe extern "C" fn sgx_fopen( mode: *const c_char, key: *const Key128bit, ) -> RawProtectedFile { - if filename.is_null() || mode.is_null() || key.is_null() { + if filename.is_null() || mode.is_null() { eos!(EINVAL).set_errno(); return ptr::null_mut(); } + #[cfg(not(feature = "tfs"))] + { + if key.is_null() { + eos!(EINVAL).set_errno(); + return ptr::null_mut(); + } + } + let name = match CStr::from_ptr(filename).to_str() { Ok(name) => name, Err(_) => { @@ -58,8 +66,12 @@ pub unsafe extern "C" fn sgx_fopen( } }; - let encrypt_mode = EncryptMode::EncryptWithIntegrity(*key); - match SgxFile::open(name, &opts, &encrypt_mode) { + let encrypt_mode = if key.is_null() { + EncryptMode::EncryptAutoKey + } else { + EncryptMode::EncryptWithIntegrity(*key) + }; + match SgxFile::open(name, &opts, &encrypt_mode, None) { Ok(file) => file.into_raw(), Err(_) => ptr::null_mut(), } @@ -94,7 +106,7 @@ pub unsafe extern "C" fn sgx_fopen_auto_key( }; let encrypt_mode = EncryptMode::EncryptAutoKey; - match SgxFile::open(name, &opts, &encrypt_mode) { + match SgxFile::open(name, &opts, &encrypt_mode, None) { Ok(file) => file.into_raw(), Err(_) => ptr::null_mut(), } @@ -128,7 +140,55 @@ pub unsafe extern "C" fn sgx_fopen_integrity_only( }; let encrypt_mode = EncryptMode::IntegrityOnly; - match SgxFile::open(name, &opts, &encrypt_mode) { + match SgxFile::open(name, &opts, &encrypt_mode, None) { + Ok(file) => file.into_raw(), + Err(_) => ptr::null_mut(), + } +} + +/// # Safety +#[no_mangle] +pub unsafe extern "C" fn sgx_fopen_ex( + filename: *const c_char, + mode: *const c_char, + key: *const Key128bit, + cache_size: u64, +) -> RawProtectedFile { + if filename.is_null() || mode.is_null() || cache_size < fs_imp::DEFAULT_CACHE_SIZE as u64 { + eos!(EINVAL).set_errno(); + return ptr::null_mut(); + } + + #[cfg(not(feature = "tfs"))] + { + if key.is_null() { + eos!(EINVAL).set_errno(); + return ptr::null_mut(); + } + } + + let name = match CStr::from_ptr(filename).to_str() { + Ok(name) => name, + Err(_) => { + eos!(EINVAL).set_errno(); + return ptr::null_mut(); + } + }; + + let opts = match parse_mode(CStr::from_ptr(mode)) { + Ok(mode) => mode, + Err(error) => { + error.set_errno(); + return ptr::null_mut(); + } + }; + + let encrypt_mode = if key.is_null() { + EncryptMode::EncryptAutoKey + } else { + EncryptMode::EncryptWithIntegrity(*key) + }; + match SgxFile::open(name, &opts, &encrypt_mode, Some(cache_size as usize)) { Ok(file) => file.into_raw(), Err(_) => ptr::null_mut(), } diff --git a/sgx_protected_fs/tfs/src/fs.rs b/sgx_protected_fs/tfs/src/fs.rs index 60e6f21b..c73de67f 100644 --- a/sgx_protected_fs/tfs/src/fs.rs +++ b/sgx_protected_fs/tfs/src/fs.rs @@ -41,6 +41,9 @@ cfg_if! { #[derive(Clone, Debug)] pub struct OpenOptions(fs_imp::OpenOptions); +#[derive(Clone, Debug)] +pub struct EncryptMode(fs_imp::EncryptMode); + /// A reference to an open Sgxfile on the filesystem. /// /// An instance of a `SgxFile` can be read and/or written depending on what options @@ -76,14 +79,14 @@ pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result SgxFile::create(path)?.write_all(contents.as_ref()) } -pub fn read_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<Vec<u8>> { +pub fn read_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<Vec<u8>> { let mut file = SgxFile::open_with_key(path, key)?; let mut bytes = Vec::with_capacity(buffer_capacity_required(&file)); file.read_to_end(&mut bytes)?; Ok(bytes) } -pub fn read_to_string_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<String> { +pub fn read_to_string_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<String> { let mut file = SgxFile::open_with_key(path, key)?; let mut string = String::with_capacity(buffer_capacity_required(&file)); file.read_to_string(&mut string)?; @@ -92,7 +95,7 @@ pub fn read_to_string_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io:: pub fn write_with_key<P: AsRef<Path>, C: AsRef<[u8]>>( path: P, - key: &Key128bit, + key: Key128bit, contents: C, ) -> io::Result<()> { SgxFile::create_with_key(path, key)?.write_all(contents.as_ref()) @@ -135,19 +138,19 @@ impl SgxFile { OpenOptions::new().append(true).open(path.as_ref()) } - pub fn open_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<SgxFile> { + pub fn open_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<SgxFile> { OpenOptions::new() .read(true) .open_with_key(path.as_ref(), key) } - pub fn create_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<SgxFile> { + pub fn create_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<SgxFile> { OpenOptions::new() .write(true) .open_with_key(path.as_ref(), key) } - pub fn append_with_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<SgxFile> { + pub fn append_with_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<SgxFile> { OpenOptions::new() .append(true) .open_with_key(path.as_ref(), key) @@ -171,7 +174,37 @@ impl SgxFile { .open_integrity_only(path.as_ref()) } - pub fn with_options() -> OpenOptions { + pub fn open_with<P: AsRef<Path>>( + path: P, + encrypt_mode: EncryptMode, + cache_size: Option<usize>, + ) -> io::Result<SgxFile> { + OpenOptions::new() + .read(true) + .open_with(path.as_ref(), encrypt_mode, cache_size) + } + + pub fn create_with<P: AsRef<Path>>( + path: P, + encrypt_mode: EncryptMode, + cache_size: Option<usize>, + ) -> io::Result<SgxFile> { + OpenOptions::new() + .write(true) + .open_with(path.as_ref(), encrypt_mode, cache_size) + } + + pub fn append_with<P: AsRef<Path>>( + path: P, + encrypt_mode: EncryptMode, + cache_size: Option<usize>, + ) -> io::Result<SgxFile> { + OpenOptions::new() + .append(true) + .open_with(path.as_ref(), encrypt_mode, cache_size) + } + + pub fn options() -> OpenOptions { OpenOptions::new() } @@ -299,8 +332,8 @@ pub fn export_key<P: AsRef<Path>>(path: P) -> io::Result<Key128bit> { } #[cfg(feature = "tfs")] -pub fn import_key<P: AsRef<Path>>(path: P, key: &Key128bit) -> io::Result<()> { - fs_imp::import_key(path.as_ref(), *key) +pub fn import_key<P: AsRef<Path>>(path: P, key: Key128bit) -> io::Result<()> { + fs_imp::import_key(path.as_ref(), key) } impl OpenOptions { @@ -342,21 +375,24 @@ impl OpenOptions { /// Opens a file at `path` with the options specified by `self`. #[cfg(feature = "tfs")] pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<SgxFile> { - let inner = fs_imp::SgxFile::open(path, &self.0, &fs_imp::EncryptMode::EncryptAutoKey)?; - Ok(SgxFile { inner }) + self.open_with(path, EncryptMode::with_auto_key(), None) } - pub fn open_with_key<P: AsRef<Path>>(&self, path: P, key: &Key128bit) -> io::Result<SgxFile> { - let inner = fs_imp::SgxFile::open( - path, - &self.0, - &fs_imp::EncryptMode::EncryptWithIntegrity(*key), - )?; - Ok(SgxFile { inner }) + pub fn open_with_key<P: AsRef<Path>>(&self, path: P, key: Key128bit) -> io::Result<SgxFile> { + self.open_with(path, EncryptMode::with_user_key(key), None) } pub fn open_integrity_only<P: AsRef<Path>>(&self, path: P) -> io::Result<SgxFile> { - let inner = fs_imp::SgxFile::open(path, &self.0, &fs_imp::EncryptMode::IntegrityOnly)?; + self.open_with(path, EncryptMode::integrity_only(), None) + } + + pub fn open_with<P: AsRef<Path>>( + &self, + path: P, + encrypt_mode: EncryptMode, + cache_size: Option<usize>, + ) -> io::Result<SgxFile> { + let inner = fs_imp::SgxFile::open(path, &self.0, &encrypt_mode.0, cache_size)?; Ok(SgxFile { inner }) } } @@ -366,3 +402,21 @@ impl Default for OpenOptions { Self::new() } } + +impl EncryptMode { + #[cfg(feature = "tfs")] + #[inline] + pub fn with_auto_key() -> EncryptMode { + EncryptMode(fs_imp::EncryptMode::EncryptAutoKey) + } + + #[inline] + pub fn with_user_key(key: Key128bit) -> EncryptMode { + EncryptMode(fs_imp::EncryptMode::EncryptWithIntegrity(key)) + } + + #[inline] + pub fn integrity_only() -> EncryptMode { + EncryptMode(fs_imp::EncryptMode::IntegrityOnly) + } +} diff --git a/sgx_protected_fs/tfs/src/sys/file/mod.rs b/sgx_protected_fs/tfs/src/sys/file/mod.rs index 986f8138..162d7d02 100644 --- a/sgx_protected_fs/tfs/src/sys/file/mod.rs +++ b/sgx_protected_fs/tfs/src/sys/file/mod.rs @@ -30,6 +30,8 @@ use std::path::Path; use std::path::PathBuf; use std::sync::Mutex; +pub use open::DEFAULT_CACHE_SIZE; + mod close; mod flush; mod node; @@ -43,8 +45,6 @@ pub struct ProtectedFile { file: Mutex<FileInner>, } -const MAX_PAGES_IN_CACHE: usize = 48; - #[derive(Debug)] struct FileInner { host_file: HostFile, @@ -54,6 +54,7 @@ struct FileInner { opts: OpenOptions, need_writing: bool, end_of_file: bool, + max_cache_page: usize, offset: usize, last_error: FsError, status: FileStatus, @@ -62,8 +63,13 @@ struct FileInner { } impl ProtectedFile { - pub fn open<P: AsRef<Path>>(path: P, opts: &OpenOptions, mode: &OpenMode) -> FsResult<Self> { - let file = FileInner::open(path.as_ref(), opts, mode)?; + pub fn open<P: AsRef<Path>>( + path: P, + opts: &OpenOptions, + mode: &OpenMode, + cache_size: Option<usize>, + ) -> FsResult<Self> { + let file = FileInner::open(path.as_ref(), opts, mode, cache_size)?; Ok(Self { file: Mutex::new(file), }) @@ -270,6 +276,7 @@ impl ProtectedFile { path.as_ref(), &OpenOptions::new().read(true), &OpenMode::AutoKey, + None, )?; file.close(CloseMode::Export).map(|key| key.unwrap()) } @@ -280,6 +287,7 @@ impl ProtectedFile { path.as_ref(), &OpenOptions::new().read(true).update(true), &OpenMode::ImportKey(key), + None, )?; file.close(CloseMode::Import).map(|_| ()) } @@ -418,6 +426,7 @@ impl OpenMode { impl From<EncryptMode> for OpenMode { fn from(encrypt_mode: EncryptMode) -> OpenMode { match encrypt_mode { + #[cfg(feature = "tfs")] EncryptMode::EncryptAutoKey => Self::AutoKey, EncryptMode::EncryptWithIntegrity(key) => Self::UserKey(key), EncryptMode::IntegrityOnly => Self::IntegrityOnly, @@ -428,6 +437,7 @@ impl From<EncryptMode> for OpenMode { impl From<&EncryptMode> for OpenMode { fn from(encrypt_mode: &EncryptMode) -> OpenMode { match encrypt_mode { + #[cfg(feature = "tfs")] EncryptMode::EncryptAutoKey => Self::AutoKey, EncryptMode::EncryptWithIntegrity(key) => Self::UserKey(*key), EncryptMode::IntegrityOnly => Self::IntegrityOnly, diff --git a/sgx_protected_fs/tfs/src/sys/file/node.rs b/sgx_protected_fs/tfs/src/sys/file/node.rs index b3f53914..24ad03c4 100644 --- a/sgx_protected_fs/tfs/src/sys/file/node.rs +++ b/sgx_protected_fs/tfs/src/sys/file/node.rs @@ -187,7 +187,7 @@ impl FileInner { } fn shrink_cache(&mut self) -> FsResult { - while self.cache.len() > super::MAX_PAGES_IN_CACHE { + while self.cache.len() > self.max_cache_page { let node = self.cache.back().ok_or(SgxStatus::Unexpected)?; if !node.borrow().need_writing { let _node = self.cache.pop_back(); diff --git a/sgx_protected_fs/tfs/src/sys/file/open.rs b/sgx_protected_fs/tfs/src/sys/file/open.rs index 193d8c9d..04232403 100644 --- a/sgx_protected_fs/tfs/src/sys/file/open.rs +++ b/sgx_protected_fs/tfs/src/sys/file/open.rs @@ -28,12 +28,27 @@ use crate::sys::node::{FileNode, FileNodeRef}; use sgx_types::error::errno::*; use sgx_types::error::SgxStatus; use sgx_types::memeq::ConstTimeEq; +use sgx_types::metadata::SE_PAGE_SIZE; use sgx_types::types::Key128bit; use std::borrow::ToOwned; use std::path::Path; +macro_rules! is_page_aligned { + ($num:expr) => { + $num & (SE_PAGE_SIZE - 1) == 0 + }; +} + +pub const DEFAULT_CACHE_SIZE: usize = 48 * SE_PAGE_SIZE; + impl FileInner { - pub fn open(path: &Path, opts: &OpenOptions, mode: &OpenMode) -> FsResult<Self> { + pub fn open( + path: &Path, + opts: &OpenOptions, + mode: &OpenMode, + cache_size: Option<usize>, + ) -> FsResult<Self> { + let cache_size = Self::check_cache_size(cache_size)?; let file_name = path.file_name().ok_or(EINVAL)?.to_str().ok_or(EINVAL)?; Self::check_open_param(path, file_name, opts, mode)?; @@ -86,11 +101,12 @@ impl FileInner { opts: *opts, need_writing, end_of_file: false, + max_cache_page: cache_size, offset, last_error: esgx!(SgxStatus::Success), status: FileStatus::NotInitialized, recovery_path, - cache: LruCache::new(super::MAX_PAGES_IN_CACHE), + cache: LruCache::new(cache_size), }; protected_file.status = FileStatus::Ok; @@ -203,4 +219,18 @@ impl FileInner { } Ok(()) } + + #[inline] + fn check_cache_size(cache_size: Option<usize>) -> FsResult<usize> { + cache_size + .or(Some(DEFAULT_CACHE_SIZE)) + .and_then(|cache_size| { + if is_page_aligned!(cache_size) && cache_size >= DEFAULT_CACHE_SIZE { + Some(cache_size / SE_PAGE_SIZE) + } else { + None + } + }) + .ok_or_else(|| eos!(EINVAL)) + } } diff --git a/sgx_protected_fs/tfs/src/sys/metadata.rs b/sgx_protected_fs/tfs/src/sys/metadata.rs index 439012cb..42c14dc0 100644 --- a/sgx_protected_fs/tfs/src/sys/metadata.rs +++ b/sgx_protected_fs/tfs/src/sys/metadata.rs @@ -20,7 +20,6 @@ use crate::sys::file::OpenMode; use crate::sys::host::HostFs; use crate::sys::keys::{DeriveKey, KeyType, RestoreKey}; use crate::sys::node::{META_DATA_PHY_NUM, NODE_SIZE}; -use crate::sys::EncryptMode; use sgx_crypto::aes::gcm::{Aad, AesGcm, Nonce}; use sgx_types::error::SgxStatus; use sgx_types::types::{Attributes, CpuSvn, Key128bit, KeyId, Mac128bit}; @@ -74,16 +73,6 @@ impl From<&OpenMode> for EncryptFlags { } } -impl From<&EncryptMode> for EncryptFlags { - fn from(mode: &EncryptMode) -> Self { - match mode { - EncryptMode::EncryptAutoKey => Self::AutoKey, - EncryptMode::EncryptWithIntegrity(_) => Self::UserKey, - EncryptMode::IntegrityOnly => Self::IntegrityOnly, - } - } -} - #[derive(Clone, Copy, Debug, Default)] #[repr(C, packed)] pub struct MetadataPlain { diff --git a/sgx_protected_fs/tfs/src/sys/mod.rs b/sgx_protected_fs/tfs/src/sys/mod.rs index 770bccf6..8744cd2a 100644 --- a/sgx_protected_fs/tfs/src/sys/mod.rs +++ b/sgx_protected_fs/tfs/src/sys/mod.rs @@ -23,6 +23,8 @@ use std::io::{Result, SeekFrom}; use std::mem::ManuallyDrop; use std::path::Path; +pub use file::DEFAULT_CACHE_SIZE; + #[macro_use] pub(crate) mod error; #[macro_use] @@ -39,6 +41,7 @@ pub struct OpenOptions(file_imp::OpenOptions); #[derive(Clone, Debug)] pub enum EncryptMode { + #[cfg(feature = "tfs")] EncryptAutoKey, EncryptWithIntegrity(Key128bit), IntegrityOnly, @@ -89,9 +92,10 @@ impl SgxFile { path: P, opts: &OpenOptions, encrypt_mode: &EncryptMode, + cache_size: Option<usize>, ) -> Result<SgxFile> { opts.check_access_mode()?; - ProtectedFile::open(path, &opts.0, &From::from(encrypt_mode)) + ProtectedFile::open(path, &opts.0, &encrypt_mode.into(), cache_size) .map_err(|e| { e.set_errno(); e.to_io_error() diff --git a/sgx_protected_fs/tfs/src/sys/node.rs b/sgx_protected_fs/tfs/src/sys/node.rs index 13b20cc8..7419c328 100644 --- a/sgx_protected_fs/tfs/src/sys/node.rs +++ b/sgx_protected_fs/tfs/src/sys/node.rs @@ -221,14 +221,14 @@ impl FileNode { node_type, logic_number, need_writing: false, - encrypt_flags, new_node: true, + encrypt_flags, ciphertext: EncryptedNode { physical_number, node_data: EncryptedData::default(), }, - parent: None, plaintext: Node::new(node_type), + parent: None, } } diff --git a/sgx_protected_fs/ufs/src/lib.rs b/sgx_protected_fs/ufs/src/lib.rs index 6ff08118..5054ee78 100644 --- a/sgx_protected_fs/ufs/src/lib.rs +++ b/sgx_protected_fs/ufs/src/lib.rs @@ -110,7 +110,12 @@ impl HostFile { } pub fn flush(&mut self) -> OsResult { - self.stream.flush() + self.stream.flush()?; + if unsafe { libc::fsync(self.fd) } == 0 { + Ok(()) + } else { + Err(errno()) + } } pub fn size(&self) -> OsResult<usize> { @@ -144,6 +149,7 @@ impl Drop for HostFile { fn drop(&mut self) { unsafe { libc::flock(self.fd, libc::LOCK_UN); + libc::fsync(self.fd); } } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
