// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <lib/crypto/global_prng.h>

#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <explicit-memory/bytes.h>
#include <fbl/algorithm.h>
#include <kernel/auto_lock.h>
#include <kernel/cmdline.h>
#include <kernel/mutex.h>
#include <lib/crypto/cryptolib.h>
#include <lib/crypto/entropy/collector.h>
#include <lib/crypto/entropy/hw_rng_collector.h>
#include <lib/crypto/entropy/jitterentropy_collector.h>
#include <lib/crypto/entropy/quality_test.h>
#include <lib/crypto/prng.h>
#include <lk/init.h>
#include <new>
#include <string.h>
#include <trace.h>

#define LOCAL_TRACE 0

namespace crypto {

namespace GlobalPRNG {

static PRNG* kGlobalPrng = nullptr;

PRNG* GetInstance() {
    ASSERT(kGlobalPrng);
    return kGlobalPrng;
}

// Returns true if the kernel cmdline provided at least PRNG::kMinEntropy bytes
// of entropy, and false otherwise.
//
// TODO(security): Remove this in favor of virtio-rng once it is available and
// we decide we don't need it for getting entropy from elsewhere.
static bool IntegrateCmdlineEntropy() {
    const char* entropy = cmdline_get("kernel.entropy-mixin");
    if (!entropy) {
        return false;
    }

    const size_t kMaxEntropyArgumentLen = 128;
    const size_t hex_len = fbl::min(strlen(entropy), kMaxEntropyArgumentLen);

    for (size_t i = 0; i < hex_len; ++i) {
        if (!isxdigit(entropy[i])) {
            panic("Invalid entropy string: idx %zu is not an ASCII hex digit\n", i);
        }
    }

    uint8_t digest[clSHA256_DIGEST_SIZE];
    clSHA256(entropy, static_cast<int>(hex_len), digest);
    kGlobalPrng->AddEntropy(digest, sizeof(digest));

    // We have a pointer to const, but it's actually a pointer to the
    // mutable global state in __kernel_cmdline that is still live (it
    // will be copied into the userboot bootstrap message later).  So
    // it's fully well-defined to cast away the const and mutate this
    // here so the bits can't leak to userboot.  While we're at it,
    // prettify the result a bit so it's obvious what one is looking at.
    mandatory_memset(const_cast<char*>(entropy), 'x', hex_len);
    if (hex_len >= sizeof(".redacted=") - 1) {
        memcpy(const_cast<char*>(entropy) - 1,
               ".redacted=", sizeof(".redacted=") - 1);
    }

    const size_t entropy_added = fbl::max(hex_len / 2, sizeof(digest));
    LTRACEF("Collected %zu bytes of entropy from the kernel cmdline.\n",
            entropy_added);
    return (entropy_added >= PRNG::kMinEntropy);
}

// Returns true on success, false on failure.
static bool SeedFrom(entropy::Collector* collector) {
    uint8_t buf[PRNG::kMinEntropy] = {0};
    size_t remaining = collector->BytesNeeded(8 * PRNG::kMinEntropy);
#if LOCAL_TRACE
    {
        char name[ZX_MAX_NAME_LEN];
        collector->get_name(name, sizeof(name));
        LTRACEF("About to collect %zu bytes of entropy from '%s'.\n",
                remaining, name);
    }
#endif
    while (remaining > 0) {
        size_t result = collector->DrawEntropy(
                buf, fbl::min(sizeof(buf), remaining));
        if (result == 0) {
            LTRACEF("Collected 0 bytes; aborting. "
                    "There were %zu bytes remaining to collect.\n",
                    remaining);
            return false;
        }
        // TODO(ZX-1007): don't assume that every byte of entropy that's added
        // has a full 8 bits worth of entropy
        kGlobalPrng->AddEntropy(buf, result);
        mandatory_memset(buf, 0, sizeof(buf));
        remaining -= result;
    }
    LTRACEF("Successfully collected entropy.\n");
    return true;
}

// Instantiates the global PRNG (in non-thread-safe mode) and seeds it.
static void EarlyBootSeed(uint level) {
    ASSERT(kGlobalPrng == nullptr);

    // Before doing anything else, test our entropy collector. This is
    // explicitly called here rather than in another init hook to ensure
    // ordering (at level LK_INIT_LEVEL_TARGET_EARLY, but before the rest of
    // EarlyBootSeed).
    entropy::EarlyBootTest();

    // Statically allocate an array of bytes to put the PRNG into.  We do this
    // to control when the PRNG constructor is called.
    // TODO(security): This causes the PRNG state to be in a fairly predictable
    // place.  Some aspects of KASLR will help with this, but we may
    // additionally want to remap where this is later.
    alignas(alignof(PRNG))static uint8_t prng_space[sizeof(PRNG)];
    kGlobalPrng = new (&prng_space) PRNG(nullptr, 0, PRNG::NonThreadSafeTag());

    // TODO(security): Have the PRNG reseed based on usage

    unsigned int successful = 0; // number of successful entropy sources
    entropy::Collector* collector;
    if (entropy::HwRngCollector::GetInstance(&collector) == ZX_OK &&
        SeedFrom(collector)) {
        successful++;
    }
    if (entropy::JitterentropyCollector::GetInstance(&collector) == ZX_OK &&
        SeedFrom(collector)) {
        successful++;
    }

    if (IntegrateCmdlineEntropy()) {
        successful++;
    }
    if (successful == 0) {
        printf("WARNING: System has insufficient randomness.  It is completely "
               "unsafe to use this system for any cryptographic applications."
               "\n");
        // TODO(security): *CRITICAL* This is a fallback for systems without RNG
        // hardware that we should remove and attempt to do better.  If this
        // fallback is used, it breaks all cryptography used on the system.
        // *CRITICAL*
        uint8_t buf[PRNG::kMinEntropy] = {0};
        kGlobalPrng->AddEntropy(buf, sizeof(buf));
        return;
    } else {
        LTRACEF("Successfully collected entropy from %u sources.\n",
                successful);
    }
}

// Migrate the global PRNG to enter thread-safe mode.
static void BecomeThreadSafe(uint level) {
    GetInstance()->BecomeThreadSafe();
}

} //namespace GlobalPRNG

} // namespace crypto


LK_INIT_HOOK(global_prng_seed, crypto::GlobalPRNG::EarlyBootSeed,
             LK_INIT_LEVEL_TARGET_EARLY)

LK_INIT_HOOK(global_prng_thread_safe, crypto::GlobalPRNG::BecomeThreadSafe,
             LK_INIT_LEVEL_THREADING - 1)
