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@*/