Imported more library files

Not compiling currently
This commit is contained in:
2025-04-12 23:37:19 +01:00
parent 264a3462e0
commit 9d06f983af
2518 changed files with 1021900 additions and 52 deletions

View File

@@ -0,0 +1,458 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_H
#define SL_SE_MANAGER_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
/***************************************************************************//**
* @addtogroup sl_se_manager SE Manager
* @{
******************************************************************************/
/***************************************************************************//**
* @addtogroup sl_se_manager_core Core
*
* @brief
* Secure Engine Manager Core API
*
* @details
* API for initialization of SE Manager and SE command context with yield
* attribute.
*
* @{
******************************************************************************/
#if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
#include "sl_se_manager_key_handling.h"
#include "sl_se_manager_cipher.h"
#endif // SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT
#include "sl_se_manager_types.h"
#include "sli_se_manager_mailbox.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* @brief
* Initialize the SE Manager.
*
* @details
* Initialize the SE Manager by checking hardware availability and setting up
* internal module specific resources like mutexes etc.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_init(void);
/***************************************************************************//**
* @brief
* Denitialize the SE Manager.
*
* @details
* Free resources held by the SE Manager.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_deinit(void);
#if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
/***************************************************************************//**
* @brief
* Set the yield attribute of the SE command context object.
*
* @param[in,out] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] yield
* The user may set this parameter to true in order to tell the SE Manager
* to yield the cpu core while waiting for the SE mailbox command to complete.
* If false, the SE Manager will busy-wait, by polling the SE mailbox response
* register until the SE mailbox command completes.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_set_yield(sl_se_command_context_t *cmd_ctx,
bool yield);
#endif // !SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT
#if defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
/***************************************************************************//**
* @brief
* From VSE mailbox read which command, if any, was executed.
*
* @param[in,out] cmd_ctx
* Pointer to an SE command context object. If this function returns
* SL_STATUS_OK the command word of the SE command context object will be set.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_read_executed_command(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Acknowledge and get status and output data of a completed command.
*
* @details
* This function acknowledges and gets the status and output data of a
* completed mailbox command. The acknowledge operation invalidates the
* contents of the output mailbox. The output data is copied into the linked
* list of output buffers pointed to in the given command data structure.
*
* @param[in,out] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx);
#endif //defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
/***************************************************************************//**
* @brief
* Initialize an SE command context object
*
* @details
* Initialize an SE command context which can be used in subsequent calls to
* the SE Manager API in order to execute SE mailbox commands.
*
* @param[in,out] cmd_ctx
* Pointer to an SE command context object to be initialized. This context
* object should be used in subsequent calls to the SE Manager API in order
* to execute SE mailbox commands. The same command context object cannot be
* used concurrently, e.g. by two different threads. However a command context
* object may be reused for the next and any subsequent mailbox operatons,
* except when streaming commands are in progress in which case only streaming
* commands of the same operation type is allowed until the streaming operation
* is finished (i.e. the corresponding sl_se_xxx_finish is called).
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_init_command_context(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* De-initialize an SE command context
*
* @details
* De-initialize an SE command context object.
*
* @param[in,out] cmd_ctx
* Pointer to an SE command context object to deinitialize.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_deinit_command_context(sl_se_command_context_t *cmd_ctx);
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager_core)
/// @} (end addtogroup sl_se_manager)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_H
// THE REST OF THE FILE IS DOCUMENTATION ONLY
/// @addtogroup sl_se_manager
/// @{
/// @details
///
/// The Secure Engine (SE) Manager provides thread-safe APIs for the Secure Engine's mailbox interface. Note that PSA Crypto is the recommended device independent crypto API and should be used
/// whenever possible. 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 Below are some of the useful application notes linked with Secure Engine Manager:\n
/// - <a href="https://www.silabs.com/documents/public/application-notes/an1190-efr32-secure-debug.pdf">AN1190: Series 2 Secure Debug</a>\n
/// - <a href="https://www.silabs.com/documents/public/application-notes/an1247-efr32-secure-vault-tamper.pdf">AN1247: Anti-Tamper Protection Configuration and Use</a>\n
/// - <a href="https://www.silabs.com/documents/public/application-notes/an1268-efr32-secure-identity.pdf">AN1268: Authenticating Silicon Labs Devices Using Device Certificates</a>\n
/// - <a href="https://www.silabs.com/documents/public/application-notes/an1271-efr32-secure-key-storage.pdf">AN1271: Secure Key Storage</a>\n
/// - <a href="https://www.silabs.com/documents/public/application-notes/an1218-secure-boot-with-rtsl.pdf">AN1218: Series 2 Secure Boot with RTSL</a>\n
///
/// # Functionality
///
/// The functionality of the SE Manager includes
///
/// - Core API, inititalizing of SE Manager and SE command context (@ref sl_se_manager_core)
/// - Secure key storage (@ref sl_se_manager_key_handling)
/// - Key wrapping
/// - Storing keys in the SE volatile storage
/// - Using key by reference
/// - Configuration of tamper responses (@ref sl_se_manager_util)
/// - 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 (@ref sl_se_manager_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 (@ref sl_se_manager_hash)
/// - Supports SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512
/// - True Random Number Generator (@ref sl_se_manager_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 (@ref sl_se_manager_signature)
/// - ECDSA and EDDSA
/// - Key agreement (@ref sl_se_manager_key_derivation)
/// - Perform Elliptic Curve Diffie-Hellman and J-PAKE key agreement operations inside the SE
/// - Key derivation functions (@ref sl_se_manager_key_derivation)
/// - Perform HKDF and PBKDF2 key derivation functions inside the SE
/// - Device configuration and utilities (@ref sl_se_manager_util)
/// - 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 (@ref sl_se_manager_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 (@ref 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 @ref 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 @ref sl_se_key_slot_t for the list of available internal SE key slots.
///
/// For more information on the key handling APIs see @ref sl_se_manager_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 (@ref sl_se_custom_weierstrass_prime_domain_t).
///
/// ### Example Usage of Keys
///
/// @code{.c}
/// #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);
/// }
/// @endcode
///
/// ## 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 @ref sl_se_manager_defines.h.
///
/// The tamper configuration is one-time-programmable, and is done using the initialise OTP command to the SE (see @ref 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:
/// <table>
/// <caption id="multi_row">Tamper configuration table</caption>
/// <tr><th>Setting <th>Description
/// <tr><td>Tamper response levels <td>A response level for each tamper signal.\n\n 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.
/// <tr><td>Filter settings <td>The tamper filter counter has two settings:
/// <ul>
/// <li>Reset period
/// <li>Trigger threshold
/// </ul>
/// 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.
/// <tr><td>Flags <td>The tamper flags is used to configure two options:
/// <ul>
/// <li>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.
/// <li>Keep Tamper Alive During Sleep (not available on EFR32xG21B devices) If set, the tamper module keeps running at sleep mode (down to EM3).
/// </ul>
/// <tr><td>Reset threshold <td>The number of consecutive tamper resets before the the part enters debug mode.\n\n
/// If the threshold is set to 0, the part will never enter the debug mode due to tamper reset.
/// </table>
///
/// ### 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.
///
/// @code{.c}
/// 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);
/// @endcode
///
/// ## 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.
///
/// In the cases where Micrium OS or FreeRTOS are included in the project (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.
///
/// @} (end addtogroup sl_se_manager)

View File

@@ -0,0 +1,209 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_ATTESTATION_H
#define SL_SE_MANAGER_ATTESTATION_H
#include "sli_se_manager_features.h"
#if (defined(SLI_MAILBOX_COMMAND_SUPPORTED) \
&& (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT))
/// @addtogroup sl_se_manager
/// @{
/***************************************************************************//**
* @addtogroup sl_se_manager_attestation Attestation
*
* @brief
* System and configuration attestation
*
* @details
* API for retrieveing attestation tokens from the SE.
*
* @{
******************************************************************************/
#include "sl_se_manager_key_handling.h"
#include "sl_se_manager_types.h"
#include "sli_se_manager_mailbox.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Defines
/// 32 byte challenge size
#define SL_SE_ATTESTATION_CHALLENGE_SIZE_32 (32U)
/// 48 byte challenge size
#define SL_SE_ATTESTATION_CHALLENGE_SIZE_48 (48U)
/// 64 byte challenge size
#define SL_SE_ATTESTATION_CHALLENGE_SIZE_64 (64U)
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* @brief
* Get the PSA initial attest token from the SE
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] auth_challenge
* Buffer with a challenge object selected by the caller.
*
* @param[in] challenge_size
* Size of the challenge object in bytes. Must be either 32, 48 or 64.
*
* @param[out] token_buf
* Buffer where the output token will be stored.
*
* @param[in] token_buf_size
* Size of token_buf in bytes. Must be at least the size found by calling
* \ref sl_se_attestation_get_psa_iat_token_size with equivalent arguments,
* and padded to word alignment.
*
* @param[out] token_size
* Number of bytes actually used in token_buf.
*
* @warning
* Once a nonce/challenge has been used, the same challenge should not be used
* ever again, to prevent replay attacks.
*
* @warning
* The output will be length-extended to the next word-multiple.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_attestation_get_psa_iat_token(sl_se_command_context_t *cmd_ctx,
const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size);
/***************************************************************************//**
* @brief
* Get the size of a PSA initial attest token with the given nonce
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] challenge_size
* Size of the challenge object in bytes. Must be either 32, 48 or 64.
*
* @param[out] token_size
* Pointer to output word. Result is stored here.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_attestation_get_psa_iat_token_size(sl_se_command_context_t *cmd_ctx,
size_t challenge_size,
size_t *token_size);
/***************************************************************************//**
* @brief
* Get an attested (signed) security configuration token from the SE
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] auth_challenge
* Buffer with a challenge object selected by the caller.
*
* @param[in] challenge_size
* Size of the challenge object in bytes. Must be 32.
*
* @param[out] token_buf
* Buffer where the output token will be stored.
*
* @param[in] token_buf_size
* Size of token_buf in bytes. Must be at least the size found by calling
* \ref sl_se_attestation_get_config_token_size with equivalent arguments,
* and padded to word alignment.
*
* @param[out] token_size
* Number of bytes actually used in token_buf.
*
* @warning
* Once a nonce/challenge has been used, the same challenge should not be used
* ever again, to prevent replay attacks.
*
* @warning
* The output will be length-extended to the next word-multiple.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_attestation_get_config_token(sl_se_command_context_t *cmd_ctx,
const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size);
/***************************************************************************//**
* @brief
* Get the size of a security configuration token
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] challenge_size
* Size of the challenge object in bytes. Must be 32.
*
* @param[out] token_size
* Pointer to output word. Result is stored here.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_attestation_get_config_token_size(sl_se_command_context_t *cmd_ctx,
size_t challenge_size,
size_t *token_size);
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager_attestation)
/// @} (end addtogroup sl_se_manager)
#endif // SLI_MAILBOX_COMMAND_SUPPORTED && VAULT
#endif // SL_SE_MANAGER_ATTESTATION_H

View File

@@ -0,0 +1,61 @@
/**************************************************************************/ /**
* @file
* @brief Consistency checks for SE Manager configuration options
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_CHECK_CONFIG_H
#define SL_SE_MANAGER_CHECK_CONFIG_H
#if defined (SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
#if defined(SL_SE_MANAGER_THREADING) \
&& !defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION) \
&& !defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#error "Yield when waiting for SE commands to finish is currently required in RTOS mode."
#endif
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION) \
&& !defined(SL_SE_MANAGER_THREADING)
#error "Yield when waiting for SE commands to finish currently requires RTOS mode. I.e. yield support is not available in bare metal mode."
#endif
#if (defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) || defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)) \
&& !defined(SL_SE_MANAGER_THREADING)
#error "RTOS requires threading mode."
#endif
#if (defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED) && defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION))
#error "Yield support is not available on EFR32xG22 devices"
#endif
#if (SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED != 1)
#error "Using multiple blocks for key stream computation is not supported"
#endif
#endif // SL_SE_MANAGER_CHECK_CONFIG_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
/**************************************************************************/ /**
* @file
* @brief SE Manager configuration options
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_CONFIG_H
#define SL_SE_MANAGER_CONFIG_H
/// This file include the configuration options of the SE Manager.
/// For the time being the user should not change the default settings
/// of the configuration options in this file.
#if defined (SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
#if defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) || defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
// Threading support (as opposed to API calls only from a single thread)
// is currently required in RTOS mode.
#define SL_SE_MANAGER_THREADING
#if !defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION) && !defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
// Enable yield support. Configure sl_se_command_context_t to yield CPU while waiting for SE commands.
// This is not supported on EFR32xG22.
#define SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
#endif
#endif
#ifndef SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED
#define SLI_SE_AES_CTR_NUM_BLOCKS_BUFFERED 1
#endif
// Check consistency of configuration options.
// Always include se_manager_check_config.h in order to assert that the
// configuration options dependencies and restrictions are ok.
#include "sl_se_manager_check_config.h"
#endif // SL_SE_MANAGER_CONFIG_H

View File

@@ -0,0 +1,533 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API definitions
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_DEFINES_H
#define SL_SE_MANAGER_DEFINES_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#if !defined(SLI_SE_MANAGER_HOST_SYSTEM)
#if !defined(SL_TRUSTZONE_NONSECURE)
#if !defined(SE_MANAGER_CONFIG_FILE)
#include "sl_se_manager_config.h"
#else
#include SE_MANAGER_CONFIG_FILE
#endif // SE_MANAGER_CONFIG_FILE
#endif // SL_TRUSTZONE_NONSECURE
#endif // SLI_SE_MANAGER_HOST_SYSTEM
#if defined (SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
/// @addtogroup sl_se_manager
/// @{
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Defines
/// @addtogroup sl_se_manager_core
/// @{
/// Context initialization values. Some of the context values are not fully
/// initialized. The user will need to call the corresponding initialization
/// function in order to fully initialize the context objects for further use
/// in the SE Manager API. The purpose of these initialization values is to set
/// the context objects to a known safe state initially when the context object
/// is declared.
#define SL_SE_COMMAND_CONTEXT_INIT { SLI_SE_MAILBOX_COMMAND_DEFAULT(0), false }
/// @} (end addtogroup sl_se_manager_core)
/// @addtogroup sl_se_manager_util
/// @{
/// Default configuration for OTP initialisation structure.
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#define SL_SE_OTP_INIT_DEFAULT \
{ \
.enable_secure_boot = false, \
.verify_secure_boot_certificate = false, \
.enable_anti_rollback = false, \
.secure_boot_page_lock_narrow = false, \
.secure_boot_page_lock_full = false, \
.tamper_levels = { 0 }, \
.tamper_filter_period = SL_SE_TAMPER_FILTER_PERIOD_2MIN, \
.tamper_filter_threshold = SL_SE_TAMPER_FILTER_THRESHOLD_4, \
.tamper_flags = 0, \
.tamper_reset_threshold = 5 \
}
#else
#define SL_SE_OTP_INIT_DEFAULT \
{ \
.enable_secure_boot = false, \
.verify_secure_boot_certificate = false, \
.enable_anti_rollback = false, \
.secure_boot_page_lock_narrow = false, \
.secure_boot_page_lock_full = false \
}
#endif
/// @} (end addtogroup sl_se_manager_util)
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
// -------------------------------
// Defines for SE functionality
/// @addtogroup sl_se_manager_key_handling
/// @{
/// Asymmetric key can only be used for signing (not key exchange)
#define SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY (1UL << 10)
/// Described key belongs to a custom ECC domain
#define SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN (1UL << 12)
/// Storage buffer contains public part of an asymmetric key
#define SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY (1UL << 13)
/// Storage buffer contains private part of an asymmetric key
#define SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY (1UL << 14)
/// Allow usage of this key by other bus masters or TrustZone levels than the
/// one which created/imported the key
#define SL_SE_KEY_FLAG_ALLOW_ANY_ACCESS (1UL << 15)
/// Old definition. Retained for backwards compatibility.
#define SL_SE_KEY_FLAG_ASYMMMETRIC_SIGNING_ONLY \
(SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY)
/// Do not allow exporting the key to plaintext
#define SL_SE_KEY_FLAG_NON_EXPORTABLE (1UL << 24)
/// Indicate that the key has been generated by this device. This flag is only
/// valid when using the SE to generate a key and makes it non-exportable.
#define SL_SE_KEY_FLAG_IS_DEVICE_GENERATED (1UL << 25)
/// Indicate that the key can only be used to sign SE generated content. This
/// flag is only valid when using the SE to generate a key and makes it
/// non-exportable.
#define SL_SE_KEY_FLAG_IS_RESTRICTED (1UL << 25 | 1UL << 24)
/// Mask for algorithm field in key type
#define SL_SE_KEY_TYPE_ALGORITHM_MASK 0xf0000000
/// Offset of algorithm field in key type
#define SL_SE_KEY_TYPE_ALGORITHM_OFFSET 28
/// Mask for attributes field in key type
#define SL_SE_KEY_TYPE_ATTRIBUTES_MASK 0x00007fff
/// Offset of attributes field in key type
#define SL_SE_KEY_TYPE_ATTRIBUTES_OFFSET 0
/// Symmetric key type
#define SL_SE_KEY_TYPE_SYMMETRIC 0x00000000
/// Symmetric key type for AES-128 (16 byte key)
#define SL_SE_KEY_TYPE_AES_128 0x00000010
/// Symmetric key type for AES-192 (24 byte key)
#define SL_SE_KEY_TYPE_AES_192 0x00000018
/// Symmetric key type for AES-256 (32 byte key)
#define SL_SE_KEY_TYPE_AES_256 0x00000020
/// ECC Weierstrass Prime key type
#define SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM (0x8U << SL_SE_KEY_TYPE_ALGORITHM_OFFSET)
/// ECC Montgomery key type
#define SL_SE_KEY_TYPE_ECC_MONTGOMERY (0xbU << SL_SE_KEY_TYPE_ALGORITHM_OFFSET)
/// EDDSA key type
#define SL_SE_KEY_TYPE_ECC_EDDSA (0xcU << SL_SE_KEY_TYPE_ALGORITHM_OFFSET)
/// ECC NIST P-192
#define SL_SE_KEY_TYPE_ECC_P192 (SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM | (0x18))
/// ECC NIST P-224
#define SL_SE_KEY_TYPE_ECC_P224 (SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM | (0x1C))
/// ECC NIST P-256
#define SL_SE_KEY_TYPE_ECC_P256 (SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM | (0x20))
/// ECC Ed25519 key for EdDSA
#define SL_SE_KEY_TYPE_ECC_ED25519 (SL_SE_KEY_TYPE_ECC_EDDSA | (0x20))
/// ECC X25519 key for ECDH
#define SL_SE_KEY_TYPE_ECC_X25519 (SL_SE_KEY_TYPE_ECC_MONTGOMERY | (0x20))
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// Symmetric key type for ChaCha20
#define SL_SE_KEY_TYPE_CHACHA20 0x00000020
/// ECC NIST P-384
#define SL_SE_KEY_TYPE_ECC_P384 (SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM | (0x30))
/// ECC NIST P-521
#define SL_SE_KEY_TYPE_ECC_P521 (SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM | (0x42))
/// ECC X448 key for ECDH
#define SL_SE_KEY_TYPE_ECC_X448 (SL_SE_KEY_TYPE_ECC_MONTGOMERY | (0x38))
/// ECC Ed448 key for EdDSA
#define SL_SE_KEY_TYPE_ECC_ED448 (SL_SE_KEY_TYPE_ECC_EDDSA | (0x38))
#endif
/// Key storage methods
/// Key is stored in a plaintext buffer in application memory. Application
/// can save its in-memory buffer to non-volatile memory as needed to
/// provide key persistence.
#define SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT 0x00
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// Key is stored encrypted in application memory. This ensures the key in
/// wrapped form is only usable on a specific device. If the key
/// additionally needs to be prevented from ever being output as plaintext,
/// also set the corresponding permission bit. Application can save its
/// in-memory buffer to non-volatile memory as needed to provide key
/// persistence.
/// Keys stored in this way should use the flag
/// SL_SE_KEY_FLAG_NON_EXPORTABLE unless there is a specific need to access
/// the key value outside the SE.
#define SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED 0x01
/// Key is stored inside the SE, and will persist until system reset or
/// explicitly deleted.
/// Keys stored in this way should use the flag
/// SL_SE_KEY_FLAG_NON_EXPORTABLE unless there is a specific need to access
/// the key value outside the SE.
#define SL_SE_KEY_STORAGE_INTERNAL_VOLATILE 0x02
#endif
/// Key is one of the pre-defined keys (pre-loaded or write-once) available
/// in the SE. See documentation for a list of available keys.
#define SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE 0x03
#if defined(_SILICON_LABS_32B_SERIES_3)
/// Key is stored in the KSURAM, an internal Key Slot RAM.
#define SL_SE_KEY_STORAGE_INTERNAL_KSU 0x04
#endif
/// List of available internal SE key slots
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#define SL_SE_KEY_SLOT_VOLATILE_0 0x00 ///< Internal volatile slot 0
#define SL_SE_KEY_SLOT_VOLATILE_1 0x01 ///< Internal volatile slot 1
#define SL_SE_KEY_SLOT_VOLATILE_2 0x02 ///< Internal volatile slot 2
#define SL_SE_KEY_SLOT_VOLATILE_3 0x03 ///< Internal volatile slot 3
#endif
#if defined(SLI_SE_SUPPORTS_NVM3_INTERNAL_KEY)
/// Minimum key slot value for internal keys
#define SL_SE_KEY_SLOT_INTERNAL_MIN 0xF6
/// Internal NVM3 key
#define SL_SE_KEY_SLOT_NVM3_KEY 0xF6
#else
/// Minimum key slot value for internal keys
#define SL_SE_KEY_SLOT_INTERNAL_MIN 0xF7
#endif
/// Internal TrustZone root key
#define SL_SE_KEY_SLOT_TRUSTZONE_ROOT_KEY 0xF7
/// Internal immutable application secure debug key
#define SL_SE_KEY_SLOT_APPLICATION_SECURE_DEBUG_KEY 0xF8
/// Internal immutable application AES-128 key (bootloader key)
#define SL_SE_KEY_SLOT_APPLICATION_AES_128_KEY 0xFA
/// Internal immutable application secure boot key
#define SL_SE_KEY_SLOT_APPLICATION_SECURE_BOOT_KEY 0xFC
/// Internal immutable application attestation key
#define SL_SE_KEY_SLOT_APPLICATION_ATTESTATION_KEY 0xFE
/// Internal immutable SE attestation key
#define SL_SE_KEY_SLOT_SE_ATTESTATION_KEY 0xFF
/// Size overhead for wrapped keys
#define SLI_SE_WRAPPED_KEY_OVERHEAD (12 + 16)
/// @} (end addtogroup sl_se_manager_key_handling)
/// @addtogroup sl_se_manager_key_derivation
/// @{
/// Defines mapping the PBKDF2 PRFs to corresponding sl_se_hash_type_t values.
#define SL_SE_PRF_AES_CMAC_128 SL_SE_HASH_NONE ///< CMAC-AES-128
#define SL_SE_PRF_HMAC_SHA1 SL_SE_HASH_SHA1 ///< HMAC-SHA-1
#define SL_SE_PRF_HMAC_SHA224 SL_SE_HASH_SHA224 ///< HMAC-SHA-224
#define SL_SE_PRF_HMAC_SHA256 SL_SE_HASH_SHA256 ///< HMAC-SHA-256
#define SL_SE_PRF_HMAC_SHA384 SL_SE_HASH_SHA384 ///< HMAC-SHA-384
#define SL_SE_PRF_HMAC_SHA512 SL_SE_HASH_SHA512 ///< HMAC-SHA-512
/// @} (end addtogroup sl_se_manager_key_derivation)
/// @addtogroup sl_se_manager_util
/// @{
/// SE Challenge size
#define SL_SE_CHALLENGE_SIZE 16
/// Certificate key size
#define SL_SE_CERT_KEY_SIZE 64
/// Certificate signature size
#define SL_SE_CERT_SIGN_SIZE 64
/// Batch ID certificate
#define SL_SE_CERT_BATCH 0x01
/// SE ID certificate
#define SL_SE_CERT_DEVICE_SE 0x02
/// Host ID certificate
#define SL_SE_CERT_DEVICE_HOST 0x03
/// @addtogroup sl_se_manager_util_tamper Tamper options
/// @brief
/// Tamper configuration options. Levels, signals and filter options.
/// @{
// SE tamper signal levels
#define SL_SE_TAMPER_LEVEL_IGNORE 0 ///< No action taken
#define SL_SE_TAMPER_LEVEL_INTERRUPT 1 ///< Generate interrupt
#define SL_SE_TAMPER_LEVEL_FILTER 2 ///< Increment filter counter
#define SL_SE_TAMPER_LEVEL_RESET 4 ///< System reset
#define SL_SE_TAMPER_LEVEL_PERMANENTLY_ERASE_OTP 7 ///< Erase OTP - THIS WILL MAKE THE DEVICE INOPERATIONAL!
// SE tamper signals
#if defined(SLI_SE_MAJOR_VERSION_ONE)
#define SL_SE_TAMPER_SIGNAL_RESERVED_1 0x0 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_FILTER_COUNTER 0x1 ///< Filter counter exceeds threshold
#define SL_SE_TAMPER_SIGNAL_WATCHDOG 0x2 ///< SE watchdog timeout
#define SL_SE_TAMPER_SIGNAL_RESERVED_2 0x3 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SE_RAM_CRC 0x4 ///< SE RAM CRC parity error
#define SL_SE_TAMPER_SIGNAL_SE_HARDFAULT 0x5 ///< SE CPU hardfault
#define SL_SE_TAMPER_SIGNAL_RESERVED_3 0x6 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SE_SOFTWARE_ASSERTION 0x7 ///< SE software triggers an assert
#define SL_SE_TAMPER_SIGNAL_SE_SECURE_BOOT_FAILED 0x8 ///< Secure boot of SE firmware failed
#define SL_SE_TAMPER_SIGNAL_USER_SECURE_BOOT_FAILED 0x9 ///< Secure boot of user code failed
#define SL_SE_TAMPER_SIGNAL_MAILBOX_AUTHORIZATION_ERROR 0xA ///< Unauthorised command received over the Mailbox interface
#define SL_SE_TAMPER_SIGNAL_DCI_AUTHORIZATION_ERROR 0xB ///< Unauthorised command received over the DCI interface
#define SL_SE_TAMPER_SIGNAL_FLASH_INTEGRITY_ERROR 0xC ///< Flash content couldn't be properly authenticated
#define SL_SE_TAMPER_SIGNAL_RESERVED_4 0xD ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SELFTEST_FAILED 0xE ///< Integrity error of internal storage is detected
#define SL_SE_TAMPER_SIGNAL_TRNG_MONITOR 0xF ///< TRNG monitor detected lack of entropy
#define SL_SE_TAMPER_SIGNAL_PRS0 0x10 ///< PRS channel 0 asserted
#define SL_SE_TAMPER_SIGNAL_PRS1 0x11 ///< PRS channel 1 asserted
#define SL_SE_TAMPER_SIGNAL_PRS2 0x12 ///< PRS channel 2 asserted
#define SL_SE_TAMPER_SIGNAL_PRS3 0x13 ///< PRS channel 3 asserted
#define SL_SE_TAMPER_SIGNAL_PRS4 0x14 ///< PRS channel 4 asserted
#define SL_SE_TAMPER_SIGNAL_PRS5 0x15 ///< PRS channel 5 asserted
#define SL_SE_TAMPER_SIGNAL_PRS6 0x16 ///< PRS channel 6 asserted
#define SL_SE_TAMPER_SIGNAL_PRS7 0x17 ///< PRS channel 7 asserted
#define SL_SE_TAMPER_SIGNAL_DECOUPLE_BOD 0x18 ///< Decouple brown-out-detector threshold alert
#define SL_SE_TAMPER_SIGNAL_TEMPERATURE_SENSOR 0x19 ///< On-device temperature sensor detects operation outside datasheet specification
#define SL_SE_TAMPER_SIGNAL_VOLTAGE_GLITCH_FALLING 0x1A ///< Voltage glitch detector detected falling glitch
#define SL_SE_TAMPER_SIGNAL_VOLTAGE_GLITCH_RISING 0x1B ///< Voltage glitch detector detected rising glitch
#define SL_SE_TAMPER_SIGNAL_SECURE_LOCK_ERROR 0x1C ///< Debug lock internal logic check failed
#define SL_SE_TAMPER_SIGNAL_SE_DEBUG_GRANTED 0x1D ///< SE debug granted
#define SL_SE_TAMPER_SIGNAL_DIGITAL_GLITCH 0x1E ///< Digital glitch detector detected an event
#define SL_SE_TAMPER_SIGNAL_SE_ICACHE_ERROR 0x1F ///< SE ICACHE checksum error
#define SL_SE_TAMPER_SIGNAL_NUM_SIGNALS 0x20 ///< Number of tamper signals
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5) || defined(_SILICON_LABS_32B_SERIES_2_CONFIG_9)
// SE tamper signals for xG25 and xG29, with ETAMPDET signal included.
#define SL_SE_TAMPER_SIGNAL_RESERVED_1 0x0 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_FILTER_COUNTER 0x1 ///< Filter counter exceeds threshold
#define SL_SE_TAMPER_SIGNAL_WATCHDOG 0x2 ///< SE watchdog timeout
#define SL_SE_TAMPER_SIGNAL_RESERVED_2 0x3 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SE_RAM_ECC_2 0x4 ///< SE RAM 2-bit ECC error
#define SL_SE_TAMPER_SIGNAL_SE_HARDFAULT 0x5 ///< SE CPU hardfault
#define SL_SE_TAMPER_SIGNAL_RESERVED_3 0x6 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SE_SOFTWARE_ASSERTION 0x7 ///< SE software triggers an assert
#define SL_SE_TAMPER_SIGNAL_SE_SECURE_BOOT_FAILED 0x8 ///< Secure boot of SE firmware failed
#define SL_SE_TAMPER_SIGNAL_USER_SECURE_BOOT_FAILED 0x9 ///< Secure boot of user code failed
#define SL_SE_TAMPER_SIGNAL_MAILBOX_AUTHORIZATION_ERROR 0xA ///< Unauthorised command received over the Mailbox interface
#define SL_SE_TAMPER_SIGNAL_DCI_AUTHORIZATION_ERROR 0xB ///< Unauthorised command received over the DCI interface
#define SL_SE_TAMPER_SIGNAL_FLASH_INTEGRITY_ERROR 0xC ///< Flash content couldn't be properly authenticated
#define SL_SE_TAMPER_SIGNAL_RESERVED_4 0xD ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SELFTEST_FAILED 0xE ///< Integrity error of internal storage is detected
#define SL_SE_TAMPER_SIGNAL_TRNG_MONITOR 0xF ///< TRNG monitor detected lack of entropy
#define SL_SE_TAMPER_SIGNAL_SECURE_LOCK_ERROR 0x10 ///< Debug lock internal logic check failed
#define SL_SE_TAMPER_ATAMPDET_EMPGD 0x11 ///< Electromagnetic pulse glitch detector
#define SL_SE_TAMPER_ATAMPDET_SUPGD 0x12 ///< Supply glitch detector
#define SL_SE_TAMPER_SE_ICACHE_ERROR 0x13 ///< SE ICache RAM error
#define SL_SE_TAMPER_SIGNAL_SE_RAM_ECC_1 0x14 ///< SE RAM 1-bit ECC error
#define SL_SE_TAMPER_SIGNAL_BOD 0x15 ///< Brown-out-detector threshold alert
#define SL_SE_TAMPER_SIGNAL_TEMPERATURE_SENSOR 0x16 ///< On-device temperature sensor
#define SL_SE_TAMPER_SIGNAL_DPLL_LOCK_FAIL_LOW 0x17 ///< DPLL lock fail low
#define SL_SE_TAMPER_SIGNAL_DPLL_LOCK_FAIL_HIGH 0x18 ///< DPLL lock fail high
#define SL_SE_TAMPER_SIGNAL_ETAMPDET 0x19 ///< External tamper detect
#define SL_SE_TAMPER_SIGNAL_PRS0 0x1a ///< PRS channel 0 asserted
#define SL_SE_TAMPER_SIGNAL_PRS1 0x1b ///< PRS channel 1 asserted
#define SL_SE_TAMPER_SIGNAL_PRS2 0x1c ///< PRS channel 2 asserted
#define SL_SE_TAMPER_SIGNAL_PRS3 0x1d ///< PRS channel 3 asserted
#define SL_SE_TAMPER_SIGNAL_PRS4 0x1e ///< PRS channel 4 asserted
#define SL_SE_TAMPER_SIGNAL_PRS5 0x1f ///< PRS channel 5 asserted
#define SL_SE_TAMPER_SIGNAL_NUM_SIGNALS 0x20 ///< Number of tamper signals
#else
// SE tamper signals
#define SL_SE_TAMPER_SIGNAL_RESERVED_1 0x0 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_FILTER_COUNTER 0x1 ///< Filter counter exceeds threshold
#define SL_SE_TAMPER_SIGNAL_WATCHDOG 0x2 ///< SE watchdog timeout
#define SL_SE_TAMPER_SIGNAL_RESERVED_2 0x3 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SE_RAM_ECC_2 0x4 ///< SE RAM 2-bit ECC error
#define SL_SE_TAMPER_SIGNAL_SE_HARDFAULT 0x5 ///< SE CPU hardfault
#define SL_SE_TAMPER_SIGNAL_RESERVED_3 0x6 ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SE_SOFTWARE_ASSERTION 0x7 ///< SE software triggers an assert
#define SL_SE_TAMPER_SIGNAL_SE_SECURE_BOOT_FAILED 0x8 ///< Secure boot of SE firmware failed
#define SL_SE_TAMPER_SIGNAL_USER_SECURE_BOOT_FAILED 0x9 ///< Secure boot of user code failed
#define SL_SE_TAMPER_SIGNAL_MAILBOX_AUTHORIZATION_ERROR 0xA ///< Unauthorised command received over the Mailbox interface
#define SL_SE_TAMPER_SIGNAL_DCI_AUTHORIZATION_ERROR 0xB ///< Unauthorised command received over the DCI interface
#define SL_SE_TAMPER_SIGNAL_FLASH_INTEGRITY_ERROR 0xC ///< Flash content couldn't be properly authenticated
#define SL_SE_TAMPER_SIGNAL_RESERVED_4 0xD ///< Reserved tamper signal
#define SL_SE_TAMPER_SIGNAL_SELFTEST_FAILED 0xE ///< Integrity error of internal storage is detected
#define SL_SE_TAMPER_SIGNAL_TRNG_MONITOR 0xF ///< TRNG monitor detected lack of entropy
#define SL_SE_TAMPER_SIGNAL_SECURE_LOCK_ERROR 0x10 ///< Debug lock internal logic check failed
#define SL_SE_TAMPER_ATAMPDET_EMPGD 0x11 ///< Electromagnetic pulse glitch detector
#define SL_SE_TAMPER_ATAMPDET_SUPGD 0x12 ///< Supply glitch detector
#define SL_SE_TAMPER_SE_ICACHE_ERROR 0x13 ///< SE ICache RAM error
#define SL_SE_TAMPER_SIGNAL_SE_RAM_ECC_1 0x14 ///< SE RAM 1-bit ECC error
#define SL_SE_TAMPER_SIGNAL_BOD 0x15 ///< Brown-out-detector threshold alert
#define SL_SE_TAMPER_SIGNAL_TEMPERATURE_SENSOR 0x16 ///< On-device temperature sensor
#define SL_SE_TAMPER_SIGNAL_DPLL_LOCK_FAIL_LOW 0x17 ///< DPLL lock fail low
#define SL_SE_TAMPER_SIGNAL_DPLL_LOCK_FAIL_HIGH 0x18 ///< DPLL lock fail high
#define SL_SE_TAMPER_SIGNAL_PRS0 0x19 ///< PRS channel 0 asserted
#define SL_SE_TAMPER_SIGNAL_PRS1 0x1a ///< PRS channel 1 asserted
#define SL_SE_TAMPER_SIGNAL_PRS2 0x1b ///< PRS channel 2 asserted
#define SL_SE_TAMPER_SIGNAL_PRS3 0x1c ///< PRS channel 3 asserted
#define SL_SE_TAMPER_SIGNAL_PRS4 0x1d ///< PRS channel 4 asserted
#define SL_SE_TAMPER_SIGNAL_PRS5 0x1e ///< PRS channel 5 asserted
#define SL_SE_TAMPER_SIGNAL_PRS6 0x1f ///< PRS channel 6 asserted
#define SL_SE_TAMPER_SIGNAL_NUM_SIGNALS 0x20 ///< Number of tamper signals
#endif
// SE tamper filter timeout period.
#define SL_SE_TAMPER_FILTER_PERIOD_32MS 0x0 ///< Timeout ~32ms
#define SL_SE_TAMPER_FILTER_PERIOD_64MS 0x1 ///< Timeout ~64ms
#define SL_SE_TAMPER_FILTER_PERIOD_128MS 0x2 ///< Timeout ~128ms
#define SL_SE_TAMPER_FILTER_PERIOD_256MS 0x3 ///< Timeout ~256ms
#define SL_SE_TAMPER_FILTER_PERIOD_512MS 0x4 ///< Timeout ~512ms
#define SL_SE_TAMPER_FILTER_PERIOD_1S 0x5 ///< Timeout ~1s
#define SL_SE_TAMPER_FILTER_PERIOD_2S 0x6 ///< Timeout ~2s
#define SL_SE_TAMPER_FILTER_PERIOD_4S 0x7 ///< Timeout ~4.1s
#define SL_SE_TAMPER_FILTER_PERIOD_8S 0x8 ///< Timeout ~8.2s
#define SL_SE_TAMPER_FILTER_PERIOD_16S 0x9 ///< Timeout ~16.4s
#define SL_SE_TAMPER_FILTER_PERIOD_33S 0xA ///< Timeout ~32.8s
#define SL_SE_TAMPER_FILTER_PERIOD_1MIN 0xB ///< Timeout ~1.1min
#define SL_SE_TAMPER_FILTER_PERIOD_2MIN 0xC ///< Timeout ~2.2min
#define SL_SE_TAMPER_FILTER_PERIOD_4MIN 0xD ///< Timeout ~4.4min
#define SL_SE_TAMPER_FILTER_PERIOD_9MIN 0xE ///< Timeout ~8.7min
#define SL_SE_TAMPER_FILTER_PERIOD_18MIN 0xF ///< Timeout ~17.5min
#define SL_SE_TAMPER_FILTER_PERIOD_35MIN 0x10 ///< Timeout ~35min
#define SL_SE_TAMPER_FILTER_PERIOD_1H 0x11 ///< Timeout ~1.2h
#define SL_SE_TAMPER_FILTER_PERIOD_2H 0x12 ///< Timeout ~2.3h
#define SL_SE_TAMPER_FILTER_PERIOD_5H 0x13 ///< Timeout ~4.7h
#define SL_SE_TAMPER_FILTER_PERIOD_9H 0x14 ///< Timeout ~9.3h
#define SL_SE_TAMPER_FILTER_PERIOD_19H 0x15 ///< Timeout ~18.6h
#define SL_SE_TAMPER_FILTER_PERIOD_2DAYS 0x16 ///< Timeout ~1.6days
#define SL_SE_TAMPER_FILTER_PERIOD_3DAYS 0x17 ///< Timeout ~3.1days
#define SL_SE_TAMPER_FILTER_PERIOD_6DAYS 0x18 ///< Timeout ~6.2days
#define SL_SE_TAMPER_FILTER_PERIOD_12DAYS 0x19 ///< Timeout ~12.4days
#define SL_SE_TAMPER_FILTER_PERIOD_25DAYS 0x1A ///< Timeout ~24.9days
#define SL_SE_TAMPER_FILTER_PERIOD_50DAYS 0x1B ///< Timeout ~49.7days
#define SL_SE_TAMPER_FILTER_PERIOD_100DAYS 0x1C ///< Timeout ~99.4days
#define SL_SE_TAMPER_FILTER_PERIOD_199DAYS 0x1D ///< Timeout ~198.8days
#define SL_SE_TAMPER_FILTER_PERIOD_398DAYS 0x1E ///< Timeout ~397.7days
#define SL_SE_TAMPER_FILTER_PERIOD_795DAYS 0x1F ///< Timeout ~795.4days
// Number of tamper counts to trigger the filter signal.
#define SL_SE_TAMPER_FILTER_THRESHOLD_2 0x7 ///< Counter threshold 2
#define SL_SE_TAMPER_FILTER_THRESHOLD_4 0x6 ///< Counter threshold 4
#define SL_SE_TAMPER_FILTER_THRESHOLD_8 0x5 ///< Counter threshold 8
#define SL_SE_TAMPER_FILTER_THRESHOLD_16 0x4 ///< Counter threshold 16
#define SL_SE_TAMPER_FILTER_THRESHOLD_32 0x3 ///< Counter threshold 32
#define SL_SE_TAMPER_FILTER_THRESHOLD_64 0x2 ///< Counter threshold 64
#define SL_SE_TAMPER_FILTER_THRESHOLD_128 0x1 ///< Counter threshold 128
#define SL_SE_TAMPER_FILTER_THRESHOLD_256 0x0 ///< Counter threshold 256
/// Tamper flags.
#define SL_SE_TAMPER_FLAG_DGLITCH_ALWAYS_ON (1UL << 1) /// Digital glitch detector always on
#define SL_SE_TAMPER_FLAG_KEEP_TAMPER_ALIVE_DURING_SLEEP (1UL << 2) /// Tamper is kept alive during sleep (down to EM3)
/// @} (end addtogroup sl_se_manager_util_tamper)
/// @} (end addtogroup sl_se_manager_util)
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
#ifdef SL_SUPPRESS_DEPRECATION_WARNINGS_SDK_2025_6
/// Initial values for CMAC streaming context struct @ref sl_se_cmac_multipart_context_t
#define SL_SE_CMAC_STREAMING_INIT_DEFAULT { NULL, { 0 }, { 0 }, 0 }
/// Initial values for AES-GCM streaming context struct @ref sl_se_gcm_multipart_context_t
#define SL_SE_GCM_STREAMING_INIT_DEFAULT { NULL, 0, 0, { 0 }, { 0 }, \
{ 0 }, 0, 0 }
#else
#define SL_SE_GCM_STREAMING_INIT_DEFAULT _Pragma("GCC warning \"'SL_SE_GCM_STREAMING_INIT_DEFAULT' macro is deprecated as of Simplicity SDK release 2024.12\""){ NULL, 0, 0, { 0 }, { 0 }, \
{ 0 }, 0, 0 }
#define SL_SE_CMAC_STREAMING_INIT_DEFAULT _Pragma("GCC warning \"'SL_SE_CMAC_STREAMING_INIT_DEFAULT' macro is deprecated as of Simplicity SDK release 2024.12\"") { NULL, { 0 }, { 0 }, 0 }
#endif
/// @endcond
/// @addtogroup sl_se_manager_cipher
/// @{
/// Block size for the AES
#define SL_SE_AES_BLOCK_SIZE (16u)
/// @} (end addtogroup sl_se_manager_cipher)
/// @addtogroup sl_se_manager_hash
/// @{
#define SL_SE_HASH_STREAMING_INIT_DEFAULT { NULL, 0, 0, NULL } ///< Default streaming hash context
#define SL_SE_SHA1_STREAMING_INIT_DEFAULT { { 0 }, { 0 }, { 0 } } ///< SHA1 streaming hash context
#define SL_SE_SHA224_STREAMING_INIT_DEFAULT { { 0 }, { 0 }, { 0 } } ///< SHA224 streaming hash context
#define SL_SE_SHA256_STREAMING_INIT_DEFAULT { { 0 }, { 0 }, { 0 } } ///< SHA256 streaming hash context
#define SL_SE_SHA384_STREAMING_INIT_DEFAULT { { 0 }, { 0 }, { 0 } } ///< SHA384 streaming hash context
#define SL_SE_SHA512_STREAMING_INIT_DEFAULT { { 0 }, { 0 }, { 0 } } ///< SHA512 streaming hash context
/// @} (end addtogroup sl_se_manager_hash)
#elif defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED) // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
// -------------------------------
// Defines for Root code functionality
#define SL_SE_ROOT_CONFIG_MCU_SETTINGS_SHIFT 16U
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#if defined(_SILICON_LABS_32B_SERIES_3)
/// @addtogroup sl_se_manager_extmem
/// @{
// The maximum number of code regions available on the device.
// The number of available code regions may be different on future devices.
#define SL_SE_MAX_CODE_REGIONS 8
/// @} (end addtogroup sl_se_manager_extmem)
#endif // defined(_SILICON_LABS_32B_SERIES_3)
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#endif // SE_MANAGER_DEFINES_H

View File

@@ -0,0 +1,97 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_ENTROPY_H
#define SL_SE_MANAGER_ENTROPY_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager
/// @{
/***************************************************************************//**
* @addtogroup sl_se_manager_entropy Entropy
*
* @brief
* Random number generators
* @details
*
* API for getting randomness from the Secure Engine True Random Number
* Generator (TRNG).
*
* @{
******************************************************************************/
#include "sl_se_manager_key_handling.h"
#include "sl_se_manager_types.h"
#include "sli_se_manager_mailbox.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* @brief
* Get random data from hardware TRNG.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] data
* Random data from TRNG.
*
* @param[in] num_bytes
* Length of data request.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_get_random(sl_se_command_context_t *cmd_ctx,
void *data,
uint32_t num_bytes);
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager_entropy)
/// @} (end addtogroup sl_se)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_ENTROPY_H

View File

@@ -0,0 +1,308 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_HASH_H
#define SL_SE_MANAGER_HASH_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager
/// @{
/***************************************************************************//**
* @addtogroup sl_se_manager_hash Hashing
*
* @brief
* Provides cryptographic hash functions (SHA-1, SHA-224, SHA-256, SHA-384,
* SHA-512).
*
* @details
* Provides API for one-way hashing functions.
*
* @{
******************************************************************************/
#include "sl_se_manager_key_handling.h"
#include "sl_se_manager_types.h"
#include "sli_se_manager_mailbox.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* @brief
* Produce a message digest (a hash block) using the input data.
*
* @details
* This function generates a message digest adhering to the given inputs.
* For instance, if the algorithm is chosen to be SHA-256, it will generate
* a 32 bytes message digest computed based on the input message.
* This function supports SHA-1, SHA-256 and SHA-512 algorithms.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] hash_type
* Which hashing algorithm to use.
*
* @param[in] message
* Pointer to the message buffer to compute the hash/digest from.
*
* @param[in] message_size
* Number of bytes in message.
*
* @param[out] digest
* Pointer to block of memory to store the final digest.
*
* @param[in] digest_len
* The length of the message digest (hash), must be at least the size of the
* corresponding hash type.
*
* @return Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash(sl_se_command_context_t *cmd_ctx,
sl_se_hash_type_t hash_type,
const uint8_t *message,
unsigned int message_size,
uint8_t* digest,
size_t digest_len);
/***************************************************************************//**
* @brief
* Prepare a SHA1 hash streaming command context object.
*
* @details
* Prepare a SHA1 hash streaming command context object to be used in
* subsequent calls to hash streaming functions sl_se_hash_multipart_update() and
* sl_se_hash_multipart_finish().
*
* @param[in] sha1_ctx
* Pointer to a SHA1 streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_sha1_multipart_starts(sl_se_sha1_multipart_context_t *sha1_ctx,
sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Prepare a SHA224 hash streaming command context object.
*
* @details
* Prepare a SHA224 hash streaming command context object to be used in
* subsequent calls to hash streaming functions sl_se_hash_multipart_update() and
* sl_se_hash_multipart_finish().
*
* @param[in] sha224_ctx
* Pointer to a SHA224 streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_sha224_multipart_starts(sl_se_sha224_multipart_context_t *sha224_ctx,
sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Prepare a SHA256 hash streaming command context object.
*
* @details
* Prepare a SHA256 hash streaming command context object to be used in
* subsequent calls to hash streaming functions sl_se_hash_multipart_update() and
* sl_se_hash_multipart_finish().
*
* @param[in] sha256_ctx
* Pointer to a SHA256 streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_sha256_multipart_starts(sl_se_sha256_multipart_context_t *sha256_ctx,
sl_se_command_context_t *cmd_ctx);
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* @brief
* Prepare a SHA384 streaming command context object.
*
* @details
* Prepare a SHA384 hash streaming command context object to be used in
* subsequent calls to hash streaming functions sl_se_hash_multipart_update() and
* sl_se_hash_multipart_finish().
*
* @param[in] sha384_ctx
* Pointer to a SHA384 streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_sha384_multipart_starts(sl_se_sha384_multipart_context_t *sha384_ctx,
sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Prepare a SHA512 streaming command context object.
*
* @details
* Prepare a SHA512 hash streaming command context object to be used in
* subsequent calls to hash streaming functions sl_se_hash_multipart_update() and
* sl_se_hash_multipart_finish().
*
* @param[in] sha512_ctx
* Pointer to a SHA512 streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_sha512_multipart_starts(sl_se_sha512_multipart_context_t *sha512_ctx,
sl_se_command_context_t *cmd_ctx);
#endif // (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* @brief
* Prepare a hash streaming command context object.
*
* @details
* Prepare a hash (message digest) streaming command context object to be
* used in subsequent calls to hash streaming functions sl_se_hash_multipart_update()
* and sl_se_hash_multipart_finish().
*
* @param[in] hash_type_ctx
* Pointer to a hash streaming context object specific to the hash type
* specified by @p hash_type.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] hash_type
* Type of hash algoritm
*
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_multipart_starts(void *hash_type_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_hash_type_t hash_type);
/***************************************************************************//**
* @brief
* Feeds an input buffer into an ongoing hash computation.
*
* This function is called between @ref sl_se_hash_multipart_starts() and
* @ref sl_se_hash_multipart_finish().
* This function can be called repeatedly.
*
* @param[in] hash_type_ctx
* Pointer to a hash streaming context object specific to the hash type
* specified by @p hash_type.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] input
* Buffer holding the input data, must be at least @p ilen bytes wide.
*
* @param[in] input_len
* The length of the input data in bytes.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_multipart_update(void *hash_type_ctx,
sl_se_command_context_t *cmd_ctx,
const uint8_t *input,
size_t input_len);
/***************************************************************************//**
* @brief
* Finish a hash streaming operation and return the resulting hash digest.
*
* This function is called after sl_se_hash_multipart_update().
*
* @param[in] hash_type_ctx
* Pointer to a hash streaming context object specific to the hash type
* specified by @p hash_type.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] digest_out
* Buffer for holding the message digest (hash), must be at least the size
* of the corresponding message digest type.
*
* @param[in] digest_len
* The length of the message digest (hash), must be at least the size of the
* corresponding hash type.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_hash_multipart_finish(void *hash_type_ctx,
sl_se_command_context_t *cmd_ctx,
uint8_t *digest_out,
size_t digest_len);
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager_hash)
/// @} (end addtogroup sl_se_manager)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_HASH_H

View File

@@ -0,0 +1,143 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager Internal key defines
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_INTERNAL_KEYS
#define SL_SE_MANAGER_INTERNAL_KEYS
#include "sli_se_manager_features.h"
#include "sl_se_manager_defines.h"
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#if defined(SLI_SE_MAJOR_VERSION_ONE)
/// Key descriptor for internal application attestation key
#define SL_SE_APPLICATION_ATTESTATION_KEY \
{ \
.type = SL_SE_KEY_TYPE_ECC_P256, \
.flags = SL_SE_KEY_FLAG_NON_EXPORTABLE \
| SL_SE_KEY_FLAG_IS_DEVICE_GENERATED \
| SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY \
| SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY, \
.storage = { \
.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE, \
.location = { \
.slot = SL_SE_KEY_SLOT_APPLICATION_ATTESTATION_KEY, \
}, \
}, \
}
#else
/// Key descriptor for internal application attestation key
#define SL_SE_APPLICATION_ATTESTATION_KEY \
{ \
.type = SL_SE_KEY_TYPE_ECC_P256, \
.flags = SL_SE_KEY_FLAG_IS_DEVICE_GENERATED \
| SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY \
| SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY, \
.storage = { \
.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE, \
.location = { \
.slot = SL_SE_KEY_SLOT_APPLICATION_ATTESTATION_KEY, \
}, \
}, \
}
#endif
/// Key descriptor for internal SE attestation key
/// @note: Can only be used to get the public part
#define SL_SE_SYSTEM_ATTESTATION_KEY \
{ \
.type = SL_SE_KEY_TYPE_ECC_P256, \
.flags = SL_SE_KEY_FLAG_NON_EXPORTABLE \
| SL_SE_KEY_FLAG_IS_DEVICE_GENERATED \
| SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PRIVATE_KEY \
| SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY, \
.storage = { \
.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE, \
.location = { \
.slot = SL_SE_KEY_SLOT_SE_ATTESTATION_KEY, \
}, \
}, \
}
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
/// Key descriptor for secure boot public key
#define SL_SE_APPLICATION_SECURE_BOOT_KEY \
{ \
.type = SL_SE_KEY_TYPE_ECC_P256, \
.flags = SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY \
| SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY, \
.storage = { \
.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE, \
.location = { \
.slot = SL_SE_KEY_SLOT_APPLICATION_SECURE_BOOT_KEY, \
}, \
}, \
}
/// Key descriptor for secure debug public key
#define SL_SE_APPLICATION_SECURE_DEBUG_KEY \
{ \
.type = SL_SE_KEY_TYPE_ECC_P256, \
.flags = SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY \
| SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY, \
.storage = { \
.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE, \
.location = { \
.slot = SL_SE_KEY_SLOT_APPLICATION_SECURE_DEBUG_KEY, \
}, \
}, \
}
/// Key descriptor for application AES-128 key
#define SL_SE_APPLICATION_AES_128_KEY \
{ \
.type = SL_SE_KEY_TYPE_AES_128, \
.flags = SL_SE_KEY_FLAG_NON_EXPORTABLE, \
.storage = { \
.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE, \
.location = { \
.slot = SL_SE_KEY_SLOT_APPLICATION_AES_128_KEY, \
}, \
}, \
}
/// Key descriptor for TrustZone root key
#define SL_SE_TRUSTZONE_ROOT_KEY \
{ \
.type = SL_SE_KEY_TYPE_AES_256, \
.flags = SL_SE_KEY_FLAG_IS_DEVICE_GENERATED, \
.storage = { \
.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE, \
.location = { \
.slot = SL_SE_KEY_SLOT_TRUSTZONE_ROOT_KEY, \
}, \
}, \
}
#endif // SL_SE_MANAGER_INTERNAL_KEYS

View File

@@ -0,0 +1,436 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_KEY_DERIVATION_H
#define SL_SE_MANAGER_KEY_DERIVATION_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager
/// @{
/***************************************************************************//**
* @addtogroup sl_se_manager_key_derivation Key derivation
*
* @brief
* API for key derivation and key agreement (ECDH, EC J-PAKE, HKDF, PBKDF2).
*
* @details
* Contains key derivation functions (HKDF, PBKDF2) and key agreement
* functions (ECDH, ECJPAKE).
*
* @{
******************************************************************************/
#include "sl_se_manager_key_handling.h"
#include "sl_se_manager_types.h"
#include "sli_se_manager_mailbox.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Prototypes
// -------------------------------
// Elliptic-curve DiffieHellman
/***************************************************************************//**
* @brief
* This function computes the shared secret with Elliptic Curve Diffie Hellman
* (ECDH) algorithm
*
* @details
* Performs Elliptic Curve Diffie Hellman shared secret computation.
*
* @note
* P-521 Elliptic Curve based Elliptic Curve Diffie Hellman (ECDH) expects
* a 544 bits (68 bytes) buffer for storing private keys, and
* a 1088 bits (136 bytes) buffer for storing public keys and shared secret.
* The first 23 bits of d, Qx, Qy and shared secret are padding bits to comply
* word-aligned addressing. The padding bits are ignored in the computation.
*
* This function does not implement the value-checking of the shared secret
* as described in RFC7748 when using Montgomery keys.
*
* In case of using custom domain curves, \p key_in_priv defines the domain
* parameters. Moreover, \p key_in_pub should always contain a public key.
* If key_in_pub contains a private key, sl_se_export_public_key() can be
* used to export the public key.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_in_priv
* Our private key.
*
* @param[in] key_in_pub
* Their public key.
*
* @param[out] key_out
* Shared secret key. Montgomery curve result is one single coordinate.
* Other curve types result in one pair of coordinate.
*
* @return
* SL_STATUS_INVALID_KEY if \p key_in_pub does not contain a public key
* when using custom domain curves, otherwise an appropriate error code
* (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecdh_compute_shared_secret(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key_in_priv,
const sl_se_key_descriptor_t *key_in_pub,
const sl_se_key_descriptor_t *key_out);
// -------------------------------
// EC J-PAKE
/***************************************************************************//**
* @brief
* Check if an EC J-PAKE context is ready for use.
*
* @param[in] ctx
* The EC J-PAKE context to check. This must be initialized.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_check(const sl_se_ecjpake_context_t *ctx);
/***************************************************************************//**
* @brief
* Derive the shared secret (TLS: Pre-Master Secret).
*
* @param[in] ctx
* The EC J-PAKE context to use. This must be initialized, set up and have
* performed both round one and two.
*
* @param[out] buf
* The buffer to write the derived secret to. This must be a writable buffer
* of length @p len bytes.
*
* @param[in] len
* The length of @p buf in bytes.
*
* @param[out] olen
* The address at which to store the total number of bytes written to @p buf.
* This must not be @c NULL.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_derive_secret(sl_se_ecjpake_context_t *ctx,
unsigned char *buf,
size_t len,
size_t *olen);
/***************************************************************************//**
* @brief
* This clears an EC J-PAKE context and frees any embedded data structure.
*
* @param[in] ctx
* The EC J-PAKE context to free. This may be @c NULL, in which case this
* function does nothing. If it is not @c NULL, it must point to an
* initialized EC J-PAKE context.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_free(sl_se_ecjpake_context_t *ctx);
/***************************************************************************//**
* @brief
* Initialize an EC J-PAKE context.
*
* @param[in] ctx
* The EC J-PAKE context to initialize. This must not be @c NULL.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_init(sl_se_ecjpake_context_t *ctx,
sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Read and process the first round message (TLS: contents of the
* Client/ServerHello extension, excluding extension type and length bytes).
*
* @param[in] ctx
* The EC J-PAKE context to use. This must be initialized and set up.
*
* @param[in] buf
* The buffer holding the first round message. This must be a readable buffer
* of length @p len bytes.
*
* @param[in] len
* The length in bytes of @p buf.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_read_round_one(sl_se_ecjpake_context_t *ctx,
const unsigned char *buf,
size_t len);
/***************************************************************************//**
* @brief
* Read and process the second round message (TLS: contents of the
* Client/ServerKeyExchange).
*
* @param[in] ctx
* The EC J-PAKE context to use. This must be initialized and set up and already
* have performed round one.
*
* @param[in] buf
* The buffer holding the second round message. This must be a readable buffer
* of length @p len bytes.
*
* @param[in] len
* The length in bytes of @p buf.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_read_round_two(sl_se_ecjpake_context_t *ctx,
const unsigned char *buf,
size_t len);
/***************************************************************************//**
* @brief
* Set up an EC J-PAKE context for use.
*
* @note
* Currently the only values for hash/curve allowed by the standard are
* @ref SL_SE_HASH_SHA256 / @ref SL_SE_KEY_TYPE_ECC_P256.
*
* @param[in] ctx
* The EC J-PAKE context to set up. This must be initialized.
*
* @param[in] role
* The role of the caller. This must be either @ref SL_SE_ECJPAKE_CLIENT or
* @ref SL_SE_ECJPAKE_SERVER.
*
* @param[in] hash
* The identifier of the hash function to use, for example
* @ref SL_SE_HASH_SHA256.
*
* @param[in] curve
* The identifier of the elliptic curve to use, for example
* @ref SL_SE_KEY_TYPE_ECC_P256.
*
* @param[in] secret
* The pre-shared secret (passphrase). This must be a readable buffer of
* length @p len bytes. It need only be valid for the duration of this call.
*
* @param[in] len
* The length of the pre-shared secret @p secret.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_setup(sl_se_ecjpake_context_t *ctx,
sl_se_ecjpake_role_t role,
sl_se_hash_type_t hash,
uint32_t curve,
const unsigned char *secret,
size_t len);
/***************************************************************************//**
* @brief
* Generate and write the first round message (TLS: contents of the
* Client/ServerHello extension, excluding extension type and length bytes).
*
* @param[in] ctx
* The EC J-PAKE context to use. This must be initialized and set up.
*
* @param[out] buf
* The buffer to write the contents to. This must be a writable buffer of
* length @p len bytes.
*
* @param[in] len
* The length of @p buf in bytes.
*
* @param[out] olen
* The address at which to store the total number of bytes written to @p buf.
* This must not be @c NULL.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_write_round_one(sl_se_ecjpake_context_t *ctx,
unsigned char *buf,
size_t len,
size_t *olen);
/***************************************************************************//**
* @brief
* Generate and write the second round message (TLS: contents of the
* Client/ServerKeyExchange).
*
* @param[in] ctx
* The EC J-PAKE context to use. This must be initialized, set up, and already
* have performed round one.
*
* @param[out] buf
* The buffer to write the round two contents to. This must be a writable
* buffer of length @p len bytes.
*
* @param[in] len
* The size of @p buf in bytes.
*
* @param[out] olen
* The address at which to store the total number of bytes written to @p buf.
* This must not be @c NULL.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecjpake_write_round_two(sl_se_ecjpake_context_t *ctx,
unsigned char *buf,
size_t len,
size_t *olen);
// -------------------------------
// Key derivation functions
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* @brief
* Derive a pseudorandom key from the input key material using HKDF.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] in_key
* Pointer to the input key material.
*
* @param[in] hash
* Which hashing algorithm to use.
*
* @param[in] salt
* An optional salt value (a non-secret random value).
*
* @param[in] salt_len
* The length of the salt.
*
* @param[in] info
* An optional context and application specific information string.
*
* @param[in] info_len
* The length of info.
*
* @param[in,out] out_key
* Pointer to the generated key material. The length member of out_key is
* used to request a given length of the generated key.
*
* @return
* SL_STATUS_OK if the signature is successfully verified, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_derive_key_hkdf(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *in_key,
sl_se_hash_type_t hash,
const unsigned char *salt,
size_t salt_len,
const unsigned char *info,
size_t info_len,
sl_se_key_descriptor_t *out_key);
/***************************************************************************//**
* @brief
* Derive a pseudorandom key from the input key material using PBKDF2.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] in_key
* Pointer to the input key material.
*
* @param[in] prf
* The underlying psuedorandom function (PRF) to use in the algorithm. The
* most common choice of HMAC-SHA-{1, 224, 256, 384, 512} is supported on all
* Series-2 devices (with Vault High Security). Newer chips, EFR32xG23 and
* later, also support usage of AES-CMAC-PRF-128.
*
* @param[in] salt
* An optional salt value (a non-secret random value).
*
* @param[in] salt_len
* The length of the salt.
*
* @param[in] iterations
* The number of iterations to use. Up to 16384 iterations is supported.
*
* @param[in,out] out_key
* Pointer to the generated key material. The length member of out_key is
* used to request a given length of the generated key.
*
* @return
* SL_STATUS_OK if the signature is successfully verified, otherwise an
* appropriate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_derive_key_pbkdf2(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *in_key,
sl_se_pbkdf2_prf_type_t prf,
const unsigned char *salt,
size_t salt_len,
uint32_t iterations,
sl_se_key_descriptor_t *out_key);
#endif // (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager_key_derivation)
/// @} (end addtogroup sl_se_manager)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_KEY_DERIVATION_H

View File

@@ -0,0 +1,258 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager key handling.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_KEY_HANDLING_H
#define SL_SE_MANAGER_KEY_HANDLING_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager
/// @{
#include "sl_se_manager_types.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* \addtogroup sl_se_manager_key_handling Key handling
*
* \brief Secure Engine key handling API.
*
* \details
* API for using cryptographic keys with the SE. Contains functionality to
* generate, import and export keys to and from protected types like wrapped
* or volatile keys.
*
* \{
******************************************************************************/
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* @brief
* Validate key descriptor.
*
* @details
* Takes a key descriptor and checks if all required properties have been set
* for the specific key type.
*
* @param[in] key
* The key to validate.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_validate_key(const sl_se_key_descriptor_t *key);
/***************************************************************************//**
* @brief
* Generate a random key adhering to the given key descriptor
*
* @details
* The SE takes a key descriptor and generates a key with the given properties
* in the location specified by the descriptor.
*
* If the key size is not aligned to a multiple of words the key
* representation is padded in front of the key.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_out
* Description of the key to generate. Sets key parameters and describes the
* storage location for the key.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_generate_key(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key_out);
/***************************************************************************//**
* @brief
* Import a key using the SE
*
* @details
* Protect a key using the SE. Import a plaintext key and store it either in a
* volatile slot or as a wrapped key.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_in
* A plaintext key.
*
* @param[in] key_out
* Either a volatile or a wrapped key with similar properties as key_in.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_import_key(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key_in,
const sl_se_key_descriptor_t *key_out);
/***************************************************************************//**
* @brief
* Export a volatile or wrapped key back to plaintext
*
* @details
* Attempt to have the SE export a volatile or wrapped key back to plaintext
* if allowed.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_in
* Either a volatile or a wrapped key with similar properties as key_out.
*
* @param[in] key_out
* The exported key in plaintext.
*
* @return
* Status code, @ref sl_status.h.
* SL_STATUS_INVALID_PARAMETER if key does not exist.
******************************************************************************/
sl_status_t sl_se_export_key(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key_in,
const sl_se_key_descriptor_t *key_out);
/***************************************************************************//**
* @brief
* Transfer a volatile or wrapped key to another protected storage.
*
* @details
* Attempt to have the SE transfer a volatile or wrapped key if allowed.
*
* @note
* The key stored in the source protected storage will not be deleted.
*
* Transferring a key between the same volatile slot is not allowed.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_in
* Either a volatile or a wrapped key with similar properties as key_out.
*
* @param[in] key_out
* Either a volatile or a wrapped key with similar properties as key_in.
*
* @return
* Status code, @ref sl_status.h.
* SL_STATUS_INVALID_PARAMETER if key does not exist.
******************************************************************************/
sl_status_t sl_se_transfer_key(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key_in,
const sl_se_key_descriptor_t *key_out);
/***************************************************************************//**
* @brief
* Export the public part of an ECC keypair
*
* @details
* The output key must be specified to only contain a public key.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_in
* An asymmetric key with either a private or public part.
*
* @param[out] key_out
* Describes output key parameters. Should only be set to contain the public
* part of the key.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_export_public_key(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key_in,
const sl_se_key_descriptor_t *key_out);
/***************************************************************************//**
* @brief
* Delete a key from a volatile SE storage slot
*
* @details
* The given key will be removed from the SE. The key descriptor is not
* modified and can be used to generate a new key without any updates.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Key to delete.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_delete_key(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key);
/***************************************************************************//**
* @brief
* Returns the required storage size for the given key
*
* @details
* Finds the total storage size required for a given key. This includes
* storage for the public and private part of asymmetric keys, as well as
* overhead for wrapping keys.
*
* @param[in] key
* The sl_se_key_descriptor_t to find the required storage size for.
*
* @param[out] storage_size
* The required storage size in bytes.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_get_storage_size(const sl_se_key_descriptor_t *key,
uint32_t *storage_size);
#ifdef __cplusplus
}
#endif
/** @} (end addtogroup sl_se_key) */
/** @} (end addtogroup sl_se) */
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_KEY_HANDLING_H

View File

@@ -0,0 +1,185 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_SIGNATURE_H
#define SL_SE_MANAGER_SIGNATURE_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager
/// @{
/***************************************************************************//**
* @addtogroup sl_se_manager_signature Signature
*
* @brief
* Digital Signature Algorithms (ECDSA, EdDSA).
*
* @details
* API for using digital signatures with the SE.
*
* @{
******************************************************************************/
#include "sl_se_manager_key_handling.h"
#include "sl_se_manager_types.h"
#include "sli_se_manager_mailbox.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* @brief
* This function computes Elliptic-Curve Cryptography (ECC) digital signatures
* of a message.
*
* @note
* Edwards-curve Digital Signature Algorithm (EdDSA) generates a message digest
* using the input message for computing signatures. The input parameters
* \p hash_alg and \p hashed_message do not apply for EdDSA.
*
* P-521 Elliptic Curve for Elliptic Curve Digital Signature Algorithm (ECDSA)
* expects a 544 bits (68 bytes) buffer for storing private keys,
* and a 1088 bits (136 bytes) buffer for storing public keys and signatures.
* The first 23 bits of d, Qx, Qy, R and S are padding bits to comply
* word-aligned addressing.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] hash_alg
* Which hashing algorithm to use. Ignored for EdDSA keys, since EdDSA always
* uses SHA-512 for Ed25519 and SHA-3 for Ed448.
*
* @param[in] hashed_message
* The input message is a message digest. Ignored for EdDSA keys, and treated
* as false.
*
* @param[in] message
* The message to be used to compute the signature.
*
* @param[in] message_len
* The length of message.
*
* @param[out] signature
* The computed signature.
*
* @param[in] signature_len
* The length of the computed signature.
*
* @return
* SL_STATUS_OK when the command was executed successfully, otherwise an
* appropiate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecc_sign(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
sl_se_hash_type_t hash_alg,
bool hashed_message,
const unsigned char *message,
size_t message_len,
unsigned char *signature,
size_t signature_len);
/***************************************************************************//**
* @brief
* This function verifies Elliptic-Curve Cryptography (ECC) digital signatures
* of a message.
*
* @note
* The input parameters \p hash_alg and \p hashed_message do not apply for
* Edwards-curve Digital Signature Algorithm (EdDSA).
*
* P-521 Elliptic Curve for Elliptic Curve Digital Signature Algorithm (ECDSA)
* expects a 544 bits (68 bytes) buffer for storing private keys,
* and a 1088 bits (136 bytes) buffer for storing public keys and signatures.
* The first 23 bits of d, Qx, Qy, R and S are padding bits to comply
* word-aligned addressing.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] hash_alg
* Which hashing algorithm to use. Ignored for EdDSA keys, since EdDSA always
* uses SHA-512 for Ed25519 and SHA-3 for Ed448.
*
* @param[in] hashed_message
* The input message is a message digest. Ignored for EdDSA keys, and treated
* as false.
*
* @param[in] message
* The message to be used to compute signatures.
*
* @param[in] message_len
* The length of message.
*
* @param[in] signature
* The signature to be verified.
*
* @param[in] signature_len
* The length of signature.
*
* @return
* SL_STATUS_OK if the signature is successfully verified, otherwise an
* appropiate error code (@ref sl_status.h).
******************************************************************************/
sl_status_t sl_se_ecc_verify(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
sl_se_hash_type_t hash_alg,
bool hashed_message,
const unsigned char *message,
size_t message_len,
const unsigned char *signature,
size_t signature_len);
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager_signature)
/// @} (end addtogroup sl_se_manager)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_SIGNATURE_H

View File

@@ -0,0 +1,514 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API types
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_TYPES_H
#define SL_SE_MANAGER_TYPES_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager
/// @{
#include "sl_se_manager_defines.h"
#include "sli_se_manager_mailbox.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Typedefs
/// @addtogroup sl_se_manager_util
/// @{
/// OTP key types
typedef enum {
SL_SE_KEY_TYPE_IMMUTABLE_BOOT = 0,
SL_SE_KEY_TYPE_IMMUTABLE_AUTH,
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
SL_SE_KEY_TYPE_IMMUTABLE_AES_128,
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
SL_SE_KEY_TYPE_IMMUTABLE_ATTESTATION,
SL_SE_KEY_TYPE_IMMUTABLE_SE_ATTESTATION,
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
#endif // SLI_MAILBOX_COMMAND_SUPPORTED
} sl_se_device_key_type_t;
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// SE tamper signal levels
typedef uint8_t sl_se_tamper_level_t;
/// SE tamper signals
typedef uint32_t sl_se_tamper_signals_t;
/// SE tamper filter timeout period
typedef uint8_t sl_se_tamper_filter_period_t;
/// Number of tamper counts to trigger the filter signal
typedef uint8_t sl_se_tamper_filter_threshold_t;
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
/// Certificate size data structure
typedef struct {
uint32_t batch_id_size; ///< size in bytes of the Batch certificate
uint32_t se_id_size; ///< size in bytes of the SE ID certificate
uint32_t host_id_size; ///< size in bytes of the Host ID certificate
} sl_se_cert_size_type_t;
/// SE certificate types
typedef uint8_t sl_se_cert_type_t;
/// OTP initialization data structure
typedef struct {
/// Enable secure boot for the host.
bool enable_secure_boot;
/// Require certificate based secure boot signing.
bool verify_secure_boot_certificate;
/// Enable anti-rollback for host application upgrades.
bool enable_anti_rollback;
/// Set flag to enable locking down all flash pages that cover the
/// secure-booted image, except the last page if end of signature is not
/// page-aligned.
bool secure_boot_page_lock_narrow;
/// Set flag to enable locking down all flash pages that cover the
/// secure-booted image, including the last page if end of signature is not
/// page-aligned.
bool secure_boot_page_lock_full;
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// List of tamper levels to configure for the different tamper sources.
sl_se_tamper_level_t tamper_levels[SL_SE_TAMPER_SIGNAL_NUM_SIGNALS];
/// Reset period for the tamper filter counter.
sl_se_tamper_filter_period_t tamper_filter_period;
/// Activation threshold for the tamper filter.
sl_se_tamper_filter_threshold_t tamper_filter_threshold;
/// Tamper flags.
uint8_t tamper_flags;
/// Tamper reset halt threshold.
uint8_t tamper_reset_threshold;
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
} sl_se_otp_init_t;
/// @} (end addtogroup sl_se_manager_util)
/// @addtogroup sl_se_manager_core
/// @{
/***************************************************************************//**
* @brief SE mailbox command context
*
* @details
* This structure defines the common SE mailbox command context used for
* all SE Manager API functions that execute SE mailbox commands. The
* members of this context structure should be considered internal to the
* SE Manager and should not be read or written directly by the user
* application. For members that are relevant for the user, the user can
* access them via corresponding set and get API functions, e.g.
* sl_se_set_yield().
******************************************************************************/
typedef struct sl_se_command_context_t {
sli_se_mailbox_command_t command; ///< SE mailbox command struct
bool yield; ///< If true, yield the CPU core while
///< waiting for the SE mailbox command
///< to complete. If false, busy-wait, by
///< polling the SE mailbox response
///< register.
} sl_se_command_context_t;
/// @} (end addtogroup sl_se_manager_core)
/// @addtogroup sl_se_manager_util
/// @{
/// SE Debug lock flags
typedef uint32_t sl_se_debug_flags_t;
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// Debug lock options
typedef struct {
/// Non-Secure, Invasive debug access enabled if true. If false, it is not
/// possible to debug the non-secure state in a way that is intrusive to
/// program execution (DBGLOCK locked).
bool non_secure_invasive_debug;
/// Non-Secure, Non-Invasive debug access enabled if true. If false, it is
/// not possible to debug the non-secure state in a way that is intrusive to
/// program execution (NIDLOCK locked).
bool non_secure_non_invasive_debug;
/// Secure, Invasive debug access enabled if true. If false, it is not
/// possible to debug the secure TrustZone state in a way that is intrusive
/// to program execution (SPIDLOCK locked).
bool secure_invasive_debug;
/// Secure, Non-Invasive debug access enabled if true. If false, it is not
/// possible to observe the secure TrustZone state using trace.
/// (SPNIDLOCK is locked. However if SPIDLOCK is open, SPNIDLOCK will also
/// remain open.)
bool secure_non_invasive_debug;
} sl_se_debug_options_t;
#endif
/// Debug status
typedef struct {
/// Whether device erase is enabled
bool device_erase_enabled;
/// Whether secure debug is enabled with @ref sl_se_enable_secure_debug().
bool secure_debug_enabled;
/// Whether the debug port has been locked with @ref sl_se_apply_debug_lock().
/// This parameter does not indicate if the debug port has been unlocked by
/// calling @ref sl_se_open_debug().
bool debug_port_lock_applied;
/// Current state of the debug port.
/// True if locked with @ref sl_se_apply_debug_lock().
/// False if new clean, erased or unlocked with @ref sl_se_open_debug().
bool debug_port_lock_state;
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// Debug option configuration as set by @ref sl_se_set_debug_options().
sl_se_debug_options_t options_config;
/// Current state of debug options, locked by @ref sl_se_set_debug_options() and
/// unlocked by @ref sl_se_open_debug().
sl_se_debug_options_t options_state;
#endif
} sl_se_debug_status_t;
/// @} (end addtogroup sl_se_manager_util)
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager_key_handling
/// @{
/// Supported key types
typedef uint32_t sl_se_key_type_t;
/// Key storage method. Can have one of @ref SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT,
/// @ref SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED,
/// @ref SL_SE_KEY_STORAGE_INTERNAL_VOLATILE,
/// @ref SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE or
/// @ref SL_SE_KEY_STORAGE_INTERNAL_KSU.
typedef uint32_t sl_se_storage_method_t;
/// Internal SE key slot
typedef uint32_t sl_se_key_slot_t;
/// Describes where the key is or should be stored
typedef struct {
uint8_t* pointer; ///< Pointer to a key buffer.
uint32_t size; ///< Size of buffer.
} sl_se_buffer_t;
/// KSU Metadata
#if defined(_SILICON_LABS_32B_SERIES_3)
typedef struct {
uint8_t keyslot; ///< Keyslot to store key at in KSU
uint8_t id; ///< KSU instance to store key
uint8_t crypto_engine_id; ///< Which Crypto Engine to use this key
uint8_t allowed_key_users; ///< Allowed key users
} sl_se_ksu_metadata_t;
#endif
/// Describes the storage location of keys
typedef struct {
/// Key storage method. Sets meaning of data in location.
sl_se_storage_method_t method;
/// Describes key storage location. @ref sl_se_buffer_t is used if @ref sl_se_key_storage_t.method is
/// @ref SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT or
/// @ref SL_SE_KEY_STORAGE_EXTERNAL_WRAPPED, while @ref sl_se_key_slot_t is
/// used for @ref SL_SE_KEY_STORAGE_INTERNAL_VOLATILE or
/// @ref SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE.
/// @ref ksu is used for @ref SL_SE_KEY_STORAGE_INTERNAL_KSU
union {
sl_se_buffer_t buffer;
sl_se_key_slot_t slot;
#if defined(_SILICON_LABS_32B_SERIES_3)
sl_se_ksu_metadata_t ksu;
#endif
} location;
} sl_se_key_storage_t;
/// Contains a full description of a key used by an SE command.
typedef struct {
/// Key type
sl_se_key_type_t type;
/// Key size, applicable if key_type == SYMMETRIC
size_t size;
/// Flags describing restrictions, permissions and attributes of the key.
uint32_t flags;
/// Storage location for this key
sl_se_key_storage_t storage;
/// Optional password for key usage (8 bytes). If no password is provided
/// (NULL pointer), any key not stored as plaintext will be stored with a
/// password of all-zero bytes.
uint8_t* password;
/// Pointer to domain descriptor if this key contains an asymmetric key on a
/// custom domain The reason for pointing instead of containing is to make
/// it possible to have the parameters in ROM.
const void* domain;
} sl_se_key_descriptor_t;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// Custom Weierstrass curve structure.
typedef struct {
/// Domain size in bytes.
const size_t size;
/// Modulus p (zero-padded from MSB, right-adjusted to extend to 32-bit
/// alignment up from domain size)
const uint8_t* p;
/// Order N (zero-padded from MSB, right-adjusted to extend to 32-bit
/// alignment up from domain size)
const uint8_t* N;
/// Generator X-coordinate (zero-padded from MSB, right-adjusted to extend
/// to 32-bit alignment up from domain size)
const uint8_t* Gx;
/// Generator Y-coordinate (zero-padded from MSB, right-adjusted to extend
/// to 32-bit alignment up from domain size)
const uint8_t* Gy;
/// Parameter a (zero-padded from MSB, right-adjusted to extend to 32-bit
/// alignment up from domain size)
const uint8_t* a;
/// Parameter b (zero-padded from MSB, right-adjusted to extend to 32-bit
/// alignment up from domain size)
const uint8_t* b;
/// Set if a equals 0
bool a_is_zero;
/// Set if a equals -3
bool a_is_minus_three;
} sl_se_custom_weierstrass_prime_domain_t;
#endif
/// @} (end addtogroup sl_se_manager_key_handling)
/// @addtogroup sl_se_manager_util
/// @{
/// SE challenge storage
typedef uint8_t sl_se_challenge_t[SL_SE_CHALLENGE_SIZE];
/// SE status
typedef struct {
/// Boot status code / error code (Bits [7:0]).
uint32_t boot_status;
/// SE firmware version.
uint32_t se_fw_version;
/// Host firmware version (if available).
uint32_t host_fw_version;
/// Debug lock status.
sl_se_debug_status_t debug_status;
/// Secure boot enabled.
bool secure_boot_enabled;
/// Active mode enabled.
bool active_mode_enabled;
/// Recorded tamper status. Reset on status read.
uint32_t tamper_status;
/// Currently active tamper sources.
uint32_t tamper_status_raw;
#if defined(_SILICON_LABS_32B_SERIES_3)
uint8_t rom_revision;
/// ROM revision
uint8_t otp_patch_sequence;
/// OTP patch sequence
#endif
} sl_se_status_t;
/// @} (end addtogroup sl_se_manager_util)
/// @addtogroup sl_se_manager_cipher
/// @{
/// Cipher operation types
typedef enum {
SL_SE_ENCRYPT,
SL_SE_DECRYPT
} sl_se_cipher_operation_t;
/// CMAC streaming context
typedef struct {
uint8_t state[16]; ///< CMAC state
uint8_t data_in[16]; ///< Unprocessed data
uint8_t data_out[16]; ///< Last 16 bytes of cipher-text
size_t length; ///< Length of all processed and unprocessed data
} sl_se_cmac_multipart_context_t;
/// CCM streaming context.
typedef struct {
uint32_t processed_message_length;///< Current length of the encrypted/decrypted data
uint32_t total_message_length; ///< Total length of data to be encrypted/decrypted
uint8_t iv[13]; ///< Nonce (MAX size is 13 bytes)
uint32_t tag_len; ///< Tag length
sl_se_cipher_operation_t mode;///< CCM mode (decrypt or encrypt)
#if defined(SLI_SE_MAJOR_VERSION_ONE)
uint8_t nonce_counter[16]; ///< Counter to keep CTR state
uint8_t iv_len; ///< Nonce length
uint8_t cbc_mac_state[16]; ///< State of authenication/MAC
uint8_t final_data[16]; ///< Input data saved for finish operation
#else
uint8_t se_ctx[32]; ///< SE encryption state
union {
uint8_t tagbuf[16]; ///< Tag
uint8_t final_data[16]; ///< Input data saved for finish operation
} mode_specific_buffer; ///< Buffer containing Tag and input data saved for finish operation
#endif
uint8_t final_data_length; ///< Length of data saved
} sl_se_ccm_multipart_context_t;
typedef struct {
uint64_t len; ///< Total length of the encrypted data
uint64_t add_len; ///< Total length of the additional data
#if defined(SLI_SE_MAJOR_VERSION_ONE)
uint8_t tagbuf[16]; ///< Tag
uint8_t previous_se_ctx[32]; ///< SE state from previous operation
#endif
uint8_t se_ctx[32]; ///< SE state
uint8_t final_data[16]; ///< Input data saved for finish operation
uint8_t final_data_length; ///< Length of data saved
sl_se_cipher_operation_t mode;///< GCM mode
bool first_operation; ///< First operation
} sl_se_gcm_multipart_context_t;
/// @} (end addtogroup sl_se_manager_cipher)
/// @addtogroup sl_se_manager_hash
/// @{
/// Hash algorithms
typedef enum {
SL_SE_HASH_NONE, ///< No hash
SL_SE_HASH_SHA1, ///< SHA-1
SL_SE_HASH_SHA224, ///< SHA-224
SL_SE_HASH_SHA256, ///< SHA-256
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
SL_SE_HASH_SHA384, ///< SHA-384
SL_SE_HASH_SHA512, ///< SHA-512
#endif
} sl_se_hash_type_t;
/// SHA-1 streaming context.
typedef struct {
sl_se_hash_type_t hash_type; ///< Hash streaming context
uint32_t total[2]; ///< number of bytes processed
uint8_t state[32]; ///< intermediate digest state
uint8_t buffer[64]; ///< data block being processed
} sl_se_sha1_multipart_context_t;
/// SHA-224 streaming context.
typedef struct {
sl_se_hash_type_t hash_type; ///< Hash streaming context
uint32_t total[2]; ///< Number of bytes processed
uint8_t state[32]; ///< Intermediate digest state
uint8_t buffer[64]; ///< Data block being processed
} sl_se_sha224_multipart_context_t;
/// SHA-256 streaming context.
typedef struct {
sl_se_hash_type_t hash_type; ///< Hash streaming context
uint32_t total[2]; ///< Number of bytes processed
uint8_t state[32]; ///< Intermediate digest state
uint8_t buffer[64]; ///< Data block being processed
} sl_se_sha256_multipart_context_t;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// SHA-384 streaming context.
typedef struct {
sl_se_hash_type_t hash_type; ///< Hash streaming context
uint32_t total[4]; ///< Number of bytes processed
uint8_t state[64]; ///< Intermediate digest state
uint8_t buffer[128]; ///< Data block being processed
} sl_se_sha384_multipart_context_t;
/// SHA-512 streaming context.
typedef struct {
sl_se_hash_type_t hash_type; ///< Hash streaming context
uint32_t total[4]; ///< Number of bytes processed
uint8_t state[64]; ///< Intermediate digest state
uint8_t buffer[128]; ///< Data block being processed
} sl_se_sha512_multipart_context_t;
#endif
/// @} (end addtogroup sl_se_manager_hash)
/// @addtogroup sl_se_manager_key_derivation
/// @{
/// Roles in the EC J-PAKE exchange
typedef enum {
SL_SE_ECJPAKE_CLIENT = 0, ///< Client
SL_SE_ECJPAKE_SERVER, ///< Server
} sl_se_ecjpake_role_t;
/**************************************************************************//**
* EC J-PAKE context structure.
*
* J-PAKE is a symmetric protocol, except for the identifiers used in
* Zero-Knowledge Proofs, and the serialization of the second message
* (KeyExchange) as defined by the Thread spec.
*
* In order to benefit from this symmetry, we choose a different naming
* convention from the Thread v1.0 spec. Correspondance is indicated in the
* description as a pair C: client name, S: server name
*****************************************************************************/
typedef struct {
sl_se_command_context_t *cmd_ctx; ///< Pointer to command context object
uint32_t curve_flags; ///< Curve flags to use
sl_se_ecjpake_role_t role; ///< Are we client or server?
char pwd[32]; ///< J-PAKE password
size_t pwd_len; ///< J-PAKE password length
uint8_t r[32]; ///< Random scalar for exchange
uint8_t Xm1[64]; ///< Our point 1 (round 1)
uint8_t Xm2[64]; ///< Our point 2 (round 1)
uint8_t Xp1[64]; ///< Their point 1 (round 1)
uint8_t Xp2[64]; ///< Their point 2 (round 1)
uint8_t Xp[64]; ///< Their point (round 2)
} sl_se_ecjpake_context_t;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// Typedef sl_se_pbkdf2_prf_type_t to sl_se_hash_type_t in order to maintain
/// backward compatibility. Defines for mapping the PRF identifiers to the
/// underlying hash enum values exists in sl_se_manager_defines.h.
typedef sl_se_hash_type_t sl_se_pbkdf2_prf_type_t;
#endif
/// @} (end addtogroup sl_se_manager_key_derivation)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_TYPES_H

View File

@@ -0,0 +1,960 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SL_SE_MANAGER_UTIL_H
#define SL_SE_MANAGER_UTIL_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
/// @addtogroup sl_se_manager
/// @{
/***************************************************************************//**
* @addtogroup sl_se_manager_util Utilities
*
* @brief
* Device initialisation, debug lock, upgrade functionality, user data...
*
* @details
* API for managing the Secure Engine or Root code on a device. Upload and
* read device configuration.
*
* @{
******************************************************************************/
#if !defined(SL_TRUSTZONE_NONSECURE)
#include "sl_se_manager_key_handling.h"
#endif
#include "sl_se_manager_types.h"
#include "sli_se_manager_mailbox.h"
#include "sl_status.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_SILICON_LABS_32B_SERIES_3)
/// Lifecycle event flags keep track of certain events and state changes by setting a one-time
/// irreversible flag in the OTP. This enum contains information on what the separate event flags
/// indicate. The lifecycle state flags can be fetched using @ref sl_se_get_lifecycle_event_flags. The utility
/// @ref sl_se_lifecycle_event_flag_is_set can be used to check if any specific flag has been set.
typedef enum {
SL_SE_LIFECYCLE_EVENT_HOST_UNSECURE_UNLOCKED = 0, ///< Host has been unsecure-unlocked
SL_SE_LIFECYCLE_EVENT_HOST_SECURE_UNLOCKED = 1, ///< Host has been secure-unlocked
SL_SE_LIFECYCLE_EVENT_SE_SECURE_UNLOCKED = 2, ///< SE has been secure-unlocked
SL_SE_LIFECYCLE_EVENT_INITIAL_DEBUG_LOCK_SET = 3, ///< Initial debug lock token has been set in MTP
SL_SE_LIFECYCLE_EVENT_HOST_SECURE_DEBUG_ENABLED = 4, ///< Host secure debug has been enabled
SL_SE_LIFECYCLE_EVENT_HOST_SECURE_DEBUG_DISABLED = 5, ///< Host secure debug has been disabled
SL_SE_LIFECYCLE_EVENT_HOST_DEBUG_LOCKED = 6, ///< Host has been debug locked
SL_SE_LIFECYCLE_EVENT_AXIP_NONCE_ROLL_DISABLED = 7, ///< AXiP nonce rolling has been disabled
} sl_se_lifecycle_event_flag_t;
#endif // #if defined(_SILICON_LABS_32B_SERIES_3)
// -----------------------------------------------------------------------------
// Prototypes
/***************************************************************************//**
* @brief
* Validate SE firmware image.
*
* @details
* Validate SE firmware image located at given address. This function is
* typically used before calling sl_se_apply_se_image.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] image_addr
* Pointer to SE image to validate.
*
* @return
* One of the following @ref status codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_check_se_image(sl_se_command_context_t *cmd_ctx,
void *image_addr);
/***************************************************************************//**
* @brief
* Apply SE firmware image.
*
* @details
* Apply SE firmware image located at given address.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] image_addr
* Pointer to SE image to apply.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_apply_se_image(sl_se_command_context_t *cmd_ctx,
void *image_addr);
/***************************************************************************//**
* @brief
* Get upgrade status of SE firmware image.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] status
* Pointer to 32-bit word where to return upgrade status.
*
* @param[in] prev_version
* Pointer to 32-bit word where to return previous version.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_get_upgrade_status_se_image(sl_se_command_context_t *cmd_ctx,
uint32_t *status,
uint32_t *prev_version);
/***************************************************************************//**
* @brief
* Validate Host firmware image.
*
* @details
* Validate Host firmware image located at given address. This function is
* typically used before calling @ref sl_se_apply_host_image.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] image_addr
* Pointer to Host image to validate.
*
* @param[in] size
* Size of Host image to validate.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_check_host_image(sl_se_command_context_t *cmd_ctx,
void *image_addr,
uint32_t size);
/***************************************************************************//**
* @brief
* Apply Host firmware image.
*
* @details
* Apply Host firmware image located at given address.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] image_addr
* Pointer to Host image to apply.
*
* @param[in] size
* Size of Host image to apply.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_apply_host_image(sl_se_command_context_t *cmd_ctx,
void *image_addr,
uint32_t size);
/***************************************************************************//**
* @brief
* Get upgrade status of Host firmware image.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] status
* Pointer to 32-bit word where to return upgrade status.
*
* @param[in] prev_version
* Pointer to 32-bit word where to return previous version.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t
sl_se_get_upgrade_status_host_image(sl_se_command_context_t *cmd_ctx,
uint32_t *status,
uint32_t *prev_version);
/***************************************************************************//**
* @brief
* Initialize key to be stored in the SE OTP flash.
*
* @details
* Initialize key stored in the SE. The command can be used to write (@ref sl_se_device_key_type_t):
* * SL_SE_KEY_TYPE_IMMUTABLE_BOOT
* * SL_SE_KEY_TYPE_IMMUTABLE_AUTH
* * SL_SE_KEY_TYPE_IMMUTABLE_AES_128
*
* @note
* These keys can not be overwritten, so this command can only be issued once
* per key per part.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_type
* ID of key type to initialize.
*
* @param[in] key
* Pointer to a buffer that contains the key.
* Public keys must be word aligned and have a length of 64 bytes.
* AES-128 keys must be word aligned and have length of 16 bytes.
*
* @param[in] num_bytes
* Length of key buffer in bytes (16 or 64 bytes).
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_init_otp_key(sl_se_command_context_t *cmd_ctx,
sl_se_device_key_type_t key_type,
void *key,
uint32_t num_bytes);
/***************************************************************************//**
* @brief
* Read a public key stored in the SE.
*
* @details
* Read out a public key stored in the SE. The command can be used to read (@ref sl_se_device_key_type_t):
* * SL_SE_KEY_TYPE_IMMUTABLE_BOOT
* * SL_SE_KEY_TYPE_IMMUTABLE_AUTH
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key_type
* ID of key type to read.
*
* @param[out] key
* Pointer to a buffer to contain the returned public key.
* Must be word aligned and have a length of 64 bytes.
*
* @param[in] num_bytes
* Length of pubkey buffer (64 bytes).
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_read_pubkey(sl_se_command_context_t *cmd_ctx,
sl_se_device_key_type_t key_type,
void *key,
uint32_t num_bytes);
/***************************************************************************//**
* @brief
* Initialize and commit SE OTP configuration to OTP.
*
* @warning
* When this function succeeds the configuration is committed to OTP and cannot be changed.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] otp_init
* Pointer to OTP initialization structure.
*
* @return
* One of the following @ref sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
* - @c SL_STATUS_ABORT when the operation is not attempted.
*
******************************************************************************/
sl_status_t sl_se_init_otp(sl_se_command_context_t *cmd_ctx,
sl_se_otp_init_t *otp_init);
/***************************************************************************//**
* @brief
* Read the OTP firmware version of the SE module.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] version
* Pointer to uint32_t word where version shall be returned.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_get_otp_version(sl_se_command_context_t *cmd_ctx,
uint32_t *version);
/***************************************************************************//**
* @brief
* Read SE OTP configuration.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] otp_settings
* Pointer to OTP initialization structure.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_COMMAND if OTP configuration isn't initialized
* - @c SL_STATUS_ABORT when the operation is not attempted.
******************************************************************************/
sl_status_t sl_se_read_otp(sl_se_command_context_t *cmd_ctx,
sl_se_otp_init_t *otp_settings);
/***************************************************************************//**
* @brief
* Read the SE firmware version.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] version
* Pointer to uint32_t word where version shall be returned.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_OWNERSHIP when the ownership is already taken
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_SE_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sl_se_get_se_version(sl_se_command_context_t *cmd_ctx,
uint32_t *version);
/***************************************************************************//**
* @brief
* Returns the current debug lock configuration.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] status
* Pointer to sl_se_debug_status_t structure to be filled out with the
* current status of the debug configuration.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_get_debug_lock_status(sl_se_command_context_t *cmd_ctx,
sl_se_debug_status_t *status);
/***************************************************************************//**
* @brief
* Enables the debug lock for the part.
*
* @details
* The debug port will be closed and the only way to open it is through
* device erase (if enabled) or through secure debug unlock (if enabled).
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
******************************************************************************/
sl_status_t sl_se_apply_debug_lock(sl_se_command_context_t *cmd_ctx);
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/***************************************************************************//**
* @brief
* Writes data to User Data section in MTP. Write data must be aligned to
* word size and contain a number of bytes that is divisable by four.
* @note
* It is recommended to erase the flash page before performing a write.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
* @param[in] offset
* Offset to the flash word to write to. Must be aligned to words.
* @param[in] data
* Data to write to flash.
* @param[in] num_bytes
* Number of bytes to write to flash. NB: Must be divisable by four.
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_write_user_data(sl_se_command_context_t *cmd_ctx,
uint32_t offset,
void *data,
uint32_t num_bytes);
/***************************************************************************//**
* @brief
* Erases User Data section in MTP.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_erase_user_data(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Returns the current boot status, versions and system configuration.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] status
* SE_Status_t containing current SE status.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK upon command completion. Errors are encoded in the
* different parts of the returned status object.
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_get_status(sl_se_command_context_t *cmd_ctx,
sl_se_status_t *status);
/***************************************************************************//**
* @brief
* Read the serial number of the SE module.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] serial
* Pointer to array of size 16 bytes.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_get_serialnumber(sl_se_command_context_t *cmd_ctx,
void *serial);
#if defined(SLI_SE_COMMAND_STATUS_READ_RSTCAUSE_AVAILABLE)
/***************************************************************************//**
* @brief
* Read the EMU->RSTCAUSE after a tamper reset. This function should be called
* if EMU->RSTCAUSE has been cleared upon boot.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] reset_cause
* Pointer to uint32_t word where reset cause shall be returned.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
******************************************************************************/
sl_status_t sl_se_get_reset_cause(sl_se_command_context_t *cmd_ctx,
uint32_t *reset_cause);
#endif
#if defined(SLI_SE_COMMAND_READ_TAMPER_RESET_CAUSE_AVAILABLE)
/***************************************************************************//**
* @brief
* Read the latest cached tamper reset cause. The returned value is the index
* of the tamper source that caused a reset.
* Requires SE version 2.2.1 or above.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] was_tamper_reset
* Pointer to bool that indicates if a tamper event occurred. If the cached
* value is 0 this will be false, true otherwise.
*
* @param[out] reset_cause
* Pointer to a uint32_t where the cached reset cause value should
* be returned.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_PARAMETER when cmd_ctx or reset_cause is NULL
******************************************************************************/
sl_status_t sl_se_get_tamper_reset_cause(sl_se_command_context_t *cmd_ctx,
bool *was_tamper_reset,
uint32_t *reset_cause);
#endif // SLI_SE_COMMAND_READ_TAMPER_RESET_CAUSE_AVAILABLE
#if defined(_SILICON_LABS_32B_SERIES_3)
/***************************************************************************//**
* @brief
* Reads out traceable lifecycle event flags from the OTP. See
* \ref sl_se_lifecycle_event_flag_t for details on what the individual flag bits
* indicate.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] event_flags
* Pointer to an array of at least 8 bytes, to contain the trace flags
*
* @return
* SL_STATUS_OK upon successfull execution, error code elsewise
******************************************************************************/
sl_status_t sl_se_get_lifecycle_event_flags(sl_se_command_context_t *cmd_ctx, uint64_t *event_flags);
/***************************************************************************//**
* @brief
* Utility for checking if a certain lifecycle event flag is set
*
* @param[in] flags
* Pointer to an 8 byte array of lifecycle event flags (event_flags from
* \ref sl_se_get_lifecycle_event_flags)
*
* @param[in] flag_index
* Which bit (event flag) to check if is set
*
* @return
* true if event flag bit was set
* false if event flag bit was not set
******************************************************************************/
__STATIC_INLINE bool sl_se_lifecycle_event_flag_is_set(uint64_t *flags, sl_se_lifecycle_event_flag_t flag_index)
{
return (*flags & (1 << flag_index) ? true : false);
}
#endif // #if defined(_SILICON_LABS_32B_SERIES_3)
/***************************************************************************//**
* @brief
* Enables the secure debug functionality.
*
* @details
* Enables the secure debug functionality that can be used to open a locked
* debug port through the Get challenge and Open debug commands. This command
* can only be executed before the debug port is locked, and after a secure
* debug public key has been installed in the SE.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
******************************************************************************/
sl_status_t sl_se_enable_secure_debug(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Disables the secure debug functionality.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @details
* Disables the secure debug functionality that can be used to open a
* locked debug port.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
******************************************************************************/
sl_status_t sl_se_disable_secure_debug(sl_se_command_context_t *cmd_ctx);
/***************************************************************************/ /**
* @brief
* Set debug options.
*
* @details
* This function makes it possible to configure the Trust-Zone access
* permissions of the debug interface. For details please refer to
* @ref sl_se_debug_options_t.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] debug_options
* Pointer to debug options structure.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
******************************************************************************/
sl_status_t sl_se_set_debug_options(sl_se_command_context_t *cmd_ctx,
const sl_se_debug_options_t *debug_options);
/***************************************************************************//**
* @brief
* Performs a device mass erase and debug unlock.
*
* @details
* Performs a device mass erase and resets the debug configuration to its
* initial unlocked state. Only available before DEVICE_ERASE_DISABLE has
* been executed.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @note
* This command clears and verifies the complete flash and ram of the
* system, excluding the user data pages and one-time programmable
* commissioning information in the secure engine.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_COMMAND if device erase is disabled.
******************************************************************************/
sl_status_t sl_se_erase_device(sl_se_command_context_t *cmd_ctx);
/****************************************************************q***********//**
* @brief
* Disabled device erase functionality.
*
* @details
* This command disables the device erase command. It does not lock the
* debug interface to the part, but it is a permanent action for the part.
* If device erase is disabled and the device is debug locked, there is no
* way to permanently unlock the part. If secure debug unlock is enabled,
* secure debug unlock can still be used to temporarily open the debug port.
*
* @warning
* This command permanently disables the device erase functionality!
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
******************************************************************************/
sl_status_t sl_se_disable_device_erase(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Request challenge from SE which can be used to open debug access.
*
* @details
* This command requests a challenge (16 bytes) which can be used to generate
* a certificate in order to open debug access, @ref sl_se_open_debug.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] challenge
* SE challenge storage.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_get_challenge(sl_se_command_context_t *cmd_ctx,
sl_se_challenge_t challenge);
/***************************************************************************//**
* @brief
* Invalidate current challenge and make a new challenge.
*
* @details
* This command requests the SE to invalidate it's current challenge (16bytes)
* and generate a new challenge.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
******************************************************************************/
sl_status_t sl_se_roll_challenge(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Unlock debug access using certificate and signed challenge.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] cert
* Certificate for debug unlock and signed challenge.
*
* @param[in] len
* Length of certificate in number of bytes.
*
* @param[in] debug_options
* Debug options to open/unlock.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_open_debug(sl_se_command_context_t *cmd_ctx,
void *cert,
uint32_t len,
const sl_se_debug_options_t *debug_options);
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* @brief
* Temporarily disable tamper configuration using certificate and signed
* challenge.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] cert
* Certificate for disabling tamper and signed challenge.
*
* @param[in] len
* Length of certificate in number of bytes.
*
* @param[in] tamper_signals
* Tamper signals to disable. Each signal represented by a bit.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_OPERATION when the SE command ID is not recognized
* - @c SL_STATUS_INVALID_CREDENTIALS when the command is not authorized
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
******************************************************************************/
sl_status_t sl_se_disable_tamper(sl_se_command_context_t *cmd_ctx,
void *cert,
uint32_t len,
sl_se_tamper_signals_t tamper_signals);
#endif // (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* @brief
* Read size of stored certificates in SE.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in,out] cert_size
* Size of the certificates stored in SE.
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_read_cert_size(sl_se_command_context_t *cmd_ctx,
sl_se_cert_size_type_t *cert_size);
/***************************************************************************//**
* @brief
* Read stored certificates in SE.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] cert_type
* Type of the certificate stored in SE.
*
* @param[in,out] cert
* Buffer to read certificate.
*
* @param[in] num_bytes
* Length of certificate in number of bytes.
*
* @return
* Status code, @ref status
******************************************************************************/
sl_status_t sl_se_read_cert(sl_se_command_context_t *cmd_ctx,
sl_se_cert_type_t cert_type,
void *cert,
uint32_t num_bytes);
/***************************************************************************//**
* @brief
* Enter SE active mode.
*
* @details
* SE will enter active mode. This will ensure SE is not powered down between
* operations, at the expense of increased power consumption.
*
* @warning
* Active mode will prevent entry to EM2/3/4. To allow energy mode entry, exit
* active mode through @ref sl_se_exit_active_mode().
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
* - @c SL_STATUS_COMMAND_IS_INVALID when already in active mode
******************************************************************************/
sl_status_t sl_se_enter_active_mode(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Exit SE active mode.
*
* @details
* SE will exit active mode.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* One of the following sl_status_t codes:
* - @c SL_STATUS_OK when the command was executed successfully
* - @c SL_STATUS_INVALID_PARAMETER when an invalid parameter was passed
* - @c SL_STATUS_COMMAND_IS_INVALID when already not in active mode
******************************************************************************/
sl_status_t sl_se_exit_active_mode(sl_se_command_context_t *cmd_ctx);
#if defined(_SILICON_LABS_32B_SERIES_3)
/***************************************************************************//**
* @brief
* Read the OTP rollback counter.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
* @param[out] rollback_counter
* Pointer to location where the rollback counter value will be returned.
*
* @return
* SL_STATUS_OK when the function executed successfully, else, a status code
* of type sl_status_t that indicates why the function was not successful,
* @ref status
******************************************************************************/
sl_status_t sl_se_get_rollback_counter(sl_se_command_context_t *cmd_ctx,
uint32_t *rollback_counter);
/***************************************************************************//**
* @brief
* Increment the OTP rollback counter.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[out] rollback_counter
* Optional: Retrieve the rollback counter count after increment
* Set to NULL to ignore
* @return
* SL_STATUS_OK when the function executed successfully, else, a status code
* of type sl_status_t that indicates why the function was not successful,
* @ref status
******************************************************************************/
sl_status_t sl_se_increment_rollback_counter(sl_se_command_context_t *cmd_ctx,
uint32_t *rollback_counter);
/***************************************************************************//**
* @brief
* Reads back the stored upgrade file version.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
* @param[out] version
* The stored upgrade file version.
*
* @return
* SL_STATUS_OK when the function executed successfully, else, a status code
* of type sl_status_t that indicates why the function was not successful,
* @ref status
******************************************************************************/
sl_status_t sl_se_get_upgrade_file_version(sl_se_command_context_t *cmd_ctx,
uint32_t *version);
/***************************************************************************//**
* @brief
* Records a new upgrade file version.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
* @param[in] version
* New upgrade file version
*
* @return
* \ref SL_STATUS_OK when the function executed successfully, else, a status code
* of type sl_status_t that indicates why the function was not successful,
* @ref status
******************************************************************************/
sl_status_t sl_se_set_upgrade_file_version(sl_se_command_context_t *cmd_ctx,
uint32_t version);
#endif // defined(_SILICON_LABS_32B_SERIES_3)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sl_se_manager_util)
/// @} (end addtogroup sl_se_manager)
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#endif // SL_SE_MANAGER_UTIL_H

View File

@@ -0,0 +1,138 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs SE Manager macros representing features.
*******************************************************************************
* # License
* <b>Copyright 2023 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SLI_SE_MANAGER_FEATURES_H
#define SLI_SE_MANAGER_FEATURES_H
#if !defined(__linux__)
#include "em_device.h"
#endif // !__linux__
#if defined(DOXYGEN)
#undef _SILICON_LABS_SECURITY_FEATURE // Allow doxygen to include the SVH only features
#define _SILICON_LABS_SECURITY_FEATURE _SILICON_LABS_SECURITY_FEATURE_VAULT
#define SLI_MAILBOX_COMMAND_SUPPORTED
#define SLI_VSE_MAILBOX_COMMAND_SUPPORTED
#define SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
#define SLI_SE_COMMAND_STATUS_READ_RSTCAUSE_AVAILABLE
#define SLI_SE_COMMAND_READ_TAMPER_RESET_CAUSE_AVAILABLE
#define SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_CMAC_AVAILABLE
#else // DOXYGEN
#if defined(__linux__)
// ---------------------------- HOST ---------------------------- //
// The header is being used on a host system with Linux running on it,
// assume that the endpoint attached to the host system is a SVH type.
#define SLI_SE_MANAGER_HOST_SYSTEM
#define SLI_MAILBOX_COMMAND_SUPPORTED
#define _SILICON_LABS_SECURITY_FEATURE_SE (0)
#define _SILICON_LABS_SECURITY_FEATURE_VAULT (1)
#define _SILICON_LABS_SECURITY_FEATURE_ROT (2)
#define _SILICON_LABS_SECURITY_FEATURE_BASE (3)
#define _SILICON_LABS_SECURITY_FEATURE _SILICON_LABS_SECURITY_FEATURE_VAULT
#define SLI_SE_COMMAND_READ_TAMPER_RESET_CAUSE_AVAILABLE
#if defined(SLI_SE_MAJOR_VERSION_ONE)
#define SLI_SE_COMMAND_STATUS_READ_RSTCAUSE_AVAILABLE
// EFR32xG23+ doesn't require padding of curve elements or other keys
#define SLI_SE_KEY_PADDING_REQUIRED
#define SLI_SE_P521_PADDING_BYTES (2u)
#define SLI_MINIMUM_REQUIRED_NUMBER_PARAMS (0u)
#elif defined(SLI_SE_MAJOR_VERSION_TWO)
#define SLI_SE_P521_PADDING_BYTES (0u)
// PBKDF2 with CMAC as the PRF was first supported on EFR32xG23.
#define SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_CMAC_AVAILABLE
#define SLI_MINIMUM_REQUIRED_NUMBER_PARAMS (1u)
#endif
// Define the helper macros needed for the host system
#define __REV(num) (((num & 0xFF000000) >> 24) \
| ((num & 0x00FF0000) >> 8) \
| ((num & 0x0000FF00) << 8) \
| ((num & 0x000000FF) << 24))
#elif defined(SEMAILBOX_PRESENT)
// --------------------------------- HSE --------------------------------- //
#define SLI_MAILBOX_COMMAND_SUPPORTED
#if (defined(_SILICON_LABS_SECURITY_FEATURE) \
&& (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) \
&& ((defined(_SILICON_LABS_32B_SERIES_2_CONFIG) && _SILICON_LABS_32B_SERIES_2_CONFIG >= 3) \
|| defined(_SILICON_LABS_32B_SERIES_3)))
// Reading the latest cached tamper reset cause requires SE version 2.2.1 or above.
#define SLI_SE_COMMAND_READ_TAMPER_RESET_CAUSE_AVAILABLE
// The option to keep the tamper alive during sleep is only configurable for SE with major version 2
#define SLI_SE_TAMPER_FLAG_KEEP_TAMPER_ALIVE_AVAILABLE
#endif
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
#define SLI_SE_MAJOR_VERSION_ONE
#else
#define SLI_SE_MAJOR_VERSION_TWO
#endif
#if defined(_SILICON_LABS_32B_SERIES_3)
#define SLI_SE_SUPPORTS_NVM3_INTERNAL_KEY
#endif
#if defined(SLI_SE_MAJOR_VERSION_ONE)
#define SLI_SE_COMMAND_STATUS_READ_RSTCAUSE_AVAILABLE
// EFR32xG23+ doesn't require padding of curve elements or other keys
#define SLI_SE_KEY_PADDING_REQUIRED
#define SLI_SE_P521_PADDING_BYTES (2u)
#define SLI_MINIMUM_REQUIRED_NUMBER_PARAMS (0u)
#elif defined(SLI_SE_MAJOR_VERSION_TWO)
#define SLI_SE_P521_PADDING_BYTES (0u)
// PBKDF2 with CMAC as the PRF was first supported on EFR32xG23.
#define SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_CMAC_AVAILABLE
#define SLI_MINIMUM_REQUIRED_NUMBER_PARAMS (1u)
#endif
#elif defined(CRYPTOACC_PRESENT)
// --------------------------------- VSE --------------------------------- //
#define SLI_VSE_MAILBOX_COMMAND_SUPPORTED
#endif // __linux__
#endif // DOXYGEN
#endif // SLI_SE_MANAGER_FEATURES_H

View File

@@ -0,0 +1,212 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager internal API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SE_MANAGER_INTERNAL_H
#define SE_MANAGER_INTERNAL_H
#include "sli_se_manager_features.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#include "sl_status.h"
#include "sli_se_manager_mailbox.h"
#include "sl_se_manager.h"
#include "sl_se_manager_key_handling.h"
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Defines
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
// Due to a problem with the countermeasures applied to
// accelerated point multiplication over elliptic curves,
// it is possible that random errors are encountered (this
// is extremely unilkely for truly random keys).
// As a workaround for this, the affected commands will
// retry the operation in order to reduce the probability
// that the error code was returned incorrectly. This helps
// lower the error probability further when using purposely
// small or large scalars, for example during testing.
#define SLI_SE_MAX_POINT_MULT_RETRIES 3U
#endif
// -------------------------------
// Function-like macros
/***************************************************************************//**
* @brief
* Helper macro to init/reset the SE command struct of an SE command context
*
* @param[in] cmd_ctx
* Pointer to SE context containing the command to initialize/reset
*
* @param[out] command_word
* Command word to set in the SE command.
*
******************************************************************************/
#define sli_se_command_init(cmd_ctx, command_word) \
cmd_ctx->command.command = command_word; \
cmd_ctx->command.data_in = NULL; \
cmd_ctx->command.data_out = NULL; \
cmd_ctx->command.num_parameters = 0;
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
/***************************************************************************//**
* @brief
* Helper macros to add key parameters and input/output blocks to SE commands
*
* @param[in] cmd_ctx
* Pointer to SE context
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure
* @param[out] status
* SL_Status_T
*
******************************************************************************/
// Add keyspec to command for given key
#define sli_add_key_parameters(cmd_ctx, key, status) { \
uint32_t keyspec; \
(status) = sli_se_key_to_keyspec((key), &keyspec); \
if ((status) != SL_STATUS_OK) { \
return (status); \
} \
sli_se_mailbox_command_add_parameter(&cmd_ctx->command, keyspec); \
}
// Add key metadata buffers to command for given key
#define sli_add_key_metadata(cmd_ctx, key, status) \
/* Auth data */ \
sli_se_datatransfer_t auth_buffer; \
(status) = sli_se_get_auth_buffer((key), &auth_buffer); \
if ((status) != SL_STATUS_OK) { \
return (status); \
} \
sli_se_mailbox_command_add_input(&cmd_ctx->command, &auth_buffer);
// Add key metadata buffers with custom auth buffer to command for given key
#define sli_add_key_metadata_custom(cmd_ctx, auth_data_buf, key, status) \
/* Auth data */ \
sli_se_datatransfer_t auth_data_buf; \
(status) = sli_se_get_auth_buffer((key), &auth_data_buf); \
if ((status) != SL_STATUS_OK) { \
return (status); \
} \
sli_se_mailbox_command_add_input(&cmd_ctx->command, &auth_data_buf);
// Add key input buffer to given command
#define sli_add_key_input(cmd_ctx, key, status) \
sli_se_datatransfer_t key_input_buffer; \
(status) = sli_se_get_key_input_output((key), &key_input_buffer); \
if ((status) != SL_STATUS_OK) { \
return (status); \
} \
sli_se_mailbox_command_add_input(&cmd_ctx->command, &key_input_buffer);
// Add Key output buffer to given command
#define sli_add_key_output(cmd_ctx, key, status) \
sli_se_datatransfer_t key_output_buffer; \
(status) = sli_se_get_key_input_output((key), &key_output_buffer); \
if ((status) != SL_STATUS_OK) { \
return (status); \
} \
sli_se_mailbox_command_add_output(&cmd_ctx->command, &key_output_buffer);
#endif // SLI_MAILBOX_COMMAND_SUPPORTED
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
sl_status_t sli_se_to_sl_status(sli_se_mailbox_response_t res);
/***************************************************************************//**
* @brief
* Take the SE lock in order to synchronize multiple threads calling into
* the SE Manager API concurrently.
*
* @return
* SL_STATUS_OK when successful, or else error code.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_SE_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_se_lock_acquire(void);
/***************************************************************************//**
* @brief
* Give the SE lock in order to synchronize multiple threads calling into
* the SE Manager API concurrently.
*
* @return
* SL_STATUS_OK when successful, or else error code.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_SE_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_se_lock_release(void);
/***************************************************************************//**
* @brief
* Execute and wait for mailbox command to complete.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_SE_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx);
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
// Key handling helper functions
sl_status_t sli_key_get_storage_size(const sl_se_key_descriptor_t* key,
uint32_t *storage_size);
sl_status_t sli_key_get_size(const sl_se_key_descriptor_t* key, uint32_t* size);
sl_status_t sli_key_check_equivalent(const sl_se_key_descriptor_t* key_1,
const sl_se_key_descriptor_t* key_2,
bool check_key_flag,
bool public_export);
sl_status_t sli_se_key_to_keyspec(const sl_se_key_descriptor_t* key,
uint32_t* keyspec);
sl_status_t sli_se_keyspec_to_key(const uint32_t keyspec,
sl_se_key_descriptor_t* key);
sl_status_t sli_se_get_auth_buffer(const sl_se_key_descriptor_t* key,
sli_se_datatransfer_t* auth_buffer);
sl_status_t sli_se_get_key_input_output(const sl_se_key_descriptor_t* key,
sli_se_datatransfer_t* buffer);
#endif // SLI_MAILBOX_COMMAND_SUPPORTED
#ifdef __cplusplus
}
#endif
#endif /* defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED) */
#endif /* SE_MANAGER_INTERNAL_H */

View File

@@ -0,0 +1,731 @@
/***************************************************************************//**
* @file
* @brief SE Mailbox API
*******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#ifndef SLI_SE_MANAGER_MAILBOX_H
#define SLI_SE_MANAGER_MAILBOX_H
#if defined(__linux__)
#define SLI_SE_MAILBOX_HOST_SYSTEM
#else
#include "em_device.h"
#endif // __linux__
#include "sl_common.h"
#if defined(SLI_SE_MAILBOX_HOST_SYSTEM) || defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*******************************************************************************
****************************** DEFINES ***********************************
******************************************************************************/
// -----------------------------------------------------------------------------
// SE status codes
/// Response status codes for the Secure Engine
#define SLI_SE_RESPONSE_MASK 0x000F0000UL
/// Command executed successfully or signature was successfully validated.
#define SLI_SE_RESPONSE_OK 0x00000000UL
/// Command was not recognized as a valid command, or is not allowed in the
/// current context.
#define SLI_SE_RESPONSE_INVALID_COMMAND 0x00010000UL
/// User did not provide the required credentials to be allowed to execute the
/// command.
#define SLI_SE_RESPONSE_AUTHORIZATION_ERROR 0x00020000UL
/// Signature validation command (e.g. SE_COMMAND_SIGNATURE_VERIFY) failed to
/// verify the given signature as being correct.
#define SLI_SE_RESPONSE_INVALID_SIGNATURE 0x00030000UL
/// A command started in non-secure mode is trying to access secure memory.
#define SLI_SE_RESPONSE_BUS_ERROR 0x00040000UL
/// Internal error
#define SLI_SE_RESPONSE_INTERNAL_ERROR 0x00050000UL
/// An internal error was raised and the command did not execute.
#define SLI_SE_RESPONSE_CRYPTO_ERROR 0x00060000UL
/// One of the passed parameters is deemed invalid (e.g. out of bounds).
#define SLI_SE_RESPONSE_INVALID_PARAMETER 0x00070000UL
/// Failure while checking the host for secure boot
#define SLI_SE_RESPONSE_SECUREBOOT_ERROR 0x00090000UL
/// Failure during selftest
#define SLI_SE_RESPONSE_SELFTEST_ERROR 0x000A0000UL
/// Feature/item not initialized or not present
#define SLI_SE_RESPONSE_NOT_INITIALIZED 0x000B0000UL
/// Abort status code is given when no operation is attempted.
#define SLI_SE_RESPONSE_ABORT 0x00FF0000UL
#if defined(CRYPTOACC_PRESENT)
/// Root Code Mailbox is invalid.
#define SLI_SE_RESPONSE_MAILBOX_INVALID 0x00FE0000UL
/// Root Code Mailbox is valid
#define SLI_SE_RESPONSE_MAILBOX_VALID 0xE5ECC0DEUL
#endif // CRYPTOACC_PRESENT
// -----------------------------------------------------------------------------
// SE command words
// Commands are grouped based on availability
#define SLI_SE_COMMAND_CHECK_SE_IMAGE 0x43020000UL
#define SLI_SE_COMMAND_APPLY_SE_IMAGE 0x43030000UL
#define SLI_SE_COMMAND_STATUS_SE_IMAGE 0x43040000UL
#define SLI_SE_COMMAND_CHECK_HOST_IMAGE 0x43050001UL
#define SLI_SE_COMMAND_APPLY_HOST_IMAGE 0x43060001UL
#define SLI_SE_COMMAND_STATUS_HOST_IMAGE 0x43070000UL
#define SLI_SE_COMMAND_READ_OTP 0xFE040000UL
#define SLI_SE_COMMAND_INIT_OTP 0xFF000001UL
#define SLI_SE_COMMAND_INIT_PUBKEY 0xFF070001UL
#define SLI_SE_COMMAND_READ_PUBKEY 0xFF080001UL
#define SLI_SE_COMMAND_READ_PUBKEY 0xFF080001UL
#define SLI_SE_COMMAND_READ_OTP 0xFE040000UL
#define SLI_SE_COMMAND_DBG_LOCK_APPLY 0x430C0000UL
// Commands limited to SE devices
#if defined(SEMAILBOX_PRESENT)
#define SLI_SE_COMMAND_CREATE_KEY 0x02000000UL
#define SLI_SE_COMMAND_READPUB_KEY 0x02010000UL
#define SLI_SE_COMMAND_HASH 0x03000000UL
#define SLI_SE_COMMAND_HASHUPDATE 0x03010000UL
#define SLI_SE_COMMAND_HMAC 0x03020000UL
#if defined(_SILICON_LABS_32B_SERIES_3)
#define SLI_SE_COMMAND_HMAC_STREAMING_START 0x03040000UL
#define SLI_SE_COMMAND_HMAC_STREAMING_UPDATE 0x03050000UL
#define SLI_SE_COMMAND_HMAC_STREAMING_FINISH 0x03060000UL
#endif // _SILICON_LABS_32B_SERIES_3
#define SLI_SE_COMMAND_HASHFINISH 0x03030000UL
#define SLI_SE_COMMAND_AES_ENCRYPT 0x04000000UL
#define SLI_SE_COMMAND_AES_DECRYPT 0x04010000UL
#define SLI_SE_COMMAND_AES_GCM_ENCRYPT 0x04020000UL
#define SLI_SE_COMMAND_AES_GCM_DECRYPT 0x04030000UL
#define SLI_SE_COMMAND_AES_CMAC 0x04040000UL
#define SLI_SE_COMMAND_AES_CCM_ENCRYPT 0x04050000UL
#define SLI_SE_COMMAND_AES_CCM_DECRYPT 0x04060000UL
#define SLI_SE_COMMAND_SIGNATURE_SIGN 0x06000000UL
#define SLI_SE_COMMAND_SIGNATURE_VERIFY 0x06010000UL
#define SLI_SE_COMMAND_EDDSA_SIGN 0x06020000UL
#define SLI_SE_COMMAND_EDDSA_VERIFY 0x06030000UL
#define SLI_SE_COMMAND_TRNG_GET_RANDOM 0x07000000UL
#define SLI_SE_COMMAND_JPAKE_R1_GENERATE 0x0B000000UL
#define SLI_SE_COMMAND_JPAKE_R1_VERIFY 0x0B000100UL
#define SLI_SE_COMMAND_JPAKE_R2_GENERATE 0x0B010000UL
#define SLI_SE_COMMAND_JPAKE_R2_VERIFY 0x0B010100UL
#define SLI_SE_COMMAND_JPAKE_GEN_SESSIONKEY 0x0B020000UL
#define SLI_SE_COMMAND_DH 0x0E000000UL
#define SLI_SE_COMMAND_STATUS_SE_VERSION 0x43080000UL
#define SLI_SE_COMMAND_STATUS_OTP_VERSION 0x43080100UL
#define SLI_SE_COMMAND_WRITE_USER_DATA 0x43090000UL
#define SLI_SE_COMMAND_ERASE_USER_DATA 0x430A0000UL
#define SLI_SE_COMMAND_DBG_LOCK_ENABLE_SECURE 0x430D0000UL
#define SLI_SE_COMMAND_DBG_LOCK_DISABLE_SECURE 0x430E0000UL
#define SLI_SE_COMMAND_DEVICE_ERASE 0x430F0000UL
#define SLI_SE_COMMAND_DEVICE_ERASE_DISABLE 0x43100000UL
#define SLI_SE_COMMAND_DBG_LOCK_STATUS 0x43110000UL
#define SLI_SE_COMMAND_DBG_SET_RESTRICTIONS 0x43120000UL
#define SLI_SE_COMMAND_PROTECTED_REGISTER 0x43210000UL
#if defined(_SILICON_LABS_32B_SERIES_3)
#define SLI_SE_COMMAND_READ_DEVICE_DATA 0x43300000UL
#define SLI_SE_COMMAND_GET_ROLLBACK_COUNTER 0x43400000UL
#endif
#if defined(SLI_SE_COMMAND_STATUS_READ_RSTCAUSE_AVAILABLE)
// SLI_SE_COMMAND_STATUS_READ_RSTCAUSE is only available on xG21 devices (series-2-config-1)
#define SLI_SE_COMMAND_STATUS_READ_RSTCAUSE 0x43220000UL
#endif // SLI_SE_COMMAND_STATUS_READ_RSTCAUSE_AVAILABLE
#define SLI_SE_COMMAND_READ_USER_CERT_SIZE 0x43FA0000UL
#define SLI_SE_COMMAND_READ_USER_CERT 0x43FB0000UL
#if defined(_SILICON_LABS_32B_SERIES_3)
#define SLI_SE_COMMAND_GET_HOST_UPGRADE_FILE_VERSION 0x44000000UL
#define SLI_SE_COMMAND_SET_HOST_UPGRADE_FILE_VERSION 0x44010000UL
#endif // _SILICON_LABS_32B_SERIES_3
#define SLI_SE_COMMAND_ENTER_ACTIVE_MODE 0x45000000UL
#define SLI_SE_COMMAND_EXIT_ACTIVE_MODE 0x45010000UL
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#define SLI_SE_COMMAND_ATTEST_PSA_IAT 0x0A030000UL
#define SLI_SE_COMMAND_ATTEST_CONFIG 0x0A040000UL
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT)
#define SLI_SE_COMMAND_GET_CHALLENGE 0xFD000001UL
#define SLI_SE_COMMAND_ROLL_CHALLENGE 0xFD000101UL
#define SLI_SE_COMMAND_OPEN_DEBUG 0xFD010001UL
#define SLI_SE_COMMAND_READ_SERIAL 0xFE000000UL
#define SLI_SE_COMMAND_GET_STATUS 0xFE010000UL
#define SLI_SE_COMMAND_READ_PUBKEYBOOT 0xFE020001UL
#define SLI_SE_COMMAND_SET_UPGRADEFLAG_SE 0xFE030000UL
#define SLI_SE_COMMAND_SET_UPGRADEFLAG_HOST 0xFE030001UL
#define SLI_SE_COMMAND_READ_TAMPER_RESET_CAUSE 0xFE050000UL
#if defined(_SILICON_LABS_32B_SERIES_3)
#define SLI_SE_COMMAND_READ_TRACE_FLAGS 0xFE060000UL
#endif
#define SLI_SE_COMMAND_INIT_PUBKEY_SIGNATURE 0xFF090001UL
#define SLI_SE_COMMAND_READ_PUBKEY_SIGNATURE 0xFF0A0001UL
#define SLI_SE_COMMAND_INIT_AES_128_KEY 0xFF0B0001UL
#if defined(_SILICON_LABS_32B_SERIES_3)
#define SLI_SE_COMMAND_CONFIGURE_QSPI_REF_CLOCK 0xFF150000UL
#define SLI_SE_COMMAND_CONFIGURE_QSPI_REGS 0xFF160000UL
#define SLI_SE_COMMAND_GET_QSPI_FLPLL_CONFIG 0xFF170000UL
#define SLI_SE_COMMAND_APPLY_CODE_REGION_CONFIG 0xFF500000UL
#define SLI_SE_COMMAND_CLOSE_CODE_REGION 0xFF510000UL
#define SLI_SE_COMMAND_ERASE_CODE_REGION 0xFF520000UL
#define SLI_SE_COMMAND_GET_CODE_REGION_CONFIG 0xFF530000UL
#define SLI_SE_COMMAND_GET_CODE_REGION_VERSION 0xFF540000UL
#define SLI_SE_COMMAND_SET_ACTIVE_BANKED_CODE_REGION 0xFF550000UL
#define SLI_SE_COMMAND_WRITE_CODE_REGION 0xFF560000UL
#define SLI_SE_COMMAND_ERASE_DATA_REGION 0xFF620000UL
#define SLI_SE_COMMAND_WRITE_DATA_REGION 0xFF630000UL
#define SLI_SE_COMMAND_GET_DATA_REGION_LOCATION 0xFF640000UL
#endif
#endif // SLI_MAILBOX_COMMAND_SUPPORTED
// Commands limited to SE Vault High devices
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#define SLI_SE_COMMAND_WRAP_KEY 0x01000000UL
#define SLI_SE_COMMAND_UNWRAP_KEY 0x01020000UL
#define SLI_SE_COMMAND_DELETE_KEY 0x01050000UL
#define SLI_SE_COMMAND_TRANSFER_KEY 0x01060000UL
#define SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_HMAC 0x02020002UL
#define SLI_SE_COMMAND_DERIVE_KEY_HKDF 0x02020003UL
#define SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_CMAC 0x02020010UL
#define SLI_SE_COMMAND_CHACHAPOLY_ENCRYPT 0x0C000000UL
#define SLI_SE_COMMAND_CHACHAPOLY_DECRYPT 0x0C010000UL
#define SLI_SE_COMMAND_CHACHA20_ENCRYPT 0x0C020000UL
#define SLI_SE_COMMAND_CHACHA20_DECRYPT 0x0C030000UL
#define SLI_SE_COMMAND_POLY1305_KEY_MAC 0x0C040000UL
#define SLI_SE_COMMAND_DISABLE_TAMPER 0xFD020001UL
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
// -----------------------------------------------------------------------------
// SE command options
// Commands are grouped based on availability
/// Secure boot pubkey
#define SLI_SE_KEY_TYPE_BOOT 0x00000100UL
/// Secure authorization (debug) pubkey
#define SLI_SE_KEY_TYPE_AUTH 0x00000200UL
// Options limited to SE devices
#if defined(SEMAILBOX_PRESENT)
/// Root pubkey
#define SLI_SE_KEY_TYPE_ROOT 0x00000300UL
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// Attestation pubkey
#define SLI_SE_KEY_TYPE_ATTEST 0x00000400UL
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
/// BGL encryption key
#define SLI_SE_IMMUTABLE_KEY_TYPE_AES_128 0x00000500UL
/// Use MD5 as hash algorithm
#define SLI_SE_COMMAND_OPTION_HASH_MD5 0x00000100UL
/// Use SHA1 as hash algorithm
#define SLI_SE_COMMAND_OPTION_HASH_SHA1 0x00000200UL
/// Use SHA224 as hash algorithm
#define SLI_SE_COMMAND_OPTION_HASH_SHA224 0x00000300UL
/// Use SHA256 as hash algorithm
#define SLI_SE_COMMAND_OPTION_HASH_SHA256 0x00000400UL
#if defined(_SILICON_LABS_32B_SERIES_3)
/// Use SHA1 as hash algorithm for HMAC streaming operation
#define SLI_SE_COMMAND_OPTION_HMAC_HASH_SHA1 0x00000700UL
/// Use SHA224 as hash algorithm for HMAC streaming operation
#define SLI_SE_COMMAND_OPTION_HMAC_HASH_SHA224 0x00000800UL
/// Use SHA256 as hash algorithm for HMAC streaming operation
#define SLI_SE_COMMAND_OPTION_HMAC_HASH_SHA256 0x00000900UL
#endif // _SILICON_LABS_32B_SERIES_3
/// Execute algorithm in ECB mode
#define SLI_SE_COMMAND_OPTION_MODE_ECB 0x00000100UL
/// Execute algorithm in CBC mode
#define SLI_SE_COMMAND_OPTION_MODE_CBC 0x00000200UL
/// Execute algorithm in CTR mode
#define SLI_SE_COMMAND_OPTION_MODE_CTR 0x00000300UL
/// Execute algorithm in CFB mode
#define SLI_SE_COMMAND_OPTION_MODE_CFB 0x00000400UL
/// Run the whole algorithm, all data present
#define SLI_SE_COMMAND_OPTION_CONTEXT_WHOLE 0x00000000UL
/// Start the algorithm, but get a context to later add more data
#define SLI_SE_COMMAND_OPTION_CONTEXT_START 0x00000001UL
/// End the algorithm, get the result
#define SLI_SE_COMMAND_OPTION_CONTEXT_END 0x00000002UL
/// Add more data input to the algorithm. Need to supply previous context,
/// and get a context back
#define SLI_SE_COMMAND_OPTION_CONTEXT_ADD 0x00000003UL
/// User data command options
/// Magic paramater for deleting user data
#define SLI_SE_COMMAND_OPTION_ERASE_UD 0xDE1E7EADUL
#define SLI_SE_COMMAND_OPTION_WRITE 0x00000100UL
#define SLI_SE_COMMAND_OPTION_READ 0x00000000UL
#define SLI_SE_COMMAND_CERT_BATCH 0x00000100UL
#define SLI_SE_COMMAND_CERT_SE 0x00000200UL
#define SLI_SE_COMMAND_CERT_HOST 0x00000300UL
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/// Use SHA384 as hash algorithm
#define SLI_SE_COMMAND_OPTION_HASH_SHA384 0x00000500UL
/// Use SHA512 as hash algorithm
#define SLI_SE_COMMAND_OPTION_HASH_SHA512 0x00000600UL
#if defined(_SILICON_LABS_32B_SERIES_3)
/// Use SHA384 as hash algorithm for HMAC streaming operation
#define SLI_SE_COMMAND_OPTION_HMAC_HASH_SHA384 0x00000A00UL
/// Use SHA512 as hash algorithm for HMAC streaming operation
#define SLI_SE_COMMAND_OPTION_HMAC_HASH_SHA512 0x00000B00UL
#endif // _SILICON_LABS_32B_SERIES_3
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
#endif // SLI_MAILBOX_COMMAND_SUPPORTED
// -----------------------------------------------------------------------------
// Other defines
/** Maximum amount of parameters supported by the hardware FIFO */
#define SE_FIFO_MAX_PARAMETERS 13U
/** Stop datatransfer */
#define SLI_SE_DATATRANSFER_STOP 0x00000001UL
/** Discard datatransfer */
#define SLI_SE_DATATRANSFER_DISCARD 0x40000000UL
/** Realign datatransfer */
#define SLI_SE_DATATRANSFER_REALIGN 0x20000000UL
/** Datatransfer Const Address*/
#define SLI_SE_DATATRANSFER_CONSTADDRESS 0x10000000UL
/** Stop Length Mask */
#define SLI_SE_DATATRANSFER_LENGTH_MASK 0x0FFFFFFFUL
/** Maximum amount of parameters for largest command in defined command set */
#ifndef SLI_SE_COMMAND_MAX_PARAMETERS
#define SLI_SE_COMMAND_MAX_PARAMETERS 4U
#endif
/* Sanity-check defines */
#if SLI_SE_COMMAND_MAX_PARAMETERS > SE_FIFO_MAX_PARAMETERS
#error "Trying to configure more parameters than supported by the hardware"
#endif
/*******************************************************************************
****************************** TYPEDEFS ***********************************
******************************************************************************/
/***************************************************************************//**
* @brief SE DMA transfer descriptor.
* Can be linked to each other to provide scatter-gather behavior.
******************************************************************************/
typedef struct {
volatile void* volatile data; /**< Data pointer */
void* volatile next; /**< Next descriptor */
volatile uint32_t length; /**< Length */
} sli_se_datatransfer_t;
/** Default initialization of data transfer struct */
#define SLI_SE_DATATRANSFER_DEFAULT(address, data_size) \
{ \
.data = (void*)(address), /* Pointer to data block */ \
.next = (void*)SLI_SE_DATATRANSFER_STOP, /* This is the last block by default */ \
.length = (data_size) | SLI_SE_DATATRANSFER_REALIGN /* Add size, use realign by default */ \
}
/***************************************************************************//**
* @brief SE mailbox command structure
*
* @details
* This structure defines the command structure used by the SE mailbox
******************************************************************************/
typedef struct {
uint32_t command; /**< SE Command */
sli_se_datatransfer_t* data_in; /**< Input data */
sli_se_datatransfer_t* data_out; /**< Output data */
uint32_t parameters[SLI_SE_COMMAND_MAX_PARAMETERS]; /**< Parameters */
size_t num_parameters; /**< Number of parameters */
} sli_se_mailbox_command_t;
/** Default initialization of command struct */
#define SLI_SE_MAILBOX_COMMAND_DEFAULT(command_word) \
{ \
.command = command_word, /* Given command word */ \
.data_in = NULL, /* No data in */ \
.data_out = NULL, /* No data out */ \
.parameters = { 0, 0, 0, 0 }, /* No parameters */ \
.num_parameters = 0 /* No parameters */ \
}
/** Possible responses to a command */
typedef uint32_t sli_se_mailbox_response_t;
/*******************************************************************************
***************************** PROTOTYPES **********************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Add input data to a mailbox command
*
* @details
* This function adds a buffer of input data to the given SE command structure
* The buffer gets appended by reference at the end of the list of already
* added buffers.
*
* @note
* Note that this function does not copy either the data buffer or the buffer
* structure, so make sure to keep the data object in scope until the command
* has been executed by the secure element.
*
* @param[in] command
* Pointer to an SE Mailbox command structure.
*
* @param[in] data
* Pointer to a data transfer structure.
******************************************************************************/
void sli_se_mailbox_command_add_input(sli_se_mailbox_command_t *command, sli_se_datatransfer_t *data);
/***************************************************************************//**
* @brief
* Add output data to a mailbox command
*
* @details
* This function adds a buffer of output data to the given command structure
* The buffer gets appended by reference at the end of the list of already
* added buffers.
*
* @note
* Note that this function does not copy either the data buffer or the buffer
* structure, so make sure to keep the data object in scope until the command
* has been executed by the secure element.
*
* @param[in] command
* Pointer to an SE mailbox command structure.
*
* @param[in] data
* Pointer to a data transfer structure.
******************************************************************************/
void sli_se_mailbox_command_add_output(sli_se_mailbox_command_t *command, sli_se_datatransfer_t *data);
/***************************************************************************//**
* @brief
* Add a parameter to a mailbox command
*
* @details
* This function adds a parameter word to the passed command.
*
* @note
* Make sure to not exceed @ref SE_MAX_PARAMETERS.
*
* @param[in] command
* Pointer to a filled-out SE command structure.
* @param[in] parameter
* Parameter to add.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_SE_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
void sli_se_mailbox_command_add_parameter(sli_se_mailbox_command_t *command, uint32_t parameter);
#if !defined(SLI_SE_MAILBOX_HOST_SYSTEM)
/***************************************************************************//**
* @brief
* Execute the passed command
*
* @details
* This function starts the execution of the passed command by the secure
* element. The RXINT interrupt flag will be set upon completion. Call
* @ref sli_se_mailbox_read_response to wait for completion and retrieve the
* command's execution status.
*
* @param[in] command
* Pointer to a filled-out SE command structure.
******************************************************************************/
SL_CODE_CLASSIFY(SL_CODE_COMPONENT_SE_MANAGER, SL_CODE_CLASS_TIME_CRITICAL)
void sli_se_mailbox_execute_command(sli_se_mailbox_command_t *command);
#endif //!defined(SLI_SE_MAILBOX_HOST_SYSTEM)
#if defined(SEMAILBOX_PRESENT)
/***************************************************************************//**
* @brief
* Read the status of the previously executed command.
*
* @details
* This function waits for any running command to complete before reading the
* status of the previously executed command.
*
* @note
* The command response needs to be read for every executed command, and can
* only be read once per executed command (FIFO behavior).
*
* @return
* One of the SE_RESPONSE return codes:
* SE_RESPONSE_OK when the command was executed successfully or a signature
* was successfully verified.
******************************************************************************/
__STATIC_INLINE sli_se_mailbox_response_t sli_se_mailbox_read_response(void)
{
while (!(SEMAILBOX_HOST->RX_STATUS & SEMAILBOX_RX_STATUS_RXINT)) {
// Wait for command completion by polling SE Mailbox RX interrupt flag
}
// Return command response
return (sli_se_mailbox_response_t)(SEMAILBOX_HOST->RX_HEADER & SLI_SE_RESPONSE_MASK);
}
/**
* \brief Handle the response of the previously executed command.
*
* \details This function handles the response of the previously
* executed HSE command by calling sli_se_mailbox_read_response
* to read the response value and returns it. For Series-3 this
* function also clears the SEMAILBOX FIFO by reading out the
* unused command handle word.
* This function is called by the ISR of the SEMAILBOX (called
* SEMBRX_IRQHandler ) to clear the SEMBRX_IRQn interrupt signal
* on the SEMAILBOX peripheral side. NOTE: The ISR will also
* need to clear the SEMBRX_IRQn condition in the internal/local
* interrupt controller (NVIC) by calling
* NVIC_ClearPendingIRQ(SEMBRX_IRQn).
*
* \return Value returned by sli_se_mailbox_read_response.
******************************************************************************/
__STATIC_INLINE sli_se_mailbox_response_t sli_se_mailbox_handle_response(void)
{
// Read command response
sli_se_mailbox_response_t se_mailbox_response = sli_se_mailbox_read_response();
#if defined(_SILICON_LABS_32B_SERIES_3)
// Read the command handle word ( not used ) from the SEMAILBOX FIFO
SEMAILBOX_HOST->FIFO;
#endif
// Return command response
return se_mailbox_response;
}
#elif defined(CRYPTOACC_PRESENT)
sli_se_mailbox_response_t sli_se_mailbox_read_response(void);
/**
* \brief Handle the response of the previously executed command.
*
* \details This function handles the response of the previously
* executed VSE command by calling sli_se_mailbox_read_response
* to read the response value and returns it.
*
* \return Value returned by sli_se_mailbox_read_response.
******************************************************************************/
__STATIC_INLINE sli_se_mailbox_response_t sli_se_mailbox_handle_response(void)
{
// Read and return VSE mailbox command response
return sli_se_mailbox_read_response();
}
#endif // #if defined(SEMAILBOX_PRESENT)
/***************************************************************************//**
* @brief
* Disable one or more SE interrupts.
*
* @param[in] flags
* SE interrupt sources to disable. Use a bitwise logic OR combination of
* valid interrupt flags for the Secure Element module
* (SE_CONFIGURATION_(TX/RX)INTEN).
******************************************************************************/
__STATIC_INLINE void sli_se_mailbox_disable_interrupt(uint32_t flags)
{
#if defined(SEMAILBOX_PRESENT)
SEMAILBOX_HOST->CONFIGURATION &= ~flags;
#else
(void) flags;
#endif
}
/***************************************************************************//**
* @brief
* Enable one or more SE interrupts.
*
* @param[in] flags
* SE interrupt sources to enable. Use a bitwise logic OR combination of
* valid interrupt flags for the Secure Element module
* (SEMAILBOX_CONFIGURATION_TXINTEN or SEMAILBOX_CONFIGURATION_RXINTEN).
******************************************************************************/
__STATIC_INLINE void sli_se_mailbox_enable_interrupt(uint32_t flags)
{
#if defined(SEMAILBOX_PRESENT)
SEMAILBOX_HOST->CONFIGURATION |= flags;
#else
(void) flags;
#endif
}
#if defined(CRYPTOACC_PRESENT)
/***************************************************************************//**
* @brief
* Get current SE version
*
* @details
* This function returns the current VSE version
*
* @param[in] version
* Pointer to location where to copy the version of VSE to.
*
* @return
* One of the SE_RESPONSE return codes:
* SLI_SE_RESPONSE_OK when the command was executed successfully
* SLI_SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
* SLI_SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_get_version(uint32_t *version);
/***************************************************************************//**
* @brief
* Get VSE configuration and status bits
*
* @details
* This function returns the current VSE configuration and status bits.
* The following list explains what the different bits in cfg_status indicate.
* A bit value of 1 means enabled, while 0 means disabled:
* * [0]: Secure boot
* * [1]: Verify secure boot certificate
* * [2]: Anti-rollback
* * [3]: Narrow page lock
* * [4]: Full page lock
* The following status bits can be read with VSE versions
* higher than 1.2.2.
* * [10]: Debug port lock
* * [11]: Device erase enabled
* * [12]: Secure debug enabled
* * [15]: Debug port register state, 1 if the debug port is locked.
*
* @param[out] cfg_status
* Pointer to location to copy Configuration Status bits into.
*
* @note
* This function will check that the mailbox content is valid before
* reading the status bits. If the command response has already been read
* with a call to @ref sli_vse_mailbox_ack_command(), the validity check will fail, and
* the config status bits cannot be read before a reset has occurred.
*
* @return
* One of the SE_RESPONSE return codes:
* SLI_SE_RESPONSE_OK when the command was executed successfully
* SLI_SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
* SLI_SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_get_cfg_status(uint32_t *cfg_status);
/***************************************************************************//**
* @brief
* Get the version number of the OTP from the status field of the output
* mailbox
* @details
* This function checks if the OTP version number flag is set in the output
* mailbox. If it is, the version number is writen to @ref otp_version pointer
* location. If not, it returns error response.
*
* @param[out] otp_version
* Pointer to location to copy OTP version number into.
* @return
* One of the SE_RESPONSE return codes.
* @retval SLI_SE_RESPONSE_OK when the command was executed successfully
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_get_otp_version(uint32_t *otp_version);
/***************************************************************************//**
* @brief
* Acknowledge and get status and output data of a completed command.
*
* @details
* This function acknowledges and gets the status and output data of a
* completed mailbox command.
* The mailbox command is acknowledged by inverting all bits in the checksum
* (XOR with 0xFFFFFFFF).
* The output data is copied into the linked list of output buffers pointed
* to in the given command data structure.
*
* @param[in] command
* Pointer to an SE command structure.
*
* @return
* One of the SE_RESPONSE return codes.
* @retval SLI_SE_RESPONSE_OK when the command was executed successfully or a
* signature was successfully verified,
* @retval SLI_SE_RESPONSE_INVALID_COMMAND when the command ID was not recognized,
* @retval SE_RESPONSE_AUTHORIZATION_ERROR when the command is not authorized,
* @retval SE_RESPONSE_INVALID_SIGNATURE when signature verification failed,
* @retval SE_RESPONSE_BUS_ERROR when a bus error was thrown during the command,
* e.g. because of conflicting Secure/Non-Secure
* memory accesses,
* @retval SE_RESPONSE_CRYPTO_ERROR on an internal SE failure, or
* @retval SLI_SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
* @retval SLI_SE_RESPONSE_MAILBOX_INVALID when mailbox command not done or invalid
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_ack_command(sli_se_mailbox_command_t *command);
/***************************************************************************//**
* @brief
* Read the previously executed command.
*
* @details
* This function reads the previously executed command.
*
* @return
* One of the SE command words.
* SLI_SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid.
******************************************************************************/
uint32_t sli_vse_mailbox_read_executed_command(void);
/***************************************************************************//**
* @brief
* Check whether the VSE Output Mailbox is valid.
*
* @return True if the VSE Output Mailbox is valid (magic and checksum OK)
******************************************************************************/
bool sli_vse_mailbox_is_output_valid(void);
#endif // #if defined(CRYPTOACC_PRESENT)
#ifdef __cplusplus
}
#endif
#endif // #if defined(SLI_SE_MAILBOX_HOST_SYSTEM) || defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
#endif /* SLI_SE_MANAGER_MAILBOX_H */

View File

@@ -0,0 +1,560 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_se_manager.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
#if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
#include "sli_se_manager_internal.h"
#include "sli_se_manager_mailbox.h"
#include "sl_assert.h"
#if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
#if defined(_SILICON_LABS_32B_SERIES_3)
#include "sl_hal_bus.h"
#else
#include "em_bus.h"
#endif
#endif
#if !defined(SLI_SE_MANAGER_HOST_SYSTEM)
#include "sli_psec_osal.h"
#endif
#include <string.h>
/// @addtogroup sl_se_managers
/// @{
// -----------------------------------------------------------------------------
// Locals
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
#if defined(SL_SE_MANAGER_THREADING)
/// Priority to use for SEMBRX IRQ
#if defined(SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY)
#if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY >= (1U << __NVIC_PRIO_BITS) )
#error Illegal SEMBRX priority level.
#endif
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
#if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY < (configMAX_SYSCALL_INTERRUPT_PRIORITY >> (8U - __NVIC_PRIO_BITS) ) )
#error Illegal SEMBRX priority level.
#endif
#else
#if (SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY < CORE_ATOMIC_BASE_PRIORITY_LEVEL)
#error Illegal SEMBRX priority level.
#endif
#endif
#define SE_MANAGER_SEMBRX_IRQ_PRIORITY SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY
#else
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
#define SE_MANAGER_SEMBRX_IRQ_PRIORITY (configMAX_SYSCALL_INTERRUPT_PRIORITY >> (8U - __NVIC_PRIO_BITS) )
#else
#define SE_MANAGER_SEMBRX_IRQ_PRIORITY (CORE_ATOMIC_BASE_PRIORITY_LEVEL)
#endif
#endif
#else // defined(SL_SE_MANAGER_THREADING)
/// Priority to use for SEMBRX IRQ
#if defined(SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY)
#define SE_MANAGER_SEMBRX_IRQ_PRIORITY SE_MANAGER_USER_SEMBRX_IRQ_PRIORITY
#else
#define SE_MANAGER_SEMBRX_IRQ_PRIORITY (0)
#endif
#endif // defined(SL_SE_MANAGER_THREADING)
#endif // defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
#if defined(SL_SE_MANAGER_THREADING) \
|| defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
// Flag to indicate that the SE Manager is initialized or not.
static volatile bool se_manager_initialized = false;
#if defined(SL_SE_MANAGER_THREADING)
// Lock mutex for synchronizing multiple threads calling into the
// SE Manager API.
static sli_psec_osal_lock_t se_lock = { 0 };
#endif // SL_SE_MANAGER_THREADING
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
// SE command completion.
static sli_psec_osal_completion_t se_command_completion;
// SE mailbox command response code. This value is read from the SEMAILBOX
// in ISR in order to clear the command complete interrupt condition.
static sli_se_mailbox_response_t se_manager_command_response = SLI_SE_RESPONSE_INTERNAL_ERROR;
#endif // SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
#endif // #if defined (SL_SE_MANAGER_THREADING)
// || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
// -----------------------------------------------------------------------------
// Global functions
/***************************************************************************//**
* Initialize the SE Manager.
******************************************************************************/
sl_status_t sl_se_init(void)
{
sl_status_t ret = SL_STATUS_OK;
#if defined (SL_SE_MANAGER_THREADING) \
|| defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
(void)se_manager_command_response;
#endif
#if defined(SL_SE_MANAGER_THREADING)
SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_START
#endif
if ( !se_manager_initialized ) {
#if defined(SL_SE_MANAGER_THREADING)
// Initialize SE lock
ret = sli_psec_osal_init_lock(&se_lock);
#endif
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
if (ret == SL_STATUS_OK) {
// Initialize command completion object.
ret = sli_psec_osal_init_completion(&se_command_completion);
if (ret == SL_STATUS_OK) {
// Enable SE RX mailbox interrupt in NVIC, but not in SEMAILBOX
// which will be enabled if the yield parameter in
// sli_se_execute_and_wait is true.
NVIC_SetPriority(SEMBRX_IRQn, SE_MANAGER_SEMBRX_IRQ_PRIORITY);
NVIC_EnableIRQ(SEMBRX_IRQn);
}
}
#endif // SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
if (ret == SL_STATUS_OK) {
se_manager_initialized = true;
}
}
#if defined(SL_SE_MANAGER_THREADING)
SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_END
#endif
#endif // #if defined (SL_SE_MANAGER_THREADING)
// || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
return ret;
}
/***************************************************************************//**
* Denitialize the SE Manager.
******************************************************************************/
sl_status_t sl_se_deinit(void)
{
sl_status_t ret = SL_STATUS_OK;
#if defined (SL_SE_MANAGER_THREADING) \
|| defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
#if defined(SL_SE_MANAGER_THREADING)
SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_START
#endif
if ( se_manager_initialized ) {
// We need to exit the critical section in case the SE lock is held by a
// thread, and we want to take it before de-initializing.
#if defined(SL_SE_MANAGER_THREADING)
SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_END
#endif
// Acquire the SE lock to make sure no thread is executing SE commands
// when we de-initialize.
ret = sli_se_lock_acquire();
if (ret != SL_STATUS_OK) {
return ret;
}
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
// Disable SE RX mailbox interrupt in NVIC.
NVIC_ClearPendingIRQ(SEMBRX_IRQn);
NVIC_DisableIRQ(SEMBRX_IRQn);
// Free command completion object.
ret = sli_psec_osal_free_completion(&se_command_completion);
#endif // SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION
#if defined(SL_SE_MANAGER_THREADING)
if (ret == SL_STATUS_OK) {
// Free the SE lock mutex
ret = sli_psec_osal_free_lock(&se_lock);
}
#endif
// Mark the SE Manager as un-initialized.
se_manager_initialized = false;
}
#if defined(SL_SE_MANAGER_THREADING)
else {
SLI_PSEC_OSAL_KERNEL_CRITICAL_SECTION_END
}
#endif
#endif // #if defined (SL_SE_MANAGER_THREADING)
// || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
return ret;
}
/***************************************************************************//**
* @brief
* Translate SE response codes to sl_status_t codes.
*
* @return
* Converted status code, their meaning is documented here @ref sl_status.h,
* Asserts and returns @c SL_STATUS_FAIL on unexpected response.
******************************************************************************/
sl_status_t sli_se_to_sl_status(sli_se_mailbox_response_t res)
{
switch (res) {
case SLI_SE_RESPONSE_OK:
return SL_STATUS_OK;
case SLI_SE_RESPONSE_INVALID_COMMAND:
return SL_STATUS_COMMAND_IS_INVALID;
case SLI_SE_RESPONSE_AUTHORIZATION_ERROR:
return SL_STATUS_INVALID_CREDENTIALS;
case SLI_SE_RESPONSE_INVALID_SIGNATURE:
return SL_STATUS_INVALID_SIGNATURE;
case SLI_SE_RESPONSE_BUS_ERROR:
return SL_STATUS_BUS_ERROR;
case SLI_SE_RESPONSE_INTERNAL_ERROR:
return SL_STATUS_FAIL;
case SLI_SE_RESPONSE_CRYPTO_ERROR:
return SL_STATUS_FAIL;
case SLI_SE_RESPONSE_INVALID_PARAMETER:
return SL_STATUS_INVALID_PARAMETER;
case SLI_SE_RESPONSE_ABORT:
return SL_STATUS_ABORT;
case SLI_SE_RESPONSE_SELFTEST_ERROR:
return SL_STATUS_INITIALIZATION;
case SLI_SE_RESPONSE_NOT_INITIALIZED:
return SL_STATUS_NOT_INITIALIZED;
#if defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)
case SLI_SE_RESPONSE_MAILBOX_INVALID:
return SL_STATUS_COMMAND_IS_INVALID;
#endif
default:
// Assert we do not get a bad SE response code.
EFM_ASSERT(false);
return SL_STATUS_FAIL;
}
}
/***************************************************************************//**
* Acquire the SE lock for exclusive access if necessary (thread mode).
* Enable the SEMAILBOX clock if necessary.
******************************************************************************/
sl_status_t sli_se_lock_acquire(void)
{
#if defined(SL_SE_MANAGER_THREADING)
sl_status_t status = sli_psec_osal_take_lock(&se_lock);
#else
sl_status_t status = SL_STATUS_OK;
#endif
#if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
if (status == SL_STATUS_OK) {
#if defined(_SILICON_LABS_32B_SERIES_3)
sl_hal_bus_reg_write_bit(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 1);
#else
BUS_RegBitWrite(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 1);
#endif
// Make sure the write to CMU->CLKEN1 is finished.
__DSB();
}
#endif
return status;
}
/***************************************************************************//**
* Release the SE lock if necessary (thread mode).
* Disable the SEMAILBOX clock if necessary.
******************************************************************************/
sl_status_t sli_se_lock_release(void)
{
#if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
#if defined(_SILICON_LABS_32B_SERIES_3)
sl_hal_bus_reg_write_bit(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 0);
#else
BUS_RegBitWrite(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 0);
#endif
#endif
#if defined(SL_SE_MANAGER_THREADING)
return sli_psec_osal_give_lock(&se_lock);
#else
return SL_STATUS_OK;
#endif
}
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
/***************************************************************************//**
* @brief
* SE Mailbox Interrupt Service Routine
******************************************************************************/
void SEMBRX_IRQHandler(void)
{
sl_status_t status;
// Check if the SE mailbox is the source of the interrupt.
if (SEMAILBOX_HOST->RX_STATUS & SEMAILBOX_RX_STATUS_RXINT) {
// Signal SE mailbox completion.
status = sli_psec_osal_complete(&se_command_completion);
EFM_ASSERT(status == SL_STATUS_OK);
}
// Get command response and clear interrupt condition in SEMAILBOX peripheral
se_manager_command_response = sli_se_mailbox_handle_response();
// Clear interrupt condition in NVIC
NVIC_ClearPendingIRQ(SEMBRX_IRQn);
}
#endif // #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
/***************************************************************************//**
* Set the yield attribute of the SE command context object.
******************************************************************************/
sl_status_t sl_se_set_yield(sl_se_command_context_t *cmd_ctx,
bool yield)
{
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
cmd_ctx->yield = yield;
return SL_STATUS_OK;
#else
if (yield) {
return SL_STATUS_NOT_AVAILABLE;
} else {
(void) cmd_ctx;
return SL_STATUS_OK;
}
#endif
}
/***************************************************************************//**
* @brief
* Execute and wait for SE mailbox command to complete.
*
* @return
* One of the following status code, any other status codes relates to internal
* function errors see @ref sl_status.h for their meaning.
* - @c SL_STATUS_OK
* - @c SL_STATUS_INVALID_PARAMETER
******************************************************************************/
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) && !defined(SLI_SE_MANAGER_HOST_SYSTEM)
sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx)
{
sl_status_t status = SL_STATUS_FAIL;
sli_se_mailbox_response_t command_response = SLI_SE_RESPONSE_INTERNAL_ERROR;
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Try to acquire SE lock
status = sli_se_lock_acquire();
if (status != SL_STATUS_OK) {
return status;
}
// Execute SE mailbox command
sli_se_mailbox_execute_command(&cmd_ctx->command);
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
if (cmd_ctx->yield) {
// Enable SEMAILBOX RXINT interrupt
sli_se_mailbox_enable_interrupt(SEMAILBOX_CONFIGURATION_RXINTEN);
// Yield and Wait for the command completion signal
status = sli_psec_osal_wait_completion(&se_command_completion,
SLI_PSEC_OSAL_WAIT_FOREVER);
// Disable SEMAILBOX RXINT interrupt.
sli_se_mailbox_disable_interrupt(SEMAILBOX_CONFIGURATION_RXINTEN);
if (status != SL_STATUS_OK) {
#if (_SILICON_LABS_32B_SERIES == 3)
// Read the command handle word ( not used ) from the SEMAILBOX FIFO
SEMAILBOX_HOST->FIFO;
#endif // #if (_SILICON_LABS_32B_SERIES == 3)
sli_se_lock_release();
return status;
}
// Get response which is read in the ISR to clear interrupt condition.
command_response = se_manager_command_response;
// Default to an error.
se_manager_command_response = SLI_SE_RESPONSE_INTERNAL_ERROR;
} else {
// Wait for command completion and get command response
command_response = sli_se_mailbox_handle_response();
}
#else // #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
// Wait for command completion and get command response
command_response = sli_se_mailbox_handle_response();
#endif // #if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
// Release SE lock
status = sli_se_lock_release();
// Return sl_status_t code.
if (command_response == SLI_SE_RESPONSE_OK) {
return status;
} else {
// Convert from sli_se_mailbox_response_t to sl_status_t code and return.
return sli_se_to_sl_status(command_response);
}
}
#elif defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED) // SLI_MAILBOX_COMMAND_SUPPORTED
sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx)
{
sl_status_t status;
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Try to acquire SE lock
status = sli_se_lock_acquire();
if (status != SL_STATUS_OK) {
return status;
}
// Execute SE mailbox command
sli_se_mailbox_execute_command(&cmd_ctx->command);
return SL_STATUS_FAIL; // Should never get to this point
}
/***************************************************************************//**
* From VSE mailbox read which command, if any, was executed.
******************************************************************************/
sl_status_t sl_se_read_executed_command(sl_se_command_context_t *cmd_ctx)
{
sl_status_t status;
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Try to acquire SE lock
status = sli_se_lock_acquire();
if (status != SL_STATUS_OK) {
return status;
}
// Read command
cmd_ctx->command.command = sli_vse_mailbox_read_executed_command();
// Release SE lock
status = sli_se_lock_release();
// Return sl_status_t code.
if (cmd_ctx->command.command == SLI_SE_RESPONSE_MAILBOX_INVALID) {
// Convert from sli_se_mailbox_response_t to sl_status_t code and return.
return sli_se_to_sl_status(SLI_SE_RESPONSE_MAILBOX_INVALID);
} else {
return status;
}
}
/***************************************************************************//**
* Acknowledge and get status and output data of a completed command.
******************************************************************************/
sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx)
{
sl_status_t status;
sl_status_t command_response;
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Try to acquire SE lock
status = sli_se_lock_acquire();
if (status != SL_STATUS_OK) {
return status;
}
// Acknowledge VSE mailbox command
command_response = sli_vse_mailbox_ack_command(&cmd_ctx->command);
// Release SE lock
status = sli_se_lock_release();
// Return sl_status_t code.
if (command_response == SLI_SE_RESPONSE_OK) {
return status;
} else {
// Convert from SE_Response_t to sl_status_t code and return.
return sli_se_to_sl_status(command_response);
}
}
#endif // SLI_VSE_MAILBOX_COMMAND_SUPPORTED
#endif // !SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT
/***************************************************************************//**
* Initialize an SE command context object
******************************************************************************/
sl_status_t sl_se_init_command_context(sl_se_command_context_t *cmd_ctx)
{
sl_se_command_context_t v = SL_SE_COMMAND_CONTEXT_INIT;
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
*cmd_ctx = v;
return SL_STATUS_OK;
}
/***************************************************************************//**
* De-initialize an SE command context object
******************************************************************************/
sl_status_t sl_se_deinit_command_context(sl_se_command_context_t *cmd_ctx)
{
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
return sl_se_init_command_context(cmd_ctx);
}
/** @} (end addtogroup sl_se) */
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED) || defined(SLI_VSE_MAILBOX_COMMAND_SUPPORTED)

View File

@@ -0,0 +1,296 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_se_manager.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED) \
&& (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#include "sl_se_manager.h"
#include "sli_se_manager_internal.h"
#include "sl_se_manager_attestation.h"
#include "sli_se_manager_mailbox.h"
/// @addtogroup sl_se_manager
/// @{
// -----------------------------------------------------------------------------
// Static Functions
/***************************************************************************//**
* @brief
* Validate the command word, challenge size and update command word with
* option flags
*
* @param[in, out] command_word
* The command word to send to the SE. Will be modified to reflect challenge
* size.
*
* @param challenge_size
* Size of the challenge to be used.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
static sl_status_t validate_and_update_command_word(uint32_t *command_word,
size_t challenge_size)
{
// Check supported challenge sizes
uint32_t command_id = *command_word & 0xFFFF0000UL;
if (command_id == SLI_SE_COMMAND_ATTEST_PSA_IAT) {
switch (challenge_size) {
case SL_SE_ATTESTATION_CHALLENGE_SIZE_32:
*command_word |= 0x01 << 8;
break;
case SL_SE_ATTESTATION_CHALLENGE_SIZE_48:
*command_word |= 0x02 << 8;
break;
case SL_SE_ATTESTATION_CHALLENGE_SIZE_64:
*command_word |= 0x03 << 8;
break;
default:
return SL_STATUS_INVALID_PARAMETER;
}
} else if (command_id == SLI_SE_COMMAND_ATTEST_CONFIG) {
if (challenge_size != SL_SE_ATTESTATION_CHALLENGE_SIZE_32) {
return SL_STATUS_INVALID_PARAMETER;
}
// No need to do anything with the command word
} else {
// Unknown command ID
return SL_STATUS_INVALID_PARAMETER;
}
// All the checks passed
return SL_STATUS_OK;
}
/***************************************************************************//**
* @brief
* Get the PSA initial attest token from the SE
*
* @param[in] cmd_ctx
* SE command context struct.
*
* @param[in] challenge_size
* Size of the challenge object in bytes. Must be either 32, 48 or 64.
*
* @param[out] token_size
* Number of bytes actually used in token_buf.
*
* @param[in] command_word
* The command word to send to the SE, to differentiat between token types
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
static sl_status_t get_attestation_token_size(sl_se_command_context_t *cmd_ctx,
size_t challenge_size,
size_t *token_size,
uint32_t command_word)
{
// Parameter check
if (cmd_ctx == NULL || token_size == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Check command word and challenge size
sl_status_t status = validate_and_update_command_word(&command_word,
challenge_size);
if (status != SL_STATUS_OK) {
return status;
}
// Use a dummy nonce since the SE requires nonce input even if we just
// want to find the token length
uint8_t dummy_nonce[SL_SE_ATTESTATION_CHALLENGE_SIZE_64] = { 0 };
// Build and execute the command
sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
// Or comman word with 0x01 to enable length output only
sli_se_command_init(cmd_ctx, command_word | 0x01UL);
sli_se_datatransfer_t noncedata =
SLI_SE_DATATRANSFER_DEFAULT(dummy_nonce, challenge_size);
sli_se_mailbox_command_add_input(se_cmd, &noncedata);
sli_se_datatransfer_t sizedata =
SLI_SE_DATATRANSFER_DEFAULT(token_size, sizeof(*token_size));
sli_se_mailbox_command_add_output(se_cmd, &sizedata);
return sli_se_execute_and_wait(cmd_ctx);
}
/***************************************************************************//**
* @brief
* Get an attestation token from the SE
*
* @param[in] cmd_ctx
* SE command context struct.
*
* @param[in] auth_challenge
* Buffer with a challenge object selected by the caller.
*
* @param[in] challenge_size
* Size of the challenge object in bytes. Must be either 32, 48 or 64.
*
* @param[out] token_buf
* Buffer where the output token will be stored.
*
* @param[in] token_buf_size
* Size of token_buf in bytes.
*
* @param[out] token_size
* Number of bytes actually used in token_buf.
*
* @param[in] command_word
* The command word to send to the SE, to differentiat between token types
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
static sl_status_t get_attestation_token(sl_se_command_context_t *cmd_ctx,
const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size,
uint32_t command_word)
{
// Parameter check
if (cmd_ctx == NULL
|| auth_challenge == NULL
|| token_buf == NULL
|| token_size == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Check supported challenge sizes
sl_status_t status = validate_and_update_command_word(&command_word,
challenge_size);
if (status != SL_STATUS_OK) {
return status;
}
// Check that buffer is sufficiently large
status = get_attestation_token_size(cmd_ctx,
challenge_size,
token_size,
command_word);
if (status != SL_STATUS_OK) {
return status;
}
if (((*token_size + 0x3) & ~0x3) > token_buf_size) {
return SL_STATUS_WOULD_OVERFLOW;
}
// Build and execute the command
sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
sli_se_command_init(cmd_ctx, command_word);
sli_se_datatransfer_t noncedata =
SLI_SE_DATATRANSFER_DEFAULT(auth_challenge, challenge_size);
sli_se_mailbox_command_add_input(se_cmd, &noncedata);
sli_se_datatransfer_t sizedata =
SLI_SE_DATATRANSFER_DEFAULT(token_size, sizeof(*token_size));
sli_se_mailbox_command_add_output(se_cmd, &sizedata);
sli_se_datatransfer_t tokendata =
SLI_SE_DATATRANSFER_DEFAULT(token_buf, ((*token_size + 0x3) & ~0x3));
sli_se_mailbox_command_add_output(se_cmd, &tokendata);
return sli_se_execute_and_wait(cmd_ctx);
}
// -----------------------------------------------------------------------------
// Global Functions
/***************************************************************************//**
* Get the PSA initial attest token from the SE
******************************************************************************/
sl_status_t sl_se_attestation_get_psa_iat_token(sl_se_command_context_t *cmd_ctx,
const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size)
{
return get_attestation_token(cmd_ctx,
auth_challenge,
challenge_size,
token_buf,
token_buf_size,
token_size,
SLI_SE_COMMAND_ATTEST_PSA_IAT);
}
/***************************************************************************//**
* Get the size of a PSA initial attest token with the given nonce
******************************************************************************/
sl_status_t sl_se_attestation_get_psa_iat_token_size(sl_se_command_context_t *cmd_ctx,
size_t challenge_size,
size_t *token_size)
{
return get_attestation_token_size(cmd_ctx,
challenge_size,
token_size,
SLI_SE_COMMAND_ATTEST_PSA_IAT);
}
/***************************************************************************//**
* Get an attested (signed) security configuration token from the SE
******************************************************************************/
sl_status_t sl_se_attestation_get_config_token(sl_se_command_context_t *cmd_ctx,
const uint8_t *auth_challenge,
size_t challenge_size,
uint8_t *token_buf,
size_t token_buf_size,
size_t *token_size)
{
return get_attestation_token(cmd_ctx,
auth_challenge,
challenge_size,
token_buf,
token_buf_size,
token_size,
SLI_SE_COMMAND_ATTEST_CONFIG);
}
/***************************************************************************//**
* Get the size of a security configuration token
******************************************************************************/
sl_status_t sl_se_attestation_get_config_token_size(sl_se_command_context_t *cmd_ctx,
size_t challenge_size,
size_t *token_size)
{
return get_attestation_token_size(cmd_ctx,
challenge_size,
token_size,
SLI_SE_COMMAND_ATTEST_CONFIG);
}
/** @} (end addtogroup sl_se_manager) */
#endif // SLI_MAILBOX_COMMAND_SUPPORTED && VAULT

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,103 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_se_manager.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#include "sli_se_manager_internal.h"
#include "sli_se_manager_mailbox.h"
#include <string.h>
/// @addtogroup sl_se_manager
/// @{
// -----------------------------------------------------------------------------
// Global Functions
/***************************************************************************//**
* Get random data from hardware TRNG.
******************************************************************************/
sl_status_t sl_se_get_random(sl_se_command_context_t *cmd_ctx,
void * data,
uint32_t num_bytes)
{
sli_se_mailbox_command_t *se_cmd;
sl_status_t ret;
uint32_t surplus_bytes, i;
uint32_t surplus_word = 0;
if (cmd_ctx == NULL || (num_bytes != 0 && data == NULL)) {
return SL_STATUS_INVALID_PARAMETER;
}
se_cmd = &cmd_ctx->command;
surplus_bytes = num_bytes & 0x3U;
num_bytes &= ~0x3U;
if (num_bytes > 0U) {
sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_TRNG_GET_RANDOM);
sli_se_datatransfer_t data_out = SLI_SE_DATATRANSFER_DEFAULT(data, num_bytes);
sli_se_mailbox_command_add_output(se_cmd, &data_out);
sli_se_mailbox_command_add_parameter(se_cmd, num_bytes);
// Execute and wait
if ((ret = sli_se_execute_and_wait(cmd_ctx)) != SL_STATUS_OK) {
memset(data, 0, num_bytes);
return ret;
}
}
if (surplus_bytes > 0) {
sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_TRNG_GET_RANDOM);
sli_se_datatransfer_t data_out = SLI_SE_DATATRANSFER_DEFAULT(&surplus_word, 4);
sli_se_mailbox_command_add_output(se_cmd, &data_out);
sli_se_mailbox_command_add_parameter(se_cmd, 4);
// Execute and wait
if ((ret = sli_se_execute_and_wait(cmd_ctx)) != SL_STATUS_OK) {
memset(data, 0, num_bytes + surplus_bytes);
return ret;
}
uint8_t *output = (uint8_t*)data + num_bytes;
for (i = 0; i < surplus_bytes; i++) {
output[i] = (surplus_word >> (i * 8U)) & 0xFFU;
}
}
return SL_STATUS_OK;
}
/** @} (end addtogroup sl_se) */
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)

View File

@@ -0,0 +1,673 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_se_manager.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#include "sli_se_manager_internal.h"
#include "sli_se_manager_mailbox.h"
#include "sl_assert.h"
#include <string.h>
/***************************************************************************//**
* \addtogroup sl_se Secure Engine Manager API
* @{
******************************************************************************/
// -----------------------------------------------------------------------------
// Global functions
/***************************************************************************//**
* Start a SHA1 stream operation.
******************************************************************************/
sl_status_t sl_se_hash_sha1_multipart_starts(sl_se_sha1_multipart_context_t *sha1_ctx,
sl_se_command_context_t *cmd_ctx)
{
static const uint8_t init_state_sha1[32] = {
0x67, 0x45, 0x23, 0x01,
0xEF, 0xCD, 0xAB, 0x89,
0x98, 0xBA, 0xDC, 0xFE,
0x10, 0x32, 0x54, 0x76,
0xC3, 0xD2, 0xE1, 0xF0,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
if (cmd_ctx == NULL || sha1_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
sha1_ctx->total[0] = 0;
sha1_ctx->total[1] = 0;
memcpy(sha1_ctx->state, init_state_sha1, sizeof(sha1_ctx->state));
sha1_ctx->hash_type = SL_SE_HASH_SHA1;
return SL_STATUS_OK;
}
/***************************************************************************//**
* Start a SHA224 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha224_multipart_starts(sl_se_sha224_multipart_context_t *sha224_ctx,
sl_se_command_context_t *cmd_ctx)
{
static const uint8_t init_state_sha224[32] = {
0xC1, 0x05, 0x9E, 0xD8,
0x36, 0x7C, 0xD5, 0x07,
0x30, 0x70, 0xDD, 0x17,
0xF7, 0x0E, 0x59, 0x39,
0xFF, 0xC0, 0x0B, 0x31,
0x68, 0x58, 0x15, 0x11,
0x64, 0xF9, 0x8F, 0xA7,
0xBE, 0xFA, 0x4F, 0xA4
};
if (cmd_ctx == NULL || sha224_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
sha224_ctx->total[0] = 0;
sha224_ctx->total[1] = 0;
memcpy(sha224_ctx->state, init_state_sha224, sizeof(sha224_ctx->state));
sha224_ctx->hash_type = SL_SE_HASH_SHA224;
return SL_STATUS_OK;
}
/***************************************************************************//**
* Start a SHA256 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha256_multipart_starts(sl_se_sha256_multipart_context_t *sha256_ctx,
sl_se_command_context_t *cmd_ctx)
{
static const uint8_t init_state_sha256[32] = {
0x6A, 0x09, 0xE6, 0x67,
0xBB, 0x67, 0xAE, 0x85,
0x3C, 0x6E, 0xF3, 0x72,
0xA5, 0x4F, 0xF5, 0x3A,
0x51, 0x0E, 0x52, 0x7F,
0x9B, 0x05, 0x68, 0x8C,
0x1F, 0x83, 0xD9, 0xAB,
0x5B, 0xE0, 0xCD, 0x19
};
if (cmd_ctx == NULL || sha256_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
sha256_ctx->total[0] = 0;
sha256_ctx->total[1] = 0;
memcpy(sha256_ctx->state, init_state_sha256, sizeof(sha256_ctx->state));
sha256_ctx->hash_type = SL_SE_HASH_SHA256;
return SL_STATUS_OK;
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* Start a SHA384 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha384_multipart_starts(sl_se_sha384_multipart_context_t *sha384_ctx,
sl_se_command_context_t *cmd_ctx)
{
static const uint8_t init_state_sha384[64] = {
0xCB, 0xBB, 0x9D, 0x5D, 0xC1, 0x05, 0x9E, 0xD8,
0x62, 0x9A, 0x29, 0x2A, 0x36, 0x7C, 0xD5, 0x07,
0x91, 0x59, 0x01, 0x5A, 0x30, 0x70, 0xDD, 0x17,
0x15, 0x2F, 0xEC, 0xD8, 0xF7, 0x0E, 0x59, 0x39,
0x67, 0x33, 0x26, 0x67, 0xFF, 0xC0, 0x0B, 0x31,
0x8E, 0xB4, 0x4A, 0x87, 0x68, 0x58, 0x15, 0x11,
0xDB, 0x0C, 0x2E, 0x0D, 0x64, 0xF9, 0x8F, 0xA7,
0x47, 0xB5, 0x48, 0x1D, 0xBE, 0xFA, 0x4F, 0xA4
};
if (cmd_ctx == NULL || sha384_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
sha384_ctx->total[0] = 0;
sha384_ctx->total[1] = 0;
sha384_ctx->total[2] = 0;
sha384_ctx->total[3] = 0;
memcpy(sha384_ctx->state, init_state_sha384, sizeof(sha384_ctx->state));
sha384_ctx->hash_type = SL_SE_HASH_SHA384;
return SL_STATUS_OK;
}
/***************************************************************************//**
* Start a SHA512 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha512_multipart_starts(sl_se_sha512_multipart_context_t *sha512_ctx, sl_se_command_context_t *cmd_ctx)
{
static const uint8_t init_state_sha512[64] = {
0x6A, 0x09, 0xE6, 0x67, 0xF3, 0xBC, 0xC9, 0x08,
0xBB, 0x67, 0xAE, 0x85, 0x84, 0xCA, 0xA7, 0x3B,
0x3C, 0x6E, 0xF3, 0x72, 0xFE, 0x94, 0xF8, 0x2B,
0xA5, 0x4F, 0xF5, 0x3A, 0x5F, 0x1D, 0x36, 0xF1,
0x51, 0x0E, 0x52, 0x7F, 0xAD, 0xE6, 0x82, 0xD1,
0x9B, 0x05, 0x68, 0x8C, 0x2B, 0x3E, 0x6C, 0x1F,
0x1F, 0x83, 0xD9, 0xAB, 0xFB, 0x41, 0xBD, 0x6B,
0x5B, 0xE0, 0xCD, 0x19, 0x13, 0x7E, 0x21, 0x79
};
if (cmd_ctx == NULL || sha512_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
sha512_ctx->total[0] = 0;
sha512_ctx->total[1] = 0;
sha512_ctx->total[2] = 0;
sha512_ctx->total[3] = 0;
memcpy(sha512_ctx->state, init_state_sha512, sizeof(sha512_ctx->state));
sha512_ctx->hash_type = SL_SE_HASH_SHA512;
return SL_STATUS_OK;
}
#endif
/***************************************************************************//**
* Start a hash stream operation.
******************************************************************************/
sl_status_t sl_se_hash_multipart_starts(void *hash_type_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_hash_type_t hash_type)
{
if (cmd_ctx == NULL || hash_type_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
switch (hash_type) {
case SL_SE_HASH_SHA1:
return sl_se_hash_sha1_multipart_starts((sl_se_sha1_multipart_context_t*)
hash_type_ctx, cmd_ctx);
case SL_SE_HASH_SHA224:
return sl_se_hash_sha224_multipart_starts((sl_se_sha224_multipart_context_t*)
hash_type_ctx, cmd_ctx);
case SL_SE_HASH_SHA256:
return sl_se_hash_sha256_multipart_starts((sl_se_sha256_multipart_context_t*)
hash_type_ctx, cmd_ctx);
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
return sl_se_hash_sha384_multipart_starts((sl_se_sha384_multipart_context_t*)
hash_type_ctx,
cmd_ctx);
case SL_SE_HASH_SHA512:
return sl_se_hash_sha512_multipart_starts((sl_se_sha512_multipart_context_t*)
hash_type_ctx, cmd_ctx);
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
}
/***************************************************************************//**
* Feeds an input block into an ongoing hash computation.
******************************************************************************/
static sl_status_t se_cmd_hash_multipart_update(void *hash_type_ctx,
sl_se_command_context_t *cmd_ctx,
const uint8_t *input,
uint32_t num_blocks)
{
sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
uint8_t *state;
uint32_t command_word = SLI_SE_COMMAND_HASHUPDATE;
size_t state_len, blocksize;
switch (((sl_se_sha1_multipart_context_t*)hash_type_ctx)->hash_type) {
case SL_SE_HASH_SHA1:
state = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->state;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA1;
state_len = 20;
blocksize = 64;
break;
case SL_SE_HASH_SHA224:
state = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->state;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA224;
state_len = 32;
blocksize = 64;
break;
case SL_SE_HASH_SHA256:
state = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->state;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA256;
state_len = 32;
blocksize = 64;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
state = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->state;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA384;
state_len = 64;
blocksize = 128;
break;
case SL_SE_HASH_SHA512:
state = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->state;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
state_len = 64;
blocksize = 128;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
sli_se_command_init(cmd_ctx, command_word);
size_t ilen = blocksize * num_blocks;
sli_se_mailbox_command_add_parameter(se_cmd, ilen);
sli_se_datatransfer_t data_in = SLI_SE_DATATRANSFER_DEFAULT(input, ilen);
sli_se_datatransfer_t iv_in = SLI_SE_DATATRANSFER_DEFAULT(state, state_len);
sli_se_datatransfer_t iv_out = SLI_SE_DATATRANSFER_DEFAULT(state, state_len);
sli_se_mailbox_command_add_input(se_cmd, &iv_in);
sli_se_mailbox_command_add_input(se_cmd, &data_in);
sli_se_mailbox_command_add_output(se_cmd, &iv_out);
// Execute and wait
return sli_se_execute_and_wait(cmd_ctx);
}
/***************************************************************************//**
* Feeds an input buffer into an ongoing hash computation.
******************************************************************************/
sl_status_t sl_se_hash_multipart_update(void *hash_type_ctx,
sl_se_command_context_t *cmd_ctx,
const uint8_t *input,
size_t input_len)
{
size_t blocks, fill, left, blocksize, countersize;
sl_status_t status;
uint8_t *buffer;
uint32_t *counter;
if ( input_len == 0 ) {
return SL_STATUS_OK;
}
if (hash_type_ctx == NULL || cmd_ctx == NULL || input == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
switch (((sl_se_sha1_multipart_context_t*)hash_type_ctx)->hash_type) {
case SL_SE_HASH_SHA1:
counter = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->buffer;
blocksize = 64;
break;
case SL_SE_HASH_SHA224:
counter = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->buffer;
blocksize = 64;
break;
case SL_SE_HASH_SHA256:
counter = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->buffer;
blocksize = 64;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
counter = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->buffer;
blocksize = 128;
break;
case SL_SE_HASH_SHA512:
counter = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->buffer;
blocksize = 128;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
countersize = blocksize / 32;
left = (counter[0] & (blocksize - 1));
fill = blocksize - left;
counter[0] += input_len;
// ripple counter
if ( counter[0] < input_len ) {
counter[1] += 1;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
for (size_t i = 1; i < (countersize - 1); i++) {
if ( counter[i] == 0 ) {
counter[i + 1]++;
}
}
#else
(void)countersize;
#endif
}
// We only support hashing up to 4 GB data
// so if anything but counter[0] is set, return NOT_SUPPORTED
#if defined(SLI_SE_MAJOR_VERSION_TWO)
for (size_t i = 1; i < countersize; i++) {
if (counter[i] != 0) {
return SL_STATUS_NOT_SUPPORTED;
}
}
#endif
if ( (left > 0) && (input_len >= fill) ) {
memcpy( (void *) (buffer + left), input, fill);
status = se_cmd_hash_multipart_update(hash_type_ctx, cmd_ctx, buffer, 1);
if (status != SL_STATUS_OK) {
return status;
}
input += fill;
input_len -= fill;
left = 0;
}
if ( input_len >= blocksize ) {
blocks = input_len / blocksize;
status = se_cmd_hash_multipart_update(hash_type_ctx, cmd_ctx, input, blocks);
if (status != SL_STATUS_OK) {
return status;
}
input += blocksize * blocks;
input_len -= blocksize * blocks;
}
if ( input_len > 0 ) {
memcpy( (void *) (buffer + left), input, input_len);
}
return SL_STATUS_OK;
}
/***************************************************************************//**
* Finish an ongoing hash streaming computation.
******************************************************************************/
sl_status_t sl_se_hash_multipart_finish(void *hash_type_ctx,
sl_se_command_context_t *cmd_ctx,
uint8_t *digest_out,
size_t digest_len)
{
sl_status_t status;
size_t countersize, blocksize, outputsize;
uint8_t *state;
uint32_t *counter;
#if defined(SLI_SE_MAJOR_VERSION_TWO)
uint32_t command_word = SLI_SE_COMMAND_HASHFINISH;
uint8_t *buffer;
size_t state_len;
#else
size_t last_data_byte, num_pad_bytes;
uint8_t msglen[16];
// Define padding as largest padding we might need
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
static const unsigned char sha_padding[128] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#else
static const unsigned char sha_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#endif
#endif
if (hash_type_ctx == NULL || cmd_ctx == NULL || digest_out == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
switch (((sl_se_sha1_multipart_context_t*)hash_type_ctx)->hash_type) {
case SL_SE_HASH_SHA1:
state = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->state;
counter = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->total;
outputsize = 20;
blocksize = 64;
#if defined(SLI_SE_MAJOR_VERSION_TWO)
state_len = 20;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA1;
buffer = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->buffer;
#endif
break;
case SL_SE_HASH_SHA224:
state = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->state;
counter = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->total;
outputsize = 28;
blocksize = 64;
#if defined(SLI_SE_MAJOR_VERSION_TWO)
state_len = 32;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA224;
buffer = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->buffer;
#endif
break;
case SL_SE_HASH_SHA256:
state = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->state;
counter = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->total;
outputsize = 32;
blocksize = 64;
#if defined(SLI_SE_MAJOR_VERSION_TWO)
state_len = 32;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA256;
buffer = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->buffer;
#endif
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
state = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->state;
counter = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->total;
outputsize = 48;
blocksize = 128;
#if defined(SLI_SE_MAJOR_VERSION_TWO)
state_len = 64;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA384;
buffer = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->buffer;
#endif
break;
case SL_SE_HASH_SHA512:
state = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->state;
counter = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->total;
outputsize = 64;
blocksize = 128;
#if defined(SLI_SE_MAJOR_VERSION_TWO)
state_len = 64;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
buffer = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->buffer;
#endif
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
if ( digest_len < outputsize ) {
return SL_STATUS_INVALID_PARAMETER;
}
countersize = blocksize / 32;
#if defined(SLI_SE_MAJOR_VERSION_TWO)
// We only support hashing up to 4 GB data
// so if anything but counter[0] is set, return NOT_SUPPORTED
for (size_t i = 1; i < countersize; i++) {
if (counter[i] != 0) {
return SL_STATUS_NOT_SUPPORTED;
}
}
// Remaining bytes in buffer
size_t rem_bytes = (counter[0] & (blocksize - 1));
sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
sli_se_command_init(cmd_ctx, command_word);
sli_se_mailbox_command_add_parameter(se_cmd, rem_bytes);
sli_se_mailbox_command_add_parameter(se_cmd, counter[0]);
sli_se_datatransfer_t in_0 = SLI_SE_DATATRANSFER_DEFAULT(state, state_len);
sli_se_datatransfer_t in_1 = SLI_SE_DATATRANSFER_DEFAULT(buffer, rem_bytes);
sli_se_datatransfer_t out = SLI_SE_DATATRANSFER_DEFAULT(digest_out, outputsize);
sli_se_mailbox_command_add_input(se_cmd, &in_0);
sli_se_mailbox_command_add_input(se_cmd, &in_1);
sli_se_mailbox_command_add_output(se_cmd, &out);
// Execute and wait
status = sli_se_execute_and_wait(cmd_ctx);
#else
/* Convert counter value to bits, and put in big-endian array */
uint8_t residual = 0;
for (size_t i = 0; i < countersize; i++) {
size_t msglen_index = ( (countersize - i) * sizeof(uint32_t) ) - 1;
msglen[msglen_index - 0] = ((counter[i] << 3) + residual) & 0xFF;
msglen[msglen_index - 1] = (counter[i] >> 5) & 0xFF;
msglen[msglen_index - 2] = (counter[i] >> 13) & 0xFF;
msglen[msglen_index - 3] = (counter[i] >> 21) & 0xFF;
residual = (counter[i] >> 29) & 0xFF;
}
last_data_byte = (counter[0] & (blocksize - 1) );
num_pad_bytes = (last_data_byte < (blocksize - (countersize * 4)) )
? ( (blocksize - (countersize * 4)) - last_data_byte)
: ( ((2 * blocksize) - (countersize * 4)) - last_data_byte);
status = sl_se_hash_multipart_update(hash_type_ctx, cmd_ctx, sha_padding, num_pad_bytes);
if (status == SL_STATUS_OK) {
status = sl_se_hash_multipart_update(hash_type_ctx, cmd_ctx, msglen, countersize * 4);
}
if (status == SL_STATUS_OK) {
memcpy(digest_out, state, outputsize);
}
#endif // SLI_SE_MAJOR_VERSION_TWO
return status;
}
/***************************************************************************//**
* Produce a message digest (a hash block) using the input data.
******************************************************************************/
sl_status_t sl_se_hash(sl_se_command_context_t *cmd_ctx,
sl_se_hash_type_t hash_type,
const uint8_t *message,
unsigned int message_size,
uint8_t* digest,
size_t digest_len)
{
if (cmd_ctx == NULL
|| digest == NULL
|| (message == NULL
&& message_size != 0)) {
return SL_STATUS_INVALID_PARAMETER;
}
sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
uint32_t command_word = SLI_SE_COMMAND_HASH;
uint32_t digest_size = 0;
switch (hash_type) {
case SL_SE_HASH_SHA1:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA1;
digest_size = 20;
break;
case SL_SE_HASH_SHA224:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA224;
digest_size = 28;
break;
case SL_SE_HASH_SHA256:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA256;
digest_size = 32;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA384;
digest_size = 48;
break;
case SL_SE_HASH_SHA512:
digest_size = 64;
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
if ( digest_len < digest_size ) {
return SL_STATUS_INVALID_PARAMETER;
}
sli_se_command_init(cmd_ctx, command_word);
sli_se_mailbox_command_add_parameter(se_cmd, message_size);
sli_se_datatransfer_t data_in = SLI_SE_DATATRANSFER_DEFAULT(message, message_size);
sli_se_datatransfer_t data_out = SLI_SE_DATATRANSFER_DEFAULT(digest, digest_size);
sli_se_mailbox_command_add_input(se_cmd, &data_in);
sli_se_mailbox_command_add_output(se_cmd, &data_out);
// Execute and wait
return sli_se_execute_and_wait(cmd_ctx);
}
/** @} (end addtogroup sl_se) */
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,215 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sl_se_manager.h"
#if defined(SLI_MAILBOX_COMMAND_SUPPORTED)
#include "sl_se_manager.h"
#include "sli_se_manager_internal.h"
#include "sli_se_manager_mailbox.h"
#include <string.h>
/// @addtogroup sl_se_manager
/// @{
// -----------------------------------------------------------------------------
// Global Functions
/***************************************************************************//**
* ECC signature generation.
******************************************************************************/
sl_status_t sl_se_ecc_sign(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
sl_se_hash_type_t hash_alg,
bool hashed_message,
const unsigned char *message,
size_t message_len,
unsigned char *signature,
size_t signature_len)
{
if (cmd_ctx == NULL || key == NULL || signature == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
if ( message == NULL && message_len != 0 ) {
return SL_STATUS_INVALID_PARAMETER;
}
sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
sl_status_t status;
uint32_t command_word = SLI_SE_COMMAND_SIGNATURE_SIGN;
if ((key->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
== SL_SE_KEY_TYPE_ECC_EDDSA) {
command_word = SLI_SE_COMMAND_EDDSA_SIGN;
} else {
if (hashed_message == false) {
switch (hash_alg) {
case SL_SE_HASH_SHA1:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA1;
break;
case SL_SE_HASH_SHA224:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA224;
break;
case SL_SE_HASH_SHA256:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA256;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA384;
break;
case SL_SE_HASH_SHA512:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
}
}
// Setup SE command and parameters
sli_se_command_init(cmd_ctx, command_word);
// Add key parameters to command
sli_add_key_parameters(cmd_ctx, key, status);
// Message size (number of bytes)
sli_se_mailbox_command_add_parameter(se_cmd, message_len);
// Add key metadata block to command
sli_add_key_metadata(cmd_ctx, key, status);
// Add key input block to command
sli_add_key_input(cmd_ctx, key, status);
sli_se_datatransfer_t message_buffer = SLI_SE_DATATRANSFER_DEFAULT(message, message_len);
sli_se_mailbox_command_add_input(se_cmd, &message_buffer);
// EdDSA requires the message twice
sli_se_datatransfer_t repeated_message_buffer = SLI_SE_DATATRANSFER_DEFAULT(message, message_len);
if ((key->type & SL_SE_KEY_TYPE_ALGORITHM_MASK) == SL_SE_KEY_TYPE_ECC_EDDSA) {
sli_se_mailbox_command_add_input(se_cmd, &repeated_message_buffer);
}
sli_se_datatransfer_t signature_buffer = SLI_SE_DATATRANSFER_DEFAULT(signature, signature_len);
sli_se_mailbox_command_add_output(se_cmd, &signature_buffer);
return sli_se_execute_and_wait(cmd_ctx);
}
/***************************************************************************//**
* ECC signature verification.
******************************************************************************/
sl_status_t sl_se_ecc_verify(sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
sl_se_hash_type_t hash_alg,
bool hashed_message,
const unsigned char *message,
size_t message_len,
const unsigned char *signature,
size_t signature_len)
{
if (cmd_ctx == NULL || key == NULL || (message == NULL && message_len != 0) || signature == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Key needs to contain public key in order to verify signatures
if (!(key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_BUFFER_HAS_PUBLIC_KEY)) {
return SL_STATUS_INVALID_PARAMETER;
}
sli_se_mailbox_command_t *se_cmd = &cmd_ctx->command;
sl_status_t status;
uint32_t command_word = SLI_SE_COMMAND_SIGNATURE_VERIFY;
if ((key->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
== SL_SE_KEY_TYPE_ECC_EDDSA) {
command_word = SLI_SE_COMMAND_EDDSA_VERIFY;
} else {
if (hashed_message == false) {
switch (hash_alg) {
case SL_SE_HASH_SHA1:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA1;
break;
case SL_SE_HASH_SHA224:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA224;
break;
case SL_SE_HASH_SHA256:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA256;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA384;
break;
case SL_SE_HASH_SHA512:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
}
}
// Setup SE command and parameters
sli_se_command_init(cmd_ctx, command_word);
// Add key parameters to command
sli_add_key_parameters(cmd_ctx, key, status);
// Message size (number of bytes)
sli_se_mailbox_command_add_parameter(se_cmd, message_len);
// Add key metadata block to command
sli_add_key_metadata(cmd_ctx, key, status);
// Add key input block to command
sli_add_key_input(cmd_ctx, key, status);
sli_se_datatransfer_t message_buffer = SLI_SE_DATATRANSFER_DEFAULT(message,
message_len);
sli_se_datatransfer_t signature_buffer = SLI_SE_DATATRANSFER_DEFAULT(signature,
signature_len);
if ((key->type & SL_SE_KEY_TYPE_ALGORITHM_MASK) == SL_SE_KEY_TYPE_ECC_EDDSA) {
sli_se_mailbox_command_add_input(se_cmd, &signature_buffer);
sli_se_mailbox_command_add_input(se_cmd, &message_buffer);
} else {
sli_se_mailbox_command_add_input(se_cmd, &message_buffer);
sli_se_mailbox_command_add_input(se_cmd, &signature_buffer);
}
return sli_se_execute_and_wait(cmd_ctx);
}
/** @} (end addtogroup sl_se) */
#endif // defined(SLI_MAILBOX_COMMAND_SUPPORTED)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,617 @@
/***************************************************************************//**
* @file
* @brief SE Mailbox API
*******************************************************************************
* # License
* <b>Copyright 2024 Silicon Laboratories Inc. www.silabs.com</b>
*******************************************************************************
*
* SPDX-License-Identifier: Zlib
*
* The licensor of this software is Silicon Laboratories Inc.
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*
******************************************************************************/
#include "sli_se_manager_mailbox.h"
#if defined(SLI_SE_MAILBOX_HOST_SYSTEM) || defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
#if !defined(SLI_SE_MAILBOX_HOST_SYSTEM)
#if defined(CRYPTOACC_PRESENT)
#include "sl_core.h"
#endif
#include "sl_assert.h"
#endif
/***************************************************************************//**
* @addtogroup se
* @{
******************************************************************************/
/*******************************************************************************
****************************** DEFINES ***********************************
******************************************************************************/
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
#if defined(CRYPTOACC_PRESENT)
/// Signal that OTP version is incorporated into the status field of the output
#define SE_VSE_REPLY_STATUS_OTP_VERSION_SET (1 << 21)
/// Mask defining the region of the status field that contains the OTP version
/// number.
#define SE_VSE_REPLY_STATUS_OTP_VERSION_MASK (0xFF000000UL)
/// Shift to insert a number into the otp version part of the status field
#define SE_VSE_REPLY_STATUS_OTP_VERSION_SHIFT (24)
/* Size of VSE Mailbox instance.
There are two instances, input and output. */
#define ROOT_MAILBOX_SIZE (512UL)
/* Base addresses of the VSE Input and Output Mailbox data structures.
(Must be stored in a RAM area which is not used by the VSE)
We use the upper 1KB of FRC RAM for the VSE mailboxes. */
#define ROOT_MAILBOX_OUTPUT_S_BASE (RDMEM_FRCRAM_S_MEM_END + 1 - ROOT_MAILBOX_SIZE)
#define ROOT_MAILBOX_INPUT_S_BASE (ROOT_MAILBOX_OUTPUT_S_BASE - ROOT_MAILBOX_SIZE)
// SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S is defined in sl_trustzone_secure_config.h
#if ((defined(SL_TRUSTZONE_SECURE) && !defined(SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S)) \
|| (defined(SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S) && SL_TRUSTZONE_PERIPHERAL_AHBRADIO_S))
#define RDMEM_FRCRAM_MEM_BASE RDMEM_FRCRAM_S_MEM_BASE
#define ROOT_MAILBOX_OUTPUT_BASE SYSCFG->ROOTDATA1;
#define ROOT_MAILBOX_OUTPUT_BASE_EXPECTED ROOT_MAILBOX_OUTPUT_S_BASE
#else
#define RDMEM_FRCRAM_MEM_BASE RDMEM_FRCRAM_NS_MEM_BASE
// VSE will always output the secure address, if NS is desired, caculate the NS address.
#define ROOT_MAILBOX_OUTPUT_BASE (SYSCFG->ROOTDATA1 - RDMEM_FRCRAM_S_MEM_BASE + RDMEM_FRCRAM_NS_MEM_BASE);
#define ROOT_MAILBOX_OUTPUT_BASE_EXPECTED (RDMEM_FRCRAM_NS_MEM_END + 1 - ROOT_MAILBOX_SIZE)
#endif
#define ROOT_MAILBOX_INPUT_BASE (ROOT_MAILBOX_OUTPUT_BASE_EXPECTED - ROOT_MAILBOX_SIZE)
/* Position of parameter number field in VSE Input Mailbox LENGTH field.*/
#define ROOT_MB_LENGTH_PARAM_NUM_SHIFT (24)
/* Done flag indicating that the VSE Mailbox handler has completed
processing the mailbox command. */
#define ROOT_MB_DONE (1 << 23)
/* VSE Configuration Status bits mask */
#define ROOT_MB_OUTPUT_STATUS_CONFIG_BITS_MASK (0xFFFF)
#endif // #if defined(CRYPTOACC_PRESENT)
/** @endcond */
/*******************************************************************************
****************************** TYPEDEFS ***********************************
******************************************************************************/
#if defined(CRYPTOACC_PRESENT)
/** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
// VSE Input Mailbox structure
typedef struct {
volatile uint32_t magic;
volatile uint32_t command;
volatile uint32_t length;
volatile uint32_t data[0];
} root_mailbox_input_t;
// VSE Output Mailbox structure
typedef struct {
volatile uint32_t magic;
volatile uint32_t version;
volatile uint32_t status;
volatile uint32_t command;
volatile uint32_t length;
volatile uint32_t data[0];
} root_mailbox_output_t;
/** @endcond */
#endif // #if defined(CRYPTOACC_PRESENT)
/*******************************************************************************
************************** STATIC FUNCTIONS *******************************
******************************************************************************/
#if defined(SEMAILBOX_PRESENT)
/***************************************************************************//**
* @brief
* Write to FIFO
*
* @param value
* Value to write to FIFO
******************************************************************************/
#if defined(_SEMAILBOX_FIFO_RESETVALUE)
__STATIC_INLINE void write_to_fifo(uint32_t value)
{
SEMAILBOX_HOST->FIFO = value;
}
#else
__STATIC_INLINE void write_to_fifo(uint32_t value)
{
SEMAILBOX_HOST->FIFO[0].DATA = value;
}
#endif
#elif defined(CRYPTOACC_PRESENT)
/***************************************************************************//**
* @brief
* Return a pointer to the root mailbox output
*
* @return root_mailbox_output_t pointer
******************************************************************************/
static root_mailbox_output_t* get_root_mailbox_output(void)
{
// Setup pointer to the VSE Output Mailbox data structure
// (must be stored in a RAM area which is not used by the VSE)
bool sys_cfg_clk_enabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
root_mailbox_output_t *mailbox_output = (root_mailbox_output_t *) ROOT_MAILBOX_OUTPUT_BASE;
if (!sys_cfg_clk_enabled) {
CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
}
return mailbox_output;
}
/***************************************************************************//**
* @brief
* Check whether the running command has completed.
*
* @details
* This function polls the SE-to-host mailbox interrupt flag.
*
* @return True if a command has completed and the result is available
******************************************************************************/
static bool vse_is_command_completed(root_mailbox_output_t *root_mailbox_output)
{
// First verify that the response is ok
if (!sli_vse_mailbox_is_output_valid()) {
return false;
}
// Check status MB_DONE flag of the mailbox
return ((root_mailbox_output->status & ROOT_MB_DONE) == ROOT_MB_DONE);
}
#endif // SEMAILBOX_PRESENT
/*******************************************************************************
************************** GLOBAL FUNCTIONS *******************************
******************************************************************************/
/***************************************************************************//**
* @brief
* Add input data to a mailbox command
******************************************************************************/
void sli_se_mailbox_command_add_input(sli_se_mailbox_command_t *command, sli_se_datatransfer_t *data)
{
if (command->data_in == NULL) {
command->data_in = data;
} else {
sli_se_datatransfer_t *next = command->data_in;
while (next->next != (void*)SLI_SE_DATATRANSFER_STOP) {
next = (sli_se_datatransfer_t*)next->next;
}
next->next = data;
}
}
/***************************************************************************//**
* @brief
* Add output data to a mailbox command
******************************************************************************/
void sli_se_mailbox_command_add_output(sli_se_mailbox_command_t *command, sli_se_datatransfer_t *data)
{
if (command->data_out == NULL) {
command->data_out = data;
} else {
sli_se_datatransfer_t *next = command->data_out;
while (next->next != (void*)SLI_SE_DATATRANSFER_STOP) {
next = (sli_se_datatransfer_t*)next->next;
}
next->next = data;
}
}
/***************************************************************************//**
* @brief
* Add a parameter to a mailbox command
******************************************************************************/
void sli_se_mailbox_command_add_parameter(sli_se_mailbox_command_t *command, uint32_t parameter)
{
if (command->num_parameters >= SLI_SE_COMMAND_MAX_PARAMETERS) {
EFM_ASSERT(command->num_parameters < SLI_SE_COMMAND_MAX_PARAMETERS);
return;
}
command->parameters[command->num_parameters] = parameter;
command->num_parameters += 1;
}
#if !defined(SLI_SE_MAILBOX_HOST_SYSTEM)
/***************************************************************************//**
* @brief
* Execute a command on the SE by writing the command to SEMAILBOX->FIFO
******************************************************************************/
void sli_se_mailbox_execute_command(sli_se_mailbox_command_t *command)
{
// Don't overflow our struct
if (command->num_parameters > SLI_SE_COMMAND_MAX_PARAMETERS) {
EFM_ASSERT(command->num_parameters <= SLI_SE_COMMAND_MAX_PARAMETERS);
return;
}
#if defined(SEMAILBOX_PRESENT)
// Wait for room available in the mailbox
while (!(SEMAILBOX_HOST->TX_STATUS & SEMAILBOX_TX_STATUS_TXINT)) {
}
#if (_SILICON_LABS_32B_SERIES == 3)
// Write header (including message size) to start transaction
SEMAILBOX_HOST->TX_HEADER = sizeof(uint32_t) * (5 + command->num_parameters);
// Write a 32-bit word to the FIFO ( potentially used as command handle )
write_to_fifo(0);
#else
// Write header (including message size) to start transaction
SEMAILBOX_HOST->TX_HEADER = sizeof(uint32_t) * (4 + command->num_parameters);
#endif
// Write command into FIFO
write_to_fifo(command->command);
// Write DMA descriptors into FIFO
write_to_fifo((uint32_t)command->data_in);
write_to_fifo((uint32_t)command->data_out);
// Write applicable parameters into FIFO
for (size_t i = 0; i < command->num_parameters; i++) {
write_to_fifo(command->parameters[i]);
}
#elif defined(CRYPTOACC_PRESENT)
// Prepare the VSE Mailbox within a critical section to prevent
// the process from getting interrupted. At this point, the only option
// we have is to go through a reset, so it is safe to enter the critical section.
(void)CORE_EnterCritical();
// Setup pointer to the VSE Mailbox Input data structure
// (must be stored in a RAM area which is not used by the VSE)
root_mailbox_input_t *mailbox_input = (root_mailbox_input_t*)ROOT_MAILBOX_INPUT_BASE;
uint32_t *mailbox_data;
unsigned int mailbox_dataLen, inDataLen, i;
sli_se_datatransfer_t *inDataDesc;
uint32_t *inData;
uint32_t checksum;
bool sysCfgClkWasEnabled = ((CMU->CLKEN0 & CMU_CLKEN0_SYSCFG) != 0);
CMU->CLKEN0_SET = CMU_CLKEN0_SYSCFG;
// Store the secure memory base addresses for VSE to be able to read from the address
// Set base of Mailbox Input data structure in SYSCFG register in order
// for VSE to find it.
SYSCFG->ROOTDATA0 = ROOT_MAILBOX_INPUT_S_BASE;
// Set base of Mailbox Output data structure in SYSCFG register in order
// for VSE to know where to write output data.
// Write command into FIFO
SYSCFG->ROOTDATA1 = ROOT_MAILBOX_OUTPUT_S_BASE;
if (!sysCfgClkWasEnabled) {
CMU->CLKEN0_CLR = CMU_CLKEN0_SYSCFG;
}
mailbox_input->magic = SLI_SE_RESPONSE_MAILBOX_VALID;
mailbox_input->command = command->command;
// Write applicable parameters into Mailbox DATA array
mailbox_data = (uint32_t*) mailbox_input->data;
for (mailbox_dataLen = 0; mailbox_dataLen < command->num_parameters; mailbox_dataLen++) {
mailbox_data[mailbox_dataLen] = command->parameters[mailbox_dataLen];
}
// Write input data into Mailbox DATA array
inDataLen = 0;
for (inDataDesc = command->data_in; inDataDesc; inDataDesc = (sli_se_datatransfer_t*) inDataDesc->next) {
inData = (uint32_t*) inDataDesc->data;
for (i = 0; i < (inDataDesc->length & SLI_SE_DATATRANSFER_LENGTH_MASK) / sizeof(uint32_t); i++) {
// Make sure we do not overflow the input mailbox.
EFM_ASSERT(mailbox_dataLen < ROOT_MAILBOX_SIZE);
mailbox_data[mailbox_dataLen++] = inData[i];
inDataLen++;
}
if (inDataDesc->next == (void*)SLI_SE_DATATRANSFER_STOP) {
break;
}
}
// Write number of parameters and data words to 'length' field of mailbox.
mailbox_input->length =
inDataLen | (command->num_parameters << ROOT_MB_LENGTH_PARAM_NUM_SHIFT);
// Calculate checksum using bitwise XOR over the all words in the mailbox
// data structure, minus the CHECKSUM word (32bit = 4bytes ) at the end.
checksum = mailbox_input->magic;
checksum ^= mailbox_input->command;
checksum ^= mailbox_input->length;
for (i = 0; i < mailbox_dataLen; i++) {
checksum ^= mailbox_data[i];
}
// Finally, write the calculated checksum to mailbox checksum field
mailbox_data[mailbox_dataLen] = checksum;
__NVIC_SystemReset();
#endif // #if defined(SEMAILBOX_PRESENT)
}
#endif // #if !defined(SLI_SE_MAILBOX_HOST_SYSTEM)
#if defined(CRYPTOACC_PRESENT)
/***************************************************************************//**
* @brief
* Get current SE version
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_get_version(uint32_t *version)
{
root_mailbox_output_t *root_mailbox_output = get_root_mailbox_output();
if (version == NULL) {
return SLI_SE_RESPONSE_INVALID_PARAMETER;
}
// First verify that the response is ok.
if (!sli_vse_mailbox_is_output_valid()) {
return SLI_SE_RESPONSE_MAILBOX_INVALID;
}
// Return the 'version' from the Output Mailbox
*version = root_mailbox_output->version;
return SLI_SE_RESPONSE_OK;
}
/***************************************************************************//**
* @brief
* Get VSE configuration and status bits
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_get_cfg_status(uint32_t *cfg_status)
{
if (cfg_status == NULL) {
return SLI_SE_RESPONSE_INVALID_PARAMETER;
}
root_mailbox_output_t *root_mailbox_output = get_root_mailbox_output();
// First verify that the response is ok.
if (!sli_vse_mailbox_is_output_valid()) {
return SLI_SE_RESPONSE_MAILBOX_INVALID;
}
// Return the configuration status bits
*cfg_status = root_mailbox_output->status & ROOT_MB_OUTPUT_STATUS_CONFIG_BITS_MASK;
return SLI_SE_RESPONSE_OK;
}
/***************************************************************************//**
* @brief
* Get the version number of the OTP from the status field of the output
* mailbox
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_get_otp_version(uint32_t *otp_version)
{
if (otp_version == NULL) {
return SLI_SE_RESPONSE_INVALID_PARAMETER;
}
root_mailbox_output_t *root_mailbox_output = get_root_mailbox_output();
// First verify that the response is ok.
if (!sli_vse_mailbox_is_output_valid()) {
return SLI_SE_RESPONSE_MAILBOX_INVALID;
}
bool is_otp_version_set = root_mailbox_output->status & SE_VSE_REPLY_STATUS_OTP_VERSION_SET;
if (is_otp_version_set) {
// Return the OTP version from the status field.
*otp_version = (root_mailbox_output->status & SE_VSE_REPLY_STATUS_OTP_VERSION_MASK) >> SE_VSE_REPLY_STATUS_OTP_VERSION_SHIFT;
} else {
return SLI_SE_RESPONSE_INVALID_COMMAND;
}
return SLI_SE_RESPONSE_OK;
}
/***************************************************************************//**
* @brief
* Read the previously executed command.
******************************************************************************/
uint32_t sli_vse_mailbox_read_executed_command(void)
{
root_mailbox_output_t *root_mailbox_output = get_root_mailbox_output();
// First verify that the Output Mailbox includes a valid response.
if (!vse_is_command_completed(root_mailbox_output)) {
return SLI_SE_RESPONSE_MAILBOX_INVALID;
}
return root_mailbox_output->command;
}
/***************************************************************************//**
* @brief
* Read the status of the previously executed command.
*
* @details
* This function reads the status of the previously executed command.
*
* @return
* One of the SE_RESPONSE return codes:
* SLI_SE_RESPONSE_OK when the command was executed successfully or a signature
* was successfully verified,
* SLI_SE_RESPONSE_INVALID_COMMAND when the command ID was not recognized,
* SE_RESPONSE_AUTHORIZATION_ERROR when the command is not authorized,
* SE_RESPONSE_INVALID_SIGNATURE when signature verification failed,
* SE_RESPONSE_BUS_ERROR when a bus error was thrown during the command, e.g.
* because of conflicting Secure/Non-Secure memory accesses,
* SE_RESPONSE_CRYPTO_ERROR on an internal SE failure, or
* SLI_SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
* SLI_SE_RESPONSE_MAILBOX_INVALID when the mailbox content is invalid
******************************************************************************/
sli_se_mailbox_response_t sli_se_mailbox_read_response(void)
{
root_mailbox_output_t *root_mailbox_output = get_root_mailbox_output();
// First verify that the Output Mailbox includes a valid response.
if (!vse_is_command_completed(root_mailbox_output)) {
return SLI_SE_RESPONSE_MAILBOX_INVALID;
}
return (sli_se_mailbox_response_t)(root_mailbox_output->status & SLI_SE_RESPONSE_MASK);
}
/***************************************************************************//**
* @brief
* Acknowledge and get status and output data of a completed command.
*
* @details
* This function acknowledges and gets the status and output data of a
* completed mailbox command.
* The mailbox command is acknowledged by inverting all bits in the checksum
* (XOR with 0xFFFFFFFF).
* The output data is copied into the linked list of output buffers pointed
* to in the given command data structure.
*
* @param[in] command
* Pointer to an SE command structure.
*
* @return
* One of the SE_RESPONSE return codes.
* @retval SLI_SE_RESPONSE_OK when the command was executed successfully or a
* signature was successfully verified,
* @retval SLI_SE_RESPONSE_INVALID_COMMAND when the command ID was not recognized,
* @retval SE_RESPONSE_AUTHORIZATION_ERROR when the command is not authorized,
* @retval SE_RESPONSE_INVALID_SIGNATURE when signature verification failed,
* @retval SE_RESPONSE_BUS_ERROR when a bus error was thrown during the command,
* e.g. because of conflicting Secure/Non-Secure
* memory accesses,
* @retval SE_RESPONSE_CRYPTO_ERROR on an internal SE failure, or
* @retval SLI_SE_RESPONSE_INVALID_PARAMETER when an invalid parameter was passed
* @retval SLI_SE_RESPONSE_MAILBOX_INVALID when mailbox command not done or invalid
******************************************************************************/
sli_se_mailbox_response_t sli_vse_mailbox_ack_command(sli_se_mailbox_command_t *command)
{
// Setup pointer to the VSE Output Mailbox data structure
// (must be stored in a RAM area which is not used by the VSE)
root_mailbox_output_t *root_mailbox_output = get_root_mailbox_output();
uint32_t *mbData = (uint32_t*) root_mailbox_output->data;
sli_se_datatransfer_t *outDataDesc = command->data_out;
unsigned int outDataLen, outDataCnt, i, outDescLen;
uint32_t *outData;
// First verify that the Output Mailbox includes a valid response.
if (!vse_is_command_completed(root_mailbox_output)) {
return SLI_SE_RESPONSE_MAILBOX_INVALID;
}
// Get output data length
outDataLen = root_mailbox_output->length;
// Acknowledge the output mailbox response by invalidating checksum
mbData[outDataLen] ^= 0xFFFFFFFFUL;
// Check command status code
if ((root_mailbox_output->status & SLI_SE_RESPONSE_MASK) != SLI_SE_RESPONSE_OK) {
return root_mailbox_output->status & SLI_SE_RESPONSE_MASK;
}
// Copy data from the Output Mailbox to the linked list of output
// buffers provided by the user
outDataCnt = 0;
while (outDataDesc && (outDataCnt < outDataLen)) {
outData = (uint32_t*) outDataDesc->data;
outDescLen =
(outDataDesc->length & SLI_SE_DATATRANSFER_LENGTH_MASK) / sizeof(uint32_t);
for (i = 0; (i < outDescLen) && (outDataCnt < outDataLen); i++) {
outData[i] = mbData[outDataCnt++];
}
// If we have reached the end of a buffer, go to next buffer descriptor
if (i == outDescLen) {
outDataDesc = (sli_se_datatransfer_t*)
((uint32_t)outDataDesc->next & ~SLI_SE_DATATRANSFER_STOP);
}
}
// Check if the output data list is too small to copy all output data in
// mailbox.
if ((outDataDesc == 0) && (outDataCnt < outDataLen)) {
return SLI_SE_RESPONSE_INVALID_PARAMETER;
}
return SLI_SE_RESPONSE_OK;
}
/***************************************************************************//**
* @brief
* Check whether the VSE Output Mailbox is valid.
*
* @return True if the VSE Output Mailbox is valid (magic and checksum OK)
******************************************************************************/
bool sli_vse_mailbox_is_output_valid(void)
{
root_mailbox_output_t *root_mailbox_output = get_root_mailbox_output();
uint32_t *mb_ptr32 = (uint32_t*) root_mailbox_output;
uint32_t checksum;
unsigned int mb_len, cnt;
if ((uint32_t)root_mailbox_output > ROOT_MAILBOX_OUTPUT_BASE_EXPECTED
|| (uint32_t)root_mailbox_output < RDMEM_FRCRAM_MEM_BASE) {
return false;
}
// Verify magic word of mailbox
if (root_mailbox_output->magic != SLI_SE_RESPONSE_MAILBOX_VALID) {
return false;
}
// Get length of mailbox
mb_len = sizeof(root_mailbox_output_t) / sizeof(uint32_t) + root_mailbox_output->length;
if (mb_len >= ROOT_MAILBOX_SIZE) {
return false;
}
// Calculate checksum using bitwise XOR over all words in the mailbox
// data structure, minus the CHECKSUM word at the end.
for (checksum = 0, cnt = 0; cnt < mb_len; cnt++) {
checksum ^= mb_ptr32[cnt];
}
// Verify that the calculated checksum is equal to the mailbox checksum.
return (mb_ptr32[mb_len] == checksum);
}
#endif // #if defined(CRYPTOACC_PRESENT)
/** @} (end addtogroup se) */
#endif /* defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT) */