Skip to content

Commit

Permalink
psa-crypto-sys: dont configure mbedtls on external builds
Browse files Browse the repository at this point in the history
When setting env vars to use a external mbedTLS library, for example
provided by a system distro, like so:
MBEDTLS_INCLUDE_DIR="/usr/include/"
MBEDTLS_LIB_DIR="/usr/lib64"

The build would configure the vendored mbedtls. Fix this by only
configuring the vendored mbedtls when being used. This would allow
clones without the submodule using a system supplied mbedtls to succeed.

Signed-off-by: Bill Roberts <[email protected]>
  • Loading branch information
billatarm committed Jan 17, 2024
1 parent f2d2351 commit 393ad05
Showing 1 changed file with 62 additions and 46 deletions.
108 changes: 62 additions & 46 deletions psa-crypto-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ fn main() -> std::io::Result<()> {

#[cfg(any(feature = "interface", feature = "operations"))]
mod common {
pub const CONFIG_FILE: &str = "custom_config.h";

#[cfg(feature = "prefix")]
use bindgen::callbacks::{ItemInfo, ParseCallbacks};

Expand Down Expand Up @@ -84,7 +86,7 @@ mod common {
// Configure the MbedTLS build for making Mbed Crypto
if !::std::process::Command::new(mbedtls_config)
.arg("--write")
.arg(&(out_dir + "/config.h"))
.arg(&(out_dir + "/" + CONFIG_FILE))
.arg("crypto")
.status()
.map_err(|_| Error::new(ErrorKind::Other, "configuring mbedtls failed"))?
Expand Down Expand Up @@ -120,70 +122,74 @@ mod common {
}
}

pub fn generate_mbed_crypto_bindings(mbed_include_dir: String) -> Result<()> {
pub fn generate_mbed_crypto_bindings(
mbed_include_dir: String,
external_mbedtls: bool,
) -> Result<()> {
let header = mbed_include_dir.clone() + "/psa/crypto.h";

println!("using mbedtls include directory of: {}", mbed_include_dir);
println!("cargo:rerun-if-changed={}", header);

let out_dir = env::var("OUT_DIR").unwrap();

#[cfg(not(feature = "prefix"))]
let shim_bindings = bindgen::Builder::default()
// Common shim builder settings
let mut shim_builder = bindgen::Builder::default()
.clang_arg(format!("-I{}", out_dir))
.clang_arg("-DMBEDTLS_CONFIG_FILE=<config.h>")
.clang_arg(format!("-I{}", mbed_include_dir))
.header("src/c/shim.h")
.blocklist_type("max_align_t")
.generate_comments(false)
.size_t_is_usize(true)
.generate()
.map_err(|_| {
Error::new(
ErrorKind::Other,
"Unable to generate bindings to mbed crypto",
)
})?;
.size_t_is_usize(true);

#[cfg(feature = "prefix")]
let shim_bindings = bindgen::Builder::default()
.clang_arg(format!("-I{}", out_dir))
.clang_arg("-DMBEDTLS_CONFIG_FILE=<config.h>")
.clang_arg(format!("-I{}", mbed_include_dir))
.header("src/c/shim.h")
.blocklist_type("max_align_t")
.generate_comments(false)
.size_t_is_usize(true)
.parse_callbacks(Box::new(RenameCallbacks {}))
.generate()
.map_err(|_| {
Error::new(
ErrorKind::Other,
"Unable to generate bindings to mbed crypto",
)
})?;
{
shim_builder = shim_builder.parse_callbacks(Box::new(RenameCallbacks {}));
}

if !external_mbedtls {
shim_builder =
shim_builder.clang_arg(format!("-DMBEDTLS_CONFIG_FILE=\"{}\"", CONFIG_FILE));
}

// Build the bindings
let shim_bindings = shim_builder.generate().map_err(|_| {
Error::new(
ErrorKind::Other,
"Unable to generate bindings to mbed crypto",
)
})?;

let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
shim_bindings.write_to_file(out_path.join("shim_bindings.rs"))?;

Ok(())
}

pub fn compile_shim_library(include_dir: String, metadata: bool) -> Result<PathBuf> {
pub fn compile_shim_library(
include_dir: String,
metadata: bool,
external_mbedtls: bool,
) -> Result<PathBuf> {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());

let shimlib_name = "libmbedcryptoshim.a";

// Compile and package the shim library
cc::Build::new()
.include(&out_dir)
.define("MBEDTLS_CONFIG_FILE", "<config.h>")
let mut cfg = cc::Build::new();
_ = cfg.include(&out_dir)
.include(include_dir)
.file("./src/c/shim.c")
.warnings(true)
.flag("-Werror")
.opt_level(2)
.cargo_metadata(metadata)
.try_compile(shimlib_name)
.cargo_metadata(metadata);

if !external_mbedtls {
_ = cfg.flag(&format!("-DMBEDTLS_CONFIG_FILE=\"{}\"", CONFIG_FILE));
}

cfg.try_compile(shimlib_name)
.map_err(|_| Error::new(ErrorKind::Other, "compiling shim.c failed"))?;

// Also link shim library
Expand All @@ -209,8 +215,8 @@ mod interface {
pub fn script_interface() -> Result<()> {
if let Ok(include_dir) = env::var("MBEDTLS_INCLUDE_DIR") {
common::configure_mbed_crypto()?;
common::generate_mbed_crypto_bindings(include_dir.clone())?;
let _ = common::compile_shim_library(include_dir, true)?;
common::generate_mbed_crypto_bindings(include_dir.clone(), false)?;
let _ = common::compile_shim_library(include_dir, true, false)?;
Ok(())
} else {
Err(Error::new(
Expand Down Expand Up @@ -253,7 +259,10 @@ mod operations {
// Build the MbedTLS libraries
let mbed_build_path = Config::new(&mbedtls_dir)
.cflag(format!("-I{}", out_dir))
.cflag("-DMBEDTLS_CONFIG_FILE='<config.h>'")
.cflag(format!(
"-DMBEDTLS_CONFIG_FILE='\"{}\"'",
common::CONFIG_FILE
))
.define("ENABLE_PROGRAMS", "OFF")
.define("ENABLE_TESTING", "OFF")
.build();
Expand All @@ -276,22 +285,25 @@ mod operations {
let lib;
let statically;
let include;
let external_mbedtls;

if env::var("MBEDTLS_LIB_DIR").is_err() ^ env::var("MBEDTLS_INCLUDE_DIR").is_err() {
return Err(Error::new(
ErrorKind::Other,
"both environment variables MBEDTLS_LIB_DIR and MBEDTLS_INCLUDE_DIR need to be set for operations feature",
));
}
common::configure_mbed_crypto()?;
if let (Ok(lib_dir), Ok(include_dir)) =
(env::var("MBEDTLS_LIB_DIR"), env::var("MBEDTLS_INCLUDE_DIR"))
{
println!("Found environment varibales, using external MbedTLS");
lib = lib_dir;
include = include_dir;
statically = cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok();
external_mbedtls = true;
} else {
println!("Did not find environment variables, building MbedTLS!");
common::configure_mbed_crypto()?;
let mut mbed_lib_dir = compile_mbed_crypto()?;
let mut mbed_include_dir = mbed_lib_dir.clone();
mbed_lib_dir.push("lib");
Expand All @@ -300,12 +312,13 @@ mod operations {
lib = mbed_lib_dir.to_str().unwrap().to_owned();
include = mbed_include_dir.to_str().unwrap().to_owned();
statically = true;
external_mbedtls = false;
}

// Linking to PSA Crypto library is only needed for the operations.
link_to_lib(lib, statically);
common::generate_mbed_crypto_bindings(include.clone())?;
match common::compile_shim_library(include, false) {
common::generate_mbed_crypto_bindings(include.clone(), external_mbedtls)?;
match common::compile_shim_library(include, false, external_mbedtls) {
Ok(_) => Ok(()),
Err(e) => Err(e),
}
Expand All @@ -320,10 +333,12 @@ mod operations {
"both environment variables MBEDTLS_LIB_DIR and MBEDTLS_INCLUDE_DIR need to be set for operations feature",
));
}
common::configure_mbed_crypto()?;

if let (Ok(lib_dir), Ok(include_dir)) =
(env::var("MBEDTLS_LIB_DIR"), env::var("MBEDTLS_INCLUDE_DIR"))
{
println!("Building with external MBEDTLS");

// Request rustc to link the Mbed Crypto library
let link_type = if cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok() {
"static"
Expand All @@ -333,19 +348,20 @@ mod operations {
println!("cargo:rustc-link-search=native={}", lib_dir);
println!("cargo:rustc-link-lib={}=mbedcrypto", link_type);

common::generate_mbed_crypto_bindings(include_dir.clone())?;
let _ = common::compile_shim_library(include_dir, true)?;
common::generate_mbed_crypto_bindings(include_dir.clone(), true)?;
let _ = common::compile_shim_library(include_dir, true, true)?;
} else {
println!("Did not find environment variables, building MbedTLS!");
common::configure_mbed_crypto()?;
let mut mbed_lib_dir = compile_mbed_crypto()?;
let mut mbed_include_dir = mbed_lib_dir.clone();
mbed_lib_dir.push("lib");
mbed_include_dir.push("include");
let main_lib = mbed_lib_dir.join("libmbedcrypto.a");

let include = mbed_include_dir.to_str().unwrap().to_owned();
common::generate_mbed_crypto_bindings(include.clone())?;
let shim_lib = common::compile_shim_library(include, false)?;
common::generate_mbed_crypto_bindings(include.clone(), false)?;
let shim_lib = common::compile_shim_library(include, false, false)?;

// Modify and copy the libraries into a new directory.
let llib_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("llib");
Expand Down

0 comments on commit 393ad05

Please sign in to comment.