Code View

plugin / plugin-2.2.0.0 / src / sign / Verifier.hh
// 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