/* capsule_sig.c -- see capsule_sig.h. */ #include "starkernel/capsule_sig.h" #include "starkernel/x509_ed25519.h" #include "starkernel/ed25519.h" #include #define SNAKEOIL_CERT_NAME "pki:snakeoil-intermediate.der" /* Cached once per boot: the cert doesn't change mid-boot, and every * capsule birth (Mama, then every child VM) would otherwise re-find and * re-parse the same cert. -1 = not yet attempted, 0 = failed, 1 = ready. */ static int pubkey_state = -1; static uint8_t cached_pubkey[32]; static int find_and_cache_pubkey(const CapsuleDesc *descs, const CapsuleNameEntry *names, const uint8_t *arena_base, uint32_t desc_count) { if (pubkey_state != -1) return pubkey_state; pubkey_state = 0; /* assume failure unless every step below succeeds */ for (uint32_t i = 0; i < desc_count; i++) { if (strcmp(names[i].name, SNAKEOIL_CERT_NAME) == 0) { const CapsuleDesc *cert_desc = &descs[i]; if (x509_extract_ed25519_pubkey(arena_base + cert_desc->offset, (size_t)cert_desc->length, cached_pubkey) == 0) { pubkey_state = 1; } break; } } return pubkey_state; } CapsuleSigResult capsule_verify_signature( const CapsuleDesc *descs, const CapsuleNameEntry *names, const CapsuleSigEntry *sigs, const uint8_t *arena_base, uint32_t desc_count, int index) { if (!descs || !names || !sigs || !arena_base || index < 0 || (uint32_t)index >= desc_count) { return CAPSULE_SIG_NO_ROOT_KEY; /* malformed call -- treat like "can't check" */ } if (!find_and_cache_pubkey(descs, names, arena_base, desc_count)) { return CAPSULE_SIG_NO_ROOT_KEY; } if (!sigs[index].has_sig) { return CAPSULE_SIG_MISSING; } const CapsuleDesc *d = &descs[index]; int ok = ed25519_verify(cached_pubkey, arena_base + d->offset, (size_t)d->length, sigs[index].sig); return ok ? CAPSULE_SIG_OK : CAPSULE_SIG_INVALID; } const char *capsule_sig_result_str(CapsuleSigResult result) { switch (result) { case CAPSULE_SIG_OK: return "ok"; case CAPSULE_SIG_MISSING: return "missing (unsigned)"; case CAPSULE_SIG_INVALID: return "INVALID -- signature does not verify"; case CAPSULE_SIG_NO_ROOT_KEY: return "no root key (cert not found/parseable)"; default: return "unknown"; } }