AVSystem Blog on Information and Communication Technology

Rethinking IoT security with PSA

Written by Mateusz Kwiatkowski | 22/09/2021

The long-running joke in the tech circles says that “the S in IoT stands for Security”. This poor reputation stems from a lot of insecure devices having flooded the IoT market over the years. However, this attitude is steadily changing, with more and more companies taking security into account very seriously in their products. Security of computer and Internet of Things products is also getting more and more attention from government regulators.

Indeed, the LwM2M protocol itself that we widely support and promote here at AVSystem has been designed with robust security in mind from the very beginning, requiring the use of DTLS, supporting many modes of ensuring proper trust between endpoints, including EST for example, and also mentioning various additional security considerations in the specification text.

Additionally, each year we see more and more of our customers ask for hardware-based security support, which isolates the root of trust to make the devices less vulnerable to both remote attacks and physical tampering.

Recognizing that perceived lack of security in the IoT environment and the difficulty in designing a proper security architecture, Arm Ltd. has been designing the Platform Security Architecture (PSA) set of specifications since 2017, which are intended to provide a holistic framework for building IoT applications that are secure from the ground up.

The PSA umbrella consists of many different documents, many of which are conceptual in nature – for example, the PSA Security Model document describes how different components of PSA are intended to interact with each other. These conceptual documents are very important for PSA Certified, Arm’s security certification program centered around PSA.

However, we will focus on the APIs exposed to the embedded software developers that have been created as part of the PSA initiative. Three such APIs have been released to date:

  • PSA Cryptography API – arguably the most crucial component, it describes an API for accessing a cryptographic root of trust that can store keys and perform elementary cryptographic operations such as encryption, decryption, generating, and verifying signatures, generating and deriving keys, etc.
  • PSA Attestation API – allows access to the “attestation token”, which is used in the PSA architecture so that an external entity (e.g., a management server) can cryptographically verify the identity and trust status of the device.
  • PSA Storage API – further divided into the Protected Storage API and Internal Trusted Storage API, it provides abstractions over accessing the non-volatile storage managed as part of the root of trust.

Additionally, PSA Firmware Update API is currently in the beta phase of development.

These APIs are intended to be implemented as calls into a secure element or a secure partition within firmware on platforms that support the Trusted Execution Environment (TEE). However, in principle, they can also be implemented directly in untrusted software, for example, for testing purposes or to reuse code on a platform that does not support the required security features.

PSA Cryptography API

In the previous post, linked above, we mentioned PKCS#11 as one of the leading software APIs for interfacing with hardware security modules and secure elements. While this is certainly true, PKCS#11 is a rather old standard, originally published in 1994 and designed for use with cryptographic devices connected to personal computers and laptops. The design has proven forward-thinking and generic enough to more or less translate into the modern era of highly integrated IoT devices – however still, the API may feel overly generic and verbose for this context.

On the other hand, attempting to interface with the security hardware directly is complicated and error-prone. Mbed TLS, the TLS implementation most commonly used in embedded software, does not even provide a uniform API to interface with such security hardware.

PSA Cryptography API has stabilized in early 2020 and has been designed with constrained devices in mind from the beginning. It provides APIs for key management and some basic cryptographic operations – similar in scope to PKCS#11 – that can be used e.g., to implement the TLS protocol, storage encryption, local network logon, etc.

The most important concept in the PSA Cryptography API is a key. Each key is identified by a numeric ID, which may be treated as a concept similar to a file name. Half of the 32-bit key ID space can be freely used by the application, while the other half is reserved for allocation by the PSA implementation itself. Aside from the key material itself, each key is assigned a set of attributes, including:

  • Type – most common symmetric and asymmetric key types are supported; keys of type “raw data” can also be used, which allows e.g., storing certificates (although arguably the PSA Protected Storage API may be better suited for this purpose).
  • Size in bits.
  • Lifetime – determines whether a given key is persistent or volatile (i.e., destroyed on reboot); it can also specify alternate physical locations for the key, which allows for more complex architectures involving e.g., separate secure elements further connected to the processor that handles the PSA API.
  • Usage flags – the set of the operations that are allowed on a given key, chosen from: export (allows reading the key material, including private key), copy (allows copying the key without inspecting it), cache (allows temporarily caching the key in memory), encrypt, decrypt, sign message, verify message, sign hash, verify hash, derive. Additionally, exporting the public portion of asymmetric keys is always allowed.
  • Algorithms permitted for use with the key – this may be used to enforce that a given key shall only be used with some specific ciphers, including e.g. the hash functions allowed in ciphersuites.

The attributes cannot be modified once a key exists within the PSA contexts and can only be further restricted when copying keys – unless the “export” operation is allowed.

The reference low-level implementation of the PSA Cryptography API has been provided in Mbed TLS since version 2.22. The higher layers of Mbed TLS (those that actually implement the TLS protocol) can also utilize keys accessed through the PSA API. So a typical device architecture could look like this.

Trusted Firmware-M, a complete set of services running in the secure partition on Cortex-M microcontrollers, is the reference implementation of the entire PSA stack (Cryptography, Attestation, Storage, and Firmware Update) and provides some additional related functionality such as secure boot.

This project is independent of the operating system running in the insecure partition, and integrations are available for CMSIS, FreeRTOS, Mbed OS, and Zephyr.

PSA in Anjay

The latest version of Anjay includes a PSA driver in its hardware security subsystem, alongside the previously introduced PKCS#11 driver. It includes full support for elliptic curve keys generation and use for (D)TLS connectivity. Certificates can also be stored either as “raw data” keys via the PSA Cryptography API or as assets via the PSA Protected Storage API.

The PSA driver is enabled at compile time, by enabling the appropriate definitions in avs_commons_config.h, or by setting the corresponding CMake options:

cmake -DWITH_AVS_CRYPTO_ENGINE=ON \

      -DWITH_MBEDTLS_PKCS11_ENGINE=OFF \

      -DWITH_MBEDTLS_PSA_ENGINE=ON .

When Anjay is configured in this way, the same functions as previously introduced for PKCS#11 can be used for PSA, just with a different query string format. For example, to use keys already present in the secure storage:

anjay_security_instance_t security_instance = {

    .ssid = 1,

    .server_uri = "coaps://try-anjay.avsystem.com:5684",

    .security_mode = ANJAY_SECURITY_CERTIFICATE,

    .public_cert = avs_crypto_certificate_chain_info_from_engine(
            "kid=0x80000002"),

    .private_key = avs_crypto_private_key_info_from_engine(
            "kid=0x80000001"),

};

Similarly, the following code can be used to configure EST with secure key storage – in this case, the lifetime attributes can also be controlled (the default persistent storage lifetime is used if not specified):

const anjay_configuration_t CONFIG = {

    /* ... usual Anjay configuration ... */

    .est_engine_key_address = "kid=1,lifetime=0x401",

    .est_engine_cert_address = "kid=2"

};

This code has been tested to work with the reference PSA API implementation in Mbed TLS (non-isolated, running on a PC) as well as the actual Trusted Firmware-M integration on top of Zephyr.

If you’re interested, please visit the Anjay product page, contact us and ask for an evaluation of the commercial version of Anjay.