18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Random number generator
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2010-2011, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This random number generator is used to provide additional entropy to the
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * one provided by the operating system (os_get_random()) for session key
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * generation. The os_get_random() output is expected to be secure and the
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * implementation here is expected to provide only limited protection against
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cases where os_get_random() cannot provide strong randomness. This
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * implementation shall not be assumed to be secure as the sole source of
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * randomness. The random_get_bytes() function mixes in randomness from
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * os_get_random() and as such, calls to os_get_random() can be replaced with
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * calls to random_get_bytes() without reducing security.
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The design here follows partially the design used in the Linux
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * drivers/char/random.c, but the implementation here is simpler and not as
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * strong. This is a compromise to reduce duplicated CPU effort and to avoid
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * extra code/memory size. As pointed out above, os_get_random() needs to be
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * guaranteed to be secure for any of the security assumptions to hold.
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __linux__
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include <fcntl.h>
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __linux__ */
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
3261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "crypto/crypto.h"
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sha1.h"
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "random.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define POOL_WORDS 32
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define POOL_WORDS_MASK (POOL_WORDS - 1)
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define POOL_TAP1 26
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define POOL_TAP2 20
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define POOL_TAP3 14
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define POOL_TAP4 7
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define POOL_TAP5 1
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define EXTRACT_LEN 16
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MIN_READY_MARK 2
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 pool[POOL_WORDS];
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned int input_rotate = 0;
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned int pool_pos = 0;
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 dummy_key[20];
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __linux__
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic size_t dummy_key_avail = 0;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int random_fd = -1;
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __linux__ */
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned int own_pool_ready = 0;
5575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen#define RANDOM_ENTROPY_SIZE 20
5675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic char *random_entropy_file = NULL;
5775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic int random_entropy_file_read = 0;
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define MIN_COLLECT_ENTROPY 1000
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned int entropy = 0;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic unsigned int total_collected = 0;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
6475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void random_write_entropy(void);
6575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
6675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u32 __ROL32(u32 x, u32 y)
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
69d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt	if (y == 0)
70d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt		return x;
71d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return (x << (y & 31)) | (x >> (32 - (y & 31)));
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void random_mix_pool(const void *buf, size_t len)
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static const u32 twist[8] = {
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	};
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	const u8 *pos = buf;
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 w;
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_EXCESSIVE, "random_mix_pool", buf, len);
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (len--) {
888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		w = __ROL32(*pos++, input_rotate & 31);
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		input_rotate += pool_pos ? 7 : 14;
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pool_pos = (pool_pos - 1) & POOL_WORDS_MASK;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		w ^= pool[pool_pos];
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		w ^= pool[(pool_pos + POOL_TAP1) & POOL_WORDS_MASK];
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		w ^= pool[(pool_pos + POOL_TAP2) & POOL_WORDS_MASK];
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		w ^= pool[(pool_pos + POOL_TAP3) & POOL_WORDS_MASK];
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		w ^= pool[(pool_pos + POOL_TAP4) & POOL_WORDS_MASK];
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		w ^= pool[(pool_pos + POOL_TAP5) & POOL_WORDS_MASK];
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pool[pool_pos] = (w >> 3) ^ twist[w & 7];
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void random_extract(u8 *out)
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int i;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 hash[SHA1_MAC_LEN];
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 *hash_ptr;
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u32 buf[POOL_WORDS / 2];
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* First, add hash back to pool to make backtracking more difficult. */
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) pool,
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(pool), hash);
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_mix_pool(hash, sizeof(hash));
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Hash half the pool to extra data */
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < POOL_WORDS / 2; i++)
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		buf[i] = pool[(pool_pos - i) & POOL_WORDS_MASK];
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hmac_sha1(dummy_key, sizeof(dummy_key), (const u8 *) buf,
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		  sizeof(buf), hash);
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Fold the hash to further reduce any potential output pattern.
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Though, compromise this to reduce CPU use for the most common output
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * length (32) and return 16 bytes from instead of only half.
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hash_ptr = (u32 *) hash;
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hash_ptr[0] ^= hash_ptr[4];
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(out, hash, EXTRACT_LEN);
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid random_add_randomness(const void *buf, size_t len)
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct os_time t;
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	static unsigned int count = 0;
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	count++;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entropy > MIN_COLLECT_ENTROPY && (count & 0x3ff) != 0) {
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * No need to add more entropy at this point, so save CPU and
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * skip the update.
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
14204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	wpa_printf(MSG_EXCESSIVE, "Add randomness: count=%u entropy=%u",
14304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		   count, entropy);
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_get_time(&t);
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_EXCESSIVE, "random pool",
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(const u8 *) pool, sizeof(pool));
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_mix_pool(&t, sizeof(t));
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_mix_pool(buf, len);
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_EXCESSIVE, "random pool",
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			(const u8 *) pool, sizeof(pool));
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	entropy++;
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	total_collected++;
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint random_get_bytes(void *buf, size_t len)
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int ret;
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *bytes = buf;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t left;
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_MSGDUMP, "Get randomness: len=%u entropy=%u",
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned int) len, entropy);
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Start with assumed strong randomness from OS */
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ret = os_get_random(buf, len);
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_EXCESSIVE, "random from os_get_random",
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			buf, len);
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* Mix in additional entropy extracted from the internal pool */
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	left = len;
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	while (left) {
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		size_t siz, i;
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		u8 tmp[EXTRACT_LEN];
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		random_extract(tmp);
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump_key(MSG_EXCESSIVE, "random from internal pool",
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				tmp, sizeof(tmp));
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		siz = left > EXTRACT_LEN ? EXTRACT_LEN : left;
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (i = 0; i < siz; i++)
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			*bytes++ ^= tmp[i];
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		left -= siz;
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
18461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
18561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_FIPS
18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/* Mix in additional entropy from the crypto module */
187d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt	bytes = buf;
18861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	left = len;
18961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	while (left) {
19061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		size_t siz, i;
19161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		u8 tmp[EXTRACT_LEN];
19261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (crypto_get_random(tmp, sizeof(tmp)) < 0) {
19361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			wpa_printf(MSG_ERROR, "random: No entropy available "
19461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				   "for generating strong random bytes");
19561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return -1;
19661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
19761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		wpa_hexdump_key(MSG_EXCESSIVE, "random from crypto module",
19861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				tmp, sizeof(tmp));
19961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		siz = left > EXTRACT_LEN ? EXTRACT_LEN : left;
20061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		for (i = 0; i < siz; i++)
20161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			*bytes++ ^= tmp[i];
20261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		left -= siz;
20361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_FIPS */
20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_key(MSG_EXCESSIVE, "mixed random", buf, len);
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (entropy < len)
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entropy = 0;
2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	else
2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		entropy -= len;
2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return ret;
2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint random_pool_ready(void)
2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __linux__
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int fd;
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssize_t res;
2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Make sure that there is reasonable entropy available before allowing
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * some key derivation operations to proceed.
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dummy_key_avail == sizeof(dummy_key))
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1; /* Already initialized - good to continue */
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/*
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * Try to fetch some more data from the kernel high quality
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * /dev/random. There may not be enough data available at this point,
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * so use non-blocking read to avoid blocking the application
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 * completely.
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	 */
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (fd < 0) {
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
240fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt			   strerror(errno));
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = read(fd, dummy_key + dummy_key_avail,
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(dummy_key) - dummy_key_avail);
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%s", strerror(errno));
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = 0;
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from "
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "/dev/random", (unsigned) res,
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned) (sizeof(dummy_key) - dummy_key_avail));
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dummy_key_avail += res;
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	close(fd);
2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
25775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (dummy_key_avail == sizeof(dummy_key)) {
25875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (own_pool_ready < MIN_READY_MARK)
25975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			own_pool_ready = MIN_READY_MARK;
26075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		random_write_entropy();
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
26275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "random data available from /dev/random",
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key));
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (own_pool_ready >= MIN_READY_MARK ||
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    total_collected + 10 * own_pool_ready > MIN_COLLECT_ENTROPY) {
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_INFO, "random: Allow operation to proceed "
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "based on internal entropy");
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 1;
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_INFO, "random: Not enough entropy pool available for "
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "secure operations");
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else /* __linux__ */
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	/* TODO: could do similar checks on non-Linux platforms */
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 1;
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __linux__ */
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid random_mark_pool_ready(void)
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	own_pool_ready++;
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be "
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK);
29075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_write_entropy();
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __linux__
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void random_close_fd(void)
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_fd >= 0) {
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		eloop_unregister_read_sock(random_fd);
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		close(random_fd);
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		random_fd = -1;
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void random_read_fd(int sock, void *eloop_ctx, void *sock_ctx)
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ssize_t res;
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dummy_key_avail == sizeof(dummy_key)) {
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		random_close_fd();
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	res = read(sock, dummy_key + dummy_key_avail,
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   sizeof(dummy_key) - dummy_key_avail);
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (res < 0) {
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "%s", strerror(errno));
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from /dev/random",
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned) res,
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   (unsigned) (sizeof(dummy_key) - dummy_key_avail));
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dummy_key_avail += res;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
32875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (dummy_key_avail == sizeof(dummy_key)) {
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		random_close_fd();
33075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		if (own_pool_ready < MIN_READY_MARK)
33175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			own_pool_ready = MIN_READY_MARK;
33275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		random_write_entropy();
33375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __linux__ */
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void random_read_entropy(void)
34075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
34175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	char *buf;
34275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	size_t len;
34375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!random_entropy_file)
34575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
34675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
34775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	buf = os_readfile(random_entropy_file, &len);
34875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (buf == NULL)
34975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return; /* entropy file not yet available */
35075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
35175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (len != 1 + RANDOM_ENTROPY_SIZE) {
35275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		wpa_printf(MSG_DEBUG, "random: Invalid entropy file %s",
35375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen			   random_entropy_file);
35475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		os_free(buf);
35575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
35675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
35775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
35875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	own_pool_ready = (u8) buf[0];
35975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_add_randomness(buf + 1, RANDOM_ENTROPY_SIZE);
36075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_entropy_file_read = 1;
36175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	os_free(buf);
36275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_printf(MSG_DEBUG, "random: Added entropy from %s "
36375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		   "(own_pool_ready=%u)",
36475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		   random_entropy_file, own_pool_ready);
36575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
36675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
36775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
36875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenstatic void random_write_entropy(void)
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
37075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	char buf[RANDOM_ENTROPY_SIZE];
37175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	FILE *f;
37275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	u8 opr;
3731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	int fail = 0;
37475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
37575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (!random_entropy_file)
37675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
37775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
3781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (random_get_bytes(buf, RANDOM_ENTROPY_SIZE) < 0)
3791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
38075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
38175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	f = fopen(random_entropy_file, "wb");
38275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (f == NULL) {
3831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "random: Could not open entropy file %s "
3841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "for writing", random_entropy_file);
38575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		return;
38675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	}
38775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
38875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	opr = own_pool_ready > 0xff ? 0xff : own_pool_ready;
3891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (fwrite(&opr, 1, 1, f) != 1 ||
3901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	    fwrite(buf, RANDOM_ENTROPY_SIZE, 1, f) != 1)
3911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		fail = 1;
39275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	fclose(f);
3931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	if (fail) {
3941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpa_printf(MSG_ERROR, "random: Could not write entropy data "
3951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			   "to %s", random_entropy_file);
3961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		return;
3971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	}
39875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
39975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	wpa_printf(MSG_DEBUG, "random: Updated entropy file %s "
40075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		   "(own_pool_ready=%u)",
40175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		   random_entropy_file, own_pool_ready);
40275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen}
40375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
40475ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
40575ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinenvoid random_init(const char *entropy_file)
40675ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen{
40775ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	os_free(random_entropy_file);
40875ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	if (entropy_file)
40975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		random_entropy_file = os_strdup(entropy_file);
41075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	else
41175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen		random_entropy_file = NULL;
41275ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_read_entropy();
41375ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __linux__
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_fd >= 0)
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (random_fd < 0) {
4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
421fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt			   strerror(errno));
4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return;
4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "random: Trying to read entropy from "
4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   "/dev/random");
4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL);
4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __linux__ */
42975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen
43075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_write_entropy();
4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid random_deinit(void)
4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef __linux__
4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_close_fd();
4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* __linux__ */
43975ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_write_entropy();
44075ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	os_free(random_entropy_file);
44175ecf5267604f166b85a7ee2cf0d9cb682966680Jouni Malinen	random_entropy_file = NULL;
4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
443