Re: [kernel-hardening] Re: get_random_bytes returns bad randomness before seeding is complete
On 3 June 2017 at 18:54, Jeffrey Waltonwrote: > On Sat, Jun 3, 2017 at 5:45 PM, Sandy Harris wrote: >> ... >> Of course this will fail on systems with no high-res timer. Are there >> still some of those? It might be done in about 1000 times as long on a >> system that lacks the realtime library's nanosecond timer but has the >> Posix standard microsecond timer, implying a delay time in the >> milliseconds. Would that be acceptable in those cases? > > A significant portion of the use cases should include mobile devices. > Device sales outnumbered desktop and server sales several years ago. > > Many devices are sensor rich. Even the low-end ones come with > accelorometers for gaming. A typical one has 3 or 4 sensors, and > higher-end ones have 7 or 8 sensors. An Evo 4G has 7 of them. > > There's no wanting for entropy in many of the use cases. The thing > that is lacking seems to be taking advantage of it. > > Jeff Hardware random number generator support is also standard on even low-end mobile devices. The Linux kernel now knows to feed some of the entropy from those hardware random generators into the kernel CSPRNG when the driver is initialized but that doesn't happen until fairly late in the kernel's boot process. The sensors present the same issue. They aren't available when the kernel starts needing entropy for features like SSP and KASLR or other early boot uses, unlike RDRAND/RDSEED on modern x86_64 CPUs. For userspace, Android's init system blocks until a certain amount of entropy is obtained from one for the kernel CSPRNG. It's possible for there to be no hwrandom but I think that's very rare now since the standard SoCs used everywhere have it available. The device vendor would probably need to go out of the way to break it. Android also regularly saves a persistent random seed and restores it on boot. It also mixes in entropy from the hardware generator regularly since the kernel didn't know how to do that before, just like it didn't know how to grab any initial entropy from the hardware generator. I don't think it's worth worrying too much about mobile. Slimmer embedded devices that probably don't even save / restore a seed in many cases or generate keys on first boot before that helps are the real issue. At least if you're not focused on KASLR and other early probabilistic kernel exploit mitigations where there's a lack of a way to get entropy in early boot right now unless the bootloader helps.
Re: [kernel-hardening] Re: get_random_bytes returns bad randomness before seeding is complete
The only sensible & general solution for the initialisation problem that I have seen is John Denker's. http://www.av8n.com/computer/htm/secure-random.htm#sec-boot-image If I read that right, it would require only minor kernel changes & none to the API Ted & others are worrying about. It would be secure except against an enemy who can read your kernel image or interfere with your install process. Assuming permissions are set sensibly, that means an enemy who already has root & such an enemy has lots of much easier ways to break things, so we need not worry about that case. The difficulty is that it would require significant changes to installation scripts. Still, since it is a general solution to a real problem, it might be better to implement that rather than work on the other suggestions in the thread.
Re: [kernel-hardening] Re: get_random_bytes returns bad randomness before seeding is complete
On Fri, Jun 2, 2017 at 10:41 AM, Daniel Micaywrote: > On Fri, 2017-06-02 at 17:53 +0200, Jason A. Donenfeld wrote: >> (Meanwhile...) >> >> In my own code, I'm currently playing with a workaround that looks >> like this: >> >> --- a/src/main.c >> +++ b/src/main.c >> >> +#include >> +#include >> >> +struct rng_initializer { >> + struct completion done; >> + struct random_ready_callback cb; >> +}; >> +static void rng_initialized_callback(struct random_ready_callback >> *cb) >> +{ >> + complete(_of(cb, struct rng_initializer, cb)->done); >> +} >> + >> static int __init mod_init(void) >> { >>int ret; >> + struct rng_initializer rng = { >> + .done = COMPLETION_INITIALIZER(rng.done), >> + .cb = { .owner = THIS_MODULE, .func = >> rng_initialized_callback } >> + }; >> + >> + ret = add_random_ready_callback(); >> + if (!ret) >> + wait_for_completion(); >> + else if (ret != -EALREADY) >> + return ret; >> >>do_things_with_get_random_bytes_maybe(); >> >> Depending on the situation, however, I could imagine that >> wait_for_completion never returning, if its blocking activity that >> contributes to the seed actually being available, if this is called >> from a compiled-in module, so I find this a bit sub-optimal... > > One of the early uses is initializing the stack canary value for SSP in > very early boot. If that blocks, it's going to be blocking nearly > anything else from happening. > > On x86, that's only the initial canary since the per-task canaries end > up being used, but elsewhere at least without SMP disabled or changes to > GCC that's all there is so the entropy matters. And just to note, building with GCC_PLUGIN_LATENT_ENTROPY, while it (correctly) doesn't credit entropy to the pool, should at least make the pool less deterministic between boots. -Kees -- Kees Cook Pixel Security
Re: [kernel-hardening] Re: get_random_bytes returns bad randomness before seeding is complete
On Fri, Jun 2, 2017 at 7:41 PM, Daniel Micaywrote: > One of the early uses is initializing the stack canary value for SSP in > very early boot. If that blocks, it's going to be blocking nearly > anything else from happening. > > On x86, that's only the initial canary since the per-task canaries end > up being used, but elsewhere at least without SMP disabled or changes to > GCC that's all there is so the entropy matters. If this is the case, then we simply need a function called get_random_bytes_but_potentially_crappy_ones_because_we_are_desperate_for_anything(), which would respond with a weaker guarantee than that get_random_bytes(), which the documentation says always returns cryptographically secure numbers.
Re: [kernel-hardening] Re: get_random_bytes returns bad randomness before seeding is complete
On Fri, 2017-06-02 at 17:53 +0200, Jason A. Donenfeld wrote: > (Meanwhile...) > > In my own code, I'm currently playing with a workaround that looks > like this: > > --- a/src/main.c > +++ b/src/main.c > > +#include > +#include > > +struct rng_initializer { > + struct completion done; > + struct random_ready_callback cb; > +}; > +static void rng_initialized_callback(struct random_ready_callback > *cb) > +{ > + complete(_of(cb, struct rng_initializer, cb)->done); > +} > + > static int __init mod_init(void) > { >int ret; > + struct rng_initializer rng = { > + .done = COMPLETION_INITIALIZER(rng.done), > + .cb = { .owner = THIS_MODULE, .func = > rng_initialized_callback } > + }; > + > + ret = add_random_ready_callback(); > + if (!ret) > + wait_for_completion(); > + else if (ret != -EALREADY) > + return ret; > >do_things_with_get_random_bytes_maybe(); > > Depending on the situation, however, I could imagine that > wait_for_completion never returning, if its blocking activity that > contributes to the seed actually being available, if this is called > from a compiled-in module, so I find this a bit sub-optimal... One of the early uses is initializing the stack canary value for SSP in very early boot. If that blocks, it's going to be blocking nearly anything else from happening. On x86, that's only the initial canary since the per-task canaries end up being used, but elsewhere at least without SMP disabled or changes to GCC that's all there is so the entropy matters.