|
SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
|
Six of the eighteen tesaiot_hsm functions are declared weak by every shipped caller and must be NULL-checked before the call. Why that is, what ENABLE_OPTIGA_CLM controls, what the archive demands from you (consumer_must_provide.txt), and how to see the contract enforce itself by building with CLM off.
proj_cm33_ns/Makefile:143-161:
and :464-475: libbento_hsm.a is on LDLIBS unconditionally — "an archive member is pulled only when something already references it, so with <tt>ENABLE_OPTIGA_CLM</tt> off nothing is extracted." With the flag off, the ingest is not compiled, nothing references the archive's MQTT-side members, and the six symbols below simply do not exist in the link. The shipped callers still compile because they declare them weak.
dist/tesaiot_hsm/overridable.txt is empty — nothing in the archive is weak. The weakness is on the consumer side: shipped callers declare these six __attribute__((weak)) so that a build without the MQTT enrolment path still links:
| Symbol | Declared weak at | Guarded call |
|---|---|---|
| publish_csr | ipc_hsm_handler.c:1691-1693 | ipc_hsm_handler.c if (publish_csr == NULL) |
| tesaiot_publish_protected_update | ipc_hsm_handler.c:1687-1689; modtesaiot.c | both guarded |
| trustm_reset_state | ipc_hsm_handler.c:1715 | if (trustm_reset_state != NULL) |
| trustm_current_correlation_id | ipc_hsm_handler.c:1721 | two NULL checks — pointer, then result |
| trustm_requested_target_oid | tesaiot_pu_ingest.c | wrapped in pu_target_oid() with 0xE0E1 fallback |
| trustm_requested_anchor_oid | tesaiot_pu_ingest.c | wrapped in pu_anchor_oid() with 0xE0E8 fallback |
The declaration:
The double-NULL form for a function that returns a pointer:
First the function pointer (is it linked?), then the returned string (is a request outstanding?). Skipping the first dereferences address zero on a CLM-off build; skipping the second turns "nothing outstanding" into a replay (chapter D2).
The wrapped-accessor form with a default:
Wrap every weak accessor in a local function that supplies the default. Do not scatter != NULL ? f() : default at call sites.
The MicroPython binding does the same, raising instead of returning — tesaiot_protected_update_py() at modtesaiot.c:730-768, marker [hsm_publish_pu_mpy_binding] (mtb-mpy zip only — this file is not in the mtb-only package):
template/lib/tesaiot_hsm/consumer_must_provide.txt is the machine-derived list of symbols the archive references but does not define. Grouped:
If you replace the template's HSM handler or MQTT module, every name on that list must still resolve, with the same semantics. The touch IPC trio in particular: substituting a non-counted resume reintroduces the 0x0102 signature from chapter D1.
What you should observe. Six T symbols. (Glob the ELF path; the TARGET directory name differs between kits.)
What you should observe. The build succeeds — that is the weak declarations working. Run the same nm line: the six names are absent (U/w at most, no T), tesaiot_pu_ingest.o is not in the link, and the [PU-Ingest] strings are gone from the ELF.
Power-cycle after flashing. Home → HSM Security → Enrol Certificate.
What you should observe. The screen shows, without touching the chip:
(ipc_hsm_handler.c, the publish_csr == NULL branch in prov_run_locked.) Then Protected Update:
(the tesaiot_publish_protected_update == NULL branch). On mtb-mpy, tesaiot.protected_update(...) from the REPL raises:
(modtesaiot.c:739-743). Those three strings are the verification for this chapter: each is a NULL-guard refusing, exactly where the table above says it would.
What you should not observe: a HardFault, a dark screen, or a [MQTT] reconnect. The guards run before the platform is reached.
Read a credential slot (WiFi page saved list, or optiga.read_metadata() on mtb-mpy).
What you should observe. It works. optiga_manager_*, optiga_chip_* and the credential IPC do not depend on the flag — the ten D1 functions are pulled from the archive because ipc_hsm_handler.c references them unconditionally. Only the MQTT-side enrolment path is gone.
Flash, power-cycle, and run chapter D2's Step 2 to confirm Enrol proceeds past the guard.
The flag, the six weak declarations, the guards and the refusal strings on the screen are identical on both variants. The OSError refusal is mtb-mpy only — modtesaiot.c is one of the ten files the mtb-only package drops. consumer_must_provide.txt is the same file in both zips; on mtb-only the printf/scanf entries resolve to retarget-io exactly as on mtb-mpy.