CDC Badge OS
Firmware for the CDC Badge v1.0 hardware security key
Loading...
Searching...
No Matches
TropicSlotMap.cpp
Go to the documentation of this file.
2#include "cdc_core/Hash.h"
3#include "tropic_slot_map.h"
4#include "cdc_log.h"
5#include <cstring>
6
7static const char* TAG = "SlotMap";
8
9namespace cdc::core {
10
13 const char* moduleName;
14 uint8_t moduleId;
15 uint16_t start;
16 uint16_t end;
17};
18
19#define BUILD_ECC_ENTRY(name, id, start, end) \
20 { TropicSlotMap::SlotType::ECC, name, static_cast<uint8_t>(id), \
21 static_cast<uint16_t>(start), static_cast<uint16_t>(end) },
22#define BUILD_RMEM_ENTRY(name, id, start, end) \
23 { TropicSlotMap::SlotType::RMEM, name, static_cast<uint8_t>(id), \
24 static_cast<uint16_t>(start), static_cast<uint16_t>(end) },
25
30
31static constexpr size_t kSlotMapCount = sizeof(kSlotMap) / sizeof(kSlotMap[0]);
32
37TropicSlotMap& TropicSlotMap::instance() {
38 static TropicSlotMap inst;
39 return inst;
40}
41
45TropicSlotMap::TropicSlotMap() {
46 validateOnce();
47}
48
53void TropicSlotMap::setError(const char* message) {
54 if (!valid_) return;
55 valid_ = false;
56 errorMessage_ = message;
57 LOG_E(TAG, "%s", message ? message : "slot map error");
58}
59
63void TropicSlotMap::validateOnce() {
64 valid_ = true;
65 errorMessage_ = nullptr;
66
67 for (size_t i = 0; i < kSlotMapCount; i++) {
68 const auto& a = kSlotMap[i];
69 if (!a.moduleName || a.moduleName[0] == '\0') {
70 setError("slot map entry with empty module name");
71 return;
72 }
73 if (a.moduleId == MODULE_ID_UNKNOWN) {
74 setError("slot map entry with unknown module id");
75 return;
76 }
77 if (a.start > a.end) {
78 setError("slot map range has start > end");
79 return;
80 }
81 if (a.start == 0 || a.end == 0) {
82 setError("slot map range uses reserved slot 0");
83 return;
84 }
85 if (a.type == SlotType::ECC) {
86 if (a.start < cdc::tropic_map::ECC_SLOT_MIN ||
88 setError("slot map ECC range out of bounds");
89 return;
90 }
92 setError("slot map ECC range includes reserved slot");
93 return;
94 }
95 } else {
96 if (a.start < cdc::tropic_map::RMEM_SLOT_MIN ||
98 setError("slot map RMEM range out of bounds");
99 return;
100 }
103 setError("slot map RMEM range below minimum allowed");
104 return;
105 }
106 }
107
108 for (size_t j = i + 1; j < kSlotMapCount; j++) {
109 const auto& b = kSlotMap[j];
110 if (!b.moduleName) continue;
111
112 if (a.type == b.type) {
113 bool overlap = !(a.end < b.start || b.end < a.start);
114 if (overlap) {
115 setError("slot map overlap detected");
116 return;
117 }
118 }
119
120 if (strcmp(a.moduleName, b.moduleName) == 0 && a.type == b.type) {
121 setError("slot map duplicate module/type entry");
122 return;
123 }
124
125 if (a.moduleId == b.moduleId &&
126 strcmp(a.moduleName, b.moduleName) != 0) {
127 setError("slot map module id used by multiple names");
128 return;
129 }
130 }
131 }
132}
133
141bool TropicSlotMap::getRangeByName(const char* moduleName, SlotType type, SlotRange* out) const {
142 if (!moduleName || !out) return false;
143 for (size_t i = 0; i < kSlotMapCount; i++) {
144 const auto& entry = kSlotMap[i];
145 if (entry.type != type) continue;
146 if (strcmp(entry.moduleName, moduleName) != 0) continue;
147 out->valid = true;
148 out->type = entry.type;
149 out->moduleName = entry.moduleName;
150 out->moduleId = entry.moduleId;
151 out->start = entry.start;
152 out->end = entry.end;
153 return true;
154 }
155 return false;
156}
157
166 if (!out) return false;
167 for (size_t i = 0; i < kSlotMapCount; i++) {
168 const auto& entry = kSlotMap[i];
169 if (entry.type != type) continue;
170 if (entry.moduleId != moduleId) continue;
171 out->valid = true;
172 out->type = entry.type;
173 out->moduleName = entry.moduleName;
174 out->moduleId = entry.moduleId;
175 out->start = entry.start;
176 out->end = entry.end;
177 return true;
178 }
179 return false;
180}
181
185void TropicSlotMap::forEachRange(SlotType type, RangeCallback cb, void* user) const {
186 if (!cb) return;
187 for (size_t i = 0; i < kSlotMapCount; i++) {
188 const auto& entry = kSlotMap[i];
189 if (entry.type != type) continue;
190 SlotRange r;
191 r.valid = true;
192 r.type = entry.type;
193 r.moduleName = entry.moduleName;
194 r.moduleId = entry.moduleId;
195 r.start = entry.start;
196 r.end = entry.end;
197 cb(r, user);
198 }
199}
200
207bool TropicSlotMap::isRmemAllowedForModuleId(uint16_t slot, uint8_t moduleId) const {
208 SlotRange range;
210 return false;
211 }
212 return slot >= range.start && slot <= range.end;
213}
214
219uint16_t TropicSlotMap::rmemMax() const {
221}
222
229 auto mix = [&hash](uint32_t v) {
231 };
232
240
241 for (size_t i = 0; i < kSlotMapCount; i++) {
242 const auto& entry = kSlotMap[i];
243 mix(static_cast<uint32_t>(entry.type));
244 mix(entry.moduleId);
245 mix(entry.start);
246 mix(entry.end);
247 }
248
249 return hash;
250}
251
252} // namespace cdc::core
static const char * TAG
Centralized non-cryptographic hash utilities.
#define BUILD_ECC_ENTRY(name, id, start, end)
#define BUILD_RMEM_ENTRY(name, id, start, end)
uint8_t moduleId
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_E(tag, fmt,...)
Definition cdc_log.h:145
void(*)(const SlotRange &range, void *user) RangeCallback
static TropicSlotMap & instance()
Returns singleton Tropic slot-map instance.
uint16_t rmemMax() const
Returns maximum RMEM slot index.
void forEachRange(SlotType type, RangeCallback cb, void *user) const
Iterates configured slot ranges of the given type in declaration order.
bool isRmemAllowedForModuleId(uint16_t slot, uint8_t moduleId) const
Checks whether RMEM slot is allowed for given module id.
bool getRangeByModuleId(uint8_t moduleId, SlotType type, SlotRange *out) const
Retrieves slot range by module id and slot type.
uint32_t computeMapSignature() const
Computes deterministic signature over static map constants and ranges.
bool getRangeByName(const char *moduleName, SlotType type, SlotRange *out) const
Retrieves slot range by module name and slot type.
static constexpr uint32_t FNV1A_32_OFFSET_BASIS
FNV-1a 32-bit constants (Fowler/Noll/Vo).
Definition Hash.h:20
void fnv1a_mix_u32(uint32_t &hash, uint32_t value)
Mixes a 32-bit word into a running FNV-1a 32-bit hash.
Definition Hash.h:41
static constexpr size_t kSlotMapCount
static const SlotMapEntry kSlotMap[]
static constexpr uint16_t RMEM_SLOT_MAX
static constexpr uint8_t ECC_SLOT_MAX
static constexpr uint16_t RMEM_SLOT_MIN
static constexpr uint16_t RMEM_SLOT_RESERVED
static constexpr uint8_t ECC_SLOT_RESERVED
static constexpr uint8_t ECC_SLOT_MIN
static constexpr uint16_t RMEM_SLOT_MIN_ALLOC
TropicSlotMap::SlotType type
#define TROPIC_ECC_SLOT_MAP(X)
#define TROPIC_RMEM_SLOT_MAP(X)
#define MODULE_ID_UNKNOWN