-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathentropy_source.h
118 lines (77 loc) · 2.77 KB
/
entropy_source.h
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
107
108
109
110
111
112
113
114
115
116
117
#include <fstream>
#include <iostream>
#include "common.h"
//
// Used to model the cryptography extension entropy source.
// See Section 4 of the Scalar Cryptography Extension specificaiton.
class entropy_source {
public:
// Valid return codes for OPST bits [31:30] when reading seed.
static const uint32_t OPST_BIST = 0x0 << 30;
static const uint32_t OPST_WAIT = 0x1 << 30;
static const uint32_t OPST_ES16 = 0x2 << 30;
static const uint32_t OPST_DEAD = 0x3 << 30;
//
// Other system events
// ------------------------------------------------------------
void reset() {
// Does nothing for now. In the future, can be used to model things
// like initial BIST states.
}
//
// seed register
// ------------------------------------------------------------
void set_seed(reg_t UNUSED val) {
// Always ignore writes to seed.
// This CSR is strictly read only. It occupies a RW CSR address
// to handle the side-effect of the changing seed value on a read.
}
//
// The format of seed is described in Section 4.1 of
// the scalar cryptography specification.
reg_t get_seed() {
uint32_t result = 0;
// Currently, always return ES16 (i.e. good randomness) In the future, we
// can more realistically model things like WAIT states, BIST warm up and
// maybe scriptable entry into the DEAD state, but until then, this is
// the bare minimum.
uint32_t return_status = OPST_ES16;
if (return_status == OPST_ES16) {
// Add some sampled entropy into the low 16 bits
uint16_t entropy = this -> get_two_random_bytes();
result |= entropy;
} else if (return_status == OPST_BIST) {
// Do nothing.
} else if (return_status == OPST_WAIT) {
// Do nothing.
} else if (return_status == OPST_DEAD) {
// Do nothing. Stay dead.
} else {
// Unreachable.
}
// Note that if we get here any return_status is anything other than
// OPST_ES16, then the low 16-bits of the return value must be zero.
result |= return_status;
// Result is zero-extended on RV64.
return (reg_t)result;
}
//
// Utility / support variables and functions.
// ------------------------------------------------------------
// The file to read entropy from.
std::string randomness_source = "/dev/urandom";
// Read two random bytes from the entropy source file.
uint16_t get_two_random_bytes() {
std::ifstream fh(this -> randomness_source, std::ios::binary);
if (fh.is_open()) {
uint16_t random_bytes;
fh.read((char*)(&random_bytes), 2);
fh.close();
return random_bytes;
} else {
fprintf(stderr, "Could not open randomness source file:\n\t");
fprintf(stderr, "%s", randomness_source.c_str());
abort();
}
}
};