Skip to content

Commit

Permalink
Add mc-sgx-core-build crate
Browse files Browse the repository at this point in the history
Add the `mc-sgx-core-build` crate to hold common build utilities used
with other SGX crates.
  • Loading branch information
nick-mobilecoin committed Jul 20, 2022
1 parent 2be48af commit 725fc73
Show file tree
Hide file tree
Showing 16 changed files with 128 additions and 98 deletions.
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"
20 changes: 20 additions & 0 deletions core/build/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# 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)
- [Build Instructions](#build-instructions)
- [Intel SGX SDK](#intel-sgx-sdk)
- [Features](#features)
- [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
1 change: 1 addition & 0 deletions trusted/trts/sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ 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.

1 change: 1 addition & 0 deletions untrusted/test_enclave/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ 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

0 comments on commit 725fc73

Please sign in to comment.