Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mc-sgx-core-build crate #26

Merged
merged 3 commits into from
Jul 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
[workspace]
resolver = "2"
members = [
"sys/types",
"sys/types",
"build",
]

[profile.dev]
Expand Down
4 changes: 4 additions & 0 deletions core/build/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[package]
name = "mc-sgx-core-build"
version = "0.1.0"
edition = "2021"
17 changes: 17 additions & 0 deletions core/build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Common build logic for SGX libraries

This crate provides common logic to build and link against the Intel SGX SDK

## Table of Contents

- [License](#license)
- [References](#references)

## License

Look for the *LICENSE* file at the root of the repo for more information.

## References

- <https://download.01.org/intel-sgx/sgx-dcap/1.13/linux/docs/Intel_SGX_Enclave_Common_Loader_API_Reference.pdf>
- <https://github.com/intel/linux-sgx#build-the-intelr-sgx-sdk-and-intelr-sgx-psw-package>
34 changes: 34 additions & 0 deletions core/build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2022 The MobileCoin Foundation

#![doc = include_str!("../README.md")]

use std::{env, path::PathBuf};

static DEFAULT_SGX_SDK_PATH: &str = "/opt/intel/sgxsdk";

/// Return the SGX library path.
///
/// Will first attempt to look at the environment variable `SGX_SDK`, if that
/// isn't present then `/opt/intel/sgxsdk` will be used.
pub fn sgx_library_path() -> String {
env::var("SGX_SDK").unwrap_or_else(|_| DEFAULT_SGX_SDK_PATH.into())
}

/// Return the build output path.
pub fn build_output_path() -> PathBuf {
PathBuf::from(env::var("OUT_DIR").expect("Missing env.OUT_DIR"))
}

/// Return the SGX library suffix
///
/// Some SGX libraries have a suffix for example `sgx_trts.a` versus
/// `sgx_trts_sim.a`. This will result the suffix based on the presence of the
/// feature `hw`.
pub fn sgx_library_suffix() -> &'static str {
// See https://doc.rust-lang.org/cargo/reference/features.html#build-scripts
// for description of `CARGO_FEATURE_<name>`
match env::var("CARGO_FEATURE_HW") {
Ok(_) => "",
_ => "_sim",
}
}
1 change: 1 addition & 0 deletions core/sys/types/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ edition = "2021"

[build-dependencies]
bindgen = "0.60.1"
mc-sgx-core-build = { path = "../../build" }
12 changes: 3 additions & 9 deletions core/sys/types/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@
//! Builds the FFI type bindings for the common SGX SDK types

use bindgen::{callbacks::ParseCallbacks, Builder};
use std::{env, path::PathBuf};

static DEFAULT_SGX_SDK_PATH: &str = "/opt/intel/sgxsdk";

#[derive(Debug)]
struct Callbacks;
Expand All @@ -18,17 +15,14 @@ impl ParseCallbacks for Callbacks {
}
}

fn sgx_library_path() -> String {
env::var("SGX_SDK").unwrap_or_else(|_| DEFAULT_SGX_SDK_PATH.into())
}

fn main() {
let sgx_library_path = mc_sgx_core_build::sgx_library_path();
let bindings = Builder::default()
.header_contents(
"core_types.h",
"#include <sgx_error.h>\n#include <sgx_report.h>",
)
.clang_arg(&format!("-I{}/include", sgx_library_path()))
.clang_arg(&format!("-I{}/include", sgx_library_path))
.newtype_enum("_status_t")
.blocklist_function("*")
.allowlist_type("_status_t")
Expand All @@ -38,7 +32,7 @@ fn main() {
.generate()
.expect("Unable to generate bindings");

let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let out_path = mc_sgx_core_build::build_output_path();
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
Expand Down
2 changes: 2 additions & 0 deletions trusted/trts/sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ mc-sgx-core-sys-types = { path = "../../../core/sys/types" }
[build-dependencies]
bindgen = "0.60.1"
cargo-emit = "0.2.1"

mc-sgx-core-build = { path = "../../../core/build" }
26 changes: 8 additions & 18 deletions trusted/trts/sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,25 @@

//! Builds the FFI function bindings for trts (trusted runtime system) of the
//! Intel SGX SDK
extern crate bindgen;
use bindgen::Builder;
use cargo_emit::{rustc_link_lib, rustc_link_search};
use std::{env, path::PathBuf};

static DEFAULT_SGX_SDK_PATH: &str = "/opt/intel/sgxsdk";

#[cfg(feature = "hw")]
const SGX_SUFFIX: &str = "";
#[cfg(not(feature = "hw"))]
const SGX_SUFFIX: &str = "_sim";

fn sgx_library_path() -> String {
env::var("SGX_SDK").unwrap_or_else(|_| DEFAULT_SGX_SDK_PATH.into())
}

fn main() {
rustc_link_lib!(&format!("sgx_trts{}", SGX_SUFFIX));
rustc_link_search!(&format!("{}/lib64", sgx_library_path()));
let sgx_library_path = mc_sgx_core_build::sgx_library_path();
let sgx_suffix = mc_sgx_core_build::sgx_library_suffix();
rustc_link_lib!(&format!("sgx_trts{}", sgx_suffix));
rustc_link_search!(&format!("{}/lib64", &sgx_library_path));

let bindings = bindgen::Builder::default()
let bindings = Builder::default()
.header_contents("trts.h", "#include <sgx_trts.h>")
.clang_arg(&format!("-I{}/include", sgx_library_path()))
.clang_arg(&format!("-I{}/include", &sgx_library_path))
.blocklist_type("*")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.ctypes_prefix("core::ffi")
.generate()
.expect("Unable to generate bindings");

let out_path = PathBuf::from(env::var("OUT_DIR").expect("Missing env.OUT_DIR"));
let out_path = mc_sgx_core_build::build_output_path();
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
Expand Down
8 changes: 8 additions & 0 deletions untrusted/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions untrusted/test_enclave/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ cc = "1.0.73"
bindgen = "0.60.1"
rsa = "0.6.1"
rand = "0.8.5"

mc-sgx-core-build = { path = "../../core/build" }
66 changes: 26 additions & 40 deletions untrusted/test_enclave/build.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2022 The MobileCoin Foundation
#![doc = include_str!("README.md")]

use bindgen;
use bindgen::Builder;
use cargo_emit::rerun_if_changed;
use cc::Build;
use rand;
Expand All @@ -24,17 +24,11 @@ struct EdgerFiles {
untrusted: PathBuf,
}

const DEFAULT_SGX_SDK_PATH: &str = "/opt/intel/sgxsdk";
const EDGER_FILE: &str = "src/enclave.edl";
const ENCLAVE_FILE: &str = "src/enclave.c";
const ENCLAVE_LINKER_SCRIPT: &str = "src/enclave.lds";
const ENCLAVE_CONFIG: &str = "src/config.xml";

#[cfg(feature = "hw")]
const SGX_SUFFIX: &str = "";
#[cfg(not(feature = "hw"))]
const SGX_SUFFIX: &str = "_sim";

fn main() {
let root_dir = root_dir();
let edger_files = build_enclave_definitions(root_dir.join(EDGER_FILE));
Expand All @@ -47,19 +41,6 @@ fn main() {
build_untrusted_bindings(untrusted_header);
}

/// Provide the base path for the Intel SGX SDK. Will use the environment
/// variable `SGX_SDK`. If this isn't set it will default to
/// `/opt/intel/sgxsdk`.
fn sgx_library_path() -> String {
env::var("SGX_SDK").unwrap_or_else(|_| DEFAULT_SGX_SDK_PATH.into())
}

/// The value of the environment variable `OUT_DIR`, this must be set.
/// See https://doc.rust-lang.org/cargo/reference/environment-variables.html
fn out_dir() -> PathBuf {
env::var("OUT_DIR").expect("Missing env.OUT_DIR").into()
}

/// The root dir of this crate. Will be the value of `CARGO_MANIFEST_DIR`
/// See https://doc.rust-lang.org/cargo/reference/environment-variables.html
fn root_dir() -> PathBuf {
Expand Down Expand Up @@ -89,8 +70,9 @@ fn build_enclave_definitions<P: AsRef<Path>>(edl_file: P) -> EdgerFiles {
.to_str()
.expect("Invalid UTF-8 in edl path"));

let mut command = Command::new(&format!("{}/bin/x64/sgx_edger8r", sgx_library_path()));
let out_dir = out_dir();
let sgx_library_path = mc_sgx_core_build::sgx_library_path();
let mut command = Command::new(&format!("{}/bin/x64/sgx_edger8r", sgx_library_path));
let out_dir = mc_sgx_core_build::build_output_path();
command
.current_dir(&out_dir)
.arg(edl_file.as_ref().as_os_str());
Expand Down Expand Up @@ -129,6 +111,8 @@ where
.expect("Invalid UTF-8 in enclave C file"));
}

let sgx_library_path = mc_sgx_core_build::sgx_library_path();

// This `Build` builds a static library. If we don't omit the
// `cargo_metadata` then this static library will be linked into
// the consuming crate. The enclave binary is meant to be a stand alone,
Expand All @@ -138,12 +122,12 @@ where
// be directly linked in.
Build::new()
.files(files)
.include(format!("{}/include", sgx_library_path()))
.include(format!("{}/include/tlibc", sgx_library_path()))
.include(format!("{}/include", sgx_library_path))
.include(format!("{}/include/tlibc", sgx_library_path))
.cargo_metadata(false)
.compile("enclave");

let static_enclave = out_dir().join("libenclave.a");
let static_enclave = mc_sgx_core_build::build_output_path().join("libenclave.a");
let dynamic_enclave = build_dynamic_enclave_binary(static_enclave);
sign_enclave_binary(dynamic_enclave)
}
Expand All @@ -165,9 +149,11 @@ where
fn build_dynamic_enclave_binary<P: AsRef<Path>>(static_enclave: P) -> PathBuf {
let mut dynamic_enclave = PathBuf::from(static_enclave.as_ref());
dynamic_enclave.set_extension("so");
let trts = format!("-lsgx_trts{}", SGX_SUFFIX);
let tservice = format!("-lsgx_tservice{}", SGX_SUFFIX);
let sgx_suffix = mc_sgx_core_build::sgx_library_suffix();
let trts = format!("-lsgx_trts{}", sgx_suffix);
let tservice = format!("-lsgx_tservice{}", sgx_suffix);

let sgx_library_path = mc_sgx_core_build::sgx_library_path();
let mut command = Command::new(ld_linker());
command
.arg("-o")
Expand All @@ -177,11 +163,8 @@ fn build_dynamic_enclave_binary<P: AsRef<Path>>(static_enclave: P) -> PathBuf {
.expect("Invalid UTF-8 in static enclave path"),
)
.args(&["-z", "relro", "-z", "now", "-z", "noexecstack"])
.arg(&format!(
"-L{}/lib64/cve_2020_0551_load",
sgx_library_path()
))
.arg(&format!("-L{}/lib64", sgx_library_path()))
.arg(&format!("-L{}/lib64/cve_2020_0551_load", sgx_library_path))
.arg(&format!("-L{}/lib64", sgx_library_path))
.arg("--no-undefined")
.arg("--nostdlib")
.arg("--start-group")
Expand Down Expand Up @@ -223,7 +206,8 @@ fn sign_enclave_binary<P: AsRef<Path>>(unsigned_enclave: P) -> PathBuf {

let signing_key = get_signing_key();

let mut command = Command::new(format!("{}/bin/x64/sgx_sign", sgx_library_path()));
let sgx_library_path = mc_sgx_core_build::sgx_library_path();
let mut command = Command::new(format!("{}/bin/x64/sgx_sign", sgx_library_path));
command
.arg("sign")
.arg("-enclave")
Expand All @@ -247,7 +231,7 @@ fn sign_enclave_binary<P: AsRef<Path>>(unsigned_enclave: P) -> PathBuf {
/// Due to the time to create a key file, this will favor returning an already
/// built signing key and only generate one as needed.
fn get_signing_key() -> PathBuf {
let key_file = out_dir().join("signing_key.pem");
let key_file = mc_sgx_core_build::build_output_path().join("signing_key.pem");
if !key_file.exists() {
// The 3072 bit size and exponent of 3 are a restriction of `sgx_sign`
let bit_size = 3072;
Expand Down Expand Up @@ -275,13 +259,14 @@ fn get_signing_key() -> PathBuf {
/// # Returns
/// The full path to resultant untrusted library.
fn build_untrusted_library<P: AsRef<Path>>(untrusted_file: P) -> PathBuf {
let sgx_library_path = mc_sgx_core_build::sgx_library_path();
Build::new()
.file(untrusted_file)
.include(format!("{}/include", sgx_library_path()))
.include(format!("{}/include/tlibc", sgx_library_path()))
.include(format!("{}/include", sgx_library_path))
.include(format!("{}/include/tlibc", sgx_library_path))
.compile("untrusted");

let mut untrusted_object = out_dir();
let mut untrusted_object = mc_sgx_core_build::build_output_path();
untrusted_object.set_file_name("untrusted.a");
untrusted_object
}
Expand All @@ -296,9 +281,10 @@ fn build_untrusted_library<P: AsRef<Path>>(untrusted_file: P) -> PathBuf {
///
/// * `header` - The untrusted header file generated from `edger8r`
fn build_untrusted_bindings<P: AsRef<Path>>(header: P) {
let bindings = bindgen::Builder::default()
let sgx_library_path = mc_sgx_core_build::sgx_library_path();
let bindings = Builder::default()
.header(header.as_ref().to_str().unwrap())
.clang_arg(format!("-I{}/include", sgx_library_path()))
.clang_arg(format!("-I{}/include", sgx_library_path))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.blocklist_type("*")
// limit to only the functions needed
Expand All @@ -307,6 +293,6 @@ fn build_untrusted_bindings<P: AsRef<Path>>(header: P) {
.expect("Unable to generate bindings");

bindings
.write_to_file(out_dir().join("bindings.rs"))
.write_to_file(mc_sgx_core_build::build_output_path().join("bindings.rs"))
.expect("Couldn't write bindings!");
}
Loading