Skip to content

Commit da2862e

Browse files
zx2c4bluca
authored andcommitted
random-seed: hash together old seed and new seed before writing out file
If we're consuming an on-disk seed, we usually write out a new one after consuming it. In that case, we might be at early boot and the randomness could be rather poor, and the kernel doesn't guarantee that it'll use the new randomness right away for us. In order to prevent the new entropy from getting any worse, hash together the old seed and the new seed, and replace the final bytes of the new seed with the hash output. This way, entropy strictly increases and never regresses. Fixes: systemd#21983 Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
1 parent 948d085 commit da2862e

File tree

1 file changed

+25
-1
lines changed

1 file changed

+25
-1
lines changed

src/random-seed/random-seed.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "random-util.h"
2727
#include "string-util.h"
2828
#include "sync-util.h"
29+
#include "sha256.h"
2930
#include "util.h"
3031
#include "xattr-util.h"
3132

@@ -106,9 +107,11 @@ static int run(int argc, char *argv[]) {
106107
_cleanup_close_ int seed_fd = -1, random_fd = -1;
107108
bool read_seed_file, write_seed_file, synchronous;
108109
_cleanup_free_ void* buf = NULL;
110+
struct sha256_ctx hash_state;
111+
uint8_t hash[32];
109112
size_t buf_size;
110113
struct stat st;
111-
ssize_t k;
114+
ssize_t k, l;
112115
int r;
113116

114117
log_setup();
@@ -242,6 +245,16 @@ static int run(int argc, char *argv[]) {
242245
if (r < 0)
243246
log_error_errno(r, "Failed to write seed to /dev/urandom: %m");
244247
}
248+
/* If we're going to later write out a seed file, initialize a hash state with
249+
* the contents of the seed file we just read, so that the new one can't regress
250+
* in entropy. */
251+
if (write_seed_file) {
252+
sha256_init_ctx(&hash_state);
253+
if (k < 0)
254+
k = 0;
255+
sha256_process_bytes(&k, sizeof(k), &hash_state);
256+
sha256_process_bytes(buf, k, &hash_state);
257+
}
245258
}
246259

247260
if (write_seed_file) {
@@ -277,6 +290,17 @@ static int run(int argc, char *argv[]) {
277290
"Got EOF while reading from /dev/urandom.");
278291
}
279292

293+
/* If we previously read in a seed file, then hash the new seed into the old one,
294+
* and replace the last 32 bytes of the seed with the hash output, so that the
295+
* new seed file can't regress in entropy. */
296+
if (read_seed_file) {
297+
sha256_process_bytes(&k, sizeof(k), &hash_state);
298+
sha256_process_bytes(buf, k, &hash_state);
299+
sha256_finish_ctx(&hash_state, hash);
300+
l = MIN(k, 32);
301+
memcpy((uint8_t *)buf + k - l, hash, l);
302+
}
303+
280304
r = loop_write(seed_fd, buf, (size_t) k, false);
281305
if (r < 0)
282306
return log_error_errno(r, "Failed to write new random seed file: %m");

0 commit comments

Comments
 (0)