// SPDX-License-Identifier: MIT
// sign/Verifier.hh
#pragma once
//
// fedem::sign::Verifier — Ed25519 signature verification for signed DSOs.
//
// Typical usage (host application):
//
// #include <sign/Verifier.hh>
//
// auto result = fedem::sign::Verifier::verify( "/path/to/addon.so",
// "/etc/myapp/trusted-keys.d" );
// switch( result.trust ) {
// case TrustLevel::TRUSTED: // load it
// case TrustLevel::UNKNOWN: // warn and load, or reject
// case TrustLevel::UNSIGNED: // load silently or reject
// case TrustLevel::REJECTED: // always reject
// }
//
// Process-wide cache
// ──────────────────
// verify() caches results keyed by soPath. Because dlopen() maps the DSO
// at load time (inode reference), the on-disk file can be replaced without
// affecting the running process. The trust level of a loaded DSO cannot
// change within one process lifetime — one verification per path is correct.
//
// isCached(soPath) returns true when a result is already in the cache.
// The host can use this to suppress repeated log messages on subsequent
// calls with the same path.
//
// shouldLoad(policy, trustLevel)
// ──────────────────────────────
// Helper that translates a string policy to a load decision:
//
// "off" → always true (no verification)
// "warn" → true unless REJECTED
// "strict" → true only for TRUSTED
#include "sign/Manifest.hh"
#include "sign/TrustLevel.hh"
#include <string>
namespace fedem {
namespace sign {
// ─────────────────────────────────────────────────────────────────────────────
// VerifyResult
// ─────────────────────────────────────────────────────────────────────────────
struct VerifyResult
{
TrustLevel trust = TrustLevel::UNSIGNED;
ManifestData data; ///< populated when hasManifest == true
bool hasManifest = false;
std::string detail; ///< human-readable reason (for logging)
};
// ─────────────────────────────────────────────────────────────────────────────
// Verifier
// ─────────────────────────────────────────────────────────────────────────────
class Verifier
{
public:
/**
* Verify the DSO at @p soPath.
*
* Steps:
* 1. Read .dso_manifest + .dso_sig ELF sections.
* 2. Strip sections → temp file → compute SHA-256.
* 3. Compare hash with manifest.sha256.
* 4. Search @p trustedKeysDir for a *.pub whose fingerprint
* matches manifest.publicKeyId.
* 5. Ed25519-verify the signature over the manifest JSON.
*
* Result is cached by soPath — subsequent calls return the cached value.
*
* @param soPath path to the DSO
* @param trustedKeysDir directory containing *.pub files (PEM Ed25519)
*/
static VerifyResult verify( std::string const& soPath,
std::string const& trustedKeysDir );
/**
* Returns true when soPath already has a cached result.
* Useful for suppressing redundant log lines across sessions.
*/
static bool isCached( std::string const& soPath );
/**
* Decide whether to load a DSO given a policy string and trust level.
*
* @param policy "off" | "warn" | "strict"
* @param level result of verify()
* @return true → proceed with loading
*/
static bool shouldLoad( std::string const& policy,
TrustLevel level ) noexcept;
private:
/// Full verification without cache — called by verify() on first access.
static VerifyResult verifyUncached( std::string const& soPath,
std::string const& trustedKeysDir );
};
} // namespace sign
} // namespace fedem