title: Is there any legitimate use for Intel's RDRAND?
body: <p>Today I thought: well, even if there is great suspicion on RDRAND implementation of <a href="http://en.wikipedia.org/wiki/NIST_SP_800-90A" rel="noreferrer">NIST SP 800-90A</a>, it is still a hardware implementation of pseudo-random number generator (PRNG) that must be good enough for non-sensitive applications. So I thought of using it on my game instead of Mersenne Twister.</p>
  <p>So, to see if there was any performance gain on using the instruction, I compared the time of the two following codes:</p>
  <pre><code>// test.cpp
  #include &lt;cstdio&gt;
  
  int main()
  {
      unsigned int rnd = 0;
      for(int i = 0; i &lt; 10000000; ++i) {
          __builtin_ia32_rdrand32_step(&amp;rnd);
      }
      printf(&quot;%x\n&quot;, rnd);
  }
  </code></pre>
  <p>and</p>
  <pre><code>//test2.cpp
  #include &lt;cstdio&gt;
  #include &lt;random&gt;
  
  int main()
  {
      unsigned int rnd = 0;
      __builtin_ia32_rdrand32_step(&amp;rnd);
      std::mt19937 gen(rnd);
      for(int i = 0; i &lt; 10000000; ++i) {
          rnd ^= gen();
      }
      printf(&quot;%x\n&quot;, rnd);
  }
  </code></pre>
  <p>and by running the two I get:</p>
  <pre><code>$ time ./test
  d230449a
  
  real    0m0.361s
  user    0m0.358s
  sys     0m0.002s
  
  $ time ./test2 
  bfc4e472
  
  real    0m0.051s
  user    0m0.050s
  sys     0m0.002s
  </code></pre>
  <p>So, Mersenne Twister is much faster than RDRAND on my CPU. Well, I was disappointed, ruled out from my game. But RDRAND is a cryptographically secure PRNG (CSPRNG), so it does much behind the scenes... more fair would be compare it to other CSPRNG. So I took my <a href="http://github.com/lvella/libestream" rel="noreferrer">Rabbit</a> implementation (plain translation of the RFC to C, no fancy tricks for performance), and wrote the following test:</p>
  <pre><code>// test3.cpp
  #include &lt;cstdio&gt;
  
  extern &quot;C&quot;
  {
  #include &quot;rabbit.h&quot;
  }
  
  int main()
  {
      rabbit_state s;
      unsigned long long buf[2];
      __builtin_ia32_rdrand64_step(&amp;buf[0]);
      __builtin_ia32_rdrand64_step(&amp;buf[1]);
      rabbit_init_key(&amp;s, (uint8_t*)&amp;buf[0]);
  
      for(int i = 0; i &lt; 10000000; ++i) {
          rabbit_extract(&amp;s, (uint8_t*)&amp;buf[0]);
      }
      printf(&quot;%llx\n&quot;, buf[0]);
  }
  </code></pre>
  <p>And for my surprise, generating twice as much pseudo-random data as the first two of them, I got a better time than RDRAND:</p>
  <pre><code>$ time ./test3 
  8ef9772277b70aba
  
  real    0m0.344s
  user    0m0.341s
  sys     0m0.002s
  </code></pre>
  <p>All three were compiled with optimization enabled.</p>
  <p>So, we have a widespread paranoia that RDRAND was made to embed NSA backdoors into everybody's software cryptography. Also we have at least one software CSPRNG faster than RDRAND, and the most widely used decent PRNG, Mersenne Twister, is <em>much</em> faster than RDRAND. Finally, we have open-source auditable software entropy pools, like <code>/dev/random</code> and <code>/dev/urandom</code>, that are not hidden behind twofold scrambler layers of AES, like RDRAND.</p>
  <p>So, the question: should people be using RDRAND? Is there any legitimate use for it? Or should we stop using it altogether?</p>