mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:27:35 +00:00
Kernel: Replace existing random implementation with Fortuna
This commit is contained in:
parent
f2d51f13a6
commit
0f32155fa4
3 changed files with 49 additions and 30 deletions
|
@ -148,12 +148,18 @@ set(KEYBOARD_SOURCES
|
|||
../Libraries/LibKeyboard/CharacterMap.cpp
|
||||
)
|
||||
|
||||
set(CRYPTO_SOURCES
|
||||
../Libraries/LibCrypto/Cipher/AES.cpp
|
||||
../Libraries/LibCrypto/Hash/SHA2.cpp
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
${KERNEL_SOURCES}
|
||||
${AK_SOURCES}
|
||||
${ELF_SOURCES}
|
||||
${VT_SOURCES}
|
||||
${KEYBOARD_SOURCES}
|
||||
${CRYPTO_SOURCES}
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DKERNEL")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020, Peter Elliott <pelliott@ualberta.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -30,37 +31,35 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
static u32 random32()
|
||||
static KernelRng* s_the;
|
||||
|
||||
KernelRng& KernelRng::the()
|
||||
{
|
||||
if (!s_the) {
|
||||
s_the = new KernelRng;
|
||||
}
|
||||
return *s_the;
|
||||
}
|
||||
|
||||
KernelRng::KernelRng()
|
||||
{
|
||||
if (g_cpu_supports_rdrand) {
|
||||
u32 value = 0;
|
||||
asm volatile(
|
||||
"1:\n"
|
||||
"rdrand %0\n"
|
||||
"jnc 1b\n"
|
||||
: "=r"(value));
|
||||
return value;
|
||||
for (size_t i = 0; i < KernelRng::pool_count * KernelRng::reseed_threshold; ++i) {
|
||||
u32 value = 0;
|
||||
asm volatile(
|
||||
"1:\n"
|
||||
"rdseed %0\n"
|
||||
"jnc 1b\n"
|
||||
: "=r"(value));
|
||||
|
||||
this->add_random_event(value, i % 32);
|
||||
}
|
||||
}
|
||||
// FIXME: This sucks lol
|
||||
static u32 next = 1;
|
||||
next = next * 1103515245 + 12345;
|
||||
return next;
|
||||
}
|
||||
|
||||
void get_good_random_bytes(u8* buffer, size_t buffer_size)
|
||||
{
|
||||
union {
|
||||
u8 bytes[4];
|
||||
u32 value;
|
||||
} u;
|
||||
size_t offset = 4;
|
||||
for (size_t i = 0; i < buffer_size; ++i) {
|
||||
if (offset >= 4) {
|
||||
u.value = random32();
|
||||
offset = 0;
|
||||
}
|
||||
buffer[i] = u.bytes[offset++];
|
||||
}
|
||||
KernelRng::the().get_random_bytes(buffer, buffer_size);
|
||||
}
|
||||
|
||||
void get_fast_random_bytes(u8* buffer, size_t buffer_size)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
* Copyright (c) 2020, Peter Elliott <pelliott@ualberta.ca
|
||||
* Copyright (c) 2020, Peter Elliott <pelliott@ualberta.ca>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -32,11 +32,14 @@
|
|||
#include <AK/Types.h>
|
||||
#include <Kernel/StdLib.h>
|
||||
#include <LibCrypto/Cipher/Cipher.h>
|
||||
#include <LibCrypto/Cipher/AES.h>
|
||||
#include <LibCrypto/Hash/SHA2.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
template<typename CipherT, typename HashT, int KeySize>
|
||||
class FortunaPRNG {
|
||||
public:
|
||||
constexpr static size_t pool_count = 32;
|
||||
constexpr static size_t reseed_threshold = 16;
|
||||
|
||||
|
@ -45,7 +48,6 @@ class FortunaPRNG {
|
|||
using HashType = HashT;
|
||||
using DigestType = HashT::DigestType;
|
||||
|
||||
public:
|
||||
void get_random_bytes(u8* buffer, size_t n)
|
||||
{
|
||||
if (m_p0_len >= reseed_threshold) {
|
||||
|
@ -57,7 +59,7 @@ public:
|
|||
// FIXME: More than 2^20 bytes cannot be generated without refreshing the key.
|
||||
ASSERT(n < (1 << 20));
|
||||
|
||||
CipherType cipher(m_key, m_key.size());
|
||||
CipherType cipher(m_key, KeySize);
|
||||
|
||||
size_t block_size = CipherType::BlockSizeInBits / 8;
|
||||
|
||||
|
@ -67,9 +69,10 @@ public:
|
|||
|
||||
// Extract a new key from the prng stream.
|
||||
|
||||
for (size_t i = 0; i < KeySize; i += block_size) {
|
||||
for (size_t i = 0; i < KeySize/8; i += block_size) {
|
||||
this->generate_block(cipher, &(m_key[i]), min(block_size, KeySize - i));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -79,13 +82,14 @@ public:
|
|||
if (pool == 0) {
|
||||
m_p0_len++;
|
||||
}
|
||||
m_pools[pool].update(reinterpret_cast<u8*>(&event_data), sizeof(T));
|
||||
m_pools[pool].update(reinterpret_cast<const u8*>(&event_data), sizeof(T));
|
||||
}
|
||||
|
||||
private:
|
||||
void generate_block(CipherType cipher, u8* buffer, size_t size)
|
||||
{
|
||||
BlockType input((u8*)m_counter, sizeof(m_counter));
|
||||
|
||||
BlockType input((u8*)&m_counter, sizeof(m_counter));
|
||||
BlockType output;
|
||||
cipher.encrypt_block(input, output);
|
||||
m_counter++;
|
||||
|
@ -119,6 +123,16 @@ private:
|
|||
HashType m_pools[pool_count];
|
||||
};
|
||||
|
||||
class KernelRng : public FortunaPRNG<Crypto::Cipher::AESCipher, Crypto::Hash::SHA256, 256> {
|
||||
AK_MAKE_ETERNAL;
|
||||
public:
|
||||
static KernelRng& the();
|
||||
|
||||
private:
|
||||
KernelRng();
|
||||
|
||||
};
|
||||
|
||||
// NOTE: These API's are primarily about expressing intent/needs in the calling code.
|
||||
// We don't make any guarantees about actual fastness or goodness yet.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue