Example #1
0
/* Pass len=0 to hash an entire file */
static int
process_file(hash_state *hs, const char *filename,
		unsigned int len, int prngd)
{
	static int already_blocked = 0;
	int readfd;
	unsigned int readcount;
	int ret = DROPBEAR_FAILURE;

#ifdef DROPBEAR_PRNGD_SOCKET
	if (prngd)
	{
		readfd = connect_unix(filename);
	}
	else
#endif
	{
		readfd = open(filename, O_RDONLY);
	}

	if (readfd < 0) {
		goto out;
	}

	readcount = 0;
	while (len == 0 || readcount < len)
	{
		int readlen, wantread;
		unsigned char readbuf[4096];
		if (!already_blocked && !prngd)
		{
			int res;
			struct timeval timeout;
			fd_set read_fds;

 			timeout.tv_sec  = 2;
 			timeout.tv_usec = 0;

			FD_ZERO(&read_fds);
			FD_SET(readfd, &read_fds);
			res = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
			if (res == 0)
			{
				dropbear_log(LOG_WARNING, "Warning: Reading the randomness source '%s' seems to have blocked.\nYou may need to find a better entropy source.", filename);
				already_blocked = 1;
			}
		}

		if (len == 0)
		{
			wantread = sizeof(readbuf);
		} 
		else
		{
			wantread = MIN(sizeof(readbuf), len-readcount);
		}

#ifdef DROPBEAR_PRNGD_SOCKET
		if (prngd)
		{
			char egdcmd[2];
			egdcmd[0] = 0x02;	/* blocking read */
			egdcmd[1] = (unsigned char)wantread;
			if (write(readfd, egdcmd, 2) < 0)
			{
				dropbear_exit("Can't send command to egd");
			}
		}
#endif

		readlen = read(readfd, readbuf, wantread);
		if (readlen <= 0) {
			if (readlen < 0 && errno == EINTR) {
				continue;
			}
			if (readlen == 0 && len == 0)
			{
				/* whole file was read as requested */
				break;
			}
			goto out;
		}
		sha1_process(hs, readbuf, readlen);
		readcount += readlen;
	}
	ret = DROPBEAR_SUCCESS;
out:
	close(readfd);
	return ret;
}
static void readrand(unsigned char* buf, unsigned int buflen) {

	static int already_blocked = 0;
	int readfd;
	unsigned int readpos;
	int readlen;
#ifdef DROPBEAR_PRNGD_SOCKET
	struct sockaddr_un egdsock;
	char egdcmd[2];
#endif

#ifdef DROPBEAR_RANDOM_DEV
	readfd = open(DROPBEAR_RANDOM_DEV, O_RDONLY);
	if (readfd < 0) {
		dropbear_exit("Couldn't open random device");
	}
#endif

#ifdef DROPBEAR_PRNGD_SOCKET
	readfd = connect_unix(DROPBEAR_PRNGD_SOCKET);

	if (readfd < 0) {
		dropbear_exit("Couldn't open random device");
	}

	if (buflen > 255)
		dropbear_exit("Can't request more than 255 bytes from egd");
	egdcmd[0] = 0x02;	/* blocking read */
	egdcmd[1] = (unsigned char)buflen;
	if (write(readfd, egdcmd, 2) < 0)
		dropbear_exit("Can't send command to egd");
#endif

	/* read the actual random data */
	readpos = 0;
	do {
		if (!already_blocked)
		{
			int ret;
			struct timeval timeout;
			fd_set read_fds;

			timeout.tv_sec = 2; /* two seconds should be enough */
			timeout.tv_usec = 0;

			FD_ZERO(&read_fds);
			FD_SET(readfd, &read_fds);
			ret = select(readfd + 1, &read_fds, NULL, NULL, &timeout);
			if (ret == 0)
			{
				dropbear_log(LOG_INFO, "Warning: Reading the random source seems to have blocked.\nIf you experience problems, you probably need to find a better entropy source.");
				already_blocked = 1;
			}
		}
		readlen = read(readfd, &buf[readpos], buflen - readpos);
		if (readlen <= 0) {
			if (readlen < 0 && errno == EINTR) {
				continue;
			}
			dropbear_exit("Error reading random source");
		}
		readpos += readlen;
	} while (readpos < buflen);

	close (readfd);
}