PARSEC: Provider of Mbed Crypto

Michael Zhao
5 min readApr 30, 2023

--

PARSEC, the Platform AbstRaction for SECurity, is an open-source initiative to provide a common API to hardware security and cryptographic services in a platform-agnostic way.

PARSEC is a Cloud Native Compute Foundation Sandbox project, hosted on Github.

In this article I will introduce how to integrate Mbed TLS as a provider of PARSEC.

This article is (will be) among a series that cover following aspects of PARSEC:

What is Mbed Crypto

Mbed Crypto is part of Mbed TLS.

Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. The project provides reference implementation of PSA Cryptography API Specification by supporting the cryptographic operations via. PSA Crypto APIs.

Mbed TLS produces 3 libraries:

  • libmbedcrypto: Crypto library, complying with the PSA Crypto API
  • libmbedx509: X509 library
  • libmbedtls: TLS library

PARSEC has a provider that use the Mbed Crypto library (libmbedcrypto) as backend. With the backend, the cryptograph function provided by PARSEC is actually served by Mbed TLS.

PSA Cryptography API Rust Wrapper

PARSEC server invokes Mbed Crypto library via a wrapper, which is a separate repository under the same project of PASEC:
rust-psa-crypto.

rust-psa-crypto produces 2 wrapper crates:

  • psa-crypto-sys: A lower-level wrapper that exposes low-level C interface for the PSA Crypto API. It links to the Mbed Crypto library of Mbed TLS.
  • psa-crypto: A higher-level, more Rust-friendly interface for PSA Crypto.

In PARSEC server, what’s called by the Mbed Crypto provider is psa-crypto. psa-crypto furtherly invokes the crypto interface exposed from psa-crypto-sys via a shim.

Build Process of rust-psa-crypto

Among the 2 crates that created by rust-psa-crypto, the build process of psa-crypto-sys is more complex, as it binds to local C code.

In the rust-psa-crypto repository, folder psa-crypto-sys has its own build script: build.rs. And the folder has a submodule that clones Mbed TLS, Before building the crate, you need to initialize the submodule:

> git clone https://github.com/parallaxsecond/rust-psa-crypto.git
> cd rust-psa-crypto
> git submodule update --init

The build script generates a shim layer for invoking the Mbed TLS: shim.c & shim.h. And using the Rust bindgen crate, the build script generates the Rust binding of the shim code.

Link Statically or Dynamically

By default, psa-crypto-sys links the C code of the Mbed TLS sub module statically. But it also provides a way for dynamically linking an external Mbed Crypto library.

psa-crypto-sys uses some environment variables to determine the choices of linkage:

  • MBEDTLS_LIB_DIR: The folder that contains the libmbedcrypto.so file
  • MBEDTLS_INCLUDE_DIR: The folder that contains the header files of MbedTLS. Usually it should be the include folder of the MbedTLS source code.

The build script checks if these 2 variables exist. If they are defined and are valid, the library libmbedcrypto.so will be dynamically linked to psa-crypto-sys. That means you need to gaurantee that the library can be found by the ELF loader in runtime.

For the sake of flexibility, the build script checks another environment variable MBEDCRYPTO_STATIC or the feature static: if anyone of them is set, the Mbed TLS will be linked statically anyway.

Build & Test

In PARSEC, the default cargo build build instruction links the Mbed Crypto library statically. But in this section, I will show how to build in the way of dynamic linkage.

Build Mbed TLS Library

Build Mbed TLS to have the Mbed Crypto library:

> git clone https://github.com/Mbed-TLS/mbedtls.git
> cd mbedtls
> mkdir build
> cd build
> cmake -DUSE_SHARED_MBEDTLS_LIBRARY=On ../
> cmake --build .

When finished, the libmbedcrypto.so file should be present in folder build/library.

Build PARSEC

Here comes the instructions for building PARSEC server. Please pay attention to the environment variables setting.

> # Set the 2 variables for dynamically linkage of libmbedcrypto.so
> export MBEDTLS_INCLUDE_DIR=/path/to/mbedtls/include
> export MBEDTLS_LIB_DIR=/path/to/mbedtls/build/library

> # Move to your PARSEC source code directory
> cd /path/to/parsec
> cargo build --features "mbed-crypto-provider,direct-authenticator"

Please notice: if you didn’t set the MBEDTLS_* environment variables, PARSEC builds as well. But the Mbed Crypto was linked statically.

You can use ldd command to check how the Mbed Crypto library was linked.

If the Mbed Crypto library was linked statically:

> ldd target/debug/parsec
linux-vdso.so.1 (0x00007ffc28da0000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f3a9a212000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3a9a1ef000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f3a9a0a0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f3a9a09a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3a9940e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3a9a246000)

But if it was dynamically linked, the libmbedcrypto.so is among the list:

> ldd target/debug/parsec
linux-vdso.so.1 (0x00007ffd9bb76000)
libmbedcrypto.so.14 => /path/to/mbedtls/build/library/libmbedcrypto.so.14 (0x00007efe7e342000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007efe7ee2d000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007efe7e31f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007efe7e1d0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007efe7ee27000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efe7dfde000)
/lib64/ld-linux-x86-64.so.2 (0x00007efe7ee61000)

Test

Before starting the PARSEC server, create a configuration file with the Mbed Crypto provider enabled (at the bottom lines):

# mbed-config.toml: Configuration file for Mbed Crypto

[core_settings]
# The CI already timestamps the logs
log_timestamp = false
log_error_details = true

# The container runs the Parsec service as root, so make sure we disable root
# checks.
allow_root = true
# Allow deprecated for testing
allow_deprecated = true

[listener]
listener_type = "DomainSocket"
# The timeout needs to be smaller than the test client timeout (five seconds) as it is testing
# that the service does not hang for very big values of body or authentication length.
timeout = 3000 # in milliseconds
socket_path = "/tmp/parsec.sock"

[authenticator]
auth_type = "Direct"

[[key_manager]]
name = "on-disk-manager"
manager_type = "OnDisk"
store_path = "./mappings"

[[provider]]
# Enable the provider of Mbed Crypto
provider_type = "MbedCrypto"
key_info_manager = "on-disk-manager"

To start the PARSEC server:

> # Make sure libmbedcrypto.so can be found by the ELF loader
> export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/mbedtls/build/library
> RUST_LOG=info ./target/debug/parsec -c mbed-config.toml

Use parsec-tool to verify the provider is working:

# Move to parsec-tool source code folder
> cd /path/to/parsec-tool

# Check the liveness of the server
> PARSEC_SERVICE_ENDPOINT=unix:/tmp/parsec.sock ./target/debug/parsec-tool ping
[INFO ] Service wire protocol version
1.0

# List the providers
> PARSEC_SERVICE_ENDPOINT=unix:/tmp/parsec.sock ./target/debug/parsec-tool list-providers
[INFO ] Available providers:
ID: 0x01 (Mbed Crypto provider)
Description: User space software provider, based on Mbed Crypto - the reference implementation of the PSA crypto API
Version: 0.1.0
Vendor: Arm
UUID: 1c1139dc-ad7c-47dc-ad6b-db6fdb466552

ID: 0x00 (Core provider)
Description: Software provider that implements only administrative (i.e. no cryptographic) operations
Version: 1.2.0
Vendor: Unspecified
UUID: 47049873-2a43-4845-9d72-831eab668784

--

--