kern: switch RNG to CTR-DBRG
This commit is contained in:
@@ -51,9 +51,7 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
static NOINLINE u32 GetCreateProcessMemoryPool();
|
static NOINLINE u32 GetCreateProcessMemoryPool();
|
||||||
|
|
||||||
/* Randomness. */
|
/* Randomness. */
|
||||||
static void GenerateRandom(u64 *dst, size_t count);
|
static void GenerateRandomBytesForUninitialized(void *dst, size_t size);
|
||||||
static u64 GenerateRandomRange(u64 min, u64 max);
|
|
||||||
static u64 GenerateRandomU64();
|
|
||||||
|
|
||||||
/* Privileged Access. */
|
/* Privileged Access. */
|
||||||
static void ReadWriteRegisterPrivileged(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
static void ReadWriteRegisterPrivileged(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
||||||
|
|||||||
@@ -33,17 +33,30 @@ namespace ams::kern {
|
|||||||
|
|
||||||
class KResourceLimit;
|
class KResourceLimit;
|
||||||
|
|
||||||
|
struct CtrDrbgContext {
|
||||||
|
u8 v[16];
|
||||||
|
u8 key[16];
|
||||||
|
u8 seed[32];
|
||||||
|
u8 temp[32];
|
||||||
|
u32 reseed_counter;
|
||||||
|
u8 output[128];
|
||||||
|
u32 remaining;
|
||||||
|
};
|
||||||
|
|
||||||
class KSystemControlBase {
|
class KSystemControlBase {
|
||||||
public:
|
public:
|
||||||
/* This can be overridden as needed. */
|
/* This can be overridden as needed. */
|
||||||
static constexpr size_t SecureAppletMemorySize = 0;
|
static constexpr size_t SecureAppletMemorySize = 0;
|
||||||
protected:
|
protected:
|
||||||
/* Nintendo uses std::mt19937_t for randomness. */
|
|
||||||
/* To save space (and because mt19337_t isn't secure anyway), */
|
|
||||||
/* We will use TinyMT. */
|
|
||||||
static constinit inline bool s_uninitialized_random_generator{true};
|
static constinit inline bool s_uninitialized_random_generator{true};
|
||||||
static constinit inline util::TinyMT s_random_generator{util::ConstantInitialize};
|
static constinit inline CtrDrbgContext s_random_generator{};
|
||||||
static constinit inline KSpinLock s_random_lock;
|
static constinit inline KSpinLock s_random_lock;
|
||||||
|
private:
|
||||||
|
/* Randomness helpers. */
|
||||||
|
static void InitializeRandomGenerator(const void *seed, size_t size);
|
||||||
|
static void ReseedRandomGeneratorInternal();
|
||||||
|
static u32 GenerateRandomU32();
|
||||||
|
static u64 GenerateRandomU64Internal();
|
||||||
public:
|
public:
|
||||||
class Init {
|
class Init {
|
||||||
private:
|
private:
|
||||||
@@ -66,7 +79,7 @@ namespace ams::kern {
|
|||||||
static u64 GenerateRandomRange(u64 min, u64 max);
|
static u64 GenerateRandomRange(u64 min, u64 max);
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
static NOINLINE void InitializePhase1Base(u64 seed);
|
static NOINLINE void InitializePhase1Base(const void *seed, size_t size);
|
||||||
public:
|
public:
|
||||||
/* Initialization. */
|
/* Initialization. */
|
||||||
static NOINLINE void ConfigureKTargetSystem();
|
static NOINLINE void ConfigureKTargetSystem();
|
||||||
@@ -78,6 +91,10 @@ namespace ams::kern {
|
|||||||
static void GenerateRandom(u64 *dst, size_t count);
|
static void GenerateRandom(u64 *dst, size_t count);
|
||||||
static u64 GenerateRandomRange(u64 min, u64 max);
|
static u64 GenerateRandomRange(u64 min, u64 max);
|
||||||
static u64 GenerateRandomU64();
|
static u64 GenerateRandomU64();
|
||||||
|
static void ReseedRandomGenerator();
|
||||||
|
|
||||||
|
/* Obtains random bytes while the generator is not yet initialized. Board-provided. */
|
||||||
|
static void GenerateRandomBytesForUninitialized(void *dst, size_t size);
|
||||||
|
|
||||||
/* Register access Access. */
|
/* Register access Access. */
|
||||||
static Result ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
static Result ReadWriteRegister(u32 *out, ams::svc::PhysicalAddress address, u32 mask, u32 value);
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ $(OFILES_SRC) : $(HFILES_BIN)
|
|||||||
|
|
||||||
kern_libc_generic.o: CFLAGS += -fno-builtin
|
kern_libc_generic.o: CFLAGS += -fno-builtin
|
||||||
|
|
||||||
|
crypto_aes_impl.arch.arm64.o: CXXFLAGS := $(filter-out -mgeneral-regs-only,$(CXXFLAGS))
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
%_bin.h %.bin.o : %.bin
|
%_bin.h %.bin.o : %.bin
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -74,12 +74,6 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE u64 GenerateRandomU64FromSmc() {
|
|
||||||
u64 value;
|
|
||||||
smc::GenerateRandomBytes(std::addressof(value), sizeof(value));
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
ALWAYS_INLINE u64 GetConfigU64(smc::ConfigItem which) {
|
ALWAYS_INLINE u64 GetConfigU64(smc::ConfigItem which) {
|
||||||
u64 value;
|
u64 value;
|
||||||
smc::GetConfig(&value, 1, which);
|
smc::GetConfig(&value, 1, which);
|
||||||
@@ -477,9 +471,9 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
|
|
||||||
/* Initialize random and resource limit. */
|
/* Initialize random and resource limit. */
|
||||||
{
|
{
|
||||||
u64 seed;
|
u8 seed[32];
|
||||||
smc::GenerateRandomBytes(std::addressof(seed), sizeof(seed));
|
smc::GenerateRandomBytes(seed, sizeof(seed));
|
||||||
KSystemControlBase::InitializePhase1Base(seed);
|
KSystemControlBase::InitializePhase1Base(seed, sizeof(seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Configure the Kernel Carveout region. */
|
/* Configure the Kernel Carveout region. */
|
||||||
@@ -524,32 +518,8 @@ namespace ams::kern::board::nintendo::nx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Randomness. */
|
/* Randomness. */
|
||||||
void KSystemControl::GenerateRandom(u64 *dst, size_t count) {
|
void KSystemControl::GenerateRandomBytesForUninitialized(void *dst, size_t size) {
|
||||||
MESOSPHERE_INIT_ABORT_UNLESS(count <= 7);
|
smc::GenerateRandomBytes(dst, size);
|
||||||
smc::GenerateRandomBytes(dst, count * sizeof(u64));
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 KSystemControl::GenerateRandomRange(u64 min, u64 max) {
|
|
||||||
KScopedInterruptDisable intr_disable;
|
|
||||||
KScopedSpinLock lk(s_random_lock);
|
|
||||||
|
|
||||||
|
|
||||||
if (AMS_LIKELY(!s_uninitialized_random_generator)) {
|
|
||||||
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); });
|
|
||||||
} else {
|
|
||||||
return KSystemControlBase::GenerateUniformRange(min, max, GenerateRandomU64FromSmc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 KSystemControl::GenerateRandomU64() {
|
|
||||||
KScopedInterruptDisable intr_disable;
|
|
||||||
KScopedSpinLock lk(s_random_lock);
|
|
||||||
|
|
||||||
if (AMS_LIKELY(!s_uninitialized_random_generator)) {
|
|
||||||
return s_random_generator.GenerateRandomU64();
|
|
||||||
} else {
|
|
||||||
return GenerateRandomU64FromSmc();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KSystemControl::SleepSystem() {
|
void KSystemControl::SleepSystem() {
|
||||||
|
|||||||
@@ -264,6 +264,11 @@ namespace ams::kern {
|
|||||||
m_is_default_application_system_resource = false;
|
m_is_default_application_system_resource = false;
|
||||||
m_is_immortal = immortal;
|
m_is_immortal = immortal;
|
||||||
|
|
||||||
|
/* Reseed the random generator on application launch. */
|
||||||
|
if (params.flags & ams::svc::CreateProcessFlag_IsApplication) {
|
||||||
|
KSystemControl::ReseedRandomGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
/* Setup our system resource. */
|
/* Setup our system resource. */
|
||||||
if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) {
|
if (const size_t system_resource_num_pages = params.system_resource_num_pages; system_resource_num_pages != 0) {
|
||||||
/* Create a secure system resource. */
|
/* Create a secure system resource. */
|
||||||
@@ -332,6 +337,11 @@ namespace ams::kern {
|
|||||||
m_is_default_application_system_resource = false;
|
m_is_default_application_system_resource = false;
|
||||||
m_is_immortal = false;
|
m_is_immortal = false;
|
||||||
|
|
||||||
|
/* Reseed the random generator on application launch. */
|
||||||
|
if (params.flags & ams::svc::CreateProcessFlag_IsApplication) {
|
||||||
|
KSystemControl::ReseedRandomGenerator();
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the memory sizes. */
|
/* Get the memory sizes. */
|
||||||
const size_t code_num_pages = params.code_num_pages;
|
const size_t code_num_pages = params.code_num_pages;
|
||||||
const size_t system_resource_num_pages = params.system_resource_num_pages;
|
const size_t system_resource_num_pages = params.system_resource_num_pages;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <mesosphere.hpp>
|
#include <mesosphere.hpp>
|
||||||
|
#include <vapours/crypto/impl/crypto_aes_impl.hpp>
|
||||||
#if defined(ATMOSPHERE_ARCH_ARM64)
|
#if defined(ATMOSPHERE_ARCH_ARM64)
|
||||||
#include <mesosphere/arch/arm64/kern_secure_monitor_base.hpp>
|
#include <mesosphere/arch/arm64/kern_secure_monitor_base.hpp>
|
||||||
#endif
|
#endif
|
||||||
@@ -27,6 +28,55 @@ namespace ams::kern {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/* The kernel is otherwise FP/SIMD-free, but AES instructions require the NEON registers. */
|
||||||
|
class KScopedFpuEnable {
|
||||||
|
private:
|
||||||
|
u64 m_saved_cpacr_el1;
|
||||||
|
public:
|
||||||
|
ALWAYS_INLINE KScopedFpuEnable() : m_saved_cpacr_el1(cpu::GetCpacrEl1()) {
|
||||||
|
cpu::SetCpacrEl1(m_saved_cpacr_el1 | 0x100000);
|
||||||
|
cpu::InstructionMemoryBarrier();
|
||||||
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE ~KScopedFpuEnable() {
|
||||||
|
cpu::SetCpacrEl1(m_saved_cpacr_el1);
|
||||||
|
cpu::InstructionMemoryBarrier();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ALWAYS_INLINE void CtrDrbgIncrementCounter(u8 *v) {
|
||||||
|
for (size_t i = 16; i > 0; --i) {
|
||||||
|
if ((++v[i - 1]) != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CtrDrbgUpdate(CtrDrbgContext &ctx, const u8 *data) {
|
||||||
|
/* Initialize the block cipher with the current key. */
|
||||||
|
ams::crypto::impl::AesImpl<16> aes;
|
||||||
|
aes.Initialize(ctx.key, sizeof(ctx.key), true);
|
||||||
|
|
||||||
|
/* Generate two blocks of new key/counter material. */
|
||||||
|
CtrDrbgIncrementCounter(ctx.v);
|
||||||
|
aes.EncryptBlock(ctx.temp + 0, 16, ctx.v, 16);
|
||||||
|
CtrDrbgIncrementCounter(ctx.v);
|
||||||
|
aes.EncryptBlock(ctx.temp + 16, 16, ctx.v, 16);
|
||||||
|
|
||||||
|
/* Mix in the provided data. */
|
||||||
|
for (size_t i = 0; i < sizeof(ctx.temp); ++i) {
|
||||||
|
ctx.temp[i] ^= data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the key and counter. */
|
||||||
|
std::memcpy(ctx.key, ctx.temp, sizeof(ctx.key));
|
||||||
|
std::memcpy(ctx.v, ctx.temp + sizeof(ctx.key), sizeof(ctx.v));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialization. */
|
/* Initialization. */
|
||||||
size_t KSystemControlBase::Init::GetRealMemorySize() {
|
size_t KSystemControlBase::Init::GetRealMemorySize() {
|
||||||
return ams::kern::MainMemorySize;
|
return ams::kern::MainMemorySize;
|
||||||
@@ -102,25 +152,13 @@ namespace ams::kern {
|
|||||||
|
|
||||||
/* Randomness for Initialization. */
|
/* Randomness for Initialization. */
|
||||||
void KSystemControlBase::Init::GenerateRandom(u64 *dst, size_t count) {
|
void KSystemControlBase::Init::GenerateRandom(u64 *dst, size_t count) {
|
||||||
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
|
|
||||||
const u64 seed = KHardwareTimer::GetTick();
|
|
||||||
s_random_generator.Initialize(reinterpret_cast<const u32*>(std::addressof(seed)), sizeof(seed) / sizeof(u32));
|
|
||||||
s_uninitialized_random_generator = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
dst[i] = s_random_generator.GenerateRandomU64();
|
dst[i] = KSystemControlBase::GenerateRandomU64();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 KSystemControlBase::Init::GenerateRandomRange(u64 min, u64 max) {
|
u64 KSystemControlBase::Init::GenerateRandomRange(u64 min, u64 max) {
|
||||||
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
|
return KSystemControlBase::GenerateRandomRange(min, max);
|
||||||
const u64 seed = KHardwareTimer::GetTick();
|
|
||||||
s_random_generator.Initialize(reinterpret_cast<const u32*>(std::addressof(seed)), sizeof(seed) / sizeof(u32));
|
|
||||||
s_uninitialized_random_generator = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* System Initialization. */
|
/* System Initialization. */
|
||||||
@@ -135,15 +173,17 @@ namespace ams::kern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize random and resource limit. */
|
/* Initialize random and resource limit. */
|
||||||
KSystemControlBase::InitializePhase1Base(KHardwareTimer::GetTick());
|
u64 seed[4];
|
||||||
|
for (size_t i = 0; i < util::size(seed); ++i) {
|
||||||
|
seed[i] = KHardwareTimer::GetTick();
|
||||||
|
}
|
||||||
|
KSystemControlBase::InitializePhase1Base(seed, sizeof(seed));
|
||||||
}
|
}
|
||||||
|
|
||||||
void KSystemControlBase::InitializePhase1Base(u64 seed) {
|
void KSystemControlBase::InitializePhase1Base(const void *seed, size_t size) {
|
||||||
/* Initialize the rng, if we somehow haven't already. */
|
/* Initialize the random generator. */
|
||||||
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
|
KSystemControlBase::InitializeRandomGenerator(seed, size);
|
||||||
s_random_generator.Initialize(reinterpret_cast<const u32*>(std::addressof(seed)), sizeof(seed) / sizeof(u32));
|
|
||||||
s_uninitialized_random_generator = false;
|
s_uninitialized_random_generator = false;
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize debug logging. */
|
/* Initialize debug logging. */
|
||||||
KDebugLog::Initialize();
|
KDebugLog::Initialize();
|
||||||
@@ -213,13 +253,97 @@ namespace ams::kern {
|
|||||||
R_THROW(svc::ResultNotImplemented());
|
R_THROW(svc::ResultNotImplemented());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Randomness helpers. Assume the caller holds the random lock. */
|
||||||
|
void KSystemControlBase::InitializeRandomGenerator(const void *seed, size_t size) {
|
||||||
|
MESOSPHERE_ASSERT(size == sizeof(s_random_generator.seed));
|
||||||
|
|
||||||
|
KScopedFpuEnable fp_enabled;
|
||||||
|
auto &ctx = s_random_generator;
|
||||||
|
|
||||||
|
/* Zero the counter and key, then derive the initial state from the seed. */
|
||||||
|
std::memset(ctx.v, 0, sizeof(ctx.v));
|
||||||
|
std::memset(ctx.key, 0, sizeof(ctx.key));
|
||||||
|
std::memcpy(ctx.seed, seed, sizeof(ctx.seed));
|
||||||
|
|
||||||
|
CtrDrbgUpdate(ctx, ctx.seed);
|
||||||
|
|
||||||
|
ctx.reseed_counter = 1;
|
||||||
|
ctx.remaining = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KSystemControlBase::ReseedRandomGeneratorInternal() {
|
||||||
|
KScopedFpuEnable fp_enabled;
|
||||||
|
auto &ctx = s_random_generator;
|
||||||
|
|
||||||
|
/* Pull fresh entropy, then derive a new state from it. */
|
||||||
|
KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed));
|
||||||
|
CtrDrbgUpdate(ctx, ctx.seed);
|
||||||
|
|
||||||
|
ctx.remaining = 0;
|
||||||
|
ctx.reseed_counter = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 KSystemControlBase::GenerateRandomU32() {
|
||||||
|
auto &ctx = s_random_generator;
|
||||||
|
|
||||||
|
if (ctx.remaining == 0) {
|
||||||
|
KScopedFpuEnable fp_enabled;
|
||||||
|
|
||||||
|
/* Reseed if we've exhausted this generation's entropy, otherwise use zero additional input. */
|
||||||
|
if (ctx.reseed_counter <= 0x7FFFFFF0) {
|
||||||
|
std::memset(ctx.seed, 0, sizeof(ctx.seed));
|
||||||
|
} else {
|
||||||
|
KSystemControl::GenerateRandomBytesForUninitialized(ctx.seed, sizeof(ctx.seed));
|
||||||
|
CtrDrbgUpdate(ctx, ctx.seed);
|
||||||
|
ctx.remaining = 0;
|
||||||
|
std::memset(ctx.seed, 0, sizeof(ctx.seed));
|
||||||
|
ctx.reseed_counter = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate eight blocks of output. */
|
||||||
|
ams::crypto::impl::AesImpl<16> aes;
|
||||||
|
aes.Initialize(ctx.key, sizeof(ctx.key), true);
|
||||||
|
for (size_t i = 0; i < 8; ++i) {
|
||||||
|
CtrDrbgIncrementCounter(ctx.v);
|
||||||
|
aes.EncryptBlock(ctx.output + 16 * i, 16, ctx.v, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Derive the next state. */
|
||||||
|
CtrDrbgUpdate(ctx, ctx.seed);
|
||||||
|
|
||||||
|
++ctx.reseed_counter;
|
||||||
|
ctx.remaining = 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume a word from the output buffer, zeroizing it in place for backtracking resistance. */
|
||||||
|
const size_t index = 32 - ctx.remaining;
|
||||||
|
u32 value;
|
||||||
|
std::memcpy(std::addressof(value), ctx.output + 4 * index, sizeof(value));
|
||||||
|
std::memset(ctx.output + 4 * index, 0, sizeof(value));
|
||||||
|
--ctx.remaining;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 KSystemControlBase::GenerateRandomU64Internal() {
|
||||||
|
/* Fall back to the board's raw source while the generator is uninitialized. */
|
||||||
|
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
|
||||||
|
u64 value;
|
||||||
|
KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value));
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u64 high = KSystemControlBase::GenerateRandomU32();
|
||||||
|
const u64 low = KSystemControlBase::GenerateRandomU32();
|
||||||
|
return (high << 32) | low;
|
||||||
|
}
|
||||||
|
|
||||||
/* Randomness. */
|
/* Randomness. */
|
||||||
void KSystemControlBase::GenerateRandom(u64 *dst, size_t count) {
|
void KSystemControlBase::GenerateRandom(u64 *dst, size_t count) {
|
||||||
KScopedInterruptDisable intr_disable;
|
KScopedInterruptDisable intr_disable;
|
||||||
KScopedSpinLock lk(s_random_lock);
|
KScopedSpinLock lk(s_random_lock);
|
||||||
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
dst[i] = s_random_generator.GenerateRandomU64();
|
dst[i] = KSystemControlBase::GenerateRandomU64Internal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,14 +351,46 @@ namespace ams::kern {
|
|||||||
KScopedInterruptDisable intr_disable;
|
KScopedInterruptDisable intr_disable;
|
||||||
KScopedSpinLock lk(s_random_lock);
|
KScopedSpinLock lk(s_random_lock);
|
||||||
|
|
||||||
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return s_random_generator.GenerateRandomU64(); });
|
/* While uninitialized, fall back to a raw single-draw modulo. */
|
||||||
|
if (AMS_UNLIKELY(s_uninitialized_random_generator)) {
|
||||||
|
u64 value;
|
||||||
|
KSystemControl::GenerateRandomBytesForUninitialized(std::addressof(value), sizeof(value));
|
||||||
|
|
||||||
|
const u64 difference = max - min;
|
||||||
|
if (difference == std::numeric_limits<u64>::max()) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return min + (value % (difference + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return KSystemControlBase::GenerateUniformRange(min, max, []() ALWAYS_INLINE_LAMBDA -> u64 { return KSystemControlBase::GenerateRandomU64Internal(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 KSystemControlBase::GenerateRandomU64() {
|
u64 KSystemControlBase::GenerateRandomU64() {
|
||||||
KScopedInterruptDisable intr_disable;
|
KScopedInterruptDisable intr_disable;
|
||||||
KScopedSpinLock lk(s_random_lock);
|
KScopedSpinLock lk(s_random_lock);
|
||||||
|
|
||||||
return s_random_generator.GenerateRandomU64();
|
return KSystemControlBase::GenerateRandomU64Internal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KSystemControlBase::ReseedRandomGenerator() {
|
||||||
|
/* This must be unreachable while the generator is uninitialized. */
|
||||||
|
MESOSPHERE_ABORT_UNLESS(!s_uninitialized_random_generator);
|
||||||
|
|
||||||
|
KScopedInterruptDisable intr_disable;
|
||||||
|
KScopedSpinLock lk(s_random_lock);
|
||||||
|
|
||||||
|
KSystemControlBase::ReseedRandomGeneratorInternal();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KSystemControlBase::GenerateRandomBytesForUninitialized(void *dst, size_t size) {
|
||||||
|
/* The default board has no secure monitor; fall back to the hardware timer. */
|
||||||
|
u8 *dst_8 = static_cast<u8 *>(dst);
|
||||||
|
for (size_t offset = 0; offset < size; offset += sizeof(u64)) {
|
||||||
|
const u64 tick = KHardwareTimer::GetTick();
|
||||||
|
std::memcpy(dst_8 + offset, std::addressof(tick), std::min(sizeof(tick), size - offset));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void KSystemControlBase::SleepSystem() {
|
void KSystemControlBase::SleepSystem() {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace ams::crypto::impl {
|
|||||||
#ifdef ATMOSPHERE_IS_EXOSPHERE
|
#ifdef ATMOSPHERE_IS_EXOSPHERE
|
||||||
int m_slot;
|
int m_slot;
|
||||||
#endif
|
#endif
|
||||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||||
u32 m_round_keys[RoundKeySize / sizeof(u32)];
|
u32 m_round_keys[RoundKeySize / sizeof(u32)];
|
||||||
#endif
|
#endif
|
||||||
public:
|
public:
|
||||||
@@ -43,7 +43,7 @@ namespace ams::crypto::impl {
|
|||||||
void EncryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const;
|
void EncryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const;
|
||||||
void DecryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const;
|
void DecryptBlock(void *dst, size_t dst_size, const void *src, size_t src_size) const;
|
||||||
|
|
||||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||||
const u8 *GetRoundKey() const {
|
const u8 *GetRoundKey() const {
|
||||||
return reinterpret_cast<const u8 *>(m_round_keys);
|
return reinterpret_cast<const u8 *>(m_round_keys);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,13 +14,16 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
#if defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||||
|
#include <mesosphere/kern_panic.hpp>
|
||||||
|
#endif
|
||||||
|
#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||||
#include <arm_neon.h>
|
#include <arm_neon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ams::crypto::impl {
|
namespace ams::crypto::impl {
|
||||||
|
|
||||||
#if defined(ATMOSPHERE_IS_STRATOSPHERE)
|
#if defined(ATMOSPHERE_IS_STRATOSPHERE) || defined(ATMOSPHERE_IS_MESOSPHERE)
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|||||||
Reference in New Issue
Block a user