modules: hal_silabs: adaptations for BLE support in Zephyr

Origin: Silicon Labs Gecko SDK
URL: https://github.com/SiliconLabs/gecko_sdk
Version: 4.2.0
Purpose: Adding RAIL support.
License: Zlib
Maintained-by: External

Signed-off-by: Pawel Czarnecki <pczarnecki@antmicro.com>
This commit is contained in:
Pawel Czarnecki 2022-11-17 13:52:17 +01:00 committed by Filip Kokosiński
parent 5ea92d1c74
commit 793db3cb74
59 changed files with 23083 additions and 718 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
zephyr/blobs/gecko
tags

View File

@ -1 +1,2 @@
add_subdirectory_ifdef(CONFIG_HAS_SILABS_GECKO gecko)
add_subdirectory_ifdef(CONFIG_HAS_SILABS_GECKO zephyr)

View File

@ -2,6 +2,7 @@
#
# Copyright (c) 2017, Christian Taedcke
# Copyright (c) 2021, Safran Passenger Innovations Germany GmbH
# Copyright (c) 2022, Antmicro <www.antmicro.com>
#
# SPDX-License-Identifier: Apache-2.0
#
@ -27,24 +28,32 @@ endif()
zephyr_include_directories(
Device/SiliconLabs/${SILABS_GECKO_DEVICE}/Include
emlib/inc
service/sleeptimer/src
service/sleeptimer/inc
service/sleeptimer/config
service/power_manager/src
service/power_manager/inc
service/power_manager/config
service/hfxo_manager/src
service/hfxo_manager/inc
service/hfxo_manager/config
board/config/${SILABS_GECKO_BOARD}
board/inc
common/inc
service/device_init/inc
emlib/inc
platform/radio/rail_lib/chip/efr32/efr32xg2x
platform/radio/rail_lib/common
platform/radio/rail_lib/plugin/pa-conversions
platform/radio/rail_lib/plugin/pa-conversions/efr32xg22/config
protocol/bluetooth//bgstack/ll/inc
service/device_init/config/s2
service/device_init/config/s2/${PRODUCT_NO}
service/device_init/inc
service/hfxo_manager/config
service/hfxo_manager/inc
service/hfxo_manager/src
service/power_manager/config
service/power_manager/inc
service/power_manager/src
service/sleeptimer/config
service/sleeptimer/inc
service/sleeptimer/src
util/third_party/crypto/sl_component/sl_protocol_crypto/src
)
foreach(root ${BOARD_ROOT})
message( "ROOT: "${root} )
message("ROOT: " ${root})
if(IS_DIRECTORY "${root}/boards/arm/${CONFIG_BOARD}")
zephyr_include_directories(${root}/boards/arm/${CONFIG_BOARD})
endif()
@ -107,3 +116,31 @@ zephyr_sources_ifdef(CONFIG_SOC_SERIES_EFM32JG12B Device/SiliconLabs/EFM32JG12B
zephyr_sources_ifdef(CONFIG_SOC_SERIES_EFR32MG21 Device/SiliconLabs/EFR32MG21/Source/system_efr32mg21.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_EFM32PG1B Device/SiliconLabs/EFM32PG1B/Source/system_efm32pg1b.c)
zephyr_sources_ifdef(CONFIG_SOC_SERIES_EFR32MG24 Device/SiliconLabs/EFR32MG24/Source/system_efr32mg24.c)
function(add_prebuilt_library lib_name prebuilt_path)
add_library(${lib_name} STATIC IMPORTED GLOBAL)
set_target_properties(${lib_name} PROPERTIES
IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../zephyr/blobs/${prebuilt_path}
)
zephyr_link_libraries(${lib_name})
endfunction()
if(CONFIG_BT_SILABS_HCI)
# rail
zephyr_sources(platform/radio/rail_lib/plugin/pa-conversions/pa_conversions_efr32.c)
# sl_protocol_crypto
zephyr_sources(util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_protocol_crypto_crypto.c)
zephyr_sources(util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_radioaes_management.c)
zephyr_sources(util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_protocol_crypto_radioaes.c)
# prebuilt libs
add_prebuilt_library(liblinklayer gecko/protocol/bluetooth/bgstack/ll/lib/libbluetooth_controller_${CONFIG_SOC_SERIES}_gcc_release.a)
add_prebuilt_library(libbgcommon gecko/protocol/bluetooth/bgcommon/lib/libbgcommon_${CONFIG_SOC_SERIES}_gcc_release.a)
add_prebuilt_library(librail gecko/platform/radio/rail_lib//autogen/librail_release/librail_${CONFIG_SOC_SERIES}_gcc_release.a)
# link mbedTLS
if(CONFIG_MBEDTLS)
zephyr_link_libraries(mbedTLS)
endif()
endif()

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,405 @@
/***************************************************************************//**
* @file
* @brief Definition of error codes that occur in rail for use in
* RAILCb_AssertFailed. This file is purely informational and optional -
* it need not be included even if rail_assert libraries are included.
*******************************************************************************
* # 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 __RAIL_ASSERT_ERROR_CODES_H__
#define __RAIL_ASSERT_ERROR_CODES_H__
#include "rail_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup Assertions
* @{
*/
/**
* Enumeration of all possible error codes from RAIL_ASSERT
*/
RAIL_ENUM_GENERIC(RAIL_AssertErrorCodes_t, uint32_t)
{
/** Appended info missing from Rx packet. */
RAIL_ASSERT_FAILED_APPENDED_INFO_MISSING = 0,
/** Receive FIFO too small for IR calibration. */
RAIL_ASSERT_FAILED_RX_FIFO_BYTES = 1,
/** Error reading back packet payload. */
RAIL_ASSERT_FAILED_RX_FIFO_ZERO_BYTES_READ = 2,
/** Receive fifo entry has invalid status. */
RAIL_ASSERT_FAILED_ILLEGAL_RXLEN_ENTRY_STATUS = 3,
/** Receive fifo entry bad packet length. */
RAIL_ASSERT_FAILED_BAD_PACKET_LENGTH = 4,
/** Unable to configure radio for IR calibration. */
RAIL_ASSERT_FAILED_SYNTH_DIVCTRL_ENUM_CONVERSION_ERROR = 5,
/** Reached unexpected state while handling Rx fifo events. */
RAIL_ASSERT_FAILED_UNEXPECTED_STATE_RX_FIFO = 6,
/** Reached unexpected state while handling RXLEN fifo events. */
RAIL_ASSERT_FAILED_UNEXPECTED_STATE_RXLEN_FIFO = 7,
/** Reached unexpected state while handling Tx fifo events. */
RAIL_ASSERT_FAILED_UNEXPECTED_STATE_TX_FIFO = 8,
/** Reached unexpected state while handling Tx ACK fifo events. */
RAIL_ASSERT_FAILED_UNEXPECTED_STATE_TXACK_FIFO = 9,
/** No memory to store receive packet. */
RAIL_ASSERT_FAILED_PBUFFER_NOT_DEFINED = 10,
/** Packet length longer than the receive FIFO size. */
RAIL_ASSERT_FAILED_INSUFFICIENT_BYTES_IN_RX_PACKET = 11,
/** Invalid radio clock prescaler. */
RAIL_ASSERT_FAILED_CLOCK_PRESCALER = 12,
/** Error synchronizing the RAIL timebase after sleep. */
RAIL_ASSERT_FAILED_RTCC_POST_WAKEUP = 13,
/** VCO frequency outside supported range. */
RAIL_ASSERT_FAILED_SYNTH_VCO_FREQUENCY = 14,
/** Radio active while changing channels. */
RAIL_ASSERT_FAILED_RAC_STATE = 15,
/** Invalid Synth VCOCTRL field calculation. */
RAIL_ASSERT_FAILED_SYNTH_INVALID_VCOCTRL = 16,
/** Nested attempt to lock the sequencer. */
RAIL_ASSERT_FAILED_NESTED_SEQUENCER_LOCK = 17,
/** RSSI averaging enabled without a valid callback. */
RAIL_ASSERT_FAILED_RSSI_AVERAGE_DONE = 18,
/** Invalid dynamic frame length setting provided (dflBits). */
RAIL_ASSERT_FAILED_DFL_BITS_SIZE = 19,
/** Unable to seed radio pseudo random number generator. */
RAIL_ASSERT_FAILED_PROTIMER_RANDOM_SEED = 20,
/** Timeout exceeds EFR32XG1 register size. */
RAIL_ASSERT_FAILED_EFR32XG1_REGISTER_SIZE = 21,
/** Invalid timer channel specified. */
RAIL_ASSERT_FAILED_PROTIMER_CHANNEL = 22,
/** Timer value larger than RAIL timebase. */
RAIL_ASSERT_FAILED_TIMER_REQUIRES_WRAP = 23,
/** LBT config exceeds EFR32XG1 register size. */
RAIL_ASSERT_FAILED_BASECNTTOP = 24,
/** Deprecated CSMA/LBT retry callback unexpectedly called. */
RAIL_ASSERT_FAILED_DEPRECATED_LBTRETRY = 25,
/** Could not synchronize RAIL timebase with the RTC. */
RAIL_ASSERT_FAILED_RTCC_SYNC_MISSED = 26,
/** Clock source not ready. */
RAIL_ASSERT_FAILED_CLOCK_SOURCE_NOT_READY = 27,
/** Attempted to set RAIL timings to invalid value. */
RAIL_ASSERT_FAILED_TIMINGS_INVALID = 28,
/** NULL was supplied as a RAIL_Handle_t argument. */
RAIL_ASSERT_NULL_HANDLE = 29,
/** Scheduled timer not running. */
RAIL_ASSERT_FAILED_SCHED_TIMER_NOT_RUNNING = 30,
/** API improperly called while protocol inactive. */
RAIL_ASSERT_FAILED_NO_ACTIVE_CONFIG = 31,
/** No active handle after switch. */
RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SWITCH = 32,
/** Reserved for future use. */
RAIL_ASSERT_FAILED_RESERVED33 = 33,
/** No active handle for scheduled rx. */
RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SCHEDRX = 34,
/** Invalid handle for scheduled tx. */
RAIL_ASSERT_FAILED_INVALID_HANDLE_SCHEDTX = 35,
/** Inactive handle for scheduled tx. */
RAIL_ASSERT_FAILED_INACTIVE_HANDLE_SCHEDTX = 36,
/** Invalid config index to switch to. */
RAIL_ASSERT_FAILED_CONFIG_INDEX_INVALID = 37,
/** No active handle for single protocol. */
RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SINGLEPROTOCOL = 38,
/** This function is deprecated and must not be called. */
RAIL_ASSERT_DEPRECATED_FUNCTION = 39,
/** Multiprotocol task started with no event to run. */
RAIL_ASSERT_MULTIPROTOCOL_NO_EVENT = 40,
/** Invalid interrupt enabled. */
RAIL_ASSERT_FAILED_INVALID_INTERRUPT_ENABLED = 41,
/** Power conversion functions called before curves were initialized. */
RAIL_ASSERT_CONVERSION_CURVES_NOT_INITIALIZED = 42,
/** Division by zero. */
RAIL_ASSERT_DIVISION_BY_ZERO = 43,
/** Function cannot be called without access to the hardware. */
RAIL_ASSERT_CANT_USE_HARDWARE = 44,
/** Pointer parameter was passed as NULL. */
RAIL_ASSERT_NULL_PARAMETER = 45,
/** Invalid task type passed to RAIL_SetTaskPriority. */
RAIL_ASSERT_INVALID_TASK_TYPE = 46,
/** Synth radio config buffer for channel hopping too small. */
RAIL_ASSERT_SMALL_SYNTH_RADIO_CONFIG_BUFFER = 47,
/** Buffer provided for RX Channel Hopping is too small. */
RAIL_ASSERT_CHANNEL_HOPPING_BUFFER_TOO_SHORT = 48,
/** Invalid action was attempted on a module. */
RAIL_ASSERT_INVALID_MODULE_ACTION = 49,
/** The radio config for this channel is not compatible with channel hopping. */
RAIL_ASSERT_CHANNEL_HOPPING_INVALID_RADIO_CONFIG = 50,
/** Channel change failed. */
RAIL_ASSERT_CHANNEL_CHANGE_FAILED = 51,
/** Attempted to read invalid register. */
RAIL_ASSERT_INVALID_REGISTER = 52,
/** Can't read register value from NULL state. */
RAIL_ASSERT_FAILED_LO_DIV_NULL_STATE = 53,
/** DMP radio config caching failed. */
RAIL_ASSERT_CACHE_CONFIG_FAILED = 54,
/** NULL was supplied as a RAIL_StateTransitions_t argument. */
RAIL_ASSERT_NULL_TRANSITIONS = 55,
/** LDMA transfer failed. */
RAIL_ASSERT_BAD_LDMA_TRANSFER = 56,
/** Attempted to wake up with invalid RTCC sync data. */
RAIL_ASSERT_INVALID_RTCC_SYNC_VALUES = 57,
/** Radio sequencer hit a fault condition. */
RAIL_ASSERT_SEQUENCER_FAULT = 58,
/** Bus fault. */
RAIL_ASSERT_BUS_ERROR = 59,
/** The current radio config cannot be used with packet filtering. */
RAIL_ASSERT_INVALID_FILTERING_CONFIG = 60,
/** Retiming configuration error. */
RAIL_ASSERT_RETIMING_CONFIG = 61,
/** TX CRC configuration is corrupt. */
RAIL_ASSERT_FAILED_TX_CRC_CONFIG = 62,
/** The current PA config does not allow for this operation. */
RAIL_ASSERT_INVALID_PA_OPERATION = 63,
/** The sequencer selected an invalid PA. */
RAIL_ASSERT_SEQ_INVALID_PA_SELECTED = 64,
/** Invalid/unsupported channel config. */
RAIL_ASSERT_FAILED_INVALID_CHANNEL_CONFIG = 65,
/** The dynamic frame length configuration is invalid. */
RAIL_ASSERT_INVALID_DYNAMIC_FRAME_LENGTH = 66,
/** Failed to enable EM1P energy mode. */
RAIL_ASSERT_FAILED_EM1P_ENTRY = 67,
/** Failed to disable EM1P energy mode. */
RAIL_ASSERT_FAILED_EM1P_EXIT = 68,
/** Failed to disable RTCC synchronization. */
RAIL_ASSERT_FAILED_RTCC_SYNC_STOP = 69,
/** Multitimer linked list corrupted. */
RAIL_ASSERT_FAILED_MULTITIMER_CORRUPT = 70,
/** Unable to configure radio for temperature calibration. */
RAIL_ASSERT_FAILED_TEMPCAL_ERROR = 71,
/** Invalid EFF configuration. */
RAIL_ASSERT_INVALID_EFF_CONFIGURATION = 72,
/** Invalid RFFPLL configuration. */
RAIL_ASSERT_INVALID_RFFPLL_CONFIGURATION = 73,
/** Secure access fault. */
RAIL_ASSERT_SECURE_ACCESS_FAULT = 74,
/** SYSRTC0 not running. */
RAIL_ASSERT_FAILED_SYSRTC0_NOT_RUNNING = 75,
/** Radio Configurator not updated. */
RAIL_ASSERT_RADIO_CONFIG_NOT_UP_TO_DATE = 76,
/** Failed to set the event for configurable RSSI threshold. */
RAIL_ASSERT_FAILED_RSSI_THRESHOLD = 77,
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Self-referencing defines minimize compiler complaints when using RAIL_ENUM
#define RAIL_ASSERT_FAILED_APPENDED_INFO_MISSING ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_APPENDED_INFO_MISSING)
#define RAIL_ASSERT_FAILED_RX_FIFO_BYTES ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RX_FIFO_BYTES)
#define RAIL_ASSERT_FAILED_RX_FIFO_ZERO_BYTES_READ ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RX_FIFO_ZERO_BYTES_READ)
#define RAIL_ASSERT_FAILED_ILLEGAL_RXLEN_ENTRY_STATUS ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_ILLEGAL_RXLEN_ENTRY_STATUS)
#define RAIL_ASSERT_FAILED_BAD_PACKET_LENGTH ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_BAD_PACKET_LENGTH)
#define RAIL_ASSERT_FAILED_SYNTH_DIVCTRL_ENUM_CONVERSION_ERROR ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_SYNTH_DIVCTRL_ENUM_CONVERSION_ERROR)
#define RAIL_ASSERT_FAILED_UNEXPECTED_STATE_RX_FIFO ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_UNEXPECTED_STATE_RX_FIFO)
#define RAIL_ASSERT_FAILED_UNEXPECTED_STATE_RXLEN_FIFO ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_UNEXPECTED_STATE_RXLEN_FIFO)
#define RAIL_ASSERT_FAILED_UNEXPECTED_STATE_TX_FIFO ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_UNEXPECTED_STATE_TX_FIFO)
#define RAIL_ASSERT_FAILED_UNEXPECTED_STATE_TXACK_FIFO ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_UNEXPECTED_STATE_TXACK_FIFO)
#define RAIL_ASSERT_FAILED_PBUFFER_NOT_DEFINED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_PBUFFER_NOT_DEFINED)
#define RAIL_ASSERT_FAILED_INSUFFICIENT_BYTES_IN_RX_PACKET ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_INSUFFICIENT_BYTES_IN_RX_PACKET)
#define RAIL_ASSERT_FAILED_CLOCK_PRESCALER ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_CLOCK_PRESCALER)
#define RAIL_ASSERT_FAILED_RTCC_POST_WAKEUP ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RTCC_POST_WAKEUP)
#define RAIL_ASSERT_FAILED_SYNTH_VCO_FREQUENCY ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_SYNTH_VCO_FREQUENCY)
#define RAIL_ASSERT_FAILED_RAC_STATE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RAC_STATE)
#define RAIL_ASSERT_FAILED_SYNTH_INVALID_VCOCTRL ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_SYNTH_INVALID_VCOCTRL)
#define RAIL_ASSERT_FAILED_NESTED_SEQUENCER_LOCK ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_NESTED_SEQUENCER_LOCK)
#define RAIL_ASSERT_FAILED_RSSI_AVERAGE_DONE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RSSI_AVERAGE_DONE)
#define RAIL_ASSERT_FAILED_DFL_BITS_SIZE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_DFL_BITS_SIZE)
#define RAIL_ASSERT_FAILED_PROTIMER_RANDOM_SEED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_PROTIMER_RANDOM_SEED)
#define RAIL_ASSERT_FAILED_EFR32XG1_REGISTER_SIZE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_EFR32XG1_REGISTER_SIZE)
#define RAIL_ASSERT_FAILED_PROTIMER_CHANNEL ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_PROTIMER_CHANNEL)
#define RAIL_ASSERT_FAILED_TIMER_REQUIRES_WRAP ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_TIMER_REQUIRES_WRAP)
#define RAIL_ASSERT_FAILED_BASECNTTOP ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_BASECNTTOP)
#define RAIL_ASSERT_FAILED_DEPRECATED_LBTRETRY ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_DEPRECATED_LBTRETRY)
#define RAIL_ASSERT_FAILED_RTCC_SYNC_MISSED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RTCC_SYNC_MISSED)
#define RAIL_ASSERT_FAILED_CLOCK_SOURCE_NOT_READY ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_CLOCK_SOURCE_NOT_READY)
#define RAIL_ASSERT_FAILED_TIMINGS_INVALID ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_TIMINGS_INVALID)
#define RAIL_ASSERT_NULL_HANDLE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_NULL_HANDLE)
#define RAIL_ASSERT_FAILED_SCHED_TIMER_NOT_RUNNING ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_SCHED_TIMER_NOT_RUNNING)
#define RAIL_ASSERT_FAILED_NO_ACTIVE_CONFIG ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_NO_ACTIVE_CONFIG)
#define RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SWITCH ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SWITCH)
#define RAIL_ASSERT_FAILED_RESERVED33 ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RESERVED33)
#define RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SCHEDRX ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SCHEDRX)
#define RAIL_ASSERT_FAILED_INVALID_HANDLE_SCHEDTX ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_INVALID_HANDLE_SCHEDTX)
#define RAIL_ASSERT_FAILED_INACTIVE_HANDLE_SCHEDTX ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_INACTIVE_HANDLE_SCHEDTX)
#define RAIL_ASSERT_FAILED_CONFIG_INDEX_INVALID ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_CONFIG_INDEX_INVALID)
#define RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SINGLEPROTOCOL ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_NO_ACTIVE_HANDLE_SINGLEPROTOCOL)
#define RAIL_ASSERT_DEPRECATED_FUNCTION ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_DEPRECATED_FUNCTION)
#define RAIL_ASSERT_MULTIPROTOCOL_NO_EVENT ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_MULTIPROTOCOL_NO_EVENT)
#define RAIL_ASSERT_FAILED_INVALID_INTERRUPT_ENABLED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_INVALID_INTERRUPT_ENABLED)
#define RAIL_ASSERT_CONVERSION_CURVES_NOT_INITIALIZED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_CONVERSION_CURVES_NOT_INITIALIZED)
#define RAIL_ASSERT_DIVISION_BY_ZERO ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_DIVISION_BY_ZERO)
#define RAIL_ASSERT_CANT_USE_HARDWARE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_CANT_USE_HARDWARE)
#define RAIL_ASSERT_NULL_PARAMETER ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_NULL_PARAMETER)
#define RAIL_ASSERT_INVALID_TASK_TYPE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_TASK_TYPE)
#define RAIL_ASSERT_SMALL_SYNTH_RADIO_CONFIG_BUFFER ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_SMALL_SYNTH_RADIO_CONFIG_BUFFER)
#define RAIL_ASSERT_CHANNEL_HOPPING_BUFFER_TOO_SHORT ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_CHANNEL_HOPPING_BUFFER_TOO_SHORT)
#define RAIL_ASSERT_INVALID_MODULE_ACTION ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_MODULE_ACTION)
#define RAIL_ASSERT_CHANNEL_HOPPING_INVALID_RADIO_CONFIG ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_CHANNEL_HOPPING_INVALID_RADIO_CONFIG)
#define RAIL_ASSERT_CHANNEL_CHANGE_FAILED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_CHANNEL_CHANGE_FAILED)
#define RAIL_ASSERT_INVALID_REGISTER ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_REGISTER)
#define RAIL_ASSERT_FAILED_LO_DIV_NULL_STATE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_LO_DIV_NULL_STATE)
#define RAIL_ASSERT_CACHE_CONFIG_FAILED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_CACHE_CONFIG_FAILED)
#define RAIL_ASSERT_NULL_TRANSITIONS ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_NULL_TRANSITIONS)
#define RAIL_ASSERT_BAD_LDMA_TRANSFER ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_BAD_LDMA_TRANSFER)
#define RAIL_ASSERT_INVALID_RTCC_SYNC_VALUES ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_RTCC_SYNC_VALUES)
#define RAIL_ASSERT_SEQUENCER_FAULT ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_SEQUENCER_FAULT)
#define RAIL_ASSERT_BUS_ERROR ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_BUS_ERROR)
#define RAIL_ASSERT_INVALID_FILTERING_CONFIG ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_FILTERING_CONFIG)
#define RAIL_ASSERT_RETIMING_CONFIG ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_RETIMING_CONFIG)
#define RAIL_ASSERT_FAILED_TX_CRC_CONFIG ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_TX_CRC_CONFIG)
#define RAIL_ASSERT_INVALID_PA_OPERATION ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_PA_OPERATION)
#define RAIL_ASSERT_SEQ_INVALID_PA_SELECTED ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_SEQ_INVALID_PA_SELECTED)
#define RAIL_ASSERT_FAILED_INVALID_CHANNEL_CONFIG ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_INVALID_CHANNEL_CONFIG)
#define RAIL_ASSERT_INVALID_DYNAMIC_FRAME_LENGTH ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_DYNAMIC_FRAME_LENGTH)
#define RAIL_ASSERT_FAILED_EM1P_ENTRY ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_EM1P_ENTRY)
#define RAIL_ASSERT_FAILED_EM1P_EXIT ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_EM1P_EXIT)
#define RAIL_ASSERT_FAILED_RTCC_SYNC_STOP ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RTCC_SYNC_STOP)
#define RAIL_ASSERT_FAILED_MULTITIMER_CORRUPT ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_MULTITIMER_CORRUPT)
#define RAIL_ASSERT_FAILED_TEMPCAL_ERROR ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_TEMPCAL_ERROR)
#define RAIL_ASSERT_INVALID_EFF_CONFIGURATION ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_EFF_CONFIGURATION)
#define RAIL_ASSERT_INVALID_RFFPLL_CONFIGURATION ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_INVALID_RFFPLL_CONFIGURATION)
#define RAIL_ASSERT_SECURE_ACCESS_FAULT ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_SECURE_ACCESS_FAULT)
#define RAIL_ASSERT_FAILED_SYSRTC0_NOT_RUNNING ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_SYSRTC0_NOT_RUNNING)
#define RAIL_ASSERT_RADIO_CONFIG_NOT_UP_TO_DATE ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_RADIO_CONFIG_NOT_UP_TO_DATE)
#define RAIL_ASSERT_FAILED_RSSI_THRESHOLD ((RAIL_AssertErrorCodes_t) RAIL_ASSERT_FAILED_RSSI_THRESHOLD)
#endif//DOXYGEN_SHOULD_SKIP_THIS
/// Use this define to create an array of error messages that map to the codes
/// in \ref RAIL_AssertErrorCodes_t. You can use these to print slightly more
/// detailed error strings related to a particular assert error code if desired.
/// For example, you could implement your assert failed callback as follows to
/// make use of this.
///
/// @code{.c}
/// void RAILCb_AssertFailed(RAIL_Handle_t railHandle, uint32_t errorCode)
/// {
/// static const char* railErrorMessages[] = RAIL_ASSERT_ERROR_MESSAGES;
/// const char *errorMessage = "Unknown";
///
/// // If this error code is within the range of known error messages then use
/// // the appropriate error message.
/// if (errorCode < (sizeof(railErrorMessages) / sizeof(char*))) {
/// errorMessage = railErrorMessages[errorCode];
/// }
/// printf(errorMessage);
///
/// // Reset the chip since an assert is a fatal error
/// NVIC_SystemReset();
/// }
/// @endcode
///
#define RAIL_ASSERT_ERROR_MESSAGES { \
/* 0*/ "Appended info missing from Rx packet", \
/* 1*/ "Receive FIFO too small for IR calibration", \
/* 2*/ "Error reading back packet payload", \
/* 3*/ "Receive fifo entry has invalid status", \
/* 4*/ "Receive fifo entry bad packet length", \
/* 5*/ "Unable to configure radio for IR calibration", \
/* 6*/ "Reached unexpected state while handling Rx fifo events", \
/* 7*/ "Reached unexpected state while handling RXLEN fifo events", \
/* 8*/ "Reached unexpected state while handling Tx fifo events", \
/* 9*/ "Reached unexpected state while handling Tx ACK fifo events", \
/*10*/ "No memory to store receive packet", \
/*11*/ "Packet length longer than the receive FIFO size", \
/*12*/ "Invalid radio clock prescaler", \
/*13*/ "Error synchronizing the RAIL timebase after sleep", \
/*14*/ "VCO frequency outside supported range", \
/*15*/ "Radio active while changing channels", \
/*16*/ "Invalid Synth VCOCTRL field calculation", \
/*17*/ "Nested attempt to lock the sequencer", \
/*18*/ "RSSI averaging enabled without a valid callback", \
/*19*/ "Invalid dynamic frame length setting provided (dflBits)", \
/*20*/ "Unable to seed radio pseudo random number generator", \
/*21*/ "Timeout exceeds EFR32XG1 register size", \
/*22*/ "Invalid timer channel specified", \
/*23*/ "Timer value larger than RAIL timebase", \
/*24*/ "LBT config exceeds EFR32XG1 register size", \
/*25*/ "Deprecated CSMA/LBT retry callback unexpectedly called", \
/*26*/ "Could not synchronize RAIL timebase with the RTC", \
/*27*/ "Clock source not ready", \
/*28*/ "Attempted to set RAIL timings to invalid value", \
/*29*/ "NULL was supplied as a RAIL_Handle_t argument", \
/*30*/ "Scheduled timer not running", \
/*31*/ "API improperly called while protocol inactive", \
/*32*/ "No active handle after switch", \
/*33*/ "Reserved for future use", \
/*34*/ "No active handle for scheduled rx", \
/*35*/ "Invalid handle for scheduled tx", \
/*36*/ "Inactive handle for scheduled tx", \
/*37*/ "Invalid config index to switch to", \
/*38*/ "No active handle for single protocol", \
/*39*/ "This function is deprecated and must not be called", \
/*40*/ "Multiprotocol task started with no event to run", \
/*41*/ "Invalid interrupt enabled", \
/*42*/ "Power conversion functions called before curves were initialized", \
/*43*/ "Division by zero", \
/*44*/ "Function cannot be called without access to the hardware", \
/*45*/ "Pointer parameter was passed as NULL", \
/*46*/ "Invalid task type passed to RAIL_SetTaskPriority", \
/*47*/ "Synth radio config buffer for channel hopping too small", \
/*48*/ "Buffer provided for RX Channel Hopping is too small", \
/*49*/ "Invalid action was attempted on a module", \
/*50*/ "The radio config for this channel is not compatible with channel hopping", \
/*51*/ "Channel change failed", \
/*52*/ "Attempted to read invalid register", \
/*53*/ "Can't read register value from NULL state", \
/*54*/ "DMP radio config caching failed", \
/*55*/ "NULL was supplied as a RAIL_StateTransitions_t argument", \
/*56*/ "LDMA transfer failed", \
/*57*/ "Attempted to wake up with invalid RTCC sync data", \
/*58*/ "Radio sequencer hit a fault condition", \
/*59*/ "Bus fault", \
/*60*/ "The current radio config cannot be used with packet filtering", \
/*61*/ "Retiming configuration error", \
/*62*/ "TX CRC configuration is corrupt", \
/*63*/ "The current PA config does not allow for this operation", \
/*64*/ "The sequencer selected an invalid PA", \
/*65*/ "Invalid/unsupported channel config", \
/*66*/ "The dynamic frame length configuration is invalid", \
/*67*/ "Failed to enable EM1P energy mode", \
/*68*/ "Failed to disable EM1P energy mode", \
/*69*/ "Failed to disable RTCC synchronization", \
/*70*/ "Multitimer linked list corrupted", \
/*71*/ "Unable to configure radio for temperature calibration", \
/*72*/ "Invalid EFF configuration", \
/*73*/ "Invalid RFFPLL configuration", \
/*74*/ "Secure access fault", \
/*75*/ "SYSRTC0 not running", \
/*76*/ "Radio Configurator not updated", \
/*77*/ "Failed to set the event for configurable RSSI threshold", \
}
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif // __RAIL_ASSERT_ERROR_CODES_H__

View File

@ -0,0 +1,719 @@
/***************************************************************************//**
* @file
* @brief Auxiliary header for the RAIL library. Includes consistent definitions
* of features available across different chips.
*******************************************************************************
* # 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 __RAIL_FEATURES_H__
#define __RAIL_FEATURES_H__
#include "em_device.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup RAIL_API RAIL API
* @{
*/
/******************************************************************************
* RAIL Features
*****************************************************************************/
/**
* @addtogroup Features
* @brief Overview of support for various features across hardware platforms.
* These defines can be used at compile time to determine which
* features are available on your platform. However, keep in mind that
* these defines hold true for chip families. Your specific part
* may have further restrictions (band limitations, power amplifier
* restrictions, and so on) on top of those listed below, for which
* runtime RAIL_Supports*() APIs can be used to check availability
* on a particular chip (after \ref RAIL_Init() has been called).
* In general, an attempt to call an API that is not supported on your
* chip family as listed below will result in a
* \ref RAIL_STATUS_INVALID_CALL.
* @{
*/
/// Boolean to indicate whether the selected chip supports both SubGHz and 2.4 GHz bands.
/// See also runtime refinement \ref RAIL_SupportsDualBand().
#if ((_SILICON_LABS_EFR32_RADIO_TYPE == _SILICON_LABS_EFR32_RADIO_DUALBAND) \
|| ((FEAT_RF_2G4 == 1) && (FEAT_RF_SUBG == 1)))
#define RAIL_SUPPORTS_DUAL_BAND 1
#else
#define RAIL_SUPPORTS_DUAL_BAND 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_DUAL_BAND.
#define RAIL_FEAT_DUAL_BAND_RADIO RAIL_SUPPORTS_DUAL_BAND
/// Boolean to indicate whether the selected chip supports the 2.4 GHz band.
/// See also runtime refinement \ref RAIL_Supports2p4GHzBand().
#if (((_SILICON_LABS_EFR32_RADIO_TYPE == _SILICON_LABS_EFR32_RADIO_DUALBAND) \
|| (_SILICON_LABS_EFR32_RADIO_TYPE == _SILICON_LABS_EFR32_RADIO_2G4HZ)) \
|| (FEAT_RF_2G4 == 1))
#define RAIL_SUPPORTS_2P4GHZ_BAND 1
#else
#define RAIL_SUPPORTS_2P4GHZ_BAND 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_2P4GHZ_BAND.
#define RAIL_FEAT_2G4_RADIO RAIL_SUPPORTS_2P4GHZ_BAND
/// Boolean to indicate whether the selected chip supports SubGHz bands.
/// See also runtime refinement \ref RAIL_SupportsSubGHzBand().
#if (((_SILICON_LABS_EFR32_RADIO_TYPE == _SILICON_LABS_EFR32_RADIO_DUALBAND) \
|| (_SILICON_LABS_EFR32_RADIO_TYPE == _SILICON_LABS_EFR32_RADIO_SUBGHZ)) \
|| (FEAT_RF_SUBG == 1))
#define RAIL_SUPPORTS_SUBGHZ_BAND 1
#else
#define RAIL_SUPPORTS_SUBGHZ_BAND 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_SUBGHZ_BAND.
#define RAIL_FEAT_SUBGIG_RADIO RAIL_SUPPORTS_SUBGHZ_BAND
/// Boolean to indicate whether the selected chip supports OFDM PA.
/// See also runtime refinement \ref RAIL_SupportsOFDMPA().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 5)
#define RAIL_SUPPORTS_OFDM_PA 1
#else
#define RAIL_SUPPORTS_OFDM_PA 0
#endif
/// Boolean to indicate whether the selected chip supports
/// bit masked address filtering.
/// See also runtime refinement \ref RAIL_SupportsAddrFilterAddressBitMask().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG >= 2)
#define RAIL_SUPPORTS_ADDR_FILTER_ADDRESS_BIT_MASK 1
#else
#define RAIL_SUPPORTS_ADDR_FILTER_ADDRESS_BIT_MASK 0
#endif
/// Boolean to indicate whether the selected chip supports
/// address filter mask information for incoming packets in
/// \ref RAIL_RxPacketInfo_t::filterMask and
/// \ref RAIL_IEEE802154_Address_t::filterMask.
/// See also runtime refinement \ref RAIL_SupportsAddrFilterMask().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_SUPPORTS_ADDR_FILTER_MASK 1
#else
#define RAIL_SUPPORTS_ADDR_FILTER_MASK 0
#endif
/// Boolean to indicate whether the selected chip supports
/// alternate power settings for the Power Amplifier.
/// See also runtime refinement \ref RAIL_SupportsAlternateTxPower().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG > 1) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 3)
#define RAIL_SUPPORTS_ALTERNATE_TX_POWER 1
#else
#define RAIL_SUPPORTS_ALTERNATE_TX_POWER 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_ALTERNATE_TX_POWER.
#define RAIL_FEAT_ALTERNATE_POWER_TX_SUPPORTED RAIL_SUPPORTS_ALTERNATE_TX_POWER
/// Boolean to indicate whether the selected chip supports antenna diversity.
/// See also runtime refinement \ref RAIL_SupportsAntennaDiversity().
#if ((_SILICON_LABS_32B_SERIES_1_CONFIG >= 2) \
|| (_SILICON_LABS_32B_SERIES == 2))
#define RAIL_SUPPORTS_ANTENNA_DIVERSITY 1
#else
#define RAIL_SUPPORTS_ANTENNA_DIVERSITY 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_ANTENNA_DIVERSITY.
#define RAIL_FEAT_ANTENNA_DIVERSITY RAIL_SUPPORTS_ANTENNA_DIVERSITY
/// Boolean to indicate whether the selected chip supports path diversity.
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 3)
#define RAIL_SUPPORTS_PATH_DIVERSITY 1
#else
#define RAIL_SUPPORTS_PATH_DIVERSITY 0
#endif
/// Boolean to indicate whether the selected chip supports channel hopping.
/// See also runtime refinement \ref RAIL_SupportsChannelHopping().
#if ((_SILICON_LABS_32B_SERIES_1_CONFIG >= 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG >= 1))
#define RAIL_SUPPORTS_CHANNEL_HOPPING 1
#else
#define RAIL_SUPPORTS_CHANNEL_HOPPING 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_CHANNEL_HOPPING.
#define RAIL_FEAT_CHANNEL_HOPPING RAIL_SUPPORTS_CHANNEL_HOPPING
/// Boolean to indicate whether the selected chip supports dual sync words.
/// See also runtime refinement \ref RAIL_SupportsDualSyncWords().
#if 1
#define RAIL_SUPPORTS_DUAL_SYNC_WORDS 1
#else
#define RAIL_SUPPORTS_DUAL_SYNC_WORDS 0
#endif
/// Boolean to indicate whether the selected chip supports automatic transitions
/// from TX to TX.
/// See also runtime refinement \ref RAIL_SupportsTxToTx().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_SUPPORTS_TX_TO_TX 1
#else
#define RAIL_SUPPORTS_TX_TO_TX 0
#endif
/// Boolean to indicate whether the selected chip supports thermistor measurements.
/// See also runtime refinement \ref RAIL_SupportsExternalThermistor().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 3) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 5) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_SUPPORTS_EXTERNAL_THERMISTOR 1
#else
#define RAIL_SUPPORTS_EXTERNAL_THERMISTOR 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_EXTERNAL_THERMISTOR.
#define RAIL_FEAT_EXTERNAL_THERMISTOR RAIL_SUPPORTS_EXTERNAL_THERMISTOR
/// Boolean to indicate whether the selected chip supports AUXADC measurements.
/// See also runtime refinement \ref RAIL_SupportsAuxAdc().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 3) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 5) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_SUPPORTS_AUXADC 1
#else
#define RAIL_SUPPORTS_AUXADC 0
#endif
/// Boolean to indicate whether the selected chip supports a high-precision
/// LFRCO.
/// Best to use the runtime refinement \ref RAIL_SupportsPrecisionLFRCO()
/// because some chip revisions do not support it.
#if ((_SILICON_LABS_32B_SERIES_1_CONFIG == 3) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_SUPPORTS_PRECISION_LFRCO 1
#else
#define RAIL_SUPPORTS_PRECISION_LFRCO 0
#endif
/// Boolean to indicate whether the selected chip supports radio entropy.
/// See also runtime refinement \ref RAIL_SupportsRadioEntropy().
#if 1
#define RAIL_SUPPORTS_RADIO_ENTROPY 1
#else
#define RAIL_SUPPORTS_RADIO_ENTROPY 0
#endif
/// Boolean to indicate whether the selected chip supports
/// RFSENSE Energy Detection Mode.
/// See also runtime refinement \ref RAIL_SupportsRfSenseEnergyDetection().
#if ((_SILICON_LABS_32B_SERIES == 1) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_SUPPORTS_RFSENSE_ENERGY_DETECTION 1
#else
#define RAIL_SUPPORTS_RFSENSE_ENERGY_DETECTION 0
#endif
/// Boolean to indicate whether the selected chip supports
/// RFSENSE Selective(OOK) Mode.
/// See also runtime refinement \ref RAIL_SupportsRfSenseSelectiveOok().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_SUPPORTS_RFSENSE_SELECTIVE_OOK 1
#else
#define RAIL_SUPPORTS_RFSENSE_SELECTIVE_OOK 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_RFSENSE_SELECTIVE_OOK.
#define RAIL_FEAT_RFSENSE_SELECTIVE_OOK_MODE_SUPPORTED \
RAIL_SUPPORTS_RFSENSE_SELECTIVE_OOK
/// Boolean to indicate whether the selected chip supports the Energy Friendly
/// Front End Module (EFF).
/// See also runtime refinement \ref RAIL_SupportsEff().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 5)
#define RAIL_SUPPORTS_EFF 1
#else
#define RAIL_SUPPORTS_EFF 0
#endif
// BLE features
// Some features may not be available on all platforms
// due to radio hardware limitations.
/// Boolean to indicate whether the selected chip supports BLE.
/// See also runtime refinement \ref RAIL_SupportsProtocolBLE().
#if 1
#define RAIL_SUPPORTS_PROTOCOL_BLE RAIL_SUPPORTS_2P4GHZ_BAND
#else
#define RAIL_SUPPORTS_PROTOCOL_BLE 0
#endif
/// Boolean to indicate whether the selected chip supports BLE 1Mbps
/// Non-Viterbi PHY.
/// See also runtime refinement \ref RAIL_BLE_Supports1MbpsNonViterbi().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG >= 1)
#define RAIL_BLE_SUPPORTS_1MBPS_NON_VITERBI RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_1MBPS_NON_VITERBI 0
#endif
/// Boolean to indicate whether the selected chip supports BLE 1Mbps Viterbi
/// PHY.
/// See also runtime refinement \ref RAIL_BLE_Supports1MbpsViterbi().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_BLE_SUPPORTS_1MBPS_VITERBI RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_1MBPS_VITERBI 0
#endif
/// Boolean to indicate whether the selected chip supports BLE 1Mbps operation.
/// See also runtime refinement \ref RAIL_BLE_Supports1Mbps().
#define RAIL_BLE_SUPPORTS_1MBPS \
(RAIL_BLE_SUPPORTS_1MBPS_NON_VITERBI || RAIL_BLE_SUPPORTS_1MBPS_VITERBI)
/// Boolean to indicate whether the selected chip supports BLE 2Mbps
/// Non-Viterbi PHY.
/// See also runtime refinement \ref RAIL_BLE_Supports2MbpsNonViterbi().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG >= 2)
#define RAIL_BLE_SUPPORTS_2MBPS_NON_VITERBI RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_2MBPS_NON_VITERBI 0
#endif
/// Boolean to indicate whether the selected chip supports BLE 2Mbps Viterbi
/// PHY.
/// See also runtime refinement \ref RAIL_BLE_Supports2MbpsViterbi().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_BLE_SUPPORTS_2MBPS_VITERBI RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_2MBPS_VITERBI 0
#endif
/// Boolean to indicate whether the selected chip supports BLE 2Mbps operation.
/// See also runtime refinement \ref RAIL_BLE_Supports2Mbps().
#define RAIL_BLE_SUPPORTS_2MBPS \
(RAIL_BLE_SUPPORTS_2MBPS_NON_VITERBI || RAIL_BLE_SUPPORTS_2MBPS_VITERBI)
/// Boolean to indicate whether the selected chip supports BLE
/// Antenna Switching needed for Angle-of-Arrival receives or
/// Angle-of-Departure transmits.
/// See also runtime refinement \ref RAIL_BLE_SupportsAntennaSwitching().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 4) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_BLE_SUPPORTS_ANTENNA_SWITCHING RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_ANTENNA_SWITCHING 0
#endif
/// Boolean to indicate whether the selected chip supports the BLE Coded PHY
/// used for Long-Range.
/// See also runtime refinement \ref RAIL_BLE_SupportsCodedPhy().
#if ((_SILICON_LABS_32B_SERIES_1_CONFIG == 3) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 1) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 2) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 4) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_BLE_SUPPORTS_CODED_PHY RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_CODED_PHY 0
#endif
/// Backwards-compatible synonym of \ref RAIL_BLE_SUPPORTS_CODED_PHY.
#define RAIL_FEAT_BLE_CODED RAIL_BLE_SUPPORTS_CODED_PHY
/// Boolean to indicate whether the selected chip supports the BLE Simulscan PHY
/// used for simultaneous BLE 1Mbps and Coded PHY reception.
/// See also runtime refinement \ref RAIL_BLE_SupportsSimulscanPhy().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 4) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_BLE_SUPPORTS_SIMULSCAN_PHY RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_SIMULSCAN_PHY 0
#endif
/// Boolean to indicate whether the selected chip supports BLE
/// CTE (Constant Tone Extension) needed for Angle-of-Arrival/Departure
/// transmits.
/// See also runtime refinement \ref RAIL_BLE_SupportsCte().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 4) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_BLE_SUPPORTS_CTE RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_CTE 0
#endif
/// Boolean to indicate whether the selected chip supports the
/// Quuppa PHY.
/// See also runtime refinement \ref RAIL_BLE_SupportsQuuppa().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_BLE_SUPPORTS_QUUPPA RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_QUUPPA 0
#endif
/// Boolean to indicate whether the selected chip supports BLE
/// IQ Sampling needed for Angle-of-Arrival/Departure receives.
/// See also runtime refinement \ref RAIL_BLE_SupportsIQSampling().
#if ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 4) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
#define RAIL_BLE_SUPPORTS_IQ_SAMPLING RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_IQ_SAMPLING 0
#endif
/// Boolean to indicate whether the selected chip supports some BLE AOX
/// features.
#define RAIL_BLE_SUPPORTS_AOX \
(RAIL_BLE_SUPPORTS_ANTENNA_SWITCHING \
|| RAIL_BLE_SUPPORTS_IQ_SAMPLING \
|| RAIL_BLE_SUPPORTS_CTE)
/// Backwards-compatible synonym of \ref RAIL_BLE_SUPPORTS_AOX
#define RAIL_FEAT_BLE_AOX_SUPPORTED RAIL_BLE_SUPPORTS_AOX
/// Boolean to indicate whether the selected chip supports BLE PHY switch to RX
/// functionality, which is used to switch BLE PHYs at a specific time
/// to receive auxiliary packets.
/// See also runtime refinement \ref RAIL_BLE_SupportsPhySwitchToRx().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_BLE_SUPPORTS_PHY_SWITCH_TO_RX RAIL_SUPPORTS_PROTOCOL_BLE
#else
#define RAIL_BLE_SUPPORTS_PHY_SWITCH_TO_RX 0
#endif
/// Backwards-compatible synonym of \ref RAIL_BLE_SUPPORTS_PHY_SWITCH_TO_RX.
#define RAIL_FEAT_BLE_PHY_SWITCH_TO_RX RAIL_BLE_SUPPORTS_PHY_SWITCH_TO_RX
// IEEE 802.15.4 features
// Some features may not be available on all platforms
// due to radio hardware limitations.
/// Boolean to indicate whether the selected chip supports IEEE 802.15.4.
/// See also runtime refinement \ref RAIL_SupportsProtocolIEEE802154().
#if 1
#define RAIL_SUPPORTS_PROTOCOL_IEEE802154 1
#else
#define RAIL_SUPPORTS_PROTOCOL_IEEE802154 0
#endif
/// Boolean to indicate whether the selected chip supports the
/// 802.15.4 Wi-Fi Coexistence PHY.
/// See also runtime refinement \ref RAIL_IEEE802154_SupportsCoexPhy().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG > 1)
#define RAIL_IEEE802154_SUPPORTS_COEX_PHY (RAIL_SUPPORTS_PROTOCOL_IEEE802154 && RAIL_SUPPORTS_2P4GHZ_BAND)
#else
#define RAIL_IEEE802154_SUPPORTS_COEX_PHY 0
#endif
/// Backwards-compatible synonym of \ref RAIL_IEEE802154_SUPPORTS_COEX_PHY.
#define RAIL_FEAT_802154_COEX_PHY RAIL_IEEE802154_SUPPORTS_COEX_PHY
/// Boolean to indicate whether the selected chip supports a front end module.
/// See also runtime refinement \ref RAIL_IEEE802154_SupportsFemPhy().
#define RAIL_IEEE802154_SUPPORTS_FEM_PHY (RAIL_SUPPORTS_PROTOCOL_IEEE802154 && RAIL_SUPPORTS_2P4GHZ_BAND)
/// Boolean to indicate whether the selected chip supports
/// IEEE 802.15.4E-2012 feature subset needed for Zigbee R22 GB868.
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsESubsetGB868().
#if 1
#define RAIL_IEEE802154_SUPPORTS_E_SUBSET_GB868 RAIL_SUPPORTS_PROTOCOL_IEEE802154
#else
#define RAIL_IEEE802154_SUPPORTS_E_SUBSET_GB868 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_E_SUBSET_GB868.
#define RAIL_FEAT_IEEE802154_E_GB868_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_E_SUBSET_GB868
/// Boolean to indicate whether the selected chip supports
/// IEEE 802.15.4E-2012 Enhanced ACKing.
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsEEnhancedAck().
#if 1
#define RAIL_IEEE802154_SUPPORTS_E_ENHANCED_ACK RAIL_IEEE802154_SUPPORTS_E_SUBSET_GB868
#else
#define RAIL_IEEE802154_SUPPORTS_E_ENHANCED_ACK 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_E_ENHANCED_ACK.
#define RAIL_FEAT_IEEE802154_E_ENH_ACK_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_E_ENHANCED_ACK
/// Boolean to indicate whether the selected chip supports
/// receiving IEEE 802.15.4E-2012 Multipurpose frames.
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsEMultipurposeFrames().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_IEEE802154_SUPPORTS_E_MULTIPURPOSE_FRAMES RAIL_IEEE802154_SUPPORTS_E_SUBSET_GB868
#else
#define RAIL_IEEE802154_SUPPORTS_E_MULTIPURPOSE_FRAMES 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_E_MULTIPURPOSE_FRAMES.
#define RAIL_FEAT_IEEE802154_MULTIPURPOSE_FRAME_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_E_MULTIPURPOSE_FRAMES
/// Boolean to indicate whether the selected chip supports
/// IEEE 802.15.4G-2012 feature subset needed for Zigbee R22 GB868.
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsGSubsetGB868().
#if 1
#define RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868 \
(RAIL_SUPPORTS_PROTOCOL_IEEE802154 && RAIL_SUPPORTS_SUBGHZ_BAND)
#else
#define RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868.
#define RAIL_FEAT_IEEE802154_G_GB868_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868
/// Boolean to indicate whether the selected chip supports
/// dynamic FEC
#if (_SILICON_LABS_32B_SERIES_2_CONFIG > 1)
#define RAIL_IEEE802154_SUPPORTS_G_DYNFEC \
RAIL_FEAT_IEEE802154_G_GB868_SUPPORTED // limit to SUBGHZ for now
#else
#define RAIL_IEEE802154_SUPPORTS_G_DYNFEC 0
#endif
/// Boolean to indicate whether the selected chip supports
/// Wi-SUN mode switching
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsGModeSwitch().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 5)
#define RAIL_IEEE802154_SUPPORTS_G_MODESWITCH \
RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868 // limit to SUBGHZ for now
#else
#define RAIL_IEEE802154_SUPPORTS_G_MODESWITCH 0
#endif
/// Boolean to indicate whether the selected chip supports
/// IEEE 802.15.4G-2012 reception and transmission of frames
/// with 4-byte CRC.
/// See also runtime refinement \ref RAIL_IEEE802154_SupportsG4ByteCrc().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_IEEE802154_SUPPORTS_G_4BYTE_CRC RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868
#else
#define RAIL_IEEE802154_SUPPORTS_G_4BYTE_CRC 0
#endif
/// Backwards-compatible synonym of \ref RAIL_IEEE802154_SUPPORTS_G_4BYTE_CRC.
#define RAIL_FEAT_IEEE802154_G_4BYTE_CRC_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_G_4BYTE_CRC
/// Boolean to indicate whether the selected chip supports
/// IEEE 802.15.4G-2012 reception of unwhitened frames.
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsGUnwhitenedRx().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_RX RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868
#else
#define RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_RX 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_RX.
#define RAIL_FEAT_IEEE802154_G_UNWHITENED_RX_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_RX
/// Boolean to indicate whether the selected chip supports
/// IEEE 802.15.4G-2012 transmission of unwhitened frames.
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsGUnwhitenedTx().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG != 1)
#define RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_TX RAIL_IEEE802154_SUPPORTS_G_SUBSET_GB868
#else
#define RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_TX 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_TX.
#define RAIL_FEAT_IEEE802154_G_UNWHITENED_TX_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_G_UNWHITENED_TX
/// Boolean to indicate whether the selected chip supports
/// canceling the frame-pending lookup event
/// \ref RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND
/// when the radio transitions to a state that renders the
/// the reporting of this event moot (i.e., too late for
/// the stack to influence the outgoing ACK).
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsCancelFramePendingLookup().
#if 1
#define RAIL_IEEE802154_SUPPORTS_CANCEL_FRAME_PENDING_LOOKUP RAIL_SUPPORTS_PROTOCOL_IEEE802154
#else
#define RAIL_IEEE802154_SUPPORTS_CANCEL_FRAME_PENDING_LOOKUP 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_CANCEL_FRAME_PENDING_LOOKUP.
#define RAIL_FEAT_IEEE802154_CANCEL_FP_LOOKUP_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_CANCEL_FRAME_PENDING_LOOKUP
/// Boolean to indicate whether the selected chip supports
/// early triggering of the frame-pending lookup event
/// \ref RAIL_EVENT_IEEE802154_DATA_REQUEST_COMMAND
/// just after MAC address fields have been received.
/// See also runtime refinement \ref
/// RAIL_IEEE802154_SupportsEarlyFramePendingLookup().
#if 1
#define RAIL_IEEE802154_SUPPORTS_EARLY_FRAME_PENDING_LOOKUP RAIL_SUPPORTS_PROTOCOL_IEEE802154
#else
#define RAIL_IEEE802154_SUPPORTS_EARLY_FRAME_PENDING_LOOKUP 0
#endif
/// Backwards-compatible synonym of \ref
/// RAIL_IEEE802154_SUPPORTS_EARLY_FRAME_PENDING_LOOKUP.
#define RAIL_FEAT_IEEE802154_EARLY_FP_LOOKUP_SUPPORTED \
RAIL_IEEE802154_SUPPORTS_EARLY_FRAME_PENDING_LOOKUP
/// Boolean to indicate whether the selected chip supports dual PA configs for mode switch
/// or concurrent mode.
/// See also runtime refinement \ref RAIL_IEEE802154_SupportsDualPaConfig().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 5)
#define RAIL_IEEE802154_SUPPORTS_DUAL_PA_CONFIG 1
#else
#define RAIL_IEEE802154_SUPPORTS_DUAL_PA_CONFIG 0
#endif
/// Boolean to indicate whether the selected chip supports IEEE 802.15.4 PHY
/// with custom settings
#if ((_SILICON_LABS_32B_SERIES_1_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_1_CONFIG == 3))
#define RAIL_IEEE802154_SUPPORTS_CUSTOM1_PHY (RAIL_SUPPORTS_PROTOCOL_IEEE802154 && RAIL_SUPPORTS_2P4GHZ_BAND)
#else
#define RAIL_IEEE802154_SUPPORTS_CUSTOM1_PHY 0
#endif
// Z-Wave features
// Some features may not be available on all platforms
// due to radio hardware limitations.
/// Boolean to indicate whether the selected chip supports Z-Wave.
/// See also runtime refinement \ref RAIL_SupportsProtocolZWave().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG >= 3) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 3)
#define RAIL_SUPPORTS_PROTOCOL_ZWAVE RAIL_SUPPORTS_SUBGHZ_BAND
#else
#define RAIL_SUPPORTS_PROTOCOL_ZWAVE 0
#endif
/// Backwards-compatible synonym of \ref RAIL_SUPPORTS_PROTOCOL_ZWAVE.
#define RAIL_FEAT_ZWAVE_SUPPORTED RAIL_SUPPORTS_PROTOCOL_ZWAVE
/// Boolean to indicate whether the selected chip supports energy detect PHY.
/// See also runtime refinement \ref RAIL_ZWAVE_SupportsEnergyDetectPhy().
#if (_SILICON_LABS_32B_SERIES_1_CONFIG >= 3)
#define RAIL_ZWAVE_SUPPORTS_ED_PHY RAIL_SUPPORTS_PROTOCOL_ZWAVE
#else
#define RAIL_ZWAVE_SUPPORTS_ED_PHY 0
#endif
/// Boolean to indicate whether the selected chip supports concurrent PHY.
/// See also runtime refinement \ref RAIL_ZWAVE_SupportsConcPhy().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 3)
#define RAIL_ZWAVE_SUPPORTS_CONC_PHY RAIL_SUPPORTS_PROTOCOL_ZWAVE
#else
#define RAIL_ZWAVE_SUPPORTS_CONC_PHY 0
#endif
/// Boolean to indicate whether the selected chip supports SQ-based PHY.
/// See also runtime refinement \ref RAIL_SupportsSQPhy().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 3) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 4) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 5)
#define RAIL_SUPPORTS_SQ_PHY 1
#else
#define RAIL_SUPPORTS_SQ_PHY 0
#endif
/// Boolean to indicate whether the code supports Z-Wave
/// region information in PTI and
/// newer RAIL_ZWAVE_RegionConfig_t structure
/// See also runtime refinement \ref RAIL_ZWAVE_SupportsRegionPti().
#if 1
#define RAIL_ZWAVE_SUPPORTS_REGION_PTI RAIL_SUPPORTS_PROTOCOL_ZWAVE
#else
#define RAIL_ZWAVE_SUPPORTS_REGION_PTI 0
#endif
/// Backwards-compatible synonym of \ref RAIL_ZWAVE_SUPPORTS_REGION_PTI.
#define RAIL_FEAT_ZWAVE_REGION_PTI RAIL_ZWAVE_SUPPORTS_REGION_PTI
/// Boolean to indicate whether the selected chip supports raw RX data
/// sources other than \ref RAIL_RxDataSource_t::RX_PACKET_DATA.
/// See also runtime refinement \ref RAIL_SupportsRxRawData().
#if 1
#define RAIL_SUPPORTS_RX_RAW_DATA 1
#else
#define RAIL_SUPPORTS_RX_RAW_DATA 0
#endif
/// Boolean to indicate whether the selected chip supports
/// direct mode.
/// See also runtime refinement \ref RAIL_SupportsDirectMode().
#if ((_SILICON_LABS_32B_SERIES == 1) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 3))
#define RAIL_SUPPORTS_DIRECT_MODE 1
#else
#define RAIL_SUPPORTS_DIRECT_MODE 0
#endif
/// Boolean to indicate whether the selected chip supports
/// RX direct mode data to FIFO.
/// See also runtime refinement \ref RAIL_SupportsRxDirectModeDataToFifo().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 3)
#define RAIL_SUPPORTS_RX_DIRECT_MODE_DATA_TO_FIFO 1
#else
#define RAIL_SUPPORTS_RX_DIRECT_MODE_DATA_TO_FIFO 0
#endif
/// Boolean to indicate whether the selected chip supports
/// MFM protocol.
/// See also runtime refinement \ref RAIL_SupportsMfm().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 3)
#define RAIL_SUPPORTS_MFM 1
#else
#define RAIL_SUPPORTS_MFM 0
#endif
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 4)
/// Boolean to indicate whether the selected chip supports
/// 802.15.4 signal detection
#define RAIL_IEEE802154_SUPPORTS_SIGNAL_IDENTIFIER (RAIL_SUPPORTS_PROTOCOL_IEEE802154)
/// Boolean to indicate whether the selected chip supports
/// BLE signal detection
#define RAIL_BLE_SUPPORTS_SIGNAL_IDENTIFIER (RAIL_SUPPORTS_PROTOCOL_BLE)
#else
/// Boolean to indicate whether the selected chip supports
/// 802.15.4 signal detection
#define RAIL_IEEE802154_SUPPORTS_SIGNAL_IDENTIFIER 0
/// Boolean to indicate whether the selected chip supports
/// BLE signal detection
#define RAIL_BLE_SUPPORTS_SIGNAL_IDENTIFIER 0
#endif
/// Boolean to indicate whether the selected chip supports
/// configurable RSSI threshold set by \ref RAIL_SetRssiDetectThreshold().
#if (_SILICON_LABS_32B_SERIES_2_CONFIG == 3) \
|| (_SILICON_LABS_32B_SERIES_2_CONFIG == 5)
#define RAIL_SUPPORTS_RSSI_DETECT_THRESHOLD (1U)
#else
#define RAIL_SUPPORTS_RSSI_DETECT_THRESHOLD (0U)
#endif
/** @} */ // end of group Features
/** @} */ // end of group RAIL_API
#ifdef __cplusplus
}
#endif
#endif // __RAIL_FEATURES_H__

View File

@ -0,0 +1,193 @@
/***************************************************************************//**
* @file
* @brief The MFM specific header file for the RAIL library.
*******************************************************************************
* # 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 __RAIL_MFM_H__
#define __RAIL_MFM_H__
#include "rail_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/// @addtogroup MFM Multi-Level Frequency Modulation
/// @ingroup Protocol_Specific
/// @brief MFM configuration routines
/// Note that this feature is only supported on EFR32xG23 devices.
///
/// This feature can be used to directly control the TX interpolation filter
/// input to allow for a more flexible frequency modulation scheme than the
/// standard MODEM. When doing this, the MFM buffer is treated as an array
/// of 8-bit signed data used as normalized frequency deviation to the SYNTH
/// frequency to directly control the interpolation filter input.
/// No support for frame handling, coding, nor shaping is supported.
/// Only compatible with FSK modulations.
///
/// The functions in this group configure RAIL Multi-Level Frequency Modulation (MFM)
/// hardware acceleration features.
///
/// To configure MFM functionality, the application must first set up
/// a RAIL instance with \ref RAIL_Init() and other setup functions.
/// Before enabling MFM, a ping-pong buffer (called buffer0 and buffer1
/// below) must be configured via \ref RAIL_SetMfmPingPongFifo() and
/// populated with the initial buffer content.
/// MFM is enabled by setting \ref RAIL_TxDataSource_t::TX_MFM_DATA using
/// \ref RAIL_ConfigData() and is activated when transmit is started by
/// \ref RAIL_StartTx(). Once transmitting the data in the ping-pong buffers,
/// RAIL will manage them so it looks like a continuous transmission to the
/// receiver. Every time one of the ping-ping buffers has been transmitted,
/// \ref RAIL_EVENT_MFM_TX_BUFFER_DONE is triggered so the application can
/// update the data in that buffer without the need to start/stop the
/// transmission. \ref RAIL_EVENT_MFM_TX_BUFFER_DONE can be enable with \ref
/// RAIL_ConfigEvents().
/// Use \ref RAIL_StopTx() to finish transmitting.
///
/// @code{.c}
///
/// uint8_t txCount = 0;
///
/// typedef struct RAIL_MFM_Config_App {
/// RAIL_MFM_PingPongBufferConfig_t buffer;
/// RAIL_StateTiming_t timings;
/// } RAIL_MFM_Config_App_t;
///
/// // Main RAIL_EVENT callback
/// static void RAILCb_Event(RAIL_Handle_t railHandle, RAIL_Events_t events)
/// {
/// // Increment TX counter
/// if (events & RAIL_EVENT_MFM_BUF_DONE) {
/// txCount++;
/// return;
/// }
/// }
/// }
///
/// static const RAIL_MFM_Config_App_t mfmConfig = {
/// .buffer = {
/// .pBuffer0 = (&channelHoppingBufferSpace[0]),
/// .pBuffer1 = (&channelHoppingBufferSpace[MFM_RAW_BUF_SZ_BYTES / 4]),
/// .bufferSizeWords = (MFM_RAW_BUF_SZ_BYTES / 4)
/// },
/// .timings = {
/// .idleToTx = 100,
/// .idleToRx = 0,
/// .rxToTx = 0,
/// .txToRx = 0,
/// .rxSearchTimeout = 0,
/// .txToRxSearchTimeout = 0
/// };
///
/// RAIL_Status_t mfmInit(void)
/// {
/// // initialize MFM
/// uint32_t idx;
/// uint32_t *pDst0 = mfmConfig.pBuffer0;
/// uint32_t *pDst1 = mfmConfig.pBuffer1;
/// RAIL_Status_t status;
/// for (idx = 0; idx < (MFM_RAW_BUF_SZ_BYTES / 16); idx++) {
/// pDst0[4 * idx + 0] = 0x755A3100;
/// pDst1[4 * idx + 0] = 0x755A3100;
/// pDst0[4 * idx + 1] = 0x315A757F;
/// pDst1[4 * idx + 1] = 0x315A757F;
/// pDst0[4 * idx + 2] = 0x8BA6CF00;
/// pDst1[4 * idx + 2] = 0x8BA6CF00;
/// pDst0[4 * idx + 3] = 0xCFA68B81;
/// pDst1[4 * idx + 3] = 0xCFA68B81;
/// }
///
/// RAIL_Status_t status;
/// railDataConfig.txSource = TX_MFM_DATA;
/// status = RAIL_SetMfmPingPongFifo(railHandle,
/// &(config->buffer));
/// if (status != RAIL_STATUS_NO_ERROR) {
/// return (status);
/// }
///
///
/// status = RAIL_ConfigData(railHandle, &railDataConfig);
/// if (status != RAIL_STATUS_NO_ERROR) {
/// return (status);
/// }
///
/// status = RAIL_SetStateTiming(railHandle, &(config->timings));
/// if (status != RAIL_STATUS_NO_ERROR) {
/// return (status);
/// }
///
/// // start transmitting
/// return (RAIL_StartTx(railHandle, 0, 0, &schedulerInfo));
/// }
///
/// RAIL_Status_t mfmDeInit(void)
/// {
/// RAIL_Status_t status;
/// status = RAIL_StopTx(railHandle, RAIL_STOP_MODES_ALL);
/// if (status != RAIL_STATUS_NO_ERROR) {
/// return (status);
/// }
///
/// railDataConfig.txSource = TX_PACKET_DATA;
/// return (RAIL_ConfigData(railHandle, &railDataConfig));
/// }
/// @endcode
///
/// @{
/**
* @struct RAIL_MFM_PingPongBufferConfig_t
* @brief A configuration structure for MFM Ping-pong buffer in RAIL.
*/
typedef struct RAIL_MFM_PingPongBufferConfig {
/** pointer to buffer0. Must be 32-bit aligned. */
uint32_t *pBuffer0;
/** pointer to buffer1. Must be 32-bit aligned. */
uint32_t *pBuffer1;
/** size of each buffer A and B in 32-bit words. */
uint32_t bufferSizeWords;
} RAIL_MFM_PingPongBufferConfig_t;
/**
* Set MFM ping-pong buffer.
*
* @param[in] railHandle A handle of RAIL instance.
* @param[in] config A MFM ping-pong buffer configuration structure.
* @return A status code indicating success of the function call.
*
*/
RAIL_Status_t RAIL_SetMfmPingPongFifo(RAIL_Handle_t railHandle,
const RAIL_MFM_PingPongBufferConfig_t *config);
/** @} */ // end of MFM
#ifdef __cplusplus
}
#endif
#endif // __RAIL_MFM_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,81 @@
/***************************************************************************//**
* @file
* @brief Power Amplifier configuration file.
*******************************************************************************
* # 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_RAIL_UTIL_PA_CONFIG_H
#define SL_RAIL_UTIL_PA_CONFIG_H
#include "rail_types.h"
// <<< Use Configuration Wizard in Context Menu >>>
// <h> PA Configuration
// <o SL_RAIL_UTIL_PA_POWER_DECI_DBM> Initial PA Power (deci-dBm, 100 = 10.0 dBm)
// <i> Default: 100
#define SL_RAIL_UTIL_PA_POWER_DECI_DBM 100
// <o SL_RAIL_UTIL_PA_RAMP_TIME_US> PA Ramp Time (microseconds)
// <0-65535:1>
// <i> Default: 2
#define SL_RAIL_UTIL_PA_RAMP_TIME_US 2
// <o SL_RAIL_UTIL_PA_VOLTAGE_MV> Milli-volts on PA supply pin (PA_VDD)
// <0-65535:1>
// <i> Default: 3300
#define SL_RAIL_UTIL_PA_VOLTAGE_MV 3300
// <o SL_RAIL_UTIL_PA_SELECTION_2P4GHZ> 2.4 GHz PA Selection
// <RAIL_TX_POWER_MODE_2P4GIG_HIGHEST=> Highest Possible
// <RAIL_TX_POWER_MODE_2P4GIG_HP=> High Power (chip-specific)
// <RAIL_TX_POWER_MODE_2P4GIG_LP=> Low Power
// <RAIL_TX_POWER_MODE_NONE=> Disable
// <i> Default: RAIL_TX_POWER_MODE_2P4GIG_HIGHEST
#define SL_RAIL_UTIL_PA_SELECTION_2P4GHZ RAIL_TX_POWER_MODE_2P4GIG_HIGHEST
// <o SL_RAIL_UTIL_PA_SELECTION_SUBGHZ> Sub-1 GHz PA Selection
// <RAIL_TX_POWER_MODE_NONE=> Disable
// <i> Default: RAIL_TX_POWER_MODE_NONE
#define SL_RAIL_UTIL_PA_SELECTION_SUBGHZ RAIL_TX_POWER_MODE_NONE
// </h>
// <h> PA Curve Configuration
// <s.50 SL_RAIL_UTIL_PA_CURVE_HEADER> Header file containing custom PA curves
// <i> Default: "pa_curves_efr32.h"
#define SL_RAIL_UTIL_PA_CURVE_HEADER "pa_curves_efr32.h"
// <s.50 SL_RAIL_UTIL_PA_CURVE_TYPES> Header file containing PA curve types
// <i> Default: "pa_curve_types_efr32.h"
#define SL_RAIL_UTIL_PA_CURVE_TYPES "pa_curve_types_efr32.h"
// </h>
// <h> PA Calibration Configuration
// <q SL_RAIL_UTIL_PA_CALIBRATION_ENABLE> Apply PA Calibration Factory Offset
// <i> Default: 1
#define SL_RAIL_UTIL_PA_CALIBRATION_ENABLE 1
// </h>
// <<< end of configuration section >>>
#endif // SL_RAIL_UTIL_PA_CONFIG_H

View File

@ -0,0 +1,117 @@
/***************************************************************************//**
* @file
* @brief PA power conversion curves used by Silicon Labs PA power conversion
* functions.
* @details This file contains the curves needed convert PA power levels to
* dBm powers.
*******************************************************************************
* # 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 __PA_CURVES_H_
#define __PA_CURVES_H_
#ifdef __cplusplus
extern "C" {
#endif
#define RAIL_PA_CURVES_PIECEWISE_SEGMENTS (9U)
#define RAIL_PA_CURVES_LP_VALUES (16U)
#define RAIL_PA_CURVES_2P4_HP_VBAT_MAX_POWER 85
#define RAIL_PA_CURVES_2P4_HP_VBAT_MIN_POWER -275
//Curve is generated by Max power (in dBm) = 10, increment(in dBm) = 3, segments = 8
#define RAIL_PA_CURVES_2P4_HP_VBAT_CURVES \
{ { 255, 100, 30 }, \
{ 127, 3355, -171056 }, \
{ 54, 951, -9651 }, \
{ 28, 345, 14060 }, \
{ 17, 189, 15304 }, \
{ 11, 113, 13588 }, \
{ 7, 73, 11317 }, \
{ 5, 55, 9733 }, \
{ 3, 20, 5375 } }
#define RAIL_PA_CURVES_2P4_LP_VBAT_MAX_POWER 0
#define RAIL_PA_CURVES_2P4_LP_VBAT_MIN_POWER -163
#define RAIL_PA_CURVES_2P4_LP_VBAT_CURVES \
{ \
-287, /*! Power Level 0 */ \
-167, /*! Power Level 1 */ \
-113, /*! Power Level 2 */ \
-83, /*! Power Level 3 */ \
-63, /*! Power Level 4 */ \
-48, /*! Power Level 5 */ \
-36, /*! Power Level 6 */ \
-28, /*! Power Level 7 */ \
-21, /*! Power Level 8 */ \
-14, /*! Power Level 9 */ \
-10, /*! Power Level 10 */ \
-6, /*! Power Level 11 */ \
-3, /*! Power Level 12 */ \
0, /*! Power Level 13 */ \
3, /*! Power Level 14 */ \
5, /*! Power Level 15 */ \
}
// *INDENT-OFF*
// Macro to declare the variables needed to initialize RAIL_TxPowerCurvesConfig_t for use in
// RAIL_InitTxPowerCurves, assuming battery powered operation
#define RAIL_DECLARE_TX_POWER_VBAT_CURVES_ALT \
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataHp = { \
RAIL_PA_CURVES_2P4_HP_VBAT_MAX_POWER, \
RAIL_PA_CURVES_2P4_HP_VBAT_MIN_POWER, \
RAIL_PA_CURVES_2P4_HP_VBAT_CURVES, \
}; \
static const int16_t RAIL_curves24Lp[RAIL_PA_CURVES_LP_VALUES] = \
RAIL_PA_CURVES_2P4_LP_VBAT_CURVES;
// *INDENT-OFF*
#define RAIL_DECLARE_TX_POWER_CURVES_CONFIG_ALT \
{ \
.curves = { \
{ \
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR, \
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS, \
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN, \
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX, \
.conversion = { .powerCurve = &RAIL_piecewiseDataHp }, \
}, \
{ \
.algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE, \
.segments = 0U, \
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN, \
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX, \
.conversion = { .mappingTable = &RAIL_curves24Lp[0] }, \
}, \
} \
}
// *INDENT-OFF*
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,529 @@
/***************************************************************************//**
* @file
* @brief PA power conversion functions provided to the customer as source for
* highest level of customization.
* @details This file contains the curves and logic that convert PA power
* levels to dBm powers.
*******************************************************************************
* # 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 "em_device.h"
#include "em_cmu.h"
#include "pa_conversions_efr32.h"
#include "rail.h"
#define MAX(a, b) ((a) > (b) ? (a) : (b))
static RAIL_TxPowerCurvesConfigAlt_t powerCurvesState;
#if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LAS_32B_SERIES_2_CONFIG_1)
#define PA_CONVERSION_MINIMUM_PWRLVL 1
#else
#define PA_CONVERSION_MINIMUM_PWRLVL 0
#endif
/* For details on how to use this plugin, see
https://www.silabs.com/documents/public/application-notes/an1127-power-amplifier-power-conversion-functions.pdf
This macro is defined when Silicon Labs builds this into the library as WEAK
to ensure it can be overriden by customer versions of these functions. The macro
should *not* be defined in a customer build. */
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurves_t *RAIL_GetTxPowerCurve(RAIL_TxPowerMode_t mode)
{
static RAIL_TxPowerCurves_t powerCurves;
// Check for an invalid Tx power mode
if (mode >= RAIL_TX_POWER_MODE_NONE) {
return NULL;
}
RAIL_Handle_t railHandle = RAIL_EFR32_HANDLE;
RAIL_TxPowerLevel_t maxPowerLevel, minPowerLevel;
if (RAIL_SupportsTxPowerModeAlt(railHandle,
&mode,
&maxPowerLevel,
&minPowerLevel) == false) {
return NULL;
}
RAIL_TxPowerCurveAlt_t const *curve =
powerCurvesState.curves[mode].conversion.powerCurve;
// Check for an invalid power curve
if (curve == NULL) {
return NULL;
}
powerCurves.maxPower = curve->maxPower;
powerCurves.minPower = curve->minPower;
powerCurves.powerParams = &curve->powerParams[0];
return &powerCurves;
}
// This function will not be supported for any parts after efr32xg1x
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
RAIL_Status_t RAIL_InitTxPowerCurves(const RAIL_TxPowerCurvesConfig_t *config)
{
#ifdef _SILICON_LABS_32B_SERIES_1
// First PA is 2.4 GHz high power, using a piecewise fit
RAIL_PaDescriptor_t *current =
&powerCurvesState.curves[RAIL_TX_POWER_MODE_2P4_HP];
current->algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR;
current->segments = config->piecewiseSegments;
current->min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN;
current->max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX;
static RAIL_TxPowerCurveAlt_t txPower2p4 = {
.minPower = 0U,
.maxPower = 0U,
.powerParams = { // The current max number of piecewise segments is 8
{ 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U },
{ 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U },
}
};
txPower2p4.maxPower = config->txPowerSgCurves->maxPower;
txPower2p4.minPower = config->txPowerSgCurves->minPower;
memcpy(&txPower2p4.powerParams[0],
config->txPowerSgCurves->powerParams,
config->piecewiseSegments * sizeof(RAIL_TxPowerCurveSegment_t));
current->conversion.powerCurve = &txPower2p4;
// Second PA is 2.4 GHz low power, using a mapping table
current = &powerCurvesState.curves[RAIL_TX_POWER_MODE_2P4_LP];
current->algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE;
current->segments = 0U;
current->min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN;
current->max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX;
current->conversion.mappingTable = config->txPower24LpCurves;
// Third and final PA is Sub-GHz, using a piecewise fit
current = &powerCurvesState.curves[RAIL_TX_POWER_MODE_SUBGIG];
current->algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR;
current->segments = config->piecewiseSegments;
current->min = RAIL_TX_POWER_LEVEL_SUBGIG_MIN;
current->max = RAIL_TX_POWER_LEVEL_SUBGIG_HP_MAX;
static RAIL_TxPowerCurveAlt_t txPowerSubGig = {
.minPower = 0U,
.maxPower = 0U,
.powerParams = { // The current max number of piecewise segments is 8
{ 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U },
{ 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U }, { 0U, 0U, 0U },
}
};
txPowerSubGig.maxPower = config->txPowerSgCurves->maxPower;
txPowerSubGig.minPower = config->txPowerSgCurves->minPower;
memcpy(&txPowerSubGig.powerParams[0],
config->txPowerSgCurves->powerParams,
config->piecewiseSegments * sizeof(RAIL_TxPowerCurveSegment_t));
current->conversion.powerCurve = &txPowerSubGig;
return RAIL_STATUS_NO_ERROR;
#else
(void) config;
return RAIL_STATUS_INVALID_CALL;
#endif
}
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
RAIL_Status_t RAIL_InitTxPowerCurvesAlt(const RAIL_TxPowerCurvesConfigAlt_t *config)
{
RAIL_VerifyTxPowerCurves(config);
powerCurvesState = *config;
return RAIL_STATUS_NO_ERROR;
}
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
RAIL_TxPowerLevel_t RAIL_ConvertDbmToRaw(RAIL_Handle_t railHandle,
RAIL_TxPowerMode_t mode,
RAIL_TxPower_t power)
{
uint32_t powerLevel;
uint32_t powerIndex = 0U;
uint32_t minPowerLevel;
(void)railHandle;
// This function is called internally from the RAIL library,
// so if the user never calls RAIL_InitTxPowerCurves - even
// if they never intend to use dBm values in their code -
// they'll always hit the assert below. Give the user a way
// to not have to call RAIL_InitTxPowerCurves if they don't
// care about dBm values by picking a dBm value that returns the
// highest RAIL_TxPowerLevel_t possible. In other words, when
// a channel dBm limitation greater than or equal to \ref RAIL_TX_POWER_MAX
// is converted to raw units, the max RAIL_TxPowerLevel_t will be
// returned. When compared to the current power level of the PA,
// it will always be greater, indicating that no power coercion
// is necessary to comply with channel limitations.
if (power >= RAIL_TX_POWER_MAX) {
return 255U;
}
// Check for an invalid Tx power mode
if (mode >= RAIL_TX_POWER_MODE_NONE) {
return 0U;
}
RAIL_PaDescriptor_t const *modeInfo = &powerCurvesState.curves[mode];
minPowerLevel = MAX(modeInfo->min, PA_CONVERSION_MINIMUM_PWRLVL);
// If we're in low power mode, just use the simple lookup table
if (modeInfo->algorithm == RAIL_PA_ALGORITHM_MAPPING_TABLE) {
// Binary search through the lookup table to find the closest power level
// without going over.
uint32_t lower = 0U;
// Track the high side of the estimate
powerIndex = modeInfo->max - minPowerLevel;
while (lower < powerIndex) {
// Calculate the midpoint of the current range
uint32_t index = powerIndex - (powerIndex - lower) / 2U;
if (power < modeInfo->conversion.mappingTable[index]) {
powerIndex = index - 1U;
} else {
lower = index;
}
}
return powerIndex + minPowerLevel;
}
// Here we know we're using the piecewise linear conversion
RAIL_TxPowerCurveAlt_t const *paParams = modeInfo->conversion.powerCurve;
// Check for valid paParams before using them
if (paParams == NULL) {
return 0U;
}
// Cap the power based on the PA settings.
if (power > paParams->maxPower) {
// If we go above the maximum dbm the chip supports
// Then provide maximum powerLevel
power = paParams->maxPower;
} else if (power < paParams->minPower) {
// If we go below the minimum we want included in the curve fit, force it.
power = paParams->minPower;
} else {
}
// Map the power value to a 0 - 7 powerIndex value
//There are 8 segments of step size of RAIL_TX_POWER_CURVE_INCREMENT in deci dBm
//starting from maximum RAIL_TX_POWER_CURVE_MAX in deci dBm
// These are just starting points to give the code
// a rough idea of which segment to use, based on
// how they were fit. Adjustments are made later on
// if this turns out to be incorrect.
RAIL_TxPower_t txPowerMax = RAIL_TX_POWER_CURVE_DEFAULT_MAX;
RAIL_TxPower_t txPowerIncrement = RAIL_TX_POWER_CURVE_DEFAULT_INCREMENT;
// if the first curve segment starts with RAIL_TX_POWER_LEVEL_INVALID
//It is an extra curve segment to depict the maxpower and increment
// (in deci-dBm) used while generating the curves.
// The extra segment is only present when curve segment is generated by
//using values different than the default - RAIL_TX_POWER_CURVE_DEFAULT_MAX
// and RAIL_TX_POWER_CURVE_DEFAULT_INCREMENT.
if ((paParams->powerParams[0].maxPowerLevel) == RAIL_TX_POWER_LEVEL_INVALID) {
powerIndex += 1U;
txPowerMax = paParams->powerParams[0].slope;
txPowerIncrement = paParams->powerParams[0].intercept;
}
powerIndex += ((txPowerMax - power) / txPowerIncrement);
if (powerIndex > (modeInfo->segments - 1U)) {
powerIndex = (modeInfo->segments - 1U);
}
do {
// Select the correct piecewise segment to use for conversion.
RAIL_TxPowerCurveSegment_t const *powerParams =
&paParams->powerParams[powerIndex];
// powerLevel can only go down to 0.
if (powerParams->intercept + powerParams->slope * power < 0) {
powerLevel = 0U;
} else {
powerLevel = powerParams->intercept + powerParams->slope * power;
}
// Add 500 to do rounding correctly, as opposed to just rounding towards 0
powerLevel = ((powerLevel + 500U) / 1000U);
// In case it turns out the resultant power level was too low and we have
// to recalculate with the next curve...
powerIndex++;
} while ((powerIndex < modeInfo->segments)
&& (powerLevel <= paParams->powerParams[powerIndex].maxPowerLevel));
// We already know that powerIndex is at most modeInfo->segments
if (powerLevel > paParams->powerParams[powerIndex - 1U].maxPowerLevel) {
powerLevel = paParams->powerParams[powerIndex - 1U].maxPowerLevel;
}
// If we go below the minimum we want included in the curve fit, force it.
if (powerLevel < minPowerLevel) {
powerLevel = minPowerLevel;
}
return (RAIL_TxPowerLevel_t)powerLevel;
}
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
RAIL_TxPower_t RAIL_ConvertRawToDbm(RAIL_Handle_t railHandle,
RAIL_TxPowerMode_t mode,
RAIL_TxPowerLevel_t powerLevel)
{
(void)railHandle;
// Check for an invalid Tx power mode
if (mode >= RAIL_TX_POWER_MODE_NONE) {
return RAIL_TX_POWER_MIN;
}
RAIL_PaDescriptor_t const *modeInfo = &powerCurvesState.curves[mode];
if (modeInfo->algorithm == RAIL_PA_ALGORITHM_MAPPING_TABLE) {
// Limit the max power level
if (powerLevel > modeInfo->max) {
powerLevel = modeInfo->max;
}
// We 1-index low power PA power levels, but of course arrays are 0 indexed
powerLevel -= MAX(modeInfo->min, PA_CONVERSION_MINIMUM_PWRLVL);
//If the index calculation above underflowed, then provide the lowest array index.
if (powerLevel > (modeInfo->max - modeInfo->min)) {
powerLevel = 0U;
}
return modeInfo->conversion.mappingTable[powerLevel];
} else {
#if defined(_SILICON_LABS_32B_SERIES_1) || defined(_SILICON_LAS_32B_SERIES_2_CONFIG_1)
// Although 0 is a legitimate power on non-2.4 LP PA's and can be set via
// "RAIL_SetTxPower(railHandle, 0)" it is MUCH lower than power
// level 1 (approximately -50 dBm). Including it in the piecewise
// linear fit would skew the curve substantially, so we exclude it
// from the conversion.
if (powerLevel == 0U) {
return -500;
}
#endif
RAIL_TxPowerCurveAlt_t const *powerCurve = modeInfo->conversion.powerCurve;
// Check for a valid powerCurve pointer before using it
if (powerCurve == NULL) {
return RAIL_TX_POWER_MIN;
}
RAIL_TxPowerCurveSegment_t const *powerParams = powerCurve->powerParams;
// Check for a valid powerParams pointer before using it
if (powerParams == NULL) {
return RAIL_TX_POWER_MIN;
}
// Hard code the extremes (i.e. don't use the curve fit) in order
// to make it clear that we are reaching the extent of the chip's
// capabilities
if (powerLevel <= modeInfo->min) {
return powerCurve->minPower;
} else if (powerLevel >= modeInfo->max) {
return powerCurve->maxPower;
} else {
}
// Figure out which parameter to use based on the power level
uint8_t x = 0;
uint8_t upperBound = modeInfo->segments - 1U;
// If the first curve segment starts with RAIL_TX_POWER_LEVEL_INVALID,
// then it is an additional curve segment that stores maxpower and increment
// (in deci-dBm) used to generate the curves.
// The extra info segment is present only if the curves were generated using
// values other than default - RAIL_TX_POWER_CURVE_DEFAULT_MAX and
// RAIL_TX_POWER_CURVE_DEFAULT_INCREMENT.
if ((powerParams[0].maxPowerLevel) == RAIL_TX_POWER_LEVEL_INVALID) {
x = 1U; // skip over the first entry
}
for (; x < upperBound; x++) {
if (powerParams[x + 1U].maxPowerLevel < powerLevel) {
break;
}
}
int32_t power;
power = ((1000 * (int32_t)(powerLevel)) - powerParams[x].intercept);
power = ((power + (powerParams[x].slope / 2)) / powerParams[x].slope);
if (power > powerCurve->maxPower) {
return powerCurve->maxPower;
} else if (power < powerCurve->minPower) {
return powerCurve->minPower;
} else {
return (RAIL_TxPower_t)power;
}
}
}
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
RAIL_Status_t RAIL_GetTxPowerCurveLimits(RAIL_Handle_t railHandle,
RAIL_TxPowerMode_t mode,
RAIL_TxPower_t *maxPower,
RAIL_TxPower_t *increment)
{
(void)railHandle;
// Check for an invalid Tx power mode
if (mode >= RAIL_TX_POWER_MODE_NONE) {
return RAIL_STATUS_INVALID_PARAMETER;
}
//The power max info only for available Linear fit
RAIL_PaDescriptor_t const *modeInfo = &powerCurvesState.curves[mode];
if (modeInfo->algorithm == RAIL_PA_ALGORITHM_MAPPING_TABLE) {
return RAIL_STATUS_INVALID_CALL;
}
*maxPower = RAIL_TX_POWER_CURVE_DEFAULT_MAX;
*increment = RAIL_TX_POWER_CURVE_DEFAULT_INCREMENT;
RAIL_TxPowerCurveAlt_t const *paParams = modeInfo->conversion.powerCurve;
if ((paParams->powerParams[0].maxPowerLevel) == RAIL_TX_POWER_LEVEL_INVALID) {
*maxPower = paParams->powerParams[0].slope;
*increment = (RAIL_TxPower_t)paParams->powerParams[0].intercept;
}
return RAIL_STATUS_NO_ERROR;
}
// This macro is defined when Silicon Labs builds curves into the library as WEAK
// to ensure it can be overriden by customer versions of these functions. It
// should *not* be defined in a customer build.
#if !defined(RAIL_PA_CONVERSIONS_WEAK) && !defined(HAL_CONFIG)
#include "sl_rail_util_pa_config.h"
void sl_rail_util_pa_init(void)
{
#if SL_RAIL_UTIL_PA_VOLTAGE_MV > 1800
(void)RAIL_InitTxPowerCurvesAlt(&RAIL_TxPowerCurvesVbat);
#else
(void)RAIL_InitTxPowerCurvesAlt(&RAIL_TxPowerCurvesDcdc);
#endif
#if SL_RAIL_UTIL_PA_CALIBRATION_ENABLE
RAIL_EnablePaCal(true);
#endif
}
#if RAIL_SUPPORTS_2P4GHZ_BAND
static RAIL_TxPowerConfig_t txPowerConfig2p4Ghz = {
.mode = SL_RAIL_UTIL_PA_SELECTION_2P4GHZ,
.voltage = SL_RAIL_UTIL_PA_VOLTAGE_MV,
.rampTime = SL_RAIL_UTIL_PA_RAMP_TIME_US,
};
#endif
RAIL_TxPowerConfig_t *sl_rail_util_pa_get_tx_power_config_2p4ghz(void)
{
#if RAIL_SUPPORTS_2P4GHZ_BAND
return &txPowerConfig2p4Ghz;
#else
return NULL;
#endif
}
#if RAIL_SUPPORTS_SUBGHZ_BAND
static RAIL_TxPowerConfig_t txPowerConfigSubGhz = {
.mode = SL_RAIL_UTIL_PA_SELECTION_SUBGHZ,
.voltage = SL_RAIL_UTIL_PA_VOLTAGE_MV,
.rampTime = SL_RAIL_UTIL_PA_RAMP_TIME_US,
};
#endif
RAIL_TxPowerConfig_t *sl_rail_util_pa_get_tx_power_config_subghz(void)
{
#if RAIL_SUPPORTS_SUBGHZ_BAND
return &txPowerConfigSubGhz;
#else
return NULL;
#endif
}
void sl_rail_util_pa_on_channel_config_change(RAIL_Handle_t rail_handle,
const RAIL_ChannelConfigEntry_t *entry)
{
if (!RAIL_IsPaAutoModeEnabled(rail_handle)) {
RAIL_TxPowerConfig_t currentTxPowerConfig;
RAIL_TxPowerConfig_t *newTxPowerConfigPtr;
RAIL_TxPower_t txPowerDeciDbm;
RAIL_Status_t status;
// Get current TX Power Config.
status = RAIL_GetTxPowerConfig(rail_handle, &currentTxPowerConfig);
if (status != RAIL_STATUS_NO_ERROR) {
while (true) {
} // Error: Can't get TX Power Config
}
#if RAIL_SUPPORTS_DUAL_BAND
// Determine new TX Power Config.
if (entry->baseFrequency < 1000000000UL) {
newTxPowerConfigPtr = &txPowerConfigSubGhz;
} else {
newTxPowerConfigPtr = &txPowerConfig2p4Ghz;
}
#else
(void) entry;
#if RAIL_SUPPORTS_2P4GHZ_BAND
newTxPowerConfigPtr = &txPowerConfig2p4Ghz;
#else
newTxPowerConfigPtr = &txPowerConfigSubGhz;
#endif
#endif
// Call RAIL_ConfigTxPower only if TX Power Config mode has changed.
if (currentTxPowerConfig.mode != newTxPowerConfigPtr->mode) {
// Save current TX power before RAIL_ConfigTxPower (because not preserved).
if (currentTxPowerConfig.mode == RAIL_TX_POWER_MODE_NONE) {
txPowerDeciDbm = SL_RAIL_UTIL_PA_POWER_DECI_DBM;
} else {
txPowerDeciDbm = RAIL_GetTxPowerDbm(rail_handle);
}
// Apply new TX Power Config.
status = RAIL_ConfigTxPower(rail_handle, newTxPowerConfigPtr);
if (status != RAIL_STATUS_NO_ERROR) {
while (true) {
} // Error: Can't set TX Power Config
}
// Restore TX power after RAIL_ConfigTxPower.
status = RAIL_SetTxPowerDbm(rail_handle, txPowerDeciDbm);
if (status != RAIL_STATUS_NO_ERROR) {
while (true) {
} // Error: Can't set TX Power
}
}
} // !RAIL_IsPaAutoModeEnabled
}
#endif // !RAIL_PA_CONVERSIONS_WEAK

View File

@ -0,0 +1,182 @@
/***************************************************************************//**
* @file
* @brief PA power conversion functions provided to the customer as source for
* highest level of customization.
* @details This file contains the curves and logic that convert PA power
* levels to dBm powers.
*******************************************************************************
* # 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 PA_CONVERSIONS_EFR32_H
#define PA_CONVERSIONS_EFR32_H
#include "rail_types.h"
// This macro is defined when Silicon Labs builds curves into the library as WEAK
// to ensure it can be overriden by customer versions of these functions. It
// should *not* be defined in a customer build.
#if !defined(RAIL_PA_CONVERSIONS_WEAK)
#ifdef SL_RAIL_UTIL_PA_CONFIG_HEADER
#include SL_RAIL_UTIL_PA_CONFIG_HEADER
#else
#include "sl_rail_util_pa_conversions_efr32_config.h"
#endif
#endif
#ifdef HAL_CONFIG
#include "hal-config.h"
#ifdef HAL_PA_CURVE_HEADER
#ifdef SL_RAIL_UTIL_PA_CURVE_HEADER
#undef SL_RAIL_UTIL_PA_CURVE_HEADER
#endif
#define SL_RAIL_UTIL_PA_CURVE_HEADER HAL_PA_CURVE_HEADER
#endif
#endif
#ifdef SL_RAIL_UTIL_PA_CURVE_HEADER
#include SL_RAIL_UTIL_PA_CURVE_HEADER
#else
#include "pa_curves_efr32.h"
#endif
#ifdef SL_RAIL_UTIL_PA_CURVE_TYPES
#include SL_RAIL_UTIL_PA_CURVE_TYPES
#else
#include "pa_curve_types_efr32.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/// The curves to be used when battery voltage powers transmission
extern const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesVbat;
/// The curves to be used when the DC-DC converter powers transmission
extern const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesDcdc;
/**
* Initialize TxPower curves.
*
* @param[in] txPowerCurvesConfig Struct containing pointers to custom
* tx power curves.
* @return RAIL_Status_t indicating success or an error.
*
* @note: This function is deprecated, and will no longer be supported
* for any chips released after EFRXG1X parts. Please use
* RAIL_InitTxPowerCurvesAlt instead.
*/
RAIL_Status_t RAIL_InitTxPowerCurves(const RAIL_TxPowerCurvesConfig_t *config);
/**
* Initialize TxPower curves.
*
* @param[in] txPowerCurvesConfig Struct containing pointers to custom
* tx power curves.
* @return RAIL_Status_t indicating success or an error.
*
*/
RAIL_Status_t RAIL_InitTxPowerCurvesAlt(const RAIL_TxPowerCurvesConfigAlt_t *config);
/**
* Gets the curve that should be used for conversion functions based on the
* current PA configuration.
*
* @param[in] mode PA mode whose curves are needed.
* @return RAIL_TxPowerCurves_t that should be used for conversion functions.
*
* @note: If the mode is not supported by the the chip,
* then NULL will be returned.
*/
RAIL_TxPowerCurves_t const * RAIL_GetTxPowerCurve(RAIL_TxPowerMode_t mode);
/**
* Gets the maximum power in deci-dBm that should be used for calculating
* the segments and to find right curve segment to convert Dbm to raw power
* level for a specific PA.
* For the PAs with \ref RAIL_PaConversionAlgorithm_t
* \ref RAIL_PA_ALGORITHM_PIECEWISE_LINEAR , if the curves are generated with
* maxPower and increment other than \ref RAIL_TX_POWER_CURVE_DEFAULT_MAX and
* \ref RAIL_TX_POWER_CURVE_DEFAULT_INCREMENT respectively, then the first
* \ref RAIL_TxPowerCurveSegment_t has its maxPowerLevel equal to
* \ref RAIL_TX_POWER_LEVEL_INVALID and its slope and intercept stores the
* maxPower and increment in deci-dBm respectively.
*
* @param[in] railHandle A RAIL instance handle.
* @param[in] mode PA mode whose curves are needed.
* @param[in] maxpower A pointer to memory allocated to hold the maxpower in
* deci-dBm used in calculation of curve segments .
* A NULL configuration will produce undefined behavior.
* @param[in] increment A pointer to memory allocated to hold the increment in
* deci-dBm used in calculation of curve segments.
* A NULL configuration will produce undefined behavior.
* @return RAIL_Status_t indicating success or an error.
*
*/
RAIL_Status_t RAIL_GetTxPowerCurveLimits(RAIL_Handle_t railHandle,
RAIL_TxPowerMode_t mode,
RAIL_TxPower_t *maxpower,
RAIL_TxPower_t *increment);
/**
* Initialize PA TX Curves
*
*/
void sl_rail_util_pa_init(void);
/**
* Get a pointer to the TX Power Config 2.4 GHz structure.
*
* @return a pointer to the TX Power Config stucture.
*
*/
RAIL_TxPowerConfig_t *sl_rail_util_pa_get_tx_power_config_2p4ghz(void);
/**
* Get a pointer to the TX Power Config Sub-GHz structure.
*
* @return a pointer to the TX Power Config stucture.
*
*/
RAIL_TxPowerConfig_t *sl_rail_util_pa_get_tx_power_config_subghz(void);
/**
* Provide a channel config change callback capable of configuring the PA
* correctly.
*
* @param[in] rail_handle The RAIL handle being passed into this callback.
* @param[in] entry The channel config entry being switched to by hardware.
*
*/
void sl_rail_util_pa_on_channel_config_change(RAIL_Handle_t rail_handle,
const RAIL_ChannelConfigEntry_t *entry);
#ifdef __cplusplus
}
#endif
#endif // PA_CONVERSIONS_EFR32_H

View File

@ -0,0 +1,221 @@
/***************************************************************************//**
* @file
* @brief PA power conversion curve types used by Silicon Labs PA power
* conversion functions.
* @details This file contains the curve types needed convert PA power levels
* to dBm powers.
*******************************************************************************
* # 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 PA_CURVE_TYPES_EFR32_H
#define PA_CURVE_TYPES_EFR32_H
#include "rail_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @struct RAIL_TxPowerCurves
*
* @brief Structure containing data defining each segment of the
* power (deci-dBm) to powerLevel mapping curve fits.
*
* Note, these used in an equation of the form:
*
* powerLevel * 1000 = slope * power + intercept
*
* powerLevel is the 0-252/0-248/1-7 values used in the RAIL_Get/SetTxPower
* functions, and power is the actual output power of the PA, specified
* in deci-dBm.
*
* @note If the curves are generated with
* maxPower and increment other than \ref RAIL_TX_POWER_CURVE_DEFAULT_MAX and
* \ref RAIL_TX_POWER_CURVE_DEFAULT_INCREMENT respectively, then the first
* \ref RAIL_TxPowerCurveSegment_t has its maxPowerLevel equal to
* \ref RAIL_TX_POWER_LEVEL_INVALID and its slope and intercept stores the
* maxPower and increment in deci-dBm respectively.
*/
typedef struct RAIL_TxPowerCurveSegment {
/** The highest power level that this segment will be used to convert */
uint16_t maxPowerLevel;
/** slope of the line */
int16_t slope;
/** y-intercept of the line */
int32_t intercept;
} RAIL_TxPowerCurveSegment_t;
/**
* @struct RAIL_TxPowerCurves
*
* @brief Structure containing the min and max values for a given
* PA and voltage supply combination (in deci-dBm).
*/
typedef struct RAIL_TxPowerCurves {
/** max deci-dBm value */
int16_t maxPower;
/** min deci-dBm value */
int16_t minPower;
/**
* Pointer to "piecewiseSegments"-length array of
* RAIL_TxPowerCurveSegment_t of power (deci-dBm) to
* powerLevel conversion fits.
*/
const RAIL_TxPowerCurveSegment_t *powerParams;
} RAIL_TxPowerCurves_t;
/**
* @struct RAIL_TxPowerCurvesConfig
*
* @brief Structure containing curve fit information and other metadata
* required to properly use the WEAK versions of RAIL_ConvertRawToDb
* and RAIL_ConvertDbmToRaw
*/
typedef struct RAIL_TxPowerCurvesConfig {
/**
* Pointer a RAIL_TxPowerCurves_t representing the piecewise linear segments
* of curves that map power level to power in dBm for the 2.4 GHz high power
* PA.
*
* @note By the default conversion implementation, segments must be specified
* in decreasing power order. That is, the 0th entry of this array should be
* used to convert the highest power (levels). Segment at position n is valid
* from maxPowerLevel+1 from the segment at n+1 (or 0 if n is array length -
* 1) to maxPowerLevel of segment n, inclusive.
*/
const RAIL_TxPowerCurves_t *txPower24HpCurves;
/**
* Pointer a RAIL_TxPowerCurves_t representing the piecewise linear segments
* of curves that map power level to power in dBm for the subgig PA.
*
* @note By the default conversion implementation, segments must be specified
* in decreasing power order. That is, the 0th entry of this array should be
* used to convert the highest power (levels). Segment at position n is valid
* from maxPowerLevel+1 from the segment at n+1 (or 0 if n is array length -
* 1) to maxPowerLevel of segment n, inclusive.
*/
const RAIL_TxPowerCurves_t *txPowerSgCurves;
/**
* Look up table for each of the power levels of the 2.4GHz low power
* amplifier and their equivalent deci-dB value.
*/
const int16_t *txPower24LpCurves;
/**
* The number of piecewise segments provided to the PA in each of the four
* conversion curve fits. The default is 8, but regardless of the number, it
* must be the same for all curves.
*/
uint8_t piecewiseSegments;
} RAIL_TxPowerCurvesConfig_t;
/// PA conversion algorithms types for converting between dBm and power levels
RAIL_ENUM(RAIL_PaConversionAlgorithm_t) {
RAIL_PA_ALGORITHM_PIECEWISE_LINEAR, /** Piecewise linear fit */
RAIL_PA_ALGORITHM_MAPPING_TABLE, /** Mapping table between quantities */
};
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// Self-referencing defines minimize compiler complaints when using RAIL_ENUM
#define RAIL_PA_ALGORITHM_PIECEWISE_LINEAR ((RAIL_PaConversionAlgorithm_t) RAIL_PA_ALGORITHM_PIECEWISE_LINEAR)
#define RAIL_PA_ALGORITHM_MAPPING_TABLE ((RAIL_PaConversionAlgorithm_t) RAIL_PA_ALGORITHM_MAPPING_TABLE)
#endif//DOXYGEN_SHOULD_SKIP_THIS
/**
* @struct RAIL_TxPowerCurvesAlt
*
* @brief Structure containing the min and max values for a given
* PA and voltage supply combination (in deci-dBm).
*/
typedef struct RAIL_TxPowerCurveAlt {
/** max deci-dBm value */
int16_t maxPower;
/** min deci-dBm value */
int16_t minPower;
/**
* "piecewiseSegments"-length array of RAIL_TxPowerCurveSegment_t
* of power (deci-dBm) to powerLevel conversion fits.
*/
RAIL_TxPowerCurveSegment_t powerParams[];
} RAIL_TxPowerCurveAlt_t;
typedef union RAIL_PowerConversion {
/**
* Pointer to a powerCurve containing line segment data for the curves
* corresponding to a specific PA.
*
* @note By the default conversion implementation, segments must be specified
* in decreasing power order. That is, the 0th entry of this array should be
* used to convert the highest power (levels). Segment at position n is valid
* from maxPowerLevel+1 from the segment at n+1 (or 0 if n is array length -
* 1) to maxPowerLevel of segment n, inclusive.
*/
const RAIL_TxPowerCurveAlt_t *powerCurve;
/**
* Lookup table for PA's which use the mapping table algorithm for converting
* between deci-dBm and power levels.
*/
const int16_t *mappingTable;
} RAIL_PowerConversion_t;
/// PA descriptor as used in the PA conversion functions
typedef struct RAIL_PaDescriptor {
/** Algorithm used to map dBm to power levels for this PA */
RAIL_PaConversionAlgorithm_t algorithm;
/**
* The number of piecewise segments provided to the PA in a piecewise linear
* curve fit. The default is 8. Should be set to 0 when not using the
* piecewise linear algorithm.
*/
uint8_t segments;
/** Min power level for this PA */
RAIL_TxPowerLevel_t min;
/** Max power level for this PA */
RAIL_TxPowerLevel_t max;
/** Union containing a pointer to algorithm-specific conversion data. */
RAIL_PowerConversion_t conversion;
} RAIL_PaDescriptor_t;
/**
* @typedef RAIL_TxPowerCurvesConfigAlt_t
*
* @brief More generic structure containing information about
* piecewise linear curves and mapping tables, instead of specific PA's.
*/
typedef struct RAIL_TxPowerCurvesConfigAlt {
RAIL_PaDescriptor_t curves[RAIL_NUM_PA];
uint32_t signature;
uint16_t paVoltage;
} RAIL_TxPowerCurvesConfigAlt_t;
#ifdef __cplusplus
}
#endif
#endif // PA_CURVE_TYPES_EFR32_H

View File

@ -0,0 +1,347 @@
/***************************************************************************//**
* @file
* @brief Default PA power conversion structures with curves calibrated by the
* RAIL team.
* @details This file contains the curves that convert PA power levels to dBm
* powers.
*******************************************************************************
* # 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.
*
******************************************************************************/
// This entire file should never be used on FCC pre-certified modules
#ifndef _SILICON_LABS_MODULE
#include "em_device.h"
#include "pa_conversions_efr32.h"
#if defined(_SILICON_LABS_32B_SERIES_1)
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataHpVbat = {
RAIL_PA_CURVES_2P4_HP_VBAT_MAX_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_MIN_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_CURVES
};
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataSgVbat = {
RAIL_PA_CURVES_SG_VBAT_MAX_POWER,
RAIL_PA_CURVES_SG_VBAT_MIN_POWER,
RAIL_PA_CURVES_SG_VBAT_CURVES
};
static const int16_t RAIL_curves24LpVbat[RAIL_PA_CURVES_LP_VALUES] =
RAIL_PA_CURVES_2P4_LP;
// This macro is defined when Silicon Labs builds this into the library as WEAK
// to ensure it can be overriden by customer versions of these functions. It
// should *not* be defined in a customer build.
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesVbat = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_2P4_HP_SG_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpVbat },
},
{
.algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE,
.segments = 0U,
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX,
.conversion = { .mappingTable = &RAIL_curves24LpVbat[0] },
},
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_2P4_HP_SG_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_SUBGIG_MIN,
.max = RAIL_TX_POWER_LEVEL_SUBGIG_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataSgVbat },
},
},
};
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataHpDcdc = {
RAIL_PA_CURVES_2P4_HP_DCDC_MAX_POWER,
RAIL_PA_CURVES_2P4_HP_DCDC_MIN_POWER,
RAIL_PA_CURVES_2P4_HP_DCDC_CURVES
};
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataSgDcdc = {
RAIL_PA_CURVES_SG_DCDC_MAX_POWER,
RAIL_PA_CURVES_SG_DCDC_MIN_POWER,
RAIL_PA_CURVES_SG_DCDC_CURVES
};
static const int16_t RAIL_curves24LpDcdc[RAIL_PA_CURVES_LP_VALUES] =
RAIL_PA_CURVES_2P4_LP;
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesDcdc = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_2P4_HP_SG_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpDcdc },
},
{
.algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE,
.segments = 0U,
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX,
.conversion = { .mappingTable = &RAIL_curves24LpDcdc[0] },
},
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_2P4_HP_SG_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_SUBGIG_MIN,
.max = RAIL_TX_POWER_LEVEL_SUBGIG_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataSgDcdc },
},
},
};
#elif ((_SILICON_LABS_32B_SERIES_2_CONFIG == 2) || (_SILICON_LABS_32B_SERIES_2_CONFIG == 7))
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataHpVbat = {
RAIL_PA_CURVES_2P4_HP_VBAT_MAX_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_MIN_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_CURVES,
};
static const int16_t RAIL_curves24Lp[RAIL_PA_CURVES_LP_VALUES] =
RAIL_PA_CURVES_2P4_LP_VBAT_CURVES;
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesVbat = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpVbat },
},
{ \
.algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE, \
.segments = 0U, \
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN, \
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX, \
.conversion = { .mappingTable = &RAIL_curves24Lp[0] }, \
},
}
};
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesDcdc = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpVbat },
},
{ \
.algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE, \
.segments = 0U, \
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN, \
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX, \
.conversion = { .mappingTable = &RAIL_curves24Lp[0] }, \
},
}
};
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3)
RAIL_DECLARE_TX_POWER_VBAT_CURVES_ALT;
// This chip has the same curve for Vbat and DCDC
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesVbat = RAIL_DECLARE_TX_POWER_CURVES_CONFIG_ALT;
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesDcdc = RAIL_DECLARE_TX_POWER_CURVES_CONFIG_ALT;
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5)
RAIL_DECLARE_TX_POWER_VBAT_CURVES_ALT;
// This chip has the same curve for Vbat and DCDC
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesVbat = RAIL_DECLARE_TX_POWER_CURVES_CONFIG_ALT;
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesDcdc = RAIL_DECLARE_TX_POWER_CURVES_CONFIG_ALT;
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataHpVbat = {
RAIL_PA_CURVES_2P4_HP_VBAT_MAX_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_MIN_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_CURVES,
};
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataMpVbat = {
RAIL_PA_CURVES_2P4_MP_VBAT_MAX_POWER,
RAIL_PA_CURVES_2P4_MP_VBAT_MIN_POWER,
RAIL_PA_CURVES_2P4_MP_VBAT_CURVES,
};
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataLpVbat = {
RAIL_PA_CURVES_2P4_LP_VBAT_MAX_POWER,
RAIL_PA_CURVES_2P4_LP_VBAT_MIN_POWER,
RAIL_PA_CURVES_2P4_LP,
};
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesVbat = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpVbat },
},
#if _SILICON_LABS_32B_SERIES_2_CONFIG == 1
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_MP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_MP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataMpVbat },
},
#endif // _SILICON_LABS_32B_SERIES_2_CONFIG == 1
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataLpVbat },
},
}
};
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesDcdc = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpVbat },
},
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_MP_MIN,
.max = RAIL_TX_POWER_LEVEL_MP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataMpVbat },
},
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_LP_MIN,
.max = RAIL_TX_POWER_LEVEL_LP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataLpVbat },
},
}
};
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4)
static const RAIL_TxPowerCurveAlt_t RAIL_piecewiseDataHpVbat = {
RAIL_PA_CURVES_2P4_HP_VBAT_MAX_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_MIN_POWER,
RAIL_PA_CURVES_2P4_HP_VBAT_CURVES,
};
static const int16_t RAIL_curves24Lp[RAIL_PA_CURVES_LP_VALUES] =
RAIL_PA_CURVES_2P4_LP_VBAT_CURVES;
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesVbat = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpVbat },
},
{ \
.algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE, \
.segments = 0U, \
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN, \
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX, \
.conversion = { .mappingTable = &RAIL_curves24Lp[0] }, \
},
}
};
#ifdef RAIL_PA_CONVERSIONS_WEAK
__WEAK
#endif
const RAIL_TxPowerCurvesConfigAlt_t RAIL_TxPowerCurvesDcdc = {
.curves = {
{
.algorithm = RAIL_PA_ALGORITHM_PIECEWISE_LINEAR,
.segments = RAIL_PA_CURVES_PIECEWISE_SEGMENTS,
.min = RAIL_TX_POWER_LEVEL_2P4_HP_MIN,
.max = RAIL_TX_POWER_LEVEL_2P4_HP_MAX,
.conversion = { .powerCurve = &RAIL_piecewiseDataHpVbat },
},
{ \
.algorithm = RAIL_PA_ALGORITHM_MAPPING_TABLE, \
.segments = 0U, \
.min = RAIL_TX_POWER_LEVEL_2P4_LP_MIN, \
.max = RAIL_TX_POWER_LEVEL_2P4_LP_MAX, \
.conversion = { .mappingTable = &RAIL_curves24Lp[0] }, \
},
}
};
#else
#error "Unsupported platform!"
#endif
#endif //_SILICON_LABS_MODULE

View File

@ -0,0 +1,80 @@
/***************************************************************************//**
* @file
* @brief PA power conversion curves used by Silicon Labs PA power conversion
* functions.
* @details This file contains the curves needed convert PA power levels to
* dBm powers.
*******************************************************************************
* # 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 PA_CURVES_EFR32_H
#define PA_CURVES_EFR32_H
#ifdef __cplusplus
extern "C" {
#endif
#include "em_device.h"
#ifdef _SILICON_LABS_32B_SERIES_1
#include "efr32xg1x/sl_rail_util_pa_curves.h"
#elif defined (_SILICON_LABS_32B_SERIES_2_CONFIG_1)
#include "efr32xg21/sl_rail_util_pa_curves.h"
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
#include "efr32xg22/sl_rail_util_pa_curves.h"
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3)
#if defined(_SILICON_LABS_EFR32_SUBGHZ_HP_PA_PRESENT)
#if (_SILICON_LABS_EFR32_SUBGHZ_HP_PA_MAX_OUTPUT_DBM == 20)
#include "efr32xg23/sl_rail_util_pa_curves_20dbm.h"
#elif (_SILICON_LABS_EFR32_SUBGHZ_HP_PA_MAX_OUTPUT_DBM == 10)
#include "efr32xg23/sl_rail_util_pa_curves_10dbm_434M.h"
#else
#include "efr32xg23/sl_rail_util_pa_curves_14dbm.h"
#endif
#else
#error "No valid PA available for selected chip."
#endif
#elif defined (_SILICON_LABS_32B_SERIES_2_CONFIG_4)
#if defined(_SILICON_LABS_EFR32_2G4HZ_HP_PA_PRESENT) \
&& (_SILICON_LABS_EFR32_2G4HZ_HP_PA_MAX_OUTPUT_DBM > 10)
#include "efr32xg24/sl_rail_util_pa_curves_20dbm.h"
#else
#include "efr32xg24/sl_rail_util_pa_curves_10dbm.h"
#endif
#elif defined (_SILICON_LABS_32B_SERIES_2_CONFIG_5)
#include "efr32xg25/sl_rail_util_pa_curves.h"
#elif (_SILICON_LABS_32B_SERIES_2_CONFIG == 7)
#include "efr32xg27/sl_rail_util_pa_curves.h"
#else
#error "Unsupported platform!"
#endif
#ifdef __cplusplus
}
#endif
#endif // PA_CURVES_EFR32_H

View File

@ -0,0 +1,63 @@
/***************************************************************************//**
* @file
* @brief PA power conversion curves used by Silicon Labs PA power conversion
* functions.
* @details This file contains the curves needed convert PA power levels to
* dBm powers.
*******************************************************************************
* # 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_RAIL_UTIL_PA_CONVERSIONS_EFR32_CONFIG_H
#define SL_RAIL_UTIL_PA_CONVERSIONS_EFR32_CONFIG_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef _SILICON_LABS_32B_SERIES_1
#include "efr32xg1x/config/sl_rail_util_pa_config.h"
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_2)
#include "efr32xg22/config/sl_rail_util_pa_config.h"
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_3)
#include "efr32xg23/config/sl_rail_util_pa_config.h"
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_4)
#include "efr32xg24/config/sl_rail_util_pa_config.h"
#elif defined(_SILICON_LABS_32B_SERIES_2_CONFIG_5)
#include "efr32xg25/config/sl_rail_util_pa_config.h"
#elif (_SILICON_LABS_32B_SERIES_2_CONFIG == 7)
#include "efr32xg27/config/sl_rail_util_pa_config.h"
#elif defined (_SILICON_LABS_32B_SERIES_2)
#include "efr32xg21/config/sl_rail_util_pa_config.h"
#else
#error "Unsupported platform!"
#endif
#ifdef __cplusplus
}
#endif
#endif // SL_RAIL_UTIL_PA_CONVERSIONS_EFR32_CONFIG_H

View File

@ -0,0 +1,122 @@
/***************************************************************************//**
* @brief Bluetooth controller HCI API.
*
* This interface is for external use.
*******************************************************************************
* # 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 _SL_BTCTRL_HCI_H_
#define _SL_BTCTRL_HCI_H_
#include <stdint.h>
#include <stdbool.h>
#include "sl_status.h"
//Initialize Vendor Specific Extensions
void sl_bthci_init_vs(void);
void sl_bthci_init_upper(void);
void hci_enableVendorSpecificDebugging(void);
void hci_debugEnable(void);
sl_status_t hci_send_sleep_command_complete(void);
/**
* The Bluetooth controller receives a HCI message fragment from the host.
* The HCI transport can give the HCI message in fragments.
* @param[in] data Pointer to the received data.
* @param[in] len Length of the received data.
* @param[in] lastFragment Indicate whether this is the last
* fragment of an HCI message (true / false).
* @return 0 - success
* -1 - out of memory
* -2 - badly formatted message. */
int16_t sl_btctrl_hci_receive(uint8_t *data, int16_t len, bool lastFragment);
static inline int16_t hci_common_transport_receive(uint8_t *data, int16_t len, bool lastFragment)
{
return sl_btctrl_hci_receive(data, len, lastFragment);
}
/**
* The HCI transport has transmitted a message.
* The HCI can transmit the next message after the transport
* has given this indication. */
void sl_btctrl_hci_transmit_complete(uint32_t status);
static inline void hci_common_transport_transmit_complete(uint32_t status)
{
sl_btctrl_hci_transmit_complete(status);
}
/**
* The HCI transport has been reconnected with the host.
* The HCI can transmit the next message after this function
* has been called. */
void sl_btctrl_hci_transmit_reconnected(void);
static inline void hci_common_transport_transmit_reconnected(void)
{
sl_btctrl_hci_transmit_reconnected();
}
/**
* Host has sent HCI reset command callback handler.
* This is implemented as weak function and can be overridden by application to perform own activities before doing reset.
* It is also possible to call sl_btctrl_hard_reset to start hard reset procedure
*
* @return - true to progress with normal soft reset
* - false if normal reset procedure should be bypassed
*/
bool sl_btctrl_reset_handler(void);
/**
* Hard reset device
* This is called from reset callback handler to implement hard reset
* If HCI packet is in middle of transmit to host, reset will be done after transmit is complete
*/
void sl_btctrl_request_hard_reset(void);
void sl_btctrl_hci_parser_init_conn(void);
void sl_btctrl_hci_parser_init_adv(void);
void sl_btctrl_hci_parser_init_phy(void);
void sl_btctrl_hci_parser_init_past(void);
void sl_btctrl_hci_parser_init_default(void);
/**
* Create hardware error event and try to send it to the host.
* The created event shall be sent as high priority event.
* @param[in] errorCode Code describing the error. */
void sl_btctrl_hci_send_hardware_error_event(uint8_t errorCode);
#endif // _SL_BTCTRL_HCI_H_

View File

@ -0,0 +1,229 @@
/***************************************************************************//**
* @brief Bluetooth Link Layer configuration API
*******************************************************************************
* # 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 _SL_BTCTRL_LINKLAYER_H_
#define _SL_BTCTRL_LINKLAYER_H_
#include "sl_status.h"
#include <stdint.h>
void sl_bt_controller_init(void);
void sl_bt_controller_deinit(void);
void sl_btctrl_init(void);
/**
* Allocate memory buffers for controller
*
* @param memsize size of memory to allocate
* @returns number of memory buffers allocated
*/
uint32_t sl_btctrl_init_mem(uint32_t memsize);
/**
* Configures how many maximum sized ACL data packets
* can the controller store.
*/
void sl_btctrl_configure_le_buffer_size(uint8_t count);
/**
* Release all memory allocated by controller
*/
void sli_btctrl_deinit_mem(void);
void sli_btctrl_set_interrupt_priorities();
sl_status_t sl_btctrl_init_ll(void);
void sli_btctrl_set_address(uint8_t *address);
//Initialize memory objects used by LinkLayer
//In future these should be configured individually
sl_status_t sl_btctrl_init_basic(uint8_t connections, uint8_t adv_sets, uint8_t whitelist);
void sli_btctrl_events_init(void);
enum sl_btctrl_channelmap_flags{
SL_BTCTRL_CHANNELMAP_FLAG_ACTIVE_ADAPTIVITY = 0x01,
SL_BTCTRL_CHANNELMAP_FLAG_PASSIVE_ADAPTIVITY= 0x02,
};
/**
* Initialize and enable adaptive frequency hopping
*/
sl_status_t sl_btctrl_init_afh(uint32_t flags);
/**
* Enable high power use under appropriate conditions
*/
void sl_btctrl_init_highpower(void);
/**
* @brief Initilize periodic advertiser
*/
void sl_btctrl_init_periodic_adv();
/**
* @brief Initilize periodic advertiser
*/
void sl_btctrl_init_periodic_scan();
/**
* @brief Enable and initialize support for the PAWR advertiser.
* @param[in] num_adv Number of advertising sets supporting PAWR.
* If set to zero, previously allocated PAWR sets are only freed.
* @return SL_STATUS_OK, or an appropriate error code.
*/
sl_status_t sl_btctrl_pawr_advertiser_configure(uint8_t max_pawr_sets);
/**
* @brief Enable and initialize support for PAWR sync/receiver.
* @return SL_STATUS_OK, or an appropriate error code. */
sl_status_t sl_btctrl_pawr_synchronizer_configure(void);
/**
* @brief Allocate memory for synchronized scanners
*
* @param num_scan Number of Periodic Scanners Allowed
* @return SL_STATUS_OK if allocation was succesfull, failure reason otherwise
*/
sl_status_t sl_btctrl_alloc_periodic_scan(uint8_t num_scan);
/**
* @brief Allocate memory for periodic advertisers
*
* @param num_adv Number of advertisers to allocate
*/
sl_status_t sl_btctrl_alloc_periodic_adv(uint8_t num_adv);
/**
* Call to enable the even connection scheduling algorithm.
* This function should be called before link layer initialization.
*/
void sl_btctrl_enable_even_connsch();
/**
* Call to initialize multiprotocol
* in bluetooth controller
*/
void sl_btctrl_init_multiprotocol();
/**
* Link with symbol to enable radio watchdog
*/
void sl_btctrl_enable_radio_watchdog();
/**
* Initialize CTE receiver
*/
sl_status_t sl_btctrl_init_cte_receiver();
/**
* Initialize CTE transmitter
*/
sl_status_t sl_btctrl_init_cte_transmitter();
/**
* Initialize both CTE receiver and transmitter
*
* Note: This is for backward compatibility. It is recommend to
* use sl_btctrl_init_cte_receiver and sl_btctrl_init_cte_transmitter
* functions instead.
*/
sl_status_t sl_btctrl_init_cte();
/**
* Check if event bitmap indicates pending events
* @return bool pending events
*/
bool sli_pending_btctrl_events(void);
/**
* Disable the support for Coded and Simulscan PHYs.
*/
void sl_btctrl_disable_coded_phy(void);
/**
* Disable the support for 2M PHY.
*/
void sl_btctrl_disable_2m_phy(void);
/**
* Initialize adv component
*/
void sl_btctrl_init_adv(void);
void sl_btctrl_init_conn(void);
void sl_btctrl_init_phy(void);
void sl_btctrl_init_adv_ext(void);
/**
* @brief Initialize extended scanner state
*
*/
void sl_btctrl_init_scan_ext(void);
void sl_btctrl_init_scan(void);
/**
* @brief return true if controller is initialized
*
*/
bool sl_btctrl_is_initialized();
/**
* @brief Sets PAST initiator feature bit,
* and links in PAST sender and ll_adv_sync symbols to the project.
*/
void sl_btctrl_init_past_local_sync_transfer(void);
/**
* @brief Sets PAST initiator feature bit,
* and links in PAST sender, ll_scan_sync and ll_scan_sync_registry symbols to the project.
*/
void sl_btctrl_init_past_remote_sync_transfer(void);
/**
* @brief Sets PAST receiver feature bit,
* and links in PAST receiver, ll_scan_sync and ll_scan_sync_registry symbols to the project.
*/
void sl_btctrl_init_past_receiver(void);
/**
* @brief Configure how often to send the Number Of Completed Packets HCI event.
* @param[in] packets When the controller has transmitted this number of ACL data packets it will send
* the Number Of Completed Packets HCI event to the host.
* @param[in] events When this number of connection events have passed and the controller did not yet report
* all the transmitted packets, then it will send the Number Of Completed Packets HCI event to the host.
*/
void sl_btctrl_configure_completed_packets_reporting(uint8_t packets, uint8_t events);
#endif

View File

@ -0,0 +1,73 @@
/***************************************************************************//**
* @brief The API between HCI and common HCI transport.
*
* The interface configuration shall be done using UC configuration.
*******************************************************************************
* # 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 _HCI_COMMON_TRANSPORT_H_
#define _HCI_COMMON_TRANSPORT_H_
#include <stdbool.h>
#include <stdint.h>
#include "sl_btctrl_hci.h"
/**
* The HCI receives a message from currently selected transport layer.
* The HCI transport calls this function implemented in the HCI
* once it has received a complete HCI message. If the HCI does not
* manage to process the message, the transport may drop the message.
* @param[in] data Pointer to the received data.
* @param[in] len Length of the received data.
* @param[in] lastFragment Indicates if this is the last fragment of
* a complete HCI message.
* @return 0 - success
* -1 - out of memory
* -2 - badly formatted message. */
int16_t hci_common_transport_receive(uint8_t *data, int16_t len, bool lastFragment);
/**
* Transmit HCI message using the currently used transport layer.
* The HCI calls this function to transmit a full HCI message.
* @param[in] data Data buffer to be transmitted.
* @param[in] len Length of the data.
* @return 0 - on success, or non-zero on failure. */
uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len);
/**
* The HCI transport indicates a message has been transmitted. */
void hci_common_transport_transmit_complete(uint32_t status);
/**
* The HCI transport has been reconnected with the host. */
void hci_common_transport_transmit_reconnected(void);
/**
* Initialize the currently selected transport layer. */
void hci_common_transport_init(void);
#endif // _COMMON_TRANSPORT_H_

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -35,7 +35,7 @@
#if defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT) || defined(DOXYGEN)
/***************************************************************************//**
* @addtogroup sl_se_manager Secure Element Manager
* @addtogroup sl_se_manager Secure Engine Manager
*
* @note The APIs are thread-safe.
*
@ -46,7 +46,7 @@
* @addtogroup sl_se_manager_core Core
*
* @brief
* Secure Element Manager Core API
* Secure Engine Manager Core API
*
* @details
* API for initialization of SE Manager and SE command context with yield
@ -55,9 +55,12 @@
* @{
******************************************************************************/
#include "sl_se_manager_key_handling.h"
#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 "sl_se_manager_cipher.h"
#include "em_se.h"
#include "sl_status.h"
#include <stdint.h>
@ -96,6 +99,60 @@ sl_status_t sl_se_init(void);
******************************************************************************/
sl_status_t sl_se_deinit(void);
#if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT) || defined(DOXYGEN)
/***************************************************************************//**
* @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 || DOXYGEN
#if defined(CRYPTOACC_PRESENT) || defined(DOXYGEN)
/***************************************************************************//**
* @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(CRYPTOACC_PRESENT)
/***************************************************************************//**
* @brief
* Initialize an SE command context object
@ -134,59 +191,6 @@ sl_status_t sl_se_init_command_context(sl_se_command_context_t *cmd_ctx);
******************************************************************************/
sl_status_t sl_se_deinit_command_context(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @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);
#if defined(CRYPTOACC_PRESENT) || defined(DOXYGEN)
/***************************************************************************//**
* @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(CRYPTOACC_PRESENT)
#ifdef __cplusplus
}
#endif
@ -199,20 +203,32 @@ sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx);
#endif // SL_SE_MANAGER_H
// THE REST OF THE FILE IS DOCUMENTATION ONLY
/// @addtogroup sl_se_manager Secure Element Manager API
/// @brief Silicon Labs Secure Element Manager
/// @addtogroup sl_se_manager Secure Engine Manager API
/// @brief Silicon Labs Secure Engine Manager
/// @{
///
/// @details
/// # Introduction
///
/// The Secure Element (SE) Manager provides thread-safe APIs for the Secure Element's mailbox interface.
/// The SE Manager will use the SE hardware peripherals to accelerate cryptographic operations.
/// The Secure Engine (SE) Manager provides thread-safe APIs for the Secure Engine's mailbox interface. Note that PSA Crypto is the main device independant crypto API and should be used
/// whenever possible, see @ref ls_psa_usage. However, 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
@ -242,9 +258,8 @@ sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx);
/// - Read SE OTP contents
/// - Read SE firmware version
/// - Read provisioned certificates
/// - Multi-thread safe APIs for MicriumOS, FreeRTOS and Zephyr OS
///
/// For a full overview of the available APIs, see @ref sl_se_manager.
/// - Multi-thread safe APIs for MicriumOS and FreeRTOS
/// - Retrieveing attestation tokens (@ref sl_se_manager_attestation)
///
/// ## Key Storage and Use of SE Wrapped Keys
///
@ -359,7 +374,7 @@ sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx);
///
/// ## Tamper
///
/// The Secure Element (SE) tamper module connects a number of hardware and software-driven tamper signals to a set of configurable hardware and software responses.
/// 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,
@ -431,22 +446,25 @@ sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx);
///
/// ## RTOS Mode and Multi-Thread Safety
///
/// The SE Manager supports multi-thread safe APIs for MicriumOS, FreeRTOS and Zephyr OS.
/// @note The SE Manager API is multi-thread safe, but does not support preemption.
/// This means the API cannot be called from ISR or critical/atomic sections when running in an RTOS thread.
/// When using the SE Manager API in a bare-metal application, it is the application developer's responsibility
/// to not call the SE Manager APIs when another operation is in progress.
///
/// The SE Manager supports multi-thread safe APIs for MicriumOS and FreeRTOS interfacing with CMSIS RTOS2 APIs.
///
/// For MicriumOS support the user application must define the compile time option SL_CATALOG_MICRIUMOS_KERNEL_PRESENT.
/// For FreeRTOS support the user application must define the compile time option SL_CATALOG_FREERTOS_KERNEL_PRESENT.
/// For Zephyr OS support the user application must define the compile time option SL_CATALOG_ZEPHYR_KERNEL_PRESENT.
/// For bare metal mode (non-RTOS) the user must not define SL_CATALOG_MICRIUMOS_KERNEL_PRESENT, SL_CATALOG_FREERTOS_KERNEL_PRESENT or SL_CATALOG_ZEPHYR_KERNEL_PRESENT.
/// For bare metal mode (non-RTOS) the user must not define SL_CATALOG_MICRIUMOS_KERNEL_PRESENT or SL_CATALOG_FREERTOS_KERNEL_PRESENT.
///
/// Applications created using Simplicity Studio 5 need to include the header file called _sl_component_catalog.h_ which will include a macro define for one of the abovementioned RTOSes if present.
///
/// In the cases with SL_CATALOG_MICRIUMOS_KERNEL_PRESENT, SL_CATALOG_FREERTOS_KERNEL_PRESENT or SL_CATALOG_ZEPHYR_KERNEL_PRESENT defined (RTOS-mode), the SE Manager will be configured with threading and yield support.
/// Configure ::sl_se_command_context_t with ::sl_se_set_yield to yield the CPU core when the SE Manager is waiting for the Secure Element to complete a mailbox command.
/// In the cases with SL_CATALOG_MICRIUMOS_KERNEL_PRESENT or SL_CATALOG_FREERTOS_KERNEL_PRESENT defined (RTOS-mode), the SE Manager will be configured with threading and yield support.
/// Configure ::sl_se_command_context_t with ::sl_se_set_yield to yield the CPU core when the SE Manager is waiting for the Secure Engine to complete a mailbox command.
///
/// For threading support the SE Manager applies an SE lock mechanism (_mutex_ in MicriumOS, _semaphore_ in FreeRTOS and both in Zephyr OS)
/// to protect the Secure Element 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.
/// 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

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -32,7 +32,9 @@
#include "em_device.h"
#if defined(SEMAILBOX_PRESENT) || defined(DOXYGEN)
#if (defined(SEMAILBOX_PRESENT) \
&& (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)) \
|| defined(DOXYGEN)
/// @addtogroup sl_se_manager
/// @{
@ -61,8 +63,6 @@
extern "C" {
#endif
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
// -----------------------------------------------------------------------------
// Defines
@ -93,7 +93,9 @@ extern "C" {
* Buffer where the output token will be stored.
*
* @param[in] token_buf_size
* Size of token_buf in bytes.
* 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.
@ -123,10 +125,10 @@ sl_status_t sl_se_attestation_get_psa_iat_token(sl_se_command_context_t *cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] challenge_size
* Pointer to sl_se_key_descriptor_t structure.
* Size of the challenge object in bytes. Must be either 32, 48 or 64.
*
* @param[out] token_size
* Buffer holding the input data.
* Pointer to output word. Result is stored here.
*
* @return
* Status code, @ref sl_status.h.
@ -152,7 +154,9 @@ sl_status_t sl_se_attestation_get_psa_iat_token_size(sl_se_command_context_t *cm
* Buffer where the output token will be stored.
*
* @param[in] token_buf_size
* Size of token_buf in bytes.
* 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.
@ -182,10 +186,10 @@ sl_status_t sl_se_attestation_get_config_token(sl_se_command_context_t *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.
* Size of the challenge object in bytes. Must be 32.
*
* @param[out] token_size
* Number of bytes actually used in token_buf.
* Pointer to output word. Result is stored here.
*
* @return
* Status code, @ref sl_status.h.
@ -194,8 +198,6 @@ sl_status_t sl_se_attestation_get_config_token_size(sl_se_command_context_t *cmd
size_t challenge_size,
size_t *token_size);
#endif // (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#ifdef __cplusplus
}
#endif
@ -203,6 +205,6 @@ sl_status_t sl_se_attestation_get_config_token_size(sl_se_command_context_t *cmd
/// @} (end addtogroup sl_se_manager_attestation)
/// @} (end addtogroup sl_se_manager)
#endif // defined(SEMAILBOX_PRESENT)
#endif // SEMAILBOX_PRESENT && VAULT
#endif // SL_SE_MANAGER_ATTESTATION_H

View File

@ -45,7 +45,7 @@
#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_CATALOG_ZEPHYR_KERNEL_PRESENT)) \
#if (defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) || defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)) \
&& !defined(SL_SE_MANAGER_THREADING)
#error "RTOS requires threading mode."
#endif

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -46,7 +46,7 @@
* @details
* API for performing symmetric encryption, Authenticated Encryption and
* Additional Data (AEAD) operations, and computing Message Authentication
* Codes (MACs) using the Secure Element.
* Codes (MACs) using the Secure Engine.
*
* @{
******************************************************************************/
@ -339,7 +339,7 @@ sl_status_t sl_se_ccm_encrypt_and_tag(sl_se_command_context_t *cmd_ctx,
* The buffer holding the tag.
*
* @param[in] tag_len
* The length of the tag in Bytes.
* The length of the tag in Bytes. Must be 4, 6, 8, 10, 12, 14 or 16.
*
* @return
* Status code, @ref sl_status.h.
@ -353,6 +353,145 @@ sl_status_t sl_se_ccm_auth_decrypt(sl_se_command_context_t *cmd_ctx,
unsigned char *output,
const unsigned char *tag, size_t tag_len);
/***************************************************************************//**
* @brief
* Prepare a CCM streaming command context object.
*
* @details
* Prepare a CCM streaming command context object to be used in subsequent
* CCM streaming function calls.
*
* @param[in] ccm_ctx
* Pointer to a CCM streaming context object.
*
* @param[in] cmd_ctx
* Pointer to a SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] mode
* The operation to perform: SL_SE_ENCRYPT or SL_SE_DECRYPT.
*
* @param[in] total_message_length
* The total length of the text to encrypt/decrypt
*
* @param[in] iv
* The initialization vector (commonly referred to as nonce for CCM).
*
* @param[in] iv_len
* The length of the IV.
*
* @param[in] add
* The buffer holding the additional data.
*
* @param[in] add_len
* The length of the additional data.
*
* @param[in] tag_len
* Encryption: The length of the tag to generate. Must be 0, 4, 6, 8, 10, 12, 14 or 16.
* Decryption: The length of the tag to authenticate. Must be 0, 4, 6, 8, 10, 12, 14 or 16.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_ccm_multipart_starts(sl_se_ccm_multipart_context_t *ccm_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
sl_se_cipher_operation_t mode,
uint32_t total_message_length,
const uint8_t *iv,
size_t iv_len,
const uint8_t *add,
size_t add_len,
size_t tag_len);
/***************************************************************************//**
* @brief
* This function feeds an input buffer into an ongoing CCM computation.
*
* It is called between sl_se_ccm_multipart_starts() and sl_se_ccm_multipart_finish().
* Can be called repeatedly.
*
* @param[in] ccm_ctx
* Pointer to a CCM streaming context object.
*
* @param[in] cmd_ctx
* Pointer to a SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] length
* The length of the input data. This must be a multiple of 16 except in
* the last call before sl_se_ccm_multipart_finish().
*
* @param[in] input
* Buffer holding the input data, must be at least @p length bytes wide.
*
* @param[out] output
* Buffer for holding the output data, must be at least @p length bytes wide.
*
* @param[out] output_length
* Length of data that has been encrypted/decrypted.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_ccm_multipart_update(sl_se_ccm_multipart_context_t *ccm_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
size_t length,
const uint8_t *input,
uint8_t *output,
size_t *output_length);
/***************************************************************************//**
* @brief
* Finish a CCM streaming operation and return the resulting CCM tag.
*
* It is called after sl_se_ccm_multipart_update().
*
* @param[in] ccm_ctx
* Pointer to a CCM streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in, out] tag
* Encryption: The buffer for holding the tag.
* Decryption: The tag to authenticate.
*
* @param[in] tag_size
* The size of the tag buffer. Must be equal or greater to the length of the expected tag.
*
* @param[out] output
* Buffer for holding the output data.
*
* @param[in] output_size
* Output buffer size. Must be equal or greater to the stored data from
* sl_se_ccm_multipart_update (maximum 16 bytes).
*
* @param[out] output_length
* Length of data that has been encrypted/decrypted.
*
* @return
* Returns SL_SE_INVALID_SIGNATURE if authentication step fails.
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_ccm_multipart_finish(sl_se_ccm_multipart_context_t *ccm_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
uint8_t *tag,
uint8_t tag_size,
uint8_t *output,
uint8_t output_size,
uint8_t *output_length);
/***************************************************************************//**
* @brief
* This function performs GCM encryption or decryption of a buffer.
@ -540,16 +679,76 @@ sl_status_t sl_se_cmac(sl_se_command_context_t *cmd_ctx,
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_cmac_multipart_starts(sl_se_cmac_multipart_context_t *cmac_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_cmac_multipart_starts().
*
* Prepare a CMAC streaming command context object.
*
* @details
* Prepare a CMAC streaming command context object to be used in subsequent
* CMAC streaming function calls.
*
* @param[in] cmac_ctx
* Pointer to a CMAC streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_cmac_starts(sl_se_cmac_streaming_context_t *cmac_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key);
const sl_se_key_descriptor_t *key) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
* This function feeds an input buffer into an ongoing CMAC computation.
*
* @details
* It is called between sl_se_cmac_starts() and sl_se_cmac_finish().
* It is called between sl_se_cmac_multipart_starts() and sl_se_cmac_multipart_finish().
* Can be called repeatedly.
*
* @param[in,out] cmac_ctx
* Pointer to a CMAC streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] input
* Buffer holding the input data, must be at least @p input_len 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_cmac_multipart_update(sl_se_cmac_multipart_context_t *cmac_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
const uint8_t *input,
size_t input_len);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_cmac_multipart_update().
*
* This function feeds an input buffer into an ongoing CMAC computation.
*
* @details
* It is called between sl_se_cmac_multipart_starts() and sl_se_cmac_multipart_finish().
* Can be called repeatedly.
*
* @param[in,out] cmac_ctx
@ -564,15 +763,45 @@ sl_status_t sl_se_cmac_starts(sl_se_cmac_streaming_context_t *cmac_ctx,
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_cmac_update(sl_se_cmac_streaming_context_t *cmac_ctx,
const uint8_t *input,
size_t input_len);
size_t input_len) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
* Finish a CMAC streaming operation and return the resulting CMAC tag.
*
* @details
* It is called after sl_se_cmac_multipart_update().
*
* @param[in,out] cmac_ctx
* Pointer to a CMAC streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[out] output
* Buffer holding the 16-byte CMAC tag, must be at least 16 bytes wide.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_cmac_multipart_finish(sl_se_cmac_multipart_context_t *cmac_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
uint8_t *output);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_cmac_multipart_finish().
*
* Finish a CMAC streaming operation and return the resulting CMAC tag.
*
* @details
* It is called after sl_se_cmac_update().
*
* @param[in,out] cmac_ctx
@ -585,12 +814,13 @@ sl_status_t sl_se_cmac_update(sl_se_cmac_streaming_context_t *cmac_ctx,
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_cmac_finish(sl_se_cmac_streaming_context_t *cmac_ctx,
uint8_t *output);
uint8_t *output) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
* Prepare a GCM streaming command context object.
* Deprecated, please switch to using \ref sl_se_gcm_multipart_starts().
*
* Prepare a GCM streaming command context object.
* @details
* Prepare a GCM streaming command context object to be used in subsequent
* GCM streaming function calls.
@ -629,10 +859,56 @@ sl_status_t sl_se_gcm_starts(sl_se_gcm_streaming_context_t *gcm_ctx,
const uint8_t *iv,
size_t iv_len,
const uint8_t *add,
size_t add_len);
size_t add_len) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
* Prepare a GCM streaming command context object.
*
* @details
* Prepare a GCM streaming command context object to be used in subsequent
* GCM streaming function calls.
*
* @param[in, out] gcm_ctx
* Pointer to a GCM streaming context object.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @param[in] key
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] mode
* The operation to perform: SL_SE_ENCRYPT or SL_SE_DECRYPT.
*
* @param[in] iv
* The initialization vector.
*
* @param[in] iv_len
* The length of the IV.
*
* @param[in] add
* The buffer holding the additional data, or NULL if @p add_len is 0.
*
* @param[in] add_len
* The length of the additional data. If 0, @p add is NULL.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_gcm_multipart_starts(sl_se_gcm_multipart_context_t *gcm_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
sl_se_cipher_operation_t mode,
const uint8_t *iv,
size_t iv_len,
const uint8_t *add,
size_t add_len);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_gcm_multipart_update().
*
* This function feeds an input buffer into an ongoing GCM computation.
*
* It is called between sl_se_gcm_starts() and sl_se_gcm_finish().
@ -657,10 +933,45 @@ sl_status_t sl_se_gcm_starts(sl_se_gcm_streaming_context_t *gcm_ctx,
sl_status_t sl_se_gcm_update(sl_se_gcm_streaming_context_t *gcm_ctx,
size_t length,
const uint8_t *input,
uint8_t *output);
uint8_t *output) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
* This function feeds an input buffer into an ongoing GCM computation.
*
* It is called between sl_se_gcm_multipart_starts() and sl_se_gcm_multiapart_finish().
* Can be called repeatedly.
*
* @param[in, out] gcm_ctx
* Pointer to a GCM streaming context object.
*
* @param[in] length
* The length of the input data.
*
* @param[in] input
* Buffer holding the input data, must be at least @p length bytes wide.
*
* @param[out] output
* Buffer for holding the output data, must be at least @p length bytes wide.
*
* @param[out] output_length
* Length of data that has been encrypted/decrypted.
*
* @return
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_gcm_multipart_update(sl_se_gcm_multipart_context_t *gcm_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
size_t length,
const uint8_t *input,
uint8_t *output,
size_t *output_length);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_gcm_multipart_finish().
*
* Finish a GCM streaming operation and return the resulting GCM tag.
*
* It is called after sl_se_gcm_update().
@ -679,7 +990,47 @@ sl_status_t sl_se_gcm_update(sl_se_gcm_streaming_context_t *gcm_ctx,
******************************************************************************/
sl_status_t sl_se_gcm_finish(sl_se_gcm_streaming_context_t *gcm_ctx,
uint8_t *tag,
size_t tag_len);
size_t tag_len) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
* Finish a GCM streaming operation and return the resulting GCM tag.
*
* It is called after sl_se_gcm_multipart_update().
*
* @param[in, out] gcm_ctx
* Pointer to a GCM streaming context object.
*
* @param[in, out] tag
* Encryption: The buffer for holding the tag.
* Decryption: The tag to authenticate.
*
* @param[in] tag_length
* Encryption: Length of the output tag.
* Decryption: Length of tag to verify
*
* @param[out] output
* Buffer for holding the output data.
*
* @param[in] output_size
* Output buffer size. Must be equal or greater to the stored data from
* sl_se_gcm_multipart_update (stored data is maximum 16 bytes).
*
* @param[out] output_length
* Length of data that has been encrypted/decrypted.
*
* @return
* Returns SL_SE_INVALID_SIGNATURE if authentication step fails.
* Status code, @ref sl_status.h.
******************************************************************************/
sl_status_t sl_se_gcm_multipart_finish(sl_se_gcm_multipart_context_t *gcm_ctx,
sl_se_command_context_t *cmd_ctx,
const sl_se_key_descriptor_t *key,
uint8_t *tag,
uint8_t tag_length,
uint8_t *output,
uint8_t output_size,
uint8_t *output_length);
/***************************************************************************//**
* @brief

View File

@ -36,10 +36,10 @@
/// of the configuration options in this file.
#if defined (SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#include "sl_component_catalog.h"
#endif
#if defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) || defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) || defined(SL_CATALOG_ZEPHYR_KERNEL_PRESENT)
#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

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API definitions
* @brief Silicon Labs Secure Engine Manager API definitions
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -34,14 +34,16 @@
#if defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT) || defined(DOXYGEN)
#if !defined(SL_TRUSTZONE_NONSECURE)
#if !defined(SE_MANAGER_CONFIG_FILE)
#include "sl_se_manager_config.h"
#else
#include SE_MANAGER_CONFIG_FILE
#endif
#endif
#if defined (SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#include "sl_component_catalog.h"
#endif
/// @addtogroup sl_se_manager
@ -139,30 +141,39 @@ extern "C" {
/// 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) || defined(DOXYGEN)
/// Symmetric key type for ChaCha20
#define SL_SE_KEY_TYPE_CHACHA20 0x00000020
/// 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-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 X25519 key for ECDH
#define SL_SE_KEY_TYPE_ECC_X25519 (SL_SE_KEY_TYPE_ECC_MONTGOMERY | (0x20))
/// 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
@ -201,6 +212,11 @@ extern "C" {
#define SL_SE_KEY_SLOT_VOLATILE_3 0x03 ///< Internal volatile slot 3
#endif
/// Minimum key slot value for internal keys
#define SL_SE_KEY_SLOT_INTERNAL_MIN 0xF7
/// 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)
@ -216,6 +232,19 @@ extern "C" {
#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
/// @{
@ -228,14 +257,12 @@ extern "C" {
/// Certificate signature size
#define SL_SE_CERT_SIGN_SIZE 64
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
/// Batch ID certificate
#define SL_SE_CERT_BATCH 0x01
#define SL_SE_CERT_BATCH 0x01
/// SE ID certificate
#define SL_SE_CERT_DEVICE_SE 0x02
#define SL_SE_CERT_DEVICE_SE 0x02
/// Host ID certificate
#define SL_SE_CERT_DEVICE_HOST 0x03
#endif
#define SL_SE_CERT_DEVICE_HOST 0x03
/// @addtogroup sl_se_manager_util_tamper Tamper options
/// @brief
@ -250,6 +277,8 @@ extern "C" {
#define SL_SE_TAMPER_LEVEL_PERMANENTLY_ERASE_OTP 7 ///< Erase OTP - THIS WILL MAKE THE DEVICE INOPERATIONAL!
// SE tamper signals
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
#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
@ -284,6 +313,45 @@ extern "C" {
#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
#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

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -42,9 +42,9 @@
*
* @brief
* Random number generators
*
* @details
* API for getting randomness from the Secure Element True Random Number
*
* API for getting randomness from the Secure Engine True Random Number
* Generator (TRNG).
*
* @{

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -109,6 +109,29 @@ sl_status_t sl_se_hash(sl_se_command_context_t *cmd_ctx,
*
* @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
* Deprecated, please switch to using \ref sl_se_hash1_multipart_starts().
*
* 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_update() and
* sl_se_hash_finish().
*
@ -126,7 +149,7 @@ sl_status_t sl_se_hash(sl_se_command_context_t *cmd_ctx,
******************************************************************************/
sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha1_streaming_context_t *sha1_ctx);
sl_se_sha1_streaming_context_t *sha1_ctx) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
@ -134,6 +157,29 @@ sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
*
* @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
* Deprecated, please switch to using \ref sl_se_hash224_multipart_starts().
*
* 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_update() and
* sl_se_hash_finish().
*
@ -151,7 +197,7 @@ sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
******************************************************************************/
sl_status_t sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha224_streaming_context_t *sha224_ctx);
sl_se_sha224_streaming_context_t *sha224_ctx) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
@ -159,6 +205,29 @@ sl_status_t sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
*
* @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);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_hash256_multipart_starts().
*
* 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_update() and
* sl_se_hash_finish().
*
@ -176,7 +245,7 @@ sl_status_t sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
******************************************************************************/
sl_status_t sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha256_streaming_context_t *sha256_ctx);
sl_se_sha256_streaming_context_t *sha256_ctx) SL_DEPRECATED_API_SDK_3_3;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
/***************************************************************************//**
@ -185,6 +254,29 @@ sl_status_t sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
*
* @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
* Deprecated, please switch to using \ref sl_se_hash384_multipart_starts().
*
* 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_update() and
* sl_se_hash_finish().
*
@ -202,7 +294,7 @@ sl_status_t sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
******************************************************************************/
sl_status_t sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha384_streaming_context_t *sha384_ctx);
sl_se_sha384_streaming_context_t *sha384_ctx) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @brief
@ -210,6 +302,29 @@ sl_status_t sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
*
* @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);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_hash512_multipart_starts().
*
* 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_update() and
* sl_se_hash_finish().
*
@ -227,7 +342,7 @@ sl_status_t sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
******************************************************************************/
sl_status_t sl_se_hash_sha512_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha512_streaming_context_t *sha512_ctx);
sl_se_sha512_streaming_context_t *sha512_ctx) SL_DEPRECATED_API_SDK_3_3;
#endif // (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
@ -236,6 +351,35 @@ sl_status_t sl_se_hash_sha512_starts(sl_se_hash_streaming_context_t *hash_ctx,
*
* @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
* Deprecated, please switch to using \ref sl_se_hash_multipart_starts().
*
* 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_update()
* and sl_se_hash_finish().
*
@ -258,12 +402,43 @@ sl_status_t sl_se_hash_sha512_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_status_t sl_se_hash_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_hash_type_t hash_type,
void *hash_type_ctx);
void *hash_type_ctx) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @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
* Deprecated, please switch to using \ref sl_se_hash_multipart_update().
*
* Feeds an input buffer into an ongoing hash computation.
*
* This function is called between @ref sl_se_hash_starts() and
* @ref sl_se_hash_finish().
* This function can be called repeatedly.
@ -282,12 +457,43 @@ sl_status_t sl_se_hash_starts(sl_se_hash_streaming_context_t *hash_ctx,
******************************************************************************/
sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
const uint8_t *input,
size_t input_len);
size_t input_len) SL_DEPRECATED_API_SDK_3_3;
/***************************************************************************//**
* @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);
/***************************************************************************//**
* @brief
* Deprecated, please switch to using \ref sl_se_hash_multipart_finish().
*
* Finish a hash streaming operation and return the resulting hash digest.
*
* This function is called after sl_se_hash_update().
*
* @param[in] hash_ctx
@ -306,7 +512,7 @@ sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
******************************************************************************/
sl_status_t sl_se_hash_finish(sl_se_hash_streaming_context_t *hash_ctx,
uint8_t *digest_out,
size_t digest_len);
size_t digest_len) SL_DEPRECATED_API_SDK_3_3;
#ifdef __cplusplus
}

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager Internal key defines
* @brief Silicon Labs Secure Engine Manager Internal key defines
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -35,6 +35,7 @@
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
/// Key descriptor for internal application attestation key
#define SL_SE_APPLICATION_ATTESTATION_KEY \
{ \
@ -50,6 +51,22 @@
}, \
}, \
}
#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
@ -111,4 +128,16 @@
}, \
}
/// 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

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -366,7 +366,7 @@ sl_status_t sl_se_ecjpake_write_round_two(sl_se_ecjpake_context_t *ctx,
*
* @param[in,out] out_key
* Pointer to the generated key material. The length member of out_key is
* used to request a given lenght of the generated key.
* used to request a given length of the generated key.
*
* @return
* SL_STATUS_OK if the signature is successfully verified, otherwise an
@ -391,8 +391,11 @@ sl_status_t sl_se_derive_key_hkdf(sl_se_command_context_t *cmd_ctx,
* @param[in] in_key
* Pointer to the input key material.
*
* @param[in] hash
* Which hashing algorithm to use.
* @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).
@ -405,7 +408,7 @@ sl_status_t sl_se_derive_key_hkdf(sl_se_command_context_t *cmd_ctx,
*
* @param[in,out] out_key
* Pointer to the generated key material. The length member of out_key is
* used to request a given lenght of the generated key.
* used to request a given length of the generated key.
*
* @return
* SL_STATUS_OK if the signature is successfully verified, otherwise an
@ -413,7 +416,7 @@ sl_status_t sl_se_derive_key_hkdf(sl_se_command_context_t *cmd_ctx,
******************************************************************************/
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_hash_type_t hash,
sl_se_pbkdf2_prf_type_t prf,
const unsigned char *salt,
size_t salt_len,
uint32_t iterations,

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager key handling.
* @brief Silicon Labs Secure Engine Manager key handling.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -50,7 +50,7 @@ extern "C" {
/***************************************************************************//**
* \addtogroup sl_se_manager_key_handling Key handling
*
* \brief Secure Element key handling API.
* \brief Secure Engine key handling API.
*
* \details
* API for using cryptographic keys with the SE. Contains functionality to

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -87,10 +87,12 @@ extern "C" {
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] hash_alg
* Which hashing algorithm to use.
* 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.
* 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.
@ -139,10 +141,12 @@ sl_status_t sl_se_ecc_sign(sl_se_command_context_t *cmd_ctx,
* Pointer to sl_se_key_descriptor_t structure.
*
* @param[in] hash_alg
* Which hashing algorithm to use.
* 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.
* 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.

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API types
* @brief Silicon Labs Secure Engine Manager API types
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -78,6 +78,7 @@ 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 {
@ -88,7 +89,6 @@ typedef struct {
/// SE certificate types
typedef uint8_t sl_se_cert_type_t;
#endif // _SILICON_LABS_SECURITY_FEATURE_VAULT
/// OTP initialization data structure
typedef struct {
@ -331,15 +331,42 @@ typedef enum {
/// CMAC streaming context
typedef struct {
sl_se_command_context_t *cmd_ctx; ///< Pointer to command context object
const sl_se_key_descriptor_t *key; ///< Pointer to key object
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;
/// CMAC streaming context. Deprecated.
typedef struct {
sl_se_command_context_t *cmd_ctx; ///< Pointer to command context object
const sl_se_key_descriptor_t *key; ///< Pointer to key object
sl_se_cmac_multipart_context_t cmac_ctx; ///< CMAC streaming context
} sl_se_cmac_streaming_context_t;
/// GCM streaming context
/// 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 (_SILICON_LABS_32B_SERIES_2_CONFIG == 1)
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;
#endif
uint8_t final_data_length; ///< Length of data saved
} sl_se_ccm_multipart_context_t;
/// GCM streaming context. Deprecated.
typedef struct {
sl_se_command_context_t *cmd_ctx; ///< Pointer to command context object
const sl_se_key_descriptor_t *key;///< Pointer to key object
@ -352,6 +379,20 @@ typedef struct {
bool last_op; ///< Last operation / update
} sl_se_gcm_streaming_context_t;
typedef struct {
uint64_t len; ///< Total length of the encrypted data
uint64_t add_len; ///< Total length of the additional data
#if (_SILICON_LABS_32B_SERIES_2_CONFIG < 3)
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
@ -369,7 +410,7 @@ typedef enum {
#endif
} sl_se_hash_type_t;
/// Generic hash streaming context
/// Generic hash streaming context. Deprecated.
typedef struct {
sl_se_command_context_t *cmd_ctx; ///< Pointer to command context object
sl_se_hash_type_t hash_type; ///< Hash type
@ -377,21 +418,45 @@ typedef struct {
void *hash_type_ctx; ///< Pointer to hash specific context
} sl_se_hash_streaming_context_t;
/// SHA-1 streaming context
/// SHA-1 streaming context. Safe to use.
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-1 streaming context. Deprecated.
typedef struct {
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_streaming_context_t;
/// SHA-224 streaming context
/// SHA-224 streaming context. Safe to use.
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-224 streaming context. Deprecated.
typedef struct {
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_streaming_context_t;
/// SHA-256 streaming context
/// SHA-256 streaming context. Safe to use.
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;
/// SHA-256 streaming context. Deprecated.
typedef struct {
uint32_t total[2]; ///< Number of bytes processed
uint8_t state[32]; ///< Intermediate digest state
@ -399,14 +464,30 @@ typedef struct {
} sl_se_sha256_streaming_context_t;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
/// SHA-384 streaming context
/// SHA-384 streaming context. Safe to use.
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-384 streaming context. Deprecated.
typedef struct {
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_streaming_context_t;
/// SHA-512 streaming context
/// SHA-512 streaming context. Safe to use.
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;
/// SHA-512 streaming context. Deprecated.
typedef struct {
uint32_t total[4]; ///< Number of bytes processed
uint8_t state[64]; ///< Intermediate digest state
@ -452,6 +533,13 @@ typedef struct {
uint8_t Xp[64]; ///< Their point (round 2)
} sl_se_ecjpake_context_t;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
/// 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(SEMAILBOX_PRESENT)

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -44,13 +44,15 @@
* Device initialisation, debug lock, upgrade functionality, user data...
*
* @details
* API for managing the Secure Element or Root code on a device. Upload and
* 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 "em_se.h"
#include "sl_status.h"
@ -181,20 +183,6 @@ sl_status_t sl_se_apply_host_image(sl_se_command_context_t *cmd_ctx,
void *image_addr,
uint32_t size);
/***************************************************************************//**
* @brief
* Clear Host firmware upgrade status.
*
* @param[in] cmd_ctx
* Pointer to an SE command context object.
*
* @return
* @retval SL_STATUS_OK when the Host upgrade status has been cleared,
* otherwise an error code from @ref sl_status.h if no upgrade has been run
* and there is nothing to clear.
******************************************************************************/
sl_status_t sl_se_upgrade_status_clear(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
* @brief
* Get upgrade status of Host firmware image.
@ -488,6 +476,7 @@ sl_status_t sl_se_get_serialnumber(sl_se_command_context_t *cmd_ctx,
sl_status_t sl_se_get_otp_version(sl_se_command_context_t *cmd_ctx,
uint32_t *version);
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1) || defined(DOXYGEN)
/***************************************************************************//**
* @brief
* Read the EMU->RSTCAUSE after a tamper reset. This function should be called
@ -506,6 +495,7 @@ sl_status_t sl_se_get_otp_version(sl_se_command_context_t *cmd_ctx,
******************************************************************************/
sl_status_t sl_se_get_reset_cause(sl_se_command_context_t *cmd_ctx,
uint32_t* reset_cause);
#endif
/***************************************************************************//**
* @brief
@ -580,7 +570,7 @@ sl_status_t sl_se_set_debug_options(sl_se_command_context_t *cmd_ctx,
* @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 element.
* commissioning information in the secure engine.
*
* @return
* One of the following sl_status_t codes:
@ -589,7 +579,7 @@ sl_status_t sl_se_set_debug_options(sl_se_command_context_t *cmd_ctx,
******************************************************************************/
sl_status_t sl_se_erase_device(sl_se_command_context_t *cmd_ctx);
/***************************************************************************//**
/****************************************************************q***********//**
* @brief
* Disabled device erase functionality.
*
@ -709,6 +699,8 @@ sl_status_t sl_se_disable_tamper(sl_se_command_context_t *cmd_ctx,
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.
@ -748,7 +740,6 @@ 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);
#endif // (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#endif // defined(SEMAILBOX_PRESENT)

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager internal API.
* @brief Silicon Labs Secure Engine Manager internal API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -49,7 +49,7 @@ extern "C" {
// -------------------------------
// SE status codes
/// Response status codes for the Secure Element
/// 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
@ -95,8 +95,6 @@ extern "C" {
#define SLI_SE_COMMAND_APPLY_HOST_IMAGE 0x43060001UL
#define SLI_SE_COMMAND_STATUS_HOST_IMAGE 0x43070000UL
#define SLI_SE_COMMAND_UPGRADE_STATUS_CLEAR 0x430B0000UL
#define SLI_SE_COMMAND_READ_OTP 0xFE040000UL
#define SLI_SE_COMMAND_INIT_OTP 0xFF000001UL
@ -127,6 +125,8 @@ extern "C" {
#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
@ -149,11 +149,13 @@ extern "C" {
#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_2_CONFIG_1)
// SLI_SE_COMMAND_STATUS_READ_RSTCAUSE is only available on xG21 devices (series-2-config-1)
#define SLI_SE_COMMAND_STATUS_READ_RSTCAUSE 0x43220000UL
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
#endif
#define SLI_SE_COMMAND_READ_USER_CERT_SIZE 0x43FA0000UL
#define SLI_SE_COMMAND_READ_USER_CERT 0x43FB0000UL
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
#define SLI_SE_COMMAND_ATTEST_PSA_IAT 0x0A030000UL
#define SLI_SE_COMMAND_ATTEST_CONFIG 0x0A040000UL
#endif
@ -173,18 +175,16 @@ extern "C" {
#define SLI_SE_COMMAND_INIT_AES_128_KEY 0xFF0B0001UL
#endif // SEMAILBOX_PRESENT
// Commands limited to SE Vault devices
// Commands limited to SE Vault High devices
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
#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 0x02020002UL
#define SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_HMAC 0x02020002UL
#define SLI_SE_COMMAND_DERIVE_KEY_HKDF 0x02020003UL
#define SLI_SE_COMMAND_EDDSA_SIGN 0x06020000UL
#define SLI_SE_COMMAND_EDDSA_VERIFY 0x06030000UL
#define SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_CMAC 0x02020010UL
#define SLI_SE_COMMAND_CHACHAPOLY_ENCRYPT 0x0C000000UL
#define SLI_SE_COMMAND_CHACHAPOLY_DECRYPT 0x0C010000UL
@ -245,11 +245,9 @@ extern "C" {
/// Magic paramater for deleting user data
#define SLI_SE_COMMAND_OPTION_ERASE_UD 0xDE1E7EADUL
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT) || defined(DOXYGEN)
#define SLI_SE_COMMAND_CERT_BATCH 0x00000100UL
#define SLI_SE_COMMAND_CERT_SE 0x00000200UL
#define SLI_SE_COMMAND_CERT_HOST 0x00000300UL
#endif
#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) || defined(DOXYGEN)
/// Use SHA384 as hash algorithm
@ -275,6 +273,15 @@ extern "C" {
#define SLI_SE_MAX_POINT_MULT_RETRIES 3U
#endif
// EFR32xG23+ doesn't require padding of curve elements or other keys
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG) \
&& (_SILICON_LABS_32B_SERIES_2_CONFIG < 3)
#define SLI_SE_KEY_PADDING_REQUIRED
#define SLI_SE_P521_PADDING_BYTES 2
#else
#define SLI_SE_P521_PADDING_BYTES 0
#endif
// -------------------------------
// Function-like macros

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -32,12 +32,16 @@
#if defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
#include "sl_se_manager.h"
#if !defined(SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT)
#include "sli_se_manager_internal.h"
#include "sli_se_manager_osal.h"
#include "em_se.h"
#include "em_core.h"
#include "em_assert.h"
#include "em_system.h"
#include "sl_assert.h"
#if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
#include "em_bus.h"
#endif
#include <string.h>
/// @addtogroup sl_se_manager
@ -48,21 +52,40 @@
#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 bool se_manager_initialized = false;
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 se_manager_osal_mutex_t se_lock;
#endif
static se_manager_osal_mutex_t se_lock = { 0 };
#define SLI_SE_MANAGER_KERNEL_CRITICAL_SECTION_START \
int32_t kernel_lock_state = 0; \
osKernelState_t kernel_state = se_manager_osal_kernel_get_state(); \
if (kernel_state != osKernelInactive && kernel_state != osKernelReady) { \
kernel_lock_state = se_manager_osal_kernel_lock(); \
if (kernel_lock_state < 0) { \
return SL_STATUS_FAIL; \
} \
}
#define SLI_SE_MANAGER_KERNEL_CRITICAL_SECTION_END \
if (kernel_state != osKernelInactive && kernel_state != osKernelReady) { \
if (se_manager_osal_kernel_restore_lock(kernel_lock_state) < 0) { \
return SL_STATUS_FAIL; \
} \
}
#endif // SL_SE_MANAGER_THREADING
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
// SE command completion.
static se_manager_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 SE_Response_t se_manager_command_response;
static SE_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)
@ -80,9 +103,9 @@ sl_status_t sl_se_init(void)
#if defined (SL_SE_MANAGER_THREADING) \
|| defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
#if defined(SL_SE_MANAGER_THREADING)
SLI_SE_MANAGER_KERNEL_CRITICAL_SECTION_START
#endif
if ( !se_manager_initialized ) {
#if defined(SL_SE_MANAGER_THREADING)
@ -107,7 +130,9 @@ sl_status_t sl_se_init(void)
}
}
CORE_EXIT_CRITICAL();
#if defined(SL_SE_MANAGER_THREADING)
SLI_SE_MANAGER_KERNEL_CRITICAL_SECTION_END
#endif
#endif // #if defined (SL_SE_MANAGER_THREADING)
// || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
@ -125,14 +150,16 @@ sl_status_t sl_se_deinit(void)
#if defined (SL_SE_MANAGER_THREADING) \
|| defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
#if defined(SL_SE_MANAGER_THREADING)
SLI_SE_MANAGER_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.
CORE_EXIT_CRITICAL();
#if defined(SL_SE_MANAGER_THREADING)
SLI_SE_MANAGER_KERNEL_CRITICAL_SECTION_END
#endif
// Acquire the SE lock to make sure no thread is executing SE commands
// when we de-initialize.
@ -158,9 +185,12 @@ sl_status_t sl_se_deinit(void)
// Mark the SE Manager as un-initialized.
se_manager_initialized = false;
} else {
CORE_EXIT_CRITICAL();
}
#if defined(SL_SE_MANAGER_THREADING)
else {
SLI_SE_MANAGER_KERNEL_CRITICAL_SECTION_END
}
#endif
#endif // #if defined (SL_SE_MANAGER_THREADING)
// || defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
@ -196,6 +226,10 @@ sl_status_t sli_se_to_sl_status(SE_Response_t res)
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(CRYPTOACC_PRESENT)
case SLI_SE_RESPONSE_MAILBOX_INVALID:
return SL_STATUS_COMMAND_IS_INVALID;
@ -207,42 +241,41 @@ sl_status_t sli_se_to_sl_status(SE_Response_t res)
}
}
#if defined(SL_SE_MANAGER_THREADING)
/***************************************************************************//**
* Take the SE lock in order to synchronize multiple threads calling into
* the SE Manager API concurrently.
* 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)
{
return se_manager_osal_take_mutex(&se_lock);
#if defined(SL_SE_MANAGER_THREADING)
sl_status_t status = se_manager_osal_take_mutex(&se_lock);
#else
sl_status_t status = SL_STATUS_OK;
#endif
#if defined(_CMU_CLKEN1_SEMAILBOXHOST_MASK)
if (status == SL_STATUS_OK) {
BUS_RegBitWrite(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 1);
}
#endif
return status;
}
/***************************************************************************//**
* Give the SE lock in order to synchronize multiple threads calling into
* the SE Manager API concurrently.
* 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)
BUS_RegBitWrite(&CMU->CLKEN1, _CMU_CLKEN1_SEMAILBOXHOST_SHIFT, 0);
#endif
#if defined(SL_SE_MANAGER_THREADING)
return se_manager_osal_give_mutex(&se_lock);
}
#else // SL_SE_MANAGER_THREADING
// No MT synchronization when the app does not need threading (e.g. bare metal)
sl_status_t sli_se_lock_acquire(void)
{
#else
return SL_STATUS_OK;
#endif
}
sl_status_t sli_se_lock_release(void)
{
return SL_STATUS_OK;
}
#endif // SL_SE_MANAGER_THREADING
#if defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION)
/***************************************************************************//**
@ -266,6 +299,29 @@ void SEMBRX_IRQHandler(void)
#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.
@ -310,6 +366,8 @@ sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx)
// 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 = SE_readCommandResponse();
@ -334,7 +392,7 @@ sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx)
}
}
#elif defined(CRYPTOACC_PRESENT)
#elif defined(CRYPTOACC_PRESENT) // SEMAILBOX_PRESENT
sl_status_t sli_se_execute_and_wait(sl_se_command_context_t *cmd_ctx)
{
@ -421,7 +479,9 @@ sl_status_t sl_se_ack_command(sl_se_command_context_t *cmd_ctx)
}
}
#endif
#endif // CRYPTOACC_PRESENT
#endif // !SL_CATALOG_TZ_SECURE_KEY_LIBRARY_NS_PRESENT
/***************************************************************************//**
* Initialize an SE command context object
@ -450,29 +510,6 @@ sl_status_t sl_se_deinit_command_context(sl_se_command_context_t *cmd_ctx)
return sl_se_init_command_context(cmd_ctx);
}
/***************************************************************************//**
* 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
}
/** @} (end addtogroup sl_se) */
#endif // defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -94,6 +94,60 @@ static sl_status_t validate_and_update_command_word(uint32_t *command_word,
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
SE_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);
SE_DataTransfer_t noncedata =
SE_DATATRANSFER_DEFAULT(dummy_nonce, challenge_size);
SE_addDataInput(se_cmd, &noncedata);
SE_DataTransfer_t sizedata =
SE_DATATRANSFER_DEFAULT(token_size, sizeof(*token_size));
SE_addDataOutput(se_cmd, &sizedata);
return sli_se_execute_and_wait(cmd_ctx);
}
/***************************************************************************//**
* @brief
* Get an attestation token from the SE
@ -145,6 +199,18 @@ static sl_status_t get_attestation_token(sl_se_command_context_t *cmd_ctx,
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
SE_Command_t *se_cmd = &cmd_ctx->command;
sli_se_command_init(cmd_ctx, command_word);
@ -155,66 +221,12 @@ static sl_status_t get_attestation_token(sl_se_command_context_t *cmd_ctx,
SE_DATATRANSFER_DEFAULT(token_size, sizeof(*token_size));
SE_addDataOutput(se_cmd, &sizedata);
SE_DataTransfer_t tokendata =
SE_DATATRANSFER_DEFAULT(token_buf, ((token_buf_size + 0x3) & ~0x3));
SE_DATATRANSFER_DEFAULT(token_buf, ((*token_size + 0x3) & ~0x3));
SE_addDataOutput(se_cmd, &tokendata);
return sli_se_execute_and_wait(cmd_ctx);
}
/***************************************************************************//**
* @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
SE_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);
SE_DataTransfer_t noncedata =
SE_DATATRANSFER_DEFAULT(dummy_nonce, challenge_size);
SE_addDataInput(se_cmd, &noncedata);
SE_DataTransfer_t sizedata =
SE_DATATRANSFER_DEFAULT(token_size, sizeof(*token_size));
SE_addDataOutput(se_cmd, &sizedata);
return sli_se_execute_and_wait(cmd_ctx);
}
// -----------------------------------------------------------------------------
// Global Functions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -34,8 +34,6 @@
#include "sl_se_manager.h"
#include "sli_se_manager_internal.h"
#include "em_se.h"
#include "em_core.h"
#include "em_assert.h"
#include "em_system.h"
#include <string.h>

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -34,13 +34,11 @@
#include "sl_se_manager.h"
#include "sli_se_manager_internal.h"
#include "em_se.h"
#include "em_core.h"
#include "em_assert.h"
#include "em_system.h"
#include "sl_assert.h"
#include <string.h>
/***************************************************************************//**
* \addtogroup sl_se Secure Element Manager API
* \addtogroup sl_se Secure Engine Manager API
* @{
******************************************************************************/
@ -50,9 +48,8 @@
/***************************************************************************//**
* Start a SHA1 stream operation.
******************************************************************************/
sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha1_streaming_context_t *sha1_ctx)
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,
@ -65,7 +62,7 @@ sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
0x00, 0x00, 0x00, 0x00
};
if (cmd_ctx == NULL || hash_ctx == NULL || sha1_ctx == NULL) {
if (cmd_ctx == NULL || sha1_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
@ -73,10 +70,35 @@ sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
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 SHA1 stream operation. Deprecated.
******************************************************************************/
sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha1_streaming_context_t *sha1_ctx)
{
if (hash_ctx == NULL || cmd_ctx == NULL || sha1_ctx == NULL ) {
return SL_STATUS_INVALID_PARAMETER;
}
hash_ctx->cmd_ctx = cmd_ctx;
sl_se_sha1_multipart_context_t sha1_ctx_multi;
sl_status_t status = sl_se_hash_sha1_multipart_starts(&sha1_ctx_multi, hash_ctx->cmd_ctx);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(sha1_ctx->total, sha1_ctx_multi.total, sizeof(sha1_ctx->total));
memcpy(sha1_ctx->state, sha1_ctx_multi.state, sizeof(sha1_ctx->state));
hash_ctx->hash_type_ctx = sha1_ctx;
hash_ctx->hash_type = SL_SE_HASH_SHA1;
hash_ctx->size = 20;
return SL_STATUS_OK;
}
@ -85,9 +107,8 @@ sl_status_t sl_se_hash_sha1_starts(sl_se_hash_streaming_context_t *hash_ctx,
* Start a SHA224 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha224_streaming_context_t *sha224_ctx)
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,
@ -100,7 +121,7 @@ sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
0xBE, 0xFA, 0x4F, 0xA4
};
if (cmd_ctx == NULL || hash_ctx == NULL || sha224_ctx == NULL) {
if (cmd_ctx == NULL || sha224_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
@ -108,10 +129,37 @@ sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
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 SHA224 stream operation. Deprecated.
******************************************************************************/
sl_status_t
sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha224_streaming_context_t *sha224_ctx)
{
if (hash_ctx == NULL || cmd_ctx == NULL || sha224_ctx == NULL ) {
return SL_STATUS_INVALID_PARAMETER;
}
hash_ctx->cmd_ctx = cmd_ctx;
sl_se_sha224_multipart_context_t sha224_ctx_multi;
sl_status_t status = sl_se_hash_sha224_multipart_starts(&sha224_ctx_multi, hash_ctx->cmd_ctx);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(sha224_ctx->total, sha224_ctx_multi.total, sizeof(sha224_ctx->total));
memcpy(sha224_ctx->state, sha224_ctx_multi.state, sizeof(sha224_ctx->state));
hash_ctx->hash_type_ctx = sha224_ctx;
hash_ctx->hash_type = SL_SE_HASH_SHA224;
hash_ctx->size = 28;
return SL_STATUS_OK;
}
@ -120,9 +168,8 @@ sl_se_hash_sha224_starts(sl_se_hash_streaming_context_t *hash_ctx,
* Start a SHA256 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha256_streaming_context_t *sha256_ctx)
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,
@ -135,7 +182,7 @@ sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
0x5B, 0xE0, 0xCD, 0x19
};
if (cmd_ctx == NULL || hash_ctx == NULL || sha256_ctx == NULL) {
if (cmd_ctx == NULL || sha256_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
@ -143,10 +190,37 @@ sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
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;
}
/***************************************************************************//**
* Start a SHA256 stream operation. Deprecated.
******************************************************************************/
sl_status_t
sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha256_streaming_context_t *sha256_ctx)
{
if (hash_ctx == NULL || cmd_ctx == NULL || sha256_ctx == NULL ) {
return SL_STATUS_INVALID_PARAMETER;
}
hash_ctx->cmd_ctx = cmd_ctx;
hash_ctx->hash_type_ctx = sha256_ctx;
sl_se_sha256_multipart_context_t sha256_ctx_multi;
sl_status_t status = sl_se_hash_sha256_multipart_starts(&sha256_ctx_multi, hash_ctx->cmd_ctx);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(sha256_ctx->total, sha256_ctx_multi.total, sizeof(sha256_ctx->total));
memcpy(sha256_ctx->state, sha256_ctx_multi.state, sizeof(sha256_ctx->state));
hash_ctx->hash_type = SL_SE_HASH_SHA256;
hash_ctx->size = 32;
hash_ctx->hash_type_ctx = sha256_ctx;
return SL_STATUS_OK;
}
@ -156,9 +230,8 @@ sl_se_hash_sha256_starts(sl_se_hash_streaming_context_t *hash_ctx,
* Start a SHA384 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha384_streaming_context_t *sha384_ctx)
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,
@ -171,7 +244,7 @@ sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
0x47, 0xB5, 0x48, 0x1D, 0xBE, 0xFA, 0x4F, 0xA4
};
if (cmd_ctx == NULL || hash_ctx == NULL || sha384_ctx == NULL) {
if (cmd_ctx == NULL || sha384_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
@ -181,10 +254,36 @@ sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
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 SHA384 stream operation. Deprecated.
******************************************************************************/
sl_status_t
sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha384_streaming_context_t *sha384_ctx)
{
if (hash_ctx == NULL || cmd_ctx == NULL || sha384_ctx == NULL ) {
return SL_STATUS_INVALID_PARAMETER;
}
hash_ctx->cmd_ctx = cmd_ctx;
hash_ctx->hash_type_ctx = sha384_ctx;
sl_se_sha384_multipart_context_t sha384_ctx_multi;
sl_status_t status = sl_se_hash_sha384_multipart_starts(&sha384_ctx_multi, hash_ctx->cmd_ctx);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(sha384_ctx->total, sha384_ctx_multi.total, sizeof(sha384_ctx->total));
memcpy(sha384_ctx->state, sha384_ctx_multi.state, sizeof(sha384_ctx->state));
hash_ctx->hash_type = SL_SE_HASH_SHA384;
hash_ctx->size = 48;
hash_ctx->hash_type_ctx = sha384_ctx;
return SL_STATUS_OK;
}
@ -193,9 +292,7 @@ sl_se_hash_sha384_starts(sl_se_hash_streaming_context_t *hash_ctx,
* Start a SHA512 stream operation.
******************************************************************************/
sl_status_t
sl_se_hash_sha512_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha512_streaming_context_t *sha512_ctx)
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,
@ -208,7 +305,7 @@ sl_se_hash_sha512_starts(sl_se_hash_streaming_context_t *hash_ctx,
0x5B, 0xE0, 0xCD, 0x19, 0x13, 0x7E, 0x21, 0x79
};
if (cmd_ctx == NULL || hash_ctx == NULL || sha512_ctx == NULL) {
if (cmd_ctx == NULL || sha512_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
@ -218,24 +315,91 @@ sl_se_hash_sha512_starts(sl_se_hash_streaming_context_t *hash_ctx,
sha512_ctx->total[3] = 0;
memcpy(sha512_ctx->state, init_state_sha512, sizeof(sha512_ctx->state));
hash_ctx->cmd_ctx = cmd_ctx;
hash_ctx->hash_type_ctx = sha512_ctx;
hash_ctx->hash_type = SL_SE_HASH_SHA512;
hash_ctx->size = 64;
sha512_ctx->hash_type = SL_SE_HASH_SHA512;
return SL_STATUS_OK;
}
/***************************************************************************//**
* Start a SHA512 stream operation. Deprecated.
******************************************************************************/
sl_status_t
sl_se_hash_sha512_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_sha512_streaming_context_t *sha512_ctx)
{
if (hash_ctx == NULL || cmd_ctx == NULL || sha512_ctx == NULL ) {
return SL_STATUS_INVALID_PARAMETER;
}
hash_ctx->cmd_ctx = cmd_ctx;
sl_se_sha512_multipart_context_t sha512_ctx_multi;
sl_status_t status = sl_se_hash_sha512_multipart_starts(&sha512_ctx_multi, hash_ctx->cmd_ctx);
if (status != SL_STATUS_OK) {
return SL_STATUS_INVALID_PARAMETER;
}
memcpy(sha512_ctx->total, sha512_ctx_multi.total, sizeof(sha512_ctx->total));
memcpy(sha512_ctx->state, sha512_ctx_multi.state, sizeof(sha512_ctx->state));
hash_ctx->hash_type = SL_SE_HASH_SHA512;
hash_ctx->hash_type_ctx = sha512_ctx;
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;
}
}
/***************************************************************************//**
* Start a hash stream operation. Deprecated.
******************************************************************************/
sl_status_t sl_se_hash_starts(sl_se_hash_streaming_context_t *hash_ctx,
sl_se_command_context_t *cmd_ctx,
sl_se_hash_type_t hash_type,
void *hash_type_ctx)
{
if (cmd_ctx == NULL || hash_ctx == NULL || hash_type_ctx == NULL) {
if (hash_ctx == NULL || cmd_ctx == NULL || hash_type_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
@ -257,7 +421,6 @@ sl_status_t sl_se_hash_starts(sl_se_hash_streaming_context_t *hash_ctx,
cmd_ctx,
(sl_se_sha256_streaming_context_t*)
hash_type_ctx);
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
return sl_se_hash_sha384_starts(hash_ctx,
@ -280,24 +443,24 @@ sl_status_t sl_se_hash_starts(sl_se_hash_streaming_context_t *hash_ctx,
/***************************************************************************//**
* Feeds an input block into an ongoing hash computation.
******************************************************************************/
static sl_status_t se_cmd_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
const uint8_t *input,
uint32_t num_blocks)
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)
{
sl_se_command_context_t *cmd_ctx = hash_ctx->cmd_ctx;
SE_Command_t *se_cmd = &cmd_ctx->command;
uint32_t command_word;
unsigned int ilen, state_len;
uint8_t *state;
switch (hash_ctx->hash_type) {
switch (((sl_se_sha1_multipart_context_t*)hash_type_ctx)->hash_type) {
case SL_SE_HASH_SHA1:
command_word = SE_COMMAND_HASHUPDATE | SE_COMMAND_OPTION_HASH_SHA1;
// SHA1 block size is 64 bytes
ilen = 64 * num_blocks;
// SHA1 state size is 20 bytes
state_len = 20;
state = ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
state = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->state;
break;
case SL_SE_HASH_SHA224:
@ -306,7 +469,7 @@ static sl_status_t se_cmd_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
ilen = 64 * num_blocks;
// SHA224 state size is 32 bytes
state_len = 32;
state = ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
state = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->state;
break;
case SL_SE_HASH_SHA256:
@ -315,7 +478,7 @@ static sl_status_t se_cmd_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
ilen = 64 * num_blocks;
// SHA256 state size is 32 bytes
state_len = 32;
state = ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
state = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->state;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
@ -325,7 +488,7 @@ static sl_status_t se_cmd_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
ilen = 128 * num_blocks;
// SHA384 state size is 64 bytes
state_len = 64;
state = ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
state = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->state;
break;
case SL_SE_HASH_SHA512:
@ -334,7 +497,7 @@ static sl_status_t se_cmd_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
ilen = 128 * num_blocks;
// SHA512 state size is 64 bytes
state_len = 64;
state = ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
state = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->state;
break;
#endif
@ -346,7 +509,7 @@ static sl_status_t se_cmd_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
SE_addParameter(se_cmd, ilen);
SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT((void *)input, ilen);
SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT(input, ilen);
SE_DataTransfer_t iv_in = SE_DATATRANSFER_DEFAULT(state, state_len);
SE_DataTransfer_t iv_out = SE_DATATRANSFER_DEFAULT(state, state_len);
@ -361,9 +524,10 @@ static sl_status_t se_cmd_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
/***************************************************************************//**
* Feeds an input buffer into an ongoing hash computation.
******************************************************************************/
sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
const uint8_t *input,
size_t input_len)
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 blocksize, countersize, blocks, fill, left;
uint32_t *counter;
@ -374,45 +538,45 @@ sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
return SL_STATUS_OK;
}
if (hash_ctx == NULL || input == NULL) {
if (hash_type_ctx == NULL || cmd_ctx == NULL || input == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
switch (hash_ctx->hash_type) {
switch (((sl_se_sha1_multipart_context_t*)hash_type_ctx)->hash_type) {
case SL_SE_HASH_SHA1:
blocksize = 64;
countersize = 64 / 32;
counter = ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
buffer = ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer;
counter = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->buffer;
break;
case SL_SE_HASH_SHA224:
blocksize = 64;
countersize = 64 / 32;
counter = ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
buffer = ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer;
counter = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->buffer;
break;
case SL_SE_HASH_SHA256:
blocksize = 64;
countersize = 64 / 32;
counter = ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
buffer = ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer;
counter = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->buffer;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
blocksize = 128;
countersize = 128 / 32;
counter = ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
buffer = ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer;
counter = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->buffer;
break;
case SL_SE_HASH_SHA512:
blocksize = 128;
countersize = 128 / 32;
counter = ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
buffer = ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer;
counter = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->total;
buffer = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->buffer;
break;
#endif
@ -428,16 +592,20 @@ sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
// 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
}
if ( (left > 0) && (input_len >= fill) ) {
memcpy( (void *) (buffer + left), input, fill);
status = se_cmd_hash_update(hash_ctx, buffer, 1);
status = se_cmd_hash_multipart_update(hash_type_ctx, cmd_ctx, buffer, 1);
if (status != SL_STATUS_OK) {
return status;
}
@ -448,7 +616,7 @@ sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
if ( input_len >= blocksize ) {
blocks = input_len / blocksize;
status = se_cmd_hash_update(hash_ctx, input, blocks);
status = se_cmd_hash_multipart_update(hash_type_ctx, cmd_ctx, input, blocks);
if (status != SL_STATUS_OK) {
return status;
}
@ -462,13 +630,121 @@ sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
return SL_STATUS_OK;
}
/***************************************************************************//**
* Feeds an input buffer into an ongoing hash computation. Deprecated.
******************************************************************************/
sl_status_t sl_se_hash_update(sl_se_hash_streaming_context_t *hash_ctx,
const uint8_t *input,
size_t input_len)
{
if (hash_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
switch (hash_ctx->hash_type) {
case SL_SE_HASH_SHA1:
{
sl_se_sha1_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = SL_SE_HASH_SHA1;
sl_status_t status = sl_se_hash_multipart_update((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, input, input_len);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->total, hash_type_ctx_multi.total, sizeof(hash_type_ctx_multi.total));
memcpy(((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, hash_type_ctx_multi.buffer, sizeof(hash_type_ctx_multi.buffer));
memcpy(((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->state, hash_type_ctx_multi.state, sizeof(hash_type_ctx_multi.state));
break;
}
case SL_SE_HASH_SHA224:
{
sl_se_sha224_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = SL_SE_HASH_SHA224;
sl_status_t status = sl_se_hash_multipart_update((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, input, input_len);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->total, hash_type_ctx_multi.total, sizeof(hash_type_ctx_multi.total));
memcpy(((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, hash_type_ctx_multi.buffer, sizeof(hash_type_ctx_multi.buffer));
memcpy(((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->state, hash_type_ctx_multi.state, sizeof(hash_type_ctx_multi.state));
break;
}
case SL_SE_HASH_SHA256:
{
sl_se_sha256_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = SL_SE_HASH_SHA256;
sl_status_t status = sl_se_hash_multipart_update((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, input, input_len);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->total, hash_type_ctx_multi.total, sizeof(hash_type_ctx_multi.total));
memcpy(((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, hash_type_ctx_multi.buffer, sizeof(hash_type_ctx_multi.buffer));
memcpy(((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->state, hash_type_ctx_multi.state, sizeof(hash_type_ctx_multi.state));
break;
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
{
sl_se_sha384_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = SL_SE_HASH_SHA384;
sl_status_t status = sl_se_hash_multipart_update((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, input, input_len);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->total, hash_type_ctx_multi.total, sizeof(hash_type_ctx_multi.total));
memcpy(((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, hash_type_ctx_multi.buffer, sizeof(hash_type_ctx_multi.buffer));
memcpy(((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->state, hash_type_ctx_multi.state, sizeof(hash_type_ctx_multi.state));
break;
}
case SL_SE_HASH_SHA512:
{
sl_se_sha512_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = SL_SE_HASH_SHA512;
sl_status_t status = sl_se_hash_multipart_update((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, input, input_len);
if (status != SL_STATUS_OK) {
return status;
}
memcpy(((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->total, hash_type_ctx_multi.total, sizeof(hash_type_ctx_multi.total));
memcpy(((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, hash_type_ctx_multi.buffer, sizeof(hash_type_ctx_multi.buffer));
memcpy(((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->state, hash_type_ctx_multi.state, sizeof(hash_type_ctx_multi.state));
break;
}
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
return SL_STATUS_OK;
}
/***************************************************************************//**
* Finish an ongoing hash streaming computation.
******************************************************************************/
sl_status_t sl_se_hash_finish(sl_se_hash_streaming_context_t *hash_ctx,
uint8_t *digest_out,
size_t digest_len)
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)
{
size_t last_data_byte, num_pad_bytes, blocksize, countersize, outputsize;
uint8_t msglen[16];
@ -495,33 +771,33 @@ sl_status_t sl_se_hash_finish(sl_se_hash_streaming_context_t *hash_ctx,
};
#endif
if (hash_ctx == NULL || digest_out == NULL) {
if (hash_type_ctx == NULL || cmd_ctx == NULL || digest_out == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
switch (hash_ctx->hash_type) {
switch (((sl_se_sha1_multipart_context_t*)hash_type_ctx)->hash_type) {
case SL_SE_HASH_SHA1:
blocksize = 64;
outputsize = 20;
countersize = 64 / 32;
counter = ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
state = ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
counter = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->total;
state = ((sl_se_sha1_multipart_context_t*)hash_type_ctx)->state;
break;
case SL_SE_HASH_SHA224:
blocksize = 64;
outputsize = 28;
countersize = 64 / 32;
counter = ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
state = ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
counter = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->total;
state = ((sl_se_sha224_multipart_context_t*)hash_type_ctx)->state;
break;
case SL_SE_HASH_SHA256:
blocksize = 64;
outputsize = 32;
countersize = 64 / 32;
counter = ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
state = ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
counter = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->total;
state = ((sl_se_sha256_multipart_context_t*)hash_type_ctx)->state;
break;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
@ -529,16 +805,16 @@ sl_status_t sl_se_hash_finish(sl_se_hash_streaming_context_t *hash_ctx,
blocksize = 128;
outputsize = 48;
countersize = 128 / 32;
counter = ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
state = ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
counter = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->total;
state = ((sl_se_sha384_multipart_context_t*)hash_type_ctx)->state;
break;
case SL_SE_HASH_SHA512:
blocksize = 128;
outputsize = 64;
countersize = 128 / 32;
counter = ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->total;
state = ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->state;
counter = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->total;
state = ((sl_se_sha512_multipart_context_t*)hash_type_ctx)->state;
break;
#endif
@ -568,12 +844,94 @@ sl_status_t sl_se_hash_finish(sl_se_hash_streaming_context_t *hash_ctx,
? ( (blocksize - (countersize * 4)) - last_data_byte)
: ( ((2 * blocksize) - (countersize * 4)) - last_data_byte);
sl_se_hash_update(hash_ctx, sha_padding, num_pad_bytes);
sl_se_hash_update(hash_ctx, msglen, countersize * 4);
sl_status_t status = sl_se_hash_multipart_update(hash_type_ctx, cmd_ctx, sha_padding, num_pad_bytes);
memcpy(digest_out, state, outputsize);
if (status == SL_STATUS_OK) {
status = sl_se_hash_multipart_update(hash_type_ctx, cmd_ctx, msglen, countersize * 4);
}
return SL_STATUS_OK;
if (status == SL_STATUS_OK) {
memcpy(digest_out, state, outputsize);
}
return status;
}
/***************************************************************************//**
* Finish an ongoing hash streaming computation. Deprecated.
******************************************************************************/
sl_status_t sl_se_hash_finish(sl_se_hash_streaming_context_t *hash_ctx,
uint8_t *digest_out,
size_t digest_len)
{
if (hash_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
switch (hash_ctx->hash_type) {
case SL_SE_HASH_SHA1:
{
sl_se_sha1_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha1_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = SL_SE_HASH_SHA1;
return sl_se_hash_multipart_finish((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, digest_out, digest_len);
break;
}
case SL_SE_HASH_SHA224:
{
sl_se_sha224_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha224_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = hash_ctx->hash_type;
return sl_se_hash_multipart_finish((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, digest_out, digest_len);
break;
}
case SL_SE_HASH_SHA256:
{
sl_se_sha256_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha256_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = hash_ctx->hash_type;
return sl_se_hash_multipart_finish((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, digest_out, digest_len);
break;
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
case SL_SE_HASH_SHA384:
{
sl_se_sha384_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha384_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = hash_ctx->hash_type;
return sl_se_hash_multipart_finish((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, digest_out, digest_len);
break;
}
case SL_SE_HASH_SHA512:
{
sl_se_sha512_multipart_context_t hash_type_ctx_multi;
memcpy(hash_type_ctx_multi.total, ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->total, sizeof(hash_type_ctx_multi.total));
memcpy(hash_type_ctx_multi.state, ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->state, sizeof(hash_type_ctx_multi.state));
memcpy(hash_type_ctx_multi.buffer, ((sl_se_sha512_streaming_context_t*)hash_ctx->hash_type_ctx)->buffer, sizeof(hash_type_ctx_multi.buffer));
hash_type_ctx_multi.hash_type = hash_ctx->hash_type;
return sl_se_hash_multipart_finish((void*)&hash_type_ctx_multi, hash_ctx->cmd_ctx, digest_out, digest_len);
break;
}
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
}
}
/***************************************************************************//**
@ -586,26 +944,60 @@ sl_status_t sl_se_hash(sl_se_command_context_t *cmd_ctx,
uint8_t* digest,
size_t digest_len)
{
sl_status_t status;
sl_se_hash_streaming_context_t hash_ctx;
union hash_type_ctx_u {
sl_se_sha1_streaming_context_t sha1_ctx;
sl_se_sha224_streaming_context_t sha224_ctx;
sl_se_sha256_streaming_context_t sha256_ctx;
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
sl_se_sha384_streaming_context_t sha384_ctx;
sl_se_sha512_streaming_context_t sha512_ctx;
#endif
} hash_type_ctx;
status = sl_se_hash_starts(&hash_ctx, cmd_ctx, hash_type, &hash_type_ctx);
if (status == SL_STATUS_OK) {
status = sl_se_hash_update(&hash_ctx, message, message_size);
if (status == SL_STATUS_OK) {
status = sl_se_hash_finish(&hash_ctx, digest, digest_len);
}
if (cmd_ctx == NULL
|| digest == NULL
|| (message == NULL
&& message_size != 0)) {
return SL_STATUS_INVALID_PARAMETER;
}
return status;
SE_Command_t *se_cmd = &cmd_ctx->command;
uint32_t command_word = SE_COMMAND_HASH;
uint32_t digest_size = 0;
switch (hash_type) {
case SL_SE_HASH_SHA1:
command_word |= SE_COMMAND_OPTION_HASH_SHA1;
digest_size = 20;
break;
case SL_SE_HASH_SHA224:
command_word |= SE_COMMAND_OPTION_HASH_SHA224;
digest_size = 28;
break;
case SL_SE_HASH_SHA256:
command_word |= 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 |= SE_COMMAND_OPTION_HASH_SHA384;
digest_size = 48;
break;
case SL_SE_HASH_SHA512:
digest_size = 64;
command_word |= 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);
SE_addParameter(se_cmd, message_size);
SE_DataTransfer_t data_in = SE_DATATRANSFER_DEFAULT(message, message_size);
SE_DataTransfer_t data_out = SE_DATATRANSFER_DEFAULT(digest, digest_size);
SE_addDataInput(se_cmd, &data_in);
SE_addDataOutput(se_cmd, &data_out);
// Execute and wait
return sli_se_execute_and_wait(cmd_ctx);
}
/** @} (end addtogroup sl_se) */

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -34,13 +34,11 @@
#include "sl_se_manager.h"
#include "sli_se_manager_internal.h"
#include "em_se.h"
#include "em_core.h"
#include "em_assert.h"
#include "em_system.h"
#include <string.h>
/***************************************************************************//**
* \addtogroup sl_se Secure Element Manager API
* \addtogroup sl_se Secure Engine Manager API
* @{
******************************************************************************/
@ -120,8 +118,14 @@ sl_status_t sl_se_ecdh_compute_shared_secret(sl_se_command_context_t *cmd_ctx,
}
}
#else
if ((key_pubkey_size * 2) > key_out->storage.location.buffer.size) {
return SL_STATUS_INVALID_PARAMETER;
if (key_in_priv->type == SL_SE_KEY_TYPE_ECC_X25519) {
if (key_pubkey_size > key_out->storage.location.buffer.size) {
return SL_STATUS_INVALID_PARAMETER;
}
} else {
if ((key_pubkey_size * 2) > key_out->storage.location.buffer.size) {
return SL_STATUS_INVALID_PARAMETER;
}
}
#endif
@ -437,7 +441,7 @@ sl_status_t sl_se_ecjpake_check(const sl_se_ecjpake_context_t *ctx)
return SL_STATUS_INVALID_PARAMETER;
}
if (ctx->curve_flags == 0 || (ctx->pwd_len > 0 && ctx->pwd == NULL)) {
if (ctx->curve_flags == 0) {
return SL_STATUS_INVALID_PARAMETER;
}
@ -1002,14 +1006,14 @@ sl_status_t sl_se_derive_key_hkdf(sl_se_command_context_t *cmd_ctx,
******************************************************************************/
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_hash_type_t hash,
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)
{
uint32_t hash_mask;
sl_status_t status = SL_STATUS_OK;
uint32_t command_word = 0U;
if ((cmd_ctx == NULL) || (in_key == NULL) || (out_key == NULL)) {
return SL_STATUS_INVALID_PARAMETER;
@ -1022,27 +1026,40 @@ sl_status_t sl_se_derive_key_pbkdf2(sl_se_command_context_t *cmd_ctx,
return SL_STATUS_INVALID_PARAMETER;
}
switch (hash) {
case SL_SE_HASH_SHA1:
hash_mask = SLI_SE_COMMAND_OPTION_HASH_SHA1;
switch (prf) {
case SL_SE_PRF_HMAC_SHA1:
command_word = SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_HMAC
| SLI_SE_COMMAND_OPTION_HASH_SHA1;
break;
case SL_SE_HASH_SHA224:
hash_mask = SLI_SE_COMMAND_OPTION_HASH_SHA224;
case SL_SE_PRF_HMAC_SHA224:
command_word = SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_HMAC
| SLI_SE_COMMAND_OPTION_HASH_SHA224;
break;
case SL_SE_HASH_SHA256:
hash_mask = SLI_SE_COMMAND_OPTION_HASH_SHA256;
case SL_SE_PRF_HMAC_SHA256:
command_word = SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_HMAC
| SLI_SE_COMMAND_OPTION_HASH_SHA256;
break;
case SL_SE_HASH_SHA384:
hash_mask = SLI_SE_COMMAND_OPTION_HASH_SHA384;
case SL_SE_PRF_HMAC_SHA384:
command_word = SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_HMAC
| SLI_SE_COMMAND_OPTION_HASH_SHA384;
break;
case SL_SE_HASH_SHA512:
hash_mask = SLI_SE_COMMAND_OPTION_HASH_SHA512;
case SL_SE_PRF_HMAC_SHA512:
command_word = SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_HMAC
| SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG) \
&& (_SILICON_LABS_32B_SERIES_2_CONFIG >= 3)
// PBKDF2 with CMAC as the PRF was first supported on EFR32xG23.
case SL_SE_PRF_AES_CMAC_128:
command_word = SLI_SE_COMMAND_DERIVE_KEY_PBKDF2_CMAC;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
break;
@ -1050,7 +1067,7 @@ sl_status_t sl_se_derive_key_pbkdf2(sl_se_command_context_t *cmd_ctx,
// SE command structures.
SE_Command_t *se_cmd = &cmd_ctx->command;
sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_DERIVE_KEY_PBKDF2 | hash_mask);
sli_se_command_init(cmd_ctx, command_word);
sli_add_key_parameters(cmd_ctx, in_key, status);
SE_addParameter(se_cmd, salt_len);

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager key handling.
* @brief Silicon Labs Secure Engine Manager key handling.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -83,29 +83,25 @@
#define KEYSPEC_ATTRIBUTES_ECC_SIGN (1U << 10)
#define KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK 0x0000007fU
#define KEYSPEC_TYPE_ECC_EDWARDS ((uint32_t)(0xaUL << KEYSPEC_TYPE_OFFSET))
#define KEYSPEC_TYPE_ECC_MONTGOMERY ((uint32_t)(0xbUL << KEYSPEC_TYPE_OFFSET))
#define KEYSPEC_TYPE_ECC_EDDSA ((uint32_t)(0xcUL << KEYSPEC_TYPE_OFFSET))
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
#define KEYSPEC_TYPE_ECC_EDWARDS \
(uint32_t)(0xaUL << KEYSPEC_TYPE_OFFSET)
#define KEYSPEC_TYPE_ECC_MONTGOMERY \
(uint32_t)(0xbUL << KEYSPEC_TYPE_OFFSET)
#define KEYSPEC_TYPE_ECC_EDDSA \
(uint32_t)(0xcUL << KEYSPEC_TYPE_OFFSET)
#define KEYSPEC_MODE_WRAPPED \
(2UL << KEYSPEC_MODE_OFFSET)
#define KEYSPEC_RESTRICTION_INTERNAL \
(2UL << KEYSPEC_RESTRICTION_OFFSET)
#define KEYSPEC_RESTRICTION_RESTRICTED \
(3UL << KEYSPEC_RESTRICTION_OFFSET)
#define KEYSPEC_ECC_WEIERSTRASS_PRIME_A_IS_ZERO \
(1U << 9)
#define KEYSPEC_ECC_WEIERSTRASS_PRIME_A_IS_MINUS_THREE \
(1U << 8)
#endif
#define KEYSPEC_RESTRICTION_LOCKED (1UL << KEYSPEC_RESTRICTION_OFFSET)
#define KEYSPEC_RESTRICTION_INTERNAL (2UL << KEYSPEC_RESTRICTION_OFFSET)
#define KEYSPEC_RESTRICTION_RESTRICTED (3UL << KEYSPEC_RESTRICTION_OFFSET)
// -----------------------------------------------------------------------------
// Local Functions
@ -113,22 +109,22 @@
sl_status_t sli_key_get_storage_size(const sl_se_key_descriptor_t* key,
uint32_t *storage_size)
{
sl_status_t status;
uint32_t key_size;
if (key == NULL || storage_size == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
status = sli_key_get_size(key, &key_size);
uint32_t key_size = 0;
sl_status_t status = sli_key_get_size(key, &key_size);
if (status != SL_STATUS_OK) {
return status;
}
uint32_t key_type = (key->type & KEYSPEC_TYPE_MASK);
#if defined(SLI_SE_KEY_PADDING_REQUIRED)
// Round up to word length
key_size = (key_size + 3U) & ~0x03U;
#endif
if (key_type == KEYSPEC_TYPE_RAW) {
*storage_size = key_size;
@ -149,22 +145,19 @@ sl_status_t sli_key_get_storage_size(const sl_se_key_descriptor_t* key,
if ((key_type == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME)) {
*storage_size = key_size * (1 * has_private_key + 2 * has_public_key + 6 * has_custom_curve);
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
else if (key_type == KEYSPEC_TYPE_ECC_EDWARDS) {
} else if (key_type == KEYSPEC_TYPE_ECC_EDWARDS) {
*storage_size = key_size * (has_private_key + has_public_key + 5 * has_custom_curve);
} else if ((key_type == KEYSPEC_TYPE_ECC_MONTGOMERY)
|| (key_type == KEYSPEC_TYPE_ECC_EDDSA)) {
*storage_size = key_size * (has_private_key + has_public_key);
}
#endif
else {
} else {
return SL_STATUS_INVALID_PARAMETER;
}
return SL_STATUS_OK;
}
#if defined(SLI_SE_KEY_PADDING_REQUIRED)
/***************************************************************************//**
* @brief
* Clear the additional bytes of a key that is not word-aligned.
@ -195,6 +188,7 @@ static sl_status_t clear_padding(const sl_se_key_descriptor_t *key)
}
return SL_STATUS_OK;
}
#endif
// -----------------------------------------------------------------------------
// Global Functions
@ -210,11 +204,9 @@ sl_status_t sli_key_get_size(const sl_se_key_descriptor_t *key, uint32_t *size)
if (key_type == KEYSPEC_TYPE_RAW) {
*size = (key->type & KEYSPEC_ATTRIBUTES_MASK);
} else if ((key_type == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME)
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
|| (key_type == KEYSPEC_TYPE_ECC_EDWARDS)
|| (key_type == KEYSPEC_TYPE_ECC_MONTGOMERY)
#endif
) {
|| (key_type == KEYSPEC_TYPE_ECC_EDDSA)) {
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
bool has_custom_curve =
((key->flags & SL_SE_KEY_FLAG_ASYMMETRIC_USES_CUSTOM_DOMAIN) != 0);
@ -236,13 +228,7 @@ sl_status_t sli_key_get_size(const sl_se_key_descriptor_t *key, uint32_t *size)
{
*size = (key->type & KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK);
}
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
else if (key_type == KEYSPEC_TYPE_ECC_EDDSA) {
*size = 32;
}
#endif
else {
} else {
return SL_STATUS_INVALID_PARAMETER;
}
@ -272,8 +258,10 @@ sl_status_t sli_key_check_equivalent(const sl_se_key_descriptor_t *key_1,
if (key_1->type != key_2->type) {
// The type fields are different, but this may be due to one of the keys
// not containing the size in the type, but rather in the size field.
if ((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
== SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM) {
if (((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
== SL_SE_KEY_TYPE_ECC_WEIERSTRASS_PRIME_CUSTOM)
|| ((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
== SL_SE_KEY_TYPE_ECC_EDDSA)) {
if ((key_1->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)
== (key_2->type & SL_SE_KEY_TYPE_ALGORITHM_MASK)) {
// Assume that the sizes are equal for now (this will be checked later)
@ -313,12 +301,12 @@ sl_status_t sli_key_check_equivalent(const sl_se_key_descriptor_t *key_1,
}
// Verify key sizes
uint32_t key_1_size;
uint32_t key_1_size = 0;
status = sli_key_get_size(key_1, &key_1_size);
if (status != SL_STATUS_OK) {
return status;
}
uint32_t key_2_size;
uint32_t key_2_size = 0;
status = sli_key_get_size(key_2, &key_2_size);
if (status != SL_STATUS_OK) {
return status;
@ -387,14 +375,12 @@ sl_status_t sli_se_key_to_keyspec(const sl_se_key_descriptor_t *key,
if (key->flags & SL_SE_KEY_FLAG_NON_EXPORTABLE) {
keyspec_restriction = KEYSPEC_RESTRICTION_LOCKED;
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
if (key->flags & SL_SE_KEY_FLAG_IS_DEVICE_GENERATED) {
keyspec_restriction = KEYSPEC_RESTRICTION_INTERNAL;
}
if ((key->flags & SL_SE_KEY_FLAG_IS_RESTRICTED) == SL_SE_KEY_FLAG_IS_RESTRICTED) {
keyspec_restriction = KEYSPEC_RESTRICTION_RESTRICTED;
}
#endif
// Key restrictions are only applicable to volatile and wrapped keys
if (key->storage.method == SL_SE_KEY_STORAGE_EXTERNAL_PLAINTEXT) {
if (keyspec_restriction != 0) {
@ -421,7 +407,7 @@ sl_status_t sli_se_key_to_keyspec(const sl_se_key_descriptor_t *key,
if (key->storage.method == SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE) {
if (key->storage.location.slot
< SL_SE_KEY_SLOT_APPLICATION_SECURE_DEBUG_KEY) {
< SL_SE_KEY_SLOT_INTERNAL_MIN) {
return SL_STATUS_INVALID_PARAMETER;
}
*keyspec = (*keyspec & ~KEYSPEC_INDEX_MASK)
@ -474,12 +460,8 @@ sl_status_t sli_se_key_to_keyspec(const sl_se_key_descriptor_t *key,
}
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
if ((key->type & KEYSPEC_TYPE_MASK) >= KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME
&& (key->type & KEYSPEC_TYPE_MASK) < KEYSPEC_TYPE_ECC_EDDSA) {
#else
if ((key->type & KEYSPEC_TYPE_MASK) == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME) {
#endif
if (signing_only) {
*keyspec |= KEYSPEC_ATTRIBUTES_ECC_SIGN;
}
@ -506,20 +488,12 @@ sl_status_t sli_se_key_to_keyspec(const sl_se_key_descriptor_t *key,
*keyspec = (*keyspec & ~KEYSPEC_ATTRIBUTES_MASK)
| (size & KEYSPEC_ATTRIBUTES_MASK);
} else if ((key_type == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME)
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
|| (key_type == KEYSPEC_TYPE_ECC_EDWARDS)
|| (key_type == KEYSPEC_TYPE_ECC_MONTGOMERY)
#endif
) {
|| (key_type == KEYSPEC_TYPE_ECC_EDDSA)) {
*keyspec = (*keyspec & ~KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK)
| ((size - 1) & KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK);
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
else if (key_type == KEYSPEC_TYPE_ECC_EDDSA) {
*keyspec = (*keyspec & ~KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK);
}
#endif
else {
} else {
return SL_STATUS_INVALID_PARAMETER;
}
@ -589,7 +563,7 @@ sl_status_t sli_se_keyspec_to_key(const uint32_t keyspec,
} else
#endif
if ((key_index <= SL_SE_KEY_SLOT_APPLICATION_ATTESTATION_KEY)
&& (key_index >= SL_SE_KEY_SLOT_APPLICATION_SECURE_DEBUG_KEY)) {
&& (key_index >= SL_SE_KEY_SLOT_INTERNAL_MIN)) {
key->storage.method = SL_SE_KEY_STORAGE_INTERNAL_IMMUTABLE;
} else {
return SL_STATUS_INVALID_PARAMETER;
@ -663,21 +637,12 @@ sl_status_t sli_se_keyspec_to_key(const uint32_t keyspec,
return SL_STATUS_INVALID_PARAMETER;
}
// For some ECC keys, their length is encoded in the type
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
if ((keyspec & KEYSPEC_TYPE_MASK) != KEYSPEC_TYPE_ECC_EDDSA)
#endif
{
key->type = (key->type & ~SL_SE_KEY_TYPE_ATTRIBUTES_MASK) | ((keyspec & KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK) + 1);
}
// For ECC keys, their length is encoded in the type
key->type = (key->type & ~SL_SE_KEY_TYPE_ATTRIBUTES_MASK) | ((keyspec & KEYSPEC_ATTRIBUTES_ECC_SIZE_MASK) + 1);
}
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
if ((keyspec & KEYSPEC_TYPE_MASK) >= KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME
&& (keyspec & KEYSPEC_TYPE_MASK) < KEYSPEC_TYPE_ECC_EDDSA) {
#else
if ((keyspec & KEYSPEC_TYPE_MASK) == KEYSPEC_TYPE_ECC_WEIERSTRASS_PRIME) {
#endif
if (signing_only) {
key->flags |= SL_SE_KEY_FLAG_ASYMMETRIC_SIGNING_ONLY;
}
@ -897,10 +862,13 @@ sl_status_t sl_se_generate_key(sl_se_command_context_t *cmd_ctx,
// Execute command
status = sli_se_execute_and_wait(cmd_ctx);
#if defined(SLI_SE_KEY_PADDING_REQUIRED)
// Clear padding for plaintext keys upon success
if (status == SL_STATUS_OK) {
status = clear_padding(key_out);
}
#endif
return status;
}
@ -1103,11 +1071,14 @@ sl_status_t sl_se_export_key(sl_se_command_context_t *cmd_ctx,
status = sli_se_execute_and_wait(cmd_ctx);
#if defined(SLI_SE_KEY_PADDING_REQUIRED)
// The SE will only output word-aligned data. Clear the extra padding before
// returning
if (status == SL_STATUS_OK) {
status = clear_padding(key_out);
}
#endif
return status;
}
@ -1180,10 +1151,14 @@ sl_status_t sl_se_transfer_key(sl_se_command_context_t *cmd_ctx,
sli_add_key_output(cmd_ctx, key_out, status);
status = sli_se_execute_and_wait(cmd_ctx);
#if defined(SLI_SE_KEY_PADDING_REQUIRED)
// Clear padding bytes for plaintext keys upon success
if (status == SL_STATUS_OK) {
status = clear_padding(key_out);
}
#endif
return status;
}

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -34,9 +34,6 @@
#include "sl_se_manager.h"
#include "sli_se_manager_internal.h"
#include "em_se.h"
#include "em_core.h"
#include "em_assert.h"
#include "em_system.h"
#include <string.h>
/// @addtogroup sl_se_manager
@ -65,31 +62,36 @@ sl_status_t sl_se_ecc_sign(sl_se_command_context_t *cmd_ctx,
sl_status_t status;
uint32_t command_word = SLI_SE_COMMAND_SIGNATURE_SIGN;
if (hashed_message == false) {
switch (hash_alg) {
case SL_SE_HASH_SHA1:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA1;
break;
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_SHA224:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA224;
break;
case SL_SE_HASH_SHA256:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA256;
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_SHA384:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA384;
break;
case SL_SE_HASH_SHA512:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
case SL_SE_HASH_SHA512:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
default:
return SL_STATUS_INVALID_PARAMETER;
}
}
}
@ -107,16 +109,11 @@ sl_status_t sl_se_ecc_sign(sl_se_command_context_t *cmd_ctx,
SE_DataTransfer_t message_buffer = SE_DATATRANSFER_DEFAULT(message, message_len);
SE_addDataInput(se_cmd, &message_buffer);
#if defined(SL_SE_KEY_TYPE_ECC_EDDSA)
// EdDSA requires the message twice
SE_DataTransfer_t repeated_message_buffer;
if (key->type == SL_SE_KEY_TYPE_ECC_EDDSA) {
repeated_message_buffer.next = (void*)SE_DATATRANSFER_STOP;
repeated_message_buffer.data = (void*)message;
repeated_message_buffer.length = message_len;
SE_addDataInput(se_cmd, (SE_DataTransfer_t*)&repeated_message_buffer);
SE_DataTransfer_t repeated_message_buffer = SE_DATATRANSFER_DEFAULT(message, message_len);
if ((key->type & SL_SE_KEY_TYPE_ALGORITHM_MASK) == SL_SE_KEY_TYPE_ECC_EDDSA) {
SE_addDataInput(se_cmd, &repeated_message_buffer);
}
#endif
SE_DataTransfer_t signature_buffer = SE_DATATRANSFER_DEFAULT(signature, signature_len);
SE_addDataOutput(se_cmd, &signature_buffer);
@ -148,32 +145,37 @@ sl_status_t sl_se_ecc_verify(sl_se_command_context_t *cmd_ctx,
sl_status_t status;
uint32_t command_word = SLI_SE_COMMAND_SIGNATURE_VERIFY;
if (hashed_message == false) {
switch (hash_alg) {
case SL_SE_HASH_SHA1:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA1;
break;
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_SHA224:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA224;
break;
case SL_SE_HASH_SHA256:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA256;
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_SHA384:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA384;
break;
case SL_SE_HASH_SHA512:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
case SL_SE_HASH_SHA512:
command_word |= SLI_SE_COMMAND_OPTION_HASH_SHA512;
break;
#endif
default:
return SL_STATUS_INVALID_PARAMETER;
default:
return SL_STATUS_INVALID_PARAMETER;
}
}
}
@ -193,13 +195,10 @@ sl_status_t sl_se_ecc_verify(sl_se_command_context_t *cmd_ctx,
SE_DataTransfer_t signature_buffer = SE_DATATRANSFER_DEFAULT(signature,
signature_len);
#if defined(SL_SE_KEY_TYPE_ECC_EDDSA)
if (key->type == SL_SE_KEY_TYPE_ECC_EDDSA) {
if ((key->type & SL_SE_KEY_TYPE_ALGORITHM_MASK) == SL_SE_KEY_TYPE_ECC_EDDSA) {
SE_addDataInput(se_cmd, &signature_buffer);
SE_addDataInput(se_cmd, &message_buffer);
} else
#endif
{
} else {
SE_addDataInput(se_cmd, &message_buffer);
SE_addDataInput(se_cmd, &signature_buffer);
}

View File

@ -1,6 +1,6 @@
/***************************************************************************//**
* @file
* @brief Silicon Labs Secure Element Manager API.
* @brief Silicon Labs Secure Engine Manager API.
*******************************************************************************
* # License
* <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
@ -34,10 +34,8 @@
#include "sl_se_manager_util.h"
#include "sli_se_manager_internal.h"
#include "em_se.h"
#include "em_core.h"
#include "em_assert.h"
#include "sl_assert.h"
#include "em_system.h"
#include <string.h>
/// @addtogroup sl_se_manager
/// @{
@ -210,21 +208,6 @@ sl_status_t sl_se_apply_host_image(sl_se_command_context_t *cmd_ctx,
return sli_se_execute_and_wait(cmd_ctx);
}
/***************************************************************************//**
* Clear Host firmware upgrade status.
******************************************************************************/
sl_status_t sl_se_upgrade_status_clear(sl_se_command_context_t *cmd_ctx)
{
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// SE command structures
sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_UPGRADE_STATUS_CLEAR);
return sli_se_execute_and_wait(cmd_ctx);
}
/***************************************************************************//**
* Get upgrade status of Host firmware image.
******************************************************************************/
@ -471,17 +454,15 @@ sl_status_t sl_se_get_debug_lock_status(sl_se_command_context_t *cmd_ctx,
#elif defined(CRYPTOACC_PRESENT)
uint32_t vse_version = 0;
uint32_t debug_lock_flags = 0;
SE_Response_t vse_mbx_status = SE_RESPONSE_MAILBOX_INVALID;
sl_status_t status;
// Try to acquire SE lock
status = sli_se_lock_acquire();
sl_status_t status = sli_se_lock_acquire();
if (status != SL_STATUS_OK) {
return status;
}
// Read SE version from VSE mailbox.
vse_mbx_status = SE_getVersion(&vse_version);
SE_Response_t vse_mbx_status = SE_getVersion(&vse_version);
// Reading debug lock status is not supported on VSE with versions <= 1.2.2.
if ((vse_version <= 0x1010202UL) || (vse_mbx_status != SE_RESPONSE_OK)) {
@ -575,15 +556,29 @@ sl_status_t sl_se_init_otp(sl_se_command_context_t *cmd_ctx,
uint8_t reset_threshold;
} otp_tamper_settings;
// Check for reserved sources
if ((otp_init->tamper_levels[SL_SE_TAMPER_SIGNAL_RESERVED_1] != SL_SE_TAMPER_LEVEL_IGNORE)
|| (otp_init->tamper_levels[SL_SE_TAMPER_SIGNAL_RESERVED_2] != SL_SE_TAMPER_LEVEL_IGNORE)
|| (otp_init->tamper_levels[SL_SE_TAMPER_SIGNAL_RESERVED_3] != SL_SE_TAMPER_LEVEL_IGNORE)
|| (otp_init->tamper_levels[SL_SE_TAMPER_SIGNAL_RESERVED_4] != SL_SE_TAMPER_LEVEL_IGNORE)) {
return SL_STATUS_INVALID_PARAMETER;
}
// Combine tamper levels, two per byte
for (size_t i = 0; i < SL_SE_TAMPER_SIGNAL_NUM_SIGNALS; i += 2) {
// Check for reserved levels
EFM_ASSERT((otp_init->tamper_levels[i] != 3)
&& (otp_init->tamper_levels[i] != 5)
&& (otp_init->tamper_levels[i] != 6));
EFM_ASSERT((otp_init->tamper_levels[i + 1] != 3)
&& (otp_init->tamper_levels[i + 1] != 5)
&& (otp_init->tamper_levels[i + 1] != 6));
for (size_t offset = 0; offset < 2; ++offset) {
switch (otp_init->tamper_levels[i + offset]) {
case SL_SE_TAMPER_LEVEL_IGNORE:
case SL_SE_TAMPER_LEVEL_INTERRUPT:
case SL_SE_TAMPER_LEVEL_FILTER:
case SL_SE_TAMPER_LEVEL_RESET:
case SL_SE_TAMPER_LEVEL_PERMANENTLY_ERASE_OTP:
break;
default:
return SL_STATUS_INVALID_PARAMETER;
}
}
otp_tamper_settings.levels[i / 2] = (otp_init->tamper_levels[i] & 0x7)
| ((otp_init->tamper_levels[i + 1] & 0x7) << 4);
@ -601,7 +596,7 @@ sl_status_t sl_se_init_otp(sl_se_command_context_t *cmd_ctx,
uint8_t reserved3[2];
} otp_tamper_settings = {
{ 0x00 },
{ 0xFF },
{ 0xFF, 0xFF },
{ 0x00 }
};
#endif
@ -766,21 +761,18 @@ sl_status_t sl_se_init_otp(sl_se_command_context_t *cmd_ctx,
sl_status_t sl_se_read_otp(sl_se_command_context_t *cmd_ctx,
sl_se_otp_init_t *otp_settings)
{
uint32_t mcu_settings_flags = 0;
SE_Response_t vse_mbx_status = SE_RESPONSE_MAILBOX_INVALID;
sl_status_t status;
if (cmd_ctx == NULL || otp_settings == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
// Try to acquire SE lock
status = sli_se_lock_acquire();
sl_status_t status = sli_se_lock_acquire();
if (status != SL_STATUS_OK) {
return status;
}
vse_mbx_status = SE_getConfigStatusBits(&mcu_settings_flags);
uint32_t mcu_settings_flags = 0;
SE_Response_t vse_mbx_status = SE_getConfigStatusBits(&mcu_settings_flags);
// Release SE lock
status = sli_se_lock_release();
@ -945,6 +937,7 @@ sl_status_t sl_se_get_otp_version(sl_se_command_context_t *cmd_ctx,
return sli_se_execute_and_wait(cmd_ctx);
}
#if defined(_SILICON_LABS_32B_SERIES_2_CONFIG_1)
/***************************************************************************//**
* Read the EMU->RSTCAUSE after a tamper reset. This function should be called
* if EMU->RSTCAUSE has been cleared upon boot.
@ -964,6 +957,7 @@ sl_status_t sl_se_get_reset_cause(sl_se_command_context_t *cmd_ctx,
SE_addDataOutput(se_cmd, &out_data);
return sli_se_execute_and_wait(cmd_ctx);
}
#endif // _SILICON_LABS_32B_SERIES_2_CONFIG_1
/***************************************************************************//**
* Enables the secure debug functionality.
@ -1073,11 +1067,16 @@ sl_status_t sl_se_get_challenge(sl_se_command_context_t *cmd_ctx,
******************************************************************************/
sl_status_t sl_se_roll_challenge(sl_se_command_context_t *cmd_ctx)
{
sl_se_challenge_t new_challenge;
if (cmd_ctx == NULL) {
return SL_STATUS_INVALID_PARAMETER;
}
SE_DataTransfer_t out_data =
SE_DATATRANSFER_DEFAULT(new_challenge, sizeof(sl_se_challenge_t));
sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_ROLL_CHALLENGE);
SE_addDataOutput(&cmd_ctx->command, &out_data);
return sli_se_execute_and_wait(cmd_ctx);
}
@ -1140,6 +1139,8 @@ sl_status_t sl_se_disable_tamper(sl_se_command_context_t *cmd_ctx,
return sli_se_execute_and_wait(cmd_ctx);
}
#endif
/***************************************************************************//**
* Read size of stored certificates in SE.
******************************************************************************/
@ -1158,9 +1159,7 @@ sl_status_t sl_se_read_cert_size(sl_se_command_context_t *cmd_ctx,
return sli_se_execute_and_wait(cmd_ctx);
}
#endif
#if (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
/***************************************************************************//**
* Read stored certificates in SE.
******************************************************************************/
@ -1196,12 +1195,16 @@ sl_status_t sl_se_read_cert(sl_se_command_context_t *cmd_ctx,
// SE command structures
sli_se_command_init(cmd_ctx, SLI_SE_COMMAND_READ_USER_CERT | se_cert_type);
#if _SILICON_LABS_32B_SERIES_2_CONFIG > 2
// One parameter is required, but has no effect
SE_addParameter(se_cmd, 0);
#endif //
SE_DataTransfer_t out_data = SE_DATATRANSFER_DEFAULT(cert, num_bytes);
SE_addDataOutput(se_cmd, &out_data);
return sli_se_execute_and_wait(cmd_ctx);
}
#endif
#endif // defined(SEMAILBOX_PRESENT)

View File

@ -38,20 +38,16 @@
#endif
#if defined (SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#include "sl_component_catalog.h"
#endif
#include "sl_status.h"
#if defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT)
// Include MicriumOS kernel abstraction layer:
#include "sli_se_manager_osal_micriumos.h"
#elif defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
// Include FreeRTOS kernel abstraction layer:
#include "sli_se_manager_osal_freertos.h"
#elif defined(SL_CATALOG_ZEPHYR_KERNEL_PRESENT)
// Include Zephyr OS kernel abstraction layer:
#include "sli_se_manager_osal_zephyr.h"
#if (defined(SL_CATALOG_MICRIUMOS_KERNEL_PRESENT) || defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)) \
&& (defined(SL_SE_MANAGER_THREADING) \
|| defined(SL_SE_MANAGER_YIELD_WHILE_WAITING_FOR_COMMAND_COMPLETION))
// Include CMSIS RTOS2 kernel abstraction layer:
#include "sli_se_manager_osal_cmsis_rtos2.h"
#else
// Include bare metal abstraction layer:
#include "sli_se_manager_osal_baremetal.h"

View File

@ -79,7 +79,7 @@ __STATIC_INLINE
sl_status_t se_manager_osal_init_completion(se_manager_osal_completion_t *p_comp)
{
*p_comp = 0;
return (0);
return SL_STATUS_OK;
}
/// Free a completion object.
@ -87,7 +87,7 @@ __STATIC_INLINE
sl_status_t se_manager_osal_free_completion(se_manager_osal_completion_t *p_comp)
{
*p_comp = 0;
return (0);
return SL_STATUS_OK;
}
/// Wait for completion event.
@ -118,7 +118,7 @@ se_manager_osal_wait_completion(se_manager_osal_completion_t *p_comp, int ticks)
}
}
return(ret);
return ret;
}
/// Signal completion event.
@ -126,7 +126,7 @@ __STATIC_INLINE
sl_status_t se_manager_osal_complete(se_manager_osal_completion_t* p_comp)
{
*p_comp = 1;
return (0);
return SL_STATUS_OK;
}
#ifdef __cplusplus

View File

@ -0,0 +1,282 @@
/**************************************************************************/ /**
* @file
* @brief OS abstraction layer primitives for SE manager on CMSIS RTOS2
*******************************************************************************
* # License
* <b>Copyright 2021 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_OSAL_CMSIS_RTOS_H
#define SE_MANAGER_OSAL_CMSIS_RTOS_H
#include "cmsis_os2.h"
#if defined (SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT)
#include "FreeRTOSConfig.h"
#if (configSUPPORT_STATIC_ALLOCATION == 1)
#include "FreeRTOS.h" // StaticSemaphore_t
#include <string.h>
#endif
#else
#include "em_core.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
// -----------------------------------------------------------------------------
// Defines
/// In order to wait forever in blocking functions the user can pass the
/// following value.
#define SE_MANAGER_OSAL_WAIT_FOREVER (osWaitForever)
/// In order to return immediately in blocking functions the user can pass the
/// following value.
#define SE_MANAGER_OSAL_NON_BLOCKING (0)
/// 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
/// Determine if executing at interrupt level on ARM Cortex-M.
#define RUNNING_AT_INTERRUPT_LEVEL (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)
// -----------------------------------------------------------------------------
// Typedefs
/// Completion object used to wait for and signal end of an operation.
typedef struct se_manager_osal_completion {
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
osSemaphoreAttr_t semaphore_attr;
StaticSemaphore_t static_sem_object;
#endif
osSemaphoreId_t semaphore_ID;
} se_manager_osal_completion_t;
/// SE manager mutex definition for CMSIS RTOS2.
typedef struct se_manager_osal_mutex {
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
osMutexAttr_t mutex_attr;
StaticSemaphore_t static_sem_object;
#endif
osMutexId_t mutex_ID;
} se_manager_osal_mutex_t;
// -----------------------------------------------------------------------------
// Functions
/// Initialize a mutex object.
__STATIC_INLINE
sl_status_t se_manager_osal_init_mutex(se_manager_osal_mutex_t *mutex)
{
if (mutex == NULL) {
return SL_STATUS_FAIL;
}
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
// Zeroize all members of the mutex attributes object and setup the static control block.
memset(&mutex->mutex_attr, 0, sizeof(mutex->mutex_attr));
mutex->mutex_attr.cb_mem = &mutex->static_sem_object;
mutex->mutex_attr.cb_size = sizeof(mutex->static_sem_object);
mutex->mutex_ID = osMutexNew(&mutex->mutex_attr);
#else
mutex->mutex_ID = osMutexNew(NULL);
#endif
return (mutex->mutex_ID == NULL ? SL_STATUS_FAIL : SL_STATUS_OK);
}
/// Free a mutex object.
__STATIC_INLINE
sl_status_t se_manager_osal_free_mutex(se_manager_osal_mutex_t *mutex)
{
if (mutex == NULL) {
return SL_STATUS_FAIL;
}
osStatus_t status = osMutexDelete(mutex->mutex_ID);
return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
}
/// Acquire ownership of a mutex. If busy, wait until available.
__STATIC_INLINE
sl_status_t se_manager_osal_take_mutex(se_manager_osal_mutex_t *mutex)
{
if (mutex == NULL) {
return SL_STATUS_FAIL;
}
osStatus_t status = osOK;
if (osKernelGetState() == osKernelRunning) {
status = osMutexAcquire(mutex->mutex_ID, SE_MANAGER_OSAL_WAIT_FOREVER);
}
return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
}
/// Try to acquire ownership of a mutex without waiting.
__STATIC_INLINE
sl_status_t se_manager_osal_take_mutex_non_blocking(se_manager_osal_mutex_t *mutex)
{
if (mutex == NULL) {
return SL_STATUS_FAIL;
}
osStatus_t status = osOK;
if (osKernelGetState() == osKernelRunning) {
status = osMutexAcquire(mutex->mutex_ID, SE_MANAGER_OSAL_NON_BLOCKING);
}
return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
}
/// Release ownership of a mutex.
__STATIC_INLINE
sl_status_t se_manager_osal_give_mutex(se_manager_osal_mutex_t *mutex)
{
if (mutex == NULL) {
return SL_STATUS_FAIL;
}
osStatus_t status = osOK;
if (osKernelGetState() == osKernelRunning) {
status = osMutexRelease(mutex->mutex_ID);
}
return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
}
/// Initialize a completion object.
__STATIC_INLINE sl_status_t
se_manager_osal_init_completion(se_manager_osal_completion_t *p_comp)
{
if (p_comp == NULL) {
return SL_STATUS_FAIL;
}
#if defined(SL_CATALOG_FREERTOS_KERNEL_PRESENT) && (configSUPPORT_STATIC_ALLOCATION == 1)
// Zeroize all members of the semaphore attributes object and setup the static control block.
memset(&p_comp->semaphore_attr, 0, sizeof(p_comp->semaphore_attr));
p_comp->semaphore_attr.cb_mem = &p_comp->static_sem_object;
p_comp->semaphore_attr.cb_size = sizeof(p_comp->static_sem_object);
p_comp->semaphore_ID = osSemaphoreNew(1u, 0u, &p_comp->semaphore_attr);
#else
p_comp->semaphore_ID = osSemaphoreNew(1u, 0u, NULL);
#endif
return (p_comp->semaphore_ID == NULL ? SL_STATUS_FAIL : SL_STATUS_OK);
}
/// Free a completion object.
__STATIC_INLINE sl_status_t
se_manager_osal_free_completion(se_manager_osal_completion_t *p_comp)
{
if (p_comp == NULL) {
return SL_STATUS_FAIL;
}
osStatus_t status = osSemaphoreDelete(p_comp->semaphore_ID);
return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
}
// Wait for a completion object to be completed.
__STATIC_INLINE sl_status_t
se_manager_osal_wait_completion(se_manager_osal_completion_t *p_comp, int ticks)
{
if (p_comp == NULL) {
return SL_STATUS_FAIL;
}
osStatus_t status = osOK;
if (osKernelGetState() == osKernelRunning) {
status = osSemaphoreAcquire(p_comp->semaphore_ID,
(uint32_t)ticks);
}
return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
}
// Complete a completion object.
__STATIC_INLINE sl_status_t
se_manager_osal_complete(se_manager_osal_completion_t* p_comp)
{
if (p_comp == NULL) {
return SL_STATUS_FAIL;
}
osStatus_t status = osOK;
osKernelState_t state = osKernelGetState();
if ((state == osKernelRunning) || (state == osKernelLocked)) {
status = osSemaphoreRelease(p_comp->semaphore_ID);
}
return (status == osOK ? SL_STATUS_OK : SL_STATUS_FAIL);
}
// Lock the RTOS Kernel scheduler.
__STATIC_INLINE int32_t
se_manager_osal_kernel_lock(void)
{
return osKernelLock();
}
// Restore the RTOS Kernel scheduler lock state.
__STATIC_INLINE int32_t
se_manager_osal_kernel_restore_lock(int32_t lock)
{
return osKernelRestoreLock(lock);
}
// Current RTOS kernel state.
__STATIC_INLINE osKernelState_t
se_manager_osal_kernel_get_state(void)
{
return osKernelGetState();
}
#ifdef __cplusplus
}
#endif
#endif // SE_MANAGER_OSAL_CMSIS_RTOS_H

View File

@ -0,0 +1,205 @@
/***************************************************************************//**
* @file
* @brief Accelerated cryptographic primitives using the CRYPTO and RADIOAES
* peripherals, for series-1 and series-2 respectively.
*******************************************************************************
* # 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 SLI_PROTOCOL_CRYPTO_H
#define SLI_PROTOCOL_CRYPTO_H
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
/***************************************************************************//**
* @addtogroup sli_protocol_crypto
* @brief Accelerated cryptographic primitives using the CRYPTO and RADIOAES
* peripherals, for series-1 and series-2 respectively.
* @{
******************************************************************************/
#include "sl_status.h"
#include "em_device.h"
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************//**
* @brief AES-CTR block encryption/decryption optimized for radio
*
* @param key AES key
* @param keybits must be 128 or 256
* @param input 16-byte input block
* @param iv_in 16-byte counter/IV starting value
* @param iv_out 16-byte counter/IV output after block round
* @param output 16-byte output block
*
* @return SL_STATUS_OK if successful, relevant status code on error
******************************************************************************/
sl_status_t sli_aes_crypt_ctr_radio(const unsigned char *key,
unsigned int keybits,
const unsigned char input[16],
const unsigned char iv_in[16],
volatile unsigned char iv_out[16],
volatile unsigned char output[16]);
/***************************************************************************//**
* @brief AES-ECB block encryption/decryption optimized for radio
*
* @param encrypt true for encryption, false for decryption
* @param key AES key
* @param keybits must be 128 or 256
* @param input 16-byte input block
* @param output 16-byte output block
*
* @return SL_STATUS_OK if successful, relevant status code on error
******************************************************************************/
sl_status_t sli_aes_crypt_ecb_radio(bool encrypt,
const unsigned char *key,
unsigned int keybits,
const unsigned char input[16],
volatile unsigned char output[16]);
#if defined(RADIOAES_PRESENT)
/***************************************************************************//**
* @brief AES-CMAC calculation optimized for radio
*
* @param key AES key
* @param keybits Must be 128 or 256
* @param input Input buffer containing the message to be signed
* @param length Amount of bytes in the input buffer
* @param output 16-byte output block for calculated CMAC
*
* @return SL_STATUS_OK if successful, relevant status code on error
******************************************************************************/
sl_status_t sli_aes_cmac_radio(const unsigned char *key,
unsigned int keybits,
const unsigned char *input,
unsigned int length,
volatile unsigned char output[16]);
/***************************************************************************//**
* @brief Seeds the AES mask. It is recommended to call this function
during initialization in order to avoid taking the potential
hit of requesting RNG output in an IRQ context.
******************************************************************************/
void sli_aes_seed_mask(void);
#endif
/***************************************************************************//**
* @brief CCM buffer authenticated decryption optimized for BLE
*
* @param data Input/output buffer of payload data of BLE packet
* @param length length of input data
* @param iv nonce (initialization vector)
* must be 13 bytes
* @param header header of BLE packet (1 byte)
* @param tag authentication tag of BLE packet (4 bytes)
*
* @return SL_STATUS_OK if successful and authenticated,
* SL_STATUS_INVALID_SIGNATURE if tag does not match payload,
* relevant status code on other error
******************************************************************************/
sl_status_t sli_ccm_auth_decrypt_ble(unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag);
/***************************************************************************//**
* @brief CCM buffer encryption optimized for BLE
*
* @param data Input/output buffer of payload data of BLE packet
* @param length length of input data
* @param iv nonce (initialization vector)
* must be 13 bytes
* @param header header of BLE packet (1 byte)
* @param tag buffer where the BLE packet tag (4 bytes) will be written
*
* @return SL_STATUS_OK if successful, relevant status code on error
******************************************************************************/
sl_status_t sli_ccm_encrypt_and_tag_ble(unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag);
/***************************************************************************//**
* @brief CCM buffer authenticated decryption optimized for Zigbee
*
* @param data Input/output buffer of payload data (decrypt-in-place)
* @param length length of input data
* @param iv nonce (initialization vector)
* must be 13 bytes
* @param aad Input buffer of Additional Authenticated Data
* @param aad_len Length of buffer @p aad
* @param tag authentication tag
* @param tag_len Length of authentication tag
*
* @return SL_STATUS_OK if successful and authenticated,
* SL_STATUS_INVALID_SIGNATURE if tag does not match payload,
* relevant status code on other error
******************************************************************************/
sl_status_t sli_ccm_zigbee(bool encrypt,
const unsigned char *data_in,
unsigned char *data_out,
size_t length,
const unsigned char *key,
const unsigned char *iv,
const unsigned char *aad,
size_t aad_len,
unsigned char *tag,
size_t tag_len);
/***************************************************************************//**
* @brief Process a table of BLE RPA device keys and look for a
* match against the supplied hash
*
* @param keytable Pointer to an array of AES-128 keys, corresponding to the
* per-device key in the BLE RPA process
* @param keymask Bitmask indicating with key indices in keytable are valid
* @param prand 24-bit BLE nonce to encrypt with each key and match against hash
* @param hash BLE RPA hash to match against (last 24 bits of AES result)
*
* @return 0-based index of matching key if a match is found, -1 for no match.
******************************************************************************/
int sli_process_ble_rpa(const unsigned char keytable[],
uint32_t keymask,
uint32_t prand,
uint32_t hash);
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sli_protocol_crypto)
/// @endcond
#endif // SLI_PROTOCOL_CRYPTO_H

View File

@ -0,0 +1,568 @@
/***************************************************************************//**
* @file
* @brief Proprietary crypto primitivies optimized for Silicon Labs devices
* with a CRYPTO peripheral.
*******************************************************************************
* # License
* <b>Copyright 2018 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 "em_device.h"
#if defined(CRYPTO_PRESENT)
#include "sli_protocol_crypto.h"
#include "crypto_management.h"
#include "em_crypto.h"
// CCM (and CCM-star) implementation optimized for radio protocol usecases
static sl_status_t aes_ccm_radio(bool encrypt,
const unsigned char *add_data,
size_t add_length,
const unsigned char *data_in,
unsigned char *data_out,
size_t length,
const unsigned char *key,
uint32_t *header,
size_t header_length_over_16,
unsigned char *tag,
size_t tag_length)
{
// Assumptions:
// * There is always header input, and the header buffer is 32 bytes and word-aligned
// * The actual data content in the header is at least 16 bytes (full block) and
// at maximum 32 bytes (precalculated B0_B1 in BLE). The remainder of the header buffer
// is passed in zero-initialized.
// * Input parameter header_length_over_16 reflects this: it says how much larger than 16 bytes the
// header input buffer is.
// * The header is always word-aligned
// * There may not always be ADD input (e.g. BLE-CCM)
// * There may not always be data input (e.g. CCM in authenticated-only mode)
// * The header input is pre-calculated by the caller of this function
// * Data output may be NULL (in which case it is discarded)
// * Tag length may be 0 (CCM-star), in which case the tag pointer is also allowed to be NULL
size_t L = (((uint8_t*)header)[0] & 0x7) + 1;
// Mangling DDATA1 (KEY), DDATA2 (= DATA0/DATA1), DDATA3 (=DATA2/DATA3),
// DDATA4 (KEYBUF). Max execution sequence length = 20
CRYPTO_TypeDef *device =
crypto_management_acquire_preemption(CRYPTO_MANAGEMENT_SAVE_DDATA1
| CRYPTO_MANAGEMENT_SAVE_DDATA2
| CRYPTO_MANAGEMENT_SAVE_DDATA3
| CRYPTO_MANAGEMENT_SAVE_DDATA4
| CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ4);
// Setup CRYPTO for AES-128 mode (256 not implemented here)
device->CTRL = CRYPTO_CTRL_AES_AES128;
device->WAC = 0UL;
CRYPTO_KeyBufWriteUnaligned(device, key, cryptoKey128Bits);
// Store CBC IV in device->DATA0
CRYPTO_DataWrite(&device->DATA0, header);
// Calculate Counter IV for encryption, which is basically
// the CBC IV with the flags byte masked with 0x7, and zeroing
// out the length field.
((uint8_t*)header)[0] &= 0x07;
for (size_t i = 16 - L; i < 16; i++) {
((uint8_t*)header)[i] = 0;
}
// Store Counter IV in crypto->DATA1
CRYPTO_DataWrite(&device->DATA1, header);
// Start the CBC-MAC by encrypting the IV and storing the result in DATA
device->CMD = CRYPTO_CMD_INSTR_AESENC;
// Update the CBC-MAC with the remainder of the header and
// the full AAD, up until block boundary
if (header_length_over_16 + add_length > 0) {
if (header_length_over_16 < 16) {
// Fill up the remainder taking from the ADD (if any) and into the
// second header block (guaranteed to have a 32-byte writeable buffer)
if (add_length > 0) {
size_t injected_add = add_length > (16 - header_length_over_16) ? 16 - header_length_over_16 : add_length;
for (size_t i = 0; i < injected_add; i++) {
(&((uint8_t*)&header[4])[header_length_over_16])[i] = add_data[i];
}
header_length_over_16 += injected_add;
add_data += injected_add;
add_length -= injected_add;
}
}
// Accumulate the second header block into the CBC-MAC
CRYPTO_DataWrite(&device->DATA3, &header[4]);
// Accumulate: XOR the input block into the previously accumulated value in DATA0
// and encrypt the result to get the updated accumulator in DATA0
device->CMD = CRYPTO_CMD_INSTR_DATA3TODATA0XOR;
device->CMD = CRYPTO_CMD_INSTR_AESENC;
device->CMD = CRYPTO_CMD_INSTR_DATA0TODATA3;
// Run the remainder of the ADD through the CBC-MAC accumulator
if (add_length > 0) {
// Set the iteration count
device->SEQCTRL = add_length;
device->SEQCTRLB = 0;
CRYPTO_EXECUTE_4(device,
CRYPTO_CMD_INSTR_DMA0TODATA, // Load new block of data into DATA0
CRYPTO_CMD_INSTR_DATA3TODATA0XOR, // XOR the accumulated tag with the new block
CRYPTO_CMD_INSTR_AESENC, // Encrypt the XOR result
CRYPTO_CMD_INSTR_DATA0TODATA3 // Store the new accumulated tag to DATA3
);
while (add_length) {
if (add_length < 16) {
// Use writeable header buffer for zero padding
header[0] = 0;
header[1] = 0;
header[2] = 0;
header[3] = 0;
// Since add_data is potentially unaligned, do a byte copy
for (size_t i = 0; i < add_length; i++) {
((uint8_t*)header)[i] = add_data[i];
}
CRYPTO_DataWrite(&device->DATA0, header);
add_length = 0;
} else {
CRYPTO_DataWriteUnaligned(&device->DATA0, add_data);
add_length -= 16;
add_data += 16;
}
}
}
} else {
// Move the CBC-MAC accumulator to DATA3
device->CMD = CRYPTO_CMD_INSTR_DATA0TODATA3;
}
// Set the iteration count
device->SEQCTRL = length;
device->SEQCTRLB = 0;
if (encrypt) {
CRYPTO_EXECUTE_16(device,
CRYPTO_CMD_INSTR_EXECIFA,
// Read data input into DATA2
CRYPTO_CMD_INSTR_DMA0TODATA,
CRYPTO_CMD_INSTR_DATA0TODATA2,
// Accumulate the plaintext into the CBC-MAC
CRYPTO_CMD_INSTR_DATA3TODATA0XOR,
CRYPTO_CMD_INSTR_AESENC,
CRYPTO_CMD_INSTR_DATA0TODATA3,
// Calculate key stream block
CRYPTO_CMD_INSTR_DATA1INC,
CRYPTO_CMD_INSTR_DATA1TODATA0,
CRYPTO_CMD_INSTR_AESENC,
// XOR plaintext with key stream and output the result
CRYPTO_CMD_INSTR_DATA2TODATA0XOR,
CRYPTO_CMD_INSTR_DATATODMA0,
// Calculate tag into DATA0 when all data has been processed
CRYPTO_CMD_INSTR_EXECIFLAST,
CRYPTO_CMD_INSTR_DATA1INCCLR,
CRYPTO_CMD_INSTR_DATA1TODATA0,
CRYPTO_CMD_INSTR_AESENC,
CRYPTO_CMD_INSTR_DATA3TODATA0XOR
);
} else {
CRYPTO_EXECUTE_18(device,
CRYPTO_CMD_INSTR_EXECIFA,
// Calculate key stream block into DATA0
CRYPTO_CMD_INSTR_DATA1INC,
CRYPTO_CMD_INSTR_DATA1TODATA0,
CRYPTO_CMD_INSTR_AESENC,
// XOR data input with key stream and output the result
CRYPTO_CMD_INSTR_DATA0TODATA2,
CRYPTO_CMD_INSTR_DMA0TODATA,
CRYPTO_CMD_INSTR_DATA2TODATA0XORLEN,
CRYPTO_CMD_INSTR_DATATODMA0,
// Accumulate the plaintext into the CBC-MAC
CRYPTO_CMD_INSTR_DATA0TODATA2,
CRYPTO_CMD_INSTR_DATA3TODATA0,
CRYPTO_CMD_INSTR_DATA2TODATA0XORLEN,
CRYPTO_CMD_INSTR_AESENC,
CRYPTO_CMD_INSTR_DATA0TODATA3,
// Calculate tag into DATA0 when all data has been processed
CRYPTO_CMD_INSTR_EXECIFLAST,
CRYPTO_CMD_INSTR_DATA1INCCLR,
CRYPTO_CMD_INSTR_DATA1TODATA0,
CRYPTO_CMD_INSTR_AESENC,
CRYPTO_CMD_INSTR_DATA3TODATA0XOR
);
}
while (length) {
if (length < 16) {
// Use writeable header buffer for zero padding
header[0] = 0;
header[1] = 0;
header[2] = 0;
header[3] = 0;
// Since input data is potentially unaligned, do a byte copy
for (size_t i = 0; i < length; i++) {
((uint8_t*)header)[i] = data_in[i];
}
CRYPTO_DataWrite(&device->DATA0, header);
CRYPTO_DataRead(&device->DATA0, header);
if (data_out) {
// Data output can be unaligned, too
for (size_t i = 0; i < length; i++) {
data_out[i] = ((uint8_t*)header)[i];
}
// In this case, we're guaranteed it is the last part of
// the data and don't need to adjust the pointer anymore.
}
length = 0;
} else {
CRYPTO_DataWriteUnaligned(&device->DATA0, data_in);
length -= 16;
data_in += 16;
if (data_out) {
CRYPTO_DataReadUnaligned(&device->DATA0, data_out);
data_out += 16;
} else {
CRYPTO_DataRead(&device->DATA0, header);
}
}
}
// Read calculated authentication tag from DATA0 register
CRYPTO_DataRead(&device->DATA0, header);
crypto_management_release_preemption(device);
if (encrypt) {
// For encryption, return the requested amount of tag
for (size_t i = 0; i < tag_length; i++) {
tag[i] = ((uint8_t*)header)[i];
}
} else {
// For decryption, verify the requested amount of tag
uint32_t accumulator = 0;
for (size_t i = 0; i < tag_length; i++) {
accumulator |= ((uint8_t*)header)[i] ^ tag[i];
}
if (accumulator != 0) {
return SL_STATUS_INVALID_SIGNATURE;
}
}
return SL_STATUS_OK;
}
// Perform a CCM encrypt/decrypt operation with BLE parameters and input.
// This means:
// * 13 bytes IV
// * 1 byte AAD (parameter 'header')
// * AES-128 key (16 byte key)
// * in-place encrypt/decrypt with variable length plain/ciphertext
// (up to 64 kB, uint16 overflow)
// * 4 byte tag
static sl_status_t aes_ccm_ble(bool encrypt,
unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag)
{
// Use 32-byte word aligned buffer to bypass some time-consuming logic in aes_ccm_radio
uint32_t b0b1_words[32 / sizeof(uint32_t)];
uint8_t* b0b1_bytes = (uint8_t*)b0b1_words;
// Fill in B0 block according to BLE spec
b0b1_bytes[0] = 0x49U;
// Copy in the 13 bytes of nonce
for (size_t i = 0; i < 13; i++) {
b0b1_bytes[i + 1] = iv[i];
}
b0b1_bytes[14] = (uint8_t) length >> 8;
b0b1_bytes[15] = (uint8_t) length;
b0b1_bytes[16] = 0; // upper octet of AAD length
b0b1_bytes[17] = 1; // lower octet of AAD length (BLE CCM always has only one byte of AAD)
b0b1_bytes[18] = header; // AAD
b0b1_bytes[19] = 0;
b0b1_words[5] = 0;
b0b1_words[6] = 0;
b0b1_words[7] = 0;
return aes_ccm_radio(encrypt,
NULL, 0,
data, data, length,
key,
b0b1_words, 32 - 16,
tag, 4);
}
//
// CCM buffer authenticated decryption optimized for BLE
//
sl_status_t sli_ccm_auth_decrypt_ble(unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag)
{
return aes_ccm_ble(false,
data,
length,
key,
iv,
header,
(uint8_t *) tag);
}
//
// CCM buffer encryption optimized for BLE
//
sl_status_t sli_ccm_encrypt_and_tag_ble(unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag)
{
return aes_ccm_ble(true,
data,
length,
key,
iv,
header,
tag);
}
sl_status_t sli_ccm_zigbee(bool encrypt,
const unsigned char *data_in,
unsigned char *data_out,
size_t length,
const unsigned char *key,
const unsigned char *iv,
const unsigned char *aad,
size_t aad_len,
unsigned char *tag,
size_t tag_len)
{
// Validated assumption: for ZigBee, the authenticated data
// length will always fit into a 16-bit length field (up to
// 64 kB of data), meaning the header data size will always
// be either 16 (no ciphertext) or 18 bytes long.
// Use 32-byte word aligned buffer to bypass some time-consuming logic in aes_ccm_radio
uint32_t header_words[32 / sizeof(uint32_t)];
uint8_t* header_bytes = (uint8_t*)header_words;
// Start with the 'flags' byte. It encodes whether there is AAD,
// and the length of the tag fields
header_bytes[0] = 0x01 // always 2 bytes of message length
| ((aad_len > 0) ? 0x40 : 0x00) // Set 'aflag' bit if there is AAD
| ((tag_len >= 4) ? (((tag_len - 2) / 2) << 3) : 0); // Encode tag length
for (size_t i = 0; i < 13; i++) {
header_bytes[i + 1] = iv[i];
}
header_bytes[14] = (uint8_t) length >> 8;
header_bytes[15] = (uint8_t) length;
header_words[4] = 0;
header_words[5] = 0;
header_words[6] = 0;
header_words[7] = 0;
if (aad_len > 0) {
header_bytes[16] = (uint8_t) aad_len >> 8; // upper octet of AAD length
header_bytes[17] = (uint8_t) aad_len; // lower octet of AAD length
}
return aes_ccm_radio(encrypt,
aad,
aad_len,
data_in,
data_out,
length,
key,
header_words,
(aad_len > 0 ? 2 : 0),
tag,
tag_len);
}
/*
* Process a table of BLE RPA device keys and look for a
* match against the supplied hash
*/
int sli_process_ble_rpa(const unsigned char keytable[],
uint32_t keymask,
uint32_t prand,
uint32_t hash)
{
size_t index;
uint32_t data_register[4] = { 0 };
data_register[3] = __REV(prand);
/* Mangling DDATA1 (KEY) and DDATA2 (= DATA0/DATA1). Max execution length = 2 */
CRYPTO_TypeDef *device =
crypto_management_acquire_preemption(CRYPTO_MANAGEMENT_SAVE_DDATA1
| CRYPTO_MANAGEMENT_SAVE_DDATA2
| CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ0);
/* Set up CRYPTO to do AES, and load prand */
device->CTRL = CRYPTO_CTRL_AES_AES128 | CRYPTO_CTRL_KEYBUFDIS;
device->WAC = 0UL;
CRYPTO_DataWrite(&device->DATA1, (uint32_t*)data_register);
/* For each key, execute AES encrypt operation and compare w hash */
/* Read result of previous iteration first to minimize stall while waiting
for AES to finish */
int currentindex = -1;
for ( index = 0; index < 32; index++ ) {
if ( (keymask & (1U << index)) == 0 ) {
continue;
}
CRYPTO_DataRead(&device->DATA0, data_register);
CRYPTO_DataWrite(&device->KEY, (uint32_t*)(&keytable[index * 16]));
CRYPTO_EXECUTE_2(device,
CRYPTO_CMD_INSTR_DATA1TODATA0,
CRYPTO_CMD_INSTR_AESENC);
if ( (currentindex >= 0)
&& ( (data_register[3] & 0xFFFFFF00UL) == __REV(hash) ) ) {
crypto_management_release_preemption(device);
return currentindex;
}
currentindex = index;
}
/* Read result of last encryption and check for hash */
CRYPTO_DataRead(&device->DATA0, data_register);
crypto_management_release_preemption(device);
if ( (data_register[3] & 0xFFFFFF00UL) == __REV(hash) ) {
return currentindex;
}
return -1;
}
sl_status_t sli_aes_crypt_ecb_radio(bool encrypt,
const unsigned char *key,
unsigned int keybits,
const unsigned char input[16],
volatile unsigned char output[16])
{
/* process one ore more blocks of data */
CRYPTO_TypeDef *device =
crypto_management_acquire_preemption(CRYPTO_MANAGEMENT_SAVE_DDATA1
| CRYPTO_MANAGEMENT_SAVE_DDATA2
| CRYPTO_MANAGEMENT_SAVE_DDATA4);
device->WAC = 0;
device->CTRL = 0;
CRYPTO_KeyBufWriteUnaligned(device, key,
(keybits == 128UL
? cryptoKey128Bits : cryptoKey256Bits));
if (!encrypt) {
// Transform encryption to decryption key
device->CMD = CRYPTO_CMD_INSTR_AESENC;
device->CMD = CRYPTO_CMD_INSTR_DDATA1TODDATA4;
}
CRYPTO_DataWriteUnaligned(&device->DATA0, (const uint8_t *)input);
if ( encrypt ) {
device->CMD = CRYPTO_CMD_INSTR_AESENC;
} else {
device->CMD = CRYPTO_CMD_INSTR_AESDEC;
}
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)output);
crypto_management_release_preemption(device);
return SL_STATUS_OK;
}
sl_status_t sli_aes_crypt_ctr_radio(const unsigned char *key,
unsigned int keybits,
const unsigned char input[16],
const unsigned char iv_in[16],
volatile unsigned char iv_out[16],
volatile unsigned char output[16])
{
/* process one ore more blocks of data */
CRYPTO_TypeDef *device =
crypto_management_acquire_preemption(CRYPTO_MANAGEMENT_SAVE_DDATA1
| CRYPTO_MANAGEMENT_SAVE_DDATA2
| CRYPTO_MANAGEMENT_SAVE_DDATA4);
device->WAC = 0;
device->CTRL = 0;
CRYPTO_KeyBufWriteUnaligned(device, key,
(keybits == 128UL
? cryptoKey128Bits : cryptoKey256Bits));
if ((uint32_t)iv_in != 0) {
CRYPTO_DataWriteUnaligned(&device->DATA1, (uint8_t *)iv_in);
} else {
uint32_t iv[4] = { 0, 0, 0, 0 };
CRYPTO_DataWrite(&device->DATA1, iv);
}
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0;
device->CMD = CRYPTO_CMD_INSTR_AESENC;
device->CMD = CRYPTO_CMD_INSTR_DATA1INC;
CRYPTO_DataWriteUnaligned(&device->DATA0XOR, (uint8_t *)(input));
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(output));
if ((uint32_t)iv_out != 0) {
CRYPTO_DataReadUnaligned(&device->DATA1, (uint8_t *)iv_out);
}
crypto_management_release_preemption(device);
return SL_STATUS_OK;
}
#endif /* CRYPTO_PRESENT */

View File

@ -0,0 +1,864 @@
/***************************************************************************//**
* @file
* @brief Accelerated cryptographic primitives using the RADIOAES peripheral.
*******************************************************************************
* # 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 "em_device.h"
#if defined(RADIOAES_PRESENT)
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
#include "sli_radioaes_management.h"
#include "sli_protocol_crypto.h"
#include "em_core.h"
#define AES_BLOCK_BYTES 16U
#define AES_128_KEY_BYTES 16U
#define AES_256_KEY_BYTES 32U
#define RADIOAES_CONFIG_BYTES 4U
#ifndef RADIOAES_BLE_RPA_MAX_KEYS
#define RADIOAES_BLE_RPA_MAX_KEYS 32
#endif
/// value for sli_radioaes_dma_sg_descr.tag to direct data to parameters
#define DMA_SG_TAG_ISCONFIG 0x00000010
/// value for sli_radioaes_dma_sg_descr.tag to direct data to processing
#define DMA_SG_TAG_ISDATA 0x00000000
/// value for sli_radioaes_dma_sg_descr.tag specifying data as last
#define DMA_SG_TAG_ISLAST 0x00000020
/// macro to set the offset in the configuration for sli_radioaes_dma_sg_descr.tag
#define DMA_SG_TAG_SETCFGOFFSET(a) ((((a) & 0xFF) << 8))
/// value for sli_radioaes_dma_sg_descr.tag specifying data type payload (will be encrypted/decrypted and authenticated)
#define DMA_SG_TAG_DATATYPE_AESPAYLOAD 0x00000000
/// value for sli_radioaes_dma_sg_descr.tag specifying data type header (will only be authenticated, not encrypted/decrypted)
#define DMA_SG_TAG_DATATYPE_AESHEADER 0x00000040
/// macro to set the amount of invalid bytes in for sli_radioaes_dma_sg_descr.tag
#define DMA_SG_TAG_SETINVALIDBYTES(a) ((((a) & 0x1F) << 8))
#define DMA_AXI_DESCR_CONST_ADDR 0x10000000
#define DMA_AXI_DESCR_REALIGN 0x20000000
#define DMA_AXI_DESCR_DISCARD 0x40000000
#define DMA_AXI_DESCR_INT_ENABLE 0x80000000
#define DMA_AXI_DESCR_INT_DISABLE 0x00000000
#define DMA_AXI_DESCR_NEXT_STOP 0x00000001
#define DMA_AXI_DESCR_NEXT_CONTINUE 0x00000000
#define DMA_AXI_DESCR_MASK_NEXT_ADD 0xFFFFFFFC
/// value of flags to discard the data
#define BLOCK_S_DISCARD_DATA 0x40000000
/// value of flags to realign the data
#define BLOCK_S_REALIGN_DATA 0x20000000
/// value of flags to set addressing in constant mode (pointing to a FIFO)
#define BLOCK_S_CONST_ADDR 0x10000000
/// value of flags to set addressing in increment mode (pointing to a buffer)
#define BLOCK_S_INCR_ADDR 0x00000000
/// mask for flags to only get DMA-related options
#define BLOCK_S_FLAG_MASK_DMA_PROPS 0x70000000
/// value of flags mask for fetcher location destination
#define BLOCK_S_MASK_LOC_DEST 0x00FFFFFF
/// Config ///
/// BA411E offset for Configuration word in DMA Scatter-Gather Tag
#define AES_OFFSET_CFG 0
/// BA411E offset for Configuration word in DMA Scatter-Gather Tag
#define AES_OFFSET_KEY 8
/// BA411E offset for Configuration word in DMA Scatter-Gather Tag
#define AES_OFFSET_IV 40
/// BA411E offset for Configuration word in DMA Scatter-Gather Tag
#define AES_OFFSET_IV2 56
/// BA411E offset for Configuration word in DMA Scatter-Gather Tag
#define AES_OFFSET_KEY2 72
/// BA411E offset for Configuration word in DMA Scatter-Gather Tag
#define AES_OFFSET_MASK 104
/// BA411E Mode Register value for ECB mode of operation
#define AES_MODEID_ECB 0x00000100
/// BA411E Mode Register value for CBC mode of operation
#define AES_MODEID_CBC 0x00000200
/// BA411E Mode Register value for CTR mode of operation
#define AES_MODEID_CTR 0x00000400
/// BA411E Mode Register value for CCM mode of operation
#define AES_MODEID_CCM 0x00002000
/// BA411E Mode Register value for CMAC mode of operation
#define AES_MODEID_CMA 0x00010000
/// BA411E Mode Register value for AES context saving
#define AES_MODEID_CX_SAVE 0x00000020
/// BA411E Mode Register value for AES context loading
#define AES_MODEID_CX_LOAD 0x00000010
/// BA411E Mode Register value for AES no context
#define AES_MODEID_NO_CX 0x00000000
/// BA411E Mode Register value for AES keysize of 128 bits
#define AES_MODEID_AES128 0x00000000
/// BA411E Mode Register value for AES keysize of 256 bits
#define AES_MODEID_AES256 0x00000004
/// BA411E Mode Register value for AES keysize of 192 bits
#define AES_MODEID_AES192 0x00000008
/// BA411E Mode Register value for encryption mode
#define AES_MODEID_ENCRYPT 0x00000000
/// BA411E Mode Register value for decryption mode
#define AES_MODEID_DECRYPT 0x00000001
/// BA411E Size for IV in GCM mode
#define AES_IV_GCM_SIZE 12
/// BA411E Size for IV in all modes except GCM
#define AES_IV_SIZE 16
/// BA411E Size for Context in GCM and CCM modes
#define AES_CTX_xCM_SIZE 32
/// BA411E Size for Context in all modes except GCM and CCM
#define AES_CTX_SIZE 16
///
/// @brief Select which IP core the DMA will use. To set in descriptor sli_radioaes_dma_sg_descr.tag.
///
typedef enum {
DMA_SG_ENGINESELECT_BYPASS = 0x00, ///< direct bypass from input to output
DMA_SG_ENGINESELECT_BA411E = 0x01, ///< data flow through BA411E AES
DMA_SG_ENGINESELECT_BA412 = 0x02, ///< data flow through BA412 DES
DMA_SG_ENGINESELECT_BA413 = 0x03, ///< data flow through BA413 Hash
DMA_SG_ENGINESELECT_BA417 = 0x04 ///< data flow through BA417 ChaChaPoly
} dma_engine_select_t;
///
/// @brief Structure that represent a descriptor for the DMA module
/// (in scatter-gather mode).
///
typedef struct {
volatile uint32_t address;
volatile uint32_t nextDescr;
volatile uint32_t lengthAndIrq;
volatile uint32_t tag;
} sli_radioaes_dma_descr_t;
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
#define SLI_RADIOAES_MASK_DESCRIPTOR(next_descr_addr) \
{ \
.address = (uint32_t) &sli_radioaes_mask, \
.nextDescr = next_descr_addr, \
.lengthAndIrq = 0x20000004UL, \
.tag = 0x00006811UL \
};
#endif
#define DMA_AXI_DESCR_END_POINTER ((sli_radioaes_dma_descr_t*) DMA_AXI_DESCR_NEXT_STOP)
// Local CCM variables
static const uint32_t aes_ccm_config_encrypt = AES_MODEID_CCM
| AES_MODEID_NO_CX
| AES_MODEID_AES128
| AES_MODEID_ENCRYPT;
static const uint32_t aes_ccm_config_decrypt = AES_MODEID_CCM
| AES_MODEID_NO_CX
| AES_MODEID_AES128
| AES_MODEID_DECRYPT;
static const uint32_t zeros = 0;
static sl_status_t sli_radioaes_run_operation(sli_radioaes_dma_descr_t *first_fetch_descriptor,
sli_radioaes_dma_descr_t *first_push_descriptor)
{
sli_radioaes_state_t aes_ctx;
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
sli_radioaes_dma_descr_t mask_descr = SLI_RADIOAES_MASK_DESCRIPTOR((uint32_t)first_fetch_descriptor);
#endif
sl_status_t status = sli_radioaes_acquire();
if (status == SL_STATUS_ISR) {
sli_radioaes_save_state(&aes_ctx);
} else if (status != SL_STATUS_OK) {
return status;
}
RADIOAES->CTRL = AES_CTRL_FETCHERSCATTERGATHER | AES_CTRL_PUSHERSCATTERGATHER;
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
RADIOAES->FETCHADDR = (uint32_t) &mask_descr;
#else
RADIOAES->FETCHADDR = (uint32_t) first_fetch_descriptor;
#endif
RADIOAES->PUSHADDR = (uint32_t) first_push_descriptor;
RADIOAES->CMD = AES_CMD_STARTPUSHER | AES_CMD_STARTFETCHER;
while (RADIOAES->STATUS & (AES_STATUS_FETCHERBSY | AES_STATUS_PUSHERBSY)) {
// Wait for completion
}
if (status == SL_STATUS_ISR) {
sli_radioaes_restore_state(&aes_ctx);
}
return sli_radioaes_release();
}
// CCM (and CCM-star) implementation
static sl_status_t aes_ccm_radio(bool encrypt,
const unsigned char *add_data,
size_t add_length,
const unsigned char *data_in,
unsigned char *data_out,
size_t length,
const unsigned char *key,
const unsigned char *header,
size_t header_length,
unsigned char *tag,
size_t tag_length)
{
// Assumptions:
// * There is always header input, but the header input may be block-aligned (BLE-CCM)
// * There may not always be ADD input (e.g. BLE-CCM)
// * There may not always be data input (e.g. CCM in authenticated-only mode)
// * The header input is pre-calculated by the caller of this function
// * Data output may be NULL (in which case it is discarded)
// * Tag length may be 0 (CCM-star), in which case the tag pointer is also allowed to be NULL
// Setup ver_failed output buffer and initialize it in case of decryption to an invalid value
volatile uint8_t ver_failed[AES_BLOCK_BYTES] = {[0 ... AES_BLOCK_BYTES - 1] = 0xFF };
// Calculate padding bytes. Since the accelerator expects to see the AESPAYLOAD data type
// at least once during the operation, ensure that we're emitting a padding block in case
// no input data is present.
size_t header_pad_bytes = (AES_BLOCK_BYTES - ((header_length + add_length) % AES_BLOCK_BYTES)) % AES_BLOCK_BYTES;
size_t data_pad_bytes = (length > 0 ? (AES_BLOCK_BYTES - (length % AES_BLOCK_BYTES)) % AES_BLOCK_BYTES : 16);
// Fetchers
// Tag output. If used, always the last descriptor. Not used for CCM-* without tag, the
// accelerator actually looks at the header and figures out whether or not to take in
// tag input.
sli_radioaes_dma_descr_t ccm_desc_fetcher_tag = {
.address = (uint32_t) tag,
.nextDescr = (uint32_t) DMA_AXI_DESCR_END_POINTER,
.lengthAndIrq = (uint32_t) tag_length
| BLOCK_S_INCR_ADDR
| BLOCK_S_REALIGN_DATA,
.tag = DMA_SG_ENGINESELECT_BA411E
| DMA_SG_TAG_ISDATA
| DMA_SG_TAG_ISLAST
| DMA_SG_TAG_DATATYPE_AESPAYLOAD
| DMA_SG_TAG_SETINVALIDBYTES(AES_BLOCK_BYTES - tag_length)
};
// Data input. Can be zero-length, in which case we'll issue a bogus descriptor instead.
sli_radioaes_dma_descr_t ccm_desc_fetcher_data = {
.address = (uint32_t) (length > 0 ? data_in : ver_failed),
.nextDescr = (uint32_t) ((encrypt || tag_length == 0) ? DMA_AXI_DESCR_END_POINTER : &ccm_desc_fetcher_tag),
.lengthAndIrq = (uint32_t) (length > 0 ? length : data_pad_bytes)
| BLOCK_S_INCR_ADDR
| BLOCK_S_REALIGN_DATA,
.tag = DMA_SG_ENGINESELECT_BA411E
| DMA_SG_TAG_ISDATA
| DMA_SG_TAG_DATATYPE_AESPAYLOAD
| ((encrypt || tag_length == 0) ? DMA_SG_TAG_ISLAST : 0)
| DMA_SG_TAG_SETINVALIDBYTES(data_pad_bytes),
};
// Possible CCM AAD block (concatenated with the header). Can be zero-length, in which case
// this descriptor should not be referenced but rather bypassed to data.
sli_radioaes_dma_descr_t ccm_desc_fetcher_add = {
.address = (uint32_t) add_data,
.nextDescr = (uint32_t) &ccm_desc_fetcher_data,
.lengthAndIrq = (uint32_t) add_length
| BLOCK_S_INCR_ADDR
| BLOCK_S_REALIGN_DATA,
.tag = DMA_SG_ENGINESELECT_BA411E
| DMA_SG_TAG_ISDATA
| DMA_SG_TAG_DATATYPE_AESHEADER
| DMA_SG_TAG_SETINVALIDBYTES(header_pad_bytes)
};
// Header input block. Always present.
sli_radioaes_dma_descr_t ccm_desc_fetcher_header = {
.address = (uint32_t) header,
.nextDescr = (uint32_t) (add_length > 0 ? &ccm_desc_fetcher_add : &ccm_desc_fetcher_data),
.lengthAndIrq = (uint32_t) header_length
| BLOCK_S_INCR_ADDR
| (add_length > 0 ? 0 : BLOCK_S_REALIGN_DATA),
.tag = DMA_SG_ENGINESELECT_BA411E
| DMA_SG_TAG_ISDATA
| DMA_SG_TAG_DATATYPE_AESHEADER
| (add_length > 0 ? 0 : DMA_SG_TAG_SETINVALIDBYTES(header_pad_bytes))
};
// Key input block. Always present.
sli_radioaes_dma_descr_t ccm_desc_fetcher_key = {
.address = (uint32_t) key,
.nextDescr = (uint32_t) &ccm_desc_fetcher_header,
.lengthAndIrq = (uint32_t) AES_128_KEY_BYTES
| BLOCK_S_INCR_ADDR
| BLOCK_S_REALIGN_DATA,
.tag = DMA_SG_ENGINESELECT_BA411E
| DMA_SG_TAG_ISCONFIG
| DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
};
// Operation configuration word block. Always present.
sli_radioaes_dma_descr_t ccm_desc_fetcher_config = {
.address = (uint32_t) (encrypt ? &aes_ccm_config_encrypt : &aes_ccm_config_decrypt),
.nextDescr = (uint32_t) &ccm_desc_fetcher_key,
.lengthAndIrq = (uint32_t) RADIOAES_CONFIG_BYTES
| BLOCK_S_INCR_ADDR
| BLOCK_S_REALIGN_DATA,
.tag = DMA_SG_ENGINESELECT_BA411E
| DMA_SG_TAG_ISCONFIG
| DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
};
// Pushers
// Tag / verification output padding, only if 0 < tag length < 16 bytes.
sli_radioaes_dma_descr_t ccm_desc_pusher_final_padding = {
.address = (uint32_t) NULL,
.nextDescr = (uint32_t) DMA_AXI_DESCR_END_POINTER,
.lengthAndIrq = (uint32_t) (AES_BLOCK_BYTES - tag_length)
| DMA_AXI_DESCR_DISCARD
};
// Tag output. Direct into tag buffer for encrypt, into local buffer for
// decrypt-and-verify. This descriptor is not referenced with tag_length == 0 (CCM-*)
sli_radioaes_dma_descr_t ccm_desc_pusher_tag = {
.address = (uint32_t) (encrypt ? tag : (unsigned char *)ver_failed),
.nextDescr = (uint32_t) ((AES_BLOCK_BYTES - tag_length) > 0 ? &ccm_desc_pusher_final_padding : DMA_AXI_DESCR_END_POINTER),
.lengthAndIrq = (uint32_t) tag_length
};
// Data padding output. There's guaranteed always at least one of data or data padding.
sli_radioaes_dma_descr_t ccm_desc_pusher_data_padding = {
.address = (uint32_t) NULL,
.nextDescr = (uint32_t) (tag_length > 0 ? &ccm_desc_pusher_tag : DMA_AXI_DESCR_END_POINTER),
.lengthAndIrq = (uint32_t) data_pad_bytes
| DMA_AXI_DESCR_DISCARD,
};
// Data (ciphertext/plaintext) output. Pointer can be NULL, in which case we tell the
// DMA to discard the data.
sli_radioaes_dma_descr_t ccm_desc_pusher_data = {
.address = (uint32_t) data_out,
.nextDescr = (uint32_t) (data_pad_bytes > 0 ? &ccm_desc_pusher_data_padding : (tag_length > 0 ? &ccm_desc_pusher_tag : DMA_AXI_DESCR_END_POINTER)),
.lengthAndIrq = (uint32_t) length
| (data_out == NULL ? DMA_AXI_DESCR_DISCARD : 0),
};
// Discard all AAD input (which is reflected back to the output). There's guaranteed always a header.
sli_radioaes_dma_descr_t ccm_desc_pusher_header_add = {
.address = (uint32_t) NULL,
.nextDescr = (uint32_t) (length > 0 ? &ccm_desc_pusher_data : &ccm_desc_pusher_data_padding),
.lengthAndIrq = (uint32_t) (header_length + add_length + header_pad_bytes)
| DMA_AXI_DESCR_DISCARD
};
sl_status_t status = sli_radioaes_run_operation(&ccm_desc_fetcher_config, &ccm_desc_pusher_header_add);
if (status != SL_STATUS_OK) {
return status;
}
// Check MIC
if (!encrypt) {
uint32_t accumulator = 0;
for (size_t i = 0; i < tag_length; i++) {
accumulator |= ver_failed[i];
}
if (accumulator != 0) {
return SL_STATUS_INVALID_SIGNATURE;
}
}
return SL_STATUS_OK;
}
// Perform a CCM encrypt/decrypt operation with BLE parameters and input.
// This means:
// * 13 bytes IV
// * 1 byte AAD (parameter 'header')
// * AES-128 key (16 byte key)
// * in-place encrypt/decrypt with variable length plain/ciphertext
// (up to 64 kB, uint16 overflow)
// * 4 byte tag
static sl_status_t aes_ccm_ble(bool encrypt,
unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag)
{
uint8_t b0b1[19];
// Fill in B0 block according to BLE spec
b0b1[0] = 0x49U;
// Copy in the 13 bytes of nonce
for (size_t i = 0; i < 13; i++) {
b0b1[i + 1] = iv[i];
}
b0b1[14] = (uint8_t) length >> 8;
b0b1[15] = (uint8_t) length;
b0b1[16] = 0; // upper octet of AAD length
b0b1[17] = 1; // lower octet of AAD length (BLE CCM always has only one byte of AAD)
b0b1[18] = header; // AAD
return aes_ccm_radio(encrypt,
NULL, 0,
data, data, length,
key,
b0b1, sizeof(b0b1),
tag, 4);
}
sl_status_t sli_aes_crypt_ctr_radio(const unsigned char *key,
unsigned int keybits,
const unsigned char input[AES_BLOCK_BYTES],
const unsigned char iv_in[AES_BLOCK_BYTES],
volatile unsigned char iv_out[AES_BLOCK_BYTES],
volatile unsigned char output[AES_BLOCK_BYTES])
{
uint32_t aes_config;
static const uint32_t zero = 0;
switch (keybits) {
case 256:
aes_config = AES_MODEID_CTR | AES_MODEID_CX_LOAD | (((uint32_t)iv_out != 0) ? AES_MODEID_CX_SAVE : 0) | AES_MODEID_AES256;
break;
case 192:
return SL_STATUS_NOT_SUPPORTED;
case 128:
aes_config = AES_MODEID_CTR | AES_MODEID_CX_LOAD | (((uint32_t)iv_out != 0) ? AES_MODEID_CX_SAVE : 0) | AES_MODEID_AES128;
break;
default:
return SL_STATUS_INVALID_KEY;
}
sli_radioaes_dma_descr_t aes_desc_pusher_ctx = {
.address = (uint32_t) iv_out,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
};
sli_radioaes_dma_descr_t aes_desc_pusher_data = {
.address = (uint32_t) output,
.nextDescr = (((uint32_t)iv_out != 0) ? (uint32_t) &aes_desc_pusher_ctx : DMA_AXI_DESCR_NEXT_STOP),
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISDATA
};
sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
.address = (uint32_t) input,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD
};
sli_radioaes_dma_descr_t aes_desc_fetcher_no_ctx = {
.address = (uint32_t) &zero,
.nextDescr = (uint32_t) &aes_desc_fetcher_data,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_CONST_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_IV)
};
sli_radioaes_dma_descr_t aes_desc_fetcher_ctx = {
.address = (uint32_t) iv_in,
.nextDescr = (uint32_t) &aes_desc_fetcher_data,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_IV)
};
sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
.address = (uint32_t) &aes_config,
.nextDescr = (((uint32_t)iv_in != 0) ? (uint32_t) &aes_desc_fetcher_ctx : (uint32_t) &aes_desc_fetcher_no_ctx),
.lengthAndIrq = sizeof(aes_config),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
};
sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
.address = (uint32_t) key,
.nextDescr = (uint32_t) &aes_desc_fetcher_config,
.lengthAndIrq = (uint32_t) (keybits / 8) | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
};
// Start operation
return sli_radioaes_run_operation(&aes_desc_fetcher_key, &aes_desc_pusher_data);
}
sl_status_t sli_aes_crypt_ecb_radio(bool encrypt,
const unsigned char *key,
unsigned int keybits,
const unsigned char input[AES_BLOCK_BYTES],
volatile unsigned char output[AES_BLOCK_BYTES])
{
uint32_t aes_config;
switch (keybits) {
case 256:
aes_config = AES_MODEID_ECB | AES_MODEID_NO_CX | AES_MODEID_AES256;
break;
case 192:
return SL_STATUS_NOT_SUPPORTED;
case 128:
aes_config = AES_MODEID_ECB | AES_MODEID_NO_CX | AES_MODEID_AES128;
break;
default:
return SL_STATUS_INVALID_KEY;
}
aes_config |= encrypt ? AES_MODEID_ENCRYPT : AES_MODEID_DECRYPT;
sli_radioaes_dma_descr_t aes_desc_pusher_data = {
.address = (uint32_t) output,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
};
sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
.address = (uint32_t) input,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD
};
sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
.address = (uint32_t) &aes_config,
.nextDescr = (uint32_t) &aes_desc_fetcher_data,
.lengthAndIrq = sizeof(aes_config),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
};
sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
.address = (uint32_t) key,
.nextDescr = (uint32_t) &aes_desc_fetcher_config,
.lengthAndIrq = (uint32_t) (keybits / 8) | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
};
// Start operation
return sli_radioaes_run_operation(&aes_desc_fetcher_key, &aes_desc_pusher_data);
}
sl_status_t sli_aes_cmac_radio(const unsigned char *key,
unsigned int keybits,
const unsigned char *input,
unsigned int length,
volatile unsigned char output[16])
{
uint32_t aes_config;
switch (keybits) {
case 256:
aes_config = AES_MODEID_CMA | AES_MODEID_NO_CX | AES_MODEID_AES256 | AES_MODEID_ENCRYPT;
break;
case 192:
return SL_STATUS_NOT_SUPPORTED;
case 128:
aes_config = AES_MODEID_CMA | AES_MODEID_NO_CX | AES_MODEID_AES128 | AES_MODEID_ENCRYPT;
break;
default:
return SL_STATUS_INVALID_KEY;
}
size_t pad_len = 16 - (length % 16);
if (pad_len == 16 && length > 0) {
pad_len = 0;
}
if (length == 0) {
length = 16UL;
input = (const unsigned char *)&zeros;
} else {
length = (length + 15) & ~0xFUL;
}
sli_radioaes_dma_descr_t aes_desc_pusher_data = {
.address = (uint32_t) output,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
};
sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
.address = (uint32_t) input,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = length | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD | DMA_SG_TAG_SETINVALIDBYTES(pad_len)
};
sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
.address = (uint32_t) &aes_config,
.nextDescr = (uint32_t) &aes_desc_fetcher_data,
.lengthAndIrq = sizeof(aes_config),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
};
sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
.address = (uint32_t) key,
.nextDescr = (uint32_t) &aes_desc_fetcher_config,
.lengthAndIrq = (uint32_t) (keybits / 8) | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
};
// Start operation
return sli_radioaes_run_operation(&aes_desc_fetcher_key, &aes_desc_pusher_data);
}
//
// CCM buffer authenticated decryption optimized for BLE
//
sl_status_t sli_ccm_auth_decrypt_ble(unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag)
{
return aes_ccm_ble(false,
data,
length,
key,
iv,
header,
(uint8_t *) tag);
}
//
// CCM buffer encryption optimized for BLE
//
sl_status_t sli_ccm_encrypt_and_tag_ble(unsigned char *data,
size_t length,
const unsigned char *key,
const unsigned char *iv,
unsigned char header,
unsigned char *tag)
{
return aes_ccm_ble(true,
data,
length,
key,
iv,
header,
tag);
}
sl_status_t sli_ccm_zigbee(bool encrypt,
const unsigned char *data_in,
unsigned char *data_out,
size_t length,
const unsigned char *key,
const unsigned char *iv,
const unsigned char *aad,
size_t aad_len,
unsigned char *tag,
size_t tag_len)
{
// Validated assumption: for ZigBee, the authenticated data
// length will always fit into a 16-bit length field, meaning
// the header will always be either 16 or 18 bytes long.
uint8_t header[18];
// Start with the 'flags' byte. It encodes whether there is AAD,
// and the length of the tag fields
header[0] = 0x01 // always 2 bytes of message length
| ((aad_len > 0) ? 0x40 : 0x00) // Set 'aflag' bit if there is AAD
| ((tag_len >= 4) ? (((tag_len - 2) / 2) << 3) : 0); // Encode tag length
for (size_t i = 0; i < 13; i++) {
header[i + 1] = iv[i];
}
header[14] = (uint8_t) length >> 8;
header[15] = (uint8_t) length;
if (aad_len > 0) {
header[16] = (uint8_t) aad_len >> 8; // upper octet of AAD length
header[17] = (uint8_t) aad_len; // lower octet of AAD length
}
return aes_ccm_radio(encrypt,
aad,
aad_len,
data_in,
data_out,
length,
key,
header,
(aad_len > 0 ? 18 : 16),
tag,
tag_len);
}
//
// Process a table of BLE RPA device keys and look for a
// match against the supplied hash. Algorithm is AES-128.
//
int sli_process_ble_rpa(const unsigned char keytable[],
uint32_t keymask,
uint32_t prand,
uint32_t hash)
{
int block;
int previous_block = -1, result = -1;
static const uint32_t aes_rpa_config = AES_MODEID_ECB
| AES_MODEID_NO_CX
| AES_MODEID_AES128
| AES_MODEID_ENCRYPT;
uint32_t rpa_data_in[AES_BLOCK_BYTES / sizeof(uint32_t)] = { 0 };
volatile uint32_t rpa_data_out[AES_BLOCK_BYTES / sizeof(uint32_t)];
sli_radioaes_state_t aes_ctx;
CORE_DECLARE_IRQ_STATE;
rpa_data_in[3] = __REV(prand);
sli_radioaes_dma_descr_t aes_desc_pusher_data = {
.address = (uint32_t) rpa_data_out,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST
};
sli_radioaes_dma_descr_t aes_desc_fetcher_data = {
.address = (uint32_t) rpa_data_in,
.nextDescr = DMA_AXI_DESCR_NEXT_STOP,
.lengthAndIrq = AES_BLOCK_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISLAST | DMA_SG_TAG_ISDATA | DMA_SG_TAG_DATATYPE_AESPAYLOAD
};
sli_radioaes_dma_descr_t aes_desc_fetcher_config = {
.address = (uint32_t) &aes_rpa_config,
.nextDescr = (uint32_t) &aes_desc_fetcher_data,
.lengthAndIrq = sizeof(aes_rpa_config),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_CFG)
};
volatile sli_radioaes_dma_descr_t aes_desc_fetcher_key = {
.address = (uint32_t) NULL, // Filled out in each round of RPA check
.nextDescr = (uint32_t) &aes_desc_fetcher_config,
.lengthAndIrq = (uint32_t) AES_128_KEY_BYTES | (BLOCK_S_INCR_ADDR & BLOCK_S_FLAG_MASK_DMA_PROPS),
.tag = DMA_SG_ENGINESELECT_BA411E | DMA_SG_TAG_ISCONFIG | DMA_SG_TAG_SETCFGOFFSET(AES_OFFSET_KEY)
};
// Start operation
sl_status_t status = sli_radioaes_acquire();
if (status == SL_STATUS_ISR) {
sli_radioaes_save_state(&aes_ctx);
} else if (status != SL_STATUS_OK) {
return -1;
}
RADIOAES->CTRL = AES_CTRL_FETCHERSCATTERGATHER | AES_CTRL_PUSHERSCATTERGATHER;
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
// Start with feeding the mask input
sli_radioaes_dma_descr_t mask_descr = SLI_RADIOAES_MASK_DESCRIPTOR(DMA_AXI_DESCR_NEXT_STOP);
RADIOAES->FETCHADDR = (uint32_t) &mask_descr;
RADIOAES->CMD = AES_CMD_STARTFETCHER;
#endif
// Start a critical section to avoid preemption in-between loading of the RPA key
// and starting the corresponding data pusher.
CORE_ENTER_CRITICAL();
// Data output contains hash in the most significant word (WORD3).
// Descriptors for blocks that are not included in key mask will be skipped.
for (block = 0; block < RADIOAES_BLE_RPA_MAX_KEYS; block++) {
if ( keymask & (1U << block) ) { // Skip masked keys
// Handle pending interrupts while the peripheral is in 'preemptable' state
CORE_YIELD_CRITICAL();
// Write key address and start operation
while (RADIOAES->STATUS & AES_STATUS_FETCHERBSY) {
// Wait for completion
}
aes_desc_fetcher_key.address = (uint32_t) &keytable[block * AES_128_KEY_BYTES];
RADIOAES->FETCHADDR = (uint32_t) &aes_desc_fetcher_key;
RADIOAES->CMD = AES_CMD_STARTFETCHER;
// Wait for pusher from previous round to finish
while (RADIOAES->STATUS & AES_STATUS_PUSHERBSY) {
// Wait for completion
}
RADIOAES->PUSHADDR = (uint32_t) &aes_desc_pusher_data;
// Check previous results while AES is processing
if ((previous_block >= 0) && ((rpa_data_out[3] & 0xFFFFFF00) == __REV(hash)) ) {
// Make sure AES is finished before returning
RADIOAES->CMD = AES_CMD_STARTPUSHER;
result = previous_block;
break;
}
// Start pusher so it is ready to push results when encryption is done
RADIOAES->CMD = AES_CMD_STARTPUSHER;
previous_block = block;
}
}
CORE_EXIT_CRITICAL();
// Wait for last data and check it
while (RADIOAES->STATUS & AES_STATUS_PUSHERBSY) {
// Wait for completion
}
if (status == SL_STATUS_ISR) {
sli_radioaes_restore_state(&aes_ctx);
}
sli_radioaes_release();
if (result >= 0) {
return result;
}
if ((rpa_data_out[3] & 0xFFFFFF00) == __REV(hash) ) {
return previous_block;
}
// No match
return -1;
}
void sli_aes_seed_mask(void)
{
// Acquiring and releasing the peripheral should ensure the mask is properly
// set.
(void) sli_radioaes_acquire();
(void) sli_radioaes_release();
}
/// @endcond
#endif // defined(RADIOAES_PRESENT)

View File

@ -0,0 +1,203 @@
/***************************************************************************//**
* @file
* @brief Threadsafe utilities for RADIOAES peripheral.
*******************************************************************************
* # 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 "em_device.h"
#if defined(RADIOAES_PRESENT)
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
#include "sli_radioaes_management.h"
#include "sli_se_manager_osal.h"
#include "em_core.h"
#if defined(SL_SE_MANAGER_THREADING)
static se_manager_osal_mutex_t radioaes_lock = { 0 };
static volatile bool radioaes_lock_initialized = false;
#endif
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
#if defined(SL_COMPONENT_CATALOG_PRESENT)
#include "sl_component_catalog.h"
#endif
#if defined(SL_CATALOG_PSA_CRYPTO_PRESENT)
// If the PSA Crypto core is present, use its randomness abstraction to get
// the initial mask seed.
#include "psa/crypto.h"
#else
// If the PSA Crypto core is not present, we need to target the TRNG driver
// directly to get the initial mask seed. We'll always have an external randomness
// provider function on devices containing a RADIOAES instance.
#include "sli_psa_driver_common.h"
#endif
#include "sl_assert.h"
uint32_t sli_radioaes_mask = 0;
static void sli_radioaes_update_mask(void)
{
if (sli_radioaes_mask == 0) {
// Mask has not been initialized yet, get a random value to start
#if defined(SL_CATALOG_PSA_CRYPTO_PRESENT)
psa_status_t status = psa_generate_random((uint8_t*)&sli_radioaes_mask, sizeof(sli_radioaes_mask));
EFM_ASSERT(status == PSA_SUCCESS);
#else
size_t out_len = 0;
psa_status_t status = mbedtls_psa_external_get_random(NULL, (uint8_t*)&sli_radioaes_mask, sizeof(sli_radioaes_mask), &out_len);
EFM_ASSERT(status == PSA_SUCCESS);
EFM_ASSERT(out_len == sizeof(sli_radioaes_mask));
#endif
}
// Use a different mask for each new operation
// The masking logic requires the upper mask bit to be set
sli_radioaes_mask = (sli_radioaes_mask + 1) | (1UL << 31);
}
#endif // SLI_RADIOAES_REQUIRES_MASKING
sl_status_t sli_radioaes_acquire(void)
{
#if defined(_CMU_CLKEN0_MASK)
CMU->CLKEN0 |= CMU_CLKEN0_RADIOAES;
#endif
CMU->RADIOCLKCTRL |= CMU_RADIOCLKCTRL_EN;
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0U) {
// IRQ: need to store & restore RADIOAES registers
while (RADIOAES->STATUS & (AES_STATUS_FETCHERBSY | AES_STATUS_PUSHERBSY | AES_STATUS_SOFTRSTBSY)) {
// Wait for completion of the previous operation, since the RADIOAES
// peripheral does not support preemption of an operation in progress.
}
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
// The mask should have been initialized from non-ISR context by calling
// sl_mbedtls_init, before using the radioaes.
EFM_ASSERT(sli_radioaes_mask != 0);
#endif
return SL_STATUS_ISR;
} else {
#if defined(SL_SE_MANAGER_THREADING)
sl_status_t ret = SL_STATUS_OK;
// Non-IRQ, RTOS available: take mutex
// Initialize mutex if that hasn't happened yet
// Check flag first before going into a critical section, to avoid going into
// a critical section on every single acquire() call. Since the _initialized
// flag only transitions false -> true, we can in 99% of the calls avoid the
// critical section.
if (!radioaes_lock_initialized) {
int32_t kernel_lock_state = 0;
osKernelState_t kernel_state = se_manager_osal_kernel_get_state();
if (kernel_state != osKernelInactive && kernel_state != osKernelReady) {
kernel_lock_state = se_manager_osal_kernel_lock();
if (kernel_lock_state < 0) {
return SL_STATUS_SUSPENDED;
}
}
// Check the flag again after entering the critical section. Now that we're
// in the critical section, we can be sure that we are the only ones looking
// at the flag and no-one is interrupting us during its manipulation.
if (!radioaes_lock_initialized) {
ret = se_manager_osal_init_mutex(&radioaes_lock);
if (ret == SL_STATUS_OK) {
radioaes_lock_initialized = true;
}
}
if (kernel_state != osKernelInactive && kernel_state != osKernelReady) {
if (se_manager_osal_kernel_restore_lock(kernel_lock_state) < 0) {
return SL_STATUS_INVALID_STATE;
}
}
}
if (ret == SL_STATUS_OK) {
ret = se_manager_osal_take_mutex(&radioaes_lock);
}
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
if (ret == SL_STATUS_OK) {
sli_radioaes_update_mask();
}
#endif
return ret;
#else
// Non-IRQ, no RTOS: busywait
while (RADIOAES->STATUS & (AES_STATUS_FETCHERBSY | AES_STATUS_PUSHERBSY | AES_STATUS_SOFTRSTBSY)) {
// Wait for completion
}
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
sli_radioaes_update_mask();
#endif
return SL_STATUS_OK;
#endif
}
}
sl_status_t sli_radioaes_release(void)
{
// IRQ: nothing to do
if ((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0U) {
return SL_STATUS_OK;
}
#if defined(SL_SE_MANAGER_THREADING)
// Non-IRQ, RTOS available: free mutex
return se_manager_osal_give_mutex(&radioaes_lock);
#else
// Non-IRQ, no RTOS: nothing to do.
return SL_STATUS_OK;
#endif
}
sl_status_t sli_radioaes_save_state(sli_radioaes_state_t *ctx)
{
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
ctx->FETCHADDR = RADIOAES->FETCHADDR;
ctx->PUSHADDR = RADIOAES->PUSHADDR;
CORE_EXIT_CRITICAL();
return SL_STATUS_OK;
}
sl_status_t sli_radioaes_restore_state(sli_radioaes_state_t *ctx)
{
CORE_DECLARE_IRQ_STATE;
CORE_ENTER_CRITICAL();
RADIOAES->FETCHADDR = ctx->FETCHADDR;
RADIOAES->PUSHADDR = ctx->PUSHADDR;
CORE_EXIT_CRITICAL();
return SL_STATUS_OK;
}
/// @endcond
#endif //defined(RADIOAES_PRESENT)

View File

@ -0,0 +1,101 @@
/**************************************************************************/ /**
* @file
* @brief Threadsafe utilities for RADIOAES peripheral.
*******************************************************************************
* # 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 SLI_RADIOAES_MANAGEMENT_H
#define SLI_RADIOAES_MANAGEMENT_H
/// @cond DO_NOT_INCLUDE_WITH_DOXYGEN
#include <stdint.h>
#include "sl_status.h"
#if defined(RADIOAES_PRESENT)
/***************************************************************************//**
* @addtogroup sli_protocol_crypto
* @{
******************************************************************************/
///
/// @brief Structure that represents the state of the RADIOAES peripheral
/// (in scatter-gather mode).
///
typedef struct {
uint32_t FETCHADDR; ///< Fetcher Address
uint32_t PUSHADDR; ///< Pusher Address
} sli_radioaes_state_t;
#if defined(SLI_RADIOAES_REQUIRES_MASKING)
/// Static variable containing the masking value for the RADIOAES
extern uint32_t sli_radioaes_mask;
#endif // SLI_RADIOAES_REQUIRES_MASKING
/***************************************************************************//**
* @brief Acquire RADIOAES access
*
* @return SL_STATUS_OK if successful and resource is idle,
* SL_STATUS_ISR if successful but resource was preempted, in
* which case the caller is responsible for saving state,
* relevant status code on error
******************************************************************************/
sl_status_t sli_radioaes_acquire(void);
/***************************************************************************//**
* @brief Release RADIOAES access
*
* @return SL_STATUS_OK if successful, relevant status code on error
******************************************************************************/
sl_status_t sli_radioaes_release(void);
/***************************************************************************//**
* @brief Save RADIOAES register state to RAM
*
* @param ctx Context struct to save register state into
*
* @return SL_STATUS_OK if successful, relevant status code on error
******************************************************************************/
sl_status_t sli_radioaes_save_state(sli_radioaes_state_t *ctx);
/***************************************************************************//**
* @brief Restore RADIOAES register state from RAM
*
* @param ctx Context struct to restore register state from
*
* @return SL_STATUS_OK if successful, relevant status code on error
******************************************************************************/
sl_status_t sli_radioaes_restore_state(sli_radioaes_state_t *ctx);
#ifdef __cplusplus
}
#endif
/// @} (end addtogroup sli_protocol_crypto)
#endif // RADIOAES_PRESENT
/// @endcond
#endif // SLI_RADIOAES_MANAGEMENT_H

8
zephyr/CMakeLists.txt Normal file
View File

@ -0,0 +1,8 @@
# Copyright (c) 2022 Antmicro <www.antmicro.com>
#
# SPDX-License-Identifier: Apache-2.0
if(CONFIG_BT_SILABS_HCI)
zephyr_include_directories(include)
zephyr_sources(src/sl_bt_ll_zephyr.c)
endif()

3
zephyr/Kconfig Normal file
View File

@ -0,0 +1,3 @@
# This file is required by Zephyr build system to properly y-select
# CONFIG_TAINT_* symbols when blobs are downloaded with the `west blobs`
# command.

View File

@ -0,0 +1,787 @@
MASTER SOFTWARE LICENSE AGREEMENT Version 20210909
THIS MASTER SOFTWARE LICENSE AGREEMENT (“AGREEMENT”) GOVERNS YOUR USE OF THE
LICENSED MATERIALS. INSTALLING, COPYING OR OTHERWISE USING THE SOFTWARE,
INDICATES YOUR ACCEPTANCE OF THE TERMS OF THIS AGREEMENT REGARDLESS OF WHETHER
YOU CLICK THE “ACCEPT” BUTTON. IF YOU DO NOT AGREE WITH THESE TERMS AND
CONDITIONS OR IF YOU ARE NOT AUTHORIZED TO ACCEPT THE TERMS OF THIS LICENSE ON
BEHALF OF YOUR EMPLOYER, DECLINE THE LICENSE TERMS AND DO NOT USE THE SOFTWARE
OR DOCUMENTATION. THESE TERMS GOVERN YOUR CONTINUED USE OF THE LICENSED
MATERIALS THAT YOU DOWNLOAD NOW OR IN THE FUTURE, INCLUDING SUCH ADDITIONAL
SOFTWARE MADE AVAILABLE TO YOU THROUGH THE LICENSED MATERIALS YOU HAVE
SELECTED, AND ALL UPDATES AND VERSIONS OF SUCH SOFTWARE.
1. Definitions.
“Application” means a product developed by Licensee, or for Licensee by a
third party, that contains Licensed Programs.
“Authorized Application” means an Application that contains, integrates, is
packaged with, or functions with a Silicon Labs Device in Licensees
Application. This includes a Licensed Program embedded in a network
co-processor or host processor that operates in conjunction with a Silicon
Labs Device.
“Authorized Subcontractor” means a third-party subcontractor that you engage
to design or manufacture Authorized Applications and has executed an agreement
that is consistent with the terms of this Agreement, including its
confidentiality provisions. At all times, you shall remain responsible for the
actions or non-actions of you Authorized Subcontractors the same as if the
action on non-action was committed by you.
“Beta Software” means Software, including Software included within an SDK,
that is undergoing testing or further development, and has not reached the
generally available (GA) stage of development.
“Commercial License” means an executed, in effect, software license agreement
between Licensee and Silicon Labs that governs Licensees rights and
obligations with respect to Licensees use of Micrium Software.
"Commercial Purpose” means embedding Micrium Software in any Application that
you sell or license to End Users or plan to do so.
“Derivative Works” means a work based upon the Source Code version of the
Software, such as a revision, modification, translation, abridgment,
condensation, expansion or any other form in which such Software may be
recast, transformed or adapted, and that, if prepared without authorization
from Silicon Labs, would constitute copyright infringement.
“Development Tool” means a software provided by Silicon Labs to enable
development of Authorized Applications, configuration of Silicon Labs Devices
and Software.
“Documentation” means Silicon Labs technical documentation related to the
Software, excluding advertising or marketing materials.
“Embedded Stacks” means Software (other than Micrium Software) that is stack
libraries, application layers, and example code.
“End User” means a purchaser, sublicensee, recipient and/or user of an
Application obtained directly or indirectly from Licensee.
“External Manufacturers” means a third-party manufacturer, including such
manufacturer's subcontractors and agents, which is authorized by Licensee to
design and/or manufacture the Applications and to use, install, and test the
Applications and the Licensed Programs.
“Firmware” means executable or binary code that is embedded in the Silicon
Labs Device in ROM or flash memory and cannot be modified by Licensee.
“Licensee” or “you” means the acquirer of the license rights granted by this
Agreement. If you are an individual working solely on your own behalf, then
you are the Licensee. If you are an employee working on behalf of your
employer, then your employer is the Licensee and you confirm that you are
authorized to accept the terms of this Agreement on behalf of your Employer.
“Licensed Programs” means Software in Object Code form that was either
originally in Object Code form or was compiled from the Software or Derivative
Works and is designed to operate in Applications in Authorized Applications.
“Licensed Materials” means Software and the related Documentation including
all updates and upgrades of the foregoing.
“Micrium Software” means the Micrium real time kernel within the Micrium real
time operating system (Micrium OS).
“Modified Open Source Software” means Silicon Labs' modifications to Open
Source Software that was created by a third party.
“Object Code” means computer programming code in binary form suitable for
machine execution by a processor without the intervening steps of
interpretation or compilation.
“Open Source Software” means the Source Code version of software that may be
freely used, modified or distributed without payment of a license fee or
royalties subject to the terms of a publicly available software license,
excluding Modified Open Source Software, the use of which is subject to the
terms of this Agreement.
“Personal Information” means data concerning an individual user, including but
not limited to a users activity on a Silicon Labs website, location, IP
address, mobile device ID, name, or biometric data collected, stored or
transmitted by a Silicon Lab Device or Software.
“SDK” means software development kit (other than Micrium Software).
“Silicon Labs” means Silicon Laboratories Inc., a Delaware corporation located
at 400 W. Cesar Chavez, Austin, TX 78701 if you are physically located within
the United States. If you are physically located outside of the United States,
Silicon Labs means Silicon Laboratories International Pte Ltd., a Singapore
corporation located at No. 18 Tai Seng Street, #05-01, 18 Tai Seng, Singapore
539775.
"Silicon Labs Devices” means Silicon Labs branded integrated circuit chips
purchased from Silicon Labs or one of its authorized distributors.
“Silicon Labs Open Source Code” means Software created by Silicon Labs and
which is (a) delivered to Licensee in Source Code format, (b) is identified as
open source code and (c) states that use of the software is subject to the
terms of this Agreement.
“Software” means the computer programing code that was downloaded or otherwise
distributed to Licensee and which is the subject of this Agreement. Software
may be in Object Code or Source Code form or may be embedded as Firmware in a
Silicon Labs Device. Software includes Embedded Stacks, SDKs and Development
Tools. Your rights are different depending on whether the Software is
delivered to you in Object Code, Source Code or Firmware. Software that is
Micrium Software is subject to specific terms and conditions defined in
Section 2.
“Source Code” means the computer programming code in an uncompiled form
readable by humans which cannot be executed by a processor unless it is
compiled into binary form.
“Third Party Software” means any software that Silicon Labs has licensed from
a third party.
“Warranty Period” means the period of time ending thirty (30) days after the
first delivery of the Software to the Licensee, whether such delivery is in
the form of a download or actual physical delivery.
“Unauthorized Use” means use or inclusion of the Licensed Materials in (a)
life support, aeronautical, aerospace, medical, military or nuclear
applications; (b) FDA Class III or other devices for which FDA premarket
approval is required; (c) implantable devices; (d) life support or life
endangering applications where failure or inaccuracy might cause death or
personal injury; and (e) automotive or transportation applications or
environments unless the specific Silicon Labs Device has been designated by
Silicon Labs as compliant with ISO/TS 16949 requirements.   2. Micrium
Software.
The terms and conditions in this Section 2 apply only to Micrium Software and
take precedence over any other conflicting terms of this Agreement.
2.1. Grant of Micrium Software License. Upon accepting this Agreement and
downloading the Micrium Software, subject to your compliance with the terms of
this Agreement, Silicon Labs hereby grants you a limited, non-exclusive,
nontransferable license for the Term (as described in Section 23), as follows:
2.1.1. You and your Authorized Subcontractors may modify the Source Code
version of Micrium Software for the sole purpose of adapting the Micrium
Software to your application.
2.1.2. You may embed the Micrium Software exclusively in products developed by
you or by your Authorized Subcontractors on your behalf during the Term that
embed the Micrium Software into Silicon Labs Devices (the “End Products”).
2.1.3. You may distribute copies of the Object Code version of the Micrium
Software solely to the extent that such copies are embedded in End Products.
2.2. Micrium Software License Restrictions. Your use of the Micrium Software
is subject to the following restrictions:
2.2.1. You may allow Authorized Subcontractors to access and use the Micrium
Software solely to the extent necessary to adapt the Micrium Software to your
application.
2.2.2. Except as provided in this Agreement, neither you, your Authorized
Subcontractors, nor any of your downstream customers may sell, transfer,
sublicense, distribute, or disseminate in any way the Object Code or
executable code of the Micrium Software in any written or electronic manner.
2.2.3. Neither you, your Authorized Subcontractors, nor any of your downstream
customers may distribute the Source Code version of Micrium Software to any
third party under any circumstances. You shall ensure that each of your
employees and Authorized Subcontractors that work with Micrium Software are
aware of this restriction.
2.2.4. Except as permitted in this Agreement, neither you, your Authorized
Subcontractors, nor any of your downstream customer may embed the Micrium
Software in any integrated circuit device that is not a Silicon Labs Device.
2.3. End User Support. You agree to be fully responsible for all End User
support services and warranty costs for all End Products.
2.4. Commercial Purpose. You are permitted to use the Micrium Software for a
Commercial Purpose only if you embed the Micrium Software into a Silicon Labs
Device. You may not embed the Micrium Software in a non-Silicon Labs Device
unless you and Silicon Labs execute a separate Commercial License Agreement
expressly permitting such use.
2.5. Ownership. Silicon Labs is and shall remain the sole and exclusive owner
of the Micrium Software and all Documentation, media, manuals, specifications,
instructions and printed materials, and any copies or portions thereof,
furnished by Silicon Labs for use with the Micrium Software. You own any
improvements or modifications to the Micrium Software made by you or your
Authorized Subcontractor on your behalf to adapt Micrium Software for use in
your End Products.
2.6. Maintenence and Support. Standard maintenance and technical support, such
as bug fixes, correction of failures, updates and maintenance patches is
provided to you at no cost for one year from date that you download the
Micrium Software. Silicon Labs may use a variety of methods, including but not
limited to telephone, Internet and/or e-mail, to provide such maintenance and
support.   3. 8051 SDK.
The terms and condition in this Section 3 apply only to the 8051 SDK and take
precedence over any other conflicting terms of this Agreement.
3.1. 8051 SDK. The 8051 SDK consists of the following items:
3.1.1. Drivers;
3.1.2. Peripheral libraries (excluding CSLIB); and
3.1.3. Example application code.
3.2. Installation and Use Rights.
3.2.1. You may download and install the 8051 SDK on one or more computers and
make any number of copies.
3.2.2. You may internally evaluate the 8051 SDK. If you elect to use the 8051
SDK for any other purpose, including modification and distribution, then the
following additional terms apply to you.
3.2.3. You may modify any files for your own use.
3.2.4. You may redistribute to your customers applications that you develop
using the 8051 SDK. Your redistribution may be in any form, including
executable binary code, source code, physical media and Internet downloads.
3.3. Restrictions.
3.3.1. You may not use the 8051 SDK with any integrated circuit products other
than those designed and manufactured by Silicon Labs.
3.3.2. Except as provided above, you may not redistribute, sublicense, assign,
rent or lease any portion of the 8051 SDK to any third party.
3.3.3. You may not modify or distribute the 8051 SDK so that all or any part
of it becomes Open Source Software.
3.3.4. You may not obscure or remove any product identification, copyright or
other notices that appear on or in the 8051 SDK, including any notices from
third parties.
3.3.5. You may not redistribute any modified or unmodified version of the 8051
SDK to any third party as a standalone product.
3.4. Ownership. Silicon Labs is and shall remain the owner of the 8051 SDK at
all times. Applications that you develop using the 8051 SDK shall belong to
you.
4. License Grant.
Silicon Labs hereby grants Licensee a limited, non-transferable,
non-exclusive, perpetual license to use the Licensed Materials solely under
the following terms and condition:
4.1. Object Code. With respect to Software (other than Micrium Software) that
is delivered to Licensee by Silicon Labs in Object Code format, Licensee may:
4.1.1. (a) if the Software is an Embedded Stack, you may install one copy of
the Software and its components all together on a single computer, and if the
Software is copied onto another computer, the original copy must be deleted or
otherwise made irreversibly inoperable; (b) if the Software is an SDK or a
Development Tool, you may make multiple copies of the Software for your own
internal use;
4.1.2. store one copy of the Software for archival (non-operational) purposes
only, so long as access to such copy is restricted;
4.1.3. use the Licensed Materials to develop applications to be used to
program Silicon Labs Devices;
4.1.4. incorporate the Licensed Materials into Authorized Applications;
4.1.5. facilitate the integration of the Licensed Materials and Silicon Labs
Devices into Authorized Applications; and
4.1.6. distribute copies of the Licensed Materials to Licensees end-user
customers, to the extent such copies are in Object Code form only and are
incorporated into Authorized Applications.
4.2. Source Code. With respect to Software (other than Micrium Software and
Silicon Labs Open Source Software) that is delivered to Licensee by Silicon
Labs in Source Code format, Licensee may:
4.2.1. use the sample application software in Source Code format to develop
and compile applications for use in Authorized Applications;
4.2.2. copy, prepare Derivative Works of, compile and modify Source Code of
the Silicon Labs Software, solely to enable Licensee to design, develop,
modify, test, support and/or debug Derivative Works and/or Licensed Programs
that are intended to operate in Authorized Applications;
4.2.3. reproduce and distribute Derivative Works to Authorized Subcontractors
under agreements consistent with Licensees rights and obligations under this
Agreement solely (a) to modify for Licensees use in developing and
maintaining the Licensed Programs; and (b) to enable Licensee to distribute
Licensed Programs externally to End Users in accordance with Section 4.2.5
below;
4.2.4. reproduce and distribute Licensed Programs internally and to Licensees
External Manufacturers under agreements consistent with Licensees rights and
obligations under this Agreement, solely (a) for Licensees use in developing
and maintaining the Licensed Programs; and (b) to enable Licensee to
distribute Licensed Programs externally to End Users in accordance with
Section 4.2.5 below; and
4.2.5. distribute Licensed Programs externally to Licensees End Users, either
directly or through Licensees distribution channels and methods, but only for
use with Authorized Applications and not on a standalone basis.
5. License Restrictions.
The Licensed Materials shall only be used as permitted by this Agreement. Any
use of the Licensed Materials not specifically authorized by this Agreement is
prohibited.
5.1. Without limiting the foregoing restriction, and except as authorized by
this Agreement, Licensee shall not:
5.1.1. assign, sublicense, or otherwise transfer the Licensed Materials to any
third party;
5.1.2. reverse compile, disassemble, alter, add to, delete from, or otherwise
modify Software delivered to Licensee in Object Code form or in libraries in
the Licensed Materials;
5.1.3. publish the Licensed Materials in any manner that would cause it to
become part of the public domain or otherwise become subject to the terms of
an Open Source Software license;
5.1.4. use the Licensed Materials except in conjunction with Silicon Labs
Devices;
5.1.5. distribute the Source Code form of Software to any third party, in
whole or in part; or
5.1.6. remove any copyright, trademark, patent or other proprietary notices
from the Licensed Materials or any portion thereof.
5.2. Licensee shall not use the Licensed Materials in any way to further the
development or improvement of any product that does or would compete with any
Silicon Labs Device.
5.3. If the Software is provided to demonstrate the capability of Silicon Labs
Devices, it shall be used only for this purpose. Incorporation of the
demonstration version of Silicon Labs Software into Applications is solely at
Licensees risk and liability.
5.4. Any subsequent distribution or transfer of the Licensed Programs to End
Users shall remain subject to the terms and conditions of this Agreement.
Whether by execution of an end-user license agreement or other commercially
reasonable means, Licensee shall ensure that its End Users use of the
Licensed Programs shall only be permitted if they are incorporated into
Authorized Applications. Licensee shall prohibit any further sublicensing,
distribution, sale, marketing, reproduction, modification, reverse engineering
or decompiling of the Licensed Programs.
5.5. Licensor may include features in the Software to restrict use of the
Software that does not comply with the terms of this Agreement.
6. Unauthorized Use.
The Licensed Materials are not licensed, designed, intended, authorized, or
warranted for Unauthorized Use. Licensee shall be solely and exclusively
responsible for any Unauthorized Uses by Licensee, Licensees Authorized
Subcontractors, Licensees End Users or other sublicensees, and any
Unauthorized Use by such Authorized Subcontractors, End Users or sublicensees,
with or without the knowledge of Licensee, shall be attributed to Licensee.
Licensee agrees to defend and indemnify Silicon Labs for all third-party
claims and for all damages, costs and fees, including Silicon Labs attorneys
fees, arising from any such Unauthorized Use of the Licensed Materials.
7. Open Source Software.
7.1. If the Software includes any Open Source Software, such Software and the
relevant Open Source Software license under which such Software is licensed
are disclosed at www.silabs.com. All use of such Open Source Software by
Licensee is subject to the terms of the relevant open source software license
and Licensees use of such Software is expressly conditioned upon Licensees
compliance with the term of such license.
7.2. If the Software is Silicon Labs Open Source Code, then the following
provisions apply:
7.2.1. Silicon Labs hereby grants to Licensee a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable copyright license to
reproduce, prepare Derivative Works of, publicly display, publicly perform,
sublicense, and distribute Silicon Labs Open Source Code and such Derivative
Works in Source Code or Object Code form.
7.2.2. Silicon Labs hereby grants to Licensee a perpetual, worldwide,
non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this
section) patent license to make, have made, use, offer to sell, sell, import,
and otherwise transfer the Silicon Labs Open Source Code, where such license
applies only to those patent claims licensable by Silicon Labs that are
necessarily infringed by Licensees use of the Silicon Labs Open Source Code
or by combination with any other device or software.
7.2.3. Licensee may add Licensees own copyright statement to Licensees
modifications of Silicon Labs Open Source Software and may provide additional
or different license terms and conditions for use, reproduction, or
distribution of such modifications, or for any such Derivative Works as a
whole, provided Licensees use, reproduction, and distribution of the Silicon
Labs Open Source Software otherwise complies with the conditions stated in
this License.
7.2.4. Licensee may reproduce and distribute copies of the Silicon Labs Open
Source Code or Derivative Works thereof in any medium, with or without
modifications, and in Source Code or Object Code form, provided that Licensee
meets the following conditions: (a) Licensee must give any other recipients of
the Silicon Labs Open Source Code or Derivative Works a copy of this License;
and (b) Licensee must cause any modified files to carry prominent notices
stating that Licensee changed the files; and (c) Licensee must retain, in the
Source Code form of any Derivative Works that Licensee distributes, all
copyright, patent, trademark, and attribution notices from the Source Code
form of the Silicon Labs Open Source Code, excluding those notices that do not
pertain to any part of the Derivative Works; and (d) If the Silicon Labs Open
Source Code includes a "NOTICE" text file as part of its distribution, then
any Derivative Works that Licensee distributes must include a readable copy of
the attribution notices contained within such NOTICE file, excluding those
notices that do not pertain to any part of the Derivative Works, in at least
one of the following places: within a NOTICE text file distributed as part of
the Derivative Works; within the Source Code form or documentation, if
provided along with the Derivative Works; or, within a display generated by
the Derivative Works, if and wherever such third-party notices normally
appear. The contents of the NOTICE file are for informational purposes only
and do not modify the License. Licensee may add Licensees own attribution
notices within Derivative Works that Licensee distributes, alongside or as an
addendum to the NOTICE text from the Silicon Labs Open Source Code, provided
that such additional attribution notices cannot be construed as modifying the
License.
7.3. With respect to Software that is not Open Source Software, Licensee shall
not:
7.3.1. cause the Software to become subject to any Open Source Software
license, including but limited to the general public license (GPL) or the
lesser general public license (LGPL);
7.3.2. cause the Software to be disclosed into the public domain or to any
third party except for those third parties to whom License is authorized to
distribute Licensed Programs under Sections 4.1.6 or 4.2.5; or 
7.3.3. cause any part of the Software to become a derivative of any Open
Source Software.
7.4. Licensee shall not enable or permit any of its End Users to breach the
provisions of this Section 7, and shall include similar restrictive provisions
in its end user license agreement with such End Users. If Licensee breaches
this Section 7, Licensee shall indemnify and hold Silicon Labs harmless from
all costs, claims, settlements and judgments incurred by Silicon Labs,
including attorneys fees, in the process of defending, challenging and/or
settling any demand, claim or order that the Software is subject to an Open
Source Software license or must be disclosed into the public domain or to any
third party.
8. Modified Open Source Software.
Notwithstanding the terms of the Open Source Software license under which the
Open Source Software is licensed, the following terms apply to modifications
to such Open Source Software that constitute Modified Open Source Software, as
defined in this Agreement. The following terms apply regardless of how the
Modified Open Source Software was delivered to you.
8.1.1. You may not use Modified Open Source Software except for use with
Licensed Programs that are intended to operate in Authorized Applications.
8.1.2. You may not obscure, modify or remove copyright notices, files or
statements concerning ownership by Silicon Labs or reference to the terms of
this Agreement.
8.1.3. Subject to Sections 8.1.1 and 8.1.2:
8.1.3.1. You may copy and compile the Source Code of the Modified Open Source
Software.
8.1.3.2. You may reproduce the Object Code and Source Code versions of
Modified Open Source Software and distribute the same through multiple levels
of distributions, including to your External Manufacturers.
8.1.3.3. You may modify Modified Open Source Software and create Derivative
Works of Modified Open Source Software.
9. Third Party Software.
9.1. If the Software contains any Third Party Software, all use of such Third
Party Software shall be subject to the terms of the license from such third
party to Silicon Labs or a separate end user license agreement, if available,
which may be set forth in the header files of the Third Party Software. You
agree to comply with all terms and conditions for use of Third Party Software.
9.2. Silicon Labs has licensed the BLE Homekit from Apple. You may not
download or use the BLE Homekit software unless you have executed a MFi
License with Apple.
9.3. Silicon Labs has licensed emWin software, including libraries and
executables and related documentation (collectively “emWin Library”) from
Segger Microcontroller GmbH. You are entitled to use the emWin Library free
of charge, subject to the following conditions, which you accept by virtue of
accepting the terms of this Agreement: (a) you may use the emWin library
exclusively with EFM 32-bit microcontrollers and EFR radios; (b) you may not
use the emWin Library to create or develop software that is similar to or
competitive with the emWin Library; and (c) you may not modify the
documentation that accompanies the emWin Library.
9.4. Silicon Labs does not make any endorsements or representations concerning
Third Party Software and disclaims all implied warranties concerning Third
Party Software. Third Party Software is offered “AS IS.”
10. Inspection Rights.
Silicon Labs shall have the right, upon reasonable advance notice, to inspect
Licensee's records and facilities with respect to the manufacture of
Applications and to receive sample units of Applications in order to verify
that such manufacturing is within the scope of this Agreement, that there are
appropriate security procedures to protect Silicon Labs Confidential
Information, and that Licensee is in compliance with its other obligations
under this Agreement.
11. No Other Licenses.
The licenses granted under this Agreement are specifically set forth herein,
and no licenses are granted by Silicon Labs to Licensee by implication or
estoppel, and no licenses shall be granted by the parties course of doing
business.
12. Beta Software.
Beta Software, whether Object Code or Source Code (a) can only be used for
internal development, demonstration or testing purposes; (b) cannot be
included within Licensees or End-Users products that are intended for
general release or high-volume production; and (c) cannot be used to support
Z-Wave certification of Silicon Labs Devices. Silicon Labs does not offer any
warranties on Beta Software and disclaims all implied warranties including,
but not limited to merchantability, fitness for use and noninfringement. Beta
Software is offered “AS IS.” Under no circumstances will Silicon Labs incur
any liability or obligation to you related to your use of Beta Software. Any
use of Beta Software by you in violation of the terms of this Agreement shall
automatically terminate your right to use Beta Software for any purpose
whatsoever.
13. Upgrades, Updates, New Versions.
Although it has no obligation to do so, Silicon Labs may introduce updates,
upgrades or new versions of the Software from time to time. Licensee is under
no obligation to download or use the updates, upgrade or new version of
Software; however, if Licensee elects to do so, the licenses granted to
Licensee pursuant to this Agreement shall be deemed to include such updates,
upgrades and new versions. In the case of any bug fix, improvement,
work-around, or correction made to the Software by Licensee, Licensee agrees
to provide to Silicon Labs, at no cost, the source code and any documentation
reasonably required for Silicon Labs to be able to incorporate such changes
into the Silicon Labs Software.
14. Regulatory Compliance.
Silicon Labs does not warrant that Software or any Application will comply
with the regulatory requirements of the United States or any other country.
Licensee is solely responsible for complying with such requirements and for
obtaining necessary government certifications, if any.
15. License Fee and Royalties.
Unless Licensee has executed a Commercial License with Silicon Labs, Licensee
is not obligated to pay any license fees or royalties to Silicon Labs so long
as Licensee complies with the terms of the licenses set forth herein. If
Licensee has executed a Commercial License, Licensee agree to pay all license
fees, maintenance fees and subscription fees described in such Commercial
License.
16. No Resale Fees.
Licensee may not directly or indirectly charge any fee or otherwise require or
accept any type of monetary compensation solely for redistributing the
Licensed Materials which is in excess of any amount paid to Silicon Labs for
the same Licensed Materials. This does not apply to the sale of hardware
products having the Licensed Materials in object code form embedded within.
17. Proprietary Rights.
All rights and title in and to the Licensed Materials, including without
limitation, patents, copyrights, moral rights, trademarks and trade secret
rights, belong to Silicon Labs or its licensors. Except for the rights
expressly granted herein, no other rights are granted to Licensee with respect
to the Licensed Materials.
18. Confidential Information.
You agree that the Licensed Materials contain confidential information,
including trade secrets, know-how and other information, that comprise the
exclusive property of Silicon Labs or its licensors. During the period this
Agreement is in effect and at all times after its termination, you shall
maintain the confidentiality of this information and shall not sell, license,
sublicense, publish, display, distribute, disclose or otherwise make available
this information to any third party nor use such information except as
authorized by this Agreement.
19. Limited Warranty and Remedies.
Silicon Labs warrants that, during the Warranty Period, the Software will
function substantially in accordance with the Documentation when used with
Silicon Labs Devices and that the media on which the Software is furnished
will be free from defects in material and workmanship, under normal use and
service, when correctly installed and maintained. Silicon Labs does not
warrant that the functions in the Licensed Materials will meet Licensees
specific requirements or that the operation of the Software will be
uninterrupted or error free. Silicon Labs does not warrant that the Software
does not contain any viruses or bugs. If Licensee notifies Silicon Labs,
during the Warranty Period, of a failure of the Software to conform to the
limited warranty stated in this section, Silicon Labs sole obligation, and
Licensees sole remedy, will be, at Silicon Labs sole discretion: (i)
replacement of the Software, or part thereof, with a functionally equivalent
software product or part, or (ii) repair of the Software. Without limiting any
term or condition stated in this Agreement, this warranty does not apply to
any nonconformance caused by (A) improper or inadequate maintenance or
calibration, or (B) software or interfacing equipment, parts or supplies not
supplied by Silicon Labs or its authorized distributor, (C) modifications to
the Software or (D) Unauthorized Use of the Software.
20. WARRANTY DISCLAIMER.
EXCEPT AS PROVIDED ABOVE IN SECTION 19, THE LICENSED MATERIALS ARE PROVIDED
“AS IS” WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING, WITHOUT
LIMITATION, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE, OR NON-INFRINGEMENT AND THE ENTIRE RISK AS TO THE QUALITY
AND PERFORMANCE OF THE LICENSED MATERIALS IS WITH LICENSEE. SILICON LABS DOES
NOT WARRANT THAT THE LICENSED MATERIALS ARE FREE FROM DEFECTS THAT COULD CAUSE
VULNERABILITY TO CYBER-ATTACK, DATA BREACH OR PRIVACY VIOLATIONS. SILICON LABS
DISCLAIMS ALL LIABILITY RELATED TO LICENSEES DATA THAT MAY BE RECEIVED,
STORED OR USED BY SILICON LABS DEVICES OR SOFTWARE OR INTERCEPTED BY THIRD
PARTIES. SILICON LABS DISCLAIMS ALL LIABILITY FOR DAMAGES CAUSED BY THIRD
PARTIES, INCLUDING MACILICOUS USE OF, OR INTEFERENCE WITH TRANSMISSION OF,
LICENSEES DATA.
21. LIMITATION OF LIABILITY.
SILICON LABS SOLE OBLIGATION OR LIABILITY UNDER THIS AGREEMENT IS THE REPAIR
OR REPLACEMENT OF THE LICENSED MATERIALS ACCORDING TO THE LIMITED WARRANTY
ABOVE. IN NO EVENT SHALL SILICON LABS OR ANY OF ITS AFFILIATES OR SUPPLIERS BE
LIABLE FOR CONSEQUENTIAL, SPECIAL, INCIDENTAL OR SIMILAR DAMAGES, SUCH AS (BUT
NOT LIMITED TO) LOSS OF BUSINESS REVENUES, PROFITS OR SAVINGS OR LOSS OF DATA
RESULTING FROM THE USE OR INABILITY TO USE THE LICENSED MATERIALS, EVEN IF
SILICON LABS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY
CLAIM BY ANY THIRD PARTY. THIS INCLUDES, BUT IS NOT LIMITED TO, DAMAGES
ARISING FROM THE FAILURE OF THE SILICON LABS DEVICE TO TRANSMIT DATA ARISING
FROM A FAILURE OF THE SOFTWARE TO PERFORM IN SUBSTANTIAL ACCORDANCE WITH THE
DOCUMENTATION. IN NO EVENT SHALL THE TOTAL CUMULATIVE LIABILITY OF SILICON
LABS TO LICENSEE FOR ALL MATTERS RELATED TO THE LICENSED MATERIALS EXCEED THE
AMOUNT PAID BY LICENSEE TO SILICON LABS FOR SUCH LICENSED MATERIALS OR ONE
UNITED STATES DOLLAR ($1.00 USD). YOU ACKNOWLEDGE THAT THE AMOUNT PAID BY YOU
FOR THE LICENSED MATERIALS REFLECTS THIS ALLOCATION OF RISK.
22. Data Collection.
To the extent that Silicon Labs Devices collect, store or transfer Personal
Information, Silicon Labs may use such Personal Information for its own
internal purposes, including marketing Silicon Labs Devices to the user.
Silicon Labs will not sell Personal Information to third parties. Silicon Labs
Devices will not transfer Personal Information to other devices in a network
or to third parties except to the extent necessary to perform the intended
function of the Silicon Labs Device. Silicon Labs will not be liable to
Licensee or Licensees customers for (a) any intended transfer of Personal
Information described in the Documentation for the Silicon Labs Device; (b)
any unintended transfer of Personal Information or loss of data caused by any
third parties or third party devices or software, including hacking, malware,
eavesdropping, man-in-the-middle attacks or other intentional acts; or (c)
unauthorized access to or misuse of Personal Information by third parties.
23. Term and Termination.
This Agreement will take effect on the date the Licensed Materials are
acquired by or delivered to Licensee, and will remain in effect unless
terminated as provided below. If you breach any of your obligations under this
Agreement, this Agreement will immediately and automatically terminate. You
may terminate this Agreement at any time by destroying all copies of the
Licensed Materials. Upon termination of this Agreement, you shall immediately
discontinue the use of the Licensed Materials and shall return or provide
certification to Silicon Labs of the destruction of all copies of the Licensed
Materials. You many keep one copy of the Licensed Materials for archival
(non-operational) purposes only, so long as access to such copies is
restricted. If the Agreement is terminated by Silicon Labs, you may continue
to distribute copies of the Software already installed in finished inventory,
but you may not make any additional copies or install the Software in
additional products. All provisions of this Agreement relating to disclaimers
of warranties, limitation of liability, remedies or damages, and Silicon Labs
proprietary rights, shall survive any termination of this Agreement for any
reason.
24. Termination of License.
If you institute patent litigation against Silicon Labs or any of its
Affiliates (including a cross-claim or counterclaim in a lawsuit) alleging
that the Licensed Programs directly or indirectly infringe a patent of
Licensee, then any patent licenses granted to you under this Agreement for
that Licensed Program shall terminate as of the date such litigation is filed.
25. Export Restrictions.
You may not export or re-export the Software or any Licensed Programs, or any
copy thereof, in violation of any applicable laws or regulations.
26. Amendments.
This Agreement may be amended unilaterally by Silicon Labs at any time. The
most recent version of this Agreement supersedes and replaces all prior
versions. In the event of any conflicting terms, the terms of the most recent
version of this Agreement shall control.
27. Miscellaneous.
This Agreement sets forth the entire agreement and understanding between the
parties and neither party shall be bound by any conditions, definitions,
warranties, understandings or representations with respect to the subject
matter hereof other than as provided herein or as duly set forth on or after
the date hereof in writing and signed by a proper and duly authorized
representative of the party to be bound thereby. The failure of any party at
any time to require performance of any provision of this Agreement shall in
not affect the right of such party to enforce the terms of this Agreement at a
later time. No waiver by any party of any condition or of any breach of any
term contained in this Agreement, in any one or more instances, shall be
construed as a further or continuing waiver of any such condition or of any
breach of any such term or any other term set forth in this Agreement. If any
provision of this Agreement is unenforceable for any reason, the remaining
terms of the Agreement shall not be deemed invalid, inoperative, or
unenforceable and, if possible, the unenforceable provision shall be modified
or interpreted in a manner to make it enforceable.
28. Governing Law.
This Agreement shall be governed by the laws of the State of Texas, United
States of America, without regard to that states conflicts of laws rules. The
1980 United Nations Convention on Contracts for the International Sale of
Goods shall not apply. In any dispute arising out of this Agreement, the
parties each consent to the exclusive personal jurisdiction and venue in the
State and Federal courts located within Travis County, Texas, United States of
America. All disputes concerning this Agreement shall be resolved by binding
arbitration in Travis County, Texas before a single arbitrator. The
arbitration shall be administered by JAMS pursuant to JAMS Streamlined
Arbitration Rules and Procedures. The arbitration award shall include an award
of attorneys fees to the prevailing party. Judgment on the award may be
entered in any court having jurisdiction. This clause shall not preclude
parties from seeking provisional remedies in aid of arbitration from a court
of appropriate jurisdiction.
29. Injunctive Relief.
The copying, disclosure, or use of the Software in a manner inconsistent with
any provision of this Agreement or the improper use of the Silicon Labs
trademarks may cause irreparable injury to Silicon Labs for which Silicon Labs
may not have an adequate remedy at law. Silicon Labs may be entitled to
equitable relief in court, including but not limited to temporary restraining
orders, preliminary injunctions and permanent injunctions.
30. Silicon Labs Trademarks.
Silicon Labs and the Silicon Labs logo are trademarks of Silicon Laboratories
Inc. in the United States and other countries. No use of the Silicon Labs
trademarks by Licensee is implied or consented to by Silicon Labs by entering
into this Agreement.
31. Commercial Computer Software.
If Licensee is an agency of the U.S. Government, the following will apply: The
Software has been developed entirely at private expense, is regularly used for
nongovernmental purposes and has been licensed to the public. The Software is
a “commercial item” as that term is defined in 48 C.F.R. 2.101 (Oct. 1995),
consisting of “commercial computer software” and “commercial computer software
documentation” as those terms are used in 48 C.F.R. 12.212 (Sept. 1995) or as
“commercial computer software” as that term is defined in 48 C.F.R.
252.227-7014 (June 1995) or any equivalent agency regulation or contract
clause, whichever is applicable. Consistent with 48 C.F.R. 12.212 and 48
C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government agencies
acquire only those rights to the Software as are expressly set forth herein.

View File

@ -0,0 +1,21 @@
Copyright 2022 Silicon Laboratories Inc. www.silabs.com
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.

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2022 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/bluetooth/hci_driver.h>
#include <sl_hci_common_transport.h>
enum h4_packet {
h4_command = 1,
h4_acl = 2,
h4_sco = 3,
h4_event = 4
};
/**
* @brief BTLE_LL_Process process linklayer events
* @param events
*/
void BTLE_LL_Process(uint32_t events);
/**
* @brief BTLE_LL_EventRaise raise events to be notified as soon as possible to linklayer
* function is implemented by upper layer
* @param events bitmap of events to raise
*/
void BTLE_LL_EventRaise(uint32_t events);
/**
* @brief Check if event bitmap indicates pending events
* @return bool pending events
*/
bool sli_pending_btctrl_events(void);
/**
* @brief Thread entry point that calls Link Layer to process raised events
*/
void slz_ll_thread_func(void);

View File

@ -1,2 +1,27 @@
build:
cmake: .
blobs:
- path: gecko/protocol/bluetooth/bgstack/ll/lib/libbluetooth_controller_efr32bg22_gcc_release.a
sha256: 99b3f9abc04c20da4ad8383993275691586aa872ea72a526a544984bb99dc27e
type: lib
version: '4.0.2'
license-path: zephyr/blobs/license/MSLA.txt
url: https://github.com/SiliconLabs/gecko_sdk/raw/gsdk_4.0/protocol/bluetooth/bgstack/ll/lib/libbluetooth_controller_efr32xg22_gcc_release.a
description: "Binary libraries supporting EFR32 RF subsystems"
doc-url: https://github.com/SiliconLabs/gecko_sdk
- path: gecko/protocol/bluetooth/bgcommon/lib/libbgcommon_efr32bg22_gcc_release.a
sha256: 324b6a724449f83c095db76df11b8ae393b6bd090b1d94c78f2db0af3333426a
type: lib
version: '4.0.2'
license-path: zephyr/blobs/license/MSLA.txt
url: https://github.com/SiliconLabs/gecko_sdk/raw/gsdk_4.0/protocol/bluetooth/bgcommon/lib/libbgcommon_efr32xg22_gcc_release.a
description: "Binary libraries supporting EFR32 RF subsystems"
doc-url: https://github.com/SiliconLabs/gecko_sdk
- path: gecko/platform/radio/rail_lib/autogen/librail_release/librail_efr32bg22_gcc_release.a
sha256: 8e31545401df4b4dbb2ae0a5814547407a24f431e2e72bb4699a158b83396f23
type: lib
version: '4.0.2'
license-path: zephyr/blobs/license/Zlib.txt
url: https://github.com/SiliconLabs/gecko_sdk/raw/gsdk_4.0/platform/radio/rail_lib//autogen/librail_release/librail_efr32xg22_gcc_release.a
description: "Binary libraries supporting EFR32 RF subsystems"
doc-url: https://github.com/SiliconLabs/gecko_sdk

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2022 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sl_bt_ll_zephyr.h>
K_SEM_DEFINE(slz_ll_sem, 0, 1);
static atomic_t sli_btctrl_events;
bool sli_pending_btctrl_events(void)
{
return false;
}
void BTLE_LL_EventRaise(uint32_t events)
{
atomic_or(&sli_btctrl_events, events);
k_sem_give(&slz_ll_sem);
}
void slz_ll_thread_func(void)
{
while (true) {
k_sem_take(&slz_ll_sem, K_FOREVER);
uint32_t events = atomic_clear(&sli_btctrl_events);
BTLE_LL_Process(events);
}
}
void sl_bt_controller_init()
{
/* No extra initialization procedure required */
}