4
$\begingroup$

While researching the topic of random number generation, especially practical aspects of using TRNG devices on different platforms, I found this code in MacOS kernel sources.

int
write_random(void* buffer, u_int numbytes)
{
#if 0
    int     retval = 0;
    prngContextp    pp;

    lck_mtx_lock(gPRNGMutex);

    pp = current_prng_context();

    if (ccdrbg_reseed(prng_infop(pp), pp->statep,
              bytesToInput, rdBuffer, 0, NULL) != 0)
        retval = EIO;

    lck_mtx_unlock(gPRNGMutex);
    return retval;
#else
#pragma  unused(buffer, numbytes)
    return 0;
#endif

Unless I'm wrong, this code snippet means that MacOS's random number generator cannot ever be manually reseeded by writing random data to /dev/random.

Is there some good reason for not allowing user-level reseeding in an operating system's random number generator?

Or maybe there are some other ways to do it? (Using securityd somehow?)

$\endgroup$
2
+50
$\begingroup$

I can only guess at Apple's specific reason for this. But a good reason for not allowing user-level reseeding is explained in a post by D.J. Bernstein here.

Consider two secure sources of entropy $x, y$, and a malicious source $z$:

  1. Generate a random $r$.
  2. Try computing $H(x,y,r)$.
  3. If $H(x,y,r)$ doesn't start with bits 0000, go back to step 1.
  4. Output $r$ as $z$.

For some crypto applications (i.e. DSA and ECDSA), being able to consistently predict as few as 4 bits of randomness could lead to a complete break (in the case of (EC)DSA, the recovery of the secret key).

In this case, allowing user-level reseeding is precisely what could allow this kind of attack, since it would be the last source added.

Like he says, there doesn't appear to be a good reason to be adding new entropy to the PRNG all the time, since many cryptographic applications (e.g. EdDSA) show it is perfectly possible to deterministically expand 256 bits of quality randomness into an unending stream of secure randomness. Needing to add entropy just indicates your PRNG has been compromised at some point in the past and everything you've done since should be considered utterly broken. Instead, generating high quality entropy once and keeping it safe is a much better idea.

It seems Apple has taken that approach.

|improve this answer|||||
$\endgroup$
  • $\begingroup$ I'll ask the same thing here. But how do you expect TRNG devices to work?.. $\endgroup$ – Ivan Anishchuk Dec 20 '16 at 17:37
  • $\begingroup$ And, sorry, can you link to a particular post, not just to the blog? $\endgroup$ – Ivan Anishchuk Dec 20 '16 at 17:40
  • $\begingroup$ Apologies, I fixed the link. And what do you mean, "how do I expect TRNG devices to work"? The idea is that you shouldn't need them, because you don't actually need as much entropy as people seem to think. If you manage to securely generate a 256 bit key, you can deterministically generate all the randomness you would ever need. If this isn't possible, a lot of cryptographic constructs are broken. $\endgroup$ – bkjvbx Dec 20 '16 at 21:27
  • $\begingroup$ To, in short: If it was allowed and the attacker was able to obtain the state, she would – under some extra conditions – be also able to able to modify the RNG state in some limited way. In other words, the preconditions for the attacks are quite strong (an already severely compromised system, I would say). $\endgroup$ – v6ak Dec 21 '16 at 7:06
  • $\begingroup$ @v6ak The preconditions are quite strong indeed! But these preconditions are the very argument that people use for adding entropy to a PRNG. $\endgroup$ – bkjvbx Dec 21 '16 at 17:43
1
$\begingroup$

I don't know Apple's reasons, but I have never been comfortable with user-level reseeding. One problem in Linux is the fact that /dev/random will block if it does not have enough entropy. But allowing regular users to reseed it manually gives rise to the following problem.

Here's an example from my Debian machine. Running the following command, we see the amount of entropy available:

$ sysctl kernel.random.entropy_avail 
kernel.random.entropy_avail = 919

That's pretty good. But we can reseed this with zeroes while dumping the output of /dev/random to /dev/null to exhaust the system entropy quite easily without even having root privileges

$ cat /dev/random > /dev/null && cat /dev/zero > /dev/random

Leaving this running for a few seconds leaves us with the following:

$ sysctl kernel.random.entropy_avail 
kernel.random.entropy_avail = 3

This is not good. Now if we try to use /dev/random, it takes forever because it is blocking until it has enough entropy available, which it will never have as long as the above command is running. Any crypto applications that rely on /dev/random (and there are quite a few) will be stuck waiting or may fall back to less secure methods. According to the documentation, applications reading from /dev/urandom could be getting very low quality random numbers that are vulnerable to attack if the entropy pool is low.

This blocking behavior of /dev/random is not present in OS X or the BSDs, but the problem of user-level reseeding remains. Seeding is something best left to the kernel as it has access to hardware devices from which it can gather environmental noise. If this is done properly, it is good enough. Allowing users to reseed creates the opportunity for someone to tamper with the seeding as shown above and does not provide any security benefits that a well-seeded kernel CSPRNG does not.

|improve this answer|||||
$\endgroup$
  • $\begingroup$ Well, no critical crypto app should use urandom but otherwise I see your point. How do you expect TRNG devices to work without userspace reseeding? $\endgroup$ – Ivan Anishchuk Dec 20 '16 at 17:34
  • $\begingroup$ Actually, urandom is fine; it's only a potential problem if someone is deliberately poisoning the seed. I don't see the point in seeding the system RNG with a TRNG unless you can't trust the kernel to do it properly. In that case, the solution is to fix the kernel, not accept arbitrary seeds from anyone. Of course, a TRNG does not strictly require user-level seeding; it could be used by the kernel as one of its sources, similar to the case of Intel's RNG . Or its output could be used directly by the application, skipping the system RNG entirely, as many HSMs do. $\endgroup$ – user40185 Dec 20 '16 at 18:02
  • $\begingroup$ For more discussion of seeds, see this answer $\endgroup$ – user40185 Dec 20 '16 at 18:06
  • $\begingroup$ Sorry. I though we were discussing practical matters. Yes, in an ideal world you can totally patch gpg and any other software and kernel and anything to support your device. And any device.In practice it means nobody using it and seeding PRNG from sources of unknown quality. $\endgroup$ – Ivan Anishchuk Dec 20 '16 at 18:06
  • $\begingroup$ The command cat /dev/random > /dev/null && cat /dev/zero > /dev/random does sometrhing else. Yes, it decreases the entropy estimate, which could be a kind of DoS from a local user. The second part will run iff the first cat command returned 0, that is, probably never. But even if it was executed, it would not increase entropy estimate. An ordinary user cannot do so. (If she can, it is a vulnerability and it should be reported.) Moreover, even if the attacker is able to reseed the RNG (on Linux, any local user usually can), she can only add some more entropy, not decrease it. $\endgroup$ – v6ak Dec 21 '16 at 7:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.