SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
Loading...
Searching...
No Matches
TESAIoT HSM (libbento_hsm.a)

Topics

 Chip gate & manager
 Touch holds
 Enrolment & Protected Update publish
 State & correlation
 Isolated test
 Usage notes

Detailed Description

The archive exports exactly 18 functions (dist/tesaiot_hsm/api.txt), all declared in the hand-written tesaiot_hsm_api.h — the editable declaration home, checked against api.txt on every package run. They are defined in three archived files (tesaiot_optiga_manager.c, tesaiot_optiga_trust_m.c, tesaiot_protected_update_isolated.c — dist/tesaiot_hsm/PROVENANCE.txt), none of which ships as source. The ~52 other functions the older tesaiot_optiga*.h headers declare are the enrolment and Protected Update machinery; they are renamed inside the archive precisely so a consumer cannot reach them.

Variant
mtb-mpy and mtb-only

Unchanged between variants: variants/mtb-only.mk:14 — "OPTIGA CSR and Protected Update. libbento_hsm.a needs zero MPY symbols."

The six weak-consumed symbols — NULL-check contract

dist/tesaiot_hsm/overridable.txt is empty: nothing in this archive is weak-overridable — no symbol here is a hook a consumer implements. But six of the 18 are consumed as weak symbols by the shipped callers, because they link only under ENABLE_OPTIGA_CLM=1 (default 1). A caller that must build with CLM off declares them __attribute__((weak)) and NULL-checks the function pointer before every call:

Function Shipped weak-consumption site
publish_csr() proj_cm33_ns/ipc_hsm_handler.c:1691-1693 (decl), :2174 (check)
tesaiot_publish_protected_update() ipc_hsm_handler.c:2192
trustm_reset_state() ipc_hsm_handler.c:1966-1968
trustm_current_correlation_id() ipc_hsm_handler.c:1792-1794 — two NULL checks: the pointer, then the returned string
trustm_requested_target_oid() tesaiot_pu_ingest.c:139-144, fallback 0xE0E1
trustm_requested_anchor_oid() tesaiot_pu_ingest.c:133-137, fallback 0xE0E8
extern int publish_csr(uint8_t *csr, size_t csr_length, uint16_t target_oid,
uint16_t trust_anchor_oid, uint32_t payload_version)
__attribute__((weak));

The other twelve are strong everywhere and need no such guard.

Three rules that recur on every topic

  1. optiga_chip_enter() is NOT an init check. It deliberately returns true when the manager was never initialised (tesaiot_optiga_manager.c:157-169). optiga_manager_lock() returns false in that state and is the "is the manager up?" test. Getting this backwards is the documented cause of several ungated-access defects.
  2. Touch holds are counted; a raw IPC_CMD_TOUCH_RESUME is banned. The secure element and the CM55 touch controller share one I2C bus. Every hold nests (s_touch_holds) and every hold needs exactly one release on every exit path. Sending the raw resume command instead of optiga_manager_touch_release() makes CM55 set touch_disabled = false unconditionally, cancelling another task's hold — OPTIGA_COMMS_ERROR (0x0102) (ipc_hsm_handler.c:1393-1405).
  3. The correlation id is the replay defence. The platform retains the last Protected Update bundle and delivers it on every connect. A run is armed by publish_csr() or tesaiot_publish_protected_update() and disarmed only by trustm_reset_state(); while trustm_current_correlation_id() is NULL an inbound bundle must be discarded. Observed three times on 2026-08-07 before the check existed, each silently redoing the previous run.