blob: 6ae2ff11808e89c21acf0d76d5fe53b1f84b9749 [file] [log] [blame]
#pragma once
#include <compartment-macros.h>
#include <ds/xoroshiro.h>
#include <interrupt.h>
#include <platform/concepts/entropy.h>
#include <riscvreg.h>
DECLARE_AND_DEFINE_INTERRUPT_CAPABILITY(RevokerInterruptEntropy,
InterruptName::EthernetReceiveInterrupt,
true,
false)
/**
* A simple entropy source. This wraps a few weak entropy sources to seed a
* PRNG. It is absolutely not secure and should not be used for anything that
* depends on cryptographically secure random numbers! Unfortunately, there is
* nothing on the Arty A7 instantiation of CHERIoT SAFE that can be used as a
* secure entropy source.
*/
class EntropySource
{
ds::xoroshiro::P128R64 prng;
public:
using ValueType = uint64_t;
/// Definitely not secure!
static constexpr bool IsSecure = false;
/// Constructor, tries to generate an independent sequence of random numbers
EntropySource()
{
reseed();
}
/// Reseed the PRNG
void reseed()
{
// Start from a not very random seed
uint64_t seed = rdcycle64();
prng.set_state(seed, seed >> 24);
uint32_t interrupts =
*interrupt_futex_get(STATIC_SEALED_VALUE(RevokerInterruptEntropy));
// Permute it with another not-very-random number
for (uint32_t i = 0; i < ((interrupts & 0xff00) >> 8); i++)
{
prng.long_jump();
}
for (uint32_t i = 0; i < (interrupts & 0xff); i++)
{
prng.jump();
}
// At this point, our random number is in a fairly predictable state,
// but with a fairly low probability of being the same predictable
// state as before.
}
ValueType operator()()
{
return prng();
}
};
static_assert(IsEntropySource<EntropySource>,
"EntropySource must be an entropy source");