random.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  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. wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
  202. strerror(errno));
  203. return -1;
  204. }
  205. res = read(fd, dummy_key + dummy_key_avail,
  206. sizeof(dummy_key) - dummy_key_avail);
  207. if (res < 0) {
  208. wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
  209. "%s", strerror(errno));
  210. res = 0;
  211. }
  212. wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from "
  213. "/dev/random", (unsigned) res,
  214. (unsigned) (sizeof(dummy_key) - dummy_key_avail));
  215. dummy_key_avail += res;
  216. close(fd);
  217. if (dummy_key_avail == sizeof(dummy_key)) {
  218. if (own_pool_ready < MIN_READY_MARK)
  219. own_pool_ready = MIN_READY_MARK;
  220. random_write_entropy();
  221. return 1;
  222. }
  223. wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
  224. "random data available from /dev/random",
  225. (unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key));
  226. if (own_pool_ready >= MIN_READY_MARK ||
  227. total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY) {
  228. wpa_printf(MSG_INFO, "random: Allow operation to proceed "
  229. "based on internal entropy");
  230. return 1;
  231. }
  232. wpa_printf(MSG_INFO, "random: Not enough entropy pool available for "
  233. "secure operations");
  234. return 0;
  235. #else /* __linux__ */
  236. /* TODO: could do similar checks on non-Linux platforms */
  237. return 1;
  238. #endif /* __linux__ */
  239. }
  240. void random_mark_pool_ready(void)
  241. {
  242. own_pool_ready++;
  243. wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be "
  244. "ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK);
  245. random_write_entropy();
  246. }
  247. #ifdef __linux__
  248. static void random_close_fd(void)
  249. {
  250. if (random_fd >= 0) {
  251. eloop_unregister_read_sock(random_fd);
  252. close(random_fd);
  253. random_fd = -1;
  254. }
  255. }
  256. static void random_read_fd(int sock, void *eloop_ctx, void *sock_ctx)
  257. {
  258. ssize_t res;
  259. if (dummy_key_avail == sizeof(dummy_key)) {
  260. random_close_fd();
  261. return;
  262. }
  263. res = read(sock, dummy_key + dummy_key_avail,
  264. sizeof(dummy_key) - dummy_key_avail);
  265. if (res < 0) {
  266. wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
  267. "%s", strerror(errno));
  268. return;
  269. }
  270. wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from /dev/random",
  271. (unsigned) res,
  272. (unsigned) (sizeof(dummy_key) - dummy_key_avail));
  273. dummy_key_avail += res;
  274. if (dummy_key_avail == sizeof(dummy_key)) {
  275. random_close_fd();
  276. if (own_pool_ready < MIN_READY_MARK)
  277. own_pool_ready = MIN_READY_MARK;
  278. random_write_entropy();
  279. }
  280. }
  281. #endif /* __linux__ */
  282. static void random_read_entropy(void)
  283. {
  284. char *buf;
  285. size_t len;
  286. if (!random_entropy_file)
  287. return;
  288. buf = os_readfile(random_entropy_file, &len);
  289. if (buf == NULL)
  290. return; /* entropy file not yet available */
  291. if (len != 1 + RANDOM_ENTROPY_SIZE) {
  292. wpa_printf(MSG_DEBUG, "random: Invalid entropy file %s",
  293. random_entropy_file);
  294. os_free(buf);
  295. return;
  296. }
  297. own_pool_ready = (u8) buf[0];
  298. random_add_randomness(buf + 1, RANDOM_ENTROPY_SIZE);
  299. random_entropy_file_read = 1;
  300. os_free(buf);
  301. wpa_printf(MSG_DEBUG, "random: Added entropy from %s "
  302. "(own_pool_ready=%u)",
  303. random_entropy_file, own_pool_ready);
  304. }
  305. static void random_write_entropy(void)
  306. {
  307. char buf[RANDOM_ENTROPY_SIZE];
  308. FILE *f;
  309. u8 opr;
  310. int fail = 0;
  311. if (!random_entropy_file)
  312. return;
  313. if (random_get_bytes(buf, RANDOM_ENTROPY_SIZE) < 0)
  314. return;
  315. f = fopen(random_entropy_file, "wb");
  316. if (f == NULL) {
  317. wpa_printf(MSG_ERROR, "random: Could not open entropy file %s "
  318. "for writing", random_entropy_file);
  319. return;
  320. }
  321. opr = own_pool_ready > 0xff ? 0xff : own_pool_ready;
  322. if (fwrite(&opr, 1, 1, f) != 1 ||
  323. fwrite(buf, RANDOM_ENTROPY_SIZE, 1, f) != 1)
  324. fail = 1;
  325. fclose(f);
  326. if (fail) {
  327. wpa_printf(MSG_ERROR, "random: Could not write entropy data "
  328. "to %s", random_entropy_file);
  329. return;
  330. }
  331. wpa_printf(MSG_DEBUG, "random: Updated entropy file %s "
  332. "(own_pool_ready=%u)",
  333. random_entropy_file, own_pool_ready);
  334. }
  335. void random_init(const char *entropy_file)
  336. {
  337. os_free(random_entropy_file);
  338. if (entropy_file)
  339. random_entropy_file = os_strdup(entropy_file);
  340. else
  341. random_entropy_file = NULL;
  342. random_read_entropy();
  343. #ifdef __linux__
  344. if (random_fd >= 0)
  345. return;
  346. random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
  347. if (random_fd < 0) {
  348. wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
  349. strerror(errno));
  350. return;
  351. }
  352. wpa_printf(MSG_DEBUG, "random: Trying to read entropy from "
  353. "/dev/random");
  354. eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL);
  355. #endif /* __linux__ */
  356. random_write_entropy();
  357. }
  358. void random_deinit(void)
  359. {
  360. #ifdef __linux__
  361. random_close_fd();
  362. #endif /* __linux__ */
  363. random_write_entropy();
  364. os_free(random_entropy_file);
  365. random_entropy_file = NULL;
  366. }