Add a more proper rand implementation

This commit is contained in:
mintsuki 2020-06-01 10:20:34 +02:00
parent 045c4078a0
commit 42906fef15
7 changed files with 118 additions and 62 deletions

Binary file not shown.

101
src/lib/rand.c Normal file
View File

@ -0,0 +1,101 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <lib/blib.h>
#include <lib/print.h>
#include <lib/rand.h>
// TODO: Find where this mersenne twister implementation is inspired from
// and properly credit the original author(s).
#define rdrand(type) ({ \
type ret; \
asm volatile ( \
"1: " \
"rdrand %0;" \
"jnc 1b;" \
: "=r" (ret) \
); \
ret; \
})
#define rdtsc(type) ({ \
type ret; \
asm volatile ( \
"rdtsc;" \
: "=A" (ret) \
); \
ret; \
})
static bool rdrand_available = false;
void init_rand(void) {
{
uint32_t eax, ebx, ecx, edx;
int ret = cpuid(1, 0, &eax, &ebx, &ecx, &edx);
if (!ret && (ecx & (1 << 30)))
rdrand_available = true;
}
uint32_t seed = ((uint32_t)0xc597060c * rdtsc(uint32_t))
* ((uint32_t)0xce86d624)
^ ((uint32_t)0xee0da130 * rdtsc(uint32_t));
if (!rdrand_available) {
srand(seed);
} else {
seed *= (seed ^ rdrand(uint32_t));
srand(seed);
}
}
#define n ((int)624)
#define m ((int)397)
#define matrix_a ((uint32_t)0x9908b0df)
#define msb ((uint32_t)0x80000000)
#define lsbs ((uint32_t)0x7fffffff)
static uint32_t status[n];
static int ctr;
void srand(uint32_t s) {
status[0] = s;
for (ctr = 1; ctr < n; ctr++)
status[ctr] = (1812433253 * (status[ctr - 1] ^ (status[ctr - 1] >> 30)) + ctr);
}
uint32_t rand32(void) {
const uint32_t mag01[2] = {0, matrix_a};
if (ctr >= n) {
for (int kk = 0; kk < n - m; kk++) {
uint32_t y = (status[kk] & msb) | (status[kk + 1] & lsbs);
status[kk] = status[kk + m] ^ (y >> 1) ^ mag01[y & 1];
}
for (int kk = n - m; kk < n - 1; kk++) {
uint32_t y = (status[kk] & msb) | (status[kk + 1] & lsbs);
status[kk] = status[kk + (m - n)] ^ (y >> 1) ^ mag01[y & 1];
}
uint32_t y = (status[n - 1] & msb) | (status[0] & lsbs);
status[n - 1] = status[m - 1] ^ (y >> 1) ^ mag01[y & 1];
ctr = 0;
}
uint32_t res = status[ctr++];
res ^= (res >> 11);
res ^= (res << 7) & 0x9d2c5680;
res ^= (res << 15) & 0xefc60000;
res ^= (res >> 18);
return res;
}
uint64_t rand64(void) {
return (((uint64_t)rand32()) << 32) | (uint64_t)rand32();
}

13
src/lib/rand.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef __LIB__RAND_H__
#define __LIB__RAND_H__
#include <stdint.h>
void init_rand(void);
void srand(uint32_t s);
uint32_t rand32(void);
uint64_t rand64(void);
#endif

View File

@ -1,48 +0,0 @@
#include <lib/blib.h>
int rdrand_available = 0;
static void check_rdrand(void) {
uint32_t eax, ebx, ecx, edx;
int ret = cpuid(1, 0, &eax, &ebx, &ecx, &edx);
if (ret)
return;
if (ecx & (1 << 30))
rdrand_available = 1;
}
static void init_simple_rand(void) {
// TODO: Some fallback randomness init
}
void init_random(void) {
check_rdrand();
if (!rdrand_available) {
init_simple_rand();
}
}
static uint32_t rdrand(void) {
uint32_t val;
asm (
"1:rdrand %0\n\t"
"jnc 1b\n\t"
:"=r"(val)
);
return val;
}
static uint32_t simple_rand(void) {
// TODO: Some fallback randomness
return 0xFEEDFACE;
}
uint32_t get_random(void) {
if (rdrand_available)
return rdrand();
else
return simple_rand();
}

View File

@ -1,10 +0,0 @@
#ifndef __LIB__RANDOM_H__
#define __LIB__RANDOM_H__
#include <stdint.h>
void init_random(void);
uint32_t get_random(void);
#endif

View File

@ -22,7 +22,7 @@ asm (
#include <lib/config.h>
#include <lib/e820.h>
#include <lib/print.h>
#include <lib/random.h>
#include <lib/rand.h>
#include <fs/file.h>
#include <lib/elf.h>
#include <protos/stivale.h>
@ -99,7 +99,7 @@ refresh:
void main(int boot_drive) {
// Initial prompt.
init_vga_textmode();
init_random();
init_rand();
print("qloader2\n\n");

View File

@ -9,7 +9,7 @@
#include <lib/config.h>
#include <lib/time.h>
#include <lib/print.h>
#include <lib/random.h>
#include <lib/rand.h>
#include <lib/real.h>
#include <drivers/vbe.h>
#include <drivers/vga_textmode.h>
@ -110,7 +110,7 @@ void stivale_load(char *cmdline, int boot_drive) {
if (!ret && ((stivale_hdr.flags >> 2) & 1)) {
// KASLR is enabled, set the slide
slide = get_random() & KASLR_SLIDE_BITMASK;
slide = rand64() & KASLR_SLIDE_BITMASK;
// Re-read the .stivalehdr with slid relocations
ret = elf64_load_section(fd, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header), slide);