SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
Loading...
Searching...
No Matches
bento_devmode.h
Go to the documentation of this file.
1/*******************************************************************************
2 * File Name: bento_devmode.h
3 *
4 * Description: Developer-mode unlock state for the Bento Desktop Buddy bridge.
5 * Gates bento.exec and other privileged verbs behind an
6 * HMAC-SHA256 challenge/response. See SPEC §5.5 + §7.3.
7 *
8 * Lifecycle:
9 * 1. Desktop sends bento.devmode.nonce → firmware returns a
10 * fresh 16-byte nonce (64-ms TTL per SPEC).
11 * 2. Desktop computes HMAC-SHA256(shared_secret, nonce) and
12 * sends bento.devmode.unlock.
13 * 3. Firmware verifies and sets the unlocked flag.
14 * 4. bento.devmode.lock clears the flag.
15 *
16 * Shared secret storage:
17 * Primary — OPTIGA Trust M arbitrary-data slot 0xE120
18 * Fallback — RAM-only, regenerated every boot (means desktop
19 * must re-provision after every reflash; see
20 * ISSUES.md ISSUE-006).
21 * v1 uses the RAM-only fallback unconditionally; OPTIGA
22 * persistence lands in a follow-up along with the proper
23 * first-pair provisioning UX (SPEC §7.3 steps 1-4).
24 *
25 ******************************************************************************/
26
27#ifndef BENTO_DEVMODE_H
28#define BENTO_DEVMODE_H
29
30#include <stdbool.h>
31#include <stddef.h>
32#include <stdint.h>
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38#define BENTO_DEVMODE_NONCE_LEN (16u)
39#define BENTO_DEVMODE_SECRET_LEN (32u)
40#define BENTO_DEVMODE_HMAC_LEN (32u) /* SHA-256 output */
41#define BENTO_DEVMODE_NONCE_TTL_MS (60000u)
42
43/* Initialise the secret (RAM-only fallback — seeds from boot entropy +
44 * TickCount on first call). Idempotent. */
46
47/* Generate a fresh 16-byte nonce and return it via `nonce_out`. Overwrites
48 * any previous pending nonce (only one in-flight challenge). Sets the
49 * internal ttl clock. */
51
52/* Verify an HMAC-SHA256 hex string against the current pending nonce + the
53 * shared secret. Returns true on match AND ttl window unexpired, in which
54 * case the internal unlocked flag is set. Consumes the nonce on any call
55 * (one-shot, prevents replay). */
56bool bento_devmode_unlock(const char *hmac_hex, size_t hmac_hex_len);
57
58/* Manually clear the unlocked flag. */
60
61/* Query whether exec is currently permitted. */
63
64/* Expose the provisioning secret as a hex string for the first-pair
65 * emit-once flow (SPEC §7.3 step 2). Returns length written (64 hex chars
66 * + NUL) or 0 if the out buffer is too small. RAM-only fallback; the
67 * caller must NOT log this to UART. */
68size_t bento_devmode_secret_hex(char *out, size_t out_sz);
69
70/* Emit `{"evt":"bento.devmode.provision","secret":"<64 hex>"}` over BLE
71 * NUS once per boot so the desktop side can store the secret in its
72 * keychain. Without this emit the desktop holds a randomly-generated
73 * placeholder secret that will never match firmware-side state and
74 * every `bento.devmode.unlock` will return `not_permitted`. Wired into
75 * ble_nus_lazy.c's CONNECTED transition, paired with
76 * `bento_fw_emit_boot_complete()`. Internally guards with a static
77 * "already sent this boot" flag — multiple BLE connect/disconnect
78 * cycles within one boot will not re-send (the secret in firmware
79 * doesn't change without a reset). */
81
82/* First 4 bytes of SHA-256(secret) as 8 hex chars + NUL — safe to log,
83 * used to cross-check that desktop and firmware are operating on the
84 * same secret without leaking it. Matches the `secret_fp` tracing on
85 * the Rust side (`verbs/devmode.rs::unlock`). */
86size_t bento_devmode_secret_fp_hex(char *out, size_t out_sz);
87
88#ifdef __cplusplus
89}
90#endif
91
92#endif /* BENTO_DEVMODE_H */
#define BENTO_DEVMODE_NONCE_LEN
Definition bento_devmode.h:38
void bento_devmode_lock(void)
Clear the unlocked flag.
bool bento_devmode_is_unlocked(void)
Whether privileged verbs (bento.exec) are permitted right now.
void bento_devmode_nonce_issue(uint8_t nonce_out[BENTO_DEVMODE_NONCE_LEN])
Fill a fresh 16-byte nonce, overwriting any pending one; starts the TTL clock.
size_t bento_devmode_secret_hex(char *out, size_t out_sz)
The secret as 64 hex chars + NUL, or 0 if the buffer is too small; never log it to UART.
bool bento_devmode_unlock(const char *hmac_hex, size_t hmac_hex_len)
Verify the HMAC against the pending nonce; consumes the nonce on any call (one-shot).
size_t bento_devmode_secret_fp_hex(char *out, size_t out_sz)
First 4 bytes of SHA-256(secret) as 8 hex chars + NUL — safe to log.
void bento_devmode_emit_provision(void)
Emit the provision event once per boot on the CONNECTED transition; a failed send retries.
void bento_devmode_init(void)
Idempotent; seeds the 32-byte RAM secret. Every public devmode entry self-calls it.