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