random.c 11 KB

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