You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ottery_entropy_rdrand.c 1.8KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /* Libottery by Nick Mathewson.
  2. This software has been dedicated to the public domain under the CC0
  3. public domain dedication.
  4. To the extent possible under law, the person who associated CC0 with
  5. libottery has waived all copyright and related or neighboring rights
  6. to libottery.
  7. You should have received a copy of the CC0 legalcode along with this
  8. work in doc/cc0.txt. If not, see
  9. <http://creativecommons.org/publicdomain/zero/1.0/>.
  10. */
  11. #if defined(i386) || \
  12. defined(__i386) || \
  13. defined(__x86_64) || \
  14. defined(__M_IX86) || \
  15. defined(_M_IX86) || \
  16. defined(__INTEL_COMPILER)
  17. extern int ottery_valgrind_;
  18. /** Helper: invoke the RDRAND instruction to get 4 random bytes in the output
  19. * value. Return 1 on success, and 0 on failure. */
  20. #define rdrand32(x) ({ unsigned char err = 0; __asm volatile(".byte 0x0f; .byte 0xc7; .byte 0xf0; setc %1":"=a"(x), "=qm"(err) :"a"(0) :"cc"); err; })
  21. /** Generate bytes using the Intel RDRAND instruction. */
  22. static int
  23. ottery_get_entropy_rdrand(const struct ottery_entropy_config *cfg,
  24. struct ottery_entropy_state *state,
  25. uint8_t *out, size_t outlen)
  26. {
  27. uint32_t up;
  28. (void) cfg;
  29. (void) state;
  30. if (! (ottery_get_cpu_capabilities_() & OTTERY_CPUCAP_RAND) || ottery_valgrind_)
  31. return OTTERY_ERR_INIT_STRONG_RNG;
  32. while (outlen >= 4) {
  33. if (rdrand32(up) != 1)
  34. return OTTERY_ERR_INIT_STRONG_RNG;
  35. memcpy (out, &up, sizeof (up));
  36. out += sizeof (up);
  37. outlen -= 4;
  38. }
  39. if (outlen) {
  40. if (rdrand32(up) != 1)
  41. return OTTERY_ERR_INIT_STRONG_RNG;
  42. memcpy(out, &up, outlen);
  43. }
  44. return 0;
  45. }
  46. #define ENTROPY_SOURCE_RDRAND \
  47. { ottery_get_entropy_rdrand, SRC(RDRAND)|DOM(CPU)|FL(FAST)|FL(STRONG) }
  48. #endif