PARSEC: Provider of Trusted Services

Michael Zhao
6 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 Trusted Services firmware as a provider of PARSEC.

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

What is Trusted Services

Trusted Services is an opensource project under the Trusted Firmware organization.

The term ‘trusted service’ is used as a general name for a class of application that runs in an isolated processing environment. Other applications rely on trusted services to perform security related operations in a way that avoids exposing secret data beyond the isolation boundary of the environment.

In very simple words, a trusted service is a service running in the secure world of ARM TrustZone for security purpose.

You can find its document here, and its source code here.

The following diagram shows the principle of how the Trusted Services works:

A quick introduction of the diagram:

  • Trusted Services runs in the secure world as Secure Partitions that are scheduled by a Secure Partition Manger (SPM, an operating system in the secure world)
  • In normal (non-secure) world, user space applications can call the trusted services via RPC. A library libts.so is deployed on Linux to provide the API for the RPC.
  • The RPC between user space application and the trusted service goes through Linux kernel, the secure monitor (usually it’s TrustedFirmware-A) and the SPM. The interface is defined by the spec Arm Firmware Framework for Arm A-profile (FF-A)[1].

PARSEC can use Trusted Services as the provider/backend. In this scenario, PARSEC sits in the position of Client App in the diagram. It calls the API of libts.so to invoke the trusted services in the secure world.

PARSEC with Trusted Services

Build Trusted Services

Please refer to the build-instructions document for all information about the build.

Trusted Services use the concept of deployment to manage the build of an assembly of components that is intended to run within a specific environment.

linux-pc Deployment

In this section I will build the deployment of libts that is going to be deployed on Linux PC environment. The CMakeLists.txt for the build is in folder deployments/libts/linux-pc.

Follow the instructions to build the libts library:

> git clone https://git.trustedfirmware.org/TS/trusted-services.git
> cd trusted-services/deployments/libts/linux-pc
> cmake -S . -B build
> cd build
> make

When the make command finish successfully, libts.so should be generated.

The deployment of libts on linux-pc is for test purpose only. It doesn’t actually communicate to any secure partition via the RPC, because on Linux PC the secure partition is not available. Instead, the libts.so includes the service binary in itself. When you call a API, the service is done via local function calls in the library.

arm-linux Deployment

If you need the libts.so for an environment where Trust Zone is available and secure partition is deployed, you should move to trusted-services/deployments/libts/arm-linux and build. That way, the generated libts.so contains only the RPC APIs, not the fake implementation. If you check the function symbols of the libts.so of arm-linux build, you will see only a few rpc_* (for RPC) and service_* (for service locating) functions:

> cd trusted-services/deployments/libts/arm-linux/build
> nm -D libts.so | grep " T "
00000000000043ec T rpc_caller_begin
0000000000004474 T rpc_caller_end
0000000000004424 T rpc_caller_invoke
00000000000043c8 T rpc_caller_set_encoding_scheme
0000000000004668 T service_context_close
0000000000004610 T service_context_open
000000000000469c T service_context_relinquish
00000000000044a8 T service_locator_init
0000000000004578 T service_locator_query

Build PARSEC

To work with Trusted Services, PARSEC has to be built with a non-default feature trusted-service-provider:

> cargo build --features "direct-authenticator,trusted-service-provider"

The build process is:

  • Clone a trusted-services submodule inside PARSEC repo
  • Generate C binding source files
  • Compile PARSEC source code
  • Link with libts.so

Next, let me break down the build process into several steps and illustrate how each step is done.

Rusting Binding of C Code

PARSEC source code repository contains a submodule of Trusted Services. Before building PARSEC you need to fetch the code of it:

> # move to the PARSEC source code folder
> cd parsec
> git submodule update --init

PARSEC has a build.rs for customizing the build process. By leveraging bindgen, PARSEC creates the binding (Rust version of the C files) of following header files:

  • components/service/locator/interface/service_locator.h
  • protocols/rpc/common/packed-c/encoding.h

These 2 files are located in the submodule folders. The APIs declared in them are used for RPC communication between FF-A components.

Build

Build with command:

> cargo build --features "direct-authenticator,trusted-service-provider"

With trusted-service-provider you enabled the Trusted Services backend/provider. But in the first build, you should run into a build error:

  = note: /usr/bin/ld: cannot find -lts
collect2: error: ld returned 1 exit status

The reason is that PARSEC need to link the local libts.so for the APIs writen in C, but the compiler cannot find the library. I chose to build the Trusted Services user space library and copy it to a folder that the compiler searches (I ignored the steps to install the prerequisite for building Trusted Services, please refer to its document[2]):

> # Clone Trusted Services source code
> https://git.trustedfirmware.org/TS/trusted-services.git

> # Build the library for Linux PC test
> cd trusted-services/deployments/libts/linux-pc
> cmake -S . -B build
> cd build
> make

> # Copy the library
> cp libts.so.1.0.0 /path/to/parsec/target/debug/deps/libts.so

Then the PARSEC build should continue successfully.

Test

Before testing the Trusted Services provider, you need to update your configuration file to enable it.

Here comes an example configuration file, please pay attention to the last section of [[provider]], which adds the Trusted Services as a backend (it is also the only backend in this example).

# test-config.toml: Configuration file with Trusted Services provider

[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]]
# (Optional) The name of the provider
name = "trusted-service-provider"
# (Required) Type of provider.
provider_type = "TrustedService"
# (Required) Name of key info manager that will support this provider.
key_info_manager = "on-disk-manager"

Now it’s time to start the PARSEC server: (The following command comes with a LD_LIBRARY_PATH environment variable setting to find the libts.so. )

> LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/trusted-services/deployments/libts/linux-pc/build RUST_LOG=info ./target/debug/parsec -c test-config.toml
...
[INFO parsec] Parsec is ready.

Start another shell window for parsec-tool, and use list-providers subcommand to check whether the Trusted Service provider is working or not:

> PARSEC_SERVICE_ENDPOINT=unix:/tmp/parsec.sock ./target/debug/parsec-tool list-providers
[INFO ] Available providers:
ID: 0x04 (Trusted Service provider)
Description: Provider exposing functionality provided by the Crypto Trusted Service running in a Trusted Execution Environment
Version: 0.1.0
Vendor: Arm
UUID: 71129441-508a-4da6-b6e8-7b98a777e4c0

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

Reference

  1. https://developer.arm.com/documentation/den0077/latest
  2. https://trusted-services.readthedocs.io/en/latest/

--

--