31constexpr uint8_t PLG_POOL_MODULE_ID = 7;
34constexpr char PLG_ECC_MAP_NS[] =
"plg_ecc_map";
39struct PluginPool { uint16_t start; uint16_t end; };
56bool active_declares_rmem(
const std::string&
name) {
59 for (
const std::string& n : p->manifest().capabilities.rmem) {
60 if (n ==
name)
return true;
65bool any_installed_declares_rmem(
const std::string&
name) {
67 for (
const std::string&
id : mgr.listInstalledIds()) {
68 auto man = mgr.getManifest(
id);
70 for (
const std::string& n : man->capabilities.rmem) {
71 if (n ==
name)
return true;
81void scan_plugin_pool(
const std::string&
name,
int& out_existing,
int& out_reclaimable) {
88 for (uint16_t slot = pool.start; slot <= pool.end; ++slot) {
89 ISecureElement::RMemHeader hdr{};
90 SeResult rr = s->rmemReadWithHeader(slot, &hdr,
nullptr, 0,
nullptr);
92 if (out_reclaimable < 0) out_reclaimable = slot;
95 std::string hdr_name(hdr.name, ::strnlen(hdr.name, RMEM_NAME_FIELD_LEN));
96 if (hdr_name ==
name) {
100 if (out_reclaimable < 0 && !any_installed_declares_rmem(hdr_name)) {
101 out_reclaimable = slot;
106bool active_declares_ecc(
const std::string&
name) {
108 if (!p)
return false;
109 for (
const std::string& n : p->manifest().capabilities.ecc) {
110 if (n ==
name)
return true;
115bool any_installed_declares_ecc(
const std::string&
name) {
117 for (
const std::string&
id : mgr.listInstalledIds()) {
118 auto man = mgr.getManifest(
id);
120 for (
const std::string& n : man->capabilities.ecc) {
121 if (n ==
name)
return true;
131int resolve_ecc_slot(
const std::string&
name,
bool assign) {
133 if (nvs_open(PLG_ECC_MAP_NS, assign ? NVS_READWRITE : NVS_READONLY, &h) != ESP_OK) {
137 int existing = -1, reclaimable = -1;
141 for (uint16_t slot = pool.start; slot <= pool.end; ++slot) {
142 std::snprintf(key,
sizeof(key),
"s%u", slot);
143 size_t sz =
sizeof(stored);
144 if (nvs_get_str(h, key, stored, &sz) != ESP_OK) {
145 if (reclaimable < 0) reclaimable = slot;
148 if (
name == stored) { existing = slot;
break; }
149 if (reclaimable < 0 && !any_installed_declares_ecc(stored)) reclaimable = slot;
155 }
else if (assign && reclaimable >= 0) {
156 std::snprintf(key,
sizeof(key),
"s%u", reclaimable);
157 if (nvs_set_str(h, key,
name.c_str()) == ESP_OK && nvs_commit(h) == ESP_OK) {
159 if (s) s->eccDelete(
static_cast<uint8_t
>(reclaimable));
160 result = reclaimable;
168void free_ecc_mapping(uint8_t slot) {
170 if (nvs_open(PLG_ECC_MAP_NS, NVS_READWRITE, &h) != ESP_OK)
return;
172 std::snprintf(key,
sizeof(key),
"s%u", slot);
173 nvs_erase_key(h, key);
180 case SeResult::OK:
return HOST_OK;
200 std::string name_s(
name);
205 int existing = -1, reclaimable = -1;
206 scan_plugin_pool(name_s, existing, reclaimable);
209 ISecureElement::RMemHeader hdr{};
210 uint16_t payload_len = 0;
211 SeResult rr = s->rmemReadWithHeader(
static_cast<uint16_t
>(existing), &hdr,
212 buf,
static_cast<uint16_t
>(*len), &payload_len);
213 if (rr != SeResult::OK)
return se_rc(rr);
221 std::string name_s(
name);
227 int existing = -1, reclaimable = -1;
228 scan_plugin_pool(name_s, existing, reclaimable);
229 int target = (existing >= 0) ? existing : reclaimable;
232 return se_rc(s->rmemWriteWithHeader(
static_cast<uint16_t
>(target),
236 buf,
static_cast<uint16_t
>(len)));
242 std::string name_s(
name);
247 int existing = -1, reclaimable = -1;
248 scan_plugin_pool(name_s, existing, reclaimable);
251 return se_rc(s->rmemErase(
static_cast<uint16_t
>(existing)));
256 if (!
name)
return false;
257 std::string name_s(
name);
258 if (!active_declares_rmem(name_s))
return false;
259 int existing = -1, reclaimable = -1;
260 scan_plugin_pool(name_s, existing, reclaimable);
261 return existing >= 0;
267 return s ? s->getRmemSlotSize() : 0;
278 int slot = resolve_ecc_slot(n,
true);
280 return se_rc(s->eccGenerate(
static_cast<uint8_t
>(slot), curve_for(
curve)));
295 int slot = resolve_ecc_slot(n,
false);
297 return se_rc(s->eccGetPublicKey(
static_cast<uint8_t
>(slot), pub,
nullptr));
307 int slot = resolve_ecc_slot(n,
false);
309 int rc = se_rc(s->eccDelete(
static_cast<uint8_t
>(slot)));
310 free_ecc_mapping(
static_cast<uint8_t
>(slot));
316 if (!
name)
return false;
318 if (!active_declares_ecc(n))
return false;
320 if (!s)
return false;
321 int slot = resolve_ecc_slot(n,
false);
322 return slot >= 0 && s->eccSlotUsed(
static_cast<uint8_t
>(slot));
332 int slot = resolve_ecc_slot(n,
false);
335 return se_rc(s->ecdsaSign(
static_cast<uint8_t
>(slot), msg, len, sig, &sig_len));
345 int slot = resolve_ecc_slot(n,
false);
347 return se_rc(s->eddsaSign(
static_cast<uint8_t
>(slot), msg, len, sig));
357 uint8_t cap = *len > 0xff ? 0xff :
static_cast<uint8_t
>(*len);
Discovers, loads, runs and unloads WASM plugins on the badge.
Owned WAMR module instance + per-plugin state.
static constexpr uint8_t RMEM_HEADER_MAGIC
char name[cdc::hal::ISecureElement::RMEM_NAME_LEN]
static constexpr uint8_t RMEM_NAME_LEN
static TropicSlotMap & instance()
Returns singleton Tropic slot-map instance.
static PluginManager & instance() noexcept
#define HOST_ECC_NAME_MAX
int host_ecc_delete(const char *name)
Erase the named ECC key and free its pool slot.
int host_se_fw_version(uint8_t *riscv, uint8_t *spect)
Read TROPIC01 firmware versions for the RISC-V CPU and SPECT core.
int host_se_chip_id(uint8_t *serial, size_t *len)
Read the TROPIC01 chip serial / identity blob.
int host_rmem_read_named(const char *name, uint8_t *buf, size_t *len)
Read a named retained-memory slot.
#define HOST_RMEM_NAME_MAX
int host_rmem_write_named(const char *name, const uint8_t *buf, size_t len)
Write up to host_rmem_slot_size() bytes into a named rmem slot.
uint16_t host_rmem_slot_size(void)
Maximum payload bytes per rmem slot.
int host_ecc_pubkey(const char *name, uint8_t *pub, uint8_t)
Export the public key for the named slot.
#define ECC_CURVE_ED25519
int host_ecdsa_sign(const char *name, const uint8_t *msg, size_t len, uint8_t sig[64])
ECDSA-sign msg with the P-256 named key; writes 64-byte raw sig.
bool host_rmem_name_used(const char *name)
True if the named rmem slot currently holds data.
int host_eddsa_sign(const char *name, const uint8_t *msg, size_t len, uint8_t sig[64])
Ed25519-sign msg with the named key; writes 64-byte signature.
int host_rmem_erase_named(const char *name)
Erase the contents of a named rmem slot.
int host_ecc_generate(const char *name, uint8_t curve)
Generate a fresh ECC key for the named slot.
int host_ecc_import(const char *, const uint8_t *, uint8_t)
Import an externally-generated private key for the named slot.
bool host_ecc_exists(const char *name)
True when the named ECC key currently holds a key.
CDC Badge OS plugin host API - canonical C ABI contract.
#define HOST_ERR_NO_CAPABILITY
#define HOST_ERR_NOT_SUPPORTED
#define HOST_ERR_INVALID_ARG
#define HOST_ERR_NO_MEMORY
#define HOST_ERR_NOT_FOUND
#define HOST_ERR_RMEM_FULL
void * plg_get_active_plugin(void)
ISecureElement * getSecureElementInstance()
Returns singleton secure-element stub instance.
ISecureElement * getSecureElementInstance()
Returns singleton secure-element stub instance.