diff --git a/.gitignore b/.gitignore index 88c90e4..ee453d6 100644 --- a/.gitignore +++ b/.gitignore @@ -116,4 +116,6 @@ crashlytics-build.properties fabric.properties /target -**/*.rs.bk \ No newline at end of file +**/*.rs.bk + +enigma-types.h \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index f6be89f..e69de29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +0,0 @@ -[submodule "enclave/incubator-teaclave-sgx-sdk"] - path = enclave/incubator-teaclave-sgx-sdk - url = git@github.com:apache/incubator-teaclave-sgx-sdk.git - branch = v1.1.1-testing diff --git a/api-server/README.md b/api-server/README.md index 115d656..0eb0413 100644 --- a/api-server/README.md +++ b/api-server/README.md @@ -69,18 +69,20 @@ The geolocation + datetime data is to be provided in an array in JSON format as "lat": 40.757339, "lng": -73.985992, "startTS": 1583064000, - "endTS": 1583067600 + "endTS": 1583067600, + "testResult": false, }, { "lat": 40.793840, "lng": -73.956900, "startTS": 1583150400, - "endTS": 1583154000 + "endTS": 1583154000, + "testResult": true, }, ] ``` -In the example above, the first datapoint is for Times Square in New York City on March 1st, 2020 from 12pm to 1pm, whereas the second data point is somewhere in Central Park the following day March 2nd, 2020 from 12pm to 1pm. +In the example above, the first datapoint is for Times Square in New York City on March 1st, 2020 from 12pm to 1pm, whereas the second data point is somewhere in Central Park the following day March 2nd, 2020 from 12pm to 1pm. This user did not test positive for Coronavirus the first day, but he tested positive the following day. # Installation diff --git a/client/data.js b/client/data.js new file mode 100644 index 0000000..895a6ff --- /dev/null +++ b/client/data.js @@ -0,0 +1,33 @@ +module.exports.DataUser1 = [ + { + "lat": 40.757339, + "lng": -73.985992, + "startTS": 1583064001, + "endTS": 1583067601, + "testResult": false, + }, + { + "lat": 40.793840, + "lng": -73.956900, + "startTS": 1583150401, + "endTS": 1583154001, + "testResult": false, + }, +] + +module.exports.DataUser2 = [ + { + "lat": 41.757339, + "lng": -73.985992, + "startTS": 1583064000, + "endTS": 1583067600, + "testResult": true, + }, + { + "lat": 40.793840, + "lng": -73.956900, + "startTS": 1583150400, + "endTS": 1583154000, + "testResult": true, + }, +] \ No newline at end of file diff --git a/client/index.js b/client/index.js index 8ef8d51..2f89015 100644 --- a/client/index.js +++ b/client/index.js @@ -4,6 +4,7 @@ const EthCrypto = require('eth-crypto'); const jaysonBrowserClient = require('jayson/lib/client/browser'); const enigma = require('enigma-js/lib/enigma-js.node'); const web3utils = require('web3-utils'); +const data = require('./data.js'); const JSON_RPC_Server='http://localhost:8080'; @@ -47,15 +48,55 @@ function getClientKeys(seed='') { return {privateKey, publicKey}; } -async function add_data(userId, data){ +async function getEncryptionKey(publicKey) { + const getEncryptionKeyResult = await new Promise((resolve, reject) => { + client.request('newTaskEncryptionKey', {userPubKey: publicKey}, + (err, response) => { + if (err) { + reject(err); + return; + } + resolve(response); + }); + }); + + const {result, id} = getEncryptionKeyResult; + const {taskPubKey, sig} = result; + // ToDo: verify signature + return taskPubKey; +} + +function encrypt(taskPubKey, privateKey, variable){ + // Generate derived key from enclave public encryption key and user's private key + const derivedKey = enigma.utils.getDerivedKey(taskPubKey, privateKey); + // Encrypt function and ABI-encoded args + return enigma.utils.encryptMessage(derivedKey, variable); +} + +function decrypt(taskPubKey, privateKey, enc_variable){ + // Generate derived key from enclave public encryption key and user's private key + const derivedKey = enigma.utils.getDerivedKey(taskPubKey, privateKey); + // Decrypt function and ABI-encoded args + let outputHex = enigma.utils.decryptMessage(derivedKey, enc_variable); + let outputStr = enigma.utils.hexToAscii(outputHex); + return JSON.parse(outputStr); +} - let {publicKey, privateKey} = getClientKeys(); - console.log(publicKey) +async function addData(userId, data){ + + let {publicKey, privateKey} = getClientKeys(); try { - const getWorkerEncryptionKeyResult = await new Promise((resolve, reject) => { - client.request('newTaskEncryptionKey', {userPubKey: publicKey}, + let taskPubKey = await getEncryptionKey(publicKey); + let encryptedUserId = encrypt(taskPubKey, privateKey, userId); + let encryptedData = encrypt(taskPubKey, privateKey, data); + + const addPersonalDataResult = await new Promise((resolve, reject) => { + client.request('addPersonalData', { + encryptedUserId: encryptedUserId, + encryptedData: encryptedData, + userPubKey: publicKey}, (err, response) => { if (err) { reject(err); @@ -65,28 +106,30 @@ async function add_data(userId, data){ }); }); - const {result, id} = getWorkerEncryptionKeyResult; - const {taskPubKey, sig} = result; - // ToDo: verify signature + const {addPersonalData} = addPersonalDataResult; - // Generate derived key from worker's encryption key and user's private key - const derivedKey = enigma.utils.getDerivedKey(taskPubKey, privateKey); - // Encrypt function and ABI-encoded args - const encryptedUserId = enigma.utils.encryptMessage(derivedKey, userId); - const encryptedData = enigma.utils.encryptMessage(derivedKey, data); - const msg = web3utils.soliditySha3( - {t: 'bytes', v: encryptedUserId}, - {t: 'bytes', v: encryptedData}, - ); + if(addPersonalData.status == 0) { + console.log('Personal data added successfully to the enclave.'); + } else { + console.log('Something went wrong. Time to debug...') + } + } catch(err) { + console.log(err); + // Or throw an error + } +} - // const a = getClientKeys(); +async function findMatch(userId){ - // console.log(a.publicKey); + let {publicKey, privateKey} = getClientKeys(); - const addPersonalDataResult = await new Promise((resolve, reject) => { - client.request('addPersonalData', { + try { + let taskPubKey = await getEncryptionKey(publicKey); + let encryptedUserId = encrypt(taskPubKey, privateKey, userId); + + const findMatchResult = await new Promise((resolve, reject) => { + client.request('findMatch', { encryptedUserId: encryptedUserId, - encryptedData: encryptedData, userPubKey: publicKey}, (err, response) => { if (err) { @@ -97,26 +140,28 @@ async function add_data(userId, data){ }); }); - const {addPersonalData} = addPersonalDataResult; + if(findMatchResult.findMatch.status == 0) { + console.log('Find Match operation successful'); - if(addPersonalData.status == 0) { - console.log('Personal data added successfully to the enclave.'); + let output = decrypt(taskPubKey, privateKey, findMatchResult.findMatch.encryptedOutput); + + if(output.length){ + console.log('Find matches:'); + console.log(output); + } else { + console.log('No matches'); + } } else { console.log('Something went wrong. Time to debug...') } - - } catch(err) { - console.log(err); - // Or Throw an error + console.log(err); + // Or throw an error } - } -add_data('myUserId', 'myDataString') - - - -let seed = ''; +addData('user1', JSON.stringify(data.DataUser1)); +addData('user2', JSON.stringify(data.DataUser2)); +findMatch('user1'); diff --git a/enclave/README.md b/enclave/README.md index 2d5c094..0f8b2e1 100644 --- a/enclave/README.md +++ b/enclave/README.md @@ -24,54 +24,28 @@ This folder contains the code that runs inside the enclave using Intel Secure Gu git clone git@github.com:enigmampc/covid-self-reporting.git ``` -2. Move into this `enclave` subfolder: +2. Install the SGX driver and SDK, as per these [instructions](https://github.com/enigmampc/EnigmaBlockchain/blob/master/docs/dev/setup-sgx.md). - ```bash - cd enclave - ``` -3. Initialize the gitsubmodule: +3. Move into the `enclave/safetrace` subfolder: ```bash - cd incubator-teaclave-sgx-sdk - git submodule init - git submodule update + cd enclave/safetrac ``` -4. Install the SGX driver and SDK, as per these [instructions](https://github.com/enigmampc/EnigmaBlockchain/blob/master/docs/dev/setup-sgx.md). - -5. A sample code is temporarily included in this repo as a starting point. You can try it out: +4. Compile the code: ```bash - cd hello-rust make - cd bin - ./app ``` - *Note: This code is very particular, and you need to run `./app` from inside the `bin` folder. If you try to run it from anywhere else (e.g. its parent folder, as in `./bin/app`), you will get the following error, because it expects another file in the same folder from where the command is run:* +5. Run the enclave code: ```bash - [-] Init Enclave Failed SGX_ERROR_ENCLAVE_FILE_ACCESS!`* - ``` - - Which should print something similar to this: - - ```bash - [+] Init Enclave Successful 2! - This is a normal world string passed into Enclave! - This is a in-Enclave Rust string! - gd: 1 0 0 1 - static: 1 eremove: 0 dyn: 0 - EDMM: 0, feature: 9007268796301311 - supported sgx - [+] say_something success... + cd bin + ./safetrace-app ``` ## ToDo -* Use the `hello-rust` folder and scaffolding for the COVID-19 code -* Write the actual Rust code for the application -* Implement Remote Attestation to provide proof of code running in legitimate enclave -* Implement data sealing and unsealing choosing the right configuration so that data is uniquely assigned to this enclave * Sign code and deploy diff --git a/enclave/hello-rust/Makefile b/enclave/hello-rust/Makefile deleted file mode 100644 index d357ade..0000000 --- a/enclave/hello-rust/Makefile +++ /dev/null @@ -1,163 +0,0 @@ -# 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. - -######## SGX SDK Settings ######## - -SGX_SDK ?= $(HOME)/.sgxsdk/sgxsdk -SGX_MODE ?= HW -SGX_ARCH ?= x64 - -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 - - -ifeq ($(SGX_DEBUG), 1) - SGX_COMMON_CFLAGS += -O0 -g -else - SGX_COMMON_CFLAGS += -O2 -endif - -######## CUSTOM Settings ######## - -CUSTOM_LIBRARY_PATH := ./lib -CUSTOM_BIN_PATH := ./bin -CUSTOM_EDL_PATH := ../incubator-teaclave-sgx-sdk/edl -CUSTOM_COMMON_PATH := ../incubator-teaclave-sgx-sdk/common - -######## EDL Settings ######## - -Enclave_EDL_Files := enclave/Enclave_t.c enclave/Enclave_t.h app/Enclave_u.c app/Enclave_u.h - -######## APP Settings ######## - -App_Rust_Flags := --release -App_SRC_Files := $(shell find app/ -type f -name '*.rs') $(shell find app/ -type f -name 'Cargo.toml') -App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include -I$(CUSTOM_EDL_PATH) -App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) - -App_Rust_Path := ./app/target/release -App_Enclave_u_Object :=app/libEnclave_u.a -App_Name := bin/app - -######## 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 -KeyExchange_Library_Name := sgx_tkey_exchange -ProtectedFs_Library_Name := sgx_tprotected_fs - -RustEnclave_C_Files := $(wildcard ./enclave/*.c) -RustEnclave_C_Objects := $(RustEnclave_C_Files:.c=.o) -RustEnclave_Include_Paths := -I$(CUSTOM_COMMON_PATH)/inc -I$(CUSTOM_EDL_PATH) -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/stlport -I$(SGX_SDK)/include/epid -I ./enclave -I./include - -RustEnclave_Link_Libs := -L$(CUSTOM_LIBRARY_PATH) -lcompiler-rt-patch -lenclave -RustEnclave_Compile_Flags := $(SGX_COMMON_CFLAGS) -nostdinc -fvisibility=hidden -fpie -fstack-protector $(RustEnclave_Include_Paths) -RustEnclave_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 -l$(Service_Library_Name) -l$(Crypto_Library_Name) $(RustEnclave_Link_Libs) -Wl,--end-group \ - -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ - -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ - -Wl,--defsym,__ImageBase=0 \ - -Wl,--gc-sections \ - -Wl,--version-script=enclave/Enclave.lds - -RustEnclave_Name := enclave/enclave.so -Signed_RustEnclave_Name := bin/enclave.signed.so - -.PHONY: all -all: $(App_Name) $(Signed_RustEnclave_Name) - -######## EDL Objects ######## - -$(Enclave_EDL_Files): $(SGX_EDGER8R) enclave/Enclave.edl - $(SGX_EDGER8R) --trusted enclave/Enclave.edl --search-path $(SGX_SDK)/include --search-path $(CUSTOM_EDL_PATH) --trusted-dir enclave - $(SGX_EDGER8R) --untrusted enclave/Enclave.edl --search-path $(SGX_SDK)/include --search-path $(CUSTOM_EDL_PATH) --untrusted-dir app - @echo "GEN => $(Enclave_EDL_Files)" - -######## App Objects ######## - -app/Enclave_u.o: $(Enclave_EDL_Files) - @$(CC) $(App_C_Flags) -c app/Enclave_u.c -o $@ - @echo "CC <= $<" - -$(App_Enclave_u_Object): app/Enclave_u.o - $(AR) rcsD $@ $^ - cp $(App_Enclave_u_Object) ./lib - -$(App_Name): $(App_Enclave_u_Object) $(App_SRC_Files) - @cd app && SGX_SDK=$(SGX_SDK) cargo build $(App_Rust_Flags) - @echo "Cargo => $@" - mkdir -p bin - cp $(App_Rust_Path)/app ./bin - -######## Enclave Objects ######## - -enclave/Enclave_t.o: $(Enclave_EDL_Files) - @$(CC) $(RustEnclave_Compile_Flags) -c enclave/Enclave_t.c -o $@ - @echo "CC <= $<" - -$(RustEnclave_Name): enclave compiler-rt enclave/Enclave_t.o - cp ../incubator-teaclave-sgx-sdk/compiler-rt/libcompiler-rt-patch.a ./lib - @$(CXX) enclave/Enclave_t.o -o $@ $(RustEnclave_Link_Flags) - @echo "LINK => $@" - -$(Signed_RustEnclave_Name): $(RustEnclave_Name) - mkdir -p bin - @$(SGX_ENCLAVE_SIGNER) sign -key enclave/Enclave_private.pem -enclave $(RustEnclave_Name) -out $@ -config enclave/Enclave.config.xml - @echo "SIGN => $@" - -.PHONY: enclave -enclave: - $(MAKE) -C ./enclave/ - -.PHONY: compiler-rt -compiler-rt: - $(MAKE) -C ../incubator-teaclave-sgx-sdk/compiler-rt/ 2> /dev/null - -.PHONY: clean -clean: - @rm -f $(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) enclave/*_t.* app/*_u.* lib/*.a - @cd enclave && cargo clean && rm -f Cargo.lock - @cd app && cargo clean && rm -f Cargo.lock - diff --git a/enclave/hello-rust/app/Cargo.toml b/enclave/hello-rust/app/Cargo.toml deleted file mode 100644 index 68243b4..0000000 --- a/enclave/hello-rust/app/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "app" -version = "1.0.0" -authors = ["The Teaclave Authors"] -build = "build.rs" - -[dependencies] -sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -sgx_urts = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } - -[patch.'https://github.com/apache/teaclave-sgx-sdk.git'] -sgx_types = { path = "../../incubator-teaclave-sgx-sdk/sgx_types" } -sgx_urts = { path = "../../incubator-teaclave-sgx-sdk/sgx_urts" } - diff --git a/enclave/hello-rust/app/build.rs b/enclave/hello-rust/app/build.rs deleted file mode 100644 index 8ec16f1..0000000 --- a/enclave/hello-rust/app/build.rs +++ /dev/null @@ -1,36 +0,0 @@ -// 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; - -fn main () { - - let sdk_dir = env::var("SGX_SDK") - .unwrap_or_else(|_| "/opt/intel/sgxsdk".to_string()); - let is_sim = env::var("SGX_MODE") - .unwrap_or_else(|_| "HW".to_string()); - - println!("cargo:rustc-link-search=native=../lib"); - println!("cargo:rustc-link-lib=static=Enclave_u"); - - println!("cargo:rustc-link-search=native={}/lib64", sdk_dir); - match is_sim.as_ref() { - "SW" => println!("cargo:rustc-link-lib=dylib=sgx_urts_sim"), - "HW" => println!("cargo:rustc-link-lib=dylib=sgx_urts"), - _ => println!("cargo:rustc-link-lib=dylib=sgx_urts"), // Treat undefined as HW - } -} diff --git a/enclave/hello-rust/app/src/main.rs b/enclave/hello-rust/app/src/main.rs deleted file mode 100644 index cdb6d39..0000000 --- a/enclave/hello-rust/app/src/main.rs +++ /dev/null @@ -1,74 +0,0 @@ -// 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.. - -extern crate sgx_types; -extern crate sgx_urts; -use sgx_types::*; -use sgx_urts::SgxEnclave; - -static ENCLAVE_FILE: &'static str = "enclave.signed.so"; - -extern { - fn say_something(eid: sgx_enclave_id_t, retval: *mut sgx_status_t, - some_string: *const u8, len: usize) -> sgx_status_t; -} - -fn init_enclave() -> SgxResult { - let mut launch_token: sgx_launch_token_t = [0; 1024]; - let mut launch_token_updated: i32 = 0; - // call sgx_create_enclave to initialize an enclave instance - // Debug Support: set 2nd parameter to 1 - let debug = 1; - let mut misc_attr = sgx_misc_attribute_t {secs_attr: sgx_attributes_t { flags:0, xfrm:0}, misc_select:0}; - SgxEnclave::create(ENCLAVE_FILE, - debug, - &mut launch_token, - &mut launch_token_updated, - &mut misc_attr) -} - -fn main() { - let enclave = match init_enclave() { - Ok(r) => { - println!("[+] Init Enclave Successful {}!", r.geteid()); - r - }, - Err(x) => { - println!("[-] Init Enclave Failed {}!", x.as_str()); - return; - }, - }; - - let input_string = String::from("This is a normal world string passed into Enclave!\n"); - let mut retval = sgx_status_t::SGX_SUCCESS; - - let result = unsafe { - say_something(enclave.geteid(), - &mut retval, - input_string.as_ptr() as * const u8, - input_string.len()) - }; - match result { - sgx_status_t::SGX_SUCCESS => {}, - _ => { - println!("[-] ECALL Enclave Failed {}!", result.as_str()); - return; - } - } - println!("[+] say_something success..."); - enclave.destroy(); -} diff --git a/enclave/hello-rust/bin/readme.txt b/enclave/hello-rust/bin/readme.txt deleted file mode 100644 index c5e82d7..0000000 --- a/enclave/hello-rust/bin/readme.txt +++ /dev/null @@ -1 +0,0 @@ -bin \ No newline at end of file diff --git a/enclave/hello-rust/enclave/Cargo.toml b/enclave/hello-rust/enclave/Cargo.toml deleted file mode 100644 index fe13dfd..0000000 --- a/enclave/hello-rust/enclave/Cargo.toml +++ /dev/null @@ -1,41 +0,0 @@ -[package] -name = "Helloworldsampleenclave" -version = "1.0.0" -authors = ["The Teaclave Authors"] - -[lib] -name = "helloworldsampleenclave" -crate-type = ["staticlib"] - -[features] -default = [] - -[target.'cfg(not(target_env = "sgx"))'.dependencies] -sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["backtrace"] } -sgx_trts = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -[patch.'https://github.com/apache/teaclave-sgx-sdk.git'] -sgx_alloc = { path = "../../incubator-teaclave-sgx-sdk/sgx_alloc" } -sgx_build_helper = { path = "../../incubator-teaclave-sgx-sdk/sgx_build_helper" } -sgx_cov = { path = "../../incubator-teaclave-sgx-sdk/sgx_cov" } -sgx_crypto_helper = { path = "../../incubator-teaclave-sgx-sdk/sgx_crypto_helper" } -sgx_libc = { path = "../../incubator-teaclave-sgx-sdk/sgx_libc" } -sgx_rand = { path = "../../incubator-teaclave-sgx-sdk/sgx_rand" } -sgx_rand_derive = { path = "../../incubator-teaclave-sgx-sdk/sgx_rand_derive" } -sgx_serialize = { path = "../../incubator-teaclave-sgx-sdk/sgx_serialize" } -sgx_serialize_derive = { path = "../../incubator-teaclave-sgx-sdk/sgx_serialize_derive" } -sgx_serialize_derive_internals = { path = "../../incubator-teaclave-sgx-sdk/sgx_serialize_derive_internals" } -sgx_tcrypto = { path = "../../incubator-teaclave-sgx-sdk/sgx_tcrypto" } -sgx_tcrypto_helper = { path = "../../incubator-teaclave-sgx-sdk/sgx_tcrypto_helper" } -sgx_tdh = { path = "../../incubator-teaclave-sgx-sdk/sgx_tdh" } -sgx_tkey_exchange = { path = "../../incubator-teaclave-sgx-sdk/sgx_tkey_exchange" } -sgx_tprotected_fs = { path = "../../incubator-teaclave-sgx-sdk/sgx_tprotected_fs" } -sgx_trts = { path = "../../incubator-teaclave-sgx-sdk/sgx_trts" } -sgx_tse = { path = "../../incubator-teaclave-sgx-sdk/sgx_tse" } -sgx_tseal = { path = "../../incubator-teaclave-sgx-sdk/sgx_tseal" } -sgx_tstd = { path = "../../incubator-teaclave-sgx-sdk/sgx_tstd" } -sgx_tunittest = { path = "../../incubator-teaclave-sgx-sdk/sgx_tunittest" } -sgx_types = { path = "../../incubator-teaclave-sgx-sdk/sgx_types" } -sgx_ucrypto = { path = "../../incubator-teaclave-sgx-sdk/sgx_ucrypto" } -sgx_unwind = { path = "../../incubator-teaclave-sgx-sdk/sgx_unwind" } -sgx_urts = { path = "../../incubator-teaclave-sgx-sdk/sgx_urts" } diff --git a/enclave/hello-rust/enclave/Enclave.config.xml b/enclave/hello-rust/enclave/Enclave.config.xml deleted file mode 100644 index ee4c3f7..0000000 --- a/enclave/hello-rust/enclave/Enclave.config.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - 0 - 0 - 0x40000 - 0x100000 - 1 - 1 - 0 - 0 - 0xFFFFFFFF - diff --git a/enclave/hello-rust/enclave/Enclave.edl b/enclave/hello-rust/enclave/Enclave.edl deleted file mode 100644 index 0263761..0000000 --- a/enclave/hello-rust/enclave/Enclave.edl +++ /dev/null @@ -1,28 +0,0 @@ -// 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. - -enclave { - from "sgx_tstd.edl" import *; - from "sgx_stdio.edl" import *; - from "sgx_backtrace.edl" import *; - from "sgx_tstdc.edl" import *; - trusted { - /* define ECALLs here. */ - - public sgx_status_t say_something([in, size=len] const uint8_t* some_string, size_t len); - }; -}; diff --git a/enclave/hello-rust/enclave/Enclave.lds b/enclave/hello-rust/enclave/Enclave.lds deleted file mode 100644 index e3d9d0e..0000000 --- a/enclave/hello-rust/enclave/Enclave.lds +++ /dev/null @@ -1,9 +0,0 @@ -enclave.so -{ - global: - g_global_data_sim; - g_global_data; - enclave_entry; - local: - *; -}; diff --git a/enclave/hello-rust/enclave/Enclave_private.pem b/enclave/hello-rust/enclave/Enclave_private.pem deleted file mode 100644 index 529d07b..0000000 --- a/enclave/hello-rust/enclave/Enclave_private.pem +++ /dev/null @@ -1,39 +0,0 @@ ------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----- diff --git a/enclave/hello-rust/enclave/Makefile b/enclave/hello-rust/enclave/Makefile deleted file mode 100644 index 386291c..0000000 --- a/enclave/hello-rust/enclave/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -# 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. -Rust_Enclave_Name := libenclave.a -Rust_Enclave_Files := $(wildcard src/*.rs) -Rust_Target_Path := $(CURDIR)/../../incubator-teaclave-sgx-sdk/xargo - -.PHONY: all - -all: $(Rust_Enclave_Name) - -$(Rust_Enclave_Name): $(Rust_Enclave_Files) -ifeq ($(XARGO_SGX), 1) - RUST_TARGET_PATH=$(Rust_Target_Path) xargo build --target x86_64-unknown-linux-sgx --release - cp ./target/x86_64-unknown-linux-sgx/release/libhelloworldsampleenclave.a ../lib/libenclave.a -else - cargo build --release - cp ./target/release/libhelloworldsampleenclave.a ../lib/libenclave.a -endif \ No newline at end of file diff --git a/enclave/hello-rust/enclave/Xargo.toml b/enclave/hello-rust/enclave/Xargo.toml deleted file mode 100644 index e54e1d7..0000000 --- a/enclave/hello-rust/enclave/Xargo.toml +++ /dev/null @@ -1,91 +0,0 @@ -[dependencies] -alloc = {} - -[dependencies.sgx_types] -path = "../../incubator-teaclave-sgx-sdk/sgx_types" -stage = 1 - -[dependencies.sgx_alloc] -path = "../../incubator-teaclave-sgx-sdk/sgx_alloc" -stage = 1 - -[dependencies.sgx_unwind] -path = "../../incubator-teaclave-sgx-sdk/sgx_unwind" -stage = 1 - -[dependencies.sgx_demangle] -path = "../../incubator-teaclave-sgx-sdk/sgx_demangle" -stage = 1 - -[dependencies.panic_abort] -path = "../../incubator-teaclave-sgx-sdk/sgx_panic_abort" -stage = 1 - -[dependencies.sgx_libc] -path = "../../incubator-teaclave-sgx-sdk/sgx_libc" -stage = 2 - -[dependencies.sgx_tkey_exchange] -path = "../../incubator-teaclave-sgx-sdk/sgx_tkey_exchange" -stage = 2 - -[dependencies.sgx_tse] -path = "../../incubator-teaclave-sgx-sdk/sgx_tse" -stage = 2 - -[dependencies.sgx_tcrypto] -path = "../../incubator-teaclave-sgx-sdk/sgx_tcrypto" -stage = 2 - -[dependencies.sgx_trts] -path = "../../incubator-teaclave-sgx-sdk/sgx_trts" -stage = 3 - -[dependencies.sgx_backtrace_sys] -path = "../../incubator-teaclave-sgx-sdk/sgx_backtrace_sys" -stage = 3 - -[dependencies.panic_unwind] -path = "../../incubator-teaclave-sgx-sdk/sgx_panic_unwind" -stage = 3 - -[dependencies.sgx_tdh] -path = "../../incubator-teaclave-sgx-sdk/sgx_tdh" -stage = 4 - -[dependencies.sgx_tseal] -path = "../../incubator-teaclave-sgx-sdk/sgx_tseal" -stage = 4 - -[dependencies.sgx_tprotected_fs] -path = "../../incubator-teaclave-sgx-sdk/sgx_tprotected_fs" -stage = 4 - -[dependencies.std] -path = "../../incubator-teaclave-sgx-sdk/xargo/sgx_tstd" -stage = 5 -features = ["backtrace"] - -[dependencies.sgx_no_tstd] -path = "../../incubator-teaclave-sgx-sdk/sgx_no_tstd" -stage = 5 - -[dependencies.sgx_rand] -path = "../../incubator-teaclave-sgx-sdk/sgx_rand" -stage = 6 - -[dependencies.sgx_serialize] -path = "../../incubator-teaclave-sgx-sdk/sgx_serialize" -stage = 6 - -[dependencies.sgx_tunittest] -path = "../../incubator-teaclave-sgx-sdk/sgx_tunittest" -stage = 6 - -[dependencies.sgx_backtrace] -path = "../../incubator-teaclave-sgx-sdk/sgx_backtrace" -stage = 7 - -[dependencies.sgx_cov] -path = "../../incubator-teaclave-sgx-sdk/sgx_cov" -stage = 7 diff --git a/enclave/hello-rust/enclave/src/lib.rs b/enclave/hello-rust/enclave/src/lib.rs deleted file mode 100644 index f661955..0000000 --- a/enclave/hello-rust/enclave/src/lib.rs +++ /dev/null @@ -1,130 +0,0 @@ -// 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.. - -#![crate_name = "helloworldsampleenclave"] -#![crate_type = "staticlib"] - -#![cfg_attr(not(target_env = "sgx"), no_std)] -#![cfg_attr(target_env = "sgx", feature(rustc_private))] - -extern crate sgx_types; -extern crate sgx_trts; -#[cfg(not(target_env = "sgx"))] -#[macro_use] -extern crate sgx_tstd as std; - -use sgx_types::*; -use sgx_types::metadata::*; -use sgx_trts::enclave; -//use sgx_trts::{is_x86_feature_detected, is_cpu_feature_supported}; -use std::string::String; -use std::vec::Vec; -use std::io::{self, Write}; -use std::slice; -use std::backtrace::{self, PrintFormat}; - -#[no_mangle] -pub extern "C" fn say_something(some_string: *const u8, some_len: usize) -> sgx_status_t { - - let str_slice = unsafe { slice::from_raw_parts(some_string, some_len) }; - let _ = io::stdout().write(str_slice); - - // A sample &'static string - let rust_raw_string = "This is a in-Enclave "; - // An array - let word:[u8;4] = [82, 117, 115, 116]; - // An vector - let word_vec:Vec = vec![32, 115, 116, 114, 105, 110, 103, 33]; - - // Construct a string from &'static string - let mut hello_string = String::from(rust_raw_string); - - // Iterate on word array - for c in word.iter() { - hello_string.push(*c as char); - } - - // Rust style convertion - hello_string += String::from_utf8(word_vec).expect("Invalid UTF-8") - .as_str(); - - // Ocall to normal world for output - println!("{}", &hello_string); - - let _ = backtrace::enable_backtrace("enclave.signed.so", PrintFormat::Full); - - let gd = enclave::SgxGlobalData::new(); - println!("gd: {} {} {} {} ", gd.get_static_tcs_num(), gd.get_eremove_tcs_num(), gd.get_dyn_tcs_num(), gd.get_tcs_max_num()); - let (static_num, eremove_num, dyn_num) = get_thread_num(); - println!("static: {} eremove: {} dyn: {}", static_num, eremove_num, dyn_num); - - unsafe { - println!("EDMM: {}, feature: {}", EDMM_supported, g_cpu_feature_indicator); - } - if is_x86_feature_detected!("sgx") { - println!("supported sgx"); - } - - sgx_status_t::SGX_SUCCESS -} - -#[link(name = "sgx_trts")] -extern { - static g_cpu_feature_indicator: uint64_t; - static EDMM_supported: c_int; -} - - -fn get_thread_num() -> (u32, u32, u32) { - let gd = unsafe { - let p = enclave::rsgx_get_global_data(); - &*p - }; - - let mut static_thread_num: u32 = 0; - let mut eremove_thread_num: u32 = 0; - let mut dyn_thread_num: u32 = 0; - let layout_table = &gd.layout_table[0..gd.layout_entry_num as usize]; - unsafe { traversal_layout(&mut static_thread_num, &mut dyn_thread_num, &mut eremove_thread_num, layout_table); } - - unsafe fn traversal_layout(static_num: &mut u32, dyn_num: &mut u32, eremove_num: &mut u32, layout_table: &[layout_t]) - { - for (i, layout) in layout_table.iter().enumerate() { - if !is_group_id!(layout.group.id as u32) { - if (layout.entry.attributes & PAGE_ATTR_EADD) != 0 { - if (layout.entry.content_offset != 0) && (layout.entry.si_flags == SI_FLAGS_TCS) { - if (layout.entry.attributes & PAGE_ATTR_EREMOVE) == 0 { - *static_num += 1; - } else { - *eremove_num += 1; - } - } - } - if (layout.entry.attributes & PAGE_ATTR_POST_ADD) != 0 { - if layout.entry.id == LAYOUT_ID_TCS_DYN as u16 { - *dyn_num += 1; - } - } - } else { - for _ in 0..layout.group.load_times { - traversal_layout(static_num, dyn_num, eremove_num, &layout_table[i - layout.group.entry_count as usize..i]) - } - } - } - } - (static_thread_num, eremove_thread_num, dyn_thread_num) -} \ No newline at end of file diff --git a/enclave/hello-rust/enclave/x86_64-unknown-linux-sgx.json b/enclave/hello-rust/enclave/x86_64-unknown-linux-sgx.json deleted file mode 100644 index 10d37a7..0000000 --- a/enclave/hello-rust/enclave/x86_64-unknown-linux-sgx.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "arch": "x86_64", - "cpu": "x86-64", - "data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128", - "dynamic-linking": true, - "env": "sgx", - "exe-allocation-crate": "alloc_system", - "executables": true, - "has-elf-tls": true, - "has-rpath": true, - "linker-flavor": "gcc", - "linker-is-gnu": true, - "llvm-target": "x86_64-unknown-linux-gnu", - "max-atomic-width": 64, - "os": "linux", - "position-independent-executables": true, - "pre-link-args": { - "gcc": [ - "-Wl,--as-needed", - "-Wl,-z,noexecstack", - "-m64" - ] - }, - "relro-level": "full", - "stack-probes": true, - "target-c-int-width": "32", - "target-endian": "little", - "target-family": "unix", - "target-pointer-width": "64", - "vendor": "mesalock" -} diff --git a/enclave/hello-rust/lib/readme.txt b/enclave/hello-rust/lib/readme.txt deleted file mode 100644 index 7951405..0000000 --- a/enclave/hello-rust/lib/readme.txt +++ /dev/null @@ -1 +0,0 @@ -lib \ No newline at end of file diff --git a/enclave/hello-rust/rust-toolchain b/enclave/hello-rust/rust-toolchain deleted file mode 100644 index 7b9d999..0000000 --- a/enclave/hello-rust/rust-toolchain +++ /dev/null @@ -1 +0,0 @@ -nightly-2020-03-12 \ No newline at end of file diff --git a/enclave/incubator-teaclave-sgx-sdk b/enclave/incubator-teaclave-sgx-sdk deleted file mode 160000 index 92e7b1c..0000000 --- a/enclave/incubator-teaclave-sgx-sdk +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 92e7b1c196a6e6025d890ebce5e63a3e1a8e98b5 diff --git a/enclave/rust-toolchain b/enclave/rust-toolchain index 7b9d999..a42a259 100644 --- a/enclave/rust-toolchain +++ b/enclave/rust-toolchain @@ -1 +1 @@ -nightly-2020-03-12 \ No newline at end of file +nightly-2019-08-01 \ No newline at end of file diff --git a/enclave/safetrace/Makefile b/enclave/safetrace/Makefile index 1b5440d..bf2012d 100644 --- a/enclave/safetrace/Makefile +++ b/enclave/safetrace/Makefile @@ -21,7 +21,9 @@ SGX_SDK ?= $(HOME)/.sgxsdk/sgxsdk # The path to the incubator-teaclave-sgx-sdk code. -SGX_SDK_RUST ?= ../incubator-teaclave-sgx-sdk/ +# SGX_SDK_RUST ?= ../incubator-teaclave-sgx-sdk/ + +SGX_SDK_RUST ?= $(HOME)/sgx SGX_MODE ?= HW @@ -78,6 +80,7 @@ Enclave_EDL_Files := enclave/Enclave_t.c enclave/Enclave_t.h app/Enclave_u.c app ######## APP Settings ######## App_Rust_Flags := --release +Rust_target_dir := release App_SRC_Files := $(shell find app/ -type f -name '*.rs') $(shell find app/ -type f -name 'Cargo.toml') # Include paths for untrusted EDL object @@ -86,7 +89,7 @@ App_Include_Paths := -I ./app -I./include -I$(SGX_SDK)/include -I$(CUSTOM_EDL_PA # C compilation flags for untrusted EDL object App_C_Flags := $(SGX_COMMON_CFLAGS) -fPIC -Wno-attributes $(App_Include_Paths) -App_Rust_Path := ./app/target/release +App_Rust_Path := ./app/target/$(Rust_target_dir) App_Enclave_u_Object :=app/libEnclave_u.a App_Name := safetrace-app @@ -160,7 +163,8 @@ enclave/Enclave_t.o: $(Enclave_EDL_Files) # Enclave DLL $(RustEnclave_Name): enclave compiler-rt $(App_Name) enclave/Enclave_t.o - cp ../incubator-teaclave-sgx-sdk/compiler-rt/libcompiler-rt-patch.a ./lib + mkdir -p $(CUSTOM_LIBRARY_PATH) + cp $(SGX_SDK_RUST)/compiler-rt/libcompiler-rt-patch.a $(CUSTOM_LIBRARY_PATH) @$(CXX) enclave/Enclave_t.o -o $@ $(RustEnclave_Link_Flags) @echo "LINK => $@" @@ -173,7 +177,7 @@ $(Signed_RustEnclave_Name): $(RustEnclave_Name) .PHONY: enclave # Invocation of Makefile in ./enclave, which builds trusted Rust static library and copies it to $(CUSTOM_LIBRARY_PATH) -enclave: +enclave: $(Enclave_EDL_Files) mkdir -p $(CUSTOM_LIBRARY_PATH) $(MAKE) -C ./enclave/ CARGO_FLAGS=$(App_Rust_Flags) Rust_target_dir=$(Rust_target_dir) @@ -184,7 +188,7 @@ compiler-rt: .PHONY: clean clean: - @rm -f $(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) enclave/*_t.* app/*_u.* lib/*.a + @rm -f $(CUSTOM_BIN_PATH)/$(App_Name) $(RustEnclave_Name) $(Signed_RustEnclave_Name) enclave/*_t.* app/*_u.* $(CUSTOM_LIBRARY_PATH)/*.a @rm -rf enclave/enigma-types.h app/enigma-types.h @cd enclave && cargo clean && rm -f Cargo.lock @cd app && cargo clean && rm -f Cargo.lock diff --git a/enclave/safetrace/app/Cargo.toml b/enclave/safetrace/app/Cargo.toml index 007cf63..970d16a 100644 --- a/enclave/safetrace/app/Cargo.toml +++ b/enclave/safetrace/app/Cargo.toml @@ -5,8 +5,12 @@ authors = ["The Teaclave Authors"] build = "build.rs" [dependencies] -sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -sgx_urts = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } +sgx_types = { git = "https://github.com/baidu/rust-sgx-sdk.git", rev = "v1.0.9" } +sgx_urts = { git = "https://github.com/baidu/rust-sgx-sdk.git", rev = "v1.0.9" } +enigma-types = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop", features = ["std"] } +enigma-tools-u = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop" } +enigma-tools-m = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop" } +enigma-crypto = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop" } futures = { version = "0.1.25", default-features = false } tokio-zmq = "0.9.0" @@ -15,8 +19,11 @@ failure = "0.1.3" serde = { version = "1.0", default-features = false, features=["serde_derive"] } serde_json = "1.0" serde_repr = "0.1" -rustc-hex = "1.0.0" # 2.0.1? rmp-serde = "0.14.0" +rustc-hex = "1.0.0" +lazy_static = "1.3.0" +log = "0.4.6" + [patch.'https://github.com/apache/teaclave-sgx-sdk.git'] sgx_types = { path = "../../incubator-teaclave-sgx-sdk/sgx_types" } diff --git a/enclave/safetrace/app/src/common_u/errors.rs b/enclave/safetrace/app/src/common_u/errors.rs index 688138d..fb67a52 100644 --- a/enclave/safetrace/app/src/common_u/errors.rs +++ b/enclave/safetrace/app/src/common_u/errors.rs @@ -1,5 +1,4 @@ #![allow(dead_code)] -use crate::enigma_types::types::*; use sgx_types::*; use std::fmt; use failure::Error; @@ -82,6 +81,6 @@ impl fmt::Display for DBErrKind { #[derive(Fail, Debug)] #[fail(display = "Error inside the Enclave = ({:?})", err)] pub struct EnclaveFailError { - pub err: EnclaveReturn, + pub err: enigma_types::EnclaveReturn, pub status: sgx_status_t, -} +} \ No newline at end of file diff --git a/enclave/safetrace/app/src/enigma_types/hash.rs b/enclave/safetrace/app/src/enigma_types/hash.rs deleted file mode 100644 index cb56f36..0000000 --- a/enclave/safetrace/app/src/enigma_types/hash.rs +++ /dev/null @@ -1,106 +0,0 @@ -//! # Hash Module -//! This module provides a struct meant for containing Hashes (Kecack256 or Sha256). - -use core::ops::{Deref, DerefMut}; -use rustc_hex::{FromHex, FromHexError}; -use arrayvec::ArrayVec; -use crate::serde::{Serialize, Deserialize}; - -/// This struct is basically a wrapper over `[u8; 32]`, and is meant to be returned from whatever hashing functions we use. -/// `#[repr(C)]` is a Rust feature which makes the struct be aligned just like C structs. -/// See [`Repr(C)`][https://doc.rust-lang.org/nomicon/other-reprs.html] -#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord, Hash, Default)] -#[serde(crate = "crate::serde")] -#[repr(C)] -pub struct Hash256([u8; 32]); - - -impl Hash256 { - /// This method exposes rust's built in [`copy_from_slice`][https://doc.rust-lang.org/std/primitive.slice.html#method.copy_from_slice] - /// Copies the elements from `src` into `self`. - /// - /// The length of `src` must be the same as `self`. - /// - /// # Panics - /// - /// This function will panic if the two slices have different lengths. - /// - /// This might not be needed since we implement `Deref` and `DerefMut` for the inner array. - pub fn copy_from_slice(&mut self, src: &[u8]) { - self.0.copy_from_slice(src) - } - - /// This function converts a hex string into `Hash256` type. - /// the hex must not contain `0x` (as is usually the case in hexs in rust) - /// if the hex length isn't 64 (which will be converted into the 32 bytes) it will return an error. - pub fn from_hex(hex: &str) -> Result { - if hex.len() != 64 { - return Err(FromHexError::InvalidHexLength); - } - let hex_vec: ArrayVec<[u8; 32]> = hex.from_hex()?; - let mut result = Self::default(); - result.copy_from_slice(&hex_vec); - Ok(result) - } - - /// Checks if the struct contains only zeroes or not. - pub fn is_zero(&self) -> bool { - self.0 == [0u8;32] - } -} - - -impl From<[u8; 32]> for Hash256 { - fn from(arr: [u8; 32]) -> Self { - Hash256(arr) - } -} - -impl Into<[u8; 32]> for Hash256 { - fn into(self) -> [u8; 32] { - self.0 - } -} - -impl Deref for Hash256 { - type Target = [u8; 32]; - - fn deref(&self) -> &[u8; 32] { - &self.0 - } -} - -impl DerefMut for Hash256 { - fn deref_mut(&mut self) -> &mut [u8; 32] { - &mut self.0 - } -} - -impl AsRef<[u8]> for Hash256 { - fn as_ref(&self) -> &[u8] { - &self.0 - } -} - -impl AsMut<[u8]> for Hash256 { - fn as_mut(&mut self) -> &mut [u8] { - &mut self.0 - } -} - -#[cfg(test)] -mod test { - use super::Hash256; - #[test] - fn test_hex_succeed() { - let a = "0101010101010101010101010101010101010101010101010101010101010101"; - Hash256::from_hex(&a).unwrap(); - } - - #[should_panic] - #[test] - fn test_hex_long() { - let a = "02020202020202020202020202020202020202020202020202020202020202020202024444020202020202"; - Hash256::from_hex(&a).unwrap(); - } -} \ No newline at end of file diff --git a/enclave/safetrace/app/src/enigma_types/lib.rs b/enclave/safetrace/app/src/enigma_types/lib.rs deleted file mode 100644 index 99b9a31..0000000 --- a/enclave/safetrace/app/src/enigma_types/lib.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] -#![deny(unused_extern_crates, missing_docs, warnings)] -//! # Enigma Types -//! This library is meant to supply all the types that are specific to our protocol.
-//! Inside of this library I abstracted the std as `localstd` so that you can use it without knowing if it's `sgx_tstd` or regular std. -//! *But* Unlike other crates this isn't just abstracting 2 different std's, -//! but this crate is expected to work even without std at all(except some parts maybe). -//! -//! in the `build.rs` I use `cbindgen` to auto generate `enigma-types.h` header so it can be included into the edl. -//! that way we can pass rust structs through the SGX bridge(which is C) -//! -//! This crate is Rust 2018 Edition, -//! meaning there's no `extern crate` and `use` statements need to start with `crate`/`self`/`super`. - - -pub mod traits; -mod types; -mod hash; - -#[cfg(all(feature = "sgx", not(feature = "std")))] -use serde_sgx as serde; - -#[cfg(not(feature = "sgx"))] -use serde_std as serde; - -use crate::traits::SliceCPtr; -pub use crate::types::*; - -/// This is a bit safer wrapper of [`core::ptr::copy_nonoverlapping`] -/// it checks that the src len is at least as big as `count` otherwise it will panic. -/// *and* it uses [`SliceCPtr`](crate::traits::SliceCPtr) trait to pass a C compatible pointer. -pub unsafe fn write_ptr(src: &[T], dst: *mut T, count: usize) { - if src.len() > count { - unimplemented!() - } - core::ptr::copy_nonoverlapping(src.as_c_ptr(), dst, src.len()); -} diff --git a/enclave/safetrace/app/src/enigma_types/mod.rs b/enclave/safetrace/app/src/enigma_types/mod.rs deleted file mode 100644 index 0bc8eda..0000000 --- a/enclave/safetrace/app/src/enigma_types/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod types; -pub mod traits; diff --git a/enclave/safetrace/app/src/enigma_types/traits.rs b/enclave/safetrace/app/src/enigma_types/traits.rs deleted file mode 100644 index c9f5b7d..0000000 --- a/enclave/safetrace/app/src/enigma_types/traits.rs +++ /dev/null @@ -1,45 +0,0 @@ -//! # Traits module -//! This module should provide low level traits that are required on both sides of the SGX. -//! right now it only contains the [`SliceCPtr`] trait which is used to *always* provide valid C pointers. - -static EMPTY: [u8; 1] = [0]; - -/// This trait provides an interface into `C` like pointers. -/// in Rust if you try to get a pointer to an empty vector you'll get: -/// 0x0000000000000001 OR 0x0000000000000000, although bear in mind this *isn't* officially defined. -/// this behavior is UB in C's `malloc`, passing an invalid pointer with size 0 to `malloc` is implementation defined. -/// in the case of Intel's + GCC what we observed is a Segmentation Fault. -/// this is why if the vec/slice is empty we use this trait to pass a pointer to a stack allocated static `[0]` array. -/// this will make the pointer valid, and when the len is zero -/// `malloc` won't allocate anything but also won't produce a SegFault -pub trait SliceCPtr { - /// The Target for the trait. - /// this trait can't be generic because it should only be implemented once per type - /// (See [Associated Types][https://doc.rust-lang.org/rust-by-example/generics/assoc_items/types.html]) - type Target; - /// This function is what will produce a valid C pointer to the target - /// even if the target is 0 sized (and rust will produce a C *invalid* pointer for it ) - fn as_c_ptr(&self) -> *const Self::Target; -} - -impl SliceCPtr for [T] { - type Target = T; - fn as_c_ptr(&self) -> *const Self::Target { - if self.is_empty() { - EMPTY.as_ptr() as *const _ - } else { - self.as_ptr() - } - } -} - -impl SliceCPtr for str { - type Target = u8; - fn as_c_ptr(&self) -> *const Self::Target { - if self.is_empty() { - EMPTY.as_ptr() as *const _ - } else { - self.as_ptr() - } - } -} diff --git a/enclave/safetrace/app/src/enigma_types/types.rs b/enclave/safetrace/app/src/enigma_types/types.rs deleted file mode 100644 index e76e6d6..0000000 --- a/enclave/safetrace/app/src/enigma_types/types.rs +++ /dev/null @@ -1,256 +0,0 @@ -//! # Types module -//! This module should provide low level types, enums and structures that are required on both sides of the SGX. -//! All enums and structures should have `#[repr(C)]` on them so they would be aligned just like in C -//! See [`Repr(C)`][https://doc.rust-lang.org/nomicon/other-reprs.html] -//! -//! Any new type here that should pass through the edl should be added into the [`build.rs]` file, -//! so it will put it into the auto generated C header. -//! -//! Note: Please use the right types even if they're only aliases right now, -//! this helps both for readability and if in the future we decide to change the alias. - -// use core::{fmt, mem, ptr, default::Default}; - -/// The size of the symmetric 256 bit key we use for encryption (in bytes). -pub const SYMMETRIC_KEY_SIZE: usize = 256 / 8; -/// symmetric key we use for encryption. -pub type SymmetricKey = [u8; SYMMETRIC_KEY_SIZE]; -/// StateKey is the key used for state encryption. -pub type StateKey = SymmetricKey; -/// DHKey is the key that results from the ECDH [`enigma_crypto::KeyPair::derive_key`](../replace_me) -pub type DhKey = SymmetricKey; - -/// PubKey is a public key that is used for ECDSA signing. -pub type PubKey = [u8; 64]; - - -/// This enum is used to return from an ecall/ocall to represent if the operation was a success and if not then what was the error. -/// The goal is to not reveal anything sensitive -/// `#[repr(C)]` is a Rust feature which makes the struct be aligned just like C structs. -/// See [`Repr(C)`][https://doc.rust-lang.org/nomicon/other-reprs.html] -#[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum EnclaveReturn { - /// Success, the function returned without any failure. - Success, - /// TaskFailure, the task(Deploy/Compute) has failed - TaskFailure, - /// KeysError, There's a key missing or failed to derive a key. - KeysError, - /// Failure in Encryption, couldn't decrypt the variable / failed to encrypt the results. - EncryptionError, - // TODO: I'm not sure this error is used anywhere. - /// SigningError, for some reason it failed on signing the results. - SigningError, - // TODO: Also don't think this is needed. - /// RecoveringError, Something failed in recovering the public key. - RecoveringError, - ///PermissionError, Received a permission error from an ocall, (i.e. opening the signing keys file or something like that) - PermissionError, - /// SgxError, Error that came from the SGX specific stuff (i.e DRAND, Sealing etc.) - SgxError, - /// StateError, an Error in the State. (i.e. failed applying delta, failed deserializing it etc.) - StateError, - /// OcallError, an error from an ocall. - OcallError, - /// OcallDBError, an error from the Database in the untrusted part, couldn't get/save something. - OcallDBError, - /// MessagingError, a message that received couldn't be processed (i.e. KM Message, User Key Exchange etc.) - MessagingError, - /// WorkerAuthError, Failed to authenticate the worker, this is specific to the KM node. - WorkerAuthError, - // TODO: should consider merging with a different error. - /// Missing StateKeys in the KM node. - KeyProvisionError, - /// Something went really wrong. - Other -} - - -/// This struct is basically some sort of a boolean that says if an operation was a success or a failure. -#[repr(C)] -#[derive(Debug, PartialEq)] -pub enum ResultStatus { - /// Ok = Success = 1. - Ok = 1, - /// Failure = Error = 0. - Failure = 0, -} - - -/// This struct is what returned from a Deploy/Compute ecall, it contains all the needed data. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct ExecuteResult { - /// A pointer to the output of the execution using [`ocall_save_to_memory`](../replace_me) (on the untrusted stack) - pub output: *const u8, - /// A pointer to the resulting delta using [`ocall_save_to_memory`](../replace_me) (on the untrusted stack) - pub delta_ptr: *const u8, - /// The delta index number. - pub delta_index: u32, - /// A pointer to the Ethereum payload using [`ocall_save_to_memory`](../replace_me) (on the untrusted stack) - pub ethereum_payload_ptr: *const u8, - /// The ethereum address that the payload belongs to. - pub ethereum_address: [u8; 20], - /// A signature by the enclave on all of the results. - pub signature: [u8; 65], - /// The gas used by the execution. - pub used_gas: u64, -} - -// /// This struct is a wrapper to a raw pointer. -// /// when you pass a pointer through the SGX bridge(EDL) the SGX Edger8r will copy the data that it's pointing to -// /// using `memalloc` and `memset` to the other side of the bridge, then it changes the pointer to point to the new data. -// /// -// /// So this struct is needed if you want to pass a pointer from one side to the other while the pointer still points to the right locaiton. -// /// -// /// Say you want to give the enclave a DB on the untrusted, so that the enclave can then pass that pointer to an ocall. -// /// This will let you do it without the Edger8r messing with the pointer. -// /// -// /// And I tried to add a mutability bool to make it a little more safe by giving you a pointer based on the original mutability. -// #[repr(C)] -// #[derive(Clone, Copy, Debug)] -// pub struct RawPointer { -// ptr: *const u8, -// _mut: bool -// } - -// impl RawPointer { -// /// Creates a new RawPointer wrapper. -// /// it will auto cast the reference into a raw pointer. -// pub unsafe fn new(reference: &T) -> Self { -// RawPointer { ptr: reference as *const T as *const u8, _mut: false } -// } - -// /// Creates a new mutable RawPointer wrapper. -// /// This is needed if when you unwrap this you want a mutable pointer. -// pub unsafe fn new_mut(reference: &mut T) -> Self { -// RawPointer { ptr: reference as *mut T as *const u8, _mut: true } -// } - -// /// This will return the underlying const raw pointer. -// pub fn get_ptr(&self) -> *const T { -// self.ptr as *const T -// } - -// /// this will return a Result and if the RawPointer was created with `new_mut` -// /// it Will return `Ok` with the underlying mut raw pointer. -// /// if the struct was created with just `new` it will return `Err`. -// pub fn get_mut_ptr(&self) -> Result<*mut T, &'static str> { -// if !self._mut { -// Err("This DoublePointer is not mutable") -// } else { -// Ok(self.ptr as *mut T) -// } -// } - -// /// This will unsafely cast the underlying pointer back into a reference. -// pub unsafe fn get_ref(&self) -> &T { -// &*(self.ptr as *const T) -// } - -// /// This will unsafely cast the underlying pointer back into a mut pointer. -// /// it will return a result and have the same rules as [`get_mut_ptr`] -// /// -// /// [`get_mut_ptr`]: #method.get_mut_ptr -// pub unsafe fn get_mut_ref(&self) -> Result<&mut T, &'static str> { -// if !self._mut { -// Err("This DoublePointer is not mutable") -// } else { -// Ok(&mut *(self.ptr as *mut T) ) -// } -// } - - -// } - -impl From for ResultStatus { - fn from(i: bool) -> Self { - if i { - ResultStatus::Ok - } else { - ResultStatus::Failure - } - } -} - -// impl Default for ExecuteResult { -// fn default() -> ExecuteResult { -// ExecuteResult { -// output: ptr::null(), -// delta_ptr: ptr::null(), -// ethereum_payload_ptr: ptr::null(), -// .. unsafe { mem::zeroed() } -// } -// } -// } - -// impl fmt::Debug for ExecuteResult { -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// let mut debug_trait_builder = f.debug_struct("ExecuteResult"); -// debug_trait_builder.field("output", &(self.output)); -// debug_trait_builder.field("delta_ptr", &(self.delta_ptr)); -// debug_trait_builder.field("delta_index", &(self.delta_index)); -// debug_trait_builder.field("ethereum_payload_ptr", &(self.ethereum_payload_ptr)); -// debug_trait_builder.field("ethereum_address", &(self.ethereum_address)); -// debug_trait_builder.field("signature", &(&self.signature[..])); -// debug_trait_builder.field("used_gas", &(self.used_gas)); -// debug_trait_builder.finish() -// } -// } - -impl Default for EnclaveReturn { - fn default() -> EnclaveReturn { EnclaveReturn::Success } -} - -// impl fmt::Display for EnclaveReturn { -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// use self::EnclaveReturn::*; -// let p = match *self { -// Success => "EnclaveReturn: Success", -// TaskFailure => "EnclaveReturn: Task failure", -// KeysError => "EnclaveReturn: KeysError", -// EncryptionError => "EnclaveReturn: EncryptionError", -// SigningError => "EnclaveReturn: SigningError", -// RecoveringError => "EnclaveReturn: RecoveringError", -// PermissionError => "EnclaveReturn: PermissionError", -// SgxError => "EnclaveReturn: SgxError", -// StateError => "EnclaveReturn: StateError", -// OcallError => "EnclaveReturn: OcallError", -// OcallDBError => "EnclaveReturn: OcallDBError", -// MessagingError => "EnclaveReturn: MessagingError", -// WorkerAuthError => "EnclaveReturn: WorkerAuthError", -// KeyProvisionError => "EnclaveReturn: KeyProvisionError", -// Other => "EnclaveReturn: Other", -// }; -// write!(f, "{}", p) -// } -// } - - -/// This trait will convert a Result into EnclaveReturn. -/// -/// I used this because there's a problem. -/// we want to convert [`enigma_tools_t::common::errors::EnclaveError`](../replace_me) into [`EnclaveReturn`] to return it back through the EDL. -/// *but* in this module we can't impl [`From`](core::convert::From) from `EnclaveError` to `EnclaveReturn` because this crate is `std` pure -/// so it doesn't have access to `enigma_tools_t`. -/// And we can't implement this as `Into for Result<(), EnclaveError>` in `enigma_tools_t` -/// because in rust you can't implement an imported trait(`From`/`Into`) on a type you imported (`Result`). -/// -/// So my solution was to declare a new trait, and to implement [`core::convert::From`] on whatever implements my trait through generics. -/// that way all we need is to implement `ResultToEnclaveReturn` on `EnclaveError` and it will auto generate a `From` impl for it. -/// -/// And if the Result is `Ok` it will return `EnclaveReturn::Success` and if `Err` it will convert using this trait. -pub trait ResultToEnclaveReturn { - /// Should return a EnclaveReturn while consuming self. - fn into_enclave_return(self) -> EnclaveReturn; -} - -impl From> for EnclaveReturn { - fn from(res: Result<(), T>) -> Self { - match res { - Ok(()) => EnclaveReturn::Success, - Err(e) => ResultToEnclaveReturn::into_enclave_return(e), - } - } -} diff --git a/enclave/safetrace/app/src/esgx/equote.rs b/enclave/safetrace/app/src/esgx/equote.rs new file mode 100644 index 0000000..6a89253 --- /dev/null +++ b/enclave/safetrace/app/src/esgx/equote.rs @@ -0,0 +1,80 @@ +use common_u::errors; +use failure::Error; +use sgx_types::*; +use std::str; +use crate::ocalls_u::ecall_get_signing_address; +// this struct is returned during the process registration back to the surface. +// quote: the base64 encoded quote +// address : the clear text public key for ecdsa signing and registration +#[derive(Serialize, Deserialize, Debug)] +pub struct GetRegisterResult { + pub errored: bool, + pub quote: String, + pub address: String, +} + +// wrapper function for getting the enclave public sign key (the one attached with produce_quote()) +//#[logfn(TRACE)] +pub fn get_register_signing_address(eid: sgx_enclave_id_t) -> Result<[u8; 20], Error> { + let mut address = [0u8; 20]; + let status = unsafe { ecall_get_signing_address(eid, &mut address) }; + if status == sgx_status_t::SGX_SUCCESS { + Ok(address) + } else { + Err(errors::GetRegisterKeyErr { status, message: String::from("error in get_register_signing_key") }.into()) + } +} + + +#[cfg(test)] +mod test { + use crate::esgx::general::init_enclave_wrapper; + use enigma_tools_u::attestation_service::{self, service::AttestationService}; + use enigma_tools_u::esgx::equote::retry_quote; + + const SPID: &str = "B0335FD3BC1CCA8F804EB98A6420592D"; // Enigma's SPID + + #[test] + fn test_produce_quote() { + // initiate the enclave + let enclave = init_enclave_wrapper().unwrap(); + // produce a quote + + let tested_encoded_quote = match retry_quote(enclave.geteid(), &SPID, 18) { + Ok(encoded_quote) => encoded_quote, + Err(e) => { + println!("[-] Produce quote Err {}, {}", e.as_fail(), e.backtrace()); + assert_eq!(0, 1); + return; + } + }; + println!("-------------------------"); + println!("{}", tested_encoded_quote); + println!("-------------------------"); + enclave.destroy(); + assert!(!tested_encoded_quote.is_empty()); + //assert_eq!(real_encoded_quote, tested_encoded_quote); + } + + #[test] + fn test_produce_and_verify_qoute() { + let enclave = init_enclave_wrapper().unwrap(); + let quote = retry_quote(enclave.geteid(), &SPID, 18).unwrap(); + let service = AttestationService::new(attestation_service::constants::ATTESTATION_SERVICE_URL); + let as_response = service.get_report(quote).unwrap(); + + assert!(as_response.result.verify_report().unwrap()); + } + + #[test] + fn test_signing_key_against_quote() { + let enclave = init_enclave_wrapper().unwrap(); + let quote = retry_quote(enclave.geteid(), &SPID, 18).unwrap(); + let service = AttestationService::new(attestation_service::constants::ATTESTATION_SERVICE_URL); + let as_response = service.get_report(quote).unwrap(); + assert!(as_response.result.verify_report().unwrap()); + let key = super::get_register_signing_address(enclave.geteid()).unwrap(); + let quote = as_response.get_quote().unwrap(); + assert_eq!(key, "e.report_body.report_data[..20]); + } +} diff --git a/enclave/safetrace/app/src/esgx/general.rs b/enclave/safetrace/app/src/esgx/general.rs new file mode 100644 index 0000000..7df0919 --- /dev/null +++ b/enclave/safetrace/app/src/esgx/general.rs @@ -0,0 +1,18 @@ +use enigma_tools_u::{self, esgx::general::storage_dir}; +use sgx_types::*; +use sgx_urts::SgxEnclave; +use std::fs; +//use log; + +static ENCLAVE_FILE: &'static str = "../bin/enclave.signed.so"; +pub static ENCLAVE_DIR: &'static str = ".enigma"; + +//#[logfn(INFO)] +pub fn init_enclave_wrapper() -> SgxResult { + // Create a folder for storage (Sealed, etc) + // If the storage folder is inaccessible, the enclave would not be able to seal info + let storage_path = storage_dir(ENCLAVE_DIR).unwrap(); + fs::create_dir_all(&storage_path).map_err(|e| { format_err!("Unable to create storage directory {}: {}", storage_path.display(), e) }).unwrap(); + + enigma_tools_u::esgx::init_enclave(&ENCLAVE_FILE) +} diff --git a/enclave/safetrace/app/src/esgx/mod.rs b/enclave/safetrace/app/src/esgx/mod.rs new file mode 100644 index 0000000..337679c --- /dev/null +++ b/enclave/safetrace/app/src/esgx/mod.rs @@ -0,0 +1,2 @@ +pub mod equote; +pub mod general; diff --git a/enclave/safetrace/app/src/keys_u.rs b/enclave/safetrace/app/src/keys_u.rs index 2217c69..ce9465e 100644 --- a/enclave/safetrace/app/src/keys_u.rs +++ b/enclave/safetrace/app/src/keys_u.rs @@ -1,7 +1,8 @@ use crate::common_u::errors::EnclaveFailError; use failure::Error; use sgx_types::{sgx_enclave_id_t, sgx_status_t}; -use crate::enigma_types::types::{EnclaveReturn}; +use enigma_types::{EnclaveReturn}; + extern { pub fn ecall_get_user_key( diff --git a/enclave/safetrace/app/src/main.rs b/enclave/safetrace/app/src/main.rs index 2b2fb9e..155694b 100644 --- a/enclave/safetrace/app/src/main.rs +++ b/enclave/safetrace/app/src/main.rs @@ -30,26 +30,28 @@ extern crate serde_repr; pub extern crate serde_json; extern crate rmp_serde; extern crate rustc_hex as hex; +#[macro_use] +pub extern crate log; use sgx_types::*; use sgx_urts::SgxEnclave; -pub mod enigma_types; +extern crate enigma_types; +pub extern crate enigma_tools_u; +extern crate enigma_tools_m; +extern crate enigma_crypto; + pub mod common_u; pub mod keys_u; pub mod networking; pub mod ocalls_u; +pub mod esgx; -use networking::{ipc_listener, IpcListener}; use futures::Future; -pub use ocalls_u::{ocall_save_to_memory}; +use networking::{ipc_listener, IpcListener}; static ENCLAVE_FILE: &'static str = "enclave.signed.so"; -extern { - fn say_something(eid: sgx_enclave_id_t, retval: *mut sgx_status_t, - some_string: *const u8, len: usize) -> sgx_status_t; -} fn init_enclave() -> SgxResult { let mut launch_token: sgx_launch_token_t = [0; 1024]; @@ -79,8 +81,10 @@ fn main() { let server = IpcListener::new(&format!("tcp://*:5552")); + const SPID: &str = "B0335FD3BC1CCA8F804EB98A6420592D"; + server - .run(move |multi| ipc_listener::handle_message(multi, &format!("SPID"), enclave.geteid(), 1)) + .run(move |multi| ipc_listener::handle_message(multi, SPID, enclave.geteid(), 1)) //.run(move |multi| ipc_listener::handle_message(multi, &opt.spid, eid, opt.retries)) // .run(|mul| { diff --git a/enclave/safetrace/app/src/networking/ipc_listener.rs b/enclave/safetrace/app/src/networking/ipc_listener.rs index 2fe52cb..7ee785f 100644 --- a/enclave/safetrace/app/src/networking/ipc_listener.rs +++ b/enclave/safetrace/app/src/networking/ipc_listener.rs @@ -1,5 +1,5 @@ use crate::networking::messages::*; -use sgx_types::{sgx_enclave_id_t, sgx_status_t}; +use sgx_types::sgx_enclave_id_t; use futures::{Future, Stream}; use std::sync::Arc; use tokio_zmq::prelude::*; @@ -49,22 +49,41 @@ pub fn handle_message(request: Multipart, spid: &str, eid: sgx_enclave_id_t, ret pub(self) mod handling { use crate::networking::messages::*; use crate::keys_u; + use crate::esgx::equote; use failure::Error; use sgx_types::{sgx_enclave_id_t, sgx_status_t}; use hex::{FromHex, ToHex}; use std::str; + use rmp_serde::Deserializer; use serde::Deserialize; use serde_json::Value; + use enigma_tools_u::{ + esgx::equote as equote_tools, + attestation_service::{service::AttestationService, constants::ATTESTATION_SERVICE_URL}, + }; + use enigma_types::{EnclaveReturn}; + extern { - fn ecall_add_personal_data( - eid: sgx_enclave_id_t, - ret: *mut sgx_status_t, - encryptedUserId: *const u8, - encryptedUserId_len: usize, - encryptedData: *const u8, - encryptedData_len: usize, - userPubKey: &[u8; 64]) -> sgx_status_t; + fn ecall_add_personal_data( + eid: sgx_enclave_id_t, + ret: *mut sgx_status_t, + encryptedUserId: *const u8, + encryptedUserId_len: usize, + encryptedData: *const u8, + encryptedData_len: usize, + userPubKey: &[u8; 64]) -> sgx_status_t; + } + + extern { + fn ecall_find_match( + eid: sgx_enclave_id_t, + ret: *mut sgx_status_t, + encryptedUserId: *const u8, + encryptedUserId_len: usize, + userPubKey: &[u8; 64], + serialized_ptr: *mut u64 + ) -> sgx_status_t; } type ResponseResult = Result; @@ -74,8 +93,31 @@ pub(self) mod handling { pubkey: Vec } + //#[logfn(TRACE)] pub fn get_enclave_report(eid: sgx_enclave_id_t, spid: &str, retries: u32) -> ResponseResult { - let result = IpcResults::EnclaveReport { spid: spid.to_string() }; + + let signing_key = equote::get_register_signing_address(eid)?; + + let enc_quote = equote_tools::retry_quote(eid, spid, 18)?; + println!("{:?}", enc_quote); + + + // *Important* `option_env!()` runs on *Compile* time. + // This means that if you want Simulation mode you need to run `export SGX_MODE=SW` Before compiling. + let (signature, report_hex) = if option_env!("SGX_MODE").unwrap_or_default() == "SW" { // Simulation Mode + let report = enc_quote.as_bytes().to_hex(); + let sig = String::new(); + (sig, report) + } else { // Hardware Mode + let service: AttestationService = AttestationService::new_with_retries(ATTESTATION_SERVICE_URL, retries); + let response = service.get_report(enc_quote)?; + let report = response.result.report_string.as_bytes().to_hex(); + let sig = response.result.signature; + (sig, report) + }; + + let result = IpcResults::EnclaveReport { signing_key: signing_key.to_hex(), report: report_hex, signature }; + Ok(IpcResponse::GetEnclaveReport { result }) } @@ -87,41 +129,32 @@ pub(self) mod handling { let (msg, sig) = keys_u::get_user_key(eid, &user_pubkey)?; - // Enigma-core implementation used MessagePack, but rmp-serde is not available - // so replaced MessagePack serialization with plain JSON serialization - //let mut des = Deserializer::new(&msg[..]); - //let res: Value = Deserialize::deserialize(&mut des).unwrap(); - //let pubkey = serde_json::from_value::>(res["pubkey"].clone())?; - //let pubkey = serde_json::from_slice::>(&msg)?; - let res = match str::from_utf8(&msg) { - Ok(v) => v, - Err(e) => panic!("Invalid UTF-8 sequence: {}", e), - }; + let mut des = Deserializer::new(&msg[..]); + let res: Value = Deserialize::deserialize(&mut des).unwrap(); + let pubkey = serde_json::from_value::>(res["pubkey"].clone())?; - let pubkey: PubkeyResult = serde_json::from_str(res)?; - - let result = IpcResults::DHKey {taskPubKey: pubkey.pubkey.to_hex(), sig: sig.to_hex() }; + let result = IpcResults::DHKey {taskPubKey: pubkey.to_hex(), sig: sig.to_hex() }; Ok(IpcResponse::NewTaskEncryptionKey { result }) } // TODO //#[logfn(DEBUG)] - pub fn add_personal_data( input: IpcInput, eid: sgx_enclave_id_t) -> ResponseResult { + pub fn add_personal_data(input: IpcInputData, eid: sgx_enclave_id_t) -> ResponseResult { let mut ret = sgx_status_t::SGX_SUCCESS; - let encryptedUserId = input.encryptedUserId.from_hex()?; - let encryptedData = input.encryptedData.from_hex()?; - let mut userPubKey = [0u8; 64]; - userPubKey.clone_from_slice(&input.userPubKey.from_hex()?); + let encrypted_userid = input.encrypted_userid.from_hex()?; + let encrypted_data = input.encrypted_data.from_hex()?; + let mut user_pub_key = [0u8; 64]; + user_pub_key.clone_from_slice(&input.user_pub_key.from_hex()?); unsafe { ecall_add_personal_data(eid, &mut ret as *mut sgx_status_t, - encryptedUserId.as_ptr() as * const u8, - encryptedUserId.len(), - encryptedData.as_ptr() as * const u8, - encryptedData.len(), - &userPubKey) }; + encrypted_userid.as_ptr() as * const u8, + encrypted_userid.len(), + encrypted_data.as_ptr() as * const u8, + encrypted_data.len(), + &user_pub_key) }; let result = IpcResults::AddPersonalData { status: Status::Passed }; Ok(IpcResponse::AddPersonalData { result }) @@ -129,8 +162,29 @@ pub(self) mod handling { // TODO //#[logfn(DEBUG)] - pub fn find_match( input: IpcInput, eid: sgx_enclave_id_t) -> ResponseResult { - let result = IpcResults::FindMatch { status: Status::Passed }; + pub fn find_match( input: IpcInputMatch, eid: sgx_enclave_id_t) -> ResponseResult { + + let mut ret = sgx_status_t::SGX_SUCCESS; + let mut serialized_ptr = 0u64; + let encrypted_userid = input.encrypted_userid.from_hex()?; + let mut user_pub_key = [0u8; 64]; + user_pub_key.clone_from_slice(&input.user_pub_key.from_hex()?); + + let status = unsafe { + ecall_find_match( + eid, + &mut ret as *mut sgx_status_t, + encrypted_userid.as_ptr() as * const u8, + encrypted_userid.len(), + &user_pub_key, + &mut serialized_ptr as *mut u64 + ) + }; + + let box_ptr = serialized_ptr as *mut Box<[u8]>; + let part = unsafe { Box::from_raw(box_ptr) }; + + let result = IpcResults::FindMatch { status: Status::Passed, encryptedOutput: part.to_hex()}; Ok(IpcResponse::FindMatch { result }) } diff --git a/enclave/safetrace/app/src/networking/messages.rs b/enclave/safetrace/app/src/networking/messages.rs index 843dcda..add5094 100644 --- a/enclave/safetrace/app/src/networking/messages.rs +++ b/enclave/safetrace/app/src/networking/messages.rs @@ -1,8 +1,6 @@ use serde_json; use serde_repr::{Serialize_repr, Deserialize_repr}; use zmq::Message; -use failure::Error; -use hex::ToHex; // These attributes enable the status to be casted as an i8 object as well @@ -13,6 +11,14 @@ pub enum Status { Passed = 0, } +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct GeolocationTime { + lat: f32, + lng: f32, + startTS: i32, + endTS: i32, +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct IpcMessageRequest { pub id: String, @@ -44,12 +50,11 @@ pub enum IpcResults { #[serde(rename = "result")] Request { request: String, sig: String }, #[serde(rename = "result")] - //EnclaveReport { #[serde(rename = "signingKey")] signing_key: String, report: String, signature: String }, - EnclaveReport { spid: String }, + EnclaveReport { #[serde(rename = "signingKey")] signing_key: String, report: String, signature: String }, #[serde(rename = "result")] DHKey { taskPubKey: String, sig: String }, AddPersonalData { status: Status }, - FindMatch { status: Status }, + FindMatch { status: Status, encryptedOutput: String }, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -57,15 +62,21 @@ pub enum IpcResults { pub enum IpcRequest { GetEnclaveReport, NewTaskEncryptionKey { userPubKey: String }, - AddPersonalData { input: IpcInput }, - FindMatch { input: IpcInput }, + AddPersonalData { input: IpcInputData }, + FindMatch { input: IpcInputMatch }, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct IpcInputData { + #[serde(rename = "encryptedUserId")] pub encrypted_userid: String, + #[serde(rename = "encryptedData")] pub encrypted_data: String, + #[serde(rename = "userPubKey")] pub user_pub_key: String, } #[derive(Serialize, Deserialize, Debug, Clone)] -pub struct IpcInput { - pub encryptedUserId: String, - pub encryptedData: String, - pub userPubKey: String, +pub struct IpcInputMatch { + #[serde(rename = "encryptedUserId")] pub encrypted_userid: String, + #[serde(rename = "userPubKey")] pub user_pub_key: String, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -112,8 +123,7 @@ impl UnwrapError for Result { match self { Ok(m) => m, Err(e) => { - //error!("Unwrapped Message failed: {}", e); - panic!("Unwrapped Message failed: {}", e); + error!("Unwrapped Message failed: {}", e); IpcResponse::Error {msg: format!("{}", e)} } } diff --git a/enclave/safetrace/app/src/ocalls_u.rs b/enclave/safetrace/app/src/ocalls_u.rs index 9a3538c..a60fac4 100644 --- a/enclave/safetrace/app/src/ocalls_u.rs +++ b/enclave/safetrace/app/src/ocalls_u.rs @@ -1,10 +1,25 @@ -use std::{ptr, slice}; -use enigma_types::traits::SliceCPtr; +use sgx_types::{sgx_enclave_id_t, sgx_status_t, sgx_target_info_t, sgx_report_t}; + //use crate::esgx::general; +// #[no_mangle] +// pub unsafe extern "C" fn ocall_save_to_memory(data_ptr: *const u8, data_len: usize) -> u64 { +// let data = slice::from_raw_parts(data_ptr, data_len).to_vec(); +// let ptr = Box::into_raw(Box::new(data.into_boxed_slice())) as *const u8; +// ptr as u64 +// } + +#[no_mangle] +extern "C" { + pub fn ecall_get_registration_quote( + eid: sgx_enclave_id_t, + retval: *mut sgx_status_t, + target_info: *const sgx_target_info_t, + report: *mut sgx_report_t, + ) -> sgx_status_t; +} + #[no_mangle] -pub unsafe extern "C" fn ocall_save_to_memory(data_ptr: *const u8, data_len: usize) -> u64 { - let data = slice::from_raw_parts(data_ptr, data_len).to_vec(); - let ptr = Box::into_raw(Box::new(data.into_boxed_slice())) as *const u8; - ptr as u64 +extern "C" { + pub fn ecall_get_signing_address(eid: sgx_enclave_id_t, arr: *mut [u8; 20usize]) -> sgx_status_t; } \ No newline at end of file diff --git a/enclave/safetrace/enclave/Cargo.toml b/enclave/safetrace/enclave/Cargo.toml index 6091e85..66ab019 100644 --- a/enclave/safetrace/enclave/Cargo.toml +++ b/enclave/safetrace/enclave/Cargo.toml @@ -2,6 +2,7 @@ name = "safetrace-enclave" version = "1.0.0" authors = ["Enigma MPC"] +edition = "2018" [lib] name = "safetraceenclave" @@ -10,47 +11,23 @@ crate-type = ["staticlib"] [features] default = [] -[target.'cfg(not(target_env = "sgx"))'.dependencies] -sgx_types = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git", features = ["backtrace"] } -sgx_trts = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -sgx_rand = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } -sgx_tseal = { git = "https://github.com/apache/teaclave-sgx-sdk.git" } - [dependencies] -arrayvec = { version = "0.4.10", default-features = false } -rustc-hex = { version = "2.0.1", default-features = false } -serde = { git = "https://github.com/mesalock-linux/serde-sgx", features = ["derive"] } -serde_json = { git = "https://github.com/mesalock-linux/serde-json-sgx" } -libsecp256k1 = { version = "0.2" } -lazy_static = {version = "1.3.0", features = ["spin_no_std"] } -tiny-keccak = { version = "1.4" } -sha2 = { version = "0.8.0", default-features = false} -ring = { git = "https://github.com/elichai/ring.git", rev = "sgx-manual", default-features = false } +enigma-types = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop", default-features = false, features = ["sgx"] } +enigma-crypto = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop", default-features = false, features = ["sgx", "asymmetric"] } +enigma-tools-t = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop" } +enigma-tools-m = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop", default-features = false, features = ["sgx"] } +enigma-runtime-t = { git = "https://github.com/enigmampc/enigma-core.git", branch="develop" } + +# rustc-hex = { version = "2.0", default-features = false } +serde = { git = "https://github.com/mesalock-linux/serde-sgx.git", rev = "sgx_1.0.9", features=["serde_derive"] } +serde_json = { git = "https://github.com/enigmampc/serde-json-sgx.git", rev = "1.0.39-sgx-1.0.9" } +rmp-serde = {git = "https://github.com/enigmampc/msgpack-rust.git", rev = "0.14.0-sgx-1.0.9" } +# serde_cbor = { git = "https://github.com/mesalock-linux/cbor-sgx.git", rev = "sgx_1.0.9", default-features = false, features=["mesalock_sgx"] } +lazy_static = {version = "1.4.0", features = ["spin_no_std"] } -[patch.'https://github.com/apache/teaclave-sgx-sdk.git'] -sgx_alloc = { path = "../../incubator-teaclave-sgx-sdk/sgx_alloc" } -sgx_build_helper = { path = "../../incubator-teaclave-sgx-sdk/sgx_build_helper" } -sgx_cov = { path = "../../incubator-teaclave-sgx-sdk/sgx_cov" } -sgx_crypto_helper = { path = "../../incubator-teaclave-sgx-sdk/sgx_crypto_helper" } -sgx_libc = { path = "../../incubator-teaclave-sgx-sdk/sgx_libc" } -sgx_rand = { path = "../../incubator-teaclave-sgx-sdk/sgx_rand" } -sgx_rand_derive = { path = "../../incubator-teaclave-sgx-sdk/sgx_rand_derive" } -sgx_serialize = { path = "../../incubator-teaclave-sgx-sdk/sgx_serialize" } -sgx_serialize_derive = { path = "../../incubator-teaclave-sgx-sdk/sgx_serialize_derive" } -sgx_serialize_derive_internals = { path = "../../incubator-teaclave-sgx-sdk/sgx_serialize_derive_internals" } -sgx_tcrypto = { path = "../../incubator-teaclave-sgx-sdk/sgx_tcrypto" } -sgx_tcrypto_helper = { path = "../../incubator-teaclave-sgx-sdk/sgx_tcrypto_helper" } -sgx_tdh = { path = "../../incubator-teaclave-sgx-sdk/sgx_tdh" } -sgx_tkey_exchange = { path = "../../incubator-teaclave-sgx-sdk/sgx_tkey_exchange" } -sgx_tprotected_fs = { path = "../../incubator-teaclave-sgx-sdk/sgx_tprotected_fs" } -sgx_trts = { path = "../../incubator-teaclave-sgx-sdk/sgx_trts" } -sgx_tse = { path = "../../incubator-teaclave-sgx-sdk/sgx_tse" } -sgx_tseal = { path = "../../incubator-teaclave-sgx-sdk/sgx_tseal" } -sgx_tstd = { path = "../../incubator-teaclave-sgx-sdk/sgx_tstd" } -sgx_tunittest = { path = "../../incubator-teaclave-sgx-sdk/sgx_tunittest" } -sgx_types = { path = "../../incubator-teaclave-sgx-sdk/sgx_types" } -sgx_ucrypto = { path = "../../incubator-teaclave-sgx-sdk/sgx_ucrypto" } -sgx_unwind = { path = "../../incubator-teaclave-sgx-sdk/sgx_unwind" } -sgx_urts = { path = "../../incubator-teaclave-sgx-sdk/sgx_urts" } +sgx_types = { git = "https://github.com/baidu/rust-sgx-sdk.git", rev = "v1.0.9" } +sgx_tstd = { git = "https://github.com/baidu/rust-sgx-sdk.git", rev = "v1.0.9" } +sgx_trts = { git = "https://github.com/baidu/rust-sgx-sdk.git", rev = "v1.0.9" } +sgx_rand = { git = "https://github.com/baidu/rust-sgx-sdk.git", rev = "v1.0.9" } +sgx_tseal = { git = "https://github.com/baidu/rust-sgx-sdk.git", rev = "v1.0.9" } diff --git a/enclave/safetrace/enclave/Enclave.edl b/enclave/safetrace/enclave/Enclave.edl index 99f6a94..4e3ee15 100644 --- a/enclave/safetrace/enclave/Enclave.edl +++ b/enclave/safetrace/enclave/Enclave.edl @@ -22,6 +22,8 @@ enclave { from "sgx_tstdc.edl" import *; from "sgx_fs.edl" import *; + include "sgx_key_exchange.h" + include "enigma-types.h" trusted { /* define ECALLs here. */ @@ -39,6 +41,20 @@ enclave { [in] uint8_t pubkey[64], [out] uint64_t* serialized_ptr ); + + public sgx_status_t ecall_get_registration_quote( + [in] const sgx_target_info_t * target_info , + [out] sgx_report_t * report + ); + + public void ecall_get_signing_address([out] uint8_t arr[20]); + + public sgx_status_t ecall_find_match( + [in, size=encryptedUserId_len] const uint8_t* encryptedUserId, + size_t encryptedUserId_len, + [in] uint8_t user_key[64], + [out] uint64_t* serialized_ptr); + }; untrusted { uint64_t ocall_save_to_memory([in, count=data_len] const uint8_t* data_ptr, size_t data_len); diff --git a/enclave/safetrace/enclave/Makefile b/enclave/safetrace/enclave/Makefile index 5f41187..23a9b31 100644 --- a/enclave/safetrace/enclave/Makefile +++ b/enclave/safetrace/enclave/Makefile @@ -1,32 +1,35 @@ -# 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. +# Because build-dependencies and regular dependencies are mixed together it's not possible to import +# bindgen into the enclave's build.rs (https://github.com/rust-lang/cargo/issues/2589) +# The solution is to install the bindgen CLI in the docker and use it manually in the Makefile. + +SGX_SDK ?= /opt/sgxsdk + Rust_Enclave_Name := libenclave.a Rust_Enclave_Files := $(wildcard src/*.rs) -Rust_Target_Path := $(CURDIR)/../../incubator-teaclave-sgx-sdk/xargo +# Rust_Target_Path := $(CURDIR)/../../incubator-teaclave-sgx-sdk/xargo + +BINDGEN_OUTPUT_FILE := src/auto_ffi.rs +BINDGEN_RAW_LINES := "\#![allow(dead_code)] use enigma_types::*; use sgx_types::*;" +BINDGEN_CLANG_FLAGS := -I$(SGX_SDK)/include -I$(HOME)/sgx/edl +BINDGEN_FLAGS := --default-enum-style=rust --rust-target=nightly \ + --no-recursive-whitelist --use-array-pointers-in-arguments \ + --whitelist-function ocall_.* --raw-line $(BINDGEN_RAW_LINES) -.PHONY: all -all: $(Rust_Enclave_Name) +all: bindgen $(Rust_Enclave_Name) $(Rust_Enclave_Name): $(Rust_Enclave_Files) ifeq ($(XARGO_SGX), 1) - RUST_TARGET_PATH=$(Rust_Target_Path) xargo build --target x86_64-unknown-linux-sgx --release - cp ./target/x86_64-unknown-linux-sgx/release/libsafetraceenclave.a ../lib/libenclave.a + RUST_TARGET_PATH=$(shell pwd) xargo build --target x86_64-unknown-linux-sgx $(CARGO_FLAGS) + cp ./target/x86_64-unknown-linux-sgx/$(Rust_target_dir)/libsafetraceenclave.a ../lib/libenclave.a else - cargo build --release - cp ./target/release/libsafetraceenclave.a ../lib/libenclave.a + cargo build $(CARGO_FLAGS) + cp ./target/$(Rust_target_dir)/libsafetraceenclave.a ../lib/libenclave.a endif + + +.PHONY: bindgen +bindgen: Enclave_t.h + cargo build -p enigma-types $(CARGO_FLAGS) # Meant to make sure `enigma-types.h` already exists and can be included. + bindgen Enclave_t.h $(BINDGEN_FLAGS) -- $(BINDGEN_CLANG_FLAGS) > $(BINDGEN_OUTPUT_FILE) + rustfmt $(BINDGEN_OUTPUT_FILE) diff --git a/enclave/safetrace/enclave/src/auto_ffi.rs b/enclave/safetrace/enclave/src/auto_ffi.rs new file mode 100644 index 0000000..4e71553 --- /dev/null +++ b/enclave/safetrace/enclave/src/auto_ffi.rs @@ -0,0 +1,13 @@ +/* automatically generated by rust-bindgen */ + +#![allow(dead_code)] +use enigma_types::*; +use sgx_types::*; + +extern "C" { + pub fn ocall_save_to_memory( + retval: *mut u64, + data_ptr: *const u8, + data_len: size_t, + ) -> sgx_status_t; +} diff --git a/enclave/safetrace/enclave/src/data.rs b/enclave/safetrace/enclave/src/data.rs index f2a7f90..359ed5f 100644 --- a/enclave/safetrace/enclave/src/data.rs +++ b/enclave/safetrace/enclave/src/data.rs @@ -1,59 +1,268 @@ -use serde::{Serialize, Deserialize}; -// use std::{slice}; -use std::string::String; -use errors_t::EnclaveError; -use types::{PubKey, DhKey}; +use enigma_tools_t::common::errors_t::{EnclaveError, EnclaveError::*, FailedTaskError::*, EnclaveSystemError::*}; +use enigma_crypto::{symmetric::decrypt, symmetric::encrypt}; +use enigma_types::{DhKey, PubKey, EnclaveReturn}; +use std::{ + string::{String,ToString}, + vec::Vec, + str, + collections::HashMap +}; +use serde_json::{Value, json}; +use serde::{Deserialize, Serialize}; +use rmp_serde::{Deserializer, Serializer}; + +use sgx_tseal::{SgxSealedData}; +use sgx_types::marker::ContiguousMemory; +use std::untrusted::fs::File; +use std::io::{Read, Write, self}; +use sgx_types::{sgx_status_t, sgx_sealed_data_t}; + +pub const DATAFILE: &str = "data.sealed"; +pub const TOVERLAP: i32 = 300; // 5min * 60s minimum overlap +pub const DISTANCE: f64 = 10.0; // in meters +pub const EARTH_RADIUS: f64 = 6371000.0; // in meters +pub const SEAL_LOG_SIZE: usize = 4096; // Maximum data can seal in bytes -> match + + +pub enum Error { + SliceError, + UnsealError(sgx_status_t), + SerializeError, + Other +} + +// TODO: Do proper mapping, using a generic for now +impl From for EnclaveError { + fn from(other: Error) -> EnclaveError { + EnclaveError::SystemError(MessagingError{ err: "Error unsealing data".to_string() }) + } +} // Structs #[derive(Serialize, Deserialize, Clone, Debug)] pub struct GeolocationTime { - lat: i32, - lng: i32, + lat: f64, + lng: f64, startTS: i32, - endTS: i32 + endTS: i32, + testResult: bool } -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct Request { - encryptedUserId: String, - encryptedData: String, - userPubKey: String +pub fn decrypt_userid(userid: &[u8], key: &DhKey) -> Result, EnclaveError> { + if userid.is_empty(){ + Err(FailedTaskError(InputError { message: "encryptedUserId is empty".to_string()})) + } else { + Ok(decrypt(userid, key)?) + } +} + +pub fn decrypt_data(data: &[u8], key: &DhKey) -> Result, EnclaveError> { + if data.is_empty(){ + Err(FailedTaskError(InputError { message: "encryptedData is empty".to_string()})) + } else { + Ok(decrypt(data, key)?) + } +} + +//pub fn create_sealeddata_for_serializable(data: &UserLocations, sealed_log_out: &mut [u8; SEAL_LOG_SIZE]) -> enigma_types::EnclaveReturn { +pub fn create_sealeddata_for_serializable(data: HashMap>, sealed_log_out: &mut [u8; SEAL_LOG_SIZE]) -> enigma_types::EnclaveReturn { + + let encoded_vec = serde_json::to_vec(&data).unwrap(); + let encoded_slice = encoded_vec.as_slice(); + // println!("Length of encoded slice: {}", encoded_slice.len()); + // println!("Encoded slice: {:?}", encoded_slice); + + let aad: [u8; 0] = [0_u8; 0]; + let result = SgxSealedData::<[u8]>::seal_data(&aad, encoded_slice); + let sealed_data = match result { + Ok(x) => x, + Err(ret) => { return EnclaveReturn::SgxError; }, + }; + + let sealed_log = sealed_log_out.as_mut_ptr(); + + let opt = to_sealed_log_for_slice(&sealed_data, sealed_log, SEAL_LOG_SIZE as u32); + if opt.is_none() { + return EnclaveReturn::SgxError; + } + + EnclaveReturn::Success +} + +pub fn recover_sealeddata_for_serializable(sealed_log: * mut u8, sealed_log_size: u32) -> Result>, Error> { + + let sealed_data = from_sealed_log_for_slice::(sealed_log, sealed_log_size).ok_or(Error::SliceError)?; + let unsealed_data = sealed_data.unseal_data().map_err(|err| Error::UnsealError(err))?; + let encoded_slice = unsealed_data.get_decrypt_txt(); + + // println!("Length of encoded slice: {}", encoded_slice.len()); + // println!("Encoded slice: {:?}", encoded_slice); + + let data: HashMap> = serde_json::from_slice(encoded_slice).unwrap(); + + Ok(data) +} + + +fn to_sealed_log_for_slice(sealed_data: &SgxSealedData<[T]>, sealed_log: * mut u8, sealed_log_size: u32) -> Option<* mut sgx_sealed_data_t> { + unsafe { + sealed_data.to_raw_sealed_data_t(sealed_log as * mut sgx_sealed_data_t, sealed_log_size) + } +} + +fn from_sealed_log_for_slice<'a, T: Copy + ContiguousMemory>(sealed_log: * mut u8, sealed_log_size: u32) -> Option> { + unsafe { + SgxSealedData::<[T]>::from_raw_sealed_data_t(sealed_log as * mut sgx_sealed_data_t, sealed_log_size) + } +} + + +// Save sealed data to disk +pub fn save_sealed_data(path: &str, sealed_data: &[u8]) { + let opt = File::create(path); + if opt.is_ok() { + debug_println!("Created file => {} ", path); + let mut file = opt.unwrap(); + let result = file.write_all(&sealed_data); + if result.is_ok() { + debug_println!("success writting to file! "); + } else { + debug_println!("error writting to file! "); + } + } +} + +// Load sealed data from disk +pub fn load_sealed_data(path: &str, sealed_data: &mut [u8]) -> Result<(), String> { + let mut file = match File::open(path) { + Err(why) => return Err("Error opening the file".to_string()), + Ok(file) => file, + }; + debug_println!("Created file => {} ", path); + + let result = file.read(sealed_data); + if result.is_ok() { + debug_println!("success reading from file! "); + } else { + debug_println!("error reading from file! "); + } + Ok(()) + +} + +pub fn unseal_data_wrapper() -> Result>, Error> { + let p = DATAFILE; + let mut sealed_log_out = [0u8; SEAL_LOG_SIZE]; + match load_sealed_data(&p, &mut sealed_log_out) { + Ok(_) => { + let sealed_log = sealed_log_out.as_mut_ptr(); + let mut data = recover_sealeddata_for_serializable(sealed_log, SEAL_LOG_SIZE as u32)?; + Ok(data) + }, + Err(err) => { + let mut data = HashMap::new(); + Ok(data) + } + } } -pub fn ecall_add_personal_data_internal( +pub fn add_personal_data_internal( encryptedUserId: &[u8], encryptedData: &[u8], userPubKey: &PubKey, dhKey: &DhKey) -> Result<(), EnclaveError> { - println!("Add personal data inside the enclave"); - println!("{:?}", dhKey); - println!("Received UserPub Key Again: {:?}", userPubKey.to_vec()); + // Decrypt inputs using dhKey + let decrypted_userid = decrypt_userid(encryptedUserId, dhKey)?; + let decrypted_data = decrypt_data(encryptedData, dhKey)?; + // TODO: Should not panic, propagate error instead + let userid = match str::from_utf8(&decrypted_userid) { + Ok(v) => v, + Err(e) => panic!("Invalid UTF-8 sequence: {}", e), + }; - // // let str_slice = unsafe { slice::from_raw_parts(data_json, some_len) }; + // Deserialize decrypted input data into expected format + let mut inputData: Vec = serde_json::from_slice(&decrypted_data).unwrap(); - // // Input sanitised in EngimaJS to object type - // let mut request: Request = serde_json::from_slice(str_slice).unwrap(); + let mut data = unseal_data_wrapper()?; + //let mut data = HashMap::new(); - // println!("EncryptedUserId: {:?}", request.encryptedUserId); + data.insert(userid.to_string(), inputData); - // let inputkey = request.userPubKey; + // Seal the data and store it on disk + let mut sealed_log_in = [0u8; SEAL_LOG_SIZE]; + create_sealeddata_for_serializable(data, &mut sealed_log_in); + let p = DATAFILE; + save_sealed_data(&p, &sealed_log_in); + let mut newdata = unseal_data_wrapper()?; + println!("This is what we got"); + println!("{:?}", newdata); - // Read from the state - // let mut data = Self::get_data(); - // Append - // data.append(&mut array); - // Write back to the state - // write_state!(DATASET => data); + Ok(()) +} - // Ocall to normal world for output - //println!("Received Data: {:?}", &request); +pub fn find_match_internal( + encryptedUserId: &[u8], + userPubKey: &PubKey, + dhKey: &DhKey) -> Result, EnclaveError> { - Ok(()) + // Decrypt inputs using dhKey + let decrypted_userid = decrypt_userid(encryptedUserId, dhKey)?; + + // TODO: Should not panic, propagate error instead + let userid = match str::from_utf8(&decrypted_userid) { + Ok(v) => v, + Err(e) => panic!("Invalid UTF-8 sequence: {}", e), + }; + + let data = unseal_data_wrapper()?; + + let mut results = Vec::new(); + + // This is the algorithm to find overlaps in time and space, defined in time by TOVERLAP (in seconds) + // and in space by DISTANCE (in meters) + // We iterate over all values in the set, excluding the user we are looking for matches. + // For all of them, we iterate over all locations and compare them with all locations from the user + for (key, val) in data.iter() { + if key != &userid { + for d in data[userid].clone() { + for e in val.iter() { + if e.testResult { + // It's easier to find overlaps in time because it's a direct comparison of integers + // so handle this first: + // Both time intervals have to be larger than the minumum time overlap TOVERLAP + // and both start times + TOVERLAP have to be smaller than the other end times + if d.endTS - d.startTS > TOVERLAP && + e.endTS - e.startTS > TOVERLAP && + d.startTS + TOVERLAP < e.endTS && e.startTS + TOVERLAP < d.endTS { + // We start comparing distance between latitudes. Each degree of lat is aprox + // 111 kms (range varies between 110.567 km at the equator to 111.699 km at the poles) + // The distance between two locations will be equal or larger than the distance between + // their latitudes (or the distance between lats will be smaller than the distance * cos(45)) + // Source: + // https://stackoverflow.com/questions/5031268/algorithm-to-find-all-latitude-longitude-locations-within-a-certain-distance-fro + if (e.lat - d.lat).abs() * 111000.0 < DISTANCE * 0.71 { + // then we can run a more computationally expensive and precise comparison + if (e.lat.sin()*d.lat.sin()+e.lat.cos()*d.lat.cos()*(e.lng-d.lng).cos()).acos() * EARTH_RADIUS < DISTANCE { + results.push(d.clone()); + } + } + } + } + } + } + } + } + + let serialized_results = serde_json::to_string(&results).map_err(|err| Error::SerializeError)?; + let array_u8_results = serialized_results.as_bytes(); + let encrypted_output = encrypt(array_u8_results, dhKey)?; + + Ok(encrypted_output) } \ No newline at end of file diff --git a/enclave/safetrace/enclave/src/errors_t.rs b/enclave/safetrace/enclave/src/errors_t.rs index 9dc827d..c7bc329 100644 --- a/enclave/safetrace/enclave/src/errors_t.rs +++ b/enclave/safetrace/enclave/src/errors_t.rs @@ -112,7 +112,9 @@ pub enum EnclaveError { used_gas: u64, err: FailedTaskError }, - SystemError(EnclaveSystemError) + SystemError(EnclaveSystemError), + BadUserId, + UnsealError } impl ::std::fmt::Display for EnclaveError { @@ -245,7 +247,8 @@ impl Into for EnclaveError { // KeyProvisionError { .. } => EnclaveReturn::KeyProvisionError, } - } + }, + BadUserId } } } diff --git a/enclave/safetrace/enclave/src/keys_t.rs b/enclave/safetrace/enclave/src/keys_t.rs index 266a6ec..3f1ccac 100644 --- a/enclave/safetrace/enclave/src/keys_t.rs +++ b/enclave/safetrace/enclave/src/keys_t.rs @@ -1,205 +1,15 @@ use crate::SIGNING_KEY; -use types::{PubKey, DhKey, SymmetricKey}; +use enigma_tools_t::common::errors_t::EnclaveError; +use enigma_tools_m::utils::LockExpectMutex; +use enigma_crypto::asymmetric::KeyPair; +use enigma_tools_m::primitives::km_primitives::UserMessage; +use enigma_types::{DhKey, PubKey}; use std::collections::HashMap; -use std::{sync::SgxMutex as Mutex, sync::SgxMutexGuard as MutexGuard, vec::Vec}; -use serde::{Deserialize, Serialize}; -use secp256k1::{PublicKey, SecretKey, SharedSecret}; -use errors_t::{CryptoError, EnclaveError, ToolsError::MessagingError}; -use hash::{Keccak256, prepare_hash_multiple}; +use std::{sync::SgxMutex, vec::Vec}; -//use ring::aead::{self, Nonce, Aad}; -//use std::{borrow::ToOwned}; +lazy_static! { pub static ref DH_KEYS: SgxMutex, DhKey>> = SgxMutex::new(HashMap::new()); } - -#[derive(Debug)] -pub struct KeyPair { - pubkey: PublicKey, - privkey: SecretKey, -} - -impl KeyPair { - /// This will generate a fresh pair of Public and Private keys. - /// it will use the available randomness from [crate::rand] - - pub fn new() -> Result { - use sgx_trts::trts::rsgx_read_rand; - // This loop is important to make sure that the resulting public key isn't a point in infinity(at the curve). - // So if the Resulting public key is bad we need to generate a new random private key and try again until it succeeds. - loop { - let mut me = [0u8; 32]; - rsgx_read_rand(&mut me); - if let Ok(privkey) = SecretKey::parse(&me) { - let pubkey = PublicKey::from_secret_key(&privkey); - return Ok(KeyPair { privkey, pubkey }); - } - } - } - - pub fn from_slice(privkey: &[u8; 32]) -> Result { - let privkey = SecretKey::parse(&privkey) - .map_err(|e| CryptoError::KeyError { key_type: "Private Key", err: Some(e) })?; - let pubkey = PublicKey::from_secret_key(&privkey); - - Ok(KeyPair { privkey, pubkey }) - } - - /// This function does an ECDH(point multiplication) between one's private key and the other one's public key. - /// - pub fn derive_key(&self, _pubarr: &PubKey) -> Result { - let mut pubarr: [u8; 65] = [0; 65]; - pubarr[0] = 4; - pubarr[1..].copy_from_slice(&_pubarr[..]); - - let pubkey = PublicKey::parse(&pubarr) - .map_err(|e| CryptoError::KeyError { key_type: "Private Key", err: Some(e) })?; - - let shared = SharedSecret::new(&pubkey, &self.privkey) - .map_err(|_| CryptoError::DerivingKeyError { self_key: self.get_pubkey(), other_key: *_pubarr })?; - - let mut result = [0u8; 32]; - result.copy_from_slice(shared.as_ref()); - Ok(result) - } - - fn pubkey_object_to_pubkey(key: &PublicKey) -> PubKey { - let mut sliced_pubkey: [u8; 64] = [0; 64]; - sliced_pubkey.clone_from_slice(&key.serialize()[1..65]); - sliced_pubkey - } - - pub fn get_privkey(&self) -> [u8; 32] { self.privkey.serialize() } - - /// Get the Public Key and slice the first byte - /// The first byte represents if the key is compressed or not. - /// Because we use uncompressed Keys That start with `0x04` we can slice it out. - /// - /// We should move to compressed keys in the future, this will save 31 bytes on each pubkey. - /// - /// See More: - /// `https://tools.ietf.org/html/rfc5480#section-2.2` - /// `https://docs.rs/libsecp256k1/0.1.13/src/secp256k1/lib.rs.html#146` - pub fn get_pubkey(&self) -> PubKey { - KeyPair::pubkey_object_to_pubkey(&self.pubkey) - } - - /// Sign a message using the Private Key. - /// # Examples - /// Simple Message signing: - /// ``` - /// use enigma_crypto::KeyPair; - /// let keys = KeyPair::new().unwrap(); - /// let msg = b"Sign this"; - /// let sig = keys.sign(msg); - /// ``` - /// - /// The function returns a 65 bytes slice that contains: - /// 1. 32 Bytes, ECDSA `r` variable. - /// 2. 32 Bytes ECDSA `s` variable. - /// 3. 1 Bytes ECDSA `v` variable aligned to the right for Ethereum compatibility - pub fn sign(&self, message: &[u8]) -> Result<[u8; 65], CryptoError> { - let hashed_msg = message.keccak256(); - let message_to_sign = secp256k1::Message::parse(&hashed_msg); - - let (sig, recovery) = secp256k1::sign(&message_to_sign, &self.privkey) - .map_err(|_| CryptoError::SigningError { hashed_msg: *hashed_msg })?; - - let v: u8 = recovery.into(); - let mut returnvalue = [0u8; 65]; - returnvalue[..64].copy_from_slice(&sig.serialize()); - returnvalue[64] = v + 27; - Ok(returnvalue) - } - -} - - -/// A struct to represent the UserMessage for the key exchange. -#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)] -pub struct UserMessage { - pub(crate) pubkey: Vec, -} - -impl UserMessage { - // The reason for the prefix is that I(@elichai) don't feel comfortable signing a plain public key. - // Because ECDSA signature contains multiplication of curve points, so I'm not sure if signing on a valid curve point has any side effect. - const PREFIX: &'static [u8; 19] = b"Enigma User Message"; - - /// Generate a new UserMessage struct with the provided public key. - pub fn new(pubkey: PubKey) -> Self { - let pubkey = pubkey.to_vec(); - Self { pubkey } - } - - /// This should serialize the struct for it to be signed, using [`enigma_crypto::hash::prepare_hash_multiple()`] - /// it will add a prefix to the data, `b"Enigma User Message"`. - pub fn to_sign(&self) -> Vec { - let to_sign = [&Self::PREFIX[..], &self.pubkey]; - prepare_hash_multiple(&to_sign) - } - - /// This will serialize the Message using MessagePack. - pub fn into_message(self) -> Result, EnclaveError> { - //let mut buf = Vec::new(); - //let val = serde_json::to_value(self).map_err(|_| MessagingError { err: "Couldn't convert UserMesssage to Value" })?; - //val.serialize(&mut Serializer::new(&mut buf)).map_err(|_| MessagingError { err: "Couldn't serialize UserMesssage" })?;; - let val = serde_json::to_vec(&self).map_err(|_| MessagingError { err: "Couldn't convert UserMesssage to Value" })?; - Ok(val) - } - - // /// This will deserialize the Message using MessagePack. - // pub fn from_message(msg: &[u8]) -> Result { - // let mut des = Deserializer::new(&msg[..]); - // let res: serde_json::Value = Deserialize::deserialize(&mut des) - // .map_err(|_| MessagingError { err: "Couldn't Deserialize UserMesssage"})?;; - // let msg: Self = serde_json::from_value(res) - // .map_err(|_| MessagingError { err: "Couldn't convert Value to UserMesssage"})?; - // Ok(msg) - // } - - // /// Will return the DH public key from the message. - // pub fn get_pubkey(&self) -> PubKey { - // let mut pubkey = [0u8; 64]; - // pubkey.copy_from_slice(&self.pubkey[..]); - // pubkey - // } -} - - -// const IV_SIZE: usize = 96/8; -// static AES_MODE: &aead::Algorithm = &aead::AES_256_GCM; -// type IV = [u8; IV_SIZE]; - -// pub fn decrypt(cipheriv: &[u8], key: &SymmetricKey) -> Result, CryptoError> { -// if cipheriv.len() < IV_SIZE { -// return Err(CryptoError::ImproperEncryption); -// } -// let aes_decrypt = aead::OpeningKey::new(&AES_MODE, key) -// .map_err(|_| CryptoError::KeyError { key_type: "Decryption", err: None })?; - -// let (ciphertext, iv) = cipheriv.split_at(cipheriv.len()-12); -// let nonce = aead::Nonce::try_assume_unique_for_key(&iv).unwrap(); // This Cannot fail because split_at promises that iv.len()==12 -// let mut ciphertext = ciphertext.to_owned(); -// let decrypted_data = aead::open_in_place(&aes_decrypt, nonce, Aad::empty(), 0, &mut ciphertext); -// let decrypted_data = decrypted_data.map_err(|_| CryptoError::DecryptionError)?; - -// Ok(decrypted_data.to_vec()) -// } - - -/// A trait that is basically a shortcut for `mutex.lock().expect(format!("{} mutex is posion", name))` -/// you instead call `mutex.lock_expect(name)` and it will act the same. -pub trait LockExpectMutex { - /// See trait documentation. a shortcut for `lock()` and `expect()` - fn lock_expect(&self, name: &str) -> MutexGuard; -} - -impl LockExpectMutex for Mutex { - fn lock_expect(&self, name: &str) -> MutexGuard { self.lock().unwrap_or_else(|_| panic!("{} mutex is poison", name)) } -} - -lazy_static! { pub static ref DH_KEYS: Mutex, DhKey>> = Mutex::new(HashMap::new()); } - -pub(crate) unsafe fn ecall_get_user_key_internal(sig: &mut [u8; 65], user_pubkey: &PubKey) -> Result, EnclaveError> { +pub(crate) unsafe fn get_user_key_internal(sig: &mut [u8; 65], user_pubkey: &PubKey) -> Result, EnclaveError> { let keys = KeyPair::new()?; let req = UserMessage::new(keys.get_pubkey()); *sig = SIGNING_KEY.sign(&req.to_sign())?; diff --git a/enclave/safetrace/enclave/src/lib.rs b/enclave/safetrace/enclave/src/lib.rs index f0f5d3f..b157ba0 100644 --- a/enclave/safetrace/enclave/src/lib.rs +++ b/enclave/safetrace/enclave/src/lib.rs @@ -17,72 +17,92 @@ #![crate_name = "safetraceenclave"] #![crate_type = "staticlib"] +#![no_std] #![cfg_attr(not(target_env = "sgx"), no_std)] #![cfg_attr(target_env = "sgx", feature(rustc_private))] +extern crate enigma_runtime_t; +#[macro_use] +extern crate enigma_tools_t; +extern crate enigma_crypto; +extern crate enigma_tools_m; +extern crate enigma_types; + extern crate sgx_types; #[cfg(not(target_env = "sgx"))] #[macro_use] extern crate sgx_tstd as std; + extern crate sgx_rand; -extern crate sgx_trts; +// extern crate sgx_trts; extern crate sgx_tseal; #[macro_use] extern crate lazy_static; +extern crate serde; +// #[macro_use] +extern crate serde_json; + // extern crate sgx_serialize; // #[macro_use] // extern crate sgx_serialize_derive; -use sgx_types::*; use std::{slice}; -extern crate serde; -extern crate serde_json; -extern crate secp256k1; -extern crate tiny_keccak; -extern crate sha2; -extern crate rustc_hex; -extern crate arrayvec; -//extern crate ring; +// extern crate serde; +// extern crate secp256k1; +// extern crate tiny_keccak; +// extern crate sha2; +// extern crate rustc_hex; +// extern crate arrayvec; +// extern crate ring; -#[macro_use] -mod macros; -mod errors_t; +// #[macro_use] +// mod macros; +// mod errors_t; mod data; mod keys_t; -mod storage; -mod types; -mod hash; -mod traits; - -use keys_t::{ecall_get_user_key_internal, KeyPair, DH_KEYS, LockExpectMutex}; -use data::ecall_add_personal_data_internal; -use storage::*; -use types::{PubKey, DhKey, EnclaveReturn}; -use errors_t::{EnclaveError, CryptoError}; -use traits::SliceCPtr; +// // mod storage; +// mod types; +// mod hash; +// mod traits; + +use sgx_types::*; +use keys_t::{get_user_key_internal}; +use data::{add_personal_data_internal, find_match_internal}; +// use storage::*; +use enigma_types::{PubKey, DhKey, EnclaveReturn}; +use enigma_tools_t::{ + common::errors_t::{EnclaveError}, + storage_t, + quote_t, +}; +use enigma_tools_m::utils::EthereumAddress; + +use enigma_tools_m::utils::{LockExpectMutex}; +use enigma_crypto::{asymmetric, CryptoError}; + + + +// use traits::SliceCPtr; + +use enigma_tools_t::{esgx::ocalls_t}; lazy_static! { - pub(crate) static ref SIGNING_KEY: KeyPair = get_sealed_keys_wrapper(); + pub(crate) static ref SIGNING_KEY: asymmetric::KeyPair = get_sealed_keys_wrapper(); } -extern "C" { - fn ocall_save_to_memory(ptr: *mut u64, data_ptr: *const u8, data_len: usize) -> sgx_status_t; +#[no_mangle] +pub extern "C" fn ecall_get_registration_quote(target_info: &sgx_target_info_t, real_report: &mut sgx_report_t) -> sgx_status_t { + quote_t::create_report_with_data(&target_info, real_report, &SIGNING_KEY.get_pubkey().address()) } +#[no_mangle] +pub extern "C" fn ecall_get_signing_address(pubkey: &mut [u8; 20]) { pubkey.copy_from_slice(&SIGNING_KEY.get_pubkey().address()); } -// TODO: Replace u64 with *const u8, and pass it via the ocall using *const *const u8 -pub fn save_to_untrusted_memory(data: &[u8]) -> Result { - let mut ptr = 0u64; - match unsafe { ocall_save_to_memory(&mut ptr as *mut u64, data.as_c_ptr(), data.len()) } { - sgx_status_t::SGX_SUCCESS => Ok(ptr), - e => Err(e.into()), - } -} -fn get_sealed_keys_wrapper() -> KeyPair { +fn get_sealed_keys_wrapper() -> asymmetric::KeyPair { // // Get Home path via Ocall // let mut path_buf = get_home_path().unwrap(); // // add the filename to the path: `keypair.sealed` @@ -90,7 +110,7 @@ fn get_sealed_keys_wrapper() -> KeyPair { // let sealed_path = path_buf.to_str().unwrap(); // TODO: Decide what to do if failed to obtain keys. - match get_sealed_keys("keypair.sealed") { + match storage_t::get_sealed_keys("keypair.sealed") { Ok(key) => key, Err(err) => panic!("Failed obtaining keys: {:?}", err), } @@ -99,11 +119,11 @@ fn get_sealed_keys_wrapper() -> KeyPair { #[no_mangle] pub unsafe extern "C" fn ecall_get_user_key(sig: &mut [u8; 65], user_pubkey: &[u8; 64], serialized_ptr: *mut u64) -> EnclaveReturn { println!("Get User Key called inside enclave"); - let msg = match ecall_get_user_key_internal(sig, user_pubkey) { + let msg = match get_user_key_internal(sig, user_pubkey) { Ok(msg) => msg, Err(e) => return e.into(), }; - *serialized_ptr = match save_to_untrusted_memory(&msg[..]) { + *serialized_ptr = match ocalls_t::save_to_untrusted_memory(&msg[..]) { Ok(ptr) => ptr, Err(e) => return e.into(), }; @@ -111,7 +131,7 @@ pub unsafe extern "C" fn ecall_get_user_key(sig: &mut [u8; 65], user_pubkey: &[u } fn get_io_key(user_key: &PubKey) -> Result { - let io_key = DH_KEYS + let io_key = keys_t::DH_KEYS .lock_expect("User DH Key") .remove(&user_key[..]) .ok_or(CryptoError::MissingKeyError { key_type: "DH Key" })?; @@ -135,6 +155,34 @@ pub unsafe extern "C" fn ecall_add_personal_data( Err(e) => return e.into(), } - let result = ecall_add_personal_data_internal(encryptedUserId, encryptedData, userPubKey, &io_key); + let result = add_personal_data_internal(encryptedUserId, encryptedData, userPubKey, &io_key); + + EnclaveReturn::Success +} + +#[no_mangle] +pub unsafe extern "C" fn ecall_find_match( + encryptedUserId: *const u8, + encryptedUserId_len: usize, + userPubKey: &[u8; 64], + serialized_ptr: *mut u64) -> EnclaveReturn { + + let encryptedUserId = slice::from_raw_parts(encryptedUserId, encryptedUserId_len); + + let io_key; + match get_io_key(userPubKey) { + Ok(v) => io_key = v, + Err(e) => return e.into(), + } + + let msg = match find_match_internal(encryptedUserId, userPubKey, &io_key) { + Ok(msg) => msg, + Err(e) => return e.into(), + }; + *serialized_ptr = match ocalls_t::save_to_untrusted_memory(&msg[..]) { + Ok(ptr) => ptr, + Err(e) => return e.into(), + }; + EnclaveReturn::Success } \ No newline at end of file