1 /*
2  * Copyright (c) 1998, 1999, 2000, 2001, 2002 X-Way Rights BV
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  */
19 
20 /*!\file entropy.c
21  * \author Bob Deblier <bob.deblier@telenet.be>
22  * \ingroup ES_m ES_audio_m ES_dsp_m ES_random_m ES_urandom_m ES_tty_m
23  */
24 
25 #define BEECRYPT_DLL_EXPORT
26 
27 #if HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 
31 #include "beecrypt/entropy.h"
32 #include "beecrypt/endianness.h"
33 
34 #if WIN32
35 # include <mmsystem.h>
36 # include <wincrypt.h>
37 # include <winerror.h>
38 #else
39 # if HAVE_SYS_IOCTL_H
40 #  include <sys/ioctl.h>
41 # endif
42 # if HAVE_SYS_STAT_H
43 #  include <sys/types.h>
44 #  include <sys/stat.h>
45 # endif
46 # if TIME_WITH_SYS_TIME
47 #  include <sys/time.h>
48 #  include <time.h>
49 # else
50 #  if HAVE_SYS_TIME_H
51 #   include <sys/time.h>
52 #  elif HAVE_TIME_H
53 #   include <time.h>
54 #  endif
55 # endif
56 # if HAVE_SYS_AUDIOIO_H
57 #   include <sys/audioio.h>
58 # endif
59 # if HAVE_SYS_SOUNDCARD_H
60 #  include <sys/soundcard.h>
61 # endif
62 # if HAVE_TERMIOS_H
63 #  include <termios.h>
64 # elif HAVE_TERMIO_H
65 #  include <termio.h>
66 # endif
67 # ifdef _REENTRANT
68 #  if HAVE_THREAD_H && HAVE_SYNCH_H
69 #   include <synch.h>
70 #  elif HAVE_PTHREAD_H
71 #   include <pthread.h>
72 #  endif
73 # endif
74 # if HAVE_AIO_H
75 #  include <aio.h>
76 # endif
77 #endif
78 #if HAVE_FCNTL_H
79 # include <fcntl.h>
80 #endif
81 #if HAVE_ERRNO_H
82 # include <errno.h>
83 #endif
84 
85 #if WIN32
86 static HINSTANCE	entropy_instance = (HINSTANCE) 0;
87 
88 static HANDLE entropy_wavein_lock;
89 static HANDLE entropy_wavein_event;
90 
entropy_provider_setup(HINSTANCE hInst)91 int entropy_provider_setup(HINSTANCE hInst)
92 {
93 	if (!entropy_instance)
94 	{
95 		entropy_instance = hInst;
96 		if (!(entropy_wavein_lock = CreateMutex(NULL, FALSE, NULL)))
97 			return -1;
98 		if (!(entropy_wavein_event = CreateEvent(NULL, FALSE, FALSE, NULL)))
99 			return -1;
100 	}
101 	return 0;
102 }
103 
entropy_provider_cleanup()104 int entropy_provider_cleanup()
105 {
106 	if (entropy_wavein_lock)
107 	{
108 		CloseHandle(entropy_wavein_lock);
109 		entropy_wavein_lock = 0;
110 	}
111 	if (entropy_wavein_event)
112 	{
113 		CloseHandle(entropy_wavein_event);
114 		entropy_wavein_event = 0;
115 	}
116 	return 0;
117 }
118 #endif
119 
120 #if WIN32 || HAVE_DEV_AUDIO || HAVE_DEV_DSP
121 /*
122  * Mask the low-order bit of a bunch of sound samples, analyze them and
123  * return an error in case they are all zeroes or ones.
124  */
entropy_noise_filter(void * sampledata,int samplecount,int samplesize,int channels,int swap)125 static int entropy_noise_filter(void* sampledata, int samplecount, int samplesize, int channels, int swap)
126 {
127 	register int rc = 0, i;
128 
129 	switch (samplesize)
130 	{
131 	case 1:
132 		{
133 			uint8_t* samples = (uint8_t*) sampledata;
134 
135 			switch (channels)
136 			{
137 			case 1:
138 				{
139 					int zero_count = 0;
140 					int ones_count = 0;
141 
142 					for (i = 0; i < samplecount; i++)
143 					{
144 						if (samples[i] &= 0x1)
145 							ones_count++;
146 						else
147 							zero_count++;
148 					}
149 
150 					if ((zero_count == 0) || (ones_count == 0))
151 					{
152 						#if HAVE_ERRNO_H
153 						errno = EIO;
154 						#endif
155 						rc = -1;
156 					}
157 				}
158 				break;
159 
160 			case 2:
161 				{
162 					int zero_count_left = 0;
163 					int ones_count_left = 0;
164 					int zero_count_right = 0;
165 					int ones_count_right = 0;
166 
167 					for (i = 0; i < samplecount; i++)
168 					{
169 						if (i & 1)
170 						{
171 							if (samples[i] &= 0x1)
172 								ones_count_left++;
173 							else
174 								zero_count_left++;
175 						}
176 						else
177 						{
178 							if (samples[i] &= 0x1)
179 								ones_count_right++;
180 							else
181 								zero_count_right++;
182 						}
183 					}
184 
185 					if ((zero_count_left == 0) || (ones_count_left == 0) ||
186 							(zero_count_right == 0) || (ones_count_right == 0))
187 					{
188 						#if HAVE_ERRNO_H
189 						errno = EIO;
190 						#endif
191 						rc = -1;
192 					}
193 				}
194 				break;
195 
196 			default:
197 				#if HAVE_ERRNO_H
198 				errno = EINVAL;
199 				#endif
200 				rc = -1;
201 			}
202 		}
203 		break;
204 
205 	case 2:
206 		{
207 			uint16_t* samples = (uint16_t*) sampledata;
208 
209 			switch (channels)
210 			{
211 			case 1:
212 				{
213 					int zero_count = 0;
214 					int ones_count = 0;
215 
216 					for (i = 0; i < samplecount; i++)
217 					{
218 						if (swap)
219 							samples[i] = swapu16(samples[i]);
220 
221 						if (samples[i] &= 0x1)
222 							ones_count++;
223 						else
224 							zero_count++;
225 					}
226 
227 					if ((zero_count == 0) || (ones_count == 0))
228 					{
229 						#if HAVE_ERRNO_H
230 						errno = EIO;
231 						#endif
232 						rc = -1;
233 					}
234 				}
235 				break;
236 
237 			case 2:
238 				{
239 					int zero_count_left = 0;
240 					int ones_count_left = 0;
241 					int zero_count_right = 0;
242 					int ones_count_right = 0;
243 
244 					for (i = 0; i < samplecount; i++)
245 					{
246 						if (swap)
247 							samples[i] = swapu16(samples[i]);
248 
249 						if (i & 1)
250 						{
251 							if (samples[i] &= 0x1)
252 								ones_count_left++;
253 							else
254 								zero_count_left++;
255 						}
256 						else
257 						{
258 							if (samples[i] &= 0x1)
259 								ones_count_right++;
260 							else
261 								zero_count_right++;
262 						}
263 					}
264 
265 					if ((zero_count_left == 0) || (ones_count_left == 0) ||
266 							(zero_count_right == 0) || (ones_count_right == 0))
267 					{
268 						#if HAVE_ERRNO_H
269 						errno = EIO;
270 						#endif
271 						rc = -1;
272 					}
273 				}
274 				break;
275 
276 			default:
277 				#if HAVE_ERRNO_H
278 				errno = EINVAL;
279 				#endif
280 				rc = -1;
281 			}
282 		}
283 		break;
284 
285 	default:
286 		#if HAVE_ERRNO_H
287 		errno = EINVAL;
288 		#endif
289 		rc = -1;
290 	}
291 
292 	return 0;
293 }
294 
295 /* bit deskewing technique: the classical Von Neumann method
296 	- only use the lsb bit of every sample
297 	- there is a chance of bias in 0 or 1 bits, so to deskew this:
298 		- look at two successive sampled bits
299 		- if they are the same, discard them
300 		- if they are different, they're either 0-1 or 1-0; use the first bit of the pair as output
301 */
302 
303 #if WIN32
entropy_noise_gather(HWAVEIN wavein,int samplesize,int channels,int swap,int timeout,byte * data,size_t size)304 static int entropy_noise_gather(HWAVEIN wavein, int samplesize, int channels, int swap, int timeout, byte* data, size_t size)
305 #else
306 static int entropy_noise_gather(int fd, int samplesize, int channels, int swap, int timeout, byte* data, size_t size)
307 #endif
308 {
309 	size_t randombits = size << 3;
310 	byte temp = 0;
311 	int rc, i;
312 
313 	byte* sampledata = (byte*) malloc(1024 * samplesize * channels);
314 
315 	#if WIN32
316 	WAVEHDR header;
317 
318 	/* first set up a wave header */
319 	header.lpData = (LPSTR) sampledata;
320 	header.dwBufferLength = 1024 * samplesize * channels;
321 	header.dwFlags = 0;
322 
323 	/* do error handling! */
324 	waveInStart(wavein);
325 
326 	/* the first event is the due to the opening of the wave */
327 	ResetEvent(entropy_wavein_event);
328 	#else
329 	# if ENABLE_AIO
330 	struct aiocb my_aiocb;
331 	const struct aiocb* my_aiocb_list = &my_aiocb;
332 	#  if HAVE_TIME_H
333 	struct timespec my_aiocb_timeout;
334 	#  else
335 	#   error
336 	#  endif
337 
338 	memset(&my_aiocb, 0, sizeof(struct aiocb));
339 
340 	my_aiocb.aio_fildes = fd;
341 	my_aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
342 	# endif
343 	#endif
344 
345 	if (sampledata == (byte*) 0)
346 	{
347 		#if HAVE_ERRNO_H
348 		errno = ENOMEM;
349 		#endif
350 		return -1;
351 	}
352 
353 	while (randombits)
354 	{
355 		#if WIN32
356 		/* pass the buffer to the wavein and wait for the event */
357 		waveInPrepareHeader(wavein, &header, sizeof(WAVEHDR));
358 		waveInAddBuffer(wavein, &header, sizeof(WAVEHDR));
359 
360 		/* in case we have to wait more than the specified timeout, bail out */
361 		if (WaitForSingleObject(entropy_wavein_event, timeout) == WAIT_OBJECT_0)
362 		{
363 			rc = header.dwBytesRecorded;
364 		}
365 		else
366 		{
367 			waveInStop(wavein);
368 			waveInReset(wavein);
369 
370 			free(sampledata);
371 			return -1;
372 		}
373 		#else
374 		# if ENABLE_AIO
375 		my_aiocb.aio_buf = sampledata;
376 		my_aiocb.aio_nbytes = 1024 * samplesize * channels;
377 
378 		rc = aio_read(&my_aiocb);
379 		# else
380 		rc = read(fd, sampledata, 1024 * samplesize * channels);
381 		# endif
382 
383 		if (rc < 0)
384 		{
385 			free(sampledata);
386 			return -1;
387 		}
388 
389 		# if ENABLE_AIO
390 		my_aiocb_timeout.tv_sec = (timeout / 1000);
391 		my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
392 
393 		rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
394 
395 		if (rc < 0)
396 		{
397 			#if HAVE_ERRNO_H
398 			if (errno == EAGAIN)
399 			{
400 				/* certain linux glibc versions are buggy and don't aio_suspend properly */
401 				nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
402 
403 				my_aiocb_timeout.tv_sec = (timeout / 1000);
404 				my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
405 
406 				/* and try again */
407 				rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
408 			}
409 			#endif
410 		}
411 
412 		if (rc < 0)
413 		{
414 			/* cancel any remaining reads */
415 			while (rc != AIO_ALLDONE)
416 			{
417 				rc = aio_cancel(fd, (struct aiocb*) 0);
418 
419 				if (rc == AIO_NOTCANCELED)
420 				{
421 					my_aiocb_timeout.tv_sec = (timeout / 1000);
422 					my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
423 
424 					nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
425 				}
426 
427 				if (rc < 0)
428 					break;
429 			}
430 			free(sampledata);
431 			return -1;
432 		}
433 
434 		rc = aio_error(&my_aiocb);
435 
436 		if (rc)
437 		{
438 			free(sampledata);
439 			return -1;
440 		}
441 
442 		rc = aio_return(&my_aiocb);
443 
444 		if (rc < 0)
445 		{
446 			free(sampledata);
447 			return -1;
448 		}
449 		# endif
450 		#endif
451 
452 		if (entropy_noise_filter(sampledata, rc / samplesize, samplesize, channels, swap) < 0)
453 		{
454 			fprintf(stderr, "noise filter indicates too much bias in audio samples\n");
455 			free(sampledata);
456 			return -1;
457 		}
458 
459 		switch (samplesize)
460 		{
461 		case 1:
462 			{
463 				uint8_t* samples = (uint8_t*) sampledata;
464 
465 				for (i = 0; randombits && (i < 1024); i += 2)
466 				{
467 					if (samples[i] ^ samples[i+1])
468 					{
469 						temp <<= 1;
470 						temp |= samples[i];
471 						randombits--;
472 						if (!(randombits & 0x7))
473 							*(data++) = temp;
474 					}
475 				}
476 			}
477 			break;
478 
479 		case 2:
480 			{
481 				uint16_t* samples = (uint16_t*) sampledata;
482 
483 				for (i = 0; randombits && (i < 1024); i += 2)
484 				{
485 					if (samples[i] ^ samples[i+1])
486 					{
487 						temp <<= 1;
488 						temp |= samples[i];
489 						randombits--;
490 						if (!(randombits & 0x7))
491 							*(data++) = temp;
492 					}
493 				}
494 			}
495 			break;
496 
497 		default:
498 			free(sampledata);
499 			return -1;
500 		}
501 	}
502 
503 	#if WIN32
504 	waveInStop(wavein);
505 	waveInReset(wavein);
506 	#endif
507 
508 	free(sampledata);
509 	return 0;
510 }
511 #endif
512 
513 #if WIN32
entropy_wavein(byte * data,size_t size)514 int entropy_wavein(byte* data, size_t size)
515 {
516 	const char *timeout_env = getenv("BEECRYPT_ENTROPY_WAVEIN_TIMEOUT");
517 
518 	WAVEINCAPS		waveincaps;
519 	WAVEFORMATEX	waveformatex;
520 	HWAVEIN			wavein;
521 	MMRESULT		rc;
522 
523 	rc = waveInGetDevCaps(WAVE_MAPPER, &waveincaps, sizeof(WAVEINCAPS));
524 	if (rc != MMSYSERR_NOERROR)
525 		return -1;
526 
527 	/* first go for the 16 bits samples -> more chance of noise bits */
528 	switch (waveformatex.nChannels = waveincaps.wChannels)
529 	{
530 	case 1:
531 		/* mono */
532 		if (waveincaps.dwFormats & WAVE_FORMAT_4M16)
533 		{
534 			waveformatex.nSamplesPerSec = 44100;
535 			waveformatex.wBitsPerSample = 16;
536 		}
537 		else if (waveincaps.dwFormats & WAVE_FORMAT_2M16)
538 		{
539 			waveformatex.nSamplesPerSec = 22050;
540 			waveformatex.wBitsPerSample = 16;
541 		}
542 		else if (waveincaps.dwFormats & WAVE_FORMAT_1M16)
543 		{
544 			waveformatex.nSamplesPerSec = 11025;
545 			waveformatex.wBitsPerSample = 16;
546 		}
547 		else if (waveincaps.dwFormats & WAVE_FORMAT_4M08)
548 		{
549 			waveformatex.nSamplesPerSec = 44100;
550 			waveformatex.wBitsPerSample = 8;
551 		}
552 		else if (waveincaps.dwFormats & WAVE_FORMAT_2M08)
553 		{
554 			waveformatex.nSamplesPerSec = 22050;
555 			waveformatex.wBitsPerSample = 8;
556 		}
557 		else if (waveincaps.dwFormats & WAVE_FORMAT_1M08)
558 		{
559 			waveformatex.nSamplesPerSec = 11025;
560 			waveformatex.wBitsPerSample = 8;
561 		}
562 		else
563 			return -1;
564 
565 		break;
566 	case 2:
567 		/* stereo */
568 		if (waveincaps.dwFormats & WAVE_FORMAT_4S16)
569 		{
570 			waveformatex.nSamplesPerSec = 44100;
571 			waveformatex.wBitsPerSample = 16;
572 		}
573 		else if (waveincaps.dwFormats & WAVE_FORMAT_2S16)
574 		{
575 			waveformatex.nSamplesPerSec = 22050;
576 			waveformatex.wBitsPerSample = 16;
577 		}
578 		else if (waveincaps.dwFormats & WAVE_FORMAT_1S16)
579 		{
580 			waveformatex.nSamplesPerSec = 11025;
581 			waveformatex.wBitsPerSample = 16;
582 		}
583 		else if (waveincaps.dwFormats & WAVE_FORMAT_4S08)
584 		{
585 			waveformatex.nSamplesPerSec = 44100;
586 			waveformatex.wBitsPerSample = 8;
587 		}
588 		else if (waveincaps.dwFormats & WAVE_FORMAT_2S08)
589 		{
590 			waveformatex.nSamplesPerSec = 22050;
591 			waveformatex.wBitsPerSample = 8;
592 		}
593 		else if (waveincaps.dwFormats & WAVE_FORMAT_1S08)
594 		{
595 			waveformatex.nSamplesPerSec = 11025;
596 			waveformatex.wBitsPerSample = 8;
597 		}
598 		else
599 			return -1;
600 
601 		break;
602 	}
603 
604 	waveformatex.wFormatTag = WAVE_FORMAT_PCM;
605 	waveformatex.nAvgBytesPerSec = (waveformatex.nSamplesPerSec * waveformatex.nChannels * waveformatex.wBitsPerSample) / 8;
606 	waveformatex.nBlockAlign = (waveformatex.nChannels * waveformatex.wBitsPerSample) / 8;
607 	waveformatex.cbSize = 0;
608 
609 	/* we now have the wavein's capabilities hammered out; from here on we need to lock */
610 
611 	if (WaitForSingleObject(entropy_wavein_lock, INFINITE) != WAIT_OBJECT_0)
612 		return -1;
613 
614 	rc = waveInOpen(&wavein, WAVE_MAPPER, &waveformatex, (DWORD_PTR) entropy_wavein_event, (DWORD) 0, CALLBACK_EVENT);
615 	if (rc != MMSYSERR_NOERROR)
616 	{
617 		fprintf(stderr, "waveInOpen failed!\n"); fflush(stderr);
618 		ReleaseMutex(entropy_wavein_lock);
619 		return -1;
620 	}
621 
622 	rc = entropy_noise_gather(wavein, waveformatex.wBitsPerSample >> 3, waveformatex.nChannels, 0, timeout_env ? atoi(timeout_env) : 2000, data, size);
623 
624 	waveInClose(wavein);
625 
626 	ReleaseMutex(entropy_wavein_lock);
627 
628 	return rc;
629 }
630 
entropy_console(byte * data,size_t size)631 int entropy_console(byte* data, size_t size)
632 {
633 	register size_t randombits = size << 3;
634 
635 	HANDLE hStdin;
636 	DWORD inRet;
637 	INPUT_RECORD inEvent;
638 	LARGE_INTEGER hrtsample;
639 
640 	hStdin = GetStdHandle(STD_INPUT_HANDLE);
641 	if (hStdin == INVALID_HANDLE_VALUE)
642 	{
643 		fprintf(stderr, "GetStdHandle error %d\n", GetLastError());
644 		return -1;
645 	}
646 
647 	printf("please press random keys on your keyboard\n"); fflush(stdout);
648 
649 	while (randombits)
650 	{
651 		if (!ReadConsoleInput(hStdin, &inEvent, 1, &inRet))
652 		{
653 			fprintf(stderr, "ReadConsoleInput failed\n"); fflush(stderr);
654 			return -1;
655 		}
656 		if ((inRet == 1) && (inEvent.EventType == KEY_EVENT) && inEvent.Event.KeyEvent.bKeyDown)
657 		{
658 			printf("."); fflush(stdout);
659 			if (!QueryPerformanceCounter(&hrtsample))
660 			{
661 				fprintf(stderr, "QueryPerformanceCounter failed\n"); fflush(stderr);
662 				return -1;
663 			}
664 
665 			/* get 8 bits from the sample */
666 			/* discard the 2 lowest bits */
667 			*(data++) = (byte)(hrtsample.LowPart >> 2);
668 			randombits -= 8;
669 		}
670 	}
671 
672 	printf("\nthanks\n");
673 
674 	Sleep(1000);
675 
676 	if (!FlushConsoleInputBuffer(hStdin))
677 	{
678 		fprintf(stderr, "FlushConsoleInputBuffer failed\n"); fflush(stderr);
679 		return -1;
680 	}
681 
682 	return 0;
683 }
684 
entropy_wincrypt(byte * data,size_t size)685 int entropy_wincrypt(byte* data, size_t size)
686 {
687 	HCRYPTPROV hCrypt;
688 	DWORD provType = PROV_RSA_FULL;
689 	BOOL rc;
690 
691 	/* consider using getenv("BEECRYPT_ENTROPY_WINCRYPT_PROVTYPE") to set provType */
692 
693 	if (!CryptAcquireContext(&hCrypt, "BeeCrypt", NULL, provType, 0))
694 	{
695 		#if defined(NTE_BAD_KEYSET)
696 		if (GetLastError() == NTE_BAD_KEYSET)
697 		{
698 			if (!CryptAcquireContext(&hCrypt, "BeeCrypt", NULL, provType, CRYPT_NEWKEYSET))
699 				return -1;
700 		}
701 		else
702 			return -1;
703 		#else
704 		return -1;
705 		#endif
706 	}
707 
708 	rc = CryptGenRandom(hCrypt, size, (BYTE*) data);
709 
710 	CryptReleaseContext(hCrypt, 0);
711 
712 	return rc ? 0 : -1;
713 }
714 
715 #else
716 
717 #if HAVE_DEV_AUDIO
718 /*!\addtogroup ES_audio_m
719  * \{
720  */
721 static const char* name_dev_audio = "/dev/audio";
722 static int dev_audio_fd = -1;
723 # ifdef _REENTRANT
724 #  if HAVE_THREAD_H && HAVE_SYNCH_H
725 static mutex_t dev_audio_lock = DEFAULTMUTEX;
726 #  elif HAVE_PTHREAD_H
727 static pthread_mutex_t dev_audio_lock = PTHREAD_MUTEX_INITIALIZER;
728 #  else
729 #   error Need locking mechanism
730 #  endif
731 # endif
732 /*!\}
733  */
734 #endif
735 
736 #if HAVE_DEV_DSP
737 /*!\addtogroup ES_dsp_m
738  * \{
739  */
740 static const char* name_dev_dsp = "/dev/dsp";
741 static int dev_dsp_fd = -1;
742 # ifdef _REENTRANT
743 #  if HAVE_THREAD_H && HAVE_SYNCH_H
744 static mutex_t dev_dsp_lock = DEFAULTMUTEX;
745 #  elif HAVE_PTHREAD_H
746 static pthread_mutex_t dev_dsp_lock = PTHREAD_MUTEX_INITIALIZER;
747 #  else
748 #   error Need locking mechanism
749 #  endif
750 # endif
751 /*!\}
752  */
753 #endif
754 
755 #if HAVE_DEV_RANDOM
756 /*!\addtogroup ES_random_m
757  * \{
758  */
759 static const char* name_dev_random = "/dev/random";
760 static int dev_random_fd = -1;
761 # ifdef _REENTRANT
762 #  if HAVE_THREAD_H && HAVE_SYNCH_H
763 static mutex_t dev_random_lock = DEFAULTMUTEX;
764 #  elif HAVE_PTHREAD_H
765 static pthread_mutex_t dev_random_lock = PTHREAD_MUTEX_INITIALIZER;
766 #  else
767 #   error Need locking mechanism
768 #  endif
769 # endif
770 /*!\}
771  */
772 #endif
773 
774 #if HAVE_DEV_URANDOM
775 /*!\addtogroup ES_urandom_m
776  * \{
777  */
778 static const char* name_dev_urandom = "/dev/urandom";
779 static int dev_urandom_fd = -1;
780 # ifdef _REENTRANT
781 #  if HAVE_THREAD_H && HAVE_SYNCH_H
782 static mutex_t dev_urandom_lock = DEFAULTMUTEX;
783 #  elif HAVE_PTHREAD_H
784 static pthread_mutex_t dev_urandom_lock = PTHREAD_MUTEX_INITIALIZER;
785 #  else
786 #   error Need locking mechanism
787 #  endif
788 # endif
789 /*!\}
790  */
791 #endif
792 
793 #if HAVE_DEV_TTY
794 /*!\addtogroup ES_tty_m
795  * \{
796  */
797 static const char *dev_tty_name = "/dev/tty";
798 static int dev_tty_fd = -1;
799 # ifdef _REENTRANT
800 #  if HAVE_THREAD_H && HAVE_SYNCH_H
801 static mutex_t dev_tty_lock = DEFAULTMUTEX;
802 #  elif HAVE_PTHREAD_H
803 static pthread_mutex_t dev_tty_lock = PTHREAD_MUTEX_INITIALIZER;
804 #  else
805 #   error Need locking mechanism
806 #  endif
807 # endif
808 /*!\}
809  */
810 #endif
811 
812 #if HAVE_SYS_STAT_H
statdevice(const char * device)813 static int statdevice(const char *device)
814 {
815 	struct stat s;
816 
817 	if (stat(device, &s) < 0)
818 	{
819 		#if HAVE_ERRNO_H && HAVE_STRING_H
820 		fprintf(stderr, "cannot stat %s: %s\n", device, strerror(errno));
821 		#endif
822 		return -1;
823 	}
824 	if (!S_ISCHR(s.st_mode))
825 	{
826 		fprintf(stderr, "%s is not a device\n", device);
827 		return -1;
828 	}
829 	return 0;
830 }
831 #endif
832 
opendevice(const char * device)833 static int opendevice(const char *device)
834 {
835 	register int fd;
836 
837 	if ((fd = open(device, O_RDONLY)) < 0)
838 	{
839 		#if HAVE_ERRNO_H && HAVE_STRING_H
840 		fprintf(stderr, "open of %s failed: %s\n", device, strerror(errno));
841 		#endif
842 		return fd;
843 	}
844 
845 	return fd;
846 }
847 
848 #if HAVE_DEV_RANDOM || HAVE_DEV_URANDOM
849 /* timeout is in milliseconds */
850 /*!\ingroup ES_random_m ES_urandom_m
851  */
entropy_randombits(int fd,int timeout,byte * data,size_t size)852 static int entropy_randombits(int fd, int timeout, byte* data, size_t size)
853 {
854 	register int rc;
855 
856 	#if ENABLE_AIO
857 	struct aiocb my_aiocb;
858 	const struct aiocb* my_aiocb_list = &my_aiocb;
859 	# if HAVE_TIME_H
860 	struct timespec my_aiocb_timeout;
861 	# else
862 	#  error
863 	# endif
864 
865 	memset(&my_aiocb, 0, sizeof(struct aiocb));
866 
867 	my_aiocb.aio_fildes = fd;
868 	my_aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
869 	#endif
870 
871 	while (size)
872 	{
873 		#if ENABLE_AIO
874 		my_aiocb.aio_buf = data;
875 		my_aiocb.aio_nbytes = size;
876 
877 		rc = aio_read(&my_aiocb);
878 		#else
879 		rc = read(fd, data, size);
880 		#endif
881 
882 		if (rc < 0)
883 			return -1;
884 
885 		#if ENABLE_AIO
886 		my_aiocb_timeout.tv_sec = (timeout / 1000);
887 		my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
888 
889 		rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
890 
891 		if (rc < 0)
892 		{
893 			#if HAVE_ERRNO_H
894 			if (errno == EAGAIN)
895 			{
896 				/* certain linux glibc versions are buggy and don't aio_suspend properly */
897 				nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
898 
899 				my_aiocb_timeout.tv_sec = 0;
900 				my_aiocb_timeout.tv_nsec = 0;
901 
902 				/* and try again */
903 				rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
904 			}
905 			#endif
906 		}
907 
908 		if (rc < 0)
909 		{
910 			/* cancel any remaining reads */
911 			while (rc != AIO_ALLDONE)
912 			{
913 				rc = aio_cancel(fd, (struct aiocb*) 0);
914 
915 				if (rc == AIO_NOTCANCELED)
916 				{
917 					my_aiocb_timeout.tv_sec = (timeout / 1000);
918 					my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
919 
920 					nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
921 				}
922 
923 				if (rc < 0)
924 					break;
925 			}
926 
927 			return -1;
928 		}
929 
930 		rc = aio_error(&my_aiocb);
931 
932 		if (rc < 0)
933 			return -1;
934 
935 		rc = aio_return(&my_aiocb);
936 
937 		if (rc < 0)
938 			return -1;
939 		#endif
940 
941 		data += rc;
942 		size -= rc;
943 	}
944 	return 0;
945 }
946 #endif
947 
948 #if HAVE_DEV_TTY
949 /*!\ingroup ES_tty_m
950  */
entropy_ttybits(int fd,byte * data,size_t size)951 static int entropy_ttybits(int fd, byte* data, size_t size)
952 {
953 	byte dummy;
954 
955 	#if HAVE_TERMIOS_H
956 	struct termios tio_save, tio_set;
957 	#elif HAVE_TERMIO_H
958 	struct termio tio_save, tio_set;
959 	#else
960 	# error need alternative
961 	#endif
962 	#if HAVE_GETHRTIME
963 	hrtime_t hrtsample;
964 	#elif HAVE_GETTIMEOFDAY
965 	struct timeval tvsample;
966 	#else
967 	# error need alternative high-precision timer
968 	#endif
969 
970 	printf("please press random keys on your keyboard\n");
971 
972 	#if HAVE_TERMIOS_H
973 	if (tcgetattr(fd, &tio_save) < 0)
974 	{
975 		#if HAVE_ERRNO_H
976 		perror("tcgetattr failed");
977 		#endif
978 		return -1;
979 	}
980 
981 	tio_set = tio_save;
982 	tio_set.c_cc[VMIN] = 1;				/* read 1 tty character at a time */
983 	tio_set.c_cc[VTIME] = 0;			/* don't timeout the read */
984 	tio_set.c_iflag |= IGNBRK;			/* ignore <ctrl>-c */
985 	tio_set.c_lflag &= ~(ECHO|ICANON);	/* don't echo characters */
986 
987 	/* change the tty settings, and flush input characters */
988 	if (tcsetattr(fd, TCSAFLUSH, &tio_set) < 0)
989 	{
990 		#if HAVE_ERRNO_H
991 		perror("tcsetattr failed");
992 		#endif
993 		return -1;
994 	}
995 	#elif HAVE_TERMIO_H
996 	if (ioctl(fd, TCGETA, &tio_save) < 0)
997 	{
998 		#if HAVE_ERRNO_H
999 		perror("ioctl TCGETA failed");
1000 		#endif
1001 		return -1;
1002 	}
1003 
1004 	tio_set = tio_save;
1005 	tio_set.c_cc[VMIN] = 1;				/* read 1 tty character at a time */
1006 	tio_set.c_cc[VTIME] = 0;			/* don't timeout the read */
1007 	tio_set.c_iflag |= IGNBRK;			/* ignore <ctrl>-c */
1008 	tio_set.c_lflag &= ~(ECHO|ICANON);	/* don't echo characters */
1009 
1010 	/* change the tty settings, and flush input characters */
1011 	if (ioctl(fd, TCSETAF, &tio_set) < 0)
1012 	{
1013 		#if HAVE_ERRNO_H
1014 		perror("ioctl TCSETAF failed");
1015 		#endif
1016 		return -1;
1017 	}
1018 	#else
1019 	# error Need alternative tty control library
1020 	#endif
1021 
1022 	while (size)
1023 	{
1024 		if (read(fd, &dummy, 1) < 0)
1025 		{
1026 			#if HAVE_ERRNO_H
1027 			perror("tty read failed");
1028 			#endif
1029 			return -1;
1030 		}
1031 		printf("."); fflush(stdout);
1032 		#if HAVE_GETHRTIME
1033 		hrtsample = gethrtime();
1034 		/* discard the 10 lowest bits i.e. 1024 nanoseconds of a sample */
1035 		*(data++) = (byte)(hrtsample >> 10);
1036 		size--;
1037 		#elif HAVE_GETTIMEOFDAY
1038 		/* discard the 4 lowest bits i.e. 4 microseconds */
1039 		gettimeofday(&tvsample, 0);
1040 		/* get 8 bits from the sample */
1041 		*(data) = (byte)(tvsample.tv_usec >> 2);
1042 		size--;
1043 		#else
1044 		# error Need alternative high-precision timer sample
1045 		#endif
1046 	}
1047 
1048 	printf("\nthanks\n");
1049 
1050 	/* give the user 1 second to stop typing */
1051 	sleep(1);
1052 
1053 	#if HAVE_TERMIOS_H
1054 	/* change the tty settings, and flush input characters */
1055 	if (tcsetattr(fd, TCSAFLUSH, &tio_save) < 0)
1056 	{
1057 		#if HAVE_ERRNO_H
1058 		perror("tcsetattr failed");
1059 		#endif
1060 		return -1;
1061 	}
1062 	#elif HAVE_TERMIO_H
1063 	/* restore the tty settings, and flush input characters */
1064 	if (ioctl(fd, TCSETAF, &tio_save) < 0)
1065 	{
1066 		#if HAVE_ERRNO_H
1067 		perror("ioctl TCSETAF failed");
1068 		#endif
1069 		return -1;
1070 	}
1071 	#else
1072 	# error Need alternative tty control library
1073 	#endif
1074 
1075 	return 0;
1076 }
1077 #endif
1078 
1079 #if HAVE_DEV_AUDIO
1080 /*!\ingroup ES_audio_m
1081  */
entropy_dev_audio(byte * data,size_t size)1082 int entropy_dev_audio(byte* data, size_t size)
1083 {
1084 	const char* timeout_env = getenv("BEECRYPT_ENTROPY_AUDIO_TIMEOUT");
1085 
1086 	register int rc;
1087 
1088 	#ifdef _REENTRANT
1089 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1090 	if (mutex_lock(&dev_audio_lock))
1091 		return -1;
1092 	# elif HAVE_PTHREAD_H
1093 	if (pthread_mutex_lock(&dev_audio_lock))
1094 		return -1;
1095 	# endif
1096 	#endif
1097 
1098 	#if HAVE_SYS_STAT_H
1099 	if (statdevice(name_dev_audio) < 0)
1100 		goto dev_audio_end;
1101 	#endif
1102 
1103 	if ((rc = dev_audio_fd = opendevice(name_dev_audio)) < 0)
1104 		goto dev_audio_end;
1105 
1106 	#if HAVE_SYS_AUDIOIO_H /* i.e. Solaris */
1107 	{
1108 		struct audio_info info;
1109 
1110 		AUDIO_INITINFO(&info);
1111 
1112 		info.record.sample_rate = 48000;
1113 		info.record.channels = 2;
1114 		info.record.precision = 16;
1115 		info.record.encoding = AUDIO_ENCODING_LINEAR;
1116 		info.record.gain = AUDIO_MAX_GAIN;
1117 		info.record.pause = 0;
1118 		info.record.buffer_size = 4096;
1119 		info.record.samples = 0;
1120 
1121 		if ((rc = ioctl(dev_audio_fd, AUDIO_SETINFO, &info)) < 0)
1122 		{
1123 			if (errno == EINVAL)
1124 			{
1125 				/* use a conservative setting this time */
1126 				info.record.sample_rate = 22050;
1127 				info.record.channels = 1;
1128 				info.record.precision = 8;
1129 
1130 				if ((rc = ioctl(dev_audio_fd, AUDIO_SETINFO, &info)) < 0)
1131 				{
1132 					#if HAVE_ERRNO_H
1133 					perror("ioctl AUDIO_SETINFO failed");
1134 					#endif
1135 					close(dev_audio_fd);
1136 
1137 					goto dev_audio_end;
1138 				}
1139 			}
1140 			else
1141 			{
1142 				#if HAVE_ERRNO_H
1143 				perror("ioctl AUDIO_SETINFO failed");
1144 				#endif
1145 				close(dev_audio_fd);
1146 
1147 				goto dev_audio_end;
1148 			}
1149 		}
1150 
1151 		rc = entropy_noise_gather(dev_audio_fd, info.record.precision >> 3, info.record.channels, 0, timeout_env ? atoi(timeout_env) : 1000, data, size);
1152 	}
1153 	#else
1154 	# error Unknown type of /dev/audio interface
1155 	#endif
1156 
1157 	close(dev_audio_fd);
1158 
1159 dev_audio_end:
1160 	#ifdef _REENTRANT
1161 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1162 	mutex_unlock(&dev_audio_lock);
1163 	# elif HAVE_PTHREAD_H
1164 	pthread_mutex_unlock(&dev_audio_lock);
1165 	# endif
1166 	#endif
1167 	return rc;
1168 }
1169 #endif
1170 
1171 #if HAVE_DEV_DSP
1172 /*!\ingroup ES_dsp_m
1173  */
entropy_dev_dsp(byte * data,size_t size)1174 int entropy_dev_dsp(byte* data, size_t size)
1175 {
1176 	const char* timeout_env = getenv("BEECRYPT_ENTROPY_DSP_TIMEOUT");
1177 
1178 	register int rc;
1179 
1180 	#ifdef _REENTRANT
1181 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1182 	if (mutex_lock(&dev_dsp_lock))
1183 		return -1;
1184 	# elif HAVE_PTHREAD_H
1185 	if (pthread_mutex_lock(&dev_dsp_lock))
1186 		return -1;
1187 	# endif
1188 	#endif
1189 
1190 	#if HAVE_SYS_STAT_H
1191 	if ((rc = statdevice(name_dev_dsp)) < 0)
1192 		goto dev_dsp_end;
1193 	#endif
1194 
1195 	if ((rc = dev_dsp_fd = opendevice(name_dev_dsp)) < 0)
1196 		goto dev_dsp_end;
1197 
1198 	#if HAVE_SYS_SOUNDCARD_H /* i.e. Linux audio */
1199 	{
1200 		int mask, format, samplesize, stereo, speed, swap;
1201 
1202 		if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_GETFMTS, &mask)) < 0)
1203 		{
1204 			#if HAVE_ERRNO_H
1205 			perror("ioctl SNDCTL_DSP_GETFMTS failed");
1206 			#endif
1207 			close (dev_dsp_fd);
1208 
1209 			goto dev_dsp_end;
1210 		}
1211 
1212 		#if WORDS_BIGENDIAN
1213 		if (mask & AFMT_S16_BE)
1214 		{
1215 			format = AFMT_S16_BE;
1216 			samplesize = 2;
1217 			swap = 0;
1218 		}
1219 		else if (mask & AFMT_S16_LE)
1220 		{
1221 			format = AFMT_S16_LE;
1222 			samplesize = 2;
1223 			swap = 1;
1224 		}
1225 		#else
1226 		if (mask & AFMT_S16_LE)
1227 		{
1228 			format = AFMT_S16_LE;
1229 			samplesize = 2;
1230 			swap = 0;
1231 		}
1232 		else if (mask & AFMT_S16_BE)
1233 		{
1234 			format = AFMT_S16_BE;
1235 			samplesize = 2;
1236 			swap = 1;
1237 		}
1238 		#endif
1239 		else if (mask & AFMT_S8)
1240 		{
1241 			format = AFMT_S8;
1242 			samplesize = 1;
1243 			swap = 0;
1244 		}
1245 		else
1246 		{
1247 			/* No linear audio format available */
1248 			rc = -1;
1249 
1250 			close(dev_dsp_fd);
1251 
1252 			goto dev_dsp_end;
1253 		}
1254 
1255 		if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_SETFMT, &format)) < 0)
1256 		{
1257 			#if HAVE_ERRNO_H
1258 			perror("ioctl SNDCTL_DSP_SETFMT failed");
1259 			#endif
1260 			close(dev_dsp_fd);
1261 
1262 			goto dev_dsp_end;
1263 		}
1264 
1265 		/* the next two commands are not critical */
1266 		stereo = 1;
1267 		ioctl(dev_dsp_fd, SNDCTL_DSP_STEREO, &stereo);
1268 
1269 		speed = 44100;
1270 		ioctl(dev_dsp_fd, SNDCTL_DSP_SPEED, &speed);
1271 
1272 		rc = entropy_noise_gather(dev_dsp_fd, samplesize, 2, swap, timeout_env ? atoi(timeout_env) : 1000, data, size);
1273 	}
1274 	#else
1275 	# error Unknown type of /dev/dsp interface
1276 	#endif
1277 
1278 	close(dev_dsp_fd);
1279 
1280 dev_dsp_end:
1281 	#ifdef _REENTRANT
1282 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1283 	mutex_unlock(&dev_dsp_lock);
1284 	# elif HAVE_PTHREAD_H
1285 	pthread_mutex_unlock(&dev_dsp_lock);
1286 	# endif
1287 	#endif
1288 
1289 	return rc;
1290 }
1291 #endif
1292 
1293 #if HAVE_DEV_RANDOM
1294 /*!\ingroup ES_random_m
1295  */
entropy_dev_random(byte * data,size_t size)1296 int entropy_dev_random(byte* data, size_t size)
1297 {
1298 	const char* timeout_env = getenv("BEECRYPT_ENTROPY_RANDOM_TIMEOUT");
1299 
1300 	int rc;
1301 
1302 	#ifdef _REENTRANT
1303 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1304 	if (mutex_lock(&dev_random_lock))
1305 		return -1;
1306 	# elif HAVE_PTHREAD_H
1307 	if (pthread_mutex_lock(&dev_random_lock))
1308 		return -1;
1309 	# endif
1310 	#endif
1311 
1312 	#if HAVE_SYS_STAT_H
1313 	if ((rc = statdevice(name_dev_random)) < 0)
1314 		goto dev_random_end;
1315 	#endif
1316 
1317 	if ((rc = dev_random_fd = opendevice(name_dev_random)) < 0)
1318 		goto dev_random_end;
1319 
1320 	/* collect entropy, with timeout */
1321 	rc = entropy_randombits(dev_random_fd, timeout_env ? atoi(timeout_env) : 1000, data, size);
1322 
1323 	close(dev_random_fd);
1324 
1325 dev_random_end:
1326 	#ifdef _REENTRANT
1327 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1328 	mutex_unlock(&dev_random_lock);
1329 	# elif HAVE_PTHREAD_H
1330 	pthread_mutex_unlock(&dev_random_lock);
1331 	# endif
1332 	#endif
1333 	return rc;
1334 }
1335 #endif
1336 
1337 #if HAVE_DEV_URANDOM
1338 /*!\ingroup ES_urandom_m
1339  */
entropy_dev_urandom(byte * data,size_t size)1340 int entropy_dev_urandom(byte* data, size_t size)
1341 {
1342 	const char* timeout_env = getenv("BEECRYPT_ENTROPY_URANDOM_TIMEOUT");
1343 
1344 	register int rc;
1345 
1346 	#ifdef _REENTRANT
1347 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1348 	if (mutex_lock(&dev_urandom_lock))
1349 		return -1;
1350 	# elif HAVE_PTHREAD_H
1351 	if (pthread_mutex_lock(&dev_urandom_lock))
1352 		return -1;
1353 	# endif
1354 	#endif
1355 
1356 	#if HAVE_SYS_STAT_H
1357 	if ((rc = statdevice(name_dev_urandom)) < 0)
1358 		goto dev_urandom_end;
1359 	#endif
1360 
1361 	if ((rc = dev_urandom_fd = opendevice(name_dev_urandom)) < 0)
1362 		goto dev_urandom_end;
1363 
1364 	/* collect entropy, with timeout */
1365 	rc = entropy_randombits(dev_urandom_fd, timeout_env ? atoi(timeout_env) : 1000, data, size);
1366 
1367 	close(dev_urandom_fd);
1368 
1369 dev_urandom_end:
1370 	#ifdef _REENTRANT
1371 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1372 	mutex_unlock(&dev_urandom_lock);
1373 	# elif HAVE_PTHREAD_H
1374 	pthread_mutex_unlock(&dev_urandom_lock);
1375 	# endif
1376 	#endif
1377 	return rc;
1378 }
1379 #endif
1380 
1381 #if HAVE_DEV_TTY
1382 /*!\ingroup ES_tty_m
1383  */
entropy_dev_tty(byte * data,size_t size)1384 int entropy_dev_tty(byte* data, size_t size)
1385 {
1386 	register int rc;
1387 
1388 	#ifdef _REENTRANT
1389 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1390 	if (mutex_lock(&dev_tty_lock))
1391 		return -1;
1392 	# elif HAVE_PTHREAD_H
1393 	if (pthread_mutex_lock(&dev_tty_lock))
1394 		return -1;
1395 	# endif
1396 	#endif
1397 
1398 	#if HAVE_SYS_STAT_H
1399 	if ((rc = statdevice(dev_tty_name)) < 0)
1400 		goto dev_tty_end;
1401 	#endif
1402 
1403 	if ((rc = dev_tty_fd = opendevice(dev_tty_name)) < 0)
1404 		goto dev_tty_end;
1405 
1406 	rc = entropy_ttybits(dev_tty_fd, data, size);
1407 
1408 	close(dev_tty_fd);
1409 
1410 dev_tty_end:
1411 	#ifdef _REENTRANT
1412 	# if HAVE_THREAD_H && HAVE_SYNCH_H
1413 	mutex_unlock(&dev_tty_lock);
1414 	# elif HAVE_PTHREAD_H
1415 	pthread_mutex_unlock(&dev_tty_lock);
1416 	# endif
1417 	#endif
1418 
1419 	return rc;
1420 }
1421 #endif
1422 
1423 #endif
1424