diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2022-04-20 15:27:29 +0200 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2022-04-20 15:42:53 +0200 |
commit | 31ec481baf106cf9c6d8f34ae6a55ab1738dea6f (patch) | |
tree | 1e7b88e2a22092d635a7c68e03b7b87da5205f57 /util-linux | |
parent | 453857899616acf1c77d0d02a4c2989b2cf5f1eb (diff) | |
download | busybox-w32-31ec481baf106cf9c6d8f34ae6a55ab1738dea6f.tar.gz busybox-w32-31ec481baf106cf9c6d8f34ae6a55ab1738dea6f.tar.bz2 busybox-w32-31ec481baf106cf9c6d8f34ae6a55ab1738dea6f.zip |
seedrng: hoist bb_strtoul out of min/max
- Hoist bb_strtoul out of min/max to prevent quadruple evaluation.
- Don't use separate variables for boottime/realtime.
- Make use of ENABLE_FEATURE_CLEAN_UP where appropriate.
- Order hash initialization after lock taking per Bernhard's taste.
- Add comment description of theory of operation.
function old new delta
seed_from_file_if_exists 533 456 -77
seedrng_main 1218 1086 -132
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-209) Total: -209 bytes
text data bss dec hex filename
976445 4227 1848 982520 efdf8 busybox_old
976236 4227 1848 982311 efd27 busybox_unstripped
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'util-linux')
-rw-r--r-- | util-linux/seedrng.c | 46 |
1 files changed, 32 insertions, 14 deletions
diff --git a/util-linux/seedrng.c b/util-linux/seedrng.c index d82a942aa..1bceae405 100644 --- a/util-linux/seedrng.c +++ b/util-linux/seedrng.c | |||
@@ -2,11 +2,26 @@ | |||
2 | /* | 2 | /* |
3 | * Copyright (C) 2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. | 3 | * Copyright (C) 2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. |
4 | * | 4 | * |
5 | * SeedRNG is a simple program made for seeding the Linux kernel random number | ||
6 | * generator from seed files. It is is useful in light of the fact that the | ||
7 | * Linux kernel RNG cannot be initialized from shell scripts, and new seeds | ||
8 | * cannot be safely generated from boot time shell scripts either. It should | ||
9 | * be run once at init time and once at shutdown time. It can be run at other | ||
10 | * times on a timer as well. Whenever it is run, it writes existing seed files | ||
11 | * into the RNG pool, and then creates a new seed file. If the RNG is | ||
12 | * initialized at the time of creating a new seed file, then that new seed file | ||
13 | * is marked as "creditable", which means it can be used to initialize the RNG. | ||
14 | * Otherwise, it is marked as "non-creditable", in which case it is still used | ||
15 | * to seed the RNG's pool, but will not initialize the RNG. In order to ensure | ||
16 | * that entropy only ever stays the same or increases from one seed file to the | ||
17 | * next, old seed values are hashed together with new seed values when writing | ||
18 | * new seed files. | ||
19 | * | ||
5 | * This is based on code from <https://git.zx2c4.com/seedrng/about/>. | 20 | * This is based on code from <https://git.zx2c4.com/seedrng/about/>. |
6 | */ | 21 | */ |
7 | 22 | ||
8 | //config:config SEEDRNG | 23 | //config:config SEEDRNG |
9 | //config: bool "seedrng (2.6 kb)" | 24 | //config: bool "seedrng (2.5 kb)" |
10 | //config: default y | 25 | //config: default y |
11 | //config: help | 26 | //config: help |
12 | //config: Seed the kernel RNG from seed files, meant to be called | 27 | //config: Seed the kernel RNG from seed files, meant to be called |
@@ -71,12 +86,14 @@ enum seedrng_lengths { | |||
71 | static size_t determine_optimal_seed_len(void) | 86 | static size_t determine_optimal_seed_len(void) |
72 | { | 87 | { |
73 | char poolsize_str[11] = { 0 }; | 88 | char poolsize_str[11] = { 0 }; |
89 | unsigned long poolsize; | ||
74 | 90 | ||
75 | if (open_read_close("/proc/sys/kernel/random/poolsize", poolsize_str, sizeof(poolsize_str) - 1) < 0) { | 91 | if (open_read_close("/proc/sys/kernel/random/poolsize", poolsize_str, sizeof(poolsize_str) - 1) < 0) { |
76 | bb_perror_msg("unable to determine pool size, falling back to %u bits", MIN_SEED_LEN * 8); | 92 | bb_perror_msg("unable to determine pool size, falling back to %u bits", MIN_SEED_LEN * 8); |
77 | return MIN_SEED_LEN; | 93 | return MIN_SEED_LEN; |
78 | } | 94 | } |
79 | return MAX(MIN((bb_strtoul(poolsize_str, NULL, 10) + 7) / 8, MAX_SEED_LEN), MIN_SEED_LEN); | 95 | poolsize = (bb_strtoul(poolsize_str, NULL, 10) + 7) / 8; |
96 | return MAX(MIN(poolsize, MAX_SEED_LEN), MIN_SEED_LEN); | ||
80 | } | 97 | } |
81 | 98 | ||
82 | static int read_new_seed(uint8_t *seed, size_t len, bool *is_creditable) | 99 | static int read_new_seed(uint8_t *seed, size_t len, bool *is_creditable) |
@@ -130,7 +147,8 @@ static int seed_rng(uint8_t *seed, size_t len, bool credit) | |||
130 | ret = ioctl(random_fd, RNDADDENTROPY, &req); | 147 | ret = ioctl(random_fd, RNDADDENTROPY, &req); |
131 | if (ret) | 148 | if (ret) |
132 | ret = -errno ? -errno : -EIO; | 149 | ret = -errno ? -errno : -EIO; |
133 | close(random_fd); | 150 | if (ENABLE_FEATURE_CLEAN_UP) |
151 | close(random_fd); | ||
134 | errno = -ret; | 152 | errno = -ret; |
135 | return ret ? -1 : 0; | 153 | return ret ? -1 : 0; |
136 | } | 154 | } |
@@ -171,7 +189,7 @@ static int seed_from_file_if_exists(const char *filename, bool credit, sha256_ct | |||
171 | if (ret < 0) | 189 | if (ret < 0) |
172 | bb_simple_perror_msg("unable to seed"); | 190 | bb_simple_perror_msg("unable to seed"); |
173 | out: | 191 | out: |
174 | if (dfd >= 0) | 192 | if (ENABLE_FEATURE_CLEAN_UP && dfd >= 0) |
175 | close(dfd); | 193 | close(dfd); |
176 | errno = -ret; | 194 | errno = -ret; |
177 | return ret ? -1 : 0; | 195 | return ret ? -1 : 0; |
@@ -187,7 +205,7 @@ int seedrng_main(int argc UNUSED_PARAM, char *argv[]) | |||
187 | size_t new_seed_len; | 205 | size_t new_seed_len; |
188 | bool new_seed_creditable; | 206 | bool new_seed_creditable; |
189 | bool skip_credit = false; | 207 | bool skip_credit = false; |
190 | struct timespec realtime = { 0 }, boottime = { 0 }; | 208 | struct timespec timestamp = { 0 }; |
191 | sha256_ctx_t hash; | 209 | sha256_ctx_t hash; |
192 | 210 | ||
193 | int opt; | 211 | int opt; |
@@ -217,13 +235,6 @@ int seedrng_main(int argc UNUSED_PARAM, char *argv[]) | |||
217 | if (getuid()) | 235 | if (getuid()) |
218 | bb_simple_error_msg_and_die("this program requires root"); | 236 | bb_simple_error_msg_and_die("this program requires root"); |
219 | 237 | ||
220 | sha256_begin(&hash); | ||
221 | sha256_hash(&hash, seedrng_prefix, strlen(seedrng_prefix)); | ||
222 | clock_gettime(CLOCK_REALTIME, &realtime); | ||
223 | clock_gettime(CLOCK_BOOTTIME, &boottime); | ||
224 | sha256_hash(&hash, &realtime, sizeof(realtime)); | ||
225 | sha256_hash(&hash, &boottime, sizeof(boottime)); | ||
226 | |||
227 | if (mkdir(seed_dir, 0700) < 0 && errno != EEXIST) | 238 | if (mkdir(seed_dir, 0700) < 0 && errno != EEXIST) |
228 | bb_simple_perror_msg_and_die("unable to create seed directory"); | 239 | bb_simple_perror_msg_and_die("unable to create seed directory"); |
229 | 240 | ||
@@ -234,6 +245,13 @@ int seedrng_main(int argc UNUSED_PARAM, char *argv[]) | |||
234 | goto out; | 245 | goto out; |
235 | } | 246 | } |
236 | 247 | ||
248 | sha256_begin(&hash); | ||
249 | sha256_hash(&hash, seedrng_prefix, strlen(seedrng_prefix)); | ||
250 | clock_gettime(CLOCK_REALTIME, ×tamp); | ||
251 | sha256_hash(&hash, ×tamp, sizeof(timestamp)); | ||
252 | clock_gettime(CLOCK_BOOTTIME, ×tamp); | ||
253 | sha256_hash(&hash, ×tamp, sizeof(timestamp)); | ||
254 | |||
237 | ret = seed_from_file_if_exists(non_creditable_seed, false, &hash); | 255 | ret = seed_from_file_if_exists(non_creditable_seed, false, &hash); |
238 | if (ret < 0) | 256 | if (ret < 0) |
239 | program_ret |= 1 << 1; | 257 | program_ret |= 1 << 1; |
@@ -270,9 +288,9 @@ int seedrng_main(int argc UNUSED_PARAM, char *argv[]) | |||
270 | program_ret |= 1 << 6; | 288 | program_ret |= 1 << 6; |
271 | } | 289 | } |
272 | out: | 290 | out: |
273 | if (fd >= 0) | 291 | if (ENABLE_FEATURE_CLEAN_UP && fd >= 0) |
274 | close(fd); | 292 | close(fd); |
275 | if (lock >= 0) | 293 | if (ENABLE_FEATURE_CLEAN_UP && lock >= 0) |
276 | close(lock); | 294 | close(lock); |
277 | return program_ret; | 295 | return program_ret; |
278 | } | 296 | } |