cryptnox-pos
1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
Toggle main menu visibility
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
18
static
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
26
typedef
struct
{
27
char
where
[24];
28
uint32_t
at_count
;
29
}
anom_entry_t
;
30
static
anom_entry_t
s_ring
[
ANOM_RING
];
31
static
uint32_t
s_ring_head
= 0U;
32
33
/* Dual counter — a glitch on the counter itself is also an anomaly (§3.3). */
34
static
volatile
uint32_t
s_ctr
= 0U;
35
static
volatile
uint32_t
s_ctr_echo
= 0U;
36
static
bool
s_loaded
=
false
;
37
44
static
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
71
static
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
89
static
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
99
void
pos_handle_anomaly
(
const
char
*where)
100
{
101
ensure_loaded
();
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
112
anom_entry_t
*e = &
s_ring
[
s_ring_head
%
ANOM_RING
];
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 :
"?"
);
118
nvs_store_ctr
(
s_ctr
);
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
125
uint32_t
pos_anomaly_count
(
void
)
126
{
127
ensure_loaded
();
128
return
s_ctr
;
129
}
TAG
static const char *const TAG
Definition
eth_rpc.cpp:33
s_ring_head
static uint32_t s_ring_head
Definition
hardening.cpp:31
K_ANOMALY
#define K_ANOMALY
Definition
hardening.cpp:21
ensure_loaded
static void ensure_loaded(void)
Lazily seed both counter copies from NVS on first use.
Definition
hardening.cpp:89
NS_HARDEN
#define NS_HARDEN
Definition
hardening.cpp:20
s_ctr_echo
static volatile uint32_t s_ctr_echo
Definition
hardening.cpp:35
nvs_store_ctr
static void nvs_store_ctr(uint32_t v)
Persist the anomaly counter to NVS.
Definition
hardening.cpp:71
s_ctr
static volatile uint32_t s_ctr
Definition
hardening.cpp:34
s_loaded
static bool s_loaded
Definition
hardening.cpp:36
ANOM_RING
#define ANOM_RING
Definition
hardening.cpp:25
pos_anomaly_count
uint32_t pos_anomaly_count(void)
Persisted total anomaly count (for the optional maintenance view).
Definition
hardening.cpp:125
nvs_load_ctr
static uint32_t nvs_load_ctr(void)
Read the persisted anomaly counter from NVS.
Definition
hardening.cpp:44
pos_handle_anomaly
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
s_ring
static anom_entry_t s_ring[ANOM_RING]
Definition
hardening.cpp:30
hardening.h
Decision-integrity primitives (see docs/HARDENING.md §3, §4).
anom_entry_t
Definition
hardening.cpp:26
anom_entry_t::at_count
uint32_t at_count
Definition
hardening.cpp:28
anom_entry_t::where
char where[24]
Definition
hardening.cpp:27
main
hardening.cpp
Generated by
1.17.0