Add Occlum.json. No more configs hardcoded in code
1. Add Occlum.json as Occlum's config file 2. Add tools/bin/build_enclave 3. Add tools/bin/protect_integrity 4. Validate Occlum.json.protected on LibOS startup 5. Parse Occlum.json.protected on LibOS startup 6. Config enclave size using Occlum.json 7. Config process memory sizes using Occlum.json
This commit is contained in:
parent
cff0de1c39
commit
76f91a1aa3
2
Makefile
2
Makefile
@ -5,7 +5,9 @@ all: src
|
|||||||
submodule:
|
submodule:
|
||||||
git submodule init
|
git submodule init
|
||||||
git submodule update
|
git submodule update
|
||||||
|
cd deps/rust-sgx-sdk && git apply ../rust-sgx-sdk.patch
|
||||||
cd deps/sefs/sefs-fuse && make
|
cd deps/sefs/sefs-fuse && make
|
||||||
|
cd tools/protect-integrity && make
|
||||||
|
|
||||||
src:
|
src:
|
||||||
@$(MAKE) --no-print-directory -C src
|
@$(MAKE) --no-print-directory -C src
|
||||||
|
387
deps/rust-sgx-sdk.patch
vendored
Normal file
387
deps/rust-sgx-sdk.patch
vendored
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
From 5a6f0000e5a5d644e547fcf8a7c9c87f89ae5935 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Liu Shuang <ls123674@antfin.com>
|
||||||
|
Date: Tue, 6 Aug 2019 06:59:49 +0000
|
||||||
|
Subject: [PATCH] Add support for integrity-only SGX protected files
|
||||||
|
|
||||||
|
1. Add SgxFile::open_integrity_only API
|
||||||
|
1. Add SgxFile::create_integrity_only API
|
||||||
|
2. Add the unit test for integrity-only SgxFile
|
||||||
|
---
|
||||||
|
samplecode/unit-test/enclave/src/lib.rs | 2 +
|
||||||
|
samplecode/unit-test/enclave/src/test_file.rs | 41 +++++++++++++
|
||||||
|
sgx_tprotected_fs/src/fs.rs | 86 +++++++++++++++++++++++++++
|
||||||
|
sgx_tstd/src/sgxfs.rs | 39 +++++++++++-
|
||||||
|
sgx_tstd/src/sys/sgxfs.rs | 40 +++++++++++--
|
||||||
|
sgx_types/src/function.rs | 4 ++
|
||||||
|
6 files changed, 205 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/samplecode/unit-test/enclave/src/lib.rs b/samplecode/unit-test/enclave/src/lib.rs
|
||||||
|
index e368e26..45579da 100644
|
||||||
|
--- a/samplecode/unit-test/enclave/src/lib.rs
|
||||||
|
+++ b/samplecode/unit-test/enclave/src/lib.rs
|
||||||
|
@@ -148,6 +148,8 @@ fn test_main_entrance() -> sgx_status_t {
|
||||||
|
test_serialize_enum,
|
||||||
|
// std::sgxfs
|
||||||
|
test_sgxfs,
|
||||||
|
+ // std::sgxfs in integrity-only mode
|
||||||
|
+ test_sgxfs_integrity_only,
|
||||||
|
// std::fs
|
||||||
|
test_fs,
|
||||||
|
// std::fs untrusted mode
|
||||||
|
diff --git a/samplecode/unit-test/enclave/src/test_file.rs b/samplecode/unit-test/enclave/src/test_file.rs
|
||||||
|
index e9a85a7..0dbc805 100644
|
||||||
|
--- a/samplecode/unit-test/enclave/src/test_file.rs
|
||||||
|
+++ b/samplecode/unit-test/enclave/src/test_file.rs
|
||||||
|
@@ -138,3 +138,44 @@ pub fn test_fs_untrusted_fs_feature_enabled() {
|
||||||
|
assert!(f.is_ok());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+pub fn test_sgxfs_integrity_only() {
|
||||||
|
+ let write_data = {
|
||||||
|
+ let read_result = std::fs::read_to_string("../Makefile");
|
||||||
|
+ assert!(read_result.is_ok());
|
||||||
|
+ read_result.unwrap()
|
||||||
|
+ };
|
||||||
|
+ let path = "sgx_file_integrity_only.data";
|
||||||
|
+ let mut new_file = {
|
||||||
|
+ let create_result = SgxFile::create_integrity_only(path);
|
||||||
|
+ assert!(create_result.is_ok());
|
||||||
|
+ create_result.unwrap()
|
||||||
|
+ };
|
||||||
|
+ let _ = new_file.write_all(&write_data.as_bytes());
|
||||||
|
+ let write_mac = {
|
||||||
|
+ let mac_result = new_file.get_mac();
|
||||||
|
+ assert!(mac_result.is_ok());
|
||||||
|
+ mac_result.unwrap()
|
||||||
|
+ };
|
||||||
|
+ drop(new_file);
|
||||||
|
+
|
||||||
|
+ let mut read_data = String::new();
|
||||||
|
+ let mut open_file = {
|
||||||
|
+ let open_result = SgxFile::open_integrity_only(path);
|
||||||
|
+ assert!(open_result.is_ok());
|
||||||
|
+ open_result.unwrap()
|
||||||
|
+ };
|
||||||
|
+ let _ = open_file.read_to_string(&mut read_data);
|
||||||
|
+ let read_mac = {
|
||||||
|
+ let mac_result = open_file.get_mac();
|
||||||
|
+ assert!(mac_result.is_ok());
|
||||||
|
+ mac_result.unwrap()
|
||||||
|
+ };
|
||||||
|
+ drop(open_file);
|
||||||
|
+
|
||||||
|
+ assert_eq!(&write_data[..], &read_data[..]);
|
||||||
|
+ assert_eq!(&write_mac, &read_mac);
|
||||||
|
+
|
||||||
|
+ let remove_result = remove_file(path);
|
||||||
|
+ assert!(remove_result.is_ok());
|
||||||
|
+}
|
||||||
|
diff --git a/sgx_tprotected_fs/src/fs.rs b/sgx_tprotected_fs/src/fs.rs
|
||||||
|
index d1e438c..b9e508f 100644
|
||||||
|
--- a/sgx_tprotected_fs/src/fs.rs
|
||||||
|
+++ b/sgx_tprotected_fs/src/fs.rs
|
||||||
|
@@ -47,6 +47,16 @@ unsafe fn rsgx_fopen(filename: &CStr, mode: &CStr, key: &sgx_key_128bit_t) -> Sy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+unsafe fn rsgx_fopen_integrity_only(filename: &CStr, mode: &CStr) -> SysResult<SGX_FILE> {
|
||||||
|
+
|
||||||
|
+ let file = sgx_fopen_integrity_only(filename.as_ptr(), mode.as_ptr());
|
||||||
|
+ if file.is_null() {
|
||||||
|
+ Err(errno())
|
||||||
|
+ } else {
|
||||||
|
+ Ok(file)
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
unsafe fn rsgx_fopen_auto_key(filename: &CStr, mode: &CStr) -> SysResult<SGX_FILE> {
|
||||||
|
|
||||||
|
let file = sgx_fopen_auto_key(filename.as_ptr(), mode.as_ptr());
|
||||||
|
@@ -218,6 +228,16 @@ unsafe fn rsgx_fimport_auto_key(filename: &CStr, key: &sgx_key_128bit_t) -> SysE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+unsafe fn rsgx_fget_mac(stream: SGX_FILE, mac: &mut sgx_aes_gcm_128bit_tag_t) -> SysError {
|
||||||
|
+
|
||||||
|
+ let ret = sgx_fget_mac(stream, mac as * mut sgx_aes_gcm_128bit_tag_t);
|
||||||
|
+ if ret == 0 {
|
||||||
|
+ Ok(())
|
||||||
|
+ } else {
|
||||||
|
+ Err(errno())
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
pub struct SgxFileStream {
|
||||||
|
stream: SGX_FILE
|
||||||
|
}
|
||||||
|
@@ -303,6 +323,48 @@ impl SgxFileStream {
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
+ /// The open function creates or opens a protected file in the integrity-only mode.
|
||||||
|
+ ///
|
||||||
|
+ /// # Description
|
||||||
|
+ ///
|
||||||
|
+ /// open_integrity_only is different from open and open_auto_key.
|
||||||
|
+ /// The protected file opened by this function is in integrity-only mode.
|
||||||
|
+ /// In this mode, the content of the file is not encrypted, only MACed.
|
||||||
|
+ ///
|
||||||
|
+ /// A protected file created by open_integrity_only cannot later be openned
|
||||||
|
+ /// by open or open_auto_key and vice versa.
|
||||||
|
+ ///
|
||||||
|
+ /// # Parameters
|
||||||
|
+ ///
|
||||||
|
+ /// **filename**
|
||||||
|
+ ///
|
||||||
|
+ /// The name of the file to be created or opened.
|
||||||
|
+ ///
|
||||||
|
+ /// **mode**
|
||||||
|
+ ///
|
||||||
|
+ /// The file open mode string. Allowed values are any combination of ‘r’, ‘w’ or ‘a’, with possible ‘+’
|
||||||
|
+ /// and possible ‘b’ (since string functions are currently not sup- ported, ‘b’ is meaningless).
|
||||||
|
+ ///
|
||||||
|
+ /// # Requirements
|
||||||
|
+ ///
|
||||||
|
+ /// Header: sgx_tprotected_fs.edl
|
||||||
|
+ ///
|
||||||
|
+ /// Library: libsgx_tprotected_fs.a
|
||||||
|
+ ///
|
||||||
|
+ /// This API is provided by Occlum's fork of Intel SGX SDK.
|
||||||
|
+ ///
|
||||||
|
+ /// # Return value
|
||||||
|
+ ///
|
||||||
|
+ /// If the function succeeds, it returns a valid file pointer, which can be used by all the other functions
|
||||||
|
+ /// in the Protected FS API, otherwise, error code is returned.
|
||||||
|
+ ///
|
||||||
|
+ pub fn open_integrity_only(filename: &CStr, mode: &CStr) -> SysResult<SgxFileStream> {
|
||||||
|
+ unsafe {
|
||||||
|
+ rsgx_fopen_integrity_only(filename, mode).map(|f| SgxFileStream{ stream: f})
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ///
|
||||||
|
/// The read function reads the requested amount of data from the file, and extends the file pointer by that amount.
|
||||||
|
///
|
||||||
|
/// # Description
|
||||||
|
@@ -542,6 +604,30 @@ impl SgxFileStream {
|
||||||
|
pub fn clear_cache(&self) -> SysError {
|
||||||
|
unsafe { rsgx_fclear_cache(self.stream) }
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ ///
|
||||||
|
+ /// The get_mac function returns the MAC of the protected file.
|
||||||
|
+ ///
|
||||||
|
+ /// # Description
|
||||||
|
+ ///
|
||||||
|
+ /// # Requirements
|
||||||
|
+ ///
|
||||||
|
+ /// Header: sgx_tprotected_fs.edl
|
||||||
|
+ ///
|
||||||
|
+ /// Library: libsgx_tprotected_fs.a
|
||||||
|
+ ///
|
||||||
|
+ /// This API is provided by Occlum's fork of Intel SGX SDK.
|
||||||
|
+ ///
|
||||||
|
+ /// # Return value
|
||||||
|
+ ///
|
||||||
|
+ /// If the function succeeded, the MAC is returned.
|
||||||
|
+ /// If the function failed, error code is returned.
|
||||||
|
+ ///
|
||||||
|
+ pub fn get_mac(&self) -> SysResult<sgx_aes_gcm_128bit_tag_t> {
|
||||||
|
+ let mut mac : sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||||
|
+ unsafe { rsgx_fget_mac(self.stream, &mut mac)?; }
|
||||||
|
+ Ok(mac)
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
diff --git a/sgx_tstd/src/sgxfs.rs b/sgx_tstd/src/sgxfs.rs
|
||||||
|
index b03d174..1b2ce52 100644
|
||||||
|
--- a/sgx_tstd/src/sgxfs.rs
|
||||||
|
+++ b/sgx_tstd/src/sgxfs.rs
|
||||||
|
@@ -28,7 +28,7 @@
|
||||||
|
|
||||||
|
//! Filesystem manipulation operations.
|
||||||
|
|
||||||
|
-use sgx_types::sgx_key_128bit_t;
|
||||||
|
+use sgx_types::{sgx_key_128bit_t, sgx_aes_gcm_128bit_tag_t};
|
||||||
|
use io::{self, SeekFrom, Seek, Read, Initializer, Write};
|
||||||
|
use path::Path;
|
||||||
|
use sys::sgxfs as fs_imp;
|
||||||
|
@@ -120,6 +120,19 @@ impl SgxFile {
|
||||||
|
OpenOptions::new().read(true).open(path.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /// Attempts to open a file in read-only and integrity-only mode.
|
||||||
|
+ ///
|
||||||
|
+ /// See the [`OpenOptions::open`] method for more details.
|
||||||
|
+ ///
|
||||||
|
+ /// # Errors
|
||||||
|
+ ///
|
||||||
|
+ /// This function will return an error if `path` does not already exist.
|
||||||
|
+ /// Other errors may also be returned according to [`OpenOptions::open`].
|
||||||
|
+ ///
|
||||||
|
+ pub fn open_integrity_only<P: AsRef<Path>>(path: P) -> io::Result<SgxFile> {
|
||||||
|
+ OpenOptions::new().read(true).open_integrity_only(path.as_ref())
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/// Opens a file in write-only mode.
|
||||||
|
///
|
||||||
|
/// This function will create a file if it does not exist,
|
||||||
|
@@ -129,6 +142,15 @@ impl SgxFile {
|
||||||
|
OpenOptions::new().write(true).open(path.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /// Opens a file in write-only and integrity-only mode.
|
||||||
|
+ ///
|
||||||
|
+ /// This function will create a file if it does not exist,
|
||||||
|
+ /// and will truncate it if it does.
|
||||||
|
+ ///
|
||||||
|
+ pub fn create_integrity_only<P: AsRef<Path>>(path: P) -> io::Result<SgxFile> {
|
||||||
|
+ OpenOptions::new().write(true).open_integrity_only(path.as_ref())
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
pub fn open_ex<P: AsRef<Path>>(path: P, key: &sgx_key_128bit_t) -> io::Result<SgxFile> {
|
||||||
|
OpenOptions::new().read(true).open_ex(path.as_ref(), key)
|
||||||
|
}
|
||||||
|
@@ -148,6 +170,12 @@ impl SgxFile {
|
||||||
|
pub fn clear_cache(&self) -> io::Result<()> {
|
||||||
|
self.inner.clear_cache()
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ /// Gets the MAC of the SGX protected file
|
||||||
|
+ ///
|
||||||
|
+ pub fn get_mac(&self) -> io::Result<sgx_aes_gcm_128bit_tag_t> {
|
||||||
|
+ self.inner.get_mac()
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInner<fs_imp::SgxFile> for SgxFile {
|
||||||
|
@@ -284,6 +312,10 @@ impl OpenOptions {
|
||||||
|
self._open_ex(path.as_ref(), key)
|
||||||
|
}
|
||||||
|
|
||||||
|
+ pub fn open_integrity_only<P: AsRef<Path>>(&self, path: P) -> io::Result<SgxFile> {
|
||||||
|
+ self._open_integrity_only(path.as_ref())
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
fn _open(&self, path: &Path) -> io::Result<SgxFile> {
|
||||||
|
let inner = fs_imp::SgxFile::open(path, &self.0)?;
|
||||||
|
Ok(SgxFile { inner: inner })
|
||||||
|
@@ -293,6 +325,11 @@ impl OpenOptions {
|
||||||
|
let inner = fs_imp::SgxFile::open_ex(path, &self.0, key)?;
|
||||||
|
Ok(SgxFile { inner: inner })
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ fn _open_integrity_only(&self, path: &Path) -> io::Result<SgxFile> {
|
||||||
|
+ let inner = fs_imp::SgxFile::open_integrity_only(path, &self.0)?;
|
||||||
|
+ Ok(SgxFile { inner: inner })
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
|
||||||
|
diff --git a/sgx_tstd/src/sys/sgxfs.rs b/sgx_tstd/src/sys/sgxfs.rs
|
||||||
|
index a32814d..ebc3627 100644
|
||||||
|
--- a/sgx_tstd/src/sys/sgxfs.rs
|
||||||
|
+++ b/sgx_tstd/src/sys/sgxfs.rs
|
||||||
|
@@ -26,7 +26,7 @@
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
-use sgx_types::{sgx_status_t, sgx_key_128bit_t};
|
||||||
|
+use sgx_types::{sgx_status_t, sgx_key_128bit_t, sgx_aes_gcm_128bit_tag_t};
|
||||||
|
use sgx_trts::libc;
|
||||||
|
use sgx_tprotected_fs::{self, SgxFileStream};
|
||||||
|
use os::unix::prelude::*;
|
||||||
|
@@ -87,7 +87,7 @@ impl SgxFile {
|
||||||
|
let path = cstr(path)?;
|
||||||
|
let mode = opts.get_access_mode()?;
|
||||||
|
let opts = CString::new(mode.as_bytes())?;
|
||||||
|
- SgxFile::open_c(&path, &opts, &sgx_key_128bit_t::default(), true)
|
||||||
|
+ SgxFile::open_c(&path, &opts, &sgx_key_128bit_t::default(), true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn open_ex(path: &Path, opts: &OpenOptions, key: &sgx_key_128bit_t) -> io::Result<SgxFile> {
|
||||||
|
@@ -95,12 +95,23 @@ impl SgxFile {
|
||||||
|
let path = cstr(path)?;
|
||||||
|
let mode = opts.get_access_mode()?;
|
||||||
|
let opts = CString::new(mode.as_bytes())?;
|
||||||
|
- SgxFile::open_c(&path, &opts, key, false)
|
||||||
|
+ SgxFile::open_c(&path, &opts, key, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
- pub fn open_c(path: &CStr, opts: &CStr, key: &sgx_key_128bit_t, auto: bool) -> io::Result<SgxFile> {
|
||||||
|
+ pub fn open_integrity_only(path: &Path, opts: &OpenOptions) -> io::Result<SgxFile> {
|
||||||
|
|
||||||
|
- let file = if auto == true {
|
||||||
|
+ let path = cstr(path)?;
|
||||||
|
+ let mode = opts.get_access_mode()?;
|
||||||
|
+ let opts = CString::new(mode.as_bytes())?;
|
||||||
|
+ SgxFile::open_c(&path, &opts, &sgx_key_128bit_t::default(), false, true)
|
||||||
|
+
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ pub fn open_c(path: &CStr, opts: &CStr, key: &sgx_key_128bit_t, auto: bool, integrity_only: bool) -> io::Result<SgxFile> {
|
||||||
|
+
|
||||||
|
+ let file = if integrity_only == true {
|
||||||
|
+ SgxFileStream::open_integrity_only(path, opts)
|
||||||
|
+ } else if auto == true {
|
||||||
|
SgxFileStream::open_auto_key(path, opts)
|
||||||
|
} else {
|
||||||
|
SgxFileStream::open(path, opts, key)
|
||||||
|
@@ -233,6 +244,23 @@ impl SgxFile {
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ pub fn get_mac(&self) -> io::Result<sgx_aes_gcm_128bit_tag_t> {
|
||||||
|
+
|
||||||
|
+ self.0.get_mac().map_err(|err| {
|
||||||
|
+ match err {
|
||||||
|
+ 1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
|
||||||
|
+ 2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
|
||||||
|
+ 3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
|
||||||
|
+ 4 | 5 => Error::from_raw_os_error(err),
|
||||||
|
+ r if r > 4096 => {
|
||||||
|
+ let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
|
||||||
|
+ Error::from_sgx_error(status)
|
||||||
|
+ },
|
||||||
|
+ _ => Error::from_raw_os_error(err),
|
||||||
|
+ }
|
||||||
|
+ })
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove(path: &Path) -> io::Result<()> {
|
||||||
|
@@ -324,4 +352,4 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||||
|
let ret = io::copy(&mut reader, &mut writer)?;
|
||||||
|
fs::set_permissions(to, perm)?;
|
||||||
|
Ok(ret)
|
||||||
|
-}
|
||||||
|
\ No newline at end of file
|
||||||
|
+}
|
||||||
|
diff --git a/sgx_types/src/function.rs b/sgx_types/src/function.rs
|
||||||
|
index 91869f7..fdd8a04 100644
|
||||||
|
--- a/sgx_types/src/function.rs
|
||||||
|
+++ b/sgx_types/src/function.rs
|
||||||
|
@@ -551,6 +551,8 @@ extern {
|
||||||
|
|
||||||
|
pub fn sgx_fopen_auto_key(filename: * const ::c_char, mode: * const ::c_char) -> SGX_FILE;
|
||||||
|
|
||||||
|
+ pub fn sgx_fopen_integrity_only(filename: * const ::c_char, mode: * const ::c_char) -> SGX_FILE;
|
||||||
|
+
|
||||||
|
pub fn sgx_fwrite(ptr: * const ::c_void,
|
||||||
|
size: ::size_t,
|
||||||
|
count: ::size_t,
|
||||||
|
@@ -582,6 +584,8 @@ extern {
|
||||||
|
pub fn sgx_fimport_auto_key(filename: * const ::c_char, key: * const sgx_key_128bit_t) -> ::int32_t;
|
||||||
|
|
||||||
|
pub fn sgx_fclear_cache(stream: SGX_FILE) -> ::int32_t;
|
||||||
|
+
|
||||||
|
+ pub fn sgx_fget_mac(stream: SGX_FILE, mac: * mut sgx_aes_gcm_128bit_tag_t) -> ::int32_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* intel sgx sdk 2.0 */
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
42
src/libos/Cargo.lock
generated
42
src/libos/Cargo.lock
generated
@ -12,6 +12,8 @@ dependencies = [
|
|||||||
"rcore-fs-mountfs 0.1.0",
|
"rcore-fs-mountfs 0.1.0",
|
||||||
"rcore-fs-ramfs 0.1.0",
|
"rcore-fs-ramfs 0.1.0",
|
||||||
"rcore-fs-sefs 0.1.0",
|
"rcore-fs-sefs 0.1.0",
|
||||||
|
"serde 1.0.84",
|
||||||
|
"serde_json 1.0.36",
|
||||||
"sgx_trts 1.0.6",
|
"sgx_trts 1.0.6",
|
||||||
"sgx_tstd 1.0.6",
|
"sgx_tstd 1.0.6",
|
||||||
"sgx_types 1.0.6",
|
"sgx_types 1.0.6",
|
||||||
@ -98,6 +100,13 @@ name = "ident_case"
|
|||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "0.4.1"
|
||||||
|
dependencies = [
|
||||||
|
"sgx_tstd 1.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@ -167,6 +176,38 @@ dependencies = [
|
|||||||
"static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "0.2.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.84"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive 1.0.84",
|
||||||
|
"sgx_tstd 1.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.84"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.36"
|
||||||
|
dependencies = [
|
||||||
|
"itoa 0.4.1",
|
||||||
|
"ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"serde 1.0.84",
|
||||||
|
"sgx_tstd 1.0.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sgx_alloc"
|
name = "sgx_alloc"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
@ -287,6 +328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
||||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||||
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||||
|
"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
|
||||||
"checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4"
|
"checksum spin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "37b5646825922b96b5d7d676b5bb3458a54498e96ed7b0ce09dc43a07038fea4"
|
||||||
"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
|
"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55"
|
||||||
"checksum static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "389ce475f424f267dbed6479cbd8f126c5e1afb053b0acdaa019c74305fc65d1"
|
"checksum static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "389ce475f424f267dbed6479cbd8f126c5e1afb053b0acdaa019c74305fc65d1"
|
||||||
|
@ -15,6 +15,8 @@ rcore-fs = { path = "../../deps/sefs/rcore-fs" }
|
|||||||
rcore-fs-sefs = { path = "../../deps/sefs/rcore-fs-sefs" }
|
rcore-fs-sefs = { path = "../../deps/sefs/rcore-fs-sefs" }
|
||||||
rcore-fs-ramfs = { path = "../../deps/sefs/rcore-fs-ramfs" }
|
rcore-fs-ramfs = { path = "../../deps/sefs/rcore-fs-ramfs" }
|
||||||
rcore-fs-mountfs = { path = "../../deps/sefs/rcore-fs-mountfs" }
|
rcore-fs-mountfs = { path = "../../deps/sefs/rcore-fs-mountfs" }
|
||||||
|
serde = { path = "../../deps/rust-sgx-sdk/third_party/serde-rs/serde/serde", features = ["derive"] }
|
||||||
|
serde_json = { path = "../../deps/rust-sgx-sdk/third_party/serde-rs/json" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["integrity_only_opt", "sgx_file_cache"]
|
default = ["integrity_only_opt", "sgx_file_cache"]
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
include ../sgxenv.mk
|
include ../sgxenv.mk
|
||||||
|
|
||||||
DEBUG=1
|
DEBUG := 1
|
||||||
|
|
||||||
LIBOS_ENCLAVE := libocclum.signed.so
|
|
||||||
LIBOS_SO := libocclum.so # Link $(LIBOS_A), $(C_OBJS) and all dependencies
|
LIBOS_SO := libocclum.so # Link $(LIBOS_A), $(C_OBJS) and all dependencies
|
||||||
LIBOS_A := libocclum_rs.a # Built from Rust code
|
LIBOS_A := libocclum_rs.a # Built from Rust code
|
||||||
|
|
||||||
@ -17,17 +16,25 @@ ENCLAVE_CONFIG := Enclave_config.xml
|
|||||||
ENCLAVE_KEY := Enclave_private.pem
|
ENCLAVE_KEY := Enclave_private.pem
|
||||||
|
|
||||||
C_FLAGS := $(SGX_CFLAGS_T) -fno-stack-protector -I./include/
|
C_FLAGS := $(SGX_CFLAGS_T) -fno-stack-protector -I./include/
|
||||||
|
|
||||||
|
# Pass builtin values by defining macros
|
||||||
|
#
|
||||||
|
# The MAC of Occlum config file must be builtin into the binary
|
||||||
|
ifdef OCCLUM_BUILTIN_CONF_FILE_MAC
|
||||||
|
C_FLAGS += -DOCCLUM_BUILTIN_CONF_FILE_MAC='"$(OCCLUM_BUILTIN_CONF_FILE_MAC)"'
|
||||||
|
endif
|
||||||
|
# The total size of user-space memory must be builtin into the binary
|
||||||
|
ifdef OCCLUM_BUILTIN_VM_USER_SPACE_SIZE
|
||||||
|
C_FLAGS += -DOCCLUM_BUILTIN_VM_USER_SPACE_SIZE='($(OCCLUM_BUILTIN_VM_USER_SPACE_SIZE))'
|
||||||
|
endif
|
||||||
|
|
||||||
_Other_Link_Flags := -L$(RUST_SGX_SDK_DIR)/compiler-rt/ -L.
|
_Other_Link_Flags := -L$(RUST_SGX_SDK_DIR)/compiler-rt/ -L.
|
||||||
_Other_Enclave_Libs := -lcompiler-rt-patch -locclum_rs -lsgx_tprotected_fs
|
_Other_Enclave_Libs := -lcompiler-rt-patch -locclum_rs -lsgx_tprotected_fs
|
||||||
LINK_FLAGS := $(SGX_LFLAGS_T)
|
LINK_FLAGS := $(SGX_LFLAGS_T)
|
||||||
|
|
||||||
.PHONY: all compiler-rt clean
|
.PHONY: all compiler-rt clean
|
||||||
|
|
||||||
all: $(LIBOS_ENCLAVE)
|
all: $(LIBOS_SO)
|
||||||
|
|
||||||
$(LIBOS_ENCLAVE): $(LIBOS_SO)
|
|
||||||
@$(SGX_ENCLAVE_SIGNER) sign -key $(ENCLAVE_KEY) -enclave $^ -out $@ -config $(ENCLAVE_CONFIG)
|
|
||||||
@echo "SIGN => $@"
|
|
||||||
|
|
||||||
$(LIBOS_SO): compiler-rt $(LIBOS_A) $(C_OBJS) $(S_OBJS)
|
$(LIBOS_SO): compiler-rt $(LIBOS_A) $(C_OBJS) $(S_OBJS)
|
||||||
@$(CC) $(C_OBJS) $(S_OBJS) -o $@ $(LINK_FLAGS)
|
@$(CC) $(C_OBJS) $(S_OBJS) -o $@ $(LINK_FLAGS)
|
||||||
@ -60,6 +67,9 @@ $(LIBOS_A): $(RUST_SRCS)
|
|||||||
@echo "CARGO (release) => $(LIBOS_A)"
|
@echo "CARGO (release) => $(LIBOS_A)"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
clean-builtin:
|
||||||
|
@-$(RM) src/builtin/*.o
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@cargo clean
|
@cargo clean
|
||||||
@-$(RM) $(LIBOS_ENCLAVE) $(LIBOS_SO) $(LIBOS_A) $(C_OBJS) $(S_OBJS) $(EDL_C_SRCS)
|
@-$(RM) $(LIBOS_SO) $(LIBOS_A) $(C_OBJS) $(S_OBJS) $(EDL_C_SRCS)
|
||||||
|
14
src/libos/src/builtin/conf_get_hardcoded_file_mac.c
Normal file
14
src/libos/src/builtin/conf_get_hardcoded_file_mac.c
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// The 128-bit MAC of Occlum.json
|
||||||
|
// Should be provided by Makefile; Set it to all zeros by default.
|
||||||
|
#ifndef OCCLUM_BUILTIN_CONF_FILE_MAC
|
||||||
|
#define ALL_ZEROS_32BIT "00-00-00-00"
|
||||||
|
#define ALL_ZEROS_128BIT (ALL_ZEROS_32BIT"-"ALL_ZEROS_32BIT"-"\
|
||||||
|
ALL_ZEROS_32BIT"-"ALL_ZEROS_32BIT)
|
||||||
|
#define OCCLUM_BUILTIN_CONF_FILE_MAC ALL_ZEROS_128BIT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* conf_get_hardcoded_file_mac(void) {
|
||||||
|
return OCCLUM_BUILTIN_CONF_FILE_MAC;
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
// The total size of the memory available to user programs
|
||||||
|
// Should be provided by Makefile
|
||||||
|
#ifndef OCCLUM_BUILTIN_VM_USER_SPACE_SIZE
|
||||||
|
#define OCCLUM_BUILTIN_VM_USER_SPACE_SIZE (128*1024*1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char __preallocated_memory[OCCLUM_BUILTIN_VM_USER_SPACE_SIZE]
|
||||||
|
__attribute__ ((
|
||||||
|
section(".exectuable_data,\"awx\",@nobits#"),
|
||||||
|
aligned(4096))) = {0};
|
||||||
|
|
||||||
|
void vm_get_preallocated_user_space_memory(void** paddr, size_t* psize) {
|
||||||
|
*paddr = __preallocated_memory;
|
||||||
|
*psize = sizeof(__preallocated_memory);
|
||||||
|
}
|
307
src/libos/src/config.rs
Normal file
307
src/libos/src/config.rs
Normal file
@ -0,0 +1,307 @@
|
|||||||
|
use super::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::sgxfs::{SgxFile};
|
||||||
|
|
||||||
|
const LIBOS_CONFIG_PATH : &str = "Occlum.json.protected";
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref LIBOS_CONFIG: Config = {
|
||||||
|
let mut config_file = {
|
||||||
|
let config_file = match SgxFile::open_integrity_only(LIBOS_CONFIG_PATH) {
|
||||||
|
Err(_) => panic!("Failed to find or open Occlum's config file: {}",
|
||||||
|
LIBOS_CONFIG_PATH),
|
||||||
|
Ok(file) => file,
|
||||||
|
};
|
||||||
|
|
||||||
|
let actual_mac = match config_file.get_mac() {
|
||||||
|
Err(_) => panic!("Failed to get the MAC of Occlum's config file: {}",
|
||||||
|
LIBOS_CONFIG_PATH),
|
||||||
|
Ok(mac) => mac,
|
||||||
|
};
|
||||||
|
let expected_mac = conf_get_hardcoded_file_mac();
|
||||||
|
if actual_mac != expected_mac {
|
||||||
|
panic!("The MAC of Occlum's config file is not as expected: {}",
|
||||||
|
LIBOS_CONFIG_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
config_file
|
||||||
|
};
|
||||||
|
let config_json = {
|
||||||
|
let mut config_json = String::new();
|
||||||
|
config_file.read_to_string(&mut config_json)
|
||||||
|
.map_err(|_| {
|
||||||
|
panic!("Failed to read from Occlum's config file: {}",
|
||||||
|
LIBOS_CONFIG_PATH);
|
||||||
|
});
|
||||||
|
config_json
|
||||||
|
};
|
||||||
|
let config_input: InputConfig = match serde_json::from_str(&config_json) {
|
||||||
|
Err(_) => panic!("Failed to parse JSON from Occlum's config file: {}",
|
||||||
|
LIBOS_CONFIG_PATH),
|
||||||
|
Ok(config_input) => config_input
|
||||||
|
};
|
||||||
|
let config = match Config::from_input(&config_input) {
|
||||||
|
Err(_) => panic!("Found invalid config in Occlum's config file: {}",
|
||||||
|
LIBOS_CONFIG_PATH),
|
||||||
|
Ok(config) => config
|
||||||
|
};
|
||||||
|
config
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn conf_get_hardcoded_file_mac() -> sgx_aes_gcm_128bit_tag_t {
|
||||||
|
// Wrap the unsafe C version to get the safe Rust version
|
||||||
|
extern "C" {
|
||||||
|
fn conf_get_hardcoded_file_mac() -> *const c_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mac_str = unsafe {
|
||||||
|
CStr::from_ptr(conf_get_hardcoded_file_mac())
|
||||||
|
.to_str()
|
||||||
|
.expect("Invalid MAC")
|
||||||
|
};
|
||||||
|
let mac = parse_mac(mac_str)
|
||||||
|
.expect("Invalid MAC");
|
||||||
|
mac
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_mac(mac_str: &str) -> Result<sgx_aes_gcm_128bit_tag_t, Error> {
|
||||||
|
let bytes_str_vec = {
|
||||||
|
let bytes_str_vec : Vec<&str> = mac_str.split("-").collect();
|
||||||
|
if bytes_str_vec.len() != 16 {
|
||||||
|
return errno!(EINVAL, "The length or format of MAC string is invalid");
|
||||||
|
}
|
||||||
|
bytes_str_vec
|
||||||
|
};
|
||||||
|
let mut mac : sgx_aes_gcm_128bit_tag_t = Default::default();
|
||||||
|
for (byte_i, byte_str) in bytes_str_vec.iter().enumerate() {
|
||||||
|
mac[byte_i] = u8::from_str_radix(byte_str, 16)
|
||||||
|
.map_err(|_| Error::new(Errno::EINVAL, "The format of MAC string is invalid"))?;
|
||||||
|
}
|
||||||
|
Ok(mac)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Config {
|
||||||
|
pub vm: ConfigVM,
|
||||||
|
pub process: ConfigProcess,
|
||||||
|
pub mount: Vec<ConfigMount>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConfigVM {
|
||||||
|
pub user_space_size : usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConfigProcess {
|
||||||
|
pub default_stack_size: usize,
|
||||||
|
pub default_heap_size: usize,
|
||||||
|
pub default_mmap_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConfigMount {
|
||||||
|
pub type_: String,
|
||||||
|
pub target: String,
|
||||||
|
pub source: Option<String>,
|
||||||
|
pub options: ConfigMountOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ConfigMountOptions {
|
||||||
|
pub integrity_only: bool,
|
||||||
|
pub mac: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
fn from_input(input: &InputConfig) -> Result<Config, Error> {
|
||||||
|
let vm = ConfigVM::from_input(&input.vm)?;
|
||||||
|
let process = ConfigProcess::from_input(&input.process)?;
|
||||||
|
let mount = {
|
||||||
|
let mut mount = Vec::new();
|
||||||
|
for input_mount in &input.mount {
|
||||||
|
mount.push(ConfigMount::from_input(&input_mount)?);
|
||||||
|
}
|
||||||
|
mount
|
||||||
|
};
|
||||||
|
Ok(Config { vm, process, mount })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigVM {
|
||||||
|
fn from_input(input: &InputConfigVM) -> Result<ConfigVM, Error> {
|
||||||
|
let user_space_size = parse_memory_size(&input.user_space_size)?;
|
||||||
|
Ok(ConfigVM { user_space_size })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigProcess {
|
||||||
|
fn from_input(input: &InputConfigProcess) -> Result<ConfigProcess, Error> {
|
||||||
|
let default_stack_size = parse_memory_size(&input.default_stack_size)?;
|
||||||
|
let default_heap_size = parse_memory_size(&input.default_heap_size)?;
|
||||||
|
let default_mmap_size = parse_memory_size(&input.default_mmap_size)?;
|
||||||
|
Ok(ConfigProcess {
|
||||||
|
default_stack_size,
|
||||||
|
default_heap_size,
|
||||||
|
default_mmap_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigMount {
|
||||||
|
fn from_input(input: &InputConfigMount) -> Result<ConfigMount, Error> {
|
||||||
|
const ALL_FS_TYPES : [&str; 3] = [ "sefs", "hostfs", "ramfs" ];
|
||||||
|
|
||||||
|
let type_ = {
|
||||||
|
let type_ = input.type_.to_string();
|
||||||
|
if !ALL_FS_TYPES.contains(&type_.as_str()) {
|
||||||
|
return errno!(EINVAL, "Unsupported file system type");
|
||||||
|
}
|
||||||
|
type_
|
||||||
|
};
|
||||||
|
let target = {
|
||||||
|
let target = input.target.clone();
|
||||||
|
if !target.starts_with("/") {
|
||||||
|
return errno!(EINVAL, "Target must be an absolute path");
|
||||||
|
}
|
||||||
|
target
|
||||||
|
};
|
||||||
|
let source = input.source.clone();
|
||||||
|
let options = ConfigMountOptions::from_input(&input.options)?;
|
||||||
|
Ok(ConfigMount { type_, target, source, options, })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigMountOptions {
|
||||||
|
fn from_input(input: &InputConfigMountOptions) -> Result<ConfigMountOptions, Error> {
|
||||||
|
let (integrity_only, mac) =
|
||||||
|
if !input.integrity_only {
|
||||||
|
(false, None)
|
||||||
|
} else {
|
||||||
|
if input.mac.is_none() {
|
||||||
|
return errno!(EINVAL, "MAC is expected");
|
||||||
|
}
|
||||||
|
(true, input.mac.clone())
|
||||||
|
};
|
||||||
|
Ok(ConfigMountOptions { integrity_only, mac })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn parse_memory_size(mem_str: &str) -> Result<usize, Error> {
|
||||||
|
const UNIT2FACTOR : [(&str, usize); 5]= [
|
||||||
|
("KB", 1024),
|
||||||
|
("MB", 1024 * 1024),
|
||||||
|
("GB", 1024 * 1024 * 1024),
|
||||||
|
("TB", 1024 * 1024 * 1024 * 1024),
|
||||||
|
("B", 1),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mem_str = mem_str.trim();
|
||||||
|
let (unit, factor) = UNIT2FACTOR
|
||||||
|
.iter()
|
||||||
|
.position(|(unit, _)| mem_str.ends_with(unit))
|
||||||
|
.ok_or_else(|| Error::new(Errno::EINVAL, "No unit"))
|
||||||
|
.map(|unit_i| &UNIT2FACTOR[unit_i])?;
|
||||||
|
let number =
|
||||||
|
match mem_str[0..mem_str.len() - unit.len()]
|
||||||
|
.trim()
|
||||||
|
.parse::<usize>()
|
||||||
|
{
|
||||||
|
Err(_) => return errno!(EINVAL, "No number"),
|
||||||
|
Ok(number) => number
|
||||||
|
};
|
||||||
|
Ok(number * factor)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct InputConfig {
|
||||||
|
#[serde(default)]
|
||||||
|
pub vm: InputConfigVM,
|
||||||
|
#[serde(default)]
|
||||||
|
pub process: InputConfigProcess,
|
||||||
|
#[serde(default)]
|
||||||
|
pub mount: Vec<InputConfigMount>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct InputConfigVM {
|
||||||
|
#[serde(default = "InputConfigVM::get_user_space_size")]
|
||||||
|
pub user_space_size : String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputConfigVM {
|
||||||
|
fn get_user_space_size() -> String {
|
||||||
|
"128MB".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InputConfigVM {
|
||||||
|
fn default() -> InputConfigVM {
|
||||||
|
InputConfigVM {
|
||||||
|
user_space_size: InputConfigVM::get_user_space_size()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct InputConfigProcess {
|
||||||
|
#[serde(default = "InputConfigProcess::get_default_stack_size")]
|
||||||
|
pub default_stack_size: String,
|
||||||
|
#[serde(default = "InputConfigProcess::get_default_heap_size")]
|
||||||
|
pub default_heap_size: String,
|
||||||
|
#[serde(default = "InputConfigProcess::get_default_mmap_size")]
|
||||||
|
pub default_mmap_size: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputConfigProcess {
|
||||||
|
fn get_default_stack_size() -> String {
|
||||||
|
"8MB".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_default_heap_size() -> String {
|
||||||
|
"16MB".to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_default_mmap_size() -> String {
|
||||||
|
"32MB".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for InputConfigProcess {
|
||||||
|
fn default() -> InputConfigProcess {
|
||||||
|
InputConfigProcess {
|
||||||
|
default_stack_size: InputConfigProcess::get_default_stack_size(),
|
||||||
|
default_heap_size: InputConfigProcess::get_default_heap_size(),
|
||||||
|
default_mmap_size: InputConfigProcess::get_default_mmap_size(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct InputConfigMount {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub type_: String,
|
||||||
|
pub target: String,
|
||||||
|
pub source: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub options: InputConfigMountOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug, Default)]
|
||||||
|
#[serde(deny_unknown_fields)]
|
||||||
|
struct InputConfigMountOptions {
|
||||||
|
#[serde(default)]
|
||||||
|
pub integrity_only: bool,
|
||||||
|
#[serde(rename = "MAC")]
|
||||||
|
#[serde(default)]
|
||||||
|
pub mac: Option<String>,
|
||||||
|
}
|
@ -28,6 +28,8 @@ extern crate rcore_fs_ramfs;
|
|||||||
extern crate rcore_fs_mountfs;
|
extern crate rcore_fs_mountfs;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate derive_builder;
|
extern crate derive_builder;
|
||||||
|
extern crate serde;
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
use sgx_trts::libc;
|
use sgx_trts::libc;
|
||||||
use sgx_types::*;
|
use sgx_types::*;
|
||||||
@ -37,8 +39,9 @@ use std::panic;
|
|||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod prelude;
|
mod prelude;
|
||||||
mod entry;
|
|
||||||
mod errno;
|
mod errno;
|
||||||
|
mod entry;
|
||||||
|
mod config;
|
||||||
mod fs;
|
mod fs;
|
||||||
mod misc;
|
mod misc;
|
||||||
mod process;
|
mod process;
|
||||||
|
@ -21,7 +21,7 @@ pub use std::fmt::{Debug, Display};
|
|||||||
pub use std::io::{Read, Seek, SeekFrom, Write};
|
pub use std::io::{Read, Seek, SeekFrom, Write};
|
||||||
pub use std::iter::Iterator;
|
pub use std::iter::Iterator;
|
||||||
pub use std::rc::Rc;
|
pub use std::rc::Rc;
|
||||||
pub use std::string::String;
|
pub use std::string::{String, ToString};
|
||||||
pub use std::vec::Vec;
|
pub use std::vec::Vec;
|
||||||
|
|
||||||
pub use errno::Errno;
|
pub use errno::Errno;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use super::vm_manager::{VMRange, VMManager, VMMapOptionsBuilder, VMMapOptions, VMMapAddr, VMInitializer};
|
use super::vm_manager::{VMRange, VMManager, VMMapOptionsBuilder, VMMapOptions, VMMapAddr, VMInitializer};
|
||||||
use super::user_space_vm::{UserSpaceVMManager, UserSpaceVMRange, USER_SPACE_VM_MANAGER};
|
use super::user_space_vm::{UserSpaceVMManager, UserSpaceVMRange, USER_SPACE_VM_MANAGER};
|
||||||
|
use super::super::config;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
|
|
||||||
@ -25,10 +26,6 @@ macro_rules! impl_setter_for_process_vm_builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ProcessVMBuilder {
|
impl ProcessVMBuilder {
|
||||||
pub const DEFAULT_STACK_SIZE: usize = 1 * 1024 * 1024;
|
|
||||||
pub const DEFAULT_HEAP_SIZE: usize = 16 * 1024 * 1024;
|
|
||||||
pub const DEFAULT_MMAP_SIZE: usize = 16 * 1024 * 1024;
|
|
||||||
|
|
||||||
pub fn new(code_size: usize, data_size: usize) -> ProcessVMBuilder {
|
pub fn new(code_size: usize, data_size: usize) -> ProcessVMBuilder {
|
||||||
ProcessVMBuilder {
|
ProcessVMBuilder {
|
||||||
code_size,
|
code_size,
|
||||||
@ -50,9 +47,12 @@ impl ProcessVMBuilder {
|
|||||||
let data_size = self.data_size;
|
let data_size = self.data_size;
|
||||||
let ldso_code_size = self.ldso_code_size.unwrap_or(0);
|
let ldso_code_size = self.ldso_code_size.unwrap_or(0);
|
||||||
let ldso_data_size = self.ldso_data_size.unwrap_or(0);
|
let ldso_data_size = self.ldso_data_size.unwrap_or(0);
|
||||||
let heap_size = self.heap_size.unwrap_or(ProcessVMBuilder::DEFAULT_HEAP_SIZE);
|
let heap_size = self.heap_size.unwrap_or(
|
||||||
let stack_size = self.stack_size.unwrap_or(ProcessVMBuilder::DEFAULT_STACK_SIZE);
|
config::LIBOS_CONFIG.process.default_heap_size);
|
||||||
let mmap_size = self.mmap_size.unwrap_or(ProcessVMBuilder::DEFAULT_MMAP_SIZE);
|
let stack_size = self.stack_size.unwrap_or(
|
||||||
|
config::LIBOS_CONFIG.process.default_stack_size);
|
||||||
|
let mmap_size = self.mmap_size.unwrap_or(
|
||||||
|
config::LIBOS_CONFIG.process.default_mmap_size);
|
||||||
let range_sizes = vec![
|
let range_sizes = vec![
|
||||||
code_size, data_size,
|
code_size, data_size,
|
||||||
ldso_code_size, ldso_data_size,
|
ldso_code_size, ldso_data_size,
|
||||||
|
@ -41,7 +41,7 @@ lazy_static! {
|
|||||||
let (addr, size) = {
|
let (addr, size) = {
|
||||||
let mut addr: usize = 0;
|
let mut addr: usize = 0;
|
||||||
let mut size: usize = 0;
|
let mut size: usize = 0;
|
||||||
unsafe { vm_get_prealloced_data_space(&mut addr, &mut size) };
|
unsafe { vm_get_preallocated_user_space_memory(&mut addr, &mut size) };
|
||||||
(addr, size)
|
(addr, size)
|
||||||
};
|
};
|
||||||
let user_space_vm_manager = unsafe {
|
let user_space_vm_manager = unsafe {
|
||||||
@ -55,7 +55,7 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
pub fn vm_get_prealloced_data_space(addr: &mut usize, size: &mut usize);
|
pub fn vm_get_preallocated_user_space_memory(addr: &mut usize, size: &mut usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#define DATA_SPACE_SIZE (128*1024*1024)
|
|
||||||
|
|
||||||
static char __prealloced_data_space[DATA_SPACE_SIZE]
|
|
||||||
__attribute__ ((
|
|
||||||
section(".exectuable_data,\"awx\",@nobits#"),
|
|
||||||
aligned(4096))) = {0};
|
|
||||||
|
|
||||||
void vm_get_prealloced_data_space(void** paddr, size_t* psize) {
|
|
||||||
*paddr = __prealloced_data_space;
|
|
||||||
*psize = DATA_SPACE_SIZE;
|
|
||||||
}
|
|
@ -36,7 +36,7 @@ SEFS_PATH := sefs
|
|||||||
|
|
||||||
all: build
|
all: build
|
||||||
|
|
||||||
build: $(BUILD_TARGETS) sefs
|
build: $(BUILD_TARGETS) sefs libocclum.signed.so
|
||||||
|
|
||||||
$(BUILD_TARGETS): %:
|
$(BUILD_TARGETS): %:
|
||||||
@$(ECHO) "$(CYAN)BUILD TEST => $@$(NO_COLOR)"
|
@$(ECHO) "$(CYAN)BUILD TEST => $@$(NO_COLOR)"
|
||||||
@ -57,6 +57,9 @@ sefs:
|
|||||||
zip
|
zip
|
||||||
@echo "SEFS => $@"
|
@echo "SEFS => $@"
|
||||||
|
|
||||||
|
libocclum.signed.so: Occlum.json Enclave_config.xml Enclave_private.pem
|
||||||
|
@$(PROJECT_DIR)/tools/bin/build-enclave Occlum.json Enclave_config.xml Enclave_private.pem
|
||||||
|
|
||||||
#############################################################################
|
#############################################################################
|
||||||
# Test targets
|
# Test targets
|
||||||
#############################################################################
|
#############################################################################
|
||||||
@ -66,9 +69,6 @@ test: build $(TEST_TARGETS)
|
|||||||
pal: $(PROJECT_DIR)/src/pal/pal
|
pal: $(PROJECT_DIR)/src/pal/pal
|
||||||
@cp $< pal
|
@cp $< pal
|
||||||
|
|
||||||
libocclum.signed.so: $(PROJECT_DIR)/src/libos/libocclum.signed.so
|
|
||||||
@cp $< libocclum.signed.so
|
|
||||||
|
|
||||||
$(TEST_TARGETS): test-%: % pal libocclum.signed.so
|
$(TEST_TARGETS): test-%: % pal libocclum.signed.so
|
||||||
@$(ECHO) "$(CYAN)RUN TEST => $<$(NO_COLOR)"
|
@$(ECHO) "$(CYAN)RUN TEST => $<$(NO_COLOR)"
|
||||||
@$(MAKE) --no-print-directory -C $< test ; \
|
@$(MAKE) --no-print-directory -C $< test ; \
|
||||||
@ -98,7 +98,7 @@ $(BENCH_TARGETS): bench-%: % pal libocclum.signed.so
|
|||||||
#############################################################################
|
#############################################################################
|
||||||
|
|
||||||
clean: $(CLEAN_TARGETS)
|
clean: $(CLEAN_TARGETS)
|
||||||
@$(RM) -f pal libocclum.signed.so
|
@$(RM) -f pal libocclum.signed.so Occlum.json.protected
|
||||||
@$(RM) -rf $(FS_PATH) $(SEFS_PATH)
|
@$(RM) -rf $(FS_PATH) $(SEFS_PATH)
|
||||||
|
|
||||||
$(CLEAN_TARGETS): clean-%:
|
$(CLEAN_TARGETS): clean-%:
|
||||||
|
35
test/Occlum.json
Normal file
35
test/Occlum.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"vm": {
|
||||||
|
"user_space_size": "128MB"
|
||||||
|
},
|
||||||
|
"process": {
|
||||||
|
"default_stack_size": "4MB",
|
||||||
|
"default_heap_size": "16MB",
|
||||||
|
"default_mmap_size": "32MB"
|
||||||
|
},
|
||||||
|
"mount": [
|
||||||
|
{
|
||||||
|
"target": "/",
|
||||||
|
"type": "sefs",
|
||||||
|
"source": "./root_sefs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "/bin",
|
||||||
|
"type": "sefs",
|
||||||
|
"source": "./bin_sefs",
|
||||||
|
"options": {
|
||||||
|
"integrity_only": true,
|
||||||
|
"MAC": "00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "/host",
|
||||||
|
"type": "hostfs",
|
||||||
|
"source": "."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"target": "/tmp",
|
||||||
|
"type": "ramfs"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1
tools/bin/.gitignore
vendored
Normal file
1
tools/bin/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
protect-integrity
|
93
tools/bin/build-enclave
Executable file
93
tools/bin/build-enclave
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
working_dir=`pwd`
|
||||||
|
this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
project_dir="$( cd "$( dirname "$this_dir/../../../" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
|
||||||
|
SGX_SDK="${SGX_SDK:-/opt/intel/sgxsdk}"
|
||||||
|
|
||||||
|
occlum_conf_json_path=$1
|
||||||
|
enclave_conf_xml_path=$2
|
||||||
|
enclave_key_pem_path=$3
|
||||||
|
protected_occlum_conf_json_path=`basename $occlum_conf_json_path`".protected"
|
||||||
|
|
||||||
|
occlum_conf_file_mac=
|
||||||
|
occlum_user_space_size=
|
||||||
|
|
||||||
|
|
||||||
|
report_arg_error() {
|
||||||
|
echo $1
|
||||||
|
echo ""
|
||||||
|
echo "Usage: occlum-build-enclave Occlum.json Enclave.xml Enclave.pem"
|
||||||
|
}
|
||||||
|
|
||||||
|
protect_occlum_json() {
|
||||||
|
cd $working_dir
|
||||||
|
"$project_dir/tools/bin/protect-integrity" protect $occlum_conf_json_path
|
||||||
|
}
|
||||||
|
|
||||||
|
print_occlum_conf_file_mac() {
|
||||||
|
cd $working_dir
|
||||||
|
"$project_dir/tools/bin/protect-integrity" show-mac $protected_occlum_conf_json_path
|
||||||
|
}
|
||||||
|
|
||||||
|
print_occlum_user_space_size() {
|
||||||
|
cd $working_dir
|
||||||
|
local size_with_unit=`cat $occlum_conf_json_path | \
|
||||||
|
python -c "import sys, json; print json.load(sys.stdin)['vm']['user_space_size']"`
|
||||||
|
numfmt --from=iec ${size_with_unit::-1}
|
||||||
|
}
|
||||||
|
|
||||||
|
build_enclave_so() {
|
||||||
|
cd $project_dir/src/libos/
|
||||||
|
make clean-builtin
|
||||||
|
make
|
||||||
|
}
|
||||||
|
|
||||||
|
sign_enclave_so() {
|
||||||
|
cd $working_dir
|
||||||
|
rm -f libocclum.signed.so
|
||||||
|
local enclave_so_path="$project_dir/src/libos/libocclum.so"
|
||||||
|
$SGX_SDK/bin/x64/sgx_sign sign \
|
||||||
|
-key $enclave_key_pem_path \
|
||||||
|
-enclave $enclave_so_path \
|
||||||
|
-out "libocclum.signed.so" \
|
||||||
|
-config $enclave_conf_xml_path
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Parse input arguments
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
if [[ $occlum_conf_json_path != *.json ]] ; then
|
||||||
|
report_arg_error "Error: Expect a JSON file as the first argument!"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
if [[ $enclave_conf_xml_path != *.xml ]] ; then
|
||||||
|
report_arg_error "Error: Expect a XML file as the second argument!"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
if [[ $enclave_key_pem_path != *.pem ]] ; then
|
||||||
|
report_arg_error "Error: Expect a PEM file as the third argument!"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ===========================================================================
|
||||||
|
# Build Occlum.json.protected and libocclum.signed.so
|
||||||
|
# ===========================================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
protect_occlum_json
|
||||||
|
echo "GEN => $protected_occlum_conf_json_path"
|
||||||
|
|
||||||
|
export OCCLUM_BUILTIN_CONF_FILE_MAC=`print_occlum_conf_file_mac`
|
||||||
|
echo "EXPORT => OCCLUM_BUILTIN_CONF_FILE_MAC = $OCCLUM_BUILTIN_CONF_FILE_MAC"
|
||||||
|
|
||||||
|
export OCCLUM_BUILTIN_VM_USER_SPACE_SIZE=`print_occlum_user_space_size`
|
||||||
|
echo "EXPORT => OCCLUM_BUILTIN_VM_USER_SPACE_SIZE = $OCCLUM_BUILTIN_VM_USER_SPACE_SIZE"
|
||||||
|
|
||||||
|
build_enclave_so
|
||||||
|
|
||||||
|
sign_enclave_so
|
||||||
|
echo "SIGN => libocclum.signed.so"
|
5
tools/protect-integrity/.gitignore
vendored
Normal file
5
tools/protect-integrity/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
protect-integrity
|
||||||
|
App/Enclave_u.h
|
||||||
|
App/Enclave_u.c
|
||||||
|
Enclave/Enclave_t.h
|
||||||
|
Enclave/Enclave_t.c
|
356
tools/protect-integrity/App/App.cpp
Normal file
356
tools/protect-integrity/App/App.cpp
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <libgen.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
|
#include <sgx_urts.h>
|
||||||
|
#include <sgx_error.h>
|
||||||
|
#include <sgx_eid.h>
|
||||||
|
#include "Enclave_u.h"
|
||||||
|
|
||||||
|
#define MAX_PATH FILENAME_MAX
|
||||||
|
#define TOKEN_FILENAME "enclave.token"
|
||||||
|
#define ENCLAVE_FILENAME "protect-integrity-enclave.signed.so"
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Enclave Initialization
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
/* Global EID shared by multiple threads */
|
||||||
|
static sgx_enclave_id_t global_eid = 0;
|
||||||
|
|
||||||
|
typedef struct _sgx_errlist_t {
|
||||||
|
sgx_status_t err;
|
||||||
|
const char *msg;
|
||||||
|
const char *sug; /* Suggestion */
|
||||||
|
} sgx_errlist_t;
|
||||||
|
|
||||||
|
#define REPEATS 500000
|
||||||
|
|
||||||
|
/* Error code returned by sgx_create_enclave */
|
||||||
|
static sgx_errlist_t sgx_errlist[] = {
|
||||||
|
{
|
||||||
|
SGX_ERROR_UNEXPECTED,
|
||||||
|
"Unexpected error occurred.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_INVALID_PARAMETER,
|
||||||
|
"Invalid parameter.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_OUT_OF_MEMORY,
|
||||||
|
"Out of memory.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_ENCLAVE_LOST,
|
||||||
|
"Power transition occurred.",
|
||||||
|
"Please refer to the sample \"PowerTransition\" for details."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_INVALID_ENCLAVE,
|
||||||
|
"Invalid enclave image.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_INVALID_ENCLAVE_ID,
|
||||||
|
"Invalid enclave identification.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_INVALID_SIGNATURE,
|
||||||
|
"Invalid enclave signature.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_OUT_OF_EPC,
|
||||||
|
"Out of EPC memory.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_NO_DEVICE,
|
||||||
|
"Invalid SGX device.",
|
||||||
|
"Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_MEMORY_MAP_CONFLICT,
|
||||||
|
"Memory map conflicted.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_INVALID_METADATA,
|
||||||
|
"Invalid enclave metadata.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_DEVICE_BUSY,
|
||||||
|
"SGX device was busy.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_INVALID_VERSION,
|
||||||
|
"Enclave version was invalid.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_INVALID_ATTRIBUTE,
|
||||||
|
"Enclave was not authorized.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
{
|
||||||
|
SGX_ERROR_ENCLAVE_FILE_ACCESS,
|
||||||
|
"Can't open enclave file.",
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Check error conditions for loading enclave */
|
||||||
|
static void print_error_message(sgx_status_t ret)
|
||||||
|
{
|
||||||
|
size_t idx = 0;
|
||||||
|
size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0];
|
||||||
|
|
||||||
|
for (idx = 0; idx < ttl; idx++) {
|
||||||
|
if(ret == sgx_errlist[idx].err) {
|
||||||
|
if(NULL != sgx_errlist[idx].sug)
|
||||||
|
printf("Info: %s\n", sgx_errlist[idx].sug);
|
||||||
|
printf("Error: %s\n", sgx_errlist[idx].msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx == ttl)
|
||||||
|
printf("Error: Unexpected error occurred.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* get_enclave_absolute_path() {
|
||||||
|
static char enclave_path[MAX_PATH] = {0};
|
||||||
|
// Get the absolute path of the executable
|
||||||
|
readlink("/proc/self/exe", enclave_path, sizeof(enclave_path));
|
||||||
|
// Get the absolute path of the containing directory
|
||||||
|
dirname(enclave_path);
|
||||||
|
// Get the absolute path of the enclave
|
||||||
|
strncat(enclave_path, "/", sizeof(enclave_path));
|
||||||
|
strncat(enclave_path, ENCLAVE_FILENAME, sizeof(enclave_path));
|
||||||
|
return (const char*)enclave_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the enclave:
|
||||||
|
* Step 1: try to retrieve the launch token saved by last transaction
|
||||||
|
* Step 2: call sgx_create_enclave to initialize an enclave instance
|
||||||
|
* Step 3: save the launch token if it is updated
|
||||||
|
*/
|
||||||
|
static int initialize_enclave(void)
|
||||||
|
{
|
||||||
|
char token_path[MAX_PATH] = {'\0'};
|
||||||
|
sgx_launch_token_t token = {0};
|
||||||
|
sgx_status_t ret = SGX_ERROR_UNEXPECTED;
|
||||||
|
int updated = 0;
|
||||||
|
|
||||||
|
/* Step 1: try to retrieve the launch token saved by last transaction
|
||||||
|
* if there is no token, then create a new one.
|
||||||
|
*/
|
||||||
|
/* try to get the token saved in $HOME */
|
||||||
|
const char *home_dir = getpwuid(getuid())->pw_dir;
|
||||||
|
|
||||||
|
if (home_dir != NULL &&
|
||||||
|
(strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) {
|
||||||
|
/* compose the token path */
|
||||||
|
strncpy(token_path, home_dir, strlen(home_dir));
|
||||||
|
strncat(token_path, "/", strlen("/"));
|
||||||
|
strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1);
|
||||||
|
} else {
|
||||||
|
/* if token path is too long or $HOME is NULL */
|
||||||
|
strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp = fopen(token_path, "rb");
|
||||||
|
if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) {
|
||||||
|
printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fp != NULL) {
|
||||||
|
/* read the token from saved file */
|
||||||
|
size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp);
|
||||||
|
if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) {
|
||||||
|
/* if token is invalid, clear the buffer */
|
||||||
|
memset(&token, 0x0, sizeof(sgx_launch_token_t));
|
||||||
|
printf("Warning: Invalid launch token read from \"%s\".\n", token_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 2: call sgx_create_enclave to initialize an enclave instance */
|
||||||
|
/* Debug Support: set 2nd parameter to 1 */
|
||||||
|
const char* enclave_path = get_enclave_absolute_path();
|
||||||
|
ret = sgx_create_enclave(enclave_path, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL);
|
||||||
|
if (ret != SGX_SUCCESS) {
|
||||||
|
print_error_message(ret);
|
||||||
|
if (fp != NULL) fclose(fp);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step 3: save the launch token if it is updated */
|
||||||
|
if (updated == 0 || fp == NULL) {
|
||||||
|
/* if the token is not updated, or file handler is invalid, do not perform saving */
|
||||||
|
if (fp != NULL) fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* reopen the file with write capablity */
|
||||||
|
fp = freopen(token_path, "wb", fp);
|
||||||
|
if (fp == NULL) return 0;
|
||||||
|
size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp);
|
||||||
|
if (write_num != sizeof(sgx_launch_token_t))
|
||||||
|
printf("Warning: Failed to save launch token to \"%s\".\n", token_path);
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// OCalls
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
void ocall_print(const char *str) {
|
||||||
|
printf("%s", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ocall_eprint(const char *str) {
|
||||||
|
fprintf(stderr, "%s", str);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ocall_open(const char* path) {
|
||||||
|
return open(path, O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t ocall_read(int fd, void* buf, size_t size) {
|
||||||
|
return read(fd, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t ocall_write(int fd, const void* buf, size_t size) {
|
||||||
|
return write(fd, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ocall_close(int fd) {
|
||||||
|
return close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Parsing program arguments
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
static void print_help(void) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Error: invalid arguments\n"
|
||||||
|
"\n"
|
||||||
|
"Usage:\n"
|
||||||
|
"\tprotect-integrity protect <ordinary_file>\n"
|
||||||
|
"\tprotect-integrity show <protected_file>\n"
|
||||||
|
"\tprotect-integrity show-mac <protected_file>\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CMD_ERROR (-1)
|
||||||
|
#define CMD_PROTECT 0
|
||||||
|
#define CMD_SHOW 1
|
||||||
|
#define CMD_SHOW_MAC 2
|
||||||
|
|
||||||
|
static int parse_args(
|
||||||
|
/* inputs */
|
||||||
|
int argc,
|
||||||
|
char* argv[],
|
||||||
|
/* outputs */
|
||||||
|
int* arg_command,
|
||||||
|
char** arg_file_path)
|
||||||
|
{
|
||||||
|
if (argc != 3) return -1;
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "protect") == 0) {
|
||||||
|
*arg_command = CMD_PROTECT;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "show") == 0) {
|
||||||
|
*arg_command = CMD_SHOW;
|
||||||
|
}
|
||||||
|
else if (strcmp(argv[1], "show-mac") == 0) {
|
||||||
|
*arg_command = CMD_SHOW_MAC;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*arg_file_path = argv[2];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Main
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
int SGX_CDECL main(int argc, char *argv[]) {
|
||||||
|
/* Parse arguments */
|
||||||
|
int arg_command = CMD_ERROR;
|
||||||
|
char* arg_file_path = NULL;
|
||||||
|
if (parse_args(argc, argv, &arg_command, &arg_file_path) < 0) {
|
||||||
|
print_help();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the enclave */
|
||||||
|
if (initialize_enclave() < 0) {
|
||||||
|
fprintf(stderr, "Error: enclave initialization failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do the command */
|
||||||
|
int ret = 0;
|
||||||
|
switch(arg_command){
|
||||||
|
case CMD_PROTECT: {
|
||||||
|
const char* input_path = arg_file_path;
|
||||||
|
|
||||||
|
const char* output_ext = ".protected";
|
||||||
|
size_t output_path_len = strlen(input_path) + strlen(output_ext) + 1;
|
||||||
|
|
||||||
|
char* output_path = (char*) malloc(output_path_len);
|
||||||
|
strncpy(output_path, input_path, output_path_len);
|
||||||
|
strncat(output_path, output_ext, output_path_len);
|
||||||
|
|
||||||
|
if (ecall_protect(global_eid, &ret, input_path, output_path)) {
|
||||||
|
fprintf(stderr, "Error: ecall failed\n");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_SHOW: {
|
||||||
|
const char* input_path = arg_file_path;
|
||||||
|
if (ecall_show(global_eid, &ret, input_path)) {
|
||||||
|
fprintf(stderr, "Error: ecall failed\n");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CMD_SHOW_MAC: {
|
||||||
|
const char* input_path = arg_file_path;
|
||||||
|
if (ecall_show_mac(global_eid, &ret, input_path)) {
|
||||||
|
fprintf(stderr, "Error: ecall failed\n");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// This should never happen!
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Destroy the enclave */
|
||||||
|
sgx_destroy_enclave(global_eid);
|
||||||
|
return ret;
|
||||||
|
}
|
20
tools/protect-integrity/App/App.h
Normal file
20
tools/protect-integrity/App/App.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef _APP_H_
|
||||||
|
#define _APP_H_
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
|
||||||
|
extern sgx_enclave_id_t global_eid; /* global enclave id */
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !_APP_H_ */
|
11
tools/protect-integrity/Enclave/Enclave.config.xml
Normal file
11
tools/protect-integrity/Enclave/Enclave.config.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<EnclaveConfiguration>
|
||||||
|
<ProdID>0</ProdID>
|
||||||
|
<ISVSVN>0</ISVSVN>
|
||||||
|
<StackMaxSize>0x40000</StackMaxSize>
|
||||||
|
<HeapMaxSize>0x100000</HeapMaxSize>
|
||||||
|
<TCSNum>10</TCSNum>
|
||||||
|
<TCSPolicy>1</TCSPolicy>
|
||||||
|
<DisableDebug>0</DisableDebug>
|
||||||
|
<MiscSelect>0</MiscSelect>
|
||||||
|
<MiscMask>0xFFFFFFFF</MiscMask>
|
||||||
|
</EnclaveConfiguration>
|
163
tools/protect-integrity/Enclave/Enclave.cpp
Normal file
163
tools/protect-integrity/Enclave/Enclave.cpp
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#include "Enclave_t.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sgx_trts.h>
|
||||||
|
#include <sgx_tprotected_fs.h>
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// Helper functions
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
#define PRINTF_BUFSIZE 512
|
||||||
|
|
||||||
|
static int printf(const char* fmt, ...) {
|
||||||
|
char buf[PRINTF_BUFSIZE] = {0};
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(buf, PRINTF_BUFSIZE, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
ocall_print(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int eprintf(const char* fmt, ...) {
|
||||||
|
char buf[PRINTF_BUFSIZE] = {0};
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
vsnprintf(buf, PRINTF_BUFSIZE, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
ocall_eprint(buf);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_mac(sgx_aes_gcm_128bit_tag_t* mac) {
|
||||||
|
unsigned char* bytes = (unsigned char*) mac;
|
||||||
|
for (size_t bi = 0; bi < sizeof(*mac); bi++) {
|
||||||
|
if (bi != 0) printf("-");
|
||||||
|
printf("%02x", bytes[bi] & 0xFF);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int open(const char* path) {
|
||||||
|
int fd = 0;
|
||||||
|
ocall_open(&fd, path);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t read(int fd, void* buf, size_t size) {
|
||||||
|
ssize_t ret = 0;
|
||||||
|
ocall_read(&ret, fd, buf, size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t write(int fd, const void* buf, size_t size) {
|
||||||
|
ssize_t ret = 0;
|
||||||
|
ocall_write(&ret, fd, buf, size);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int close(int fd) {
|
||||||
|
int ret = 0;
|
||||||
|
ocall_close(&ret, fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================================
|
||||||
|
// ECalls
|
||||||
|
// ==========================================================================
|
||||||
|
|
||||||
|
int ecall_protect(const char* input_path, const char* output_path) {
|
||||||
|
int input_file = -1;
|
||||||
|
SGX_FILE* output_file = NULL;
|
||||||
|
size_t len;
|
||||||
|
char buf[4 * 1024];
|
||||||
|
|
||||||
|
input_file = open(input_path);
|
||||||
|
if (input_file < 0) {
|
||||||
|
eprintf("Error: cannot open the input file at %s\n", input_path);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
output_file = sgx_fopen_integrity_only(output_path, "w");
|
||||||
|
if (output_file == NULL) {
|
||||||
|
eprintf("Error: cannot create the output file %s\n", output_path);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((len = read(input_file, buf, sizeof(buf))) > 0) {
|
||||||
|
if (sgx_fwrite(buf, 1, len, output_file) != len) {
|
||||||
|
eprintf("Error: failed to write to the output file %s\n", output_path);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(input_file);
|
||||||
|
sgx_fclose(output_file);
|
||||||
|
return 0;
|
||||||
|
on_error:
|
||||||
|
if (input_file >= 0) {
|
||||||
|
close(input_file);
|
||||||
|
}
|
||||||
|
if (output_file != NULL) {
|
||||||
|
sgx_fclose(output_file);
|
||||||
|
sgx_remove(output_path);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecall_show(const char* protected_file_path) {
|
||||||
|
SGX_FILE* protected_file = NULL;
|
||||||
|
ssize_t len;
|
||||||
|
char buf[4 * 1024];
|
||||||
|
|
||||||
|
protected_file = sgx_fopen_integrity_only(protected_file_path, "r");
|
||||||
|
if (protected_file == NULL) {
|
||||||
|
eprintf("Error: failed to open the given protected file %s\n", protected_file_path);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((len = sgx_fread(buf, 1, sizeof(buf), protected_file)) > 0) {
|
||||||
|
write(1/* stdout */, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sgx_ferror(protected_file)) {
|
||||||
|
eprintf("Error: failed to read the given protected file %s\n", protected_file_path);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
sgx_fclose(protected_file);
|
||||||
|
return 0;
|
||||||
|
on_error:
|
||||||
|
if (protected_file != NULL) {
|
||||||
|
sgx_fclose(protected_file);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecall_show_mac(const char* protected_file_path) {
|
||||||
|
SGX_FILE* protected_file = NULL;
|
||||||
|
sgx_aes_gcm_128bit_tag_t mac = { 0 };
|
||||||
|
|
||||||
|
protected_file = sgx_fopen_integrity_only(protected_file_path, "r");
|
||||||
|
if (protected_file == NULL) {
|
||||||
|
eprintf("Error: failed to open the given protected file %s\n", protected_file_path);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sgx_fget_mac(protected_file, &mac)) {
|
||||||
|
eprintf("Error: failed to get the MAC of the protected file %s\n", protected_file_path);
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_mac(&mac);
|
||||||
|
|
||||||
|
sgx_fclose(protected_file);
|
||||||
|
return 0;
|
||||||
|
on_error:
|
||||||
|
if (protected_file != NULL) {
|
||||||
|
sgx_fclose(protected_file);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
27
tools/protect-integrity/Enclave/Enclave.edl
Normal file
27
tools/protect-integrity/Enclave/Enclave.edl
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
enclave {
|
||||||
|
include "sys/types.h"
|
||||||
|
include "sgx_key.h"
|
||||||
|
|
||||||
|
from "sgx_tstdc.edl" import *;
|
||||||
|
from "sgx_tprotected_fs.edl" import *;
|
||||||
|
|
||||||
|
trusted {
|
||||||
|
public int ecall_protect([in, string] const char* input_path,
|
||||||
|
[in, string] const char* ouput_path);
|
||||||
|
public int ecall_show([in, string] const char* input_path);
|
||||||
|
public int ecall_show_mac([in, string] const char* input_path);
|
||||||
|
};
|
||||||
|
|
||||||
|
untrusted {
|
||||||
|
// File operations
|
||||||
|
int ocall_open([in, string] const char* path);
|
||||||
|
ssize_t ocall_read(int fd, [out, size=size] void* buf, size_t size);
|
||||||
|
ssize_t ocall_write(int fd, [in, size=size] const void* buf, size_t size);
|
||||||
|
int ocall_close(int fd);
|
||||||
|
|
||||||
|
// Print to the standard output
|
||||||
|
void ocall_print([in, string] const char* msg);
|
||||||
|
// Print to the standard error
|
||||||
|
void ocall_eprint([in, string] const char* msg);
|
||||||
|
};
|
||||||
|
};
|
16
tools/protect-integrity/Enclave/Enclave.h
Normal file
16
tools/protect-integrity/Enclave/Enclave.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _ENCLAVE_H_
|
||||||
|
#define _ENCLAVE_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !_ENCLAVE_H_ */
|
9
tools/protect-integrity/Enclave/Enclave.lds
Normal file
9
tools/protect-integrity/Enclave/Enclave.lds
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
enclave.so
|
||||||
|
{
|
||||||
|
global:
|
||||||
|
g_global_data_sim;
|
||||||
|
g_global_data;
|
||||||
|
enclave_entry;
|
||||||
|
local:
|
||||||
|
*;
|
||||||
|
};
|
39
tools/protect-integrity/Enclave/Enclave_private.pem
Normal file
39
tools/protect-integrity/Enclave/Enclave_private.pem
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ
|
||||||
|
AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ
|
||||||
|
ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr
|
||||||
|
nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b
|
||||||
|
3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H
|
||||||
|
ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD
|
||||||
|
5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW
|
||||||
|
KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC
|
||||||
|
1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe
|
||||||
|
K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z
|
||||||
|
AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q
|
||||||
|
ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6
|
||||||
|
JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826
|
||||||
|
5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02
|
||||||
|
wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9
|
||||||
|
osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm
|
||||||
|
WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i
|
||||||
|
Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9
|
||||||
|
xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd
|
||||||
|
vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD
|
||||||
|
Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a
|
||||||
|
cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC
|
||||||
|
0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ
|
||||||
|
gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo
|
||||||
|
gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t
|
||||||
|
k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz
|
||||||
|
Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6
|
||||||
|
O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5
|
||||||
|
afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom
|
||||||
|
e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G
|
||||||
|
BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv
|
||||||
|
fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN
|
||||||
|
t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9
|
||||||
|
yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp
|
||||||
|
6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg
|
||||||
|
WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH
|
||||||
|
NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk=
|
||||||
|
-----END RSA PRIVATE KEY-----
|
204
tools/protect-integrity/Makefile
Normal file
204
tools/protect-integrity/Makefile
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
######## SGX SDK Settings ########
|
||||||
|
|
||||||
|
SGX_SDK ?= /opt/intel/sgxsdk
|
||||||
|
SGX_MODE ?= HW
|
||||||
|
SGX_ARCH ?= x64
|
||||||
|
SGX_DEBUG ?= 1
|
||||||
|
|
||||||
|
ifeq ($(shell getconf LONG_BIT), 32)
|
||||||
|
SGX_ARCH := x86
|
||||||
|
else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32)
|
||||||
|
SGX_ARCH := x86
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SGX_ARCH), x86)
|
||||||
|
SGX_COMMON_CFLAGS := -m32
|
||||||
|
SGX_LIBRARY_PATH := $(SGX_SDK)/lib
|
||||||
|
SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign
|
||||||
|
SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r
|
||||||
|
else
|
||||||
|
SGX_COMMON_CFLAGS := -m64
|
||||||
|
SGX_LIBRARY_PATH := $(SGX_SDK)/lib64
|
||||||
|
SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign
|
||||||
|
SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(SGX_DEBUG), 1)
|
||||||
|
ifeq ($(SGX_PRERELEASE), 1)
|
||||||
|
$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
SGX_COMMON_CFLAGS += -Wall -Wno-unused-result
|
||||||
|
|
||||||
|
ifeq ($(SGX_DEBUG), 1)
|
||||||
|
SGX_COMMON_CFLAGS += -O2 -g
|
||||||
|
else
|
||||||
|
SGX_COMMON_CFLAGS += -O2
|
||||||
|
endif
|
||||||
|
|
||||||
|
######## App Settings ########
|
||||||
|
|
||||||
|
ifneq ($(SGX_MODE), HW)
|
||||||
|
Urts_Library_Name := sgx_urts_sim
|
||||||
|
else
|
||||||
|
Urts_Library_Name := sgx_urts
|
||||||
|
endif
|
||||||
|
|
||||||
|
App_Cpp_Files := App/App.cpp
|
||||||
|
App_Include_Paths := -IInclude -IApp -I$(SGX_SDK)/include
|
||||||
|
|
||||||
|
App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths)
|
||||||
|
|
||||||
|
# Three configuration modes - Debug, prerelease, release
|
||||||
|
# Debug - Macro DEBUG enabled.
|
||||||
|
# Prerelease - Macro NDEBUG and EDEBUG enabled.
|
||||||
|
# Release - Macro NDEBUG enabled.
|
||||||
|
ifeq ($(SGX_DEBUG), 1)
|
||||||
|
App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG
|
||||||
|
else ifeq ($(SGX_PRERELEASE), 1)
|
||||||
|
App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG
|
||||||
|
else
|
||||||
|
App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG
|
||||||
|
endif
|
||||||
|
|
||||||
|
App_Cpp_Flags := $(App_C_Flags) -std=c++11
|
||||||
|
App_Link_Flags := $(SGX_COMMON_CFLAGS) -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lsgx_uprotected_fs -lpthread
|
||||||
|
|
||||||
|
ifneq ($(SGX_MODE), HW)
|
||||||
|
App_Link_Flags += -lsgx_uae_service_sim
|
||||||
|
else
|
||||||
|
App_Link_Flags += -lsgx_uae_service
|
||||||
|
endif
|
||||||
|
|
||||||
|
App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o)
|
||||||
|
|
||||||
|
App_Name := protect-integrity
|
||||||
|
|
||||||
|
######## Enclave Settings ########
|
||||||
|
|
||||||
|
ifneq ($(SGX_MODE), HW)
|
||||||
|
Trts_Library_Name := sgx_trts_sim
|
||||||
|
Service_Library_Name := sgx_tservice_sim
|
||||||
|
else
|
||||||
|
Trts_Library_Name := sgx_trts
|
||||||
|
Service_Library_Name := sgx_tservice
|
||||||
|
endif
|
||||||
|
Crypto_Library_Name := sgx_tcrypto
|
||||||
|
|
||||||
|
Enclave_Cpp_Files := Enclave/Enclave.cpp
|
||||||
|
Enclave_C_Files :=
|
||||||
|
Enclave_Include_Paths := -IInclude -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport
|
||||||
|
|
||||||
|
Enclave_C_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fPIC -fstack-protector $(Enclave_Include_Paths)
|
||||||
|
Enclave_Cpp_Flags := $(Enclave_C_Flags) -std=c++03 -nostdinc++
|
||||||
|
|
||||||
|
# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries:
|
||||||
|
# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options,
|
||||||
|
# so that the whole content of trts is included in the enclave.
|
||||||
|
# 2. For other libraries, you just need to pull the required symbols.
|
||||||
|
# Use `--start-group' and `--end-group' to link these libraries.
|
||||||
|
# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options.
|
||||||
|
# Otherwise, you may get some undesirable errors.
|
||||||
|
Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) \
|
||||||
|
-Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
|
||||||
|
-Wl,--start-group -lsgx_tstdc -lsgx_tcxx -lsgx_tprotected_fs -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \
|
||||||
|
-Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
|
||||||
|
-Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
|
||||||
|
-Wl,--defsym,__ImageBase=0 \
|
||||||
|
-Wl,--version-script=Enclave/Enclave.lds
|
||||||
|
|
||||||
|
Enclave_Cpp_Objects := $(Enclave_Cpp_Files:.cpp=.o)
|
||||||
|
Enclave_C_Objects := $(Enclave_C_Files:.c=.o)
|
||||||
|
|
||||||
|
Enclave_Name := protect-integrity-enclave.so
|
||||||
|
Signed_Enclave_Name := protect-integrity-enclave.signed.so
|
||||||
|
Enclave_Config_File := Enclave/Enclave.config.xml
|
||||||
|
|
||||||
|
ifeq ($(SGX_MODE), HW)
|
||||||
|
ifneq ($(SGX_DEBUG), 1)
|
||||||
|
ifneq ($(SGX_PRERELEASE), 1)
|
||||||
|
Build_Mode = HW_RELEASE
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
.PHONY: all run
|
||||||
|
|
||||||
|
ifeq ($(Build_Mode), HW_RELEASE)
|
||||||
|
all: $(App_Name) $(Enclave_Name)
|
||||||
|
@echo "The project has been built in release hardware mode."
|
||||||
|
@echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave."
|
||||||
|
@echo "To sign the enclave use the command:"
|
||||||
|
@echo " $(SGX_ENCLAVE_SIGNER) sign -key <your key> -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)"
|
||||||
|
@echo "You can also sign the enclave using an external signing tool."
|
||||||
|
@echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW."
|
||||||
|
else
|
||||||
|
|
||||||
|
all: $(App_Name) $(Signed_Enclave_Name)
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
######## App Objects ########
|
||||||
|
|
||||||
|
App/Enclave_u.c: $(SGX_EDGER8R) Enclave/Enclave.edl
|
||||||
|
@cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include
|
||||||
|
@echo "GEN => $@"
|
||||||
|
|
||||||
|
App/Enclave_u.o: App/Enclave_u.c
|
||||||
|
@$(CC) $(App_C_Flags) -c $< -o $@
|
||||||
|
@echo "CC <= $<"
|
||||||
|
|
||||||
|
App/%.o: App/%.cpp
|
||||||
|
@$(CXX) $(App_Cpp_Flags) -c $< -o $@
|
||||||
|
@echo "CXX <= $<"
|
||||||
|
|
||||||
|
$(App_Name): App/Enclave_u.o $(App_Cpp_Objects)
|
||||||
|
@$(CXX) $^ -o $@ $(App_Link_Flags)
|
||||||
|
@cp $(App_Name) ../bin/
|
||||||
|
@echo "LINK => $@"
|
||||||
|
|
||||||
|
|
||||||
|
######## Enclave Objects ########
|
||||||
|
|
||||||
|
Enclave/Enclave_t.c: $(SGX_EDGER8R) Enclave/Enclave.edl
|
||||||
|
@cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include
|
||||||
|
@echo "GEN => $@"
|
||||||
|
|
||||||
|
Enclave/Enclave_t.o: Enclave/Enclave_t.c
|
||||||
|
@$(CC) $(Enclave_C_Flags) -c $< -o $@
|
||||||
|
@echo "CC <= $<"
|
||||||
|
|
||||||
|
$(Enclave_Cpp_Objects): Enclave/%.o: Enclave/%.cpp
|
||||||
|
@$(CXX) $(Enclave_Cpp_Flags) -c $< -o $@
|
||||||
|
@echo "CXX <= $<"
|
||||||
|
|
||||||
|
$(Enclave_C_Objects): Enclave/%.o: Enclave/%.c
|
||||||
|
@$(CC) $(Enclave_C_Flags) -c $< -o $@
|
||||||
|
@echo "CC <= $<"
|
||||||
|
|
||||||
|
$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects) $(Enclave_C_Objects)
|
||||||
|
$(CXX) $^ -o $@ $(Enclave_Link_Flags)
|
||||||
|
@echo "LINK => $@"
|
||||||
|
|
||||||
|
$(Signed_Enclave_Name): $(Enclave_Name)
|
||||||
|
@$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File)
|
||||||
|
@cp $(Signed_Enclave_Name) ../bin/
|
||||||
|
@echo "SIGN => $@"
|
||||||
|
|
||||||
|
.PHONY: test
|
||||||
|
test: all random.txt
|
||||||
|
./protect-integrity protect random.txt
|
||||||
|
./protect-integrity show random.txt.protected > random.txt.unprotected
|
||||||
|
./protect-integrity show-mac random.txt.protected
|
||||||
|
diff random.txt random.txt.unprotected
|
||||||
|
@echo "Pass ^_^"
|
||||||
|
|
||||||
|
random.txt:
|
||||||
|
@base64 /dev/urandom | head -c 10000000 > random.txt
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
@rm -f $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) $(Enclave_C_Objects) Enclave/Enclave_t.* *.test.txt random.txt*
|
37
tools/protect-integrity/README.md
Normal file
37
tools/protect-integrity/README.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# protect-integrity
|
||||||
|
|
||||||
|
This is a command-line utility that protects the _integrity_ of a file using the _integrity-only_ mode of SGX Protected File System Library.
|
||||||
|
|
||||||
|
## Prerequesite
|
||||||
|
|
||||||
|
This integrity-only mode is provided by Occlum's fork of Intel SGX SDK, not available on vanilla Intel SGX SDK. So make sure that you have Occlum's fork of Intel SGX SDK installed.
|
||||||
|
|
||||||
|
## How to Build
|
||||||
|
|
||||||
|
To build the project, run the following command
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
To test the project, run the following command
|
||||||
|
|
||||||
|
make test
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
To protect an ordinary file, run the following command
|
||||||
|
|
||||||
|
./protect-integrity protect <ordinary_file>
|
||||||
|
|
||||||
|
which will generate a protected file named `<ordinary_file>.protected` in the current working directory. The content of `<ordinary_file>.protected` is the same as `<ordinary_file` but associated with (a tree of) 128-bit MACs to protect its integrity.
|
||||||
|
|
||||||
|
To show the content of a protected file, run the following command
|
||||||
|
|
||||||
|
./protect-integrity show <protected_file>
|
||||||
|
|
||||||
|
To show the (root) MAC of a protected file, run the following command
|
||||||
|
|
||||||
|
./protect-integrity show-mac <protected_file>
|
||||||
|
|
||||||
|
## Note
|
||||||
|
|
||||||
|
This utility is intended to be used in _trusted_ development environment, not _untrusted_ deployment environment.
|
Loading…
Reference in New Issue
Block a user