cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
Loading...
Searching...
No Matches
hardening.cpp
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 * Copyright (c) 2026 Cryptnox SA
4 */
5
11
12#include "hardening.h"
13
14#include <stdio.h>
15#include "nvs.h"
16#include "esp_log.h"
17
18static const char *const TAG = "harden";
19
20#define NS_HARDEN "harden"
21#define K_ANOMALY "anomaly_ct"
22
23/* In-RAM ring of the most recent anomalies; a technician reads these over the
24 * log on-site. The total count is persisted so it survives reboots. */
25#define ANOM_RING 8U
26typedef struct {
27 char where[24];
28 uint32_t at_count;
31static uint32_t s_ring_head = 0U;
32
33/* Dual counter — a glitch on the counter itself is also an anomaly (§3.3). */
34static volatile uint32_t s_ctr = 0U;
35static volatile uint32_t s_ctr_echo = 0U;
36static bool s_loaded = false;
37
44static uint32_t nvs_load_ctr(void)
45{
46 uint32_t v = 0U;
47 nvs_handle_t h;
48 if (nvs_open(NS_HARDEN, NVS_READONLY, &h) == ESP_OK) {
49 esp_err_t err = nvs_get_u32(h, K_ANOMALY, &v);
50 if (err == ESP_ERR_NVS_NOT_FOUND) {
51 /* First boot: no anomaly has ever been recorded. */
52 } else if (err != ESP_OK) {
53 /* The entry exists but failed its CRC — the history is lost, and
54 * that loss is itself worth surfacing to the technician. */
55 ESP_LOGE(TAG, "anomaly counter unreadable (%s), restarting from 0",
56 esp_err_to_name(err));
57 v = 0U;
58 }
59 nvs_close(h);
60 } else {
61 ESP_LOGW(TAG, "anomaly counter: nvs_open failed");
62 }
63 return v;
64}
65
71static void nvs_store_ctr(uint32_t v)
72{
73 nvs_handle_t h;
74 if (nvs_open(NS_HARDEN, NVS_READWRITE, &h) == ESP_OK) {
75 (void)nvs_set_u32(h, K_ANOMALY, v);
76 (void)nvs_commit(h);
77 nvs_close(h);
78 } else {
79 ESP_LOGW(TAG, "anomaly counter: nvs_open failed");
80 }
81}
82
89static void ensure_loaded(void)
90{
91 if (!s_loaded) {
92 const uint32_t v = nvs_load_ctr();
93 s_ctr = v;
94 s_ctr_echo = v;
95 s_loaded = true;
96 }
97}
98
99void pos_handle_anomaly(const char *where)
100{
102
103 s_ctr += 1U;
104 s_ctr_echo += 1U;
105 if (s_ctr != s_ctr_echo) {
106 /* the counter got glitched too — take the higher of the two */
107 const uint32_t hi = (s_ctr > s_ctr_echo) ? s_ctr : s_ctr_echo;
108 s_ctr = hi;
109 s_ctr_echo = hi;
110 }
111
113 s_ring_head++;
114 (void)snprintf(e->where, sizeof(e->where), "%s", (where != NULL) ? where : "?");
115 e->at_count = s_ctr;
116
117 ESP_LOGE(TAG, "anomaly #%u: %s", (unsigned)s_ctr, (where != NULL) ? where : "?");
119
120 /* Fail-closed for the CURRENT transaction only: the caller's decision
121 * returns FALSE32 and the UI shows FAILED. No server, no brick — the
122 * persisted counter lets a technician inspect anomalies on-site (§3.3). */
123}
124
125uint32_t pos_anomaly_count(void)
126{
128 return s_ctr;
129}
static const char *const TAG
Definition eth_rpc.cpp:33
static uint32_t s_ring_head
Definition hardening.cpp:31
#define K_ANOMALY
Definition hardening.cpp:21
static void ensure_loaded(void)
Lazily seed both counter copies from NVS on first use.
Definition hardening.cpp:89
#define NS_HARDEN
Definition hardening.cpp:20
static volatile uint32_t s_ctr_echo
Definition hardening.cpp:35
static void nvs_store_ctr(uint32_t v)
Persist the anomaly counter to NVS.
Definition hardening.cpp:71
static volatile uint32_t s_ctr
Definition hardening.cpp:34
static bool s_loaded
Definition hardening.cpp:36
#define ANOM_RING
Definition hardening.cpp:25
uint32_t pos_anomaly_count(void)
Persisted total anomaly count (for the optional maintenance view).
static uint32_t nvs_load_ctr(void)
Read the persisted anomaly counter from NVS.
Definition hardening.cpp:44
void pos_handle_anomaly(const char *where)
Report an anomaly: bump a self-checked persisted counter, log it, and keep a local ring buffer for on...
Definition hardening.cpp:99
static anom_entry_t s_ring[ANOM_RING]
Definition hardening.cpp:30
Decision-integrity primitives (see docs/HARDENING.md §3, §4).
Definition hardening.cpp:26
uint32_t at_count
Definition hardening.cpp:28
char where[24]
Definition hardening.cpp:27