00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #define BEECRYPT_DLL_EXPORT
00030
00031 #include "system.h"
00032 #include "entropy.h"
00033 #include "endianness.h"
00034
00035 #if WIN32
00036 # include <mmsystem.h>
00037 # include <wincrypt.h>
00038 # include <winerror.h>
00039 #else
00040 # if HAVE_SYS_IOCTL_H
00041 # include <sys/ioctl.h>
00042 # endif
00043 # if HAVE_SYS_AUDIOIO_H
00044 # include <sys/audioio.h>
00045 # endif
00046 # if HAVE_SYS_SOUNDCARD_H
00047 # include <sys/soundcard.h>
00048 # endif
00049 # if HAVE_TERMIOS_H
00050 # include <termios.h>
00051 # elif HAVE_TERMIO_H
00052 # include <termio.h>
00053 # endif
00054 # if HAVE_SYNCH_H
00055 # include <synch.h>
00056 # elif HAVE_PTHREAD_H
00057 # include <pthread.h>
00058 # endif
00059 # if HAVE_AIO_H
00060 # include <aio.h>
00061 # if defined(__LCLINT__)
00062
00063 extern int
00064 nanosleep (const struct timespec *__requested_time,
00065 struct timespec *__remaining)
00066 ;
00067
00068 extern void
00069 aio_init (const struct aioinit *__init)
00070 ;
00071 extern int
00072 aio_read (struct aiocb *__aiocbp)
00073 ;
00074 extern int
00075 aio_write (struct aiocb *__aiocbp)
00076 ;
00077 extern int
00078 lio_listio (int __mode,
00079 struct aiocb *const __list[],
00080 int __nent, struct sigevent *__sig)
00081 ;
00082 extern int
00083 aio_error (const struct aiocb *__aiocbp)
00084 ;
00085 extern __ssize_t
00086 aio_return (struct aiocb *__aiocbp)
00087 ;
00088 extern int
00089 aio_cancel (int __fildes, struct aiocb *__aiocbp)
00090 ;
00091 extern int
00092 aio_suspend ( const struct aiocb *const __list[], int __nent,
00093 const struct timespec *__timeout)
00094 ;
00095 extern int
00096 aio_fsync (int __operation, struct aiocb *__aiocbp)
00097 ;
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 # endif
00113 # endif
00114 #endif
00115
00116 #include "debug.h"
00117
00118 #if WIN32
00119 static HINSTANCE entropy_instance = (HINSTANCE) 0;
00120
00121 static HANDLE entropy_wavein_lock;
00122 static HANDLE entropy_wavein_event;
00123
00124 int entropy_provider_setup(HINSTANCE hInst)
00125 {
00126 if (!entropy_instance)
00127 {
00128 entropy_instance = hInst;
00129 if (!(entropy_wavein_lock = CreateMutex(NULL, FALSE, NULL)))
00130 return -1;
00131 if (!(entropy_wavein_event = CreateEvent(NULL, FALSE, FALSE, NULL)))
00132 return -1;
00133 }
00134 return 0;
00135 }
00136
00137 int entropy_provider_cleanup()
00138 {
00139 if (entropy_wavein_lock)
00140 {
00141 CloseHandle(entropy_wavein_lock);
00142 entropy_wavein_lock = 0;
00143 }
00144 if (entropy_wavein_event)
00145 {
00146 CloseHandle(entropy_wavein_event);
00147 entropy_wavein_event = 0;
00148 }
00149 return 0;
00150 }
00151 #endif
00152
00153 #if WIN32 || HAVE_DEV_AUDIO || HAVE_DEV_DSP
00154
00158
00159 static int entropy_noise_filter(void* sampledata, int samplecount, int samplesize, int channels, int swap)
00160
00161
00162 {
00163 register int rc = 0, i;
00164
00165 switch (samplesize)
00166 {
00167 case 1:
00168 {
00169 uint8* samples = (uint8*) sampledata;
00170
00171 switch (channels)
00172 {
00173 case 1:
00174 {
00175 int zero_count = 0;
00176 int ones_count = 0;
00177
00178 for (i = 0; i < samplecount; i++)
00179 {
00180 if ((samples[i] & 0x1) != 0)
00181 ones_count++;
00182 else
00183 zero_count++;
00184 }
00185
00186 if ((zero_count == 0) || (ones_count == 0))
00187 {
00188 #if HAVE_ERRNO_H
00189 errno = EIO;
00190 #endif
00191 rc = -1;
00192 }
00193 }
00194 break;
00195
00196 case 2:
00197 {
00198 int zero_count_left = 0;
00199 int ones_count_left = 0;
00200 int zero_count_right = 0;
00201 int ones_count_right = 0;
00202
00203 for (i = 0; i < samplecount; i++)
00204 {
00205 if (i & 1)
00206 {
00207 if ((samples[i] & 0x1) != 0)
00208 ones_count_left++;
00209 else
00210 zero_count_left++;
00211 }
00212 else
00213 {
00214 if ((samples[i] & 0x1) != 0)
00215 ones_count_right++;
00216 else
00217 zero_count_right++;
00218 }
00219 }
00220
00221 if ((zero_count_left == 0) || (ones_count_left == 0) ||
00222 (zero_count_right == 0) || (ones_count_right == 0))
00223 {
00224 #if HAVE_ERRNO_H
00225 errno = EIO;
00226 #endif
00227 rc = -1;
00228 }
00229 }
00230 break;
00231
00232 default:
00233 #if HAVE_ERRNO_H
00234 errno = EINVAL;
00235 #endif
00236 rc = -1;
00237 }
00238 }
00239 break;
00240
00241 case 2:
00242 {
00243 uint16* samples = (uint16*) sampledata;
00244
00245 switch (channels)
00246 {
00247 case 1:
00248 {
00249 int zero_count = 0;
00250 int ones_count = 0;
00251
00252 for (i = 0; i < samplecount; i++)
00253 {
00254 if (swap)
00255 samples[i] = swapu16(samples[i]);
00256
00257 if ((samples[i] & 0x1) != 0)
00258 ones_count++;
00259 else
00260 zero_count++;
00261 }
00262
00263 if ((zero_count == 0) || (ones_count == 0))
00264 {
00265 #if HAVE_ERRNO_H
00266 errno = EIO;
00267 #endif
00268 rc = -1;
00269 }
00270 }
00271 break;
00272
00273 case 2:
00274 {
00275 int zero_count_left = 0;
00276 int ones_count_left = 0;
00277 int zero_count_right = 0;
00278 int ones_count_right = 0;
00279
00280 for (i = 0; i < samplecount; i++)
00281 {
00282 if (swap)
00283 samples[i] = swapu16(samples[i]);
00284
00285 if (i & 1)
00286 {
00287 if ((samples[i] & 0x1) != 0)
00288 ones_count_left++;
00289 else
00290 zero_count_left++;
00291 }
00292 else
00293 {
00294 if ((samples[i] & 0x1) != 0)
00295 ones_count_right++;
00296 else
00297 zero_count_right++;
00298 }
00299 }
00300
00301 if ((zero_count_left == 0) || (ones_count_left == 0) ||
00302 (zero_count_right == 0) || (ones_count_right == 0))
00303 {
00304 #if HAVE_ERRNO_H
00305 errno = EIO;
00306 #endif
00307 rc = -1;
00308 }
00309 }
00310 break;
00311
00312 default:
00313 #if HAVE_ERRNO_H
00314 errno = EINVAL;
00315 #endif
00316 rc = -1;
00317 break;
00318 }
00319 }
00320 break;
00321
00322 default:
00323 #if HAVE_ERRNO_H
00324 errno = EINVAL;
00325 #endif
00326 rc = -1;
00327 break;
00328 }
00329
00330 return 0;
00331 }
00332
00333
00343 #if WIN32
00344 static int entropy_noise_gather(HWAVEIN wavein, int samplesize, int channels, int swap, int timeout, uint32 *data, int size)
00345 #else
00346
00347
00348 static int entropy_noise_gather(int fd, int samplesize, int channels, int swap, int timeout, uint32 *data, int size)
00349
00350
00351 #endif
00352 {
00353 uint32 randombits = ((unsigned)size) << 5;
00354 uint32 temp = 0;
00355 int rc, i;
00356
00357 byte* sampledata = (byte*) malloc(1024 * samplesize * channels);
00358
00359 #if WIN32
00360 WAVEHDR header;
00361
00362
00363 header.lpData = (LPSTR) sampledata;
00364 header.dwBufferLength = 1024 * samplesize * channels;
00365 header.dwFlags = 0;
00366
00367
00368 waveInStart(wavein);
00369
00370
00371 ResetEvent(entropy_wavein_event);
00372 #else
00373 # if ENABLE_AIO
00374 struct aiocb my_aiocb;
00375 const struct aiocb* my_aiocb_list = &my_aiocb;
00376 # if HAVE_TIME_H
00377 struct timespec my_aiocb_timeout;
00378 # else
00379 # error
00380 # endif
00381
00382
00383 *sampledata = 0;
00384
00385 memset(&my_aiocb, 0, sizeof(struct aiocb));
00386 memset(&my_aiocb_timeout, 0, sizeof(struct timespec));
00387
00388 my_aiocb.aio_fildes = fd;
00389 my_aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
00390 # endif
00391 #endif
00392
00393 if (sampledata == (byte*) 0)
00394 {
00395 #if HAVE_ERRNO_H
00396 errno = ENOMEM;
00397 #endif
00398 return -1;
00399 }
00400
00401
00402 while (randombits)
00403 {
00404 #if WIN32
00405
00406 waveInPrepareHeader(wavein, &header, sizeof(WAVEHDR));
00407 waveInAddBuffer(wavein, &header, sizeof(WAVEHDR));
00408
00409
00410 if (WaitForSingleObject(entropy_wavein_event, timeout) == WAIT_OBJECT_0)
00411 {
00412 rc = header.dwBytesRecorded;
00413 }
00414 else
00415 {
00416 waveInStop(wavein);
00417 waveInReset(wavein);
00418
00419 free(sampledata);
00420 return -1;
00421 }
00422 #else
00423 # if ENABLE_AIO
00424
00425 my_aiocb.aio_buf = sampledata;
00426
00427 my_aiocb.aio_nbytes = 1024 * samplesize * channels;
00428
00429 rc = aio_read(&my_aiocb);
00430 # else
00431 rc = read(fd, sampledata, 1024 * samplesize * channels);
00432 # endif
00433
00434 if (rc < 0)
00435 {
00436
00437 free(sampledata);
00438
00439 return -1;
00440 }
00441
00442 # if ENABLE_AIO
00443 my_aiocb_timeout.tv_sec = (timeout / 1000);
00444 my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
00445
00446 rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
00447
00448 if (rc < 0)
00449 {
00450 #if HAVE_ERRNO_H
00451 if (errno == EAGAIN)
00452 {
00453
00454 (void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
00455
00456 my_aiocb_timeout.tv_sec = (timeout / 1000);
00457 my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
00458
00459
00460 rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
00461 }
00462 #endif
00463 }
00464
00465 if (rc < 0)
00466 {
00467
00468 while (rc != AIO_ALLDONE)
00469 {
00470 rc = aio_cancel(fd, (struct aiocb*) 0);
00471
00472 if (rc == AIO_NOTCANCELED)
00473 {
00474 my_aiocb_timeout.tv_sec = (timeout / 1000);
00475 my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
00476
00477 (void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
00478 }
00479
00480 if (rc < 0)
00481 break;
00482 }
00483
00484 free(sampledata);
00485
00486 return -1;
00487 }
00488
00489 rc = aio_error(&my_aiocb);
00490
00491 if (rc)
00492 {
00493
00494 free(sampledata);
00495
00496 return -1;
00497 }
00498
00499 rc = aio_return(&my_aiocb);
00500
00501 if (rc < 0)
00502 {
00503
00504 free(sampledata);
00505
00506 return -1;
00507 }
00508 # endif
00509 #endif
00510
00511 if (entropy_noise_filter(sampledata, rc / samplesize, samplesize, channels, swap) < 0)
00512 {
00513 fprintf(stderr, "noise filter indicates too much bias in audio samples\n");
00514
00515 free(sampledata);
00516
00517 return -1;
00518 }
00519
00520 switch (samplesize)
00521 {
00522 case 1:
00523 {
00524 uint8* samples = (uint8*) sampledata;
00525
00526 for (i = 0; randombits && (i < 1024); i += 2)
00527 {
00528 if ((samples[i] ^ samples[i+1]) != 0)
00529 {
00530 temp <<= 1;
00531 temp |= samples[i];
00532 randombits--;
00533 if (!(randombits & 0x1f))
00534 *(data++) = temp;
00535 }
00536 }
00537 }
00538 break;
00539
00540 case 2:
00541 {
00542 uint16* samples = (uint16*) sampledata;
00543
00544 for (i = 0; randombits && (i < 1024); i += 2)
00545 {
00546 if (samples[i] ^ samples[i+1])
00547 {
00548 temp <<= 1;
00549 temp |= samples[i];
00550 randombits--;
00551 if (!(randombits & 0x1f))
00552 *(data++) = temp;
00553 }
00554 }
00555 }
00556 break;
00557
00558 default:
00559
00560 free(sampledata);
00561
00562 return -1;
00563 break;
00564 }
00565 }
00566
00567
00568 #if WIN32
00569 waveInStop(wavein);
00570 waveInReset(wavein);
00571 #endif
00572
00573
00574 free(sampledata);
00575
00576 return 0;
00577 }
00578
00579
00580 #endif
00581
00582 #if WIN32
00583 int entropy_wavein(uint32* data, int size)
00584 {
00585 const char *timeout_env = getenv("BEECRYPT_ENTROPY_WAVEIN_TIMEOUT");
00586
00587 WAVEINCAPS waveincaps;
00588 WAVEFORMATEX waveformatex;
00589 HWAVEIN wavein;
00590 MMRESULT rc;
00591
00592 rc = waveInGetDevCaps(WAVE_MAPPER, &waveincaps, sizeof(WAVEINCAPS));
00593 if (rc != MMSYSERR_NOERROR)
00594 return -1;
00595
00596
00597 switch (waveformatex.nChannels = waveincaps.wChannels)
00598 {
00599 case 1:
00600
00601 if (waveincaps.dwFormats & WAVE_FORMAT_4M16)
00602 {
00603 waveformatex.nSamplesPerSec = 44100;
00604 waveformatex.wBitsPerSample = 16;
00605 }
00606 else if (waveincaps.dwFormats & WAVE_FORMAT_2M16)
00607 {
00608 waveformatex.nSamplesPerSec = 22050;
00609 waveformatex.wBitsPerSample = 16;
00610 }
00611 else if (waveincaps.dwFormats & WAVE_FORMAT_1M16)
00612 {
00613 waveformatex.nSamplesPerSec = 11025;
00614 waveformatex.wBitsPerSample = 16;
00615 }
00616 else if (waveincaps.dwFormats & WAVE_FORMAT_4M08)
00617 {
00618 waveformatex.nSamplesPerSec = 44100;
00619 waveformatex.wBitsPerSample = 8;
00620 }
00621 else if (waveincaps.dwFormats & WAVE_FORMAT_2M08)
00622 {
00623 waveformatex.nSamplesPerSec = 22050;
00624 waveformatex.wBitsPerSample = 8;
00625 }
00626 else if (waveincaps.dwFormats & WAVE_FORMAT_1M08)
00627 {
00628 waveformatex.nSamplesPerSec = 11025;
00629 waveformatex.wBitsPerSample = 8;
00630 }
00631 else
00632 return -1;
00633
00634 break;
00635 case 2:
00636
00637 if (waveincaps.dwFormats & WAVE_FORMAT_4S16)
00638 {
00639 waveformatex.nSamplesPerSec = 44100;
00640 waveformatex.wBitsPerSample = 16;
00641 }
00642 else if (waveincaps.dwFormats & WAVE_FORMAT_2S16)
00643 {
00644 waveformatex.nSamplesPerSec = 22050;
00645 waveformatex.wBitsPerSample = 16;
00646 }
00647 else if (waveincaps.dwFormats & WAVE_FORMAT_1S16)
00648 {
00649 waveformatex.nSamplesPerSec = 11025;
00650 waveformatex.wBitsPerSample = 16;
00651 }
00652 else if (waveincaps.dwFormats & WAVE_FORMAT_4S08)
00653 {
00654 waveformatex.nSamplesPerSec = 44100;
00655 waveformatex.wBitsPerSample = 8;
00656 }
00657 else if (waveincaps.dwFormats & WAVE_FORMAT_2S08)
00658 {
00659 waveformatex.nSamplesPerSec = 22050;
00660 waveformatex.wBitsPerSample = 8;
00661 }
00662 else if (waveincaps.dwFormats & WAVE_FORMAT_1S08)
00663 {
00664 waveformatex.nSamplesPerSec = 11025;
00665 waveformatex.wBitsPerSample = 8;
00666 }
00667 else
00668 return -1;
00669
00670 break;
00671 }
00672
00673 waveformatex.wFormatTag = WAVE_FORMAT_PCM;
00674 waveformatex.nAvgBytesPerSec = (waveformatex.nSamplesPerSec * waveformatex.nChannels * waveformatex.wBitsPerSample) / 8;
00675 waveformatex.nBlockAlign = (waveformatex.nChannels * waveformatex.wBitsPerSample) / 8;
00676 waveformatex.cbSize = 0;
00677
00678
00679
00680 if (WaitForSingleObject(entropy_wavein_lock, INFINITE) != WAIT_OBJECT_0)
00681 return -1;
00682
00683 rc = waveInOpen(&wavein, WAVE_MAPPER, &waveformatex, (DWORD) entropy_wavein_event, (DWORD) 0, CALLBACK_EVENT);
00684 if (rc != MMSYSERR_NOERROR)
00685 {
00686 fprintf(stderr, "waveInOpen failed!\n"); (void) fflush(stderr);
00687 ReleaseMutex(entropy_wavein_lock);
00688 return -1;
00689 }
00690
00691 rc = entropy_noise_gather(wavein, waveformatex.wBitsPerSample >> 3, waveformatex.nChannels, 0, timeout_env ? atoi(timeout_env) : 2000, data, size);
00692
00693 waveInClose(wavein);
00694
00695 ReleaseMutex(entropy_wavein_lock);
00696
00697 return rc;
00698 }
00699
00700 int entropy_console(uint32* data, int size)
00701 {
00702 register uint32 randombits = size << 5;
00703 register uint32 temp = 0;
00704
00705 HANDLE hStdin;
00706 DWORD inRet;
00707 INPUT_RECORD inEvent;
00708 LARGE_INTEGER hrtsample;
00709
00710 hStdin = GetStdHandle(STD_INPUT_HANDLE);
00711 if (hStdin == INVALID_HANDLE_VALUE)
00712 {
00713 fprintf(stderr, "GetStdHandle error %d\n", GetLastError());
00714 return -1;
00715 }
00716
00717 printf("please press random keys on your keyboard\n"); (void) fflush(stdout);
00718
00719 while (randombits)
00720 {
00721 if (!ReadConsoleInput(hStdin, &inEvent, 1, &inRet))
00722 {
00723 fprintf(stderr, "ReadConsoleInput failed\n"); (void) fflush(stderr);
00724 return -1;
00725 }
00726 if ((inRet == 1) && (inEvent.EventType == KEY_EVENT) && inEvent.Event.KeyEvent.bKeyDown)
00727 {
00728 printf("."); (void) fflush(stdout);
00729 if (!QueryPerformanceCounter(&hrtsample))
00730 {
00731 fprintf(stderr, "QueryPerformanceCounter failed\n"); (void) fflush(stderr);
00732 return -1;
00733 }
00734
00735
00736 temp <<= 8;
00737
00738 temp |= (uint32)(hrtsample.LowPart >> 2);
00739 randombits -= 8;
00740
00741 if (!(randombits & 0x1f))
00742 *(data++) = temp;
00743 }
00744 }
00745
00746 printf("\nthanks\n");
00747
00748 Sleep(1000);
00749
00750 if (!FlushConsoleInputBuffer(hStdin))
00751 {
00752 fprintf(stderr, "FlushConsoleInputBuffer failed\n"); (void) fflush(stderr);
00753 return -1;
00754 }
00755
00756 return 0;
00757 }
00758
00759 int entropy_wincrypt(uint32* data, int size)
00760 {
00761 HCRYPTPROV hCrypt;
00762 DWORD provType = PROV_RSA_FULL;
00763 BOOL rc;
00764
00765
00766
00767 if (!CryptAcquireContext(&hCrypt, "BeeCrypt", NULL, provType, 0))
00768 {
00769 #if defined(NTE_BAD_KEYSET)
00770 if (GetLastError() == NTE_BAD_KEYSET)
00771 {
00772 if (!CryptAcquireContext(&hCrypt, "BeeCrypt", NULL, provType, CRYPT_NEWKEYSET))
00773 return -1;
00774 }
00775 else
00776 return -1;
00777 #else
00778 return -1;
00779 #endif
00780 }
00781
00782 rc = CryptGenRandom(hCrypt, size << 2, (BYTE*) data);
00783
00784 CryptReleaseContext(hCrypt, 0);
00785
00786 return rc ? 0 : -1;
00787 }
00788
00789 #else
00790
00791 #if HAVE_DEV_AUDIO
00792
00794
00795 static const char* name_dev_audio = "/dev/audio";
00796
00799
00800 static int dev_audio_fd = -1;
00801
00804 # ifdef _REENTRANT
00805 # if HAVE_SYNCH_H
00806
00807 static mutex_t dev_audio_lock = DEFAULTMUTEX;
00808 # elif HAVE_PTHREAD_H
00809
00810 static pthread_mutex_t dev_audio_lock = PTHREAD_MUTEX_INITIALIZER;
00811 # else
00812 # error Need locking mechanism
00813 # endif
00814 # endif
00815 #endif
00816
00817 #if HAVE_DEV_DSP
00818
00820
00821 static const char* name_dev_dsp = "/dev/dsp";
00822
00825
00826 static int dev_dsp_fd = -1;
00827
00830 # ifdef _REENTRANT
00831 # if HAVE_SYNCH_H
00832
00833 static mutex_t dev_dsp_lock = DEFAULTMUTEX;
00834 # elif HAVE_PTHREAD_H
00835
00836 static pthread_mutex_t dev_dsp_lock = PTHREAD_MUTEX_INITIALIZER;
00837 # else
00838 # error Need locking mechanism
00839 # endif
00840 # endif
00841 #endif
00842
00843 #if HAVE_DEV_RANDOM
00844
00846
00847 static const char* name_dev_random = "/dev/random";
00848
00851
00852 static int dev_random_fd = -1;
00853
00856 # ifdef _REENTRANT
00857 # if HAVE_SYNCH_H
00858
00859 static mutex_t dev_random_lock = DEFAULTMUTEX;
00860 # elif HAVE_PTHREAD_H
00861
00862 static pthread_mutex_t dev_random_lock = PTHREAD_MUTEX_INITIALIZER;
00863 # else
00864 # error Need locking mechanism
00865 # endif
00866 # endif
00867 #endif
00868
00869 #if HAVE_DEV_URANDOM
00870
00872
00873 static const char* name_dev_urandom = "/dev/urandom";
00874
00877
00878 static int dev_urandom_fd = -1;
00879
00882 # ifdef _REENTRANT
00883 # if HAVE_SYNCH_H
00884
00885 static mutex_t dev_urandom_lock = DEFAULTMUTEX;
00886 # elif HAVE_PTHREAD_H
00887
00888 static pthread_mutex_t dev_urandom_lock = PTHREAD_MUTEX_INITIALIZER;
00889 # else
00890 # error Need locking mechanism
00891 # endif
00892 # endif
00893 #endif
00894
00895 #if HAVE_DEV_TTY
00896
00898
00899 static const char *dev_tty_name = "/dev/tty";
00900
00903
00904 static int dev_tty_fd = -1;
00905
00909 # if defined(_REENTRANT) && !defined(hpux)
00910 # if HAVE_SYNCH_H
00911
00912 static mutex_t dev_tty_lock = DEFAULTMUTEX;
00913 # elif HAVE_PTHREAD_H
00914
00915 static pthread_mutex_t dev_tty_lock = PTHREAD_MUTEX_INITIALIZER;
00916 # else
00917 # error Need locking mechanism
00918 # endif
00919 # endif
00920 #endif
00921
00922 #if HAVE_SYS_STAT_H
00923
00927 static int statdevice(const char *device)
00928
00929
00930 {
00931 struct stat s;
00932
00933 if (stat(device, &s) < 0)
00934 {
00935 #if HAVE_ERRNO_H && HAVE_STRING_H
00936 fprintf(stderr, "cannot stat %s: %s\n", device, strerror(errno));
00937 #endif
00938 return -1;
00939 }
00940 if (!S_ISCHR(s.st_mode))
00941 {
00942 fprintf(stderr, "%s is not a device\n", device);
00943 return -1;
00944 }
00945 return 0;
00946 }
00947 #endif
00948
00953 static int opendevice(const char *device)
00954
00955
00956 {
00957 register int fd;
00958
00959 if ((fd = open(device, O_RDONLY)) < 0)
00960 {
00961 #if HAVE_ERRNO_H && HAVE_STRING_H
00962 fprintf(stderr, "open of %s failed: %s\n", device, strerror(errno));
00963 #endif
00964 return fd;
00965 }
00966
00967 return fd;
00968 }
00969
00970 #if HAVE_DEV_RANDOM || HAVE_DEV_URANDOM
00971
00978
00979 static int entropy_randombits(int fd, int timeout, uint32* data, int size)
00980
00981 {
00982 register byte* bytedata = (byte*) data;
00983 register int bytesize = (((unsigned)size) << 2);
00984 register int rc;
00985
00986 #if ENABLE_AIO
00987 struct aiocb my_aiocb;
00988 const struct aiocb* my_aiocb_list = &my_aiocb;
00989 # if HAVE_TIME_H
00990 struct timespec my_aiocb_timeout;
00991 # else
00992 # error
00993 # endif
00994
00995 memset(&my_aiocb, 0, sizeof(struct aiocb));
00996 memset(&my_aiocb_timeout, 0, sizeof(struct timespec));
00997
00998 my_aiocb.aio_fildes = fd;
00999 my_aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
01000 #endif
01001
01002
01003 while (bytesize)
01004 {
01005 #if ENABLE_AIO
01006
01007 my_aiocb.aio_buf = bytedata;
01008
01009 my_aiocb.aio_nbytes = bytesize;
01010
01011 rc = aio_read(&my_aiocb);
01012 #else
01013 rc = read(fd, bytedata, bytesize);
01014 #endif
01015
01016 if (rc < 0)
01017 return -1;
01018
01019 #if ENABLE_AIO
01020 my_aiocb_timeout.tv_sec = (timeout / 1000);
01021 my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
01022
01023 rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
01024
01025 if (rc < 0)
01026 {
01027 #if HAVE_ERRNO_H
01028 if (errno == EAGAIN)
01029 {
01030
01031 (void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
01032
01033 my_aiocb_timeout.tv_sec = 0;
01034 my_aiocb_timeout.tv_nsec = 0;
01035
01036
01037 rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
01038 }
01039 #endif
01040 }
01041
01042 if (rc < 0)
01043 {
01044
01045 while (rc != AIO_ALLDONE)
01046 {
01047 rc = aio_cancel(fd, (struct aiocb*) 0);
01048
01049 if (rc == AIO_NOTCANCELED)
01050 {
01051 my_aiocb_timeout.tv_sec = (timeout / 1000);
01052 my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
01053
01054 (void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
01055 }
01056
01057 if (rc < 0)
01058 break;
01059 }
01060
01061 return -1;
01062 }
01063
01064 rc = aio_error(&my_aiocb);
01065
01066 if (rc < 0)
01067 return -1;
01068
01069 rc = aio_return(&my_aiocb);
01070
01071 if (rc < 0)
01072 return -1;
01073 #endif
01074
01075 bytedata += rc;
01076 bytesize -= rc;
01077 }
01078
01079 return 0;
01080 }
01081
01082 #endif
01083
01084 #if HAVE_DEV_TTY
01085
01091
01092 static int entropy_ttybits(int fd, uint32* data, int size)
01093
01094
01095 {
01096 uint32 randombits = ((unsigned)size) << 5;
01097 uint32 temp = 0;
01098 byte dummy;
01099
01100 #if HAVE_TERMIOS_H
01101 struct termios tio_save, tio_set;
01102 #elif HAVE_TERMIO_H
01103 struct termio tio_save, tio_set;
01104 #else
01105 # need alternative
01106 #endif
01107 #if HAVE_GETHRTIME
01108 hrtime_t hrtsample;
01109 #elif HAVE_GETTIMEOFDAY
01110 struct timeval tvsample;
01111 #else
01112 # error Need alternative high-precision timer
01113 #endif
01114
01115 printf("please press random keys on your keyboard\n");
01116
01117 #if HAVE_TERMIOS_H
01118 if (tcgetattr(fd, &tio_save) < 0)
01119 {
01120 #if HAVE_ERRNO_H
01121 perror("tcgetattr failed");
01122 #endif
01123 return -1;
01124 }
01125
01126 tio_set = tio_save;
01127
01128 tio_set.c_cc[VMIN] = 1;
01129 tio_set.c_cc[VTIME] = 0;
01130
01131 tio_set.c_iflag |= IGNBRK;
01132 tio_set.c_lflag &= ~(ECHO|ICANON);
01133
01134
01135 if (tcsetattr(fd, TCSAFLUSH, &tio_set) < 0)
01136 {
01137 #if HAVE_ERRNO_H
01138 perror("tcsetattr failed");
01139 #endif
01140 return -1;
01141 }
01142 #elif HAVE_TERMIO_H
01143 if (ioctl(fd, TCGETA, &tio_save) < 0)
01144 {
01145 #if HAVE_ERRNO_H
01146 perror("ioctl TCGETA failed");
01147 #endif
01148 return -1;
01149 }
01150
01151 tio_set = tio_save;
01152 tio_set.c_cc[VMIN] = 1;
01153 tio_set.c_cc[VTIME] = 0;
01154 tio_set.c_iflag |= IGNBRK;
01155 tio_set.c_lflag &= ~(ECHO|ICANON);
01156
01157
01158 if (ioctl(fd, TCSETAF, &tio_set) < 0)
01159 {
01160 #if HAVE_ERRNO_H
01161 perror("ioctl TCSETAF failed");
01162 #endif
01163 return -1;
01164 }
01165 #else
01166 # error Need alternative tty control library
01167 #endif
01168
01169 while (randombits)
01170 {
01171 if (read(fd, &dummy, 1) < 0)
01172 {
01173 #if HAVE_ERRNO_H
01174 perror("tty read failed");
01175 #endif
01176 return -1;
01177 }
01178 printf("."); (void) fflush(stdout);
01179 #if HAVE_GETHRTIME
01180 hrtsample = gethrtime();
01181
01182 temp <<= 16;
01183
01184 temp |= (uint16)(hrtsample >> 10);
01185 randombits -= 16;
01186 #elif HAVE_GETTIMEOFDAY
01187
01188 (void) gettimeofday(&tvsample, 0);
01189
01190 temp <<= 8;
01191 temp |= (uint8)(((unsigned)tvsample.tv_usec) >> 2);
01192 randombits -= 8;
01193 #else
01194 # error Need alternative high-precision timer sample
01195 #endif
01196 if (!(randombits & 0x1f))
01197 *(data++) = temp;
01198 }
01199
01200 printf("\nthanks\n");
01201
01202
01203 (void) sleep(1);
01204
01205 #if HAVE_TERMIOS_H
01206
01207 if (tcsetattr(fd, TCSAFLUSH, &tio_save) < 0)
01208 {
01209 #if HAVE_ERRNO_H
01210 perror("tcsetattr failed");
01211 #endif
01212 return -1;
01213 }
01214 #elif HAVE_TERMIO_H
01215
01216 if (ioctl(fd, TCSETAF, &tio_save) < 0)
01217 {
01218 #if HAVE_ERRNO_H
01219 perror("ioctl TCSETAF failed");
01220 #endif
01221 return -1;
01222 }
01223 #else
01224 # error Need alternative tty control library
01225 #endif
01226
01227 return 0;
01228 }
01229
01230 #endif
01231
01232 #if HAVE_DEV_AUDIO
01233 int entropy_dev_audio(uint32 *data, int size)
01234 {
01235 const char* timeout_env = getenv("BEECRYPT_ENTROPY_AUDIO_TIMEOUT");
01236
01237 register int rc;
01238
01239 #ifdef _REENTRANT
01240 # if HAVE_SYNCH_H
01241 if (mutex_lock(&dev_audio_lock))
01242 return -1;
01243 # elif HAVE_PTHREAD_H
01244 if (pthread_mutex_lock(&dev_audio_lock))
01245 return -1;
01246 # endif
01247 #endif
01248
01249 #if HAVE_SYS_STAT_H
01250 if (statdevice(name_dev_audio) < 0)
01251 goto dev_audio_end;
01252 #endif
01253
01254 if ((rc = dev_audio_fd = opendevice(name_dev_audio)) < 0)
01255 goto dev_audio_end;
01256
01257 #if HAVE_SYS_AUDIOIO_H
01258 {
01259 struct audio_info info;
01260
01261 AUDIO_INITINFO(&info);
01262
01263 info.record.sample_rate = 48000;
01264 info.record.channels = 2;
01265 info.record.precision = 16;
01266 info.record.encoding = AUDIO_ENCODING_LINEAR;
01267 info.record.gain = AUDIO_MAX_GAIN;
01268 info.record.pause = 0;
01269 info.record.buffer_size = 4096;
01270 info.record.samples = 0;
01271
01272 if ((rc = ioctl(dev_audio_fd, AUDIO_SETINFO, &info)) < 0)
01273 {
01274 if (errno == EINVAL)
01275 {
01276
01277 info.record.sample_rate = 22050;
01278 info.record.channels = 1;
01279 info.record.precision = 8;
01280
01281 if ((rc = ioctl(dev_audio_fd, AUDIO_SETINFO, &info)) < 0)
01282 {
01283 #if HAVE_ERRNO_H
01284 perror("ioctl AUDIO_SETINFO failed");
01285 #endif
01286 (void) close(dev_audio_fd);
01287
01288 goto dev_audio_end;
01289 }
01290 }
01291 else
01292 {
01293 #if HAVE_ERRNO_H
01294 perror("ioctl AUDIO_SETINFO failed");
01295 #endif
01296 (void) close(dev_audio_fd);
01297
01298 goto dev_audio_end;
01299 }
01300 }
01301
01302 rc = entropy_noise_gather(dev_audio_fd, info.record.precision >> 3, info.record.channels, 0, timeout_env ? atoi(timeout_env) : 1000, data, size);
01303 }
01304 #else
01305 # error Unknown type of /dev/audio interface
01306 #endif
01307
01308 (void) close(dev_audio_fd);
01309
01310 dev_audio_end:
01311 #ifdef _REENTRANT
01312 # if HAVE_SYNCH_H
01313 mutex_unlock(&dev_audio_lock);
01314 # elif HAVE_PTHREAD_H
01315 pthread_mutex_unlock(&dev_audio_lock);
01316 # endif
01317 #endif
01318 return rc;
01319 }
01320 #endif
01321
01322 #if HAVE_DEV_DSP
01323 int entropy_dev_dsp(uint32 *data, int size)
01324
01325
01326 {
01327 const char* timeout_env = getenv("BEECRYPT_ENTROPY_DSP_TIMEOUT");
01328
01329 register int rc;
01330
01331 #ifdef _REENTRANT
01332 # if HAVE_SYNCH_H
01333 if (mutex_lock(&dev_dsp_lock))
01334 return -1;
01335 # elif HAVE_PTHREAD_H
01336
01337 if (pthread_mutex_lock(&dev_dsp_lock))
01338 return -1;
01339
01340 # endif
01341 #endif
01342
01343 #if HAVE_SYS_STAT_H
01344 if ((rc = statdevice(name_dev_dsp)) < 0)
01345 goto dev_dsp_end;
01346 #endif
01347
01348 if ((rc = dev_dsp_fd = opendevice(name_dev_dsp)) < 0)
01349 goto dev_dsp_end;
01350
01351 #if HAVE_SYS_SOUNDCARD_H
01352 {
01353 int mask, format, samplesize, stereo, speed, swap;
01354
01355 mask = 0;
01356
01357 if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_GETFMTS, &mask)) < 0)
01358
01359 {
01360 #if HAVE_ERRNO_H
01361 perror("ioctl SNDCTL_DSP_GETFMTS failed");
01362 #endif
01363 (void) close (dev_dsp_fd);
01364
01365 goto dev_dsp_end;
01366 }
01367
01368 #if WORDS_BIGENDIAN
01369 if (mask & AFMT_S16_BE)
01370 {
01371 format = AFMT_S16_BE;
01372 samplesize = 2;
01373 swap = 0;
01374 }
01375 else if (mask & AFMT_S16_LE)
01376 {
01377 format = AFMT_S16_LE;
01378 samplesize = 2;
01379 swap = 1;
01380 }
01381 #else
01382 if (mask & AFMT_S16_LE)
01383 {
01384 format = AFMT_S16_LE;
01385 samplesize = 2;
01386 swap = 0;
01387 }
01388 else if (mask & AFMT_S16_BE)
01389 {
01390 format = AFMT_S16_BE;
01391 samplesize = 2;
01392 swap = 1;
01393 }
01394 #endif
01395 else if (mask & AFMT_S8)
01396 {
01397 format = AFMT_S8;
01398 samplesize = 1;
01399 swap = 0;
01400 }
01401 else
01402 {
01403
01404 rc = -1;
01405
01406 (void) close(dev_dsp_fd);
01407
01408 goto dev_dsp_end;
01409 }
01410
01411
01412 if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_SETFMT, &format)) < 0)
01413
01414 {
01415 #if HAVE_ERRNO_H
01416 perror("ioctl SNDCTL_DSP_SETFMT failed");
01417 #endif
01418 (void) close(dev_dsp_fd);
01419
01420 goto dev_dsp_end;
01421 }
01422
01423
01424 stereo = 1;
01425
01426 (void) ioctl(dev_dsp_fd, SNDCTL_DSP_STEREO, &stereo);
01427
01428
01429 speed = 44100;
01430
01431 (void) ioctl(dev_dsp_fd, SNDCTL_DSP_SPEED, &speed);
01432
01433
01434 rc = entropy_noise_gather(dev_dsp_fd, samplesize, 2, swap, timeout_env ? atoi(timeout_env) : 1000, data, size);
01435 }
01436 #else
01437 # error Unknown type of /dev/dsp interface
01438 #endif
01439
01440 (void) close(dev_dsp_fd);
01441
01442 dev_dsp_end:
01443 #ifdef _REENTRANT
01444 # if HAVE_SYNCH_H
01445 mutex_unlock(&dev_dsp_lock);
01446 # elif HAVE_PTHREAD_H
01447
01448 (void) pthread_mutex_unlock(&dev_dsp_lock);
01449
01450 # endif
01451 #endif
01452
01453 return rc;
01454 }
01455 #endif
01456
01457 #if HAVE_DEV_RANDOM
01458 int entropy_dev_random(uint32* data, int size)
01459
01460
01461 {
01462 const char* timeout_env = getenv("BEECRYPT_ENTROPY_RANDOM_TIMEOUT");
01463
01464 int rc;
01465
01466 #ifdef _REENTRANT
01467 # if HAVE_SYNCH_H
01468 if (mutex_lock(&dev_random_lock))
01469 return -1;
01470 # elif HAVE_PTHREAD_H
01471
01472 if (pthread_mutex_lock(&dev_random_lock))
01473 return -1;
01474
01475 # endif
01476 #endif
01477
01478 #if HAVE_SYS_STAT_H
01479 if ((rc = statdevice(name_dev_random)) < 0)
01480 goto dev_random_end;
01481 #endif
01482
01483 if ((rc = dev_random_fd = opendevice(name_dev_random)) < 0)
01484 goto dev_random_end;
01485
01486
01487 rc = entropy_randombits(dev_random_fd, timeout_env ? atoi(timeout_env) : 1000, data, size);
01488
01489 (void) close(dev_random_fd);
01490
01491 dev_random_end:
01492 #ifdef _REENTRANT
01493 # if HAVE_SYNCH_H
01494 mutex_unlock(&dev_random_lock);
01495 # elif HAVE_PTHREAD_H
01496
01497 (void) pthread_mutex_unlock(&dev_random_lock);
01498
01499 # endif
01500 #endif
01501 return rc;
01502 }
01503 #endif
01504
01505 #if HAVE_DEV_URANDOM
01506 int entropy_dev_urandom(uint32* data, int size)
01507
01508
01509 {
01510 const char* timeout_env = getenv("BEECRYPT_ENTROPY_URANDOM_TIMEOUT");
01511
01512 register int rc;
01513
01514 #ifdef _REENTRANT
01515 # if HAVE_SYNCH_H
01516 if (mutex_lock(&dev_urandom_lock))
01517 return -1;
01518 # elif HAVE_PTHREAD_H
01519
01520 if (pthread_mutex_lock(&dev_urandom_lock))
01521 return -1;
01522
01523 # endif
01524 #endif
01525
01526 #if HAVE_SYS_STAT_H
01527 if ((rc = statdevice(name_dev_urandom)) < 0)
01528 goto dev_urandom_end;
01529 #endif
01530
01531 if ((rc = dev_urandom_fd = opendevice(name_dev_urandom)) < 0)
01532 goto dev_urandom_end;
01533
01534
01535 rc = entropy_randombits(dev_urandom_fd, timeout_env ? atoi(timeout_env) : 1000, data, size);
01536
01537 (void) close(dev_urandom_fd);
01538
01539 dev_urandom_end:
01540 #ifdef _REENTRANT
01541 # if HAVE_SYNCH_H
01542 mutex_unlock(&dev_urandom_lock);
01543 # elif HAVE_PTHREAD_H
01544
01545 (void) pthread_mutex_unlock(&dev_urandom_lock);
01546
01547 # endif
01548 #endif
01549 return rc;
01550 }
01551 #endif
01552
01553 #if HAVE_DEV_TTY
01554 int entropy_dev_tty(uint32* data, int size)
01555
01556
01557 {
01558 register int rc;
01559
01561 #if defined(_REENTRANT) && !defined(hpux)
01562 # if HAVE_SYNCH_H
01563 if (mutex_lock(&dev_tty_lock))
01564 return -1;
01565 # elif HAVE_PTHREAD_H
01566
01567 if (pthread_mutex_lock(&dev_tty_lock))
01568 return -1;
01569
01570 # endif
01571 #endif
01572
01573 #if HAVE_SYS_STAT_H
01574 if ((rc = statdevice(dev_tty_name)) < 0)
01575 goto dev_tty_end;
01576 #endif
01577
01578 if ((rc = dev_tty_fd = opendevice(dev_tty_name)) < 0)
01579 goto dev_tty_end;
01580
01581 rc = entropy_ttybits(dev_tty_fd, data, size);
01582
01583 (void) close(dev_tty_fd);
01584
01585 dev_tty_end:
01587 #if defined(_REENTRANT) && !defined(hpux)
01588 # if HAVE_SYNCH_H
01589 mutex_unlock(&dev_tty_lock);
01590 # elif HAVE_PTHREAD_H
01591
01592 (void) pthread_mutex_unlock(&dev_tty_lock);
01593
01594 # endif
01595 #endif
01596
01597 return rc;
01598 }
01599 #endif
01600
01601 #endif
01602