Skip to content

Commit

Permalink
Add an interface feature only using include files
Browse files Browse the repository at this point in the history
For some use-cases, for example building a Secure Element driver, it is
only needed to have an abstraction over the PSA Crypto API include files
but not the operations. The new interface feature is made for that.

Fix parallaxsecond#38

Signed-off-by: Hugues de Valon <hugues.devalon@arm.com>
  • Loading branch information
hug-dev committed Jul 9, 2020
1 parent aed8881 commit f74d0db
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 103 deletions.
10 changes: 7 additions & 3 deletions ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ cargo build --no-default-features
popd
pushd psa-crypto
cargo build --no-default-features
cargo build --no-default-features --features with-mbed-crypto
cargo build --no-default-features --features operations
cargo build --no-default-features --features no-std

# Test dynamic linking
Expand All @@ -57,10 +57,14 @@ git checkout mbedtls-2.22.0
SHARED=1 make
popd

# Build the driver, clean before to force dynamic linking
# Clean before to force dynamic linking
cargo clean
MBEDTLS_LIB_DIR=$(pwd)/mbedtls/library MBEDTLS_INCLUDE_DIR=$(pwd)/mbedtls/include cargo build --release

# Build the driver, clean before to force static linking
# Clean before to force static linking
cargo clean
MBEDTLS_LIB_DIR=$(pwd)/mbedtls/library MBEDTLS_INCLUDE_DIR=$(pwd)/mbedtls/include MBEDCRYPTO_STATIC=1 cargo build --release

# Clean before to only build the interface
cargo clean
MBEDTLS_INCLUDE_DIR=$(pwd)/mbedtls/include cargo build --release
5 changes: 3 additions & 2 deletions psa-crypto-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ cc = "1.0.54"
cmake = "0.1.44"

[features]
default = ["implementation-defined"]
default = ["operations"]
static = []
implementation-defined = []
interface = []
operations = ["interface"]
10 changes: 7 additions & 3 deletions psa-crypto-sys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,12 @@ requirements for configuring and building MbedTLS can be found
[on their repository homepage](https://github.com/ARMmbed/mbedtls#tool-versions).

Linking and generating implementation-specific APIs is controlled by the
`implementation-defined` feature that is enabled by default. Therefore, if you
require only the spec-defined bits of the API (namely the constants and types)
`operations` feature that is enabled by default. Therefore, if you
require only the specification-defined bits of the API (namely the constants and types)
you can simply disable default features.

Currently the version of MbedTLS built is 2.22.0
You might want to only use the interface part (including the
implementation-defined bits) of this crate to build for example a PSA Secure
Element Driver. With the feature `interface`, this crate will only produce the
implementation-defined types and their helpers/accessors using the
`MBEDTLS_INCLUDE_DIR` variable that you need to pass.
73 changes: 45 additions & 28 deletions psa-crypto-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,7 @@ fn compile_shim_library(include_dir: String) -> Result<()> {
.flag("-Werror")
.opt_level(2)
.try_compile("libshim.a")
.or_else(|_| Err(Error::new(ErrorKind::Other, "compiling shim.c failed")))
}

fn link_to_lib(lib_path: String, link_statically: bool) -> Result<()> {
let link_type = if link_statically { "static" } else { "dylib" };

// Request rustc to link the Mbed Crypto library
println!("cargo:rustc-link-search=native={}", lib_path,);
println!("cargo:rustc-link-lib={}=mbedcrypto", link_type);
.or_else(|_| Err(Error::new(ErrorKind::Other, "compiling shim.c failed")))?;

// Also link shim library
println!(
Expand All @@ -118,35 +110,60 @@ fn link_to_lib(lib_path: String, link_statically: bool) -> Result<()> {
Ok(())
}

fn link_to_lib(lib_path: String, link_statically: bool) {
let link_type = if link_statically { "static" } else { "dylib" };

// Request rustc to link the Mbed Crypto library
println!("cargo:rustc-link-search=native={}", lib_path,);
println!("cargo:rustc-link-lib={}=mbedcrypto", link_type);
}

fn main() -> Result<()> {
if !cfg!(feature = "implementation-defined") {
if !(cfg!(feature = "interface") || cfg!(feature = "operations")) {
return Ok(());
}
let lib;

let include;
let statically;

if let (Ok(lib_dir), Ok(include_dir)) =
(env::var("MBEDTLS_LIB_DIR"), env::var("MBEDTLS_INCLUDE_DIR"))
{
lib = lib_dir;
include = include_dir;
statically = cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok();
if cfg!(feature = "operations") {
let lib;
let statically;

if let (Ok(lib_dir), Ok(include_dir)) =
(env::var("MBEDTLS_LIB_DIR"), env::var("MBEDTLS_INCLUDE_DIR"))
{
lib = lib_dir;
include = include_dir;
statically = cfg!(feature = "static") || env::var("MBEDCRYPTO_STATIC").is_ok();
} else {
println!("Did not find environment variables, building MbedTLS!");
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");

lib = mbed_lib_dir.to_str().unwrap().to_owned();
include = mbed_include_dir.to_str().unwrap().to_owned();
statically = true;
}

// Linking to PSA Crypto library is only needed for the operations.
link_to_lib(lib, statically);
} else if cfg!(feature = "interface") {
if let Ok(include_dir) = env::var("MBEDTLS_INCLUDE_DIR") {
include = include_dir;
} else {
return Err(Error::new(
ErrorKind::Other,
"interface feature necessitates MBEDTLS_INCLUDE_DIR environment variable",
));
}
} else {
println!("Did not find environment variables, building MbedTLS!");
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");

lib = mbed_lib_dir.to_str().unwrap().to_owned();
include = mbed_include_dir.to_str().unwrap().to_owned();
statically = true;
return Ok(());
}

generate_mbed_crypto_bindings(include.clone())?;
compile_shim_library(include)?;
link_to_lib(lib, statically)?;

Ok(())
}
3 changes: 0 additions & 3 deletions psa-crypto-sys/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,3 @@ pub const PSA_KEY_USAGE_VERIFY: psa_key_usage_t = 2048;
pub const PSA_KEY_USAGE_DERIVE: psa_key_usage_t = 4096;
pub const PSA_KEY_ID_USER_MIN: psa_key_id_t = 0x0000_0001;
pub const PSA_KEY_ID_USER_MAX: psa_key_id_t = 0x3fff_ffff;

#[cfg(feature = "implementation-defined")]
pub const PSA_DRV_SE_HAL_VERSION: u32 = 5;
16 changes: 9 additions & 7 deletions psa-crypto-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,36 +21,38 @@
trivial_casts
)]
#[allow(clippy::all)]
#[cfg(feature = "implementation-defined")]
#[cfg(feature = "interface")]
mod psa_crypto_binding {
include!(concat!(env!("OUT_DIR"), "/shim_bindings.rs"));
}

#[allow(dead_code)]
mod constants;
#[allow(dead_code)]
#[cfg(feature = "implementation-defined")]
#[cfg(feature = "interface")]
mod shim_methods;
#[allow(dead_code)]
mod types;

pub use constants::*;
pub use types::*;

#[cfg(feature = "implementation-defined")]
#[cfg(feature = "operations")]
pub use psa_crypto_binding::{
psa_asymmetric_decrypt, psa_asymmetric_encrypt, psa_close_key, psa_crypto_init,
psa_destroy_key, psa_export_public_key, psa_generate_key, psa_get_key_attributes,
psa_import_key, psa_key_attributes_t, psa_open_key, psa_reset_key_attributes, psa_sign_hash,
psa_verify_hash,
psa_import_key, psa_open_key, psa_reset_key_attributes, psa_sign_hash, psa_verify_hash,
};

#[cfg(feature = "interface")]
pub use psa_crypto_binding::psa_key_attributes_t;

// Secure Element Driver definitions
#[cfg(feature = "implementation-defined")]
#[cfg(feature = "interface")]
pub use psa_crypto_binding::{
psa_drv_se_asymmetric_t, psa_drv_se_context_t, psa_drv_se_key_management_t, psa_drv_se_t,
psa_key_creation_method_t, psa_key_slot_number_t,
};

#[cfg(feature = "implementation-defined")]
#[cfg(feature = "interface")]
pub use shim_methods::*;
5 changes: 3 additions & 2 deletions psa-crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ rsa = "0.3.0"
rand = "0.7.3"

[features]
default = ["with-mbed-crypto", "no-std"]
with-mbed-crypto = ["psa-crypto-sys/implementation-defined"]
default = ["operations", "no-std"]
operations = ["psa-crypto-sys/operations", "interface"]
interface = ["psa-crypto-sys/interface"]
no-std = []
18 changes: 11 additions & 7 deletions psa-crypto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ This is the higher-level, more Rust-friendly interface.

## Mbed Crypto backing

The `psa-crypto` comes by default with Mbed Crypto backing for
the interface exposed. If the functionality of the library is
not important/relevant, the interface type system (that offers
functionality for identifying cryptographic algorithms and
modelling key metadata) can be used independently by disabling
the default features of the crate. The feature adding the Mbed
Crypto support is `with-mbed-crypto`.
The features of this crate can modify what is compiled in from the PSA Crypto
specification:
* `operations`: everything is included. The `psa-crypto-sys` crate statically
links by default Mbed Crypto. See the documentation of [that
crate](https://github.com/parallaxsecond/rust-psa-crypto/tree/master/psa-crypto-sys)
to see how to modify the linking options. This feature is activated by default.
* `interface`: only the abstraction over the PSA Crypto interface (types,
helper methods) are included. The `MBEDTLS_INCLUDE_DIR` environment variable
is needed to produce Rust shims around PSA Crypto macros.
* without any of the above: only the specification-defined parts are included.
It will only include the specification-defined types.
13 changes: 6 additions & 7 deletions psa-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,18 @@
// This one is hard to avoid.
#![allow(clippy::multiple_crate_versions)]

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "operations")]
pub mod operations;
pub mod types;

#[cfg(feature = "with-mbed-crypto")]
pub use psa_crypto_sys as ffi;

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "operations")]
use core::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "operations")]
use types::status::{Error, Result, Status};

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "operations")]
static INITIALISED: AtomicBool = AtomicBool::new(false);

/// Initialize the PSA Crypto library
Expand All @@ -71,7 +70,7 @@ static INITIALISED: AtomicBool = AtomicBool::new(false);
/// // Can be called twice
/// init().unwrap();
/// ```
#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "operations")]
pub fn init() -> Result<()> {
// It is not a problem to call psa_crypto_init more than once.
Status::from(unsafe { psa_crypto_sys::psa_crypto_init() }).to_result()?;
Expand All @@ -89,7 +88,7 @@ pub fn init() -> Result<()> {
/// init().unwrap();
/// initialized().unwrap();
/// ```
#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "operations")]
pub fn initialized() -> Result<()> {
if INITIALISED.load(Ordering::Relaxed) {
Ok(())
Expand Down
26 changes: 13 additions & 13 deletions psa-crypto/src/types/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
#![allow(deprecated)]

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
use crate::types::status::{Error, Result};
#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
use core::convert::{TryFrom, TryInto};
#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
use log::error;
use serde::{Deserialize, Serialize};
use zeroize::Zeroize;
Expand Down Expand Up @@ -538,7 +538,7 @@ impl From<KeyDerivation> for Algorithm {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Algorithm {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
Expand Down Expand Up @@ -575,7 +575,7 @@ impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Algorithm {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl TryFrom<Algorithm> for psa_crypto_sys::psa_algorithm_t {
type Error = Error;
fn try_from(alg: Algorithm) -> Result<Self> {
Expand All @@ -592,7 +592,7 @@ impl TryFrom<Algorithm> for psa_crypto_sys::psa_algorithm_t {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Hash {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
Expand Down Expand Up @@ -620,7 +620,7 @@ impl TryFrom<psa_crypto_sys::psa_algorithm_t> for Hash {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl From<Hash> for psa_crypto_sys::psa_algorithm_t {
fn from(hash: Hash) -> Self {
match hash {
Expand All @@ -643,7 +643,7 @@ impl From<Hash> for psa_crypto_sys::psa_algorithm_t {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for SignHash {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
Expand All @@ -655,7 +655,7 @@ impl TryFrom<psa_crypto_sys::psa_algorithm_t> for SignHash {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl From<SignHash> for psa_crypto_sys::psa_algorithm_t {
fn from(sign_hash: SignHash) -> Self {
match sign_hash {
Expand All @@ -665,7 +665,7 @@ impl From<SignHash> for psa_crypto_sys::psa_algorithm_t {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for AsymmetricSignature {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
Expand Down Expand Up @@ -699,7 +699,7 @@ impl TryFrom<psa_crypto_sys::psa_algorithm_t> for AsymmetricSignature {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl From<AsymmetricSignature> for psa_crypto_sys::psa_algorithm_t {
fn from(asym_sign: AsymmetricSignature) -> Self {
match asym_sign {
Expand All @@ -723,7 +723,7 @@ impl From<AsymmetricSignature> for psa_crypto_sys::psa_algorithm_t {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl TryFrom<psa_crypto_sys::psa_algorithm_t> for AsymmetricEncryption {
type Error = Error;
fn try_from(alg: psa_crypto_sys::psa_algorithm_t) -> Result<Self> {
Expand All @@ -743,7 +743,7 @@ impl TryFrom<psa_crypto_sys::psa_algorithm_t> for AsymmetricEncryption {
}
}

#[cfg(feature = "with-mbed-crypto")]
#[cfg(feature = "interface")]
impl From<AsymmetricEncryption> for psa_crypto_sys::psa_algorithm_t {
fn from(asym_encrypt: AsymmetricEncryption) -> Self {
match asym_encrypt {
Expand Down
Loading

0 comments on commit f74d0db

Please sign in to comment.