1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:57:43 +00:00

LibCrypto: Add CTR cipher mode

Kernel: Changed fortuna implementation to use CTR mode instead of
manually implementing a counter.
This commit is contained in:
Peter Elliott 2020-06-23 14:05:26 -06:00 committed by Andreas Kling
parent 0f32155fa4
commit 2e8cfe5435
3 changed files with 153 additions and 26 deletions

View file

@ -31,8 +31,8 @@
#include <AK/ByteBuffer.h>
#include <AK/Types.h>
#include <Kernel/StdLib.h>
#include <LibCrypto/Cipher/Cipher.h>
#include <LibCrypto/Cipher/AES.h>
#include <LibCrypto/Cipher/Cipher.h>
#include <LibCrypto/Hash/SHA2.h>
namespace Kernel {
@ -48,31 +48,30 @@ public:
using HashType = HashT;
using DigestType = HashT::DigestType;
FortunaPRNG()
: m_counter(ByteBuffer::create_zeroed(BlockType::block_size()))
{
}
void get_random_bytes(u8* buffer, size_t n)
{
if (m_p0_len >= reseed_threshold) {
this->reseed();
}
ASSERT(m_counter != 0);
ASSERT(m_reseed_number > 0);
// FIXME: More than 2^20 bytes cannot be generated without refreshing the key.
ASSERT(n < (1 << 20));
CipherType cipher(m_key, KeySize);
typename CipherType::CTRMode cipher(m_key, KeySize);
size_t block_size = CipherType::BlockSizeInBits / 8;
for (size_t i = 0; i < n; i += block_size) {
this->generate_block(cipher, &buffer[i], min(block_size, n - i));
}
auto wrapped_buffer = ByteBuffer::wrap(buffer, n);
m_counter = cipher.key_stream(wrapped_buffer, m_counter).value();
// Extract a new key from the prng stream.
for (size_t i = 0; i < KeySize/8; i += block_size) {
this->generate_block(cipher, &(m_key[i]), min(block_size, KeySize - i));
}
m_counter = cipher.key_stream(m_key, m_counter).value();
}
template<typename T>
@ -86,17 +85,6 @@ public:
}
private:
void generate_block(CipherType cipher, u8* buffer, size_t size)
{
BlockType input((u8*)&m_counter, sizeof(m_counter));
BlockType output;
cipher.encrypt_block(input, output);
m_counter++;
memcpy(buffer, output.get().data(), size);
}
void reseed()
{
HashType new_key;
@ -111,12 +99,11 @@ private:
m_key = ByteBuffer::copy(digest.immutable_data(),
digest.data_length());
m_counter++;
m_reseed_number++;
m_p0_len = 0;
}
size_t m_counter { 0 };
ByteBuffer m_counter;
size_t m_reseed_number { 0 };
size_t m_p0_len { 0 };
ByteBuffer m_key;
@ -125,12 +112,12 @@ private:
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.