Skip to content

Commit 4170fbc

Browse files
committed
rng: Initialize per CPU
1 parent ae78de7 commit 4170fbc

3 files changed

Lines changed: 46 additions & 30 deletions

File tree

api/kernel/rng.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
99
// You may obtain a copy of the License at
10-
//
10+
//
1111
// http://www.apache.org/licenses/LICENSE-2.0
12-
//
12+
//
1313
// Unless required by applicable law or agreed to in writing, software
1414
// distributed under the License is distributed on an "AS IS" BASIS,
1515
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -40,5 +40,10 @@ inline uint32_t rng_extract_uint32()
4040
return x;
4141
}
4242

43+
struct RNG
44+
{
45+
static void init();
46+
};
47+
4348

4449
#endif

src/kernel/os.cpp

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -165,26 +165,7 @@ void OS::start(uint32_t boot_magic, uint32_t boot_addr)
165165

166166
MYINFO("Initializing RNG");
167167
PROFILE("RNG init");
168-
// initialize random seed based on cycles since start
169-
if (CPUID::has_feature(CPUID::Feature::RDRAND)) {
170-
uint32_t rdrand_output[32];
171-
172-
for (size_t i = 0; i != 32; ++i) {
173-
while (!rdrand32(&rdrand_output[i])) {}
174-
}
175-
176-
rng_absorb(rdrand_output, sizeof(rdrand_output));
177-
}
178-
else {
179-
// this is horrible, better solution needed here
180-
for (size_t i = 0; i != 32; ++i) {
181-
uint64_t clock = cycles_since_boot();
182-
// maybe additionally call something which will take
183-
// variable time depending in some way on the processor
184-
// state (clflush?) or a HAVEGE-like approach.
185-
rng_absorb(&clock, sizeof(clock));
186-
}
187-
}
168+
RNG::init();
188169

189170
// Seed rand with 32 bits from RNG
190171
srand(rng_extract_uint32());

src/kernel/rng.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,28 @@
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
88
// You may obtain a copy of the License at
9-
//
9+
//
1010
// http://www.apache.org/licenses/LICENSE-2.0
11-
//
11+
//
1212
// Unless required by applicable law or agreed to in writing, software
1313
// distributed under the License is distributed on an "AS IS" BASIS,
1414
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1515
// See the License for the specific language governing permissions and
1616
// limitations under the License.
1717

1818
#include <kernel/rng.hpp>
19-
#include <kernel/rdrand.hpp>
2019
#include <kernel/cpuid.hpp>
20+
#include <kernel/os.hpp>
21+
#include <kernel/rdrand.hpp>
2122
#include <algorithm>
2223
#include <cstring>
24+
#include <smp>
2325

24-
static uint64_t rng_state[25];
26+
struct rng_state
27+
{
28+
uint64_t state[25];
29+
};
30+
static SMP_ARRAY<rng_state> rng;
2531

2632
static inline uint64_t rotate_left(uint64_t input, size_t rot) {
2733
return (input << rot) | (input >> (64-rot));
@@ -125,10 +131,10 @@ void rng_absorb(const void* input, size_t bytes)
125131
size_t absorbing = std::min<size_t>(bytes - absorbed, SHAKE_128_RATE);
126132

127133
xor_bytes(static_cast<const uint8_t*>(input) + absorbed,
128-
reinterpret_cast<uint8_t*>(rng_state),
134+
reinterpret_cast<uint8_t*>(PER_CPU(rng).state),
129135
absorbing);
130136

131-
keccak_1600_p(rng_state);
137+
keccak_1600_p(PER_CPU(rng).state);
132138
absorbed += absorbing;
133139
}
134140
}
@@ -140,8 +146,32 @@ void rng_extract(void* output, size_t bytes)
140146
while(copied < bytes)
141147
{
142148
size_t copying = std::min<size_t>(bytes - copied, SHAKE_128_RATE);
143-
memcpy(static_cast<uint8_t*>(output) + copied, rng_state, copying);
144-
keccak_1600_p(rng_state);
149+
memcpy(static_cast<uint8_t*>(output) + copied, PER_CPU(rng).state, copying);
150+
keccak_1600_p(PER_CPU(rng).state);
145151
copied += copying;
146152
}
147153
}
154+
155+
void RNG::init()
156+
{
157+
// initialize random seed based on cycles since start
158+
if (CPUID::has_feature(CPUID::Feature::RDRAND)) {
159+
uint32_t rdrand_output[32];
160+
161+
for (size_t i = 0; i != 32; ++i) {
162+
while (!rdrand32(&rdrand_output[i])) {}
163+
}
164+
165+
rng_absorb(rdrand_output, sizeof(rdrand_output));
166+
}
167+
else {
168+
// this is horrible, better solution needed here
169+
for (size_t i = 0; i != 32; ++i) {
170+
uint64_t clock = OS::cycles_since_boot();
171+
// maybe additionally call something which will take
172+
// variable time depending in some way on the processor
173+
// state (clflush?) or a HAVEGE-like approach.
174+
rng_absorb(&clock, sizeof(clock));
175+
}
176+
}
177+
}

0 commit comments

Comments
 (0)