Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

beecrypt/entropy.c

Go to the documentation of this file.
00001 /*@-sizeoftype -type@*/
00008 /*
00009  * Copyright (c) 1998, 1999, 2000, 2001, 2002 Virtual Unlimited B.V.
00010  *
00011  * Author: Bob Deblier <bob@virtualunlimited.com>
00012  *
00013  * This library is free software; you can redistribute it and/or
00014  * modify it under the terms of the GNU Lesser General Public
00015  * License as published by the Free Software Foundation; either
00016  * version 2.1 of the License, or (at your option) any later version.
00017  *
00018  * This library is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021  * Lesser General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public
00024  * License along with this library; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 /*@-declundef -exportheader -incondefs -constuse -warnmissingglobs @*/
00063         extern int
00064 nanosleep (const struct timespec *__requested_time,
00065                       /*@out@*/ /*@null@*/ struct timespec *__remaining)
00066         /*@modifies errno @*/;
00067 
00068         extern void
00069 aio_init (const struct aioinit *__init)
00070         /*@*/;
00071         extern int
00072 aio_read (struct aiocb *__aiocbp)
00073         /*@modifies errno, fileSystem, systemState @*/;
00074         extern int
00075 aio_write (struct aiocb *__aiocbp)
00076         /*@modifies errno, fileSystem, systemState @*/;
00077         extern int
00078 lio_listio (int __mode,
00079                        struct aiocb *const __list[],
00080                        int __nent, struct sigevent *__sig)
00081         /*@modifies errno, fileSystem, systemState @*/;
00082         extern int
00083 aio_error (const struct aiocb *__aiocbp)
00084         /*@modifies errno @*/;
00085         extern __ssize_t
00086 aio_return (struct aiocb *__aiocbp)
00087         /*@modifies errno, systemState @*/;
00088         extern int
00089 aio_cancel (int __fildes, /*@null@*/ struct aiocb *__aiocbp)
00090         /*@modifies errno, systemState @*/;
00091         extern int
00092 aio_suspend (/*@out@*/ const struct aiocb *const __list[], int __nent,
00093                         /*@out@*/ const struct timespec *__timeout)
00094         /*@modifies errno, systemState @*/;
00095         extern int
00096 aio_fsync (int __operation, struct aiocb *__aiocbp)
00097         /*@modifies errno, fileSystem, systemState @*/;
00098 
00099 /*@constant int AIO_CANCELED@*/
00100 /*@constant int AIO_NOTCANCELED@*/
00101 /*@constant int AIO_ALLDONE@*/
00102 /*@constant int LIO_READ@*/
00103 /*@constant int LIO_WRITE@*/
00104 /*@constant int LIO_NOP@*/
00105 /*@constant int LIO_WAIT@*/
00106 /*@constant int LIO_NOWAIT@*/
00107 /*@constant int SIGEV_SIGNAL@*/
00108 /*@constant int SIGEV_NONE@*/
00109 /*@constant int SIGEV_THREAD@*/
00110 
00111 /*@=declundef =exportheader =incondefs =constuse =warnmissingglobs @*/
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 /*@-boundswrite@*/
00159 static int entropy_noise_filter(void* sampledata, int samplecount, int samplesize, int channels, int swap)
00160         /*@globals errno @*/
00161         /*@modifies sampledata, errno @*/
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                                 /*@innerbreak@*/ 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                                 /*@innerbreak@*/ 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                                 /*@innerbreak@*/ 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                                 /*@innerbreak@*/ break;
00311 
00312                         default:
00313                                 #if HAVE_ERRNO_H
00314                                 errno = EINVAL;
00315                                 #endif
00316                                 rc = -1;
00317                                 /*@innerbreak@*/ 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 /*@=boundswrite@*/
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 /*@-boundswrite@*/
00347 /*@-mustmod@*/ /* data is modified, annotations incorrect */
00348 static int entropy_noise_gather(int fd, int samplesize, int channels, int swap, int timeout, /*@out@*/ uint32 *data, int size)
00349         /*@globals errno, fileSystem @*/
00350         /*@modifies data, errno, fileSystem @*/
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         /* first set up a wave header */
00363         header.lpData = (LPSTR) sampledata;
00364         header.dwBufferLength = 1024 * samplesize * channels;
00365         header.dwFlags = 0;
00366 
00367         /* do error handling! */
00368         waveInStart(wavein);
00369         
00370         /* the first event is the due to the opening of the wave */
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         /*@-nullderef@*/
00383         *sampledata = 0;
00384         /*@=nullderef@*/
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         /*@-infloops -infloopsuncon -branchstate @*/
00402         while (randombits)
00403         {
00404                 #if WIN32
00405                 /* pass the buffer to the wavein and wait for the event */
00406                 waveInPrepareHeader(wavein, &header, sizeof(WAVEHDR));
00407                 waveInAddBuffer(wavein, &header, sizeof(WAVEHDR));
00408 
00409                 /* in case we have to wait more than the specified timeout, bail out */
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                 /*@-mustfree@*/ /* my_aiocb.aio_buf is OK */
00425                 my_aiocb.aio_buf = sampledata;
00426                 /*@=mustfree@*/
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                         /*@-kepttrans@*/
00437                         free(sampledata);
00438                         /*@=kepttrans@*/
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                                 /* certain linux glibc versions are buggy and don't aio_suspend properly */
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                                 /* and try again */
00460                                 rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
00461                         }
00462                         #endif
00463                 }
00464 
00465                 if (rc < 0)
00466                 {
00467                         /* cancel any remaining reads */
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                                         /*@innerbreak@*/ break;
00482                         }
00483                         /*@-kepttrans@*/
00484                         free(sampledata);
00485                         /*@=kepttrans@*/
00486                         return -1;
00487                 }
00488 
00489                 rc = aio_error(&my_aiocb);
00490 
00491                 if (rc)
00492                 {
00493                         /*@-kepttrans@*/
00494                         free(sampledata);
00495                         /*@=kepttrans@*/
00496                         return -1;
00497                 }
00498 
00499                 rc = aio_return(&my_aiocb);
00500 
00501                 if (rc < 0)
00502                 {
00503                         /*@-kepttrans@*/
00504                         free(sampledata);
00505                         /*@=kepttrans@*/
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                         /*@-kepttrans@*/
00515                         free(sampledata);
00516                         /*@=kepttrans@*/
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                         /*@switchbreak@*/ 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                         /*@switchbreak@*/ break;
00557 
00558                 default:
00559                         /*@-kepttrans@*/
00560                         free(sampledata);
00561                         /*@=kepttrans@*/
00562                         return -1;
00563                         /*@notreached@*/ /*@switchbreak@*/ break;
00564                 }
00565         }
00566         /*@=infloops =infloopsuncon =branchstate @*/
00567 
00568         #if WIN32
00569         waveInStop(wavein);
00570         waveInReset(wavein);
00571         #endif
00572 
00573         /*@-usereleased -kepttrans@*/
00574         free(sampledata);
00575         /*@=usereleased =kepttrans@*/
00576         return 0;
00577 }
00578 /*@=mustmod@*/
00579 /*@=boundswrite@*/
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         /* first go for the 16 bits samples -> more chance of noise bits */
00597         switch (waveformatex.nChannels = waveincaps.wChannels)
00598         {
00599         case 1:
00600                 /* mono */
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                 /* stereo */
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         /* we now have the wavein's capabilities hammered out; from here on we need to lock */
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                         /* get 8 bits from the sample */
00736                         temp <<= 8;
00737                         /* discard the 2 lowest bits */
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         /* consider using getenv("BEECRYPT_ENTROPY_WINCRYPT_PROVTYPE") to set provType */
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 /*@observer@*/ /*@unchecked@*/
00795 static const char* name_dev_audio = "/dev/audio";
00796 
00799 /*@unchecked@*/
00800 static int dev_audio_fd = -1;
00801 
00804 # ifdef _REENTRANT
00805 #  if HAVE_SYNCH_H
00806 /*@unchecked@*/
00807 static mutex_t dev_audio_lock = DEFAULTMUTEX;
00808 #  elif HAVE_PTHREAD_H
00809 /*@unchecked@*/
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 /*@observer@*/ /*@unchecked@*/
00821 static const char* name_dev_dsp = "/dev/dsp";
00822 
00825 /*@unchecked@*/
00826 static int dev_dsp_fd = -1;
00827 
00830 # ifdef _REENTRANT
00831 #  if HAVE_SYNCH_H
00832 /*@unchecked@*/
00833 static mutex_t dev_dsp_lock = DEFAULTMUTEX;
00834 #  elif HAVE_PTHREAD_H
00835 /*@unchecked@*/
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 /*@observer@*/ /*@unchecked@*/
00847 static const char* name_dev_random = "/dev/random";
00848 
00851 /*@unchecked@*/
00852 static int dev_random_fd = -1;
00853 
00856 # ifdef _REENTRANT
00857 #  if HAVE_SYNCH_H
00858 /*@unchecked@*/
00859 static mutex_t dev_random_lock = DEFAULTMUTEX;
00860 #  elif HAVE_PTHREAD_H
00861 /*@unchecked@*/
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 /*@observer@*/ /*@unchecked@*/
00873 static const char* name_dev_urandom = "/dev/urandom";
00874 
00877 /*@unchecked@*/
00878 static int dev_urandom_fd = -1;
00879 
00882 # ifdef _REENTRANT
00883 #  if HAVE_SYNCH_H
00884 /*@unchecked@*/
00885 static mutex_t dev_urandom_lock = DEFAULTMUTEX;
00886 #  elif HAVE_PTHREAD_H
00887 /*@unchecked@*/
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 /*@observer@*/ /*@unchecked@*/
00899 static const char *dev_tty_name = "/dev/tty";
00900 
00903 /*@unchecked@*/
00904 static int dev_tty_fd = -1;
00905 
00909 # if defined(_REENTRANT) && !defined(hpux)
00910 #  if HAVE_SYNCH_H
00911 /*@unchecked@*/
00912 static mutex_t dev_tty_lock = DEFAULTMUTEX;
00913 #  elif HAVE_PTHREAD_H
00914 /*@unchecked@*/
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         /*@globals fileSystem @*/
00929         /*@modifies fileSystem @*/
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         /*@globals fileSystem @*/
00955         /*@modifies fileSystem @*/
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 /*@-boundswrite@*/
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         /*@-branchstate@*/
01003         while (bytesize)
01004         {
01005                 #if ENABLE_AIO
01006                 /*@-mustfree@*/ /* my_aiocb.aio_buf is OK */
01007                 my_aiocb.aio_buf = bytedata;
01008                 /*@=mustfree@*/
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                                 /* certain linux glibc versions are buggy and don't aio_suspend properly */
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                                 /* and try again */
01037                                 rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
01038                         }
01039                         #endif
01040                 }
01041 
01042                 if (rc < 0)
01043                 {
01044                         /* cancel any remaining reads */
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                                         /*@innerbreak@*/ 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         /*@=branchstate@*/
01079         return 0;
01080 }
01081 /*@=boundswrite@*/
01082 #endif
01083 
01084 #if HAVE_DEV_TTY
01085 
01091 /*@-boundswrite@*/
01092 static int entropy_ttybits(int fd, uint32* data, int size)
01093         /*@globals fileSystem @*/
01094         /*@modifies fileSystem @*/
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         /*@-noeffect@*/ /* LCL: dunno @*/
01128         tio_set.c_cc[VMIN] = 1;                         /* read 1 tty character at a time */
01129         tio_set.c_cc[VTIME] = 0;                        /* don't timeout the read */
01130         /*@=noeffect@*/
01131         tio_set.c_iflag |= IGNBRK;                      /* ignore <ctrl>-c */
01132         tio_set.c_lflag &= ~(ECHO|ICANON);      /* don't echo characters */
01133 
01134         /* change the tty settings, and flush input characters */
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;                         /* read 1 tty character at a time */
01153         tio_set.c_cc[VTIME] = 0;                        /* don't timeout the read */
01154         tio_set.c_iflag |= IGNBRK;                      /* ignore <ctrl>-c */
01155         tio_set.c_lflag &= ~(ECHO|ICANON);      /* don't echo characters */
01156 
01157         /* change the tty settings, and flush input characters */
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                 /* get 16 bits from the sample */
01182                 temp <<= 16;
01183                 /* discard the 10 lowest bits i.e. 1024 nanoseconds */
01184                 temp |= (uint16)(hrtsample >> 10);
01185                 randombits -= 16;
01186                 #elif HAVE_GETTIMEOFDAY
01187                 /* discard the 4 lowest bits i.e. 4 microseconds */
01188                 (void) gettimeofday(&tvsample, 0);
01189                 /* get 8 bits from the sample */
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         /* give the user 1 second to stop typing */
01203         (void) sleep(1);
01204 
01205         #if HAVE_TERMIOS_H
01206         /* change the tty settings, and flush input characters */
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         /* restore the tty settings, and flush input characters */
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 /*@=boundswrite@*/
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 /* i.e. Solaris */
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                                 /* use a conservative setting this time */
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         /*@globals dev_dsp_fd @*/
01325         /*@modifies dev_dsp_fd @*/
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01337         if (pthread_mutex_lock(&dev_dsp_lock))
01338                 return -1;
01339         /*@=moduncon =noeffectuncon @*/
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 /* i.e. Linux audio */
01352         {
01353                 int mask, format, samplesize, stereo, speed, swap;
01354 
01355                 mask = 0;
01356                 /*@-shiftimplementation@*/
01357                 if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_GETFMTS, &mask)) < 0)
01358                 /*@=shiftimplementation@*/
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                         /* No linear audio format available */
01404                         rc = -1;
01405 
01406                         (void) close(dev_dsp_fd);
01407 
01408                         goto dev_dsp_end;
01409                 }
01410 
01411                 /*@-shiftimplementation@*/
01412                 if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_SETFMT, &format)) < 0)
01413                 /*@=shiftimplementation@*/
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                 /* the next two commands are not critical */
01424                 stereo = 1;
01425                 /*@-shiftimplementation@*/
01426                 (void) ioctl(dev_dsp_fd, SNDCTL_DSP_STEREO, &stereo);
01427                 /*@=shiftimplementation@*/
01428 
01429                 speed = 44100;
01430                 /*@-shiftimplementation@*/
01431                 (void) ioctl(dev_dsp_fd, SNDCTL_DSP_SPEED, &speed);
01432                 /*@=shiftimplementation@*/
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01448         (void) pthread_mutex_unlock(&dev_dsp_lock);
01449         /*@=moduncon =noeffectuncon @*/
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         /*@globals dev_random_fd @*/
01460         /*@modifies dev_random_fd @*/
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01472         if (pthread_mutex_lock(&dev_random_lock))
01473                 return -1;
01474         /*@=moduncon =noeffectuncon @*/
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         /* collect entropy, with timeout */
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01497         (void) pthread_mutex_unlock(&dev_random_lock);
01498         /*@=moduncon =noeffectuncon @*/
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         /*@globals dev_urandom_fd @*/
01508         /*@modifies dev_urandom_fd @*/
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01520         if (pthread_mutex_lock(&dev_urandom_lock))
01521                 return -1;
01522         /*@=moduncon =noeffectuncon @*/
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         /* collect entropy, with timeout */
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01545         (void) pthread_mutex_unlock(&dev_urandom_lock);
01546         /*@=moduncon =noeffectuncon @*/
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         /*@globals dev_tty_fd @*/
01556         /*@modifies dev_tty_fd @*/
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01567         if (pthread_mutex_lock(&dev_tty_lock))
01568                 return -1;
01569         /*@=moduncon =noeffectuncon @*/
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         /*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
01592         (void) pthread_mutex_unlock(&dev_tty_lock);
01593         /*@=moduncon =noeffectuncon @*/
01594         # endif
01595         #endif
01596 
01597         return rc;
01598 }
01599 #endif
01600 
01601 #endif
01602 /*@=sizeoftype =type@*/

Generated on Tue Sep 17 15:56:36 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002