2. Understanding Libtropic¶
This chapter is a short TL;DR that helps you get oriented quickly so you can continue with the next tutorials. It intentionally links to deeper reference pages instead of duplicating them.
If you are interested in details about the TROPIC01 chip itself, refer to the TROPIC01 repository, where we provide datasheets and a documentation of the low-level user API.
Which version of the TROPIC01 Datasheet / User API should I use?
There are several versions of the documents. The right version depends on the TROPIC01 Application Firmware version. This is not relevant for the model (use the latest), but it matters for the real chip. You will learn how to read the Application Firmware version in the tutorial for each platform, based on which you can select the right document version.
Communication Layers¶
Libtropic communicates with TROPIC01 using a layered protocol described in the reference architecture page.
- Read: Libtropic Architecture
The practical takeaway:
- L1 (Layer 1) is a raw communication. Part of this layer is implemented in Libtropic core, part in the Hardware Abstraction Layer (explained below) of the platform.
- You will normally never send raw L1 data manually when using Libtropic.
- L2 (Layer 2) is an unencrypted layer. It is used for reading chip information and setup tasks (including setting up L3 and firmware update).
- Unit of communication is a frame. Libtropic sends Requests and receives Responses from TROPIC01.
- L3 (Layer 3) is encrypted and requires an established Secure Channel Session. Majority of TROPIC01 functionality is available over L3 only.
- Unit of communication is a packet. Libtropic sends Commands and receives Results from TROPIC01.
If you’re unsure which API call is L2 vs L3, the function naming and tutorial text usually hint at it (e.g., “L2 Request”, “L3 Command”), and the Doxygen API reference is the ultimate source.
- Read: API reference
Libtropic Architecture in 30 Seconds¶
At a high level:
- Core: Public API functions are in
include/libtropic.hand implemented insrc/.- Refer to: API reference
- HAL (hardware abstraction layer for the host platform) lives in
hal/and provides the low-level transport (SPI on embedded targets, TCP to the model, etc.).- It allows us to run Libtropic on various hardware: from Linux computers to ESP32 microcontrollers.
- Supported platforms: read Host Platforms
- CAL (cryptography abstraction layer) lives in
cal/and plugs in “Cryptographic Functionality Providers” (CFP).- We need cryptographic operations available in Libtropic to securely communicate with the TROPIC01 on Layer 3 (via the Secure Channel Session, which is encrypted).
- CAL allows us to support multiple “Cryptographic Functionality Providers”, which is our umbrella term for crypto libraries (e.g., MbedTLS, OpenSSL) and hardware crypto accelerators.
- Read more: CFPs
CAL and HAL can be chosen at build time:
- Read: Integrating Libtropic
lt_handle_t: Your per-chip context¶
Almost all Libtropic calls operate on an lt_handle_t. Think of it as a context object for one TROPIC01 instance.
What it contains (simplified):
- L2 state (including a pointer to your HAL device context at
h.l2.device). - L3 state (Secure Channel Session status, an L3 buffer, and a pointer to your CAL/CFP context at
h.l3.crypto_ctx). - A few metadata used by the library.
Practical rules:
- Create one handle per chip (you can have multiple handles if you talk to multiple chips).
- The handle stores pointers to your HAL device structure and CAL/CFP crypto context structure. These objects must stay alive for the whole lifetime of the handle (Libtropic does not copy them).
- Set the pointers before calling
lt_init(&h). - If
lt_init(&h)fails, do not calllt_deinit(&h)(cleanup is handled internally). - As a general C best practice, initialize the handle to zero before filling in pointers (e.g.,
lt_handle_t h = {0};).
Also remember the basic lifecycle:
- Initialize your platform's hardware interfaces (GPIO, SPI, clocks, etc.) and selected CFP.
- Fill your HAL device struct and CAL crypto context struct.
- Point the handle to them (
h.l2.device = ...,h.l3.crypto_ctx = ...). - Call
lt_init(&h)and check the return code. - Use L2 requests and/or establish a Secure Channel Session for L3.
- Call
lt_session_abort(&h)when you are done with L3. - Call
lt_deinit(&h)at the end.
Minimal initialization pattern (illustrative, not a full program):
lt_handle_t h = {0};
lt_dev_<port>_t dev;
lt_ctx_<cfp>_t crypto;
h.l2.device = &dev;
h.l3.crypto_ctx = &crypto;
lt_init(&h);
Where do I see the real initialization?
The contents of lt_dev_<port>_t (HAL device struct) depend on the host platform (SPI pins/speed, TCP host/port for the model, etc.). The easiest way to learn what to fill in is to look at the corresponding example for your platform and find the code that prepares the handle right before lt_init(&h).
For a complete example (including which headers to include and what needs to be initialized inside the HAL device struct), see:
Secure Channel Session Basics (and Pairing Keys)¶
Most interesting TROPIC01 features are accessed via L3 Layer, so you will frequently do this flow:
Terminology note
Secure Channel Session is a protocol used for secure communication on L3 Layer. It is sometimes shortened to Secure Channel or Secure Session.
More information in the TROPIC01 Datasheet.
- Use L2 requests to read info or reboot to the right mode.
- Start a Secure Session with a selected pairing key slot.
- We recommend using our helper
lt_verify_chip_and_start_secure_session, which will handle all L2 communication required to establish a Secure Session.
- We recommend using our helper
- Execute L3 commands.
- Abort the session and deinitialize.
Pairing keys are central to the handshake:
- Read: Default Pairing Keys
Key points:
- New chips come with a factory pairing public key in slot 0 and you use the corresponding private key to establish your first Secure Session.
- A common production pattern is: use slot 0 to bootstrap, then write your own pairing public key to another slot and invalidate slot 0.
- It is also highly recommended to ensure that your TROPIC01 is genuine by verifying whole certificate chain.
- We provide tutorials for certificate verification for Linux: USB DevKit, SPI.
Irreversible Actions
Some operations are one-way. Invalidating pairing slots, erasing certain chip configuration, and similar actions are not reversible on a real chip. On the model, you can recover by restarting the model server (fresh state), but do not rely on that behavior for real hardware.
If Secure Session establishment fails, the most common causes are wrong pairing keys or the chip being in a mode where L3 is unavailable (Start-up Mode):
- Read: FAQ
Debugging and Observability¶
When something doesn’t work, you typically want: (1) clear return codes, (2) logs, (3) a way to inspect the transport.
1) Return Codes¶
Most API functions return a lt_ret_t error code. The FAQ explains common “surprising” root causes (wiring, maintenance mode, etc.):
- Read: FAQ
To translate lt_ret_t error code to a string, use lt_ret_verbose(ret).
2) Logging¶
Libtropic logging is off by default (unless you build tests, which default to Info). Turn it on during evaluation:
- Logging guide
- Configuration (CMake options)
Useful options:
LT_LOG_LVLto increase verbosity.LT_PRINT_SPI_DATAif you need to see low-level traffic.
3) Debuggers and Sanitizers¶
If you suspect memory issues or need to step through code:
On Linux, tests against the model can be run with AddressSanitizer or Valgrind (and you can attach gdb).
Model + gdb
If you want to debug an example/your Libtropic binary against the model, run the model server manually (as in the first tutorial) and then run your binary under gdb.
TROPIC01 Firmware: Keep it up to date¶
On physical TROPIC01 chip, keeping TROPIC01 firmware current matters for reliability, security fixes, and compatibility with newer SDK features.
What to remember:
- Firmware runs on multiple execution engines (CPU FW + SPECT/ECC FW). Libtropic includes the low-level update commands and ships update files.
- A failed or interrupted update can leave the chip in a state where parts of the API are unavailable (often showing up as “Maintenance Mode” symptoms).
- Treat firmware update as a sensitive operation: avoid power loss/disconnects during update.
Where to learn/do it:
- Read: TROPIC01 Firmware
- If Secure Session / commands start failing unexpectedly, also check: FAQ
- Follow the firmware-update tutorials for your platform (for example on Linux USB devkit): Tutorials
Safety: Operations that Can Change Chip State Permanently¶
TROPIC01 exposes powerful commands; some of them intentionally make permanent changes.
Examples you will encounter in these tutorials:
- Pairing key writes/invalidations (used in the hardware-wallet tutorial).
- I-config (I-memory) writes.
- Firmware update (interruption can brick the device; avoid power loss).
When in doubt, use the model!
If you are exploring commands you don’t fully understand yet, prefer using the TROPIC01 Model until you’re confident about the effects.
Where to Go Next¶
- Continue with Hardware Wallet to see secure-session + configuration/pairing key management in practice.
- Keep Libtropic Architecture and Debugging open while working through the rest of the tutorials on the TROPIC01 model.