Add Teaclave SGX Tool (#379)
diff --git a/.drone.yml b/.drone.yml
index 968da46..3cdd28f 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -36,6 +36,8 @@
path: /var/run/aesmd/aesm.socket
commands:
- . /root/.cargo/env
+ - (cd release/tool && ./teaclave_sgx_tool status)
+ - (cd release/tool && ./teaclave_sgx_tool attestation --key $AS_KEY --spid $AS_SPID)
- cd build && make run-tests
volumes:
diff --git a/README.md b/README.md
index 09fa0d4..4c00db3 100644
--- a/README.md
+++ b/README.md
@@ -72,6 +72,7 @@
- [Teaclave Worker](worker)
- [Test Harness and Test Cases](tests)
- [Third-Party Dependency Vendoring](third_party)
+- [Tool](tool)
- [Types](types)
### API Docs
diff --git a/attestation/src/key.rs b/attestation/src/key.rs
index 87acf3f..a506b37 100644
--- a/attestation/src/key.rs
+++ b/attestation/src/key.rs
@@ -30,14 +30,14 @@
/// NistP256KeyPair stores a pair of ECDSA (private, public) key based on the
/// NIST P-256 curve (a.k.a secp256r1).
-pub(crate) struct NistP256KeyPair {
+pub struct NistP256KeyPair {
prv_k: sgx_ec256_private_t,
pub_k: sgx_ec256_public_t,
}
impl NistP256KeyPair {
/// Generate a ECDSA key pair.
- pub(crate) fn new() -> Result<Self> {
+ pub fn new() -> Result<Self> {
let ecc_handle = SgxEccHandle::new();
ecc_handle.open()?;
let (prv_k, pub_k) = ecc_handle.create_key_pair()?;
@@ -45,7 +45,7 @@
Ok(Self { prv_k, pub_k })
}
- pub(crate) fn pub_k(&self) -> sgx_ec256_public_t {
+ pub fn pub_k(&self) -> sgx_ec256_public_t {
self.pub_k
}
diff --git a/attestation/src/lib.rs b/attestation/src/lib.rs
index 5fc7685..11e5bd7 100644
--- a/attestation/src/lib.rs
+++ b/attestation/src/lib.rs
@@ -137,7 +137,7 @@
/// using EPID or Data Center Attestation
/// Service (platform dependent) using ECDSA.
#[derive(Default, Serialize, Deserialize)]
-pub(crate) struct EndorsedAttestationReport {
+pub struct EndorsedAttestationReport {
/// Attestation report generated by the hardware
pub report: Vec<u8>,
/// Singature of the report
@@ -163,7 +163,7 @@
cfg_if::cfg_if! {
if #[cfg(feature = "mesalock_sgx")] {
mod service;
- mod key;
+ pub mod key;
mod platform;
mod attestation;
pub use attestation::RemoteAttestation;
diff --git a/attestation/src/report.rs b/attestation/src/report.rs
index 7d334e7..5b8d758 100644
--- a/attestation/src/report.rs
+++ b/attestation/src/report.rs
@@ -342,7 +342,7 @@
impl SgxQuote {
/// Parse from bytes to `SgxQuote`.
- fn parse_from<'a>(bytes: &'a [u8]) -> Result<Self> {
+ pub fn parse_from<'a>(bytes: &'a [u8]) -> Result<Self> {
let mut pos: usize = 0;
let mut take = |n: usize| -> Result<&'a [u8]> {
if n > 0 && bytes.len() >= pos + n {
diff --git a/attestation/src/service.rs b/attestation/src/service.rs
index 3117c03..34173ca 100644
--- a/attestation/src/service.rs
+++ b/attestation/src/service.rs
@@ -71,7 +71,7 @@
}
impl EndorsedAttestationReport {
- pub(crate) fn new(
+ pub fn new(
att_service_cfg: &AttestationServiceConfig,
pub_k: sgx_types::sgx_ec256_public_t,
) -> anyhow::Result<Self> {
diff --git a/binder/src/proto.rs b/binder/src/proto.rs
index 95e103a..b3e7fa7 100644
--- a/binder/src/proto.rs
+++ b/binder/src/proto.rs
@@ -24,6 +24,7 @@
InitEnclave,
FinalizeEnclave,
RunTest,
+ Raw,
Unimplemented,
}
@@ -35,6 +36,7 @@
0x0000_1001 => ECallCommand::InitEnclave,
0x0000_1002 => ECallCommand::FinalizeEnclave,
0x0000_1003 => ECallCommand::RunTest,
+ 0x0000_1004 => ECallCommand::Raw,
_ => ECallCommand::Unimplemented,
}
}
@@ -48,6 +50,7 @@
ECallCommand::InitEnclave => 0x0000_1001,
ECallCommand::FinalizeEnclave => 0x0000_1002,
ECallCommand::RunTest => 0x0000_1003,
+ ECallCommand::Raw => 0x0000_1004,
ECallCommand::Unimplemented => 0xffff_ffff,
}
}
@@ -92,3 +95,21 @@
#[derive(Serialize, Deserialize, Debug)]
pub struct RunTestOutput;
+
+#[derive(Default, Serialize, Deserialize, Debug)]
+pub struct RawJsonInput {
+ pub json: String,
+}
+
+impl RawJsonInput {
+ pub fn new(json: impl ToString) -> Self {
+ Self {
+ json: json.to_string(),
+ }
+ }
+}
+
+#[derive(Default, Serialize, Deserialize, Debug)]
+pub struct RawJsonOutput {
+ pub json: String,
+}
diff --git a/cmake/TeaclaveGenVars.cmake b/cmake/TeaclaveGenVars.cmake
index 006af9a..6e6894c 100644
--- a/cmake/TeaclaveGenVars.cmake
+++ b/cmake/TeaclaveGenVars.cmake
@@ -7,6 +7,7 @@
set(TEACLAVE_EXAMPLE_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/examples)
set(TEACLAVE_BIN_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/bin)
set(TEACLAVE_CLI_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/cli)
+set(TEACLAVE_TOOL_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/tool)
set(TEACLAVE_DCAP_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/dcap)
set(TEACLAVE_LIB_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/lib)
set(TEACLAVE_DOC_INSTALL_DIR ${TEACLAVE_INSTALL_DIR}/docs)
@@ -102,6 +103,7 @@
TEACLAVE_EXAMPLE_INSTALL_DIR=${TEACLAVE_EXAMPLE_INSTALL_DIR}
TEACLAVE_BIN_INSTALL_DIR=${TEACLAVE_BIN_INSTALL_DIR}
TEACLAVE_CLI_INSTALL_DIR=${TEACLAVE_CLI_INSTALL_DIR}
+ TEACLAVE_TOOL_INSTALL_DIR=${TEACLAVE_TOOL_INSTALL_DIR}
TEACLAVE_DCAP_INSTALL_DIR=${TEACLAVE_DCAP_INSTALL_DIR}
TEACLAVE_LIB_INSTALL_DIR=${TEACLAVE_LIB_INSTALL_DIR}
TEACLAVE_DOC_INSTALL_DIR=${TEACLAVE_DOC_INSTALL_DIR}
diff --git a/cmake/TeaclaveUtils.cmake b/cmake/TeaclaveUtils.cmake
index 85b5bfc..2ada262 100644
--- a/cmake/TeaclaveUtils.cmake
+++ b/cmake/TeaclaveUtils.cmake
@@ -186,6 +186,10 @@
set(_enclave_info "${TEACLAVE_OUT_DIR}/${pkg_name}_info.toml")
endif()
+ if(pkg_name_no_enclave MATCHES "_tool$")
+ set(_enclave_info "/dev/null")
+ endif()
+
add_custom_target(
${_target_name} ALL
COMMAND
diff --git a/cmake/scripts/parse_cargo_packages.py b/cmake/scripts/parse_cargo_packages.py
index 46399a5..6d77327 100644
--- a/cmake/scripts/parse_cargo_packages.py
+++ b/cmake/scripts/parse_cargo_packages.py
@@ -63,6 +63,8 @@
return 'examples'
elif pkg_path.startswith('tests/'):
return 'tests'
+ elif pkg_path.startswith('tool/'):
+ return 'tool'
elif pkg_path == 'cli':
return 'cli'
elif pkg_path == 'dcap':
diff --git a/cmake/scripts/prep.sh b/cmake/scripts/prep.sh
index a7fca71..ec85f7b 100755
--- a/cmake/scripts/prep.sh
+++ b/cmake/scripts/prep.sh
@@ -5,7 +5,8 @@
"SGX_EDGER8R" "TEACLAVE_EDL_DIR" "SGX_SDK" "RUST_SGX_SDK" "CMAKE_C_COMPILER"
"CMAKE_AR" "SGX_UNTRUSTED_CFLAGS" "SGX_TRUSTED_CFLAGS" "MT_SCRIPT_DIR"
"TEACLAVE_SERVICE_INSTALL_DIR" "TEACLAVE_EXAMPLE_INSTALL_DIR" "TEACLAVE_BIN_INSTALL_DIR"
-"TEACLAVE_CLI_INSTALL_DIR" "TEACLAVE_DCAP_INSTALL_DIR" "TEACLAVE_LIB_INSTALL_DIR" "TEACLAVE_TEST_INSTALL_DIR"
+"TEACLAVE_CLI_INSTALL_DIR" "TEACLAVE_TOOL_INSTALL_DIR" "TEACLAVE_DCAP_INSTALL_DIR"
+"TEACLAVE_LIB_INSTALL_DIR" "TEACLAVE_TEST_INSTALL_DIR"
"TEACLAVE_AUDITORS_DIR" "TEACLAVE_EXAMPLE_AUDITORS_DIR" "DCAP" "TEACLAVE_SYMLINKS"
"TEACLAVE_PROJECT_ROOT"
)
@@ -16,7 +17,7 @@
${MT_SCRIPT_DIR}/setup_cmake_tomls.py ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}
mkdir -p ${TEACLAVE_OUT_DIR} ${TEACLAVE_TARGET_DIR} ${TEACLAVE_SERVICE_INSTALL_DIR} \
- ${TEACLAVE_EXAMPLE_INSTALL_DIR} ${TEACLAVE_CLI_INSTALL_DIR} \
+ ${TEACLAVE_EXAMPLE_INSTALL_DIR} ${TEACLAVE_CLI_INSTALL_DIR} ${TEACLAVE_TOOL_INSTALL_DIR} \
${TEACLAVE_BIN_INSTALL_DIR} ${TEACLAVE_LIB_INSTALL_DIR} \
${TEACLAVE_TEST_INSTALL_DIR} ${TEACLAVE_AUDITORS_DIR} ${TEACLAVE_EXAMPLE_AUDITORS_DIR}
if [ -n "$DCAP" ]; then
diff --git a/cmake/tomls/Cargo.sgx_trusted_lib.toml b/cmake/tomls/Cargo.sgx_trusted_lib.toml
index 959603e..24d0b67 100644
--- a/cmake/tomls/Cargo.sgx_trusted_lib.toml
+++ b/cmake/tomls/Cargo.sgx_trusted_lib.toml
@@ -11,6 +11,7 @@
"tests/unit/enclave",
"tests/functional/enclave",
"tests/integration/enclave",
+ "tool/enclave",
]
exclude = [
diff --git a/cmake/tomls/Cargo.sgx_untrusted_app.toml b/cmake/tomls/Cargo.sgx_untrusted_app.toml
index 21fe9b3..1ef34f3 100644
--- a/cmake/tomls/Cargo.sgx_untrusted_app.toml
+++ b/cmake/tomls/Cargo.sgx_untrusted_app.toml
@@ -11,6 +11,7 @@
"tests/unit/app",
"tests/functional/app",
"tests/integration/app",
+ "tool/app",
]
exclude = [
diff --git a/third_party/crates-io b/third_party/crates-io
index dd10153..eb25981 160000
--- a/third_party/crates-io
+++ b/third_party/crates-io
@@ -1 +1 @@
-Subproject commit dd10153ccb910b83d095bc290300a95a35a260c4
+Subproject commit eb259811db1316ec63d9dd01cda3d87e3b860ca0
diff --git a/tool/README.md b/tool/README.md
new file mode 100644
index 0000000..329cfd8
--- /dev/null
+++ b/tool/README.md
@@ -0,0 +1,54 @@
+# Teaclave SGX Tool
+
+This tool is to dump some SGX related information, e.g., hardware and software
+information, remote attestation report. This can help to diagnose some issues
+which may caused by the platform settings.
+
+## Hardware/Software Status
+
+To dump the SGX related hardware and software information, you can use this
+command:
+
+```
+$ ./teaclave_sgx_tool status
+Vendor: GenuineIntel
+CPU Model: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
+SGX:
+ Has SGX: true
+ Has SGX1: true
+ Has SGX2: false
+ Supports ENCLV instruction leaves EINCVIRTCHILD, EDECVIRTCHILD, and ESETCONTEXT: false
+ Supports ENCLS instruction leaves ETRACKC, ERDINFO, ELDBC, and ELDUC: false
+ Bit vector of supported extended SGX features: 0x00000000
+ Maximum supported enclave size in non-64-bit mode: 2^31
+ Maximum supported enclave size in 64-bit mode: 2^36
+ Bits of SECS.ATTRIBUTES[127:0] set with ECREATE: 0x0000000000000036 (lower) 0x000000000000001F (upper)
+ EPC physical base: 0x00000000B0200000
+ EPC size: 0x0000000005D80000 (93M)
+ Supports flexible launch control: true
+
+...
+```
+
+## Remote Attestation Report
+
+Use the following command to dump remote attestation report and configure the
+platform accordingly:
+
+```
+$ ./teaclave_sgx_tool attestation --key {as_key} --spid {as_spid} --url {as_url} --algorithm {as_algorithm}
+Remote Attestation Report:
+{
+ "advisoryIDs": [
+ "INTEL-SA-00161",
+ "INTEL-SA-00320",
+ "INTEL-SA-00329",
+ "INTEL-SA-00220",
+ "INTEL-SA-00270",
+ "INTEL-SA-00293",
+ "INTEL-SA-00233"
+ ],
+ "advisoryURL": "https://security-center.intel.com",
+ ...
+}
+```
diff --git a/tool/app/Cargo.toml b/tool/app/Cargo.toml
new file mode 100644
index 0000000..a2b80bc
--- /dev/null
+++ b/tool/app/Cargo.toml
@@ -0,0 +1,22 @@
+[package]
+name = "teaclave_sgx_tool"
+version = "0.1.0"
+authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
+description = "Teaclave SGX Tool"
+license = "Apache-2.0"
+build = "build.rs"
+edition = "2018"
+
+[dependencies]
+log = { version = "0.4.6", features = ["release_max_level_info"] }
+env_logger = { version = "0.7.1" }
+anyhow = { version = "1.0.26" }
+serde = { version = "1.0.92", features = ["derive"] }
+serde_json = { version = "1.0.39" }
+raw-cpuid = "8.1.0"
+structopt = "0.3"
+
+teaclave_binder = { path = "../../binder", features = ["app"] }
+teaclave_types = { path = "../../types" }
+
+sgx_types = { version = "1.1.2" }
diff --git a/tool/app/build.rs b/tool/app/build.rs
new file mode 100644
index 0000000..dff52fd
--- /dev/null
+++ b/tool/app/build.rs
@@ -0,0 +1,54 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use std::env;
+use std::path::PathBuf;
+
+fn choose_sgx_dylib(is_sim: bool) {
+ if is_sim {
+ println!("cargo:rustc-link-lib=dylib=sgx_urts_sim");
+ println!("cargo:rustc-link-lib=dylib=sgx_uae_service_sim");
+ } else {
+ println!("cargo:rustc-link-lib=dylib=sgx_urts");
+ println!("cargo:rustc-link-lib=dylib=sgx_uae_service");
+ }
+}
+
+fn main() {
+ let sdk_dir = env::var("SGX_SDK").unwrap_or("/opt/intel/sgxsdk".into());
+ println!("cargo:rustc-link-search=native={}/lib64", sdk_dir);
+
+ let out_path = env::var_os("ENCLAVE_OUT_DIR").unwrap_or("out".into());
+ let out_dir = &PathBuf::from(out_path);
+
+ println!("cargo:rustc-link-search=native={}", out_dir.display());
+ if let Ok(edl_dir) = env::var("TEACLAVE_EDL_DIR") {
+ println!("cargo:rerun-if-changed={}/Enclave_common.edl", edl_dir);
+ }
+ println!("cargo:rustc-link-lib=static=Enclave_common_u");
+
+ let is_sim = match env::var("SGX_MODE") {
+ Ok(ref v) if v == "SW" => true,
+ Ok(ref v) if v == "HW" => false,
+ Err(env::VarError::NotPresent) => false,
+ _ => {
+ panic!("Stop build process, wrong SGX_MODE env provided.");
+ }
+ };
+
+ choose_sgx_dylib(is_sim);
+}
diff --git a/tool/app/src/main.rs b/tool/app/src/main.rs
new file mode 100644
index 0000000..8b20963
--- /dev/null
+++ b/tool/app/src/main.rs
@@ -0,0 +1,201 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+use anyhow::Result;
+use log::error;
+use std::process;
+use structopt::StructOpt;
+use teaclave_binder::proto::{ECallCommand, RawJsonInput, RawJsonOutput};
+use teaclave_binder::TeeBinder;
+use teaclave_types::TeeServiceResult;
+
+fn attestation(opt: &AttestationOpt) -> anyhow::Result<()> {
+ env_logger::init();
+ let tee = TeeBinder::new(env!("CARGO_PKG_NAME"))?;
+ run(&tee, opt)?;
+ tee.finalize();
+
+ Ok(())
+}
+
+fn start_enclave_unit_test_driver(tee: &TeeBinder, opt: &AttestationOpt) -> anyhow::Result<()> {
+ let cmd = ECallCommand::Raw;
+ let json = serde_json::to_string(opt)?;
+ let input = RawJsonInput::new(json);
+ match tee.invoke::<RawJsonInput, TeeServiceResult<RawJsonOutput>>(cmd, input) {
+ Err(e) => error!("{:?}", e),
+ Ok(Err(e)) => error!("{:?}", e),
+ _ => (),
+ }
+
+ Ok(())
+}
+
+fn run(tee: &TeeBinder, opt: &AttestationOpt) -> anyhow::Result<()> {
+ start_enclave_unit_test_driver(tee, opt)?;
+
+ Ok(())
+}
+
+#[derive(Debug, StructOpt)]
+#[structopt(name = "teaclave_sgx_tool", about = "Teaclave SGX tool.")]
+struct Opt {
+ #[structopt(subcommand)]
+ command: Command,
+}
+
+#[derive(Debug, StructOpt, serde::Serialize)]
+struct AttestationOpt {
+ /// Attestation algorithm, supported algorithms are "sgx_epid" for IAS
+ /// attestation and "sgx_ecdsa" for DCAP attestation.
+ #[structopt(long, default_value = "sgx_epid")]
+ algorithm: String,
+
+ /// URL of attestation service.
+ #[structopt(long, default_value = "https://api.trustedservices.intel.com:443")]
+ url: String,
+
+ /// API key for attestation service.
+ #[structopt(long, default_value = "00000000000000000000000000000000")]
+ key: String,
+
+ /// SPID for attestation service.
+ #[structopt(long, default_value = "00000000000000000000000000000000")]
+ spid: String,
+}
+
+#[derive(Debug, StructOpt)]
+enum Command {
+ /// Dump current hardware and software information related with Intel SGX
+ #[structopt(name = "status")]
+ Status,
+ /// Dump remote attestationation report
+ #[structopt(name = "attestation")]
+ Attestation(AttestationOpt),
+}
+
+fn status() {
+ let cpuid = raw_cpuid::CpuId::new();
+ println!(
+ "Vendor: {}",
+ cpuid
+ .get_vendor_info()
+ .as_ref()
+ .map_or_else(|| "unknown", |vf| vf.as_string(),)
+ );
+
+ println!(
+ "CPU Model: {}",
+ cpuid.get_extended_function_info().as_ref().map_or_else(
+ || "n/a",
+ |extfuninfo| extfuninfo.processor_brand_string().unwrap_or("unreadable"),
+ )
+ );
+
+ println!("SGX: ");
+
+ println!(
+ " Has SGX: {}",
+ cpuid
+ .get_extended_feature_info()
+ .as_ref()
+ .map_or_else(|| "n/a".to_string(), |ext| ext.has_sgx().to_string(),)
+ );
+
+ let sgx_info = cpuid.get_sgx_info();
+ match sgx_info {
+ Some(sgx_info) => {
+ println!(" Has SGX1: {}", sgx_info.has_sgx1());
+ println!(" Has SGX2: {}", sgx_info.has_sgx2());
+ println!(" Supports ENCLV instruction leaves EINCVIRTCHILD, EDECVIRTCHILD, and ESETCONTEXT: {}", sgx_info.has_enclv_leaves_einvirtchild_edecvirtchild_esetcontext());
+ println!(
+ " Supports ENCLS instruction leaves ETRACKC, ERDINFO, ELDBC, and ELDUC: {}",
+ sgx_info.has_encls_leaves_etrackc_erdinfo_eldbc_elduc()
+ );
+ println!(
+ " Bit vector of supported extended SGX features: {:#010X}",
+ sgx_info.miscselect()
+ );
+ println!(
+ " Maximum supported enclave size in non-64-bit mode: 2^{}",
+ sgx_info.max_enclave_size_non_64bit()
+ );
+ println!(
+ " Maximum supported enclave size in 64-bit mode: 2^{}",
+ sgx_info.max_enclave_size_64bit()
+ );
+ println!(" Bits of SECS.ATTRIBUTES[127:0] set with ECREATE: {:#018X} (lower) {:#018X} (upper)", sgx_info.secs_attributes().0, sgx_info.secs_attributes().1);
+ for i in sgx_info.iter() {
+ match i {
+ raw_cpuid::SgxSectionInfo::Epc(epc) => {
+ println!(" EPC physical base: {:#018X}", epc.physical_base());
+ println!(
+ " EPC size: {:#018X} ({}M)",
+ epc.size(),
+ epc.size() / 1024 / 1024
+ );
+ }
+ }
+ }
+ }
+ None => println!(" Intel SGX: n/a"),
+ }
+
+ println!(
+ " Supports flexible launch control: {}",
+ cpuid
+ .get_extended_feature_info()
+ .as_ref()
+ .map_or_else(|| "n/a".to_string(), |ext| ext.has_sgx_lc().to_string(),)
+ );
+
+ println!(
+ " SGX device: /dev/sgx {}, /dev/isgx {}",
+ std::path::Path::new("/dev/sgx").exists(),
+ std::path::Path::new("/dev/isgx").exists()
+ );
+ println!(
+ " AESM service: {}",
+ std::path::Path::new("/var/run/aesmd/aesm.socket").exists()
+ );
+
+ println!("\nKernel module (isgx):");
+ if process::Command::new("modinfo")
+ .arg("isgx")
+ .status()
+ .is_err()
+ {
+ println!("failed to execute modinfo isgx");
+ }
+ println!("\nKernel module (sgx):");
+ if process::Command::new("modinfo")
+ .arg("sgx")
+ .status()
+ .is_err()
+ {
+ println!("failed to execute modinfo sgx");
+ }
+}
+
+fn main() -> Result<()> {
+ let args = Opt::from_args();
+ match args.command {
+ Command::Status => status(),
+ Command::Attestation(opt) => attestation(&opt)?,
+ };
+ Ok(())
+}
diff --git a/tool/enclave/Cargo.toml b/tool/enclave/Cargo.toml
new file mode 100644
index 0000000..3c780c2
--- /dev/null
+++ b/tool/enclave/Cargo.toml
@@ -0,0 +1,39 @@
+[package]
+name = "teaclave_sgx_tool_enclave"
+version = "0.1.0"
+authors = ["Teaclave Contributors <dev@teaclave.apache.org>"]
+description = "Teaclave SGX Tool"
+license = "Apache-2.0"
+edition = "2018"
+
+[lib]
+name = "teaclave_sgx_tool_enclave"
+crate-type = ["staticlib"]
+
+[features]
+default = []
+mesalock_sgx = [
+ "sgx_tstd",
+ "teaclave_attestation/mesalock_sgx",
+ "teaclave_binder/mesalock_sgx",
+ "teaclave_types/mesalock_sgx",
+ "teaclave_service_enclave_utils/mesalock_sgx",
+]
+cov = ["teaclave_service_enclave_utils/cov"]
+
+[dependencies]
+log = { version = "0.4.6", features = ["release_max_level_info"] }
+anyhow = { version = "1.0.26" }
+serde = { version = "1.0.92" }
+serde_json = { version = "1.0.39" }
+base64 = { version = "0.10.1" }
+thiserror = { version = "1.0.9" }
+
+
+teaclave_attestation = { path = "../../attestation" }
+teaclave_binder = { path = "../../binder" }
+teaclave_service_enclave_utils = { path = "../../services/utils/service_enclave_utils" }
+teaclave_types = { path = "../../types" }
+
+sgx_tstd = { version = "1.1.2", features = ["net", "thread", "backtrace"], optional = true }
+sgx_types = { version = "1.1.2" }
diff --git a/tool/enclave/Enclave.config.xml b/tool/enclave/Enclave.config.xml
new file mode 100644
index 0000000..2c4cfca
--- /dev/null
+++ b/tool/enclave/Enclave.config.xml
@@ -0,0 +1,12 @@
+<!-- Please refer to User's Guide for the explanation of each field -->
+<EnclaveConfiguration>
+ <ProdID>0</ProdID>
+ <ISVSVN>0</ISVSVN>
+ <StackMaxSize>0x200000</StackMaxSize>
+ <HeapMaxSize>0x8000000</HeapMaxSize>
+ <TCSNum>22</TCSNum>
+ <TCSPolicy>0</TCSPolicy>
+ <DisableDebug>0</DisableDebug>
+ <MiscSelect>0</MiscSelect>
+ <MiscMask>0xFFFFFFFF</MiscMask>
+</EnclaveConfiguration>
diff --git a/tool/enclave/src/lib.rs b/tool/enclave/src/lib.rs
new file mode 100644
index 0000000..0bf1c67
--- /dev/null
+++ b/tool/enclave/src/lib.rs
@@ -0,0 +1,97 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#![cfg_attr(feature = "mesalock_sgx", no_std)]
+#[cfg(feature = "mesalock_sgx")]
+#[macro_use]
+extern crate sgx_tstd as std;
+
+use std::prelude::v1::*;
+
+use serde_json::Value;
+use teaclave_attestation::report::SgxQuote;
+use teaclave_attestation::EndorsedAttestationReport;
+use teaclave_attestation::{key, AttestationConfig};
+use teaclave_binder::proto::{
+ ECallCommand, FinalizeEnclaveInput, FinalizeEnclaveOutput, InitEnclaveInput, InitEnclaveOutput,
+ RawJsonInput, RawJsonOutput,
+};
+use teaclave_binder::{handle_ecall, register_ecall_handler};
+use teaclave_service_enclave_utils::ServiceEnclave;
+use teaclave_types::TeeServiceError;
+use teaclave_types::{self, TeeServiceResult};
+
+fn attestation(raw_json_input: &RawJsonInput) -> anyhow::Result<()> {
+ let v: serde_json::Value = serde_json::from_str(&raw_json_input.json)?;
+ let attestation_config = AttestationConfig::new(
+ v["algorithm"].as_str().unwrap(),
+ v["url"].as_str().unwrap(),
+ v["key"].as_str().unwrap(),
+ v["spid"].as_str().unwrap(),
+ )?;
+ let key_pair = key::NistP256KeyPair::new()?;
+ let report = match *attestation_config {
+ AttestationConfig::NoAttestation => EndorsedAttestationReport::default(),
+ AttestationConfig::WithAttestation(ref config) => {
+ EndorsedAttestationReport::new(config, key_pair.pub_k())?
+ }
+ };
+ let attn_report: Value = serde_json::from_slice(&report.report)?;
+ let sgx_quote_body = {
+ let quote_encoded = attn_report["isvEnclaveQuoteBody"]
+ .as_str()
+ .ok_or_else(|| anyhow::anyhow!("report error"))?;
+ let quote_raw = base64::decode("e_encoded.as_bytes())?;
+ SgxQuote::parse_from(quote_raw.as_slice())?
+ };
+ println!("Remote Attestation Report:");
+ println!("{}", serde_json::to_string_pretty(&attn_report)?);
+ println!("");
+ println!("ISV Enclave Quote Body:");
+ println!("{:?}", sgx_quote_body);
+ Ok(())
+}
+
+#[handle_ecall]
+fn handle_run_test(input: &RawJsonInput) -> TeeServiceResult<RawJsonOutput> {
+ match attestation(input) {
+ Ok(_) => Ok(RawJsonOutput::default()),
+ Err(e) => {
+ log::error!("Failed to start the service: {}", e);
+ Err(TeeServiceError::ServiceError)
+ }
+ }
+}
+
+#[handle_ecall]
+fn handle_init_enclave(_: &InitEnclaveInput) -> TeeServiceResult<InitEnclaveOutput> {
+ ServiceEnclave::init(env!("CARGO_PKG_NAME"))?;
+ Ok(InitEnclaveOutput)
+}
+
+#[handle_ecall]
+fn handle_finalize_enclave(_: &FinalizeEnclaveInput) -> TeeServiceResult<FinalizeEnclaveOutput> {
+ ServiceEnclave::finalize()?;
+ Ok(FinalizeEnclaveOutput)
+}
+
+register_ecall_handler!(
+ type ECallCommand,
+ (ECallCommand::Raw, RawJsonInput, RawJsonOutput),
+ (ECallCommand::InitEnclave, InitEnclaveInput, InitEnclaveOutput),
+ (ECallCommand::FinalizeEnclave, FinalizeEnclaveInput, FinalizeEnclaveOutput),
+);