-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First end-to-end working prototype of the TPS Client APIs
An end-to-end working demo of the TPS Client APIs which should work on any desktop class machine, and should be easily portable into constrained embedded devices as the Rust components do not require the Rust standard library (c_example requires a C library currently) There is a very basic demo of how to write a connector and TPS Service in Rust - ROT13. - tps_error: Common Rust error handling for TPS crates - tps_connector: Common Connector API definitions - tps_client_common: Common definitions for TPS crates (no dependencies) - tps_client_c: C language API (and example program) for the TPS Client API - tps_client_api: The TPS Client API Rust library At this point the code is of "demo" quality and intended to show the basic operation of the APIs. Code should be thread-safe, but has not been extensively tested. Signed-off-by: Jeremy O'Donoghue <[email protected]>
- Loading branch information
1 parent
2625c50
commit 0c27126
Showing
39 changed files
with
4,893 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Copyright © 2022, Qualcomm Innovation Center, Inc. All rights reserved. | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | ||
# documentation files (the “Software”), to deal in the Software without restriction, including without limitation | ||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and | ||
# to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in all copies or substantial portions | ||
# of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | ||
# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
# SOFTWARE. | ||
|
||
cmake_minimum_required(VERSION 3.20) | ||
project(tps_client_api C) | ||
|
||
set(CMAKE_C_STANDARD 99) | ||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake_rust") | ||
enable_language(Rust) | ||
include(CMakeCargo) | ||
|
||
include_directories(tps_client_c) | ||
|
||
add_subdirectory(tps_client_c) | ||
add_subdirectory(rot13_connector) | ||
add_subdirectory(tps_client_c/c_example) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# Copyright (c) 2021, 2022, Qualcomm Innovation Center, Inc. All rights reserved. Jeremy O'Donoghue. All rights reserved. | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software | ||
# and associated documentation files (the “Software”), to deal in the Software without | ||
# restriction, including without limitation the rights to use, copy, modify, merge, publish, | ||
# distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the | ||
# Software is furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in all copies or | ||
# substantial portions of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | ||
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
[workspace] | ||
|
||
members = [ | ||
"rs_minicbor", | ||
"rs_cddl", | ||
"tps_client_common", | ||
"tps_error", | ||
"tps_client_api", | ||
"tps_client_c", | ||
"tps_connector", | ||
"rot13_connector", | ||
"rot13_service" | ||
] | ||
|
||
[profile.release] | ||
opt-level = 'z' | ||
lto = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,115 @@ | ||
# TPS API Reference Implementations | ||
## TPS Client API | ||
|
||
This project provides a set of reference implementations for specifications created | ||
by the [GlobalPlatform](https://globalplatform.org) Trusted Platform Services | ||
Committee and its Working Groups. | ||
## Overview | ||
|
||
The Trusted Platform Services Committee aims to create APIs which allow application | ||
developers to use standardized security services hosted on Secure Components such as | ||
a Trusted Execution Environment, a Secure Element or a Trusted Platform Module (TPM). | ||
This crate contains a reference implementation of the GlobalPlatform TPS Client API. | ||
This implementation is intended to be suitable for relatively constrained embedded targets. | ||
|
||
The Client API is implemented as a library which can be linked with anything that | ||
exposes a C language FFI (which means virtually anything). It also provides a Rust | ||
API to simplify integration with applications written in Rust. | ||
|
||
Communication with Secure Components is provided by _Connectors_ which provide an | ||
abstract service-oriented interface to TPS Services implemented on Secure Components. | ||
|
||
The implementations are intended to support `no_std` environments and thus have no | ||
dependency on the Rust standard library. | ||
|
||
The Trusted Platform Services APIs make heavy use of | ||
[CBOR](https://www.rfc-editor.org/info/rfc8949) and related technologies such as | ||
[COSE](https://www.rfc-editor.org/info/rfc8152) and | ||
[CDDL](https://www.rfc-editor.org/info/rfc8610), which are standardized by the IETF. | ||
|
||
The reference implementations on this site are, where appropriate, intended to be | ||
usable on relatively constrained embedded microcontroller platforms (circa 200-500kB RAM/ROM). | ||
This project is composed of multiple sub-crates: | ||
|
||
As this is a new project, we have preference for contributions in the | ||
[Rust](https://rust-lang.org) programming language. | ||
- `tps_client_api` implements most of the Client API functionality in a Rust crate. | ||
- `tps_client_api_c` creates a statically linkable C library with a C language API | ||
which allows the TPS Client API to be used anywhere that supports a C language FFI. | ||
This library includes `tps_client_api`, and is able to connect to libraries that | ||
export the `tps_connector` API. | ||
- `tps_client_common` provides definitions that are used across multiple crates in | ||
a system. It has no dependencies. | ||
- `tps_error` contains error definitions for any crate using the TPS API ecosystem. | ||
- `tps_connector` defines an API which enables security component back-ends to be | ||
called from `tps_client_api`. Both Rust and C language APIs are provided, | ||
allowing Connector instances to be written in either language. | ||
- `rot13_connector` provides a minimal implementation of the TPS Connector API | ||
- `rot13_service` provides a minimal implementation of a TPS Service (in this case, ROT13 | ||
"encryption). | ||
- `rs_minicbor` is an implementation of [IETF CBOR (RFC8949)](https://www.rfc-editor.org/rfc/rfc8949.html) | ||
encoding and decoding, with no requirement for an allocator or the standard | ||
library. | ||
|
||
## License | ||
|
||
Contributions *and their dependencies* must be MIT licensed or provided under a | ||
compatible license. Dual-licensed (Apache 2 OR MIT) dependencies, which are | ||
common in the Rust language ecosystem, are fine. | ||
All parts of the TPS Client API are MIT licensed, See LICENSE. | ||
|
||
## Building | ||
|
||
> The current version of the project is built using CMake. This is likely to change | ||
> in a future version to a build system based entirely on Cargo. | ||
The build system is in a state of flux, and doesn't manage generated header files as | ||
it should. The following instructions should enable you to build and run the example | ||
and tests. | ||
|
||
### Build dependencies | ||
|
||
You will need to have the following installed: | ||
|
||
- Rust toolchain (tested for Rust v1.64.0) | ||
- [cbindgen](https://github.com/eqrion/cbindgen) | ||
- `cargo install --force cbindgen` is easiest way to install. | ||
- CMake (tested for version 3.20 - this is set as a lower bound in the scripts, so | ||
older versions will not work) | ||
- Install from [CMake downloads](https://cmake.org/download/) or your package manager. | ||
- [CMakeRust](https://github.com/Devolutions/CMakeRust) | ||
- Instructions to use CMakeRust can be found on | ||
[Devolutions blog](https://blog.devolutions.net/2018/06/insider-series-using-rust-code-in-a-cc-project-with-cmake/) | ||
|
||
#### Using CMakeRust in the build system | ||
|
||
Create a directory in the top of the repo for CMakeRust: | ||
|
||
`cd <path_to_tps_repository>` | ||
`mkdir cmake_rust` | ||
|
||
Copy the contents of the cmake directory in the CMakeRust repository into the `cmake_rust` directory. I have | ||
the following files: | ||
|
||
- `CargoLink.cmake` | ||
- `CMakeCargo.cmake` | ||
- `CMakeDetermineRustCOmpiler.cmake` | ||
- `CMakeRustCompiler.cmake.in` | ||
- `CMakeRustInformation.cmake` | ||
- `CMakeTestRustCompiler.cmake` | ||
- `FindRust.cmake` | ||
- Various license files. | ||
|
||
Credit to the team at [Devolutions](https://devolutions.net) for CMakeRust, which is dual MIT/Apache2 licensed. | ||
|
||
### Building the example | ||
|
||
This assumes that you are in the top directory of the repository. | ||
|
||
`cd <path_to_tps_repository` | ||
|
||
Next, create a directory for CMake artifacts | ||
|
||
`mkdir cmake-build-debug` | ||
|
||
Now you need to build everything with Cartgo, as this generates headers. | ||
|
||
`cargo build` | ||
|
||
This takes 30 seconds or so on my moderately powerful laptop with a decent internet connection. | ||
|
||
The easiest way to verify license conditions is to install `cargo license` and | ||
run it inside each crate. | ||
``` | ||
cd cmake-build-debug | ||
cmake .. | ||
cd .. | ||
cmake --build cmake-build-debug | ||
``` | ||
|
||
## Components | ||
### Running the Example | ||
|
||
- [**`rs_minicbor`**](rs_minicbor/README.md): An implementation of | ||
[RFC 8949 Concise Binary Object Representation (CBOR)](https://www.rfc-editor.org/rfc/rfc8949) | ||
intended for use on embedded platforms, or other places where the developer requires more | ||
control over serialization and deserialization than something like SERDE CBOR. | ||
- [**`rs_cddl`**](rs_cddl/README.md): Tooling for working with | ||
[RFC8610 Concise Data Definition Language](https://www.rfc-editor.org/rfc/rfc8610.txt). This | ||
tooling is at an early development phase, but does include a complete CDDL parser and AST. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Copyright © 2022 Qualcomm Innovation Center, Inc. All rights reserved. | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | ||
# documentation files (the “Software”), to deal in the Software without restriction, including without limitation | ||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and | ||
# to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in all copies or substantial portions | ||
# of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | ||
# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
# SOFTWARE. | ||
cargo_build(NAME rot13_connector) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Copyright © 2022 Qualcomm Innovation Center, Inc. All rights reserved. | ||
# | ||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated | ||
# documentation files (the “Software”), to deal in the Software without restriction, including without limitation | ||
# the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and | ||
# to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
# | ||
# The above copyright notice and this permission notice shall be included in all copies or substantial portions | ||
# of the Software. | ||
# | ||
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO | ||
# THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
# SOFTWARE. | ||
[package] | ||
name = "rot13_connector" | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "MIT" | ||
authors = ["Jeremy O'Donoghue<[email protected]"] | ||
description = "Minmal reference implementation of a Connector for the GlobalPlatform Trusted Platform Services API" | ||
homepage = "https://globalplatform.org" | ||
repository = "https://github.com/GlobalPlatform/TPS-API-Reference-Implementations" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
getrandom = { version = "0.2.7" } | ||
tps_client_common = { path = "../tps_client_common" } | ||
tps_connector = { path = "../tps_connector"} | ||
tps_error = { path = "../tps_error" } | ||
rot13_service = { path = "../rot13_service" } | ||
|
||
[lib] | ||
crate-type = ["lib", "staticlib"] | ||
|
||
# [features] # Features not yet used | ||
# std = [] | ||
|
||
[profile.release] | ||
opt-level = 'z' | ||
lto = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# ROT13 Connector | ||
|
||
A minimal example of TPS Client connector implementation in Rust. | ||
|
||
The ROT13 Connector builds as a static (C-linkable) library exporting the | ||
connector API | ||
|
||
## License | ||
|
||
`rot13_connector` is MIT licensed. | ||
|
||
## Usage | ||
|
||
The `rot13_connector` crate provides a minimal example of how to implement a | ||
TPS connector. The implementation should work for connectors implemented both | ||
as statically loadable libraries and as dynamically loaded libraries. | ||
|
||
The connector API requires exports a single function: | ||
|
||
```rust | ||
pub unsafe extern "C" fn TPSC_GetConnectorAPI() -> *const Connector {} | ||
``` | ||
|
||
Where the `Connector` definition is provided by the `tps_connector` crate. | ||
|
||
### lib.rs | ||
|
||
The underlying implementation of the top-level module is fairly simple: there | ||
is a static structure, `CONNECTOR` which holds the required C callable APIs | ||
for the connector. There are sample implementations of each of these | ||
functions in the `c_api` module. | ||
|
||
### c_api.rs | ||
|
||
Each of the callable functions in the `c_api` module does some sanitization | ||
of any pointers provided - this is necessarily limited mainly to checking | ||
for NULL pointers - and calls the relevant function in the `service` module, | ||
which is pure safe Rust. | ||
|
||
It is quite likely that the functions in the `c_api` module can be re-used | ||
without change in many implementations. | ||
|
||
### service.rs | ||
|
||
The majority of the sample implementation is in the `service` module. | ||
|
||
To adapt this code to some other component, you will need to do at least the | ||
following: | ||
|
||
#### Secure Component Instance | ||
|
||
Set the Secure Component Instance on which your service is running. | ||
|
||
In this sample code I have used a randomly generated UUID. If you are | ||
implementing on a real Secure Component, you should use an appropriate | ||
mechanism to generate a repeatable, but statistically unique UUID for the | ||
Secure Component Instance. Some Secure Component APIs may already provide | ||
a suitable mechanism for this. | ||
|
||
The TPS Client API Specification suggests some recommended ways to do this, | ||
but the thing that matters is that the value is stable over time and | ||
statistically unique. | ||
|
||
#### Determine the Service Instance ID | ||
|
||
As with the Secure Component Instance, this is a UUID and is required to | ||
be statistically unique. | ||
|
||
#### SERVICES array | ||
|
||
During Service Discovery, a connector reports the services available from | ||
the attached Secure Component. | ||
|
||
The implementation in this sample is simplified too much to be used in most | ||
real-world deployment scenarios, and is intended purely to show how the API | ||
is expected to work. | ||
|
||
The `SERVICES` array is a reference to an array of `ServiceIdentifier` | ||
instances. Each `ServiceIdentifier` needs to define the following fields: | ||
|
||
- `service_instance` a UUID which provides a unique and stable identifier | ||
for the instance of a service on a Secure Component. This value *must* be | ||
different for each service on a given secure component. Where there is | ||
more than one Secure Component on a device, it *must* be unique across | ||
devices. This means that you should generate this identity when a service | ||
is installed or first created on a device. | ||
- `service_id` a UUID which defines what the service does. This value *must* | ||
be the same for all instances of the same type of service. GlobalPlatform | ||
specifies UUIDs for every service that it defines, and here we use the | ||
standard UUID for the ROT13 service. | ||
- `secure_component_type` a UUID defining the type of Secure Component, for | ||
example TEE, Secure Element, TPM etc., that the service runs on. Bodies | ||
defining standardized Secure Components such as GlobalPlatform and the | ||
Trusted Computing Group define these for the components they standardize. | ||
In this case we use a "test" value, `GPP_TEST_SC_TYPE` which indicates | ||
that we are using a test component for which no security guarantees are made. | ||
- `service_version`: this is a structure indicating the version of the | ||
service API that is supported. For specifications defined by GlobalPlatform, | ||
this will align with the version of the GlobalPlatform document that defines | ||
the specification. | ||
|
||
## Platform requirements | ||
|
||
The implementation does not require the standard library, except when compiled | ||
for test. | ||
|
||
This implementation is intended to run on constrained devices (bare-metal or | ||
RTOS-based) which may not have rich synchronization and threading APIs. The | ||
code is thread-safe if the underlying platform provides atomic operations, as | ||
there is a dependency on `AtomicBool` and `AtomicU32`. | ||
|
||
The provided implementation generates somewhat unpredictable values for | ||
`session_id` using a random number generator. In general, the use of | ||
unpredictable values of `session_id` has some security benefit, but it may | ||
be acceptable to replace this with something simpler on some platforms. There | ||
is in any case no expectation of cryptographic quality randomness here. | ||
|
||
## Known Limitations | ||
|
||
This implementation is unlikely to be well-suited to interactions with | ||
complex Secure Components supporting dynamic installation and update of | ||
services. | ||
|
||
Currently the implementation of `execute_transaction` does not support | ||
session handling, which prevents use with multi-service cases. |
Oops, something went wrong.