PARSEC: Provider of Trusted Services
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:
- PARSEC Introduction
- PARSEC Architecture
- PARSEC Client & Interface
- PARSEC Server
- PARSEC Provider: Mbed TLS
- PARSEC Provider: TPM
- PARSEC Provider: Trusted Services (this one)
- PARSEC Deployment
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