Secure Engine Manager#

Silicon Labs Secure Engine Manager.

Note

  • The APIs are thread-safe.

Introduction#

The Secure Engine (SE) Manager provides thread-safe APIs for the Secure Engine's mailbox interface. Note that PSA Crypto is the main device independant crypto API and should be used whenever possible. Visit the Mbed TLS & PSA Crypto documentation hub for more details. The SE manager APIs can be used directly for performance or space constrained applications.

Available functionality will vary between devices: device management, such as secure firmware upgrade, secure boot and secure debug implementation, is available on all series 2 devices. Devices with the SE subsystem includes a low level crypto API where the SE Manager will use the SE hardware peripherals to accelerate cryptographic operations. Finally, Vault High devices also include secure key storage functionality, anti-tamper protection, advanced crypto API and attestation.

Note

Functionality#

The functionality of the SE Manager includes

  • Core API, inititalizing of SE Manager and SE command context (Core)

  • Secure key storage (Key handling)

    • Key wrapping

    • Storing keys in the SE volatile storage

    • Using key by reference

  • Configuration of tamper responses (Utilities)

    • The available signals include core hard-fault, glitch detectors, PRS, and failed authenticated commands, while the responses vary from triggering an interrupt to the hardware autonomously erasing the one-time-programmable (OTP) memory

  • Block ciphers (Cipher)

    • Supports AES-ECB, AES-CBC, AES-CFB128, AES-CFB8, AES-CTR, AES-CCM, AES-GCM, CMAC, HMAC and ChaCha20/Poly1305

    • The cipher operations can be performed using plaintext keys, wrapped keys or referencing a key in the SE

    • Streaming operations are supported for AES-GCM and CMAC

  • Block and streaming hash operations (Hashing)

    • Supports SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512

  • True Random Number Generator (Entropy)

    • Hardware block inside the SE used for generating random numbers. Can be used as a source of entropy, or to securely generate keys inside the SE

  • Elliptic Curve Signature operation (Signature)

    • ECDSA and EDDSA

  • Key agreement (Key derivation)

    • Perform Elliptic Curve Diffie-Hellman and J-PAKE key agreement operations inside the SE

  • Key derivation functions (Key derivation)

    • Perform HKDF and PBKDF2 key derivation functions inside the SE

  • Device configuration and utilities (Utilities)

    • Write to user data stored inside the SE

    • Configuration of debug locks

    • Configuration of secure boot

    • Configuration of flash lock

    • Read SE OTP contents

    • Read SE firmware version

    • Read provisioned certificates

  • Multi-thread safe APIs for MicriumOS and FreeRTOS

  • Retrieveing attestation tokens (Attestation)

Key Storage and Use of SE Wrapped Keys#

The way keys are stored and operated on depends on the options set in the key descriptor used (sl_se_key_descriptor_t). Each key descriptor is initialized with a storage location, a key type, and length of the key (some key types have a known length, and it is not required to be set). The storage location can either be application memory or inside the SE, for more details, see sl_se_storage_method_t. Depending on the use-case, the key descriptors will also store the pointer to a key and an SE key slot, see sl_se_key_slot_t for the list of available internal SE key slots.

For more information on the key handling APIs see Key handling.

Supported Key Types#

Symmetric keys

  • AES-128 (16 bytes)

  • AES-192 (24 bytes)

  • AES-256 (32 bytes)

  • ChaCha20 (32 bytes)

Asymmetric keys for ECC

  • NIST P-192

  • NIST P-256

  • NIST P-384

  • NIST P-521

  • Curve25519

  • Curve448

Custom Weierstrass Prime curves are also supported (sl_se_custom_weierstrass_prime_domain_t).

Example Usage of Keys#

#define WRAPPED_KEY_OVERHEAD (12UL + 16UL)
#define AES_256_KEY_SIZE 32UL

uint8_t key_buffer[AES_256_KEY_SIZE];
uint8_t wrapped_key_buffer[AES_256_KEY_SIZE + WRAPPED_KEY_OVERHEAD];

void demo_se_create_key_in_slot(void) {
    sl_se_key_descriptor_t new_key = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .flags = SL_SE_KEY_FLAG_NON_EXPORTABLE,
        .storage.method = SL_SE_KEY_STORAGE_INTERNAL_VOLATILE,
        .storage.location.slot = SL_SE_KEY_SLOT_VOLATILE_0,
    };
    sl_se_generate_key(&new_key);
}

void demo_se_create_plaintext_key(void) {
    sl_se_key_descriptor_t new_key = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .storage.method = SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT,
    };
    new_key.storage.location.buffer.pointer = key_buffer;
    new_key.storage.location.buffer.size = sizeof(key_buffer);
    sl_se_generate_key(&new_key);
}

void demo_se_create_wrapped_key(void) {
    sl_se_key_descriptor_t new_wrapped_key = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .flags = SL_SE_KEY_FLAG_NON_EXPORTABLE,
        .storage.method = SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED,
    };
    new_wrapped_key.storage.location.buffer.pointer = wrapped_key_buffer;
    new_wrapped_key.storage.location.buffer.size = sizeof(wrapped_key_buffer);
    sl_se_generate_key(&new_wrapped_key);
}

void demo_se_wrapped_key_to_volatile_slot(void) {
    sl_se_key_descriptor_t existing_wrapped_key = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .flags = SL_SE_KEY_FLAG_NON_EXPORTABLE,
        .storage.method = SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED,
    };
    existing_wrapped_key.storage.location.buffer.pointer = wrapped_key_buffer;
    existing_wrapped_key.storage.location.buffer.size = sizeof(wrapped_key_buffer);
    sl_se_key_descriptor_t key_in_slot = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .flags = SL_SE_KEY_FLAG_NON_EXPORTABLE,
        .storage.method = SL_SE_KEY_STORAGE_INTERNAL_VOLATILE,
        .storage.location.slot = SL_SE_KEY_SLOT_VOLATILE_0,
    };
    sl_se_import_key(&existing_wrapped_key, &key_in_slot);
}

void demo_se_volatile_slot_to_wrapped_key(void) {
    sl_se_key_descriptor_t existing_volatile_key = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .flags = SL_SE_KEY_FLAG_NON_EXPORTABLE,
        .storage.method = SL_SE_KEY_STORAGE_INTERNAL_VOLATILE,
        .storage.location.slot = SL_SE_KEY_SLOT_VOLATILE_0,
    };
    sl_se_key_descriptor_t wrapped_key_out = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .flags = SL_SE_KEY_FLAG_NON_EXPORTABLE,
        .storage.method = SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED,
    };
    wrapped_key_out.storage.location.buffer.pointer = wrapped_key_buffer;
    wrapped_key_out.storage.location.buffer.size = sizeof(wrapped_key_buffer);
    sl_se_export_key(&existing_volatile_key, &wrapped_key_out);
}

void demo_se_delete_from_volatile_slot(void) {
    sl_se_key_descriptor_t existing_volatile_key = {
        .type = SL_SE_KEY_TYPE_AES_256,
        .flags = SL_SE_KEY_FLAG_NON_EXPORTABLE,
        .storage.method = SL_SE_KEY_STORAGE_INTERNAL_VOLATILE,
        .storage.location.slot = SL_SE_KEY_SLOT_VOLATILE_0,
    };
    sl_se_delete_key(&existing_volatile_key);
}

Tamper#

The Secure Engine (SE) tamper module connects a number of hardware and software-driven tamper signals to a set of configurable hardware and software responses. This can be used to program the device to automatically respond to external events that could signal that someone is trying to tamper with the device, and very rapidly remove secrets stored in the SE. The available tamper signals range from signals based on failed authentication and secure boot to specialized glitch detectors. When any of these signals fire, the tamper block can be configured to trigger several different responses, ranging from triggering an interrupt to erasing the one-time-programmable (OTP) memory, removing all SE secrets and resulting in a permanently destroyed device.

A tamper signal can lead to a series of different autonomous responses from the tamper module. These responses are listed in the table below.

Response

Description

0

Ignore

No action is taken.

1

Interrupt

The SETAMPERHOST interrupt on the host is triggered.

2

Filter

A counter in the tamper filter is increased.

4

Reset

The device is reset.

7

Erase OTP

Erases the OTP configuration of the device.

These responses are cumulative, meaning that if a filter response is triggered, an interrupt will also be triggered. For a full overview of the tamper signals, see sl_se_manager_defines.h.

The tamper configuration is one-time-programmable, and is done using the initialise OTP command to the SE (see sl_se_init_otp). This means that tamper settings must be written together with secure boot settings, and are immutable after they are written. After tamper has been initialized, it is possible to temporarily disable one or several tamper signals using an authenticated command, similar to secure debug unlock. This is only possible if the debug public key has been installed on the device. It is only possible to disable the customer enabled response. The default response to a signal cannot be disabled.

Tamper is configured by providing the following:

Tamper configuration table

Setting

Description

Tamper response levels

A response level for each tamper signal.

It is not possible to degrade the default response level of a tamper signal, so if a response is set to a lower level than the default response level listed in the table in the Signals section, this won't have any effect.

Filter settings

The tamper filter counter has two settings:

  • Reset period

  • Trigger threshold

These options can be set to the values given in the tables in the Response Filter section. Please see the examples section for a suggested use of the tamper filter signal.

Flags

The tamper flags is used to configure two options:

  • Digital Glitch Detector Always On – This option will keep the digital glitch detector running even while the SE is not performing any operations. This leads to increased energy consumption.

  • Keep Tamper Alive During Sleep (not available on EFR32xG21B devices) – If set, the tamper module keeps running at sleep mode (down to EM3).

Reset threshold

The number of consecutive tamper resets before the the part enters debug mode.

If the threshold is set to 0, the part will never enter the debug mode due to tamper reset.

Example Usage#

The glitch detectors can see spurious activations, and should typically not be used to directly drive a serious tamper response. Instead they should feed their signals into a tamper interrupt (to handle the response logic on the M33), or into the tamper filter counter, which can be used to activate a high level response if a number of incidents occur in a short time window. The time period and counter threshold must be tuned to the use case. In the following example the device will erase OTP and become inoperable if 4 glitch signals is seen in a 1 minute time period.

Since you can only configure tamper once for each device, please make sure that this is the configuration you actually want before you execute this example on actual device.

sl_se_otp_init_t otp_settings_init = SL_SE_OTP_INIT_DEFAULT;

// Configure tamper levels
otp_settings_init.tamper_levels[SL_SE_TAMPER_SIGNAL_FILTER] = SL_SE_TAMPER_LEVEL_PERMANENTLY_ERASE_OTP;
otp_settings_init.tamper_levels[SL_SE_TAMPER_SIGNAL_VGLITCHFALLING] = SL_SE_TAMPER_LEVEL_FILTER;
otp_settings_init.tamper_levels[SL_SE_TAMPER_SIGNAL_VGLITCHRISING] = SL_SE_TAMPER_LEVEL_FILTER;
otp_settings_init.tamper_levels[SL_SE_TAMPER_SIGNAL_DGLITCH] = SL_SE_TAMPER_LEVEL_FILTER;


// Configure tamper filter options
otp_settings_init.tamper_filter_period = SL_SE_TAMPER_FILTER_PERIOD_1MIN;
otp_settings_init.tamper_filter_threshold = SL_SE_TAMPER_FILTER_THRESHOLD_4;


// Commit OTP settings. This command is only available once!
sl_se_init_otp(&otp_settings_init);

RTOS Mode and Multi-Thread Safety#

Note

  • The SE Manager API is multi-thread safe, but does not support preemption. This means the API cannot be called from ISR or critical/atomic sections when running in an RTOS thread. When using the SE Manager API in a bare-metal application, it is the application developer's responsibility to not call the SE Manager APIs when another operation is in progress.

The SE Manager supports multi-thread safe APIs for MicriumOS and FreeRTOS interfacing with CMSIS RTOS2 APIs.

For MicriumOS support the user application must define the compile time option SL_CATALOG_MICRIUMOS_KERNEL_PRESENT. For FreeRTOS support the user application must define the compile time option SL_CATALOG_FREERTOS_KERNEL_PRESENT. For bare metal mode (non-RTOS) the user must not define SL_CATALOG_MICRIUMOS_KERNEL_PRESENT or SL_CATALOG_FREERTOS_KERNEL_PRESENT.

Applications created using Simplicity Studio 5 need to include the header file called sl_component_catalog.h which will include a macro define for one of the abovementioned RTOSes if present.

In the cases with SL_CATALOG_MICRIUMOS_KERNEL_PRESENT or SL_CATALOG_FREERTOS_KERNEL_PRESENT defined (RTOS-mode), the SE Manager will be configured with threading and yield support. Configure sl_se_command_context_t with sl_se_set_yield to yield the CPU core when the SE Manager is waiting for the Secure Engine to complete a mailbox command.

For threading support the SE Manager applies an SE lock mechanism to protect the Secure Engine Mailbox interface from being accessed by more than one thread, ensuring multi-thread safety. For yielding the CPU core while waiting for the SE, the SE Manager APIs that invoke SE mailbox commands will wait on a semaphore which is signaled in the ISR that handles the SE mailbox completion interrupt. Hence other threads may run on the CPU core while the SE is processing the mailbox command.

Modules#

Attestation

Cipher

Core

Entropy

Hashing

Key derivation

Key handling

Signature

Utilities