diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 834e10486..7840d25f4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -144,6 +144,18 @@ set(PLATFORM-BITBOX02-SOURCES ${PLATFORM-BITBOX02-SOURCES} PARENT_SCOPE) set(SECURECHIP-SOURCES ${CMAKE_SOURCE_DIR}/src/atecc/atecc.c ${CMAKE_SOURCE_DIR}/src/securechip/securechip.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_crypt_mbedtls.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_gpio.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_i2c.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_ifx_i2c_config.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_logger.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_os_datastore.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_os_event.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_os_lock.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_os_timer.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/pal_os_memory.c + ${CMAKE_SOURCE_DIR}/src/optiga-pal/optiga.c ) set(SECURECHIP-SOURCES ${SECURECHIP-SOURCES} PARENT_SCOPE) diff --git a/src/memory/memory_shared.c b/src/memory/memory_shared.c index 9488183e5..71e3874c1 100644 --- a/src/memory/memory_shared.c +++ b/src/memory/memory_shared.c @@ -54,5 +54,14 @@ uint8_t memory_get_screen_type(void) uint8_t memory_get_securechip_type(void) { - return MEMORY_SECURECHIP_TYPE_ATECC; + chunk_shared_t chunk = {0}; + memory_read_shared_bootdata(&chunk); + uint8_t securechip_type = chunk.fields.securechip_type; + util_zero(&chunk, sizeof(chunk)); + switch (securechip_type) { + case MEMORY_SECURECHIP_TYPE_OPTIGA: + return securechip_type; + default: + return MEMORY_SECURECHIP_TYPE_ATECC; + } } diff --git a/src/memory/memory_shared.h b/src/memory/memory_shared.h index 5e8f8f985..c1a91e6bb 100644 --- a/src/memory/memory_shared.h +++ b/src/memory/memory_shared.h @@ -75,8 +75,8 @@ typedef union { uint8_t auto_enter; uint8_t upside_down; uint8_t screen_type; + uint8_t securechip_type; // Following are used by firmware only - uint8_t reserved[1]; uint8_t io_protection_key_split[32]; uint8_t authorization_key_split[32]; uint8_t encryption_key_split[32]; diff --git a/src/optiga-pal/README.bitbox02.md b/src/optiga-pal/README.bitbox02.md new file mode 100644 index 000000000..5e3998693 --- /dev/null +++ b/src/optiga-pal/README.bitbox02.md @@ -0,0 +1 @@ +copied from external/optiga-trust-m/pal/NEW_PAL_TEMPLATE diff --git a/src/optiga-pal/README.md b/src/optiga-pal/README.md new file mode 100644 index 000000000..f86613d2a --- /dev/null +++ b/src/optiga-pal/README.md @@ -0,0 +1,275 @@ +# Porting Guide + +The implementation of Platform Abstraction Layer (PAL) needs to be updated in order to migrate to a new +target platform. + +The PAL reference code for the XMC4800 IoT connectivity kit is provided as part of package which can be used. +The implementation can be found in “/pal/xmc4800” and the header files are available in +“/optiga/include” with the required APIs used by upper layers. The header files are platform +agnostic and would not require any changes. The low level drivers used by PAL for XMC4800 are configured and +generated using DAVE™. + +## Communication with OPTIGA™ Trust M + +The hardware/platform resource configuration with respect to I2C master and GPIOs (Vdd and Reset) are to be +updated in pal_ifx_i2c_config.c. These configurations are used by the IFX I2C implementation to communicate +with OPTIGA™ Trust M. + +### Update I2C master platform specific context[e.g. (void)&i2c_master_0] + +```c +/* +* \brief PAL I2C configuration for OPTIGA +*/ +pal_i2c_t optiga_pal_i2c_context_0 = +{ + /// Pointer to I2C master platform specific context + (void)&i2c_master_0, + /// Slave address + 0x30, + /// Upper layer context + NULL, + /// Callback event handler + NULL +}; +``` + +### Update platform specific context for GPIOs (Vdd and Reset) [e.g. (void)&pin_3_4] +```c +/* +* \brief Vdd pin configuration for OPTIGA +*/ +pal_gpio_t optiga_vdd_0 = +{ + // Platform specific GPIO context for the pin used to toggle Vdd + (void*)&vdd_pin +}; + +/** +* \brief Reset pin configuration for OPTIGA +*/ + pal_gpio_t optiga_reset_0 = +{ + // Platform specific GPIO context for the pin used to toggle Reset + (void*)&reset_pin +}; +``` + +### Update PAL I2C APIs [pal_i2c.c] to communicate with OPTIGA™ Trust M + +The `pal_i2c` is expected to provide the APIs for I2C driver initialization, de-initialization, read, write and set +bitrate kind of operations + +1. `pal_i2c_init` +2. `pal_i2c_deinit` +3. `pal_i2c_read` +4. `pal_i2c_write` +5. `pal_i2c_set_bitrate` + +A few target platforms, the I2C master driver initialization (`pal_i2c_init`) is done during the platform start up. In +such an environment, there is no need to implement pal_i2c_init and `pal_i2c_deinit` functions. Otherwise, +these (`pal_i2c_init` & `pal_i2c_deinit`) functions must be implemented as per the upper layer expectations based +on the need. The details of these expectations are available in the [Host library API documentation (chm)](https://github.com/Infineon/optiga-trust-m/blob/master/documents/OPTIGA_Trust_M_V1_Host_Library_Documentation.chm). + +The reference implementation of PAL I2C based on XMC4800 IoT connectivity kit does not need to have the +platform I2C driver initialization explicitly done as part of pal_i2c_init as it is taken care by the DAVE™ library +initialization. Hence pal_i2c_init & pal_i2c_deinit are not implemented. + +In addition to the above specified APIs, the PAL I2C must handle the events from the low level I2C driver and +invoke the upper layer handlers registered with PAL I2C context for the respective transaction as shown in the +below example. + +```c +//I2C driver callback function when the transmit is completed successfully +void i2c_master_end_of_transmit_callback(void) +{ + invoke_upper_layer_callback(gp_pal_i2c_current_ctx, (uint8_t)PAL_I2C_EVENT_TX_SUCCESS); +} +``` + +In above example the I2C driver callback, when transmission is successful invokes the handler to inform the +result. + +### Update PAL GPIO [pal_gpio.c] to power on and reset the OPTIGA™ Trust M + +1. `pal_gpio_set_high` +2. `pal_gpio_set_low` + +### Update PAL Timer [pal_os_timer.c] to enable timer + +1. `pal_os_timer_get_time_in_milliseconds` +2. `pal_os_timer_delay_in_milliseconds` + +### Update Event management for the asynchronous interactions for IFX I2C [pal_os_event.c] + +1. `pal_os_event_register_callback_oneshot` +2. `pal_os_event_trigger_registered_callback` + +The `pal_os_event_register_callback_oneshot` function is expected to register the handler and context +provided as part of input parameters and triggers the timer for the requested time. The `p_pal_os_event` is an +event instance created using `pal_os_event_create`. + +```c +void pal_os_event_register_callback_oneshot(pal_os_event_t * p_pal_os_event, + register_callback callback, + void* callback_args, + uint32_t time_us) +{ + p_pal_os_event->callback_registered = callback; + p_pal_os_event->callback_ctx = callback_args; + //lint --e{534} suppress "Return value is not required to be checked" + TIMER_SetTimeInterval(&scheduler_timer, (time_us*100)); + TIMER_Start(&scheduler_timer); +} +``` + +The handler registered must be invoked once the timer has elapsed as shown in +`pal_os_event_trigger_registered_callback`. The `pal_os_event_trigger_registered_callback` is to be +registered with event timer interrupt to get trigerred when the timer expires. The `pal_os_event_0` is the +instance in the `pal_os_event` used store the registered callback and context. + +```c +void pal_os_event_trigger_registered_callback(void) +{ + register_callback callback; + + TIMER_ClearEvent(&scheduler_timer); + //lint --e{534} suppress "Return value is not required to be checked" + TIMER_Stop(&scheduler_timer); + TIMER_Clear(&scheduler_timer); + + if (pal_os_event_0.callback_registered) + { + Callback = pal_os_event_0.callback_registered; + callback ((void*)callback_ctx); + } +} +``` + +## Initalisation hints + +This is a code sample demonstrating initialization routine for the security chip, as well as a hibernation example +```c +#include "optiga/optiga_util.h" +#include "optiga/pal/pal_os_event.h" +#include "optiga/pal/pal.h" +#include "optiga/pal/pal_os_timer.h" +/** + * Callback when optiga_util_xxxx operation is completed asynchronously + */ +static volatile optiga_lib_status_t optiga_lib_status; +static void optiga_util_callback(void * context, optiga_lib_status_t return_status) +{ + optiga_lib_status = return_status; +} + +int32_t main(void) +{ + uint8_t return_value = 0; + + optiga_lib_status_t return_status; + + optiga_util_t * me_util; + + do + { + //Create an instance of optiga_util to open the application on OPTIGA. + me_util = optiga_util_create(0, optiga_util_callback, NULL); + + /** + * Open the application on OPTIGA which is a precondition to perform any other operations + * using optiga_util_open_application + */ + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_open_application(me_util, 0); + + if (OPTIGA_LIB_SUCCESS != return_status) + { + break; + } + while (optiga_lib_status == OPTIGA_LIB_BUSY) + { + //Wait until the optiga_util_open_application is completed + } + if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + { + //optiga util open application failed + break; + } + /** + * Hibernate the application on OPTIGA + * using optiga_util_close_application + */ + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_close_application(me_util, 1); + + if (OPTIGA_LIB_SUCCESS != return_status) + { + break; + } + + while (optiga_lib_status == OPTIGA_LIB_BUSY) + { + //Wait until the optiga_util_close_application is completed + } + + if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + { + //optiga util close application failed + break; + } + /** + * Restore the application on OPTIGA + * using optiga_util_open_application + */ + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_open_application(me_util, 1); + + if (OPTIGA_LIB_SUCCESS != return_status) + { + break; + } + while (OPTIGA_LIB_BUSY == optiga_lib_status) + { + //Wait until the optiga_util_open_application is completed + } + if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + { + //optiga util open application failed + break; + } + + /* + Paste your code is here + */ + + /** + * Close the application on OPTIGA after all the operations are executed + * using optiga_util_close_application + */ + optiga_lib_status = OPTIGA_LIB_BUSY; + return_status = optiga_util_close_application(me_util, 0); + + if (OPTIGA_LIB_SUCCESS != return_status) + { + break; + } + + while (optiga_lib_status == OPTIGA_LIB_BUSY) + { + //Wait until the optiga_util_close_application is completed + } + + if (OPTIGA_LIB_SUCCESS != optiga_lib_status) + { + //optiga util close application failed + break; + } + + // destroy util and crypt instances + optiga_util_destroy(me_util); + }while (FALSE); + + return return_value; +} +``` diff --git a/src/optiga-pal/optiga.c b/src/optiga-pal/optiga.c new file mode 100644 index 000000000..cc2efa4a1 --- /dev/null +++ b/src/optiga-pal/optiga.c @@ -0,0 +1,463 @@ +// Copyright 2024 Shift Crypto AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include "optiga-pal/optiga.h" +#include "hal_delay.h" +#include "hardfault.h" +#include "mbedtls/memory_buffer_alloc.h" +#include "optiga/optiga_crypt.h" +#include "optiga/optiga_util.h" +#include "optiga/pal/pal_i2c.h" +#include "optiga/pal/pal_os_datastore.h" +#include "optiga/pal/pal_os_timer.h" +#include "securechip/securechip.h" +#include "util.h" + +#define OPTIGA_DATA_OBJECT_ID_HMAC 0xF1D0 +#define OPTIGA_DATA_OBJECT_ID_PLATFORM_BINDING 0xE140 + +#define ABORT_IF_NULL(ptr) \ + do { \ + if ((ptr) == 0) { \ + Abort("Not initalized"); \ + } \ + } while (0) + +static optiga_util_t* util; +static optiga_crypt_t* crypt; + +static const securechip_interface_functions_t* _ifs = NULL; + +// The OPTIGA library is asynchronous and will schedule a callback when the command is done. The +// callback will set this shared variable to the result of the command. +static volatile optiga_lib_status_t optiga_lib_status; + +static void optiga_lib_callback(void* callback_ctx, optiga_lib_status_t event) +{ + (void)callback_ctx; + optiga_lib_status = event; + printf("optiga_lib_callback 0x%.3x\n", event); +} + +// Helper that is used in the main thread to busy wait for the callback to update the shared +// variable. +// It first checks the return status of the command, then busy waits, and then checks the +// asynchronous return status. +// Will return from caller if command failed. +// `return_status` will be updated with the actual return status +// Return statuses are documented in optiga_lib_return_codes.h +#define _WAIT(return_status, optiga_lib_status) \ + do { \ + if ((return_status) != OPTIGA_UTIL_SUCCESS) { \ + traceln("%s failed immediately (code: 0x%04x)\n", __func__, (return_status)); \ + return (return_status); \ + } \ + while (OPTIGA_LIB_BUSY == (optiga_lib_status)) { \ + } \ + if (OPTIGA_LIB_SUCCESS != (optiga_lib_status)) { \ + traceln("%s failed eventually (code: 0x%04x)\n", __func__, (optiga_lib_status)); \ + return (optiga_lib_status); \ + } \ + (return_status) = (optiga_lib_status); \ + } while (0) + +// Value of Operational state +#define LCSO_STATE_CREATION (0x01) +// Value of Operational state +#define LCSO_STATE_OPERATIONAL (0x07) + +// Currently set to Creation state(defualt value). At the real time/customer side this needs to be +// LCSO_STATE_OPERATIONAL (0x07) +#define FINAL_LCSO_STATE (LCSO_STATE_CREATION) + +/* Platform Binding Shared Secret (0xE140) Metadata to be updated */ +const uint8_t platform_binding_shared_secret_metadata_final[] = { + // Metadata to be updated + 0x20, + 0x17, + // LcsO + 0xC0, + 0x01, + FINAL_LCSO_STATE, // Refer Macro to see the value or some more notes + // Change/Write Access tag + 0xD0, + 0x07, + // This allows updating the binding secret during the runtime using shielded connection + // If not required to update the secret over the runtime, set this to NEV and + // update Metadata length accordingly + 0xE1, + 0xFC, + LCSO_STATE_OPERATIONAL, // LcsO < Operational state + 0xFE, + 0x20, + 0xE1, + 0x40, + // Read Access tag + 0xD1, + 0x03, + 0xE1, + 0xFC, + LCSO_STATE_OPERATIONAL, // LcsO < Operational state + // Execute Access tag + 0xD3, + 0x01, + 0x00, // Always + // Data object Type + 0xE8, + 0x01, + 0x22, // Platform binding secret type +}; + +static const uint8_t hmac_metadata[] = { + // Metadata tag in the data object + 0x20, + 0x06, + // Data object type set to PRESSEC + 0xE8, + 0x01, + 0x21, + 0xD3, + 0x01, + 0x00, +}; + +// +// Sync wrappers around optiga util/crypt functions +// + +// static optiga_lib_status_t _optiga_util_read_data_sync( +// optiga_util_t* me, +// uint16_t optiga_oid, +// uint16_t offset, +// uint8_t* buffer, +// uint16_t* length) +//{ +// ABORT_IF_NULL(me); +// +// optiga_lib_status = OPTIGA_LIB_BUSY; +// optiga_lib_status_t res = optiga_util_read_data(me, optiga_oid, offset, buffer, length); +// _WAIT(res, optiga_lib_status); +// return res; +// } + +// static optiga_lib_status_t _optiga_util_read_metadata_sync( +// optiga_util_t* me, +// uint16_t optiga_oid, +// uint8_t* buffer, +// uint16_t* length) +//{ +// ABORT_IF_NULL(me); +// +// optiga_lib_status = OPTIGA_LIB_BUSY; +// optiga_lib_status_t res = optiga_util_read_metadata(me, optiga_oid, buffer, length); +// _WAIT(res, optiga_lib_status); +// return res; +// } + +static optiga_lib_status_t _optiga_util_write_data_sync( + optiga_util_t* me, + uint16_t optiga_oid, + uint8_t write_type, + uint16_t offset, + const uint8_t* buffer, + uint16_t length) +{ + ABORT_IF_NULL(me); + + optiga_lib_status = OPTIGA_LIB_BUSY; + optiga_lib_status_t res = + optiga_util_write_data(me, optiga_oid, write_type, offset, buffer, length); + _WAIT(res, optiga_lib_status); + return res; +} + +static optiga_lib_status_t _optiga_util_write_metadata_sync( + optiga_util_t* me, + uint16_t optiga_oid, + const uint8_t* buffer, + uint8_t length) +{ + ABORT_IF_NULL(me); + + optiga_lib_status = OPTIGA_LIB_BUSY; + optiga_lib_status_t res = optiga_util_write_metadata(me, optiga_oid, buffer, length); + _WAIT(res, optiga_lib_status); + return res; +} + +static optiga_lib_status_t _optiga_util_open_application_sync( + optiga_util_t* me, + bool_t perform_restore) +{ + ABORT_IF_NULL(me); + + optiga_lib_status = OPTIGA_LIB_BUSY; + optiga_lib_status_t res = optiga_util_open_application(me, perform_restore); + _WAIT(res, optiga_lib_status); + return res; +} + +static optiga_lib_status_t _optiga_util_close_application_sync( + optiga_util_t* me, + bool_t perform_hibernate) +{ + ABORT_IF_NULL(me); + + optiga_lib_status = OPTIGA_LIB_BUSY; + optiga_lib_status_t res = optiga_util_close_application(me, perform_hibernate); + _WAIT(res, optiga_lib_status); + return res; +} + +static optiga_lib_status_t _optiga_crypt_hmac_sync( + optiga_crypt_t* me, + optiga_hmac_type_t type, + uint16_t secret, + const uint8_t* input_data, + uint32_t input_data_length, + uint8_t* mac, + uint32_t* mac_length) +{ + ABORT_IF_NULL(me); + + optiga_lib_status = OPTIGA_LIB_BUSY; + optiga_lib_status_t res = + optiga_crypt_hmac(me, type, secret, input_data, input_data_length, mac, mac_length); + _WAIT(res, optiga_lib_status); + return res; +} + +static optiga_lib_status_t _optiga_crypt_random_sync( + optiga_crypt_t* me, + optiga_rng_type_t rng_type, + uint8_t* random_data, + uint16_t random_data_length) +{ + ABORT_IF_NULL(me); + + optiga_lib_status = OPTIGA_LIB_BUSY; + optiga_lib_status_t res = optiga_crypt_random(me, rng_type, random_data, random_data_length); + _WAIT(res, optiga_lib_status); + return res; +} + +static bool _write_config(void) +{ + // + // Write platform binding secret to securechip + // + + uint8_t platform_binding_secret[32]; + uint16_t len = sizeof(platform_binding_secret); + optiga_lib_status_t res; + pal_status_t pal_res; + + pal_res = pal_os_datastore_read( + OPTIGA_PLATFORM_BINDING_SHARED_SECRET_ID, platform_binding_secret, &len); + + if (PAL_STATUS_SUCCESS != pal_res) { + return false; + } + + OPTIGA_UTIL_SET_COMMS_PROTECTION_LEVEL(util, OPTIGA_COMMS_NO_PROTECTION); + res = _optiga_util_write_data_sync( + util, + OPTIGA_DATA_OBJECT_ID_PLATFORM_BINDING, + OPTIGA_UTIL_ERASE_AND_WRITE, + 0, + platform_binding_secret, + sizeof(platform_binding_secret)); + if (res != OPTIGA_LIB_SUCCESS) { + return false; + } + + OPTIGA_UTIL_SET_COMMS_PROTECTION_LEVEL(util, OPTIGA_COMMS_NO_PROTECTION); + res = _optiga_util_write_metadata_sync( + util, + OPTIGA_DATA_OBJECT_ID_PLATFORM_BINDING, + platform_binding_shared_secret_metadata_final, + sizeof(platform_binding_shared_secret_metadata_final)); + if (res != OPTIGA_LIB_SUCCESS) { + return false; + } + + // + // Configure HMAC data object + // + + OPTIGA_UTIL_SET_COMMS_PROTECTION_LEVEL(util, OPTIGA_COMMS_NO_PROTECTION); + res = _optiga_util_write_metadata_sync( + util, OPTIGA_DATA_OBJECT_ID_HMAC, hmac_metadata, sizeof(hmac_metadata)); + + if (res != OPTIGA_LIB_SUCCESS) { + return false; + } + + return true; +} + +static bool _factory_setup(void) +{ + optiga_lib_status_t res; + + util = optiga_util_create(OPTIGA_INSTANCE_ID_0, optiga_lib_callback, NULL); + if (NULL == util) { + traceln("%s", "util_create returned null"); + return 1; + } + + crypt = optiga_crypt_create(OPTIGA_INSTANCE_ID_0, optiga_lib_callback, NULL); + if (NULL == crypt) { + traceln("%s", "crypt_create returned null"); + return 1; + } + + OPTIGA_UTIL_SET_COMMS_PROTECTION_LEVEL(util, OPTIGA_COMMS_NO_PROTECTION); + res = _optiga_util_open_application_sync(util, 0); + if (res != OPTIGA_LIB_SUCCESS) { + traceln("Failed to open application %d", res); + return 1; + } + + if (!_write_config()) { + traceln("%s", "failed to write config to chip"); + return false; + } + + res = _optiga_util_close_application_sync(util, 0); + if (res != OPTIGA_LIB_SUCCESS) { + traceln("Failed to open application %d", res); + return 1; + } + + if (NULL != crypt) { + optiga_crypt_destroy(crypt); + crypt = NULL; + } + + if (NULL != util) { + optiga_util_destroy(util); + util = NULL; + } + + return true; +} + +static bool _verify_config(void) +{ + optiga_lib_status_t res; + + util = optiga_util_create(OPTIGA_INSTANCE_ID_0, optiga_lib_callback, NULL); + if (NULL == util) { + traceln("%s", "util_create returned null"); + return false; + } + + crypt = optiga_crypt_create(OPTIGA_INSTANCE_ID_0, optiga_lib_callback, NULL); + if (NULL == crypt) { + traceln("%s", "crypt_create returned null"); + return false; + } + + res = _optiga_util_open_application_sync(util, 0); + if (res != OPTIGA_LIB_SUCCESS) { + traceln("Failed to open application %d", res); + return false; + } + traceln("%s", "Application open"); + return true; +} + +int optiga_setup(const securechip_interface_functions_t* ifs) +{ + if (ifs == NULL) { + return SC_ERR_IFS; + } + _ifs = ifs; + + // A timer is used to provide the OPTIGA library with the ability to schedule work on the main + // event loop + pal_timer_init(); + +#if true // FACTORYSETUP == 1 + bool res = _factory_setup(); + if (!res) { + return res; + } + traceln("%s", "factory setup done"); +#endif + + if (_verify_config()) { + return 0; + } + return SC_ERR_INVALID_ARGS; +} + +static bool _update_hmac_key(void) +{ + ABORT_IF_NULL(util); + ABORT_IF_NULL(_ifs); + ABORT_IF_NULL(_ifs->random_32_bytes); + + uint8_t new_key[32] = {0}; + _ifs->random_32_bytes(new_key); + + traceln("new hmac key: %s", util_uint8_to_hex_alloc(new_key, sizeof(new_key))); + + return _optiga_util_write_data_sync( + util, + OPTIGA_DATA_OBJECT_ID_HMAC, + OPTIGA_UTIL_ERASE_AND_WRITE, + 0x00, + new_key, + sizeof(new_key)) == OPTIGA_LIB_SUCCESS; +} + +int optiga_hmac(const uint8_t* msg, size_t len, uint8_t* mac_out) +{ + ABORT_IF_NULL(crypt); + // The equivalient of python `mac_out = hmac.new(key, msg[:len], hashlib.sha256).digest()` + + _update_hmac_key(); + uint32_t mac_out_len = 32; + + optiga_lib_status_t res = _optiga_crypt_hmac_sync( + crypt, OPTIGA_HMAC_SHA_256, OPTIGA_DATA_OBJECT_ID_HMAC, msg, len, mac_out, &mac_out_len); + + if (mac_out_len != 32) { + traceln("%s", "Unexpected MAC length"); + } + + return res == OPTIGA_LIB_SUCCESS; +} + +// rand_out must be 32 bytes +bool optiga_random(uint8_t* rand_out) +{ + return _optiga_crypt_random_sync(crypt, OPTIGA_RNG_TYPE_TRNG, rand_out, 32) == + OPTIGA_LIB_SUCCESS; +} + +bool optiga_model(securechip_model_t* model_out) +{ + *model_out = OPTIGA_TRUST_M_V3; + return true; +} + +// bool _ecc_write_priv_key(uint8_t* priv_key) { +// +// } +// +// bool securitufunctions_ecc_generate_public_key(uint8_t* priv_key, uint8_t* pub_key) { +// _ecc_write_priv_key(priv_key +// } diff --git a/src/optiga-pal/optiga.h b/src/optiga-pal/optiga.h new file mode 100644 index 000000000..1fa45d1ae --- /dev/null +++ b/src/optiga-pal/optiga.h @@ -0,0 +1,26 @@ +// Copyright 2024 Shift Crypto AG +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _OPTIGA_H_ +#define _OPTIGA_H_ +#include "securechip/securechip.h" +#include +#include +#include + +int optiga_setup(const securechip_interface_functions_t* ifs); +bool optiga_random(uint8_t* rand_out); +int optiga_hmac(const uint8_t* msg, size_t len, uint8_t* mac_out); +bool optiga_model(securechip_model_t* model_out); +#endif // _OPTIGA_H_ diff --git a/src/optiga-pal/pal.c b/src/optiga-pal/pal.c new file mode 100644 index 000000000..bf038d76c --- /dev/null +++ b/src/optiga-pal/pal.c @@ -0,0 +1,52 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal.c + * + * \brief This file implements the platform abstraction layer APIs. + * + * \ingroup grPAL + * + * @{ + */ + +#include "optiga/pal/pal.h" + +pal_status_t pal_init(void) +{ + return PAL_STATUS_SUCCESS; +} + +pal_status_t pal_deinit(void) +{ + return PAL_STATUS_SUCCESS; +} + +/** + * @} + */ diff --git a/src/optiga-pal/pal_crypt_mbedtls.c b/src/optiga-pal/pal_crypt_mbedtls.c new file mode 100644 index 000000000..ec579eb74 --- /dev/null +++ b/src/optiga-pal/pal_crypt_mbedtls.c @@ -0,0 +1,303 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2021 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_crypt_mbedtls.c + * + * \brief This file implements the platform abstraction layer APIs for cryptographic functions + * using mbedTLS SW Crypto. + * + * \ingroup grPAL + * + * @{ + */ + +#include "mbedtls/ccm.h" +#include "mbedtls/md.h" +#include "mbedtls/ssl.h" +#include "mbedtls/version.h" +#include "optiga/common/optiga_lib_common.h" +#include "optiga/pal/pal_crypt.h" +#include "optiga/pal/pal_os_memory.h" + +#define PAL_CRYPT_MAX_LABEL_SEED_LENGTH (96U) +// lint --e{818, 715, 830} suppress "argument "p_pal_crypt" is not used in the implementation but +// kept for future use" +pal_status_t pal_crypt_tls_prf_sha256( + pal_crypt_t* p_pal_crypt, + const uint8_t* p_secret, + uint16_t secret_length, + const uint8_t* p_label, + uint16_t label_length, + const uint8_t* p_seed, + uint16_t seed_length, + uint8_t* p_derived_key, + uint16_t derived_key_length) +{ + (void)p_pal_crypt; +#define PAL_CRYPT_DIGEST_MAX_SIZE (32U) + + pal_status_t return_value = PAL_STATUS_FAILURE; + uint8_t message_digest_length = PAL_CRYPT_DIGEST_MAX_SIZE; + uint16_t derive_key_len_index, hmac_checksum_result_index; + uint16_t hmac_result_length; + uint8_t md_hmac_temp_array[PAL_CRYPT_MAX_LABEL_SEED_LENGTH + PAL_CRYPT_DIGEST_MAX_SIZE]; + uint8_t hmac_checksum_result[PAL_CRYPT_DIGEST_MAX_SIZE]; + const mbedtls_md_info_t* message_digest_info; + mbedtls_md_context_t message_digest_context; + uint16_t final_seed_length = 0; + + mbedtls_md_init(&message_digest_context); + + do { +#ifdef OPTIGA_LIB_DEBUG_NULL_CHECK + if ((NULL == p_secret) || (NULL == p_label) || (NULL == p_seed) || + (NULL == p_derived_key)) { + break; + } +#endif // OPTIGA_LIB_DEBUG_NULL_CHECK + + if (sizeof(md_hmac_temp_array) < + (uint32_t)(message_digest_length + label_length + seed_length)) { + return_value = PAL_STATUS_INVALID_INPUT; + break; + } + + message_digest_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + + memcpy(md_hmac_temp_array + message_digest_length, p_label, label_length); + memcpy(md_hmac_temp_array + message_digest_length + label_length, p_seed, seed_length); + final_seed_length = label_length + seed_length; + + if (0 != (mbedtls_md_setup(&message_digest_context, message_digest_info, 1))) { + return_value = PAL_STATUS_INVALID_INPUT; + break; + } + + if (0 != mbedtls_md_hmac_starts(&message_digest_context, p_secret, secret_length)) { + break; + } + + if (0 != mbedtls_md_hmac_update( + &message_digest_context, + md_hmac_temp_array + message_digest_length, + final_seed_length)) { + break; + } + + if (0 != mbedtls_md_hmac_finish(&message_digest_context, md_hmac_temp_array)) { + break; + } + + for (derive_key_len_index = 0; derive_key_len_index < derived_key_length; + derive_key_len_index += message_digest_length) { + if (0 != mbedtls_md_hmac_reset(&message_digest_context)) { + break; + } + if (0 != mbedtls_md_hmac_update( + &message_digest_context, + md_hmac_temp_array, + message_digest_length + final_seed_length)) { + break; + } + if (0 != mbedtls_md_hmac_finish(&message_digest_context, hmac_checksum_result)) { + break; + } + + if (0 != mbedtls_md_hmac_reset(&message_digest_context)) { + break; + } + if (0 != mbedtls_md_hmac_update( + &message_digest_context, md_hmac_temp_array, message_digest_length)) { + break; + } + if (0 != mbedtls_md_hmac_finish(&message_digest_context, md_hmac_temp_array)) { + break; + } + + hmac_result_length = + ((derive_key_len_index + message_digest_length) > derived_key_length) + ? (derived_key_length % message_digest_length) + : (message_digest_length); + + for (hmac_checksum_result_index = 0; hmac_checksum_result_index < hmac_result_length; + hmac_checksum_result_index++) { + p_derived_key[derive_key_len_index + hmac_checksum_result_index] = + hmac_checksum_result[hmac_checksum_result_index]; + } + } + if (derive_key_len_index >= derived_key_length) { + return_value = PAL_STATUS_SUCCESS; + } + } while (FALSE); + + mbedtls_md_free(&message_digest_context); + + memset(md_hmac_temp_array, 0x00, sizeof(md_hmac_temp_array)); + memset(hmac_checksum_result, 0x00, sizeof(hmac_checksum_result)); +#undef PAL_CRYPT_DIGEST_MAX_SIZE + return return_value; +} + +// lint --e{818, 715, 830} suppress "argument "p_pal_crypt" is not used in the implementation but +// kept for future use" +pal_status_t pal_crypt_encrypt_aes128_ccm( + pal_crypt_t* p_pal_crypt, + const uint8_t* p_plain_text, + uint16_t plain_text_length, + const uint8_t* p_encrypt_key, + const uint8_t* p_nonce, + uint16_t nonce_length, + const uint8_t* p_associated_data, + uint16_t associated_data_length, + uint8_t mac_size, + uint8_t* p_cipher_text) +{ + (void)p_pal_crypt; +#define AES128_KEY_BITS_SIZE (16U) +#define MAC_TAG_BUFFER_SIZE (16U) + + pal_status_t return_status = PAL_STATUS_FAILURE; + uint8_t mac_tag_output[MAC_TAG_BUFFER_SIZE]; + mbedtls_ccm_context sEncrypt; + + mbedtls_ccm_init(&sEncrypt); + + do { +#ifdef OPTIGA_LIB_DEBUG_NULL_CHECK + if ((NULL == p_cipher_text) || (NULL == p_plain_text) || (NULL == p_nonce) || + (NULL == p_associated_data) || (NULL == p_encrypt_key)) { + break; + } +#endif + + if (0 != mbedtls_ccm_setkey( + &sEncrypt, MBEDTLS_CIPHER_ID_AES, p_encrypt_key, 8 * AES128_KEY_BITS_SIZE)) { + break; + } + + if (0 != mbedtls_ccm_encrypt_and_tag( + &sEncrypt, + plain_text_length, + p_nonce, + nonce_length, + p_associated_data, + associated_data_length, + p_plain_text, + p_cipher_text, + mac_tag_output, + mac_size)) + + { + break; + } + + memcpy((p_cipher_text + plain_text_length), mac_tag_output, mac_size); + return_status = PAL_STATUS_SUCCESS; + } while (FALSE); + mbedtls_ccm_free(&sEncrypt); +#undef AES128_KEY_BITS_SIZE +#undef MAC_TAG_BUFFER_SIZE + return return_status; +} + +// lint --e{818, 715, 830} suppress "argument "p_pal_crypt" is not used in the implementation but +// kept for future use" +pal_status_t pal_crypt_decrypt_aes128_ccm( + pal_crypt_t* p_pal_crypt, + const uint8_t* p_cipher_text, + uint16_t cipher_text_length, + const uint8_t* p_decrypt_key, + const uint8_t* p_nonce, + uint16_t nonce_length, + const uint8_t* p_associated_data, + uint16_t associated_data_length, + uint8_t mac_size, + uint8_t* p_plain_text) +{ + (void)p_pal_crypt; +#define AES128_KEY_BITS_SIZE (16U) + pal_status_t return_status = PAL_STATUS_FAILURE; + mbedtls_ccm_context sDecrypt; + + mbedtls_ccm_init(&sDecrypt); + + do { +#ifdef OPTIGA_LIB_DEBUG_NULL_CHECK + if ((NULL == p_plain_text) || (NULL == p_cipher_text) || (NULL == p_nonce) || + (NULL == p_associated_data) || (NULL == p_decrypt_key)) { + break; + } +#endif + + if (0 != mbedtls_ccm_setkey( + &sDecrypt, MBEDTLS_CIPHER_ID_AES, p_decrypt_key, 8 * AES128_KEY_BITS_SIZE)) { + break; + } + + if (0 != mbedtls_ccm_auth_decrypt( + &sDecrypt, + (cipher_text_length - mac_size), + p_nonce, + nonce_length, + p_associated_data, + associated_data_length, + p_cipher_text, + p_plain_text, + &p_cipher_text[cipher_text_length - mac_size], + mac_size)) { + break; + } + return_status = PAL_STATUS_SUCCESS; + } while (FALSE); + mbedtls_ccm_free(&sDecrypt); +#undef AES128_KEY_BITS_SIZE + return return_status; +} + +pal_status_t pal_crypt_version(uint8_t* p_crypt_lib_version_info, uint16_t* length) +{ + pal_status_t return_value = PAL_STATUS_FAILURE; + uint8_t sizeof_version_number = (uint8_t)strlen(MBEDTLS_VERSION_STRING); + + do { + if (sizeof_version_number > *length) { + break; + } + + pal_os_memcpy(p_crypt_lib_version_info, MBEDTLS_VERSION_STRING, sizeof_version_number); + *length = sizeof_version_number; + + return_value = PAL_STATUS_SUCCESS; + + } while (0); + return return_value; +} + +/** + * @} + */ diff --git a/src/optiga-pal/pal_gpio.c b/src/optiga-pal/pal_gpio.c new file mode 100644 index 000000000..72e0109e1 --- /dev/null +++ b/src/optiga-pal/pal_gpio.c @@ -0,0 +1,66 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_gpio.c + * + * \brief This file implements the platform abstraction layer APIs for GPIO. + * + * \ingroup grPAL + * + * @{ + */ + +#include "optiga/pal/pal_gpio.h" + +pal_status_t pal_gpio_init(const pal_gpio_t* p_gpio_context) +{ + (void)p_gpio_context; + return PAL_STATUS_SUCCESS; +} + +pal_status_t pal_gpio_deinit(const pal_gpio_t* p_gpio_context) +{ + (void)p_gpio_context; + return PAL_STATUS_SUCCESS; +} + +void pal_gpio_set_high(const pal_gpio_t* p_gpio_context) +{ + (void)p_gpio_context; + // We don't support setting vdd or rst pins +} + +void pal_gpio_set_low(const pal_gpio_t* p_gpio_context) +{ + (void)p_gpio_context; + // We don't support setting vdd or rst pins +} + +/** + * @} + */ diff --git a/src/optiga-pal/pal_i2c.c b/src/optiga-pal/pal_i2c.c new file mode 100644 index 000000000..9c3e413cd --- /dev/null +++ b/src/optiga-pal/pal_i2c.c @@ -0,0 +1,322 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_i2c.c + * + * \brief This file implements the platform abstraction layer(pal) APIs for I2C. + * + * \ingroup grPAL + * + * @{ + */ + +#include "optiga/pal/pal_i2c.h" +#include "hal_delay.h" +#include "hal_i2c_m_sync.h" +#include "optiga/pal/pal_os_timer.h" +#include "util.h" +extern struct i2c_m_sync_desc I2C_0; + +#define PAL_I2C_MASTER_MAX_BITRATE (400U) + +static volatile uint32_t g_entry_count = 0; +static const pal_i2c_t* gp_pal_i2c_current_ctx; + +static pal_status_t pal_i2c_acquire(const void* p_i2c_context) +{ + // To avoid compiler errors/warnings. This context might be used by a target + // system to implement a proper mutex handling + (void)p_i2c_context; + + if (0 == g_entry_count) { + g_entry_count++; + if (1 == g_entry_count) { + return PAL_STATUS_SUCCESS; + } + } + traceln("%s: acquired failed", __func__); + return PAL_STATUS_FAILURE; +} + +static void pal_i2c_release(const void* p_i2c_context) +{ + // To avoid compiler errors/warnings. This context might be used by a target + // system to implement a proper mutex handling + (void)p_i2c_context; + + g_entry_count = 0; +} + +static void invoke_upper_layer_callback(const pal_i2c_t* p_pal_i2c_ctx, optiga_lib_status_t event) +{ + upper_layer_callback_t upper_layer_handler; + + // Casting a data pointer to a function pointer is not OK according to ISO C. However, everyone + // does it... +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + upper_layer_handler = (upper_layer_callback_t)p_pal_i2c_ctx->upper_layer_event_handler; +#pragma GCC diagnostic pop + + upper_layer_handler(p_pal_i2c_ctx->p_upper_layer_ctx, event); + + // Release I2C Bus + pal_i2c_release(p_pal_i2c_ctx->p_upper_layer_ctx); +} + +// !!!OPTIGA_LIB_PORTING_REQUIRED +// The next 5 functions are required only in case you have interrupt based i2c implementation +// void i2c_master_end_of_transmit_callback(void) +//{ +// invoke_upper_layer_callback(gp_pal_i2c_current_ctx, PAL_I2C_EVENT_SUCCESS); +//} +// +// void i2c_master_end_of_receive_callback(void) +//{ +// invoke_upper_layer_callback(gp_pal_i2c_current_ctx, PAL_I2C_EVENT_SUCCESS); +//} +// +// void i2c_master_error_detected_callback(void) +//{ +// invoke_upper_layer_callback(gp_pal_i2c_current_ctx, PAL_I2C_EVENT_ERROR); +//} +// +// void i2c_master_nack_received_callback(void) +//{ +// i2c_master_error_detected_callback(); +//} +// +// void i2c_master_arbitration_lost_callback(void) +//{ +// i2c_master_error_detected_callback(); +//} + +pal_status_t pal_i2c_init(const pal_i2c_t* p_i2c_context) +{ + (void)p_i2c_context; + return PAL_STATUS_SUCCESS; +} + +pal_status_t pal_i2c_deinit(const pal_i2c_t* p_i2c_context) +{ + (void)p_i2c_context; + return PAL_STATUS_SUCCESS; +} + +pal_status_t pal_i2c_write(const pal_i2c_t* p_i2c_context, uint8_t* p_data, uint16_t length) +{ + // traceln("%s", __func__); + pal_status_t status = PAL_STATUS_FAILURE; + struct _i2c_m_msg packet; + uint8_t retries = 25U; + int32_t r; + + packet.addr = p_i2c_context->slave_address; + packet.len = (int32_t)length; + packet.buffer = p_data; + packet.flags = I2C_M_SEVEN | I2C_M_STOP; + + // Acquire the I2C bus before read/write + if (PAL_STATUS_SUCCESS == pal_i2c_acquire(p_i2c_context)) { + gp_pal_i2c_current_ctx = p_i2c_context; + + // Invoke the low level i2c master driver API to write to the bus + // !!!OPTIGA_LIB_PORTING_REQUIRED + do { + r = i2c_m_sync_transfer(p_i2c_context->p_i2c_hw_config, &packet); + delay_ms(2U); + } while (retries-- && r != I2C_OK); + + if (r != I2C_OK) { + // If I2C Master fails to invoke the write operation, invoke upper layer event handler + // with error. + + // Casting a data pointer to a function pointer is not OK according to ISO C. However, + // everyone does it... +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + ((upper_layer_callback_t)(p_i2c_context->upper_layer_event_handler))( + p_i2c_context->p_upper_layer_ctx, PAL_I2C_EVENT_ERROR); +#pragma GCC diagnostic pop + + // Release I2C Bus + pal_i2c_release(p_i2c_context); + } else { + // !!!OPTIGA_LIB_PORTING_REQUIRED + /** + * Infineon I2C Protocol is a polling based protocol, if foo_i2c_write will fail it will + * be reported to the upper layers by calling + * (p_i2c_context->upper_layer_event_handler))(p_i2c_context->p_upper_layer_ctx , + * PAL_I2C_EVENT_ERROR); If the function foo_i2c_write() will succedd then two options + * are possible + * 1. if foo_i2c_write() is interrupt based, then you need to configure interrupts in + * the function pal_i2c_init() so that on a succesfull transmit interrupt the callback + * i2c_master_end_of_transmit_callback(), in case of successfull receive + * i2c_master_end_of_receive_callback() callback in case of not acknowedged, arbitration + * lost, generic error i2c_master_nack_received_callback() or + * i2c_master_arbitration_lost_callback() + * 2. If foo_i2c_write() is a blocking function which will return either ok or failure + * after transmitting data you can handle this case directly here and call + * invoke_upper_layer_callback(gp_pal_i2c_current_ctx, PAL_I2C_EVENT_SUCCESS); + * + */ + invoke_upper_layer_callback(gp_pal_i2c_current_ctx, PAL_I2C_EVENT_SUCCESS); + status = PAL_STATUS_SUCCESS; + } + } else { + status = PAL_STATUS_I2C_BUSY; + // Casting a data pointer to a function pointer is not OK according to ISO C. However, + // everyone does it... +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + ((upper_layer_callback_t)(p_i2c_context->upper_layer_event_handler))( + p_i2c_context->p_upper_layer_ctx, PAL_I2C_EVENT_BUSY); +#pragma GCC diagnostic pop + } + return status; +} + +pal_status_t pal_i2c_read(const pal_i2c_t* p_i2c_context, uint8_t* p_data, uint16_t length) +{ + // traceln("%s", __func__); + // int32_t start = pal_os_timer_get_time_in_milliseconds(); + pal_status_t status = PAL_STATUS_FAILURE; + struct _i2c_m_msg packet; + uint8_t retries = 25U; + int32_t r; + + packet.addr = p_i2c_context->slave_address; + packet.len = (int32_t)length; + packet.buffer = p_data; + packet.flags = I2C_M_SEVEN | I2C_M_RD | I2C_M_STOP; + + // Acquire the I2C bus before read/write + if (PAL_STATUS_SUCCESS == pal_i2c_acquire(p_i2c_context)) { + gp_pal_i2c_current_ctx = p_i2c_context; + + // Invoke the low level i2c master driver API to read from the bus + do { + r = i2c_m_sync_transfer(p_i2c_context->p_i2c_hw_config, &packet); + delay_ms(2U); + } while (retries-- && r != I2C_OK); + + if (r != I2C_OK) { + traceln("%s transfer failed", __func__); + // If I2C Master fails to invoke the read operation, invoke upper layer event handler + // with error. + // Casting a data pointer to a function pointer is not OK according to ISO C. However, + // everyone does it... +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + ((upper_layer_callback_t)(p_i2c_context->upper_layer_event_handler))( + p_i2c_context->p_upper_layer_ctx, PAL_I2C_EVENT_ERROR); +#pragma GCC diagnostic pop + + // Release I2C Bus + pal_i2c_release(p_i2c_context); + } else { + // !!!OPTIGA_LIB_PORTING_REQUIRED + /** + * Similar to the foo_i2c_write() case you can directly call + * invoke_upper_layer_callback(gp_pal_i2c_current_ctx, PAL_I2C_EVENT_SUCCESS); + * if you have blocking (non-interrupt) i2c calls + */ + invoke_upper_layer_callback(gp_pal_i2c_current_ctx, PAL_I2C_EVENT_SUCCESS); + status = PAL_STATUS_SUCCESS; + } + } else { + status = PAL_STATUS_I2C_BUSY; + // Casting a data pointer to a function pointer is not OK according to ISO C. However, + // everyone does it... +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + ((upper_layer_callback_t)(p_i2c_context->upper_layer_event_handler))( + p_i2c_context->p_upper_layer_ctx, PAL_I2C_EVENT_BUSY); +#pragma GCC diagnostic pop + } + // uint32_t final_time = pal_os_timer_get_time_in_milliseconds() - start; + // traceln("took %lu ms", final_time); + return status; +} + +pal_status_t pal_i2c_set_bitrate(const pal_i2c_t* p_i2c_context, uint16_t bitrate) +{ + // traceln("%s %d", __func__, bitrate); + pal_status_t return_status = PAL_STATUS_FAILURE; + optiga_lib_status_t event = PAL_I2C_EVENT_ERROR; + + // Acquire the I2C bus before setting the bitrate + if (PAL_STATUS_SUCCESS == pal_i2c_acquire(p_i2c_context)) { + // If the user provided bitrate is greater than the I2C master hardware maximum supported + // value, set the I2C master to its maximum supported value. + if (bitrate > PAL_I2C_MASTER_MAX_BITRATE) { + bitrate = PAL_I2C_MASTER_MAX_BITRATE; + } + + do { + if (0 != i2c_m_sync_disable(&I2C_0)) { + traceln("%s: failed to disable i2c", __func__); + return_status = PAL_STATUS_FAILURE; + break; + } + + if (0 != i2c_m_sync_set_baudrate(p_i2c_context->p_i2c_hw_config, 0, bitrate)) { + traceln("%s: failed to set bitrate", __func__); + return_status = PAL_STATUS_FAILURE; + break; + } + + if (0 != i2c_m_sync_enable(&I2C_0)) { + traceln("%s: failed to enable i2c", __func__); + return_status = PAL_STATUS_FAILURE; + break; + } + event = PAL_I2C_EVENT_SUCCESS; + return_status = PAL_STATUS_SUCCESS; + } while (0); + } else { + return_status = PAL_STATUS_I2C_BUSY; + event = PAL_I2C_EVENT_BUSY; + } + if (0 != p_i2c_context->upper_layer_event_handler) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + ((upper_layer_callback_t)(p_i2c_context->upper_layer_event_handler))( + p_i2c_context->p_upper_layer_ctx, event); +#pragma GCC diagnostic pop + } + // Release I2C Bus if its acquired + if (PAL_STATUS_I2C_BUSY != return_status) { + pal_i2c_release(p_i2c_context); + } + return return_status; +} + +/** + * @} + */ diff --git a/src/optiga-pal/pal_ifx_i2c_config.c b/src/optiga-pal/pal_ifx_i2c_config.c new file mode 100644 index 000000000..191c0e162 --- /dev/null +++ b/src/optiga-pal/pal_ifx_i2c_config.c @@ -0,0 +1,90 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_ifx_i2c_config.c + * + * \brief This file implements platform abstraction layer configurations for ifx i2c protocol. + * + * \ingroup grPAL + * + * @{ + */ + +#include "driver_init.h" +#include "optiga/ifx_i2c/ifx_i2c_config.h" +#include "optiga/pal/pal_gpio.h" +#include "optiga/pal/pal_i2c.h" + +// !!!OPTIGA_LIB_PORTING_REQUIRED +// typedef struct locl_i2c_struct_to_descroibe_master +//{ +// // you parameters to control the master instance +// // See other implementation to get intuition on how to implement this part +//}local_i2c_struct_to_descroibe_master_t; +// +// local_i2c_struct_to_descroibe_master_t i2c_master_0; + +/** + * \brief PAL I2C configuration for OPTIGA. + */ +pal_i2c_t optiga_pal_i2c_context_0 = { + /// Pointer to I2C master platform specific context + (void*)&I2C_0, + /// Upper layer context + NULL, + /// Callback event handler + NULL, + /// Slave address + 0x30, +}; + +/** + * \brief PAL vdd pin configuration for OPTIGA. + * NC on bitbox02 + */ +pal_gpio_t optiga_vdd_0 = { + // !!!OPTIGA_LIB_PORTING_REQUIRED + // Platform specific GPIO context for the pin used to toggle Vdd. + // You should have vdd_pin define in your system, + // alternativly you can put here raw GPIO number, but without the & sign + 0}; + +/** + * \brief PAL reset pin configuration for OPTIGA. + * NC on bitbox02 + */ +pal_gpio_t optiga_reset_0 = { + // !!!OPTIGA_LIB_PORTING_REQUIRED + // Platform specific GPIO context for the pin used to toggle Reset. + // You should have reset_pin define in your system, + // alternativly you can put here raw GPIO number, but without the & sign + 0}; + +/** + * @} + */ diff --git a/src/optiga-pal/pal_logger.c b/src/optiga-pal/pal_logger.c new file mode 100644 index 000000000..28dddcb08 --- /dev/null +++ b/src/optiga-pal/pal_logger.c @@ -0,0 +1,107 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_logger.c + * + * \brief This file provides the prototypes declarations for pal logger. + * + * \ingroup grPAL + * + * @{ + */ +#include "optiga/pal/pal_logger.h" +#include "util.h" + +pal_logger_t logger_console = { + .logger_config_ptr = NULL, + .logger_rx_flag = 0, + .logger_tx_flag = 1, +}; + +pal_status_t pal_logger_init(void* p_logger_context) +{ + pal_status_t return_status = PAL_STATUS_FAILURE; + pal_logger_t* p_log_context = p_logger_context; + (void)p_log_context; + + do { + // !!!OPTIGA_LIB_PORTING_REQUIRED + } while (0); + return return_status; +} + +pal_status_t pal_logger_deinit(void* p_logger_context) +{ + pal_status_t return_status = PAL_STATUS_FAILURE; + pal_logger_t* p_log_context = p_logger_context; + (void)p_log_context; + + do { + // !!!OPTIGA_LIB_PORTING_REQUIRED + } while (0); + return return_status; +} + +pal_status_t pal_logger_write( + void* p_logger_context, + const uint8_t* p_log_data, + uint32_t log_data_length) +{ + int32_t return_status = PAL_STATUS_FAILURE; + pal_logger_t* p_log_context = p_logger_context; + (void)p_log_context; + do { + const char* p = (const char*)p_log_data; + while (p < (const char*)p_log_data + log_data_length) { + // Optega library logs with \r\n as line ending, but we only need \n. + if (*p != '\r') { + putchar(*p); + } + p++; + } + return_status = PAL_STATUS_SUCCESS; + } while (0); + return ((pal_status_t)return_status); +} + +pal_status_t pal_logger_read(void* p_logger_context, uint8_t* p_log_data, uint32_t log_data_length) +{ + int32_t return_status = PAL_STATUS_FAILURE; + pal_logger_t* p_log_context = p_logger_context; + (void)p_log_context; + + do { + for (uint8_t* p = p_log_data; p < p_log_data + log_data_length; p++) { + *p = getchar(); + } + } while (0); + return ((pal_status_t)return_status); +} +/** + * @} + */ diff --git a/src/optiga-pal/pal_os_datastore.c b/src/optiga-pal/pal_os_datastore.c new file mode 100644 index 000000000..0c018bd7c --- /dev/null +++ b/src/optiga-pal/pal_os_datastore.c @@ -0,0 +1,86 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2020 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_os_datastore.c + * + * \brief This file implements the platform abstraction layer APIs for data store. + * + * \ingroup grPAL + * + * @{ + */ + +#include "optiga/pal/pal_os_datastore.h" +#include "memory/memory.h" +/// @cond hidden + +pal_status_t pal_os_datastore_write(uint16_t datastore_id, const uint8_t* p_buffer, uint16_t length) +{ + pal_status_t return_status = PAL_STATUS_FAILURE; + (void)p_buffer; + (void)length; + + switch (datastore_id) { + case OPTIGA_PLATFORM_BINDING_SHARED_SECRET_ID: { + // Not implemented + return_status = PAL_STATUS_FAILURE; + break; + } + default: { + break; + } + } + return return_status; +} + +pal_status_t pal_os_datastore_read( + uint16_t datastore_id, + uint8_t* p_buffer, + uint16_t* p_buffer_length) +{ + pal_status_t return_status = PAL_STATUS_FAILURE; + + switch (datastore_id) { + case OPTIGA_PLATFORM_BINDING_SHARED_SECRET_ID: { + memory_get_io_protection_key(p_buffer); + *p_buffer_length = 32; + return_status = PAL_STATUS_SUCCESS; + break; + } + default: { + *p_buffer_length = 0; + break; + } + } + + return return_status; +} +/// @endcond +/** + * @} + */ diff --git a/src/optiga-pal/pal_os_event.c b/src/optiga-pal/pal_os_event.c new file mode 100644 index 000000000..a8935416c --- /dev/null +++ b/src/optiga-pal/pal_os_event.c @@ -0,0 +1,110 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_os_event.c + * + * \brief This file implements the platform abstraction layer APIs for os event/scheduler. + * + * \ingroup grPAL + * + * @{ + */ + +#include "optiga/pal/pal_os_event.h" +#include "hal_timer.h" +#include "util.h" +extern struct timer_descriptor TIMER_0; + +static pal_os_event_t pal_os_event_0 = {0}; + +void pal_os_event_start( + pal_os_event_t* p_pal_os_event, + register_callback callback, + void* callback_args) +{ + if (0 == p_pal_os_event->is_event_triggered) { + p_pal_os_event->is_event_triggered = TRUE; + pal_os_event_register_callback_oneshot(p_pal_os_event, callback, callback_args, 1000); + } +} + +void pal_os_event_stop(pal_os_event_t* p_pal_os_event) +{ + p_pal_os_event->is_event_triggered = 0; +} + +pal_os_event_t* pal_os_event_create(register_callback callback, void* callback_args) +{ + if ((NULL != callback) && (NULL != callback_args)) { + pal_os_event_start(&pal_os_event_0, callback, callback_args); + } + return (&pal_os_event_0); +} + +static struct timer_task scheduler; + +void pal_os_event_trigger_registered_callback(void) +{ + // traceln("%s: called", __func__); + register_callback callback; + + if (pal_os_event_0.callback_registered) { + callback = pal_os_event_0.callback_registered; + callback((void*)pal_os_event_0.callback_ctx); + } +} + +static void _timer_cb(const struct timer_task* const timer_task) +{ + (void)timer_task; + pal_os_event_trigger_registered_callback(); +} + +void pal_os_event_register_callback_oneshot( + pal_os_event_t* p_pal_os_event, + register_callback callback, + void* callback_args, + uint32_t time_us) +{ + p_pal_os_event->callback_registered = callback; + p_pal_os_event->callback_ctx = callback_args; + + scheduler.interval = (time_us + 99) / 100; + scheduler.cb = _timer_cb; + scheduler.mode = TIMER_TASK_ONE_SHOT; + timer_add_task(&TIMER_0, &scheduler); +} + +void pal_os_event_destroy(pal_os_event_t* pal_os_event) +{ + (void)pal_os_event; +} + +/** + * @} + */ diff --git a/src/optiga-pal/pal_os_lock.c b/src/optiga-pal/pal_os_lock.c new file mode 100644 index 000000000..4d7de3918 --- /dev/null +++ b/src/optiga-pal/pal_os_lock.c @@ -0,0 +1,88 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_os_lock.c + * + * \brief This file implements the platform abstraction layer APIs for os locks (e.g. semaphore). + * + * \ingroup grPAL + * + * @{ + */ + +#include "optiga/pal/pal_os_lock.h" + +void pal_os_lock_create(pal_os_lock_t* p_lock, uint8_t lock_type) +{ + p_lock->type = lock_type; + p_lock->lock = 0; +} + +void pal_os_lock_destroy(pal_os_lock_t* p_lock) +{ + (void)p_lock; +} + +pal_status_t pal_os_lock_acquire(pal_os_lock_t* p_lock) +{ + pal_status_t return_status = PAL_STATUS_FAILURE; + + // Below is a sample shared resource acquire mechanism + // it doesn't provide a guarantee against a deadlock + if (!(p_lock->lock)) { + p_lock->lock++; + if (1 != p_lock->lock) { + p_lock->lock--; + } + return_status = PAL_STATUS_SUCCESS; + } + return return_status; +} + +void pal_os_lock_release(pal_os_lock_t* p_lock) +{ + // Below is a sample shared resource acquire mechanism + // it doesn't provide a guarantee against a deadlock + if (0 != p_lock->lock) { + p_lock->lock--; + } +} + +void pal_os_lock_enter_critical_section() +{ + // For safety critical systems it is recommended to implement a critical section entry +} + +void pal_os_lock_exit_critical_section() +{ + // For safety critical systems it is recommended to implement a critical section exit +} + +/** + * @} + */ diff --git a/src/optiga-pal/pal_os_memory.c b/src/optiga-pal/pal_os_memory.c new file mode 100644 index 000000000..8a12df6c7 --- /dev/null +++ b/src/optiga-pal/pal_os_memory.c @@ -0,0 +1,31 @@ +#include "optiga/pal/pal_os_memory.h" +#include "util.h" +#include + +void* pal_os_malloc(uint32_t block_size) +{ + void* res = malloc(block_size); + traceln("Allocating %lu at %p", block_size, res); + return res; +} + +void* pal_os_calloc(uint32_t number_of_blocks, uint32_t block_size) +{ + return calloc(number_of_blocks, block_size); +} + +void pal_os_free(void* block) +{ + traceln("Freeing %p", block); + free(block); +} + +void pal_os_memcpy(void* p_destination, const void* p_source, uint32_t size) +{ + memcpy(p_destination, p_source, size); +} + +void pal_os_memset(void* p_buffer, uint32_t value, uint32_t size) +{ + memset(p_buffer, value, size); +} diff --git a/src/optiga-pal/pal_os_timer.c b/src/optiga-pal/pal_os_timer.c new file mode 100644 index 000000000..a47ca1180 --- /dev/null +++ b/src/optiga-pal/pal_os_timer.c @@ -0,0 +1,88 @@ +/** + * \copyright + * MIT License + * + * Copyright (c) 2019 Infineon Technologies AG + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE + * + * \endcopyright + * + * \author Infineon Technologies AG + * + * \file pal_os_timer.c + * + * \brief This file implements the platform abstraction layer APIs for timer. + * + * \ingroup grPAL + * + * @{ + */ + +#include "optiga/pal/pal_os_timer.h" +#include "hal_delay.h" +#include "hal_timer.h" +#include "hpl_time_measure.h" +#include "util.h" +extern struct timer_descriptor TIMER_0; + +static volatile uint32_t g_ms_count = 0; +static struct timer_task scheduler; + +uint32_t pal_os_timer_get_time_in_microseconds(void) +{ + static uint32_t count = 0; + // The implementation must ensure that every invocation of this API returns a unique + // value. + return g_ms_count * 1000 + (count++); +} + +uint32_t pal_os_timer_get_time_in_milliseconds(void) +{ + return g_ms_count; +} + +void pal_os_timer_delay_in_milliseconds(uint16_t milliseconds) +{ + delay_ms(milliseconds); +} + +static void _timer_cb(const struct timer_task* const timer_task) +{ + (void)timer_task; + g_ms_count++; +} + +pal_status_t pal_timer_init(void) +{ + scheduler.interval = 1; + scheduler.cb = _timer_cb; + scheduler.mode = TIMER_TASK_REPEAT; + timer_add_task(&TIMER_0, &scheduler); + return PAL_STATUS_SUCCESS; +} + +pal_status_t pal_timer_deinit(void) +{ + timer_remove_task(&TIMER_0, &scheduler); + return PAL_STATUS_SUCCESS; +} +/** + * @} + */ diff --git a/src/rust/bitbox02-rust/src/hww/api/device_info.rs b/src/rust/bitbox02-rust/src/hww/api/device_info.rs index 41f00227f..b2fa68b7f 100644 --- a/src/rust/bitbox02-rust/src/hww/api/device_info.rs +++ b/src/rust/bitbox02-rust/src/hww/api/device_info.rs @@ -29,6 +29,7 @@ pub fn process() -> Result { securechip_model: match securechip::model()? { securechip::Model::ATECC_ATECC608A => "ATECC608A".into(), securechip::Model::ATECC_ATECC608B => "ATECC608B".into(), + securechip::Model::OPTIGA_TRUST_M_V3 => "OPTIGA_TRUST_M_V3".into(), }, })) } diff --git a/src/securechip/securechip.c b/src/securechip/securechip.c index 1fe64b57d..1c9e06e95 100644 --- a/src/securechip/securechip.c +++ b/src/securechip/securechip.c @@ -16,6 +16,7 @@ #include "atecc/atecc.h" #include "hardfault.h" #include "memory/memory_shared.h" +#include "optiga-pal/optiga.h" typedef struct { int (*setup)(const securechip_interface_functions_t* fns); @@ -44,7 +45,10 @@ bool securechip_init(void) { switch (memory_get_securechip_type()) { case MEMORY_SECURECHIP_TYPE_OPTIGA: - Abort("Not implemented"); + _fns.setup = optiga_setup; + _fns.kdf = optiga_hmac; + _fns.random = optiga_random; + _fns.model = optiga_model; break; case MEMORY_SECURECHIP_TYPE_ATECC: default: diff --git a/src/securechip/securechip.h b/src/securechip/securechip.h index f471c395d..70f49c61e 100644 --- a/src/securechip/securechip.h +++ b/src/securechip/securechip.h @@ -161,6 +161,7 @@ USE_RESULT bool securechip_u2f_counter_inc(uint32_t* counter); typedef enum { ATECC_ATECC608A, ATECC_ATECC608B, + OPTIGA_TRUST_M_V3, } securechip_model_t; /**