It should be taking advantage of hardware CSPRNGs automatically, saving / restoring entropy via pstore and using entropy passed from the previous boot stage. Unfortunately, if you aren't using the EFI boot stub, the kernel skips using the EFI random protocol as an early seed.
Conversation
They use pstore to store kernel panics but for some reason no one has ever realized that they could be regularly storing CSPRNG output and then using that as an additional source of entropy on boot rather than leaving this up to init. Init should be dealing with this too though.
1
It doesn't credit EFI or hardware CSPRNGs for generating entropy so a system with a cycle counter ends up handling this via jitter entropy when there's finally a blocking call to getrandom and an embedded system without one won't have an initialized CSPRNG state for a long time.
2
Yes. I think AT_RANDOM is fine for hardening only but useless in my context (need to support arbitrary old/bad kernels) for arc4random, getentropy fallback, etc.
1
I'm actually thinking about trying to implement a fallback in userspace with a chaotic feedback loop of timing memory accesses at addresses controlled by output of previous iterations (something like jitter).
1
Linux 3.17+ provides getrandom so that pretty much covers everything getting meaningful security patches. I wouldn't worry about perfection on older systems. The main issue is handling getrandom blocking on newer systems. I think a normal build of musl should probably just block.
2
If you use getrandom with GRND_NONBLOCK, I don't think the kernel will try to force initialization. You could use that to detect that it isn't initialized and spend a certain amount of time trying to force initialization. I think you should ultimately just fall back to blocking.
1
Ideally, you should be trying to force the kernel CSPRNG to be initialized. If someone uses musl across the system, you will end up doing init's job for it and then everything else will succeed calling getrandom. I don't know what exactly you're allowed to do as libc though.
1
So for example, init can and should do something like spawning a thread pool randomly piping garbage between each other which will fix the problem quickly. Since you probably can't do that, maybe you could use timers. Keep going until getrandom GRND_NONBLOCK doesn't say EAGAIN.
1
1
The issue that will happen in practice otherwise is that init will call getrandom when libc tries to initialize arc4random. Kernels that are more than a few months old will just sit there blocking, and init will just sit there blocking. Problem may not correct itself for ages.
1
1
So, code using getrandom that wants to be friendly to older kernels or screwed up embedded systems needs to actively do something to cause interrupts. Spawning threads would really be the best / fastest way but timers in a single thread could at least make progress to fixing it.
Here's roughly the idea I had in mind, very different (doing it all in userspace, screw the kernel). I think the basic idea is sound unless you have a really dumb machine with no cache, modern dram, mmu/tlb misses, etc.
Quote Tweet
Really stupid userspace-entropy harvester, wonder if it actually works: ix.io/2ltF Basic idea is a[n intended-to-be] chaotic feedback loop of timings of memory accesses.

