Skip to content

Commit d716621

Browse files
authored
Merge pull request #2094 from fwsGonzo/early_rng
Some RNG enhancements
2 parents 0efba18 + 3b26db0 commit d716621

16 files changed

Lines changed: 179 additions & 53 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,7 @@ option (undefined_san "Enable undefined-behavior sanitizer" OFF)
5656
option (thin_lto "Enable the Thin LTO plugin" OFF)
5757
option (full_lto "Enable full LTO (compatibility)" OFF)
5858

59-
# create random hex string as stack protector canary
60-
string(RANDOM LENGTH 16 ALPHABET 0123456789ABCDEF STACK_PROTECTOR_VALUE)
61-
62-
set(CAPABS "${CAPABS} -g -fstack-protector-strong -D_STACK_GUARD_VALUE_=0x${STACK_PROTECTOR_VALUE}")
59+
set(CAPABS "${CAPABS} -g -fstack-protector-strong")
6360

6461
# Various global defines
6562
# * NO_DEBUG disables output from the debug macro

api/kernel/cpuid.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ namespace CPUID
5959
AVX, // AVX Instructions
6060
F16C, // 16-bit Floating Point Instructions
6161
RDRAND, // RDRAND Instruction
62+
RDSEED, // RDSEED Instruction
6263

6364
FPU, // Floating-Point Unit On-Chip
6465
VME, // Virtual 8086 Mode Extensions

api/kernel/rng.hpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,16 @@
2222

2323
#include <cstdlib>
2424
#include <cstdint>
25+
#include <delegate>
2526

2627
// Incorporate seed data into the system RNG state
2728
extern void rng_absorb(const void* input, size_t bytes);
2829

2930
// Extract output from the system RNG
3031
extern void rng_extract(void* output, size_t bytes);
3132

32-
// Try to reseed the RNG state somehow
33-
extern void rng_reseed();
33+
// Try to reseed the RNG state
34+
extern void rng_reseed_init(delegate<void(uint64_t*)>, int rounds);
3435

3536
// Extract 32 bit integer from system RNG
3637
inline uint32_t rng_extract_uint32()
@@ -40,6 +41,13 @@ inline uint32_t rng_extract_uint32()
4041
return x;
4142
}
4243

44+
// Extract 64 bit integer from system RNG
45+
inline uint64_t rng_extract_uint64()
46+
{
47+
uint64_t x;
48+
rng_extract(&x, sizeof(x));
49+
return x;
50+
}
4351

4452
#include <fs/fd_compatible.hpp>
4553
class RNG : public FD_compatible {
@@ -50,7 +58,7 @@ class RNG : public FD_compatible {
5058
return rng;
5159
}
5260

53-
void init();
61+
static void init();
5462

5563
private:
5664
RNG() {}

cmake/post.service.cmake

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,14 @@ if ("${PLATFORM}" STREQUAL "x86_solo5")
294294
set(PRE_BSS_SIZE "--defsym PRE_BSS_AREA=0x200000")
295295
endif()
296296

297-
set(LDFLAGS "-nostdlib -melf_${ELF} --eh-frame-hdr ${LD_STRIP} --script=${INSTALL_LOC}/${ARCH}/linker.ld ${PRE_BSS_SIZE}")
297+
option(for_production "Stop the OS when conditions not suitable for production" ON)
298+
if (for_production)
299+
set(PROD_USE 0x2000)
300+
else()
301+
set(PROD_USE 0x1000)
302+
endif()
303+
304+
set(LDFLAGS "-nostdlib -melf_${ELF} --eh-frame-hdr ${LD_STRIP} --script=${INSTALL_LOC}/${ARCH}/linker.ld ${PRE_BSS_SIZE} --defsym __for_production_use=${PROD_USE}")
298305

299306
set_target_properties(service PROPERTIES LINK_FLAGS "${LDFLAGS}")
300307

linux/src/os.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#include <kernel/os.hpp>
22
#include <kernel/events.hpp>
3+
#include <kernel/rng.hpp>
34
#include <kernel/service.hpp>
45
#include <kernel/timers.hpp>
56
#include <system_log>
67
#include <sys/time.h>
8+
#include <sys/random.h>
79
#include <malloc.h> // mallinfo()
810
#include <sched.h>
911
extern bool __libc_initialized;
@@ -101,6 +103,11 @@ void OS::start(const char* cmdline)
101103
// setup timer system
102104
Timers::init(begin_timer, stop_timers);
103105
Timers::ready();
106+
// seed RNG with entropy
107+
char entropy[2048];
108+
ssize_t rngres = getrandom(entropy, sizeof(entropy), 0);
109+
assert(rngres == sizeof(entropy));
110+
rng_absorb(entropy, sizeof(entropy));
104111
// fake CPU frequency
105112
using namespace std::chrono;
106113
OS::cpu_khz_ = decltype(OS::cpu_freq()) {3000000ul};

seed/service/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ set(SOURCES
2323
set(DRIVERS
2424
# virtionet # Virtio networking driver
2525
# virtioblk # Virtio block device driver
26-
#boot_logger # Enable lots of logging from boot stage
26+
boot_logger # Enable lots of logging from boot stage
2727

2828
# Use "boot --drivers ." to see other drivers
2929
)

seed/service/service.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <service>
1919
#include <cstdio>
2020
#include <isotime>
21+
#include <kernel/cpuid.hpp>
2122

2223
void Service::start(const std::string& args)
2324
{
@@ -27,4 +28,6 @@ void Service::start(const std::string& args)
2728
printf("Hello world! Time is now %s\n", isotime::now().c_str());
2829
printf("Args = %s\n", args.c_str());
2930
printf("Try giving the service less memory, eg. 5MB in vm.json\n");
31+
printf("CPU has RDRAND: %d\n", CPUID::has_feature(CPUID::Feature::RDRAND));
32+
printf("CPU has RDSEED: %d\n", CPUID::has_feature(CPUID::Feature::RDSEED));
3033
}

src/arch/x86_64/apic_asm.asm

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,27 @@ reset_idtr:
6161
__amd64_load_tr:
6262
ltr di
6363
ret
64+
65+
GLOBAL intel_rdrand:function
66+
intel_rdrand:
67+
mov eax, 0x1
68+
retry_rdrand:
69+
rdrand rcx
70+
mov QWORD [rdi], rcx
71+
cmovb ecx, eax
72+
jae retry_rdrand
73+
cmp ecx, 0x1
74+
sete al
75+
ret
76+
77+
GLOBAL intel_rdseed:function
78+
intel_rdseed:
79+
mov eax, 0x1
80+
retry_rdseed:
81+
rdseed rcx
82+
mov QWORD [rdi], rcx
83+
cmovb ecx, eax
84+
jae retry_rdseed
85+
cmp ecx, 0x1
86+
sete al
87+
ret

src/kernel/cpuid.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace CPUID {
3737
{Feature::SSE3,"SSE3"},
3838
{Feature::SSSE3,"SSSE3"},
3939
{Feature::RDRAND,"RDRAND"},
40+
{Feature::RDSEED,"RDSEED"},
4041
{Feature::XSAVE,"XSAVE"},
4142
{Feature::FXSR,"FXSR"},
4243
{Feature::AES,"AES"},
@@ -207,10 +208,12 @@ namespace
207208

208209
case Feature::SVM: return FeatureInfo { 0x80000001, 0, Register::ECX, 1u << 2 }; // Secure Virtual Machine (AMD-V)
209210
case Feature::SSE4A: return FeatureInfo { 0x80000001, 0, Register::ECX, 1u << 6 }; // SSE4a
211+
// Standard function 7
210212
case Feature::AVX2: return FeatureInfo { 7, 0, Register::ECX, 1u << 5 }; // AVX2
211213
case Feature::BMI1: return FeatureInfo { 7, 0, Register::ECX, 1u << 3 }; // BMI1
212214
case Feature::BMI2: return FeatureInfo { 7, 0, Register::ECX, 1u << 8 }; // BMI2
213215
case Feature::LZCNT: return FeatureInfo { 7, 0, Register::ECX, 1u << 5 }; // LZCNT
216+
case Feature::RDSEED: return FeatureInfo { 7, 0, Register::EBX, 1u << 18 }; // RDSEED
214217
default: throw std::out_of_range("Unimplemented CPU feature encountered");
215218
}
216219
}

src/kernel/os.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#endif
2424

2525
#include <kernel/os.hpp>
26+
#include <kernel/cpuid.hpp>
2627
#include <kernel/rng.hpp>
2728
#include <service>
2829
#include <cstdio>
@@ -49,6 +50,10 @@ extern char _LOAD_START_;
4950
extern char _ELF_END_;
5051

5152
bool __libc_initialized = false;
53+
extern char __for_production_use;
54+
inline static bool is_for_production_use() {
55+
return &__for_production_use == (char*) 0x2000;
56+
}
5257

5358
bool OS::power_ = true;
5459
bool OS::boot_sequence_passed_ = false;
@@ -134,10 +139,6 @@ void OS::post_start()
134139
// Dependent on the liveupdate location being set
135140
SystemLog::initialize();
136141

137-
MYINFO("Initializing RNG");
138-
PROFILE("RNG init");
139-
RNG::get().init();
140-
141142
// Seed rand with 32 bits from RNG
142143
srand(rng_extract_uint32());
143144

@@ -169,6 +170,24 @@ void OS::post_start()
169170
printf(" +--> Running [ %s ]\n", Service::name());
170171
FILLINE('~');
171172

173+
// if we have disabled important checks, its unsafe for production
174+
#if defined(LIBFUZZER_ENABLED) || defined(ARP_PASSTHROUGH) || defined(DISABLE_INET_CHECKSUMS)
175+
const bool unsafe = true;
176+
#else
177+
// if we dont have a good random source, its unsafe for production
178+
const bool unsafe = !CPUID::has_feature(CPUID::Feature::RDSEED)
179+
&& !CPUID::has_feature(CPUID::Feature::RDRAND);
180+
#endif
181+
if (unsafe) {
182+
printf(" +--> WARNiNG: Environment unsafe for production\n");
183+
if (is_for_production_use()) {
184+
printf(" +--> Stop option enabled. Shutting down now...\n");
185+
OS::shutdown();
186+
return;
187+
}
188+
FILLINE('~');
189+
}
190+
172191
Service::start();
173192
}
174193

0 commit comments

Comments
 (0)