/
main.rs
106 lines (87 loc) · 2.63 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#![feature(asm)]
#![feature(rand)]
extern crate syscall;
extern crate raw_cpuid;
extern crate rand;
use std::fs::File;
use std::io::{Read, Write};
use rand::chacha::ChaChaRng;
use rand::Rng;
use raw_cpuid::CpuId;
use syscall::{Packet, Result, SchemeMut};
use syscall::data::Stat;
//TODO: Use a CSPRNG, allow write of entropy
struct RandScheme {
prng: ChaChaRng
}
impl SchemeMut for RandScheme {
fn open(&mut self, _path: &[u8], _flags: usize, _uid: u32, _gid: u32) -> Result<usize> {
Ok(0)
}
fn dup(&mut self, file: usize, _buf: &[u8]) -> Result<usize> {
Ok(file)
}
fn read(&mut self, _file: usize, buf: &mut [u8]) -> Result<usize> {
let mut i = 0;
for chunk in buf.chunks_mut(8) {
let mut rand = self.prng.next_u64();
for b in chunk.iter_mut() {
*b = rand as u8;
rand = rand >> 8;
i += 1;
}
}
Ok(i)
}
fn fpath(&mut self, _file: usize, buf: &mut [u8]) -> Result<usize> {
let mut i = 0;
let scheme_path = b"rand";
while i < buf.len() && i < scheme_path.len() {
buf[i] = scheme_path[i];
i += 1;
}
Ok(i)
}
fn fstat(&mut self, id: usize, stat: &mut Stat) -> Result<usize> {
*stat = Stat {
st_mode: 0o020000 /*IFCHR*/ | 0o666,
..Default::default()
};
Ok(0)
}
fn fcntl(&mut self, _id: usize, _cmd: usize, _arg: usize) -> Result<usize> {
Ok(0)
}
fn close(&mut self, _file: usize) -> Result<usize> {
Ok(0)
}
}
fn main(){
let has_rdrand = CpuId::new().get_feature_info().unwrap().has_rdrand();
// Daemonize
if unsafe { syscall::clone(0).unwrap() } == 0 {
let mut socket = File::create(":rand").expect("rand: failed to create rand scheme");
let mut rng = ChaChaRng::new_unseeded();
if has_rdrand {
println!("rand: seeding with rdrand");
let rand: u64;
unsafe {
asm!("rdrand rax"
: "={rax}"(rand)
:
:
: "intel", "volatile");
}
rng.set_counter(0, rand);
} else {
println!("rand: unseeded");
}
let mut scheme = RandScheme{prng: rng};
loop {
let mut packet = Packet::default();
socket.read(&mut packet).expect("rand: failed to read events from rand scheme");
scheme.handle(&mut packet);
socket.write(&packet).expect("rand: failed to write responses to rand scheme");
}
}
}