random.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * Random number generator
  3. * Copyright (c) 2010-2011, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. *
  8. * This random number generator is used to provide additional entropy to the
  9. * one provided by the operating system (os_get_random()) for session key
  10. * generation. The os_get_random() output is expected to be secure and the
  11. * implementation here is expected to provide only limited protection against
  12. * cases where os_get_random() cannot provide strong randomness. This
  13. * implementation shall not be assumed to be secure as the sole source of
  14. * randomness. The random_get_bytes() function mixes in randomness from
  15. * os_get_random() and as such, calls to os_get_random() can be replaced with
  16. * calls to random_get_bytes() without reducing security.
  17. *
  18. * The design here follows partially the design used in the Linux
  19. * drivers/char/random.c, but the implementation here is simpler and not as
  20. * strong. This is a compromise to reduce duplicated CPU effort and to avoid
  21. * extra code/memory size. As pointed out above, os_get_random() needs to be
  22. * guaranteed to be secure for any of the security assumptions to hold.
  23. */
  24. #include "utils/includes.h"
  25. #ifdef __linux__
  26. #include <fcntl.h>
  27. #endif /* __linux__ */
  28. #include "utils/common.h"
  29. #include "utils/eloop.h"
  30. #include "crypto/crypto.h"
  31. #include "sha1.h"
  32. #include "random.h"
  33. #define POOL_WORDS 32
  34. #define POOL_WORDS_MASK (POOL_WORDS - 1)
  35. #define POOL_TAP1 26
  36. #define POOL_TAP2 20
  37. #define POOL_TAP3 14
  38. #define POOL_TAP4 7
  39. #define POOL_TAP5 1
  40. #define EXTRACT_LEN 16
  41. #define MIN_READY_MARK 2
  42. static u32 pool[POOL_WORDS];
  43. static unsigned int input_rotate = 0;
  44. static unsigned int pool_pos = 0;
  45. static u8 dummy_key[20];
  46. #ifdef __linux__
  47. static size_t dummy_key_avail = 0;
  48. static int random_fd = -1;
  49. #endif /* __linux__ */
  50. static unsigned int own_pool_ready = 0;
  51. #define RANDOM_ENTROPY_SIZE 20
  52. static char *random_entropy_file = NULL;
  53. static int random_entropy_file_read = 0;
  54. #define MIN_COLLECT_ENTROPY 1000
  55. static unsigned int entropy = 0;
  56. static unsigned int total_collected = 0;
  57. static void random_write_entropy(void);
  58. static u32 __ROL32(u32 x, u32 y)
  59. {
  60. return (x << (y & 31)) | (x >> (32 - (y & 31)));
  61. }
  62. static void random_mix_pool(const void *buf, size_t len)
  63. {
  64. static const u32 twist[8] = {
  65. 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
  66. 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278
  67. };
  68. const u8 *pos = buf;
  69. u32 w;
  70. wpa_hexdump_key(MSG_EXCESSIVE, "random_mix_pool", buf, len);
  71. while (len--) {
  72. w = __ROL32(*pos++, input_rotate & 31);
  73. input_rotate += pool_pos ? 7 : 14;
  74. pool_pos = (pool_pos - 1) & POOL_WORDS_MASK;
  75. w ^= pool[pool_pos];
  76. w ^= pool[(pool_pos + POOL_TAP1) & POOL_WORDS_MASK];
  77. w ^= pool[(pool_pos + POOL_TAP2) & POOL_WORDS_MASK];
  78. w ^= pool[(pool_pos + POOL_TAP3) & POOL_WORDS_MASK];
  79. w ^= pool[(pool_pos + POOL_TAP4) & POOL_WORDS_MASK];
  80. w ^= pool[(pool_pos + POOL_TAP5) & POOL_WORDS_MASK];
  81. pool[pool_pos] = (w >> 3) ^ twist[w & 7];
  82. }
  83. }
  84. static void random_extract(u8 *out)
  85. {
  86. unsigned int i;
  87. u8 hash[SHA1_MAC_LEN];
  88. u32 *hash_ptr;
  89. u32 buf[POOL_WORDS / 2];
  90. /* First, add hash back to pool to make backtracking more difficult. */
  91. hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) pool,
  92. sizeof(pool), hash);
  93. random_mix_pool(hash, sizeof(hash));
  94. /* Hash half the pool to extra data */
  95. for (i = 0; i < POOL_WORDS / 2; i++)
  96. buf[i] = pool[(pool_pos - i) & POOL_WORDS_MASK];
  97. hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) buf,
  98. sizeof(buf), hash);
  99. /*
  100. * Fold the hash to further reduce any potential output pattern.
  101. * Though, compromise this to reduce CPU use for the most common output
  102. * length (32) and return 16 bytes from instead of only half.
  103. */
  104. hash_ptr = (u32 *) hash;
  105. hash_ptr[0] ^= hash_ptr[4];
  106. os_memcpy(out, hash, EXTRACT_LEN);
  107. }
  108. void random_add_randomness(const void *buf, size_t len)
  109. {
  110. struct os_time t;
  111. static unsigned int count = 0;
  112. count++;
  113. if (entropy > MIN_COLLECT_ENTROPY && (count & 0x3ff) != 0) {
  114. /*
  115. * No need to add more entropy at this point, so save CPU and
  116. * skip the update.
  117. */
  118. return;
  119. }
  120. wpa_printf(MSG_EXCESSIVE, "Add randomness: count=%u entropy=%u",
  121. count, entropy);
  122. os_get_time(&t);
  123. wpa_hexdump_key(MSG_EXCESSIVE, "random pool",
  124. (const u8 *) pool, sizeof(pool));
  125. random_mix_pool(&t, sizeof(t));
  126. random_mix_pool(buf, len);
  127. wpa_hexdump_key(MSG_EXCESSIVE, "random pool",
  128. (const u8 *) pool, sizeof(pool));
  129. entropy++;
  130. total_collected++;
  131. }
  132. int random_get_bytes(void *buf, size_t len)
  133. {
  134. int ret;
  135. u8 *bytes = buf;
  136. size_t left;
  137. wpa_printf(MSG_MSGDUMP, "Get randomness: len=%u entropy=%u",
  138. (unsigned int) len, entropy);
  139. /* Start with assumed strong randomness from OS */
  140. ret = os_get_random(buf, len);
  141. wpa_hexdump_key(MSG_EXCESSIVE, "random from os_get_random",
  142. buf, len);
  143. /* Mix in additional entropy extracted from the internal pool */
  144. left = len;
  145. while (left) {
  146. size_t siz, i;
  147. u8 tmp[EXTRACT_LEN];
  148. random_extract(tmp);
  149. wpa_hexdump_key(MSG_EXCESSIVE, "random from internal pool",
  150. tmp, sizeof(tmp));
  151. siz = left > EXTRACT_LEN ? EXTRACT_LEN : left;
  152. for (i = 0; i < siz; i++)
  153. *bytes++ ^= tmp[i];
  154. left -= siz;
  155. }
  156. #ifdef CONFIG_FIPS
  157. /* Mix in additional entropy from the crypto module */
  158. left = len;
  159. while (left) {
  160. size_t siz, i;
  161. u8 tmp[EXTRACT_LEN];
  162. if (crypto_get_random(tmp, sizeof(tmp)) < 0) {
  163. wpa_printf(MSG_ERROR, "random: No entropy available "
  164. "for generating strong random bytes");
  165. return -1;
  166. }
  167. wpa_hexdump_key(MSG_EXCESSIVE, "random from crypto module",
  168. tmp, sizeof(tmp));
  169. siz = left > EXTRACT_LEN ? EXTRACT_LEN : left;
  170. for (i = 0; i < siz; i++)
  171. *bytes++ ^= tmp[i];
  172. left -= siz;
  173. }
  174. #endif /* CONFIG_FIPS */
  175. wpa_hexdump_key(MSG_EXCESSIVE, "mixed random", buf, len);
  176. if (entropy < len)
  177. entropy = 0;
  178. else
  179. entropy -= len;
  180. return ret;
  181. }
  182. int random_pool_ready(void)
  183. {
  184. #ifdef __linux__
  185. int fd;
  186. ssize_t res;
  187. /*
  188. * Make sure that there is reasonable entropy available before allowing
  189. * some key derivation operations to proceed.
  190. */
  191. if (dummy_key_avail == sizeof(dummy_key))
  192. return 1; /* Already initialized - good to continue */
  193. /*
  194. * Try to fetch some more data from the kernel high quality
  195. * /dev/random. There may not be enough data available at this point,
  196. * so use non-blocking read to avoid blocking the application
  197. * completely.
  198. */
  199. fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
  200. if (fd < 0) {
  201. #ifndef CONFIG_NO_STDOUT_DEBUG
  202. int error = errno;
  203. perror("open(/dev/random)");
  204. wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
  205. strerror(error));
  206. #endif /* CONFIG_NO_STDOUT_DEBUG */
  207. return -1;
  208. }
  209. res = read(fd, dummy_key + dummy_key_avail,
  210. sizeof(dummy_key) - dummy_key_avail);
  211. if (res < 0) {
  212. wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
  213. "%s", strerror(errno));
  214. res = 0;
  215. }
  216. wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from "
  217. "/dev/random", (unsigned) res,
  218. (unsigned) (sizeof(dummy_key) - dummy_key_avail));
  219. dummy_key_avail += res;
  220. close(fd);
  221. if (dummy_key_avail == sizeof(dummy_key)) {
  222. if (own_pool_ready < MIN_READY_MARK)
  223. own_pool_ready = MIN_READY_MARK;
  224. random_write_entropy();
  225. return 1;
  226. }
  227. wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
  228. "random data available from /dev/random",
  229. (unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key));
  230. if (own_pool_ready >= MIN_READY_MARK ||
  231. total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY) {
  232. wpa_printf(MSG_INFO, "random: Allow operation to proceed "
  233. "based on internal entropy");
  234. return 1;
  235. }
  236. wpa_printf(MSG_INFO, "random: Not enough entropy pool available for "
  237. "secure operations");
  238. return 0;
  239. #else /* __linux__ */
  240. /* TODO: could do similar checks on non-Linux platforms */
  241. return 1;
  242. #endif /* __linux__ */
  243. }
  244. void random_mark_pool_ready(void)
  245. {
  246. own_pool_ready++;
  247. wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be "
  248. "ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK);
  249. random_write_entropy();
  250. }
  251. #ifdef __linux__
  252. static void random_close_fd(void)
  253. {
  254. if (random_fd >= 0) {
  255. eloop_unregister_read_sock(random_fd);
  256. close(random_fd);
  257. random_fd = -1;
  258. }
  259. }
  260. static void random_read_fd(int sock, void *eloop_ctx, void *sock_ctx)
  261. {
  262. ssize_t res;
  263. if (dummy_key_avail == sizeof(dummy_key)) {
  264. random_close_fd();
  265. return;
  266. }
  267. res = read(sock, dummy_key + dummy_key_avail,
  268. sizeof(dummy_key) - dummy_key_avail);
  269. if (res < 0) {
  270. wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
  271. "%s", strerror(errno));
  272. return;
  273. }
  274. wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from /dev/random",
  275. (unsigned) res,
  276. (unsigned) (sizeof(dummy_key) - dummy_key_avail));
  277. dummy_key_avail += res;
  278. if (dummy_key_avail == sizeof(dummy_key)) {
  279. random_close_fd();
  280. if (own_pool_ready < MIN_READY_MARK)
  281. own_pool_ready = MIN_READY_MARK;
  282. random_write_entropy();
  283. }
  284. }
  285. #endif /* __linux__ */
  286. static void random_read_entropy(void)
  287. {
  288. char *buf;
  289. size_t len;
  290. if (!random_entropy_file)
  291. return;
  292. buf = os_readfile(random_entropy_file, &len);
  293. if (buf == NULL)
  294. return; /* entropy file not yet available */
  295. if (len != 1 + RANDOM_ENTROPY_SIZE) {
  296. wpa_printf(MSG_DEBUG, "random: Invalid entropy file %s",
  297. random_entropy_file);
  298. os_free(buf);
  299. return;
  300. }
  301. own_pool_ready = (u8) buf[0];
  302. random_add_randomness(buf + 1, RANDOM_ENTROPY_SIZE);
  303. random_entropy_file_read = 1;
  304. os_free(buf);
  305. wpa_printf(MSG_DEBUG, "random: Added entropy from %s "
  306. "(own_pool_ready=%u)",
  307. random_entropy_file, own_pool_ready);
  308. }
  309. static void random_write_entropy(void)
  310. {
  311. char buf[RANDOM_ENTROPY_SIZE];
  312. FILE *f;
  313. u8 opr;
  314. int fail = 0;
  315. if (!random_entropy_file)
  316. return;
  317. if (random_get_bytes(buf, RANDOM_ENTROPY_SIZE) < 0)
  318. return;
  319. f = fopen(random_entropy_file, "wb");
  320. if (f == NULL) {
  321. wpa_printf(MSG_ERROR, "random: Could not open entropy file %s "
  322. "for writing", random_entropy_file);
  323. return;
  324. }
  325. opr = own_pool_ready > 0xff ? 0xff : own_pool_ready;
  326. if (fwrite(&opr, 1, 1, f) != 1 ||
  327. fwrite(buf, RANDOM_ENTROPY_SIZE, 1, f) != 1)
  328. fail = 1;
  329. fclose(f);
  330. if (fail) {
  331. wpa_printf(MSG_ERROR, "random: Could not write entropy data "
  332. "to %s", random_entropy_file);
  333. return;
  334. }
  335. wpa_printf(MSG_DEBUG, "random: Updated entropy file %s "
  336. "(own_pool_ready=%u)",
  337. random_entropy_file, own_pool_ready);
  338. }
  339. void random_init(const char *entropy_file)
  340. {
  341. os_free(random_entropy_file);
  342. if (entropy_file)
  343. random_entropy_file = os_strdup(entropy_file);
  344. else
  345. random_entropy_file = NULL;
  346. random_read_entropy();
  347. #ifdef __linux__
  348. if (random_fd >= 0)
  349. return;
  350. random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
  351. if (random_fd < 0) {
  352. #ifndef CONFIG_NO_STDOUT_DEBUG
  353. int error = errno;
  354. perror("open(/dev/random)");
  355. wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
  356. strerror(error));
  357. #endif /* CONFIG_NO_STDOUT_DEBUG */
  358. return;
  359. }
  360. wpa_printf(MSG_DEBUG, "random: Trying to read entropy from "
  361. "/dev/random");
  362. eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL);
  363. #endif /* __linux__ */
  364. random_write_entropy();
  365. }
  366. void random_deinit(void)
  367. {
  368. #ifdef __linux__
  369. random_close_fd();
  370. #endif /* __linux__ */
  371. random_write_entropy();
  372. os_free(random_entropy_file);
  373. random_entropy_file = NULL;
  374. }