| // Copyright (C) 2017-2018 Baidu, Inc. All Rights Reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in |
| // the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Baidu, Inc., nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| #![allow(dead_code)] |
| #![allow(unused_assignments)] |
| |
| extern crate sgx_types; |
| extern crate sgx_urts; |
| extern crate dirs; |
| use sgx_types::*; |
| use sgx_urts::SgxEnclave; |
| |
| extern crate mio; |
| |
| use std::os::unix::io::{IntoRawFd, AsRawFd}; |
| use std::fs; |
| use std::path; |
| use std::net::{TcpListener, TcpStream, SocketAddr}; |
| use std::str; |
| use std::io::{Read, Write}; |
| |
| static ENCLAVE_FILE: &'static str = "enclave.signed.so"; |
| static ENCLAVE_TOKEN: &'static str = "enclave.token"; |
| |
| extern { |
| fn run_server(eid: sgx_enclave_id_t, retval: *mut sgx_status_t, |
| socket_fd: c_int) -> sgx_status_t; |
| } |
| |
| #[no_mangle] |
| pub extern "C" |
| fn ocall_sgx_init_quote(ret_ti: *mut sgx_target_info_t, |
| ret_gid : *mut sgx_epid_group_id_t) -> sgx_status_t { |
| println!("Entering ocall_sgx_init_quote"); |
| unsafe {sgx_init_quote(ret_ti, ret_gid)} |
| } |
| |
| pub fn lookup_ipv4(host: &str, port: u16) -> SocketAddr { |
| use std::net::ToSocketAddrs; |
| |
| let addrs = (host, port).to_socket_addrs().unwrap(); |
| for addr in addrs { |
| if let SocketAddr::V4(_) = addr { |
| return addr; |
| } |
| } |
| |
| unreachable!("Cannot lookup address"); |
| } |
| |
| |
| #[no_mangle] |
| pub extern "C" |
| fn ocall_get_ias_socket(ret_fd : *mut c_int) -> sgx_status_t { |
| let port = 443; |
| let hostname = "test-as.sgx.trustedservices.intel.com"; |
| let addr = lookup_ipv4(hostname, port); |
| let sock = TcpStream::connect(&addr).expect("[-] Connect tls server failed!"); |
| |
| unsafe {*ret_fd = sock.into_raw_fd();} |
| |
| sgx_status_t::SGX_SUCCESS |
| } |
| |
| #[no_mangle] |
| pub extern "C" |
| fn ocall_get_quote (p_sigrl : *const u8, |
| sigrl_len : u32, |
| p_report : *const sgx_report_t, |
| quote_type : sgx_quote_sign_type_t, |
| p_spid : *const sgx_spid_t, |
| p_nonce : *const sgx_quote_nonce_t, |
| p_qe_report : *mut sgx_report_t, |
| p_quote : *mut u8, |
| _maxlen : u32, |
| p_quote_len : *mut u32) -> sgx_status_t { |
| println!("Entering ocall_get_quote"); |
| |
| let mut real_quote_len : u32 = 0; |
| |
| let ret = unsafe { |
| sgx_calc_quote_size(p_sigrl, sigrl_len, &mut real_quote_len as *mut u32) |
| }; |
| |
| if ret != sgx_status_t::SGX_SUCCESS { |
| println!("sgx_calc_quote_size returned {}", ret); |
| return ret; |
| } |
| |
| println!("quote size = {}", real_quote_len); |
| unsafe { *p_quote_len = real_quote_len; } |
| |
| let ret = unsafe { |
| sgx_get_quote(p_report, |
| quote_type, |
| p_spid, |
| p_nonce, |
| p_sigrl, |
| sigrl_len, |
| p_qe_report, |
| p_quote as *mut sgx_quote_t, |
| real_quote_len) |
| }; |
| |
| if ret != sgx_status_t::SGX_SUCCESS { |
| println!("sgx_calc_quote_size returned {}", ret); |
| return ret; |
| } |
| |
| println!("sgx_calc_quote_size returned {}", ret); |
| ret |
| } |
| |
| #[no_mangle] |
| pub extern "C" |
| fn ocall_get_update_info (platform_blob: * const sgx_platform_info_t, |
| enclave_trusted: i32, |
| update_info: * mut sgx_update_info_bit_t) -> sgx_status_t { |
| unsafe{ |
| sgx_report_attestation_status(platform_blob, enclave_trusted, update_info) |
| } |
| } |
| |
| fn init_enclave() -> SgxResult<SgxEnclave> { |
| |
| let mut launch_token: sgx_launch_token_t = [0; 1024]; |
| let mut launch_token_updated: i32 = 0; |
| // Step 1: try to retrieve the launch token saved by last transaction |
| // if there is no token, then create a new one. |
| // |
| // try to get the token saved in $HOME */ |
| let mut home_dir = path::PathBuf::new(); |
| let use_token = match dirs::home_dir() { |
| Some(path) => { |
| println!("[+] Home dir is {}", path.display()); |
| home_dir = path; |
| true |
| }, |
| None => { |
| println!("[-] Cannot get home dir"); |
| false |
| } |
| }; |
| |
| let token_file: path::PathBuf = home_dir.join(ENCLAVE_TOKEN);; |
| if use_token == true { |
| match fs::File::open(&token_file) { |
| Err(_) => { |
| println!("[-] Open token file {} error! Will create one.", token_file.as_path().to_str().unwrap()); |
| }, |
| Ok(mut f) => { |
| println!("[+] Open token file success! "); |
| match f.read(&mut launch_token) { |
| Ok(1024) => { |
| println!("[+] Token file valid!"); |
| }, |
| _ => println!("[+] Token file invalid, will create new token file"), |
| } |
| } |
| } |
| } |
| |
| // Step 2: 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}; |
| let enclave = try!(SgxEnclave::create(ENCLAVE_FILE, |
| debug, |
| &mut launch_token, |
| &mut launch_token_updated, |
| &mut misc_attr)); |
| |
| // Step 3: save the launch token if it is updated |
| if use_token == true && launch_token_updated != 0 { |
| // reopen the file with write capablity |
| match fs::File::create(&token_file) { |
| Ok(mut f) => { |
| match f.write_all(&launch_token) { |
| Ok(()) => println!("[+] Saved updated launch token!"), |
| Err(_) => println!("[-] Failed to save updated launch token!"), |
| } |
| }, |
| Err(_) => { |
| println!("[-] Failed to save updated enclave token, but doesn't matter"); |
| }, |
| } |
| } |
| |
| Ok(enclave) |
| } |
| |
| 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; |
| }, |
| }; |
| |
| println!("Running as server..."); |
| let listener = TcpListener::bind("0.0.0.0:3443").unwrap(); |
| match listener.accept() { |
| Ok((socket, addr)) => { |
| println!("new client from {:?}", addr); |
| let mut retval = sgx_status_t::SGX_SUCCESS; |
| let result = unsafe { |
| run_server(enclave.geteid(), &mut retval, socket.as_raw_fd()) |
| }; |
| match result { |
| sgx_status_t::SGX_SUCCESS => { |
| println!("ECALL success!"); |
| }, |
| _ => { |
| println!("[-] ECALL Enclave Failed {}!", result.as_str()); |
| return; |
| } |
| } |
| } |
| Err(e) => println!("couldn't get client: {:?}", e), |
| } |
| |
| println!("[+] Done!"); |
| |
| enclave.destroy(); |
| } |