10static const char*
TAG =
"PASSWORD";
33static void copyText(
char* dst,
size_t dstSize,
const char* src) {
34 if (!dst || dstSize == 0)
return;
39 strncpy(dst, src, dstSize - 1);
40 dst[dstSize - 1] =
'\0';
48 static PasswordStore inst;
67 if (!out)
return false;
68 if (!slots_.hasSlotRange())
return false;
69 uint16_t physSlot = 0;
73 if (!se)
return false;
75 cdc::hal::ISecureElement::RMemHeader header = {};
77 uint16_t payloadLen = 0;
79 auto res = se->rmemReadWithHeader(physSlot, &header,
80 reinterpret_cast<uint8_t*
>(&payload),
81 sizeof(payload), &payloadLen);
86 if (header.moduleId != slots_.moduleId()) {
90 memset(out, 0,
sizeof(*out));
91 if (payload.
title[0]) {
111 if (!slots_.hasSlotRange())
return false;
113 if (!slots_.findFreeSlot(&slot)) {
114 LOG_W(
TAG,
"No free password slots");
127 if (entry.
title[0]) {
130 copyText(headerName,
sizeof(headerName),
"Password");
134 if (!se)
return false;
136 auto res = se->rmemWriteWithHeader(
141 reinterpret_cast<const uint8_t*
>(&payload),
146 LOG_E(
TAG,
"Failed to write slot %u (SeResult=%u, payload=%u bytes)",
147 slot,
static_cast<unsigned>(res),
148 static_cast<unsigned>(
sizeof(payload)));
164 if (!slots_.hasSlotRange())
return false;
165 uint16_t physSlot = 0;
177 if (entry.
title[0]) {
180 copyText(headerName,
sizeof(headerName),
"Password");
184 if (!se)
return false;
186 auto res = se->rmemWriteWithHeader(
191 reinterpret_cast<const uint8_t*
>(&payload),
196 LOG_E(
TAG,
"Failed to write slot %u", slot);
211 if (!slots_.hasSlotRange())
return false;
212 uint16_t physSlot = 0;
216 if (!se)
return false;
218 auto res = se->rmemErase(physSlot);
233int PasswordStore::compareTitles(
const char* a,
const char* b) {
234 if (!a)
return b ? -1 : 0;
237 int ca = *a ? std::tolower(
static_cast<unsigned char>(*a)) : 0;
238 int cb = *b ? std::tolower(
static_cast<unsigned char>(*b)) : 0;
239 if (ca != cb)
return ca - cb;
254 if (!entries || !countOut)
return false;
255 if (!slots_.hasSlotRange())
return false;
261 } ctx = { entries, countOut, maxEntries };
265 auto* ctx =
static_cast<Ctx*
>(user);
266 if (!ctx || !ctx->entries || !ctx->count)
return;
267 if (*ctx->count >= ctx->max)
return;
269 uint16_t logical = 0;
272 uint16_t idx = *ctx->count;
273 copyText(ctx->entries[idx].title,
sizeof(ctx->entries[idx].title), entry.name);
274 ctx->entries[idx].slot = logical;
279 slots_.moduleId(), slots_.rmemStart(), slots_.rmemEnd(), cb, &ctx);
282 return PasswordStore::compareTitles(a.
title, b.
title) < 0;
299 if (!title || !logicalSlotOut)
return false;
300 if (!slots_.hasSlotRange())
return false;
306 } ctx = { title, 0,
false };
309 auto* c =
static_cast<Ctx*
>(user);
310 if (c->found)
return;
311 if (PasswordStore::compareTitles(entry.name, c->target) == 0) {
312 uint16_t logical = 0;
321 slots_.moduleId(), slots_.rmemStart(), slots_.rmemEnd(), cb, &ctx);
323 if (!ctx.found)
return false;
324 *logicalSlotOut = ctx.slot;
334 if (!logicalSlotOut)
return false;
335 uint16_t physSlot = 0;
336 if (!slots_.findFreeSlot(&physSlot))
return false;
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_W(tag, fmt,...)
#define LOG_E(tag, fmt,...)
bool writeSlot(uint8_t moduleId, uint16_t slot, const char *name, uint8_t flags)
Writes or updates cached metadata entry for one slot.
bool eraseSlot(uint8_t moduleId, uint16_t slot)
Clears cached metadata entry for one slot.
static TropicStorage & instance()
Returns singleton instance of TROPIC metadata cache manager.
bool forEachSlot(uint8_t moduleId, SlotCallback cb, void *ctx)
Iterates all cached slots for one module across its allowed range.
static constexpr uint8_t RMEM_NAME_LEN
bool toPhysicalSlot(uint16_t logicalIndex, uint16_t *slotOut) const
static constexpr uint8_t PASSWORD_LEN
bool updateEntry(uint16_t slot, const PasswordEntry &entry)
Updates existing password entry.
static constexpr uint8_t TITLE_LEN
bool addEntry(const PasswordEntry &entry)
Adds a new password entry into first free slot.
static constexpr size_t NOTES_LEN
bool findFreeLogicalSlot(uint16_t *logicalSlotOut) const
Finds first free logical slot in this module's range.
static constexpr uint8_t USERNAME_LEN
static PasswordStore & instance()
Returns singleton password store instance.
bool listEntriesSorted(EntryIndex *entries, uint16_t maxEntries, uint16_t *countOut) const
Lists entries sorted alphabetically by title.
bool deleteEntry(uint16_t slot)
Deletes entry at logical slot index.
static constexpr uint8_t URL_LEN
bool toLogicalSlot(uint16_t slot, uint16_t *logicalIndexOut) const
static constexpr size_t PAYLOAD_MAX
bool findByTitle(const char *title, uint16_t *logicalSlotOut) const
Finds the logical slot of an entry with a matching title.
bool readEntry(uint16_t slot, PasswordEntry *out) const
Reads one password entry from secure-element storage.
void setSlotRange(const cdc::core::IModule::SlotRange &range)
Configures logical-to-physical slot mapping for password entries.
ISecureElement * getSecureElementInstance()
Returns singleton secure-element stub instance.
static void copyText(char *dst, size_t dstSize, const char *src)
Copies text into bounded destination buffer.
char password[PASSWORD_PASSWORD_LEN+1]
char url[PASSWORD_URL_LEN+1]
char title[PASSWORD_TITLE_LEN+1]
char notes[PASSWORD_NOTES_LEN+1]
char username[PASSWORD_USERNAME_LEN+1]
char url[PasswordStore::URL_LEN]
char password[PasswordStore::PASSWORD_LEN]
char notes[PasswordStore::NOTES_LEN]
char username[PasswordStore::USERNAME_LEN]
char title[PasswordStore::TITLE_LEN]