1614 lines
34 KiB
C
1614 lines
34 KiB
C
/*@-sizeoftype -type@*/
|
||
/** \ingroup ES_m
|
||
* \file entropy.c
|
||
*
|
||
* Entropy gathering routine(s) for pseudo-random generator initialization.
|
||
*/
|
||
|
||
/*
|
||
* Copyright (c) 1998, 1999, 2000, 2001 Virtual Unlimited B.V.
|
||
*
|
||
* Author: Bob Deblier <bob@virtualunlimited.com>
|
||
*
|
||
* This library is free software; you can redistribute it and/or
|
||
* modify it under the terms of the GNU Lesser General Public
|
||
* License as published by the Free Software Foundation; either
|
||
* version 2.1 of the License, or (at your option) any later version.
|
||
*
|
||
* This library is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
* Lesser General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with this library; if not, write to the Free Software
|
||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
*
|
||
*/
|
||
|
||
#define BEECRYPT_DLL_EXPORT
|
||
|
||
#include "entropy.h"
|
||
#include "endianness.h"
|
||
|
||
#if WIN32
|
||
# include <mmsystem.h>
|
||
# include <wincrypt.h>
|
||
# include <winerror.h>
|
||
#else
|
||
# if HAVE_SYS_IOCTL_H
|
||
# include <sys/ioctl.h>
|
||
# endif
|
||
# if HAVE_SYS_STAT_H
|
||
# include <sys/types.h>
|
||
# include <sys/stat.h>
|
||
# endif
|
||
# if HAVE_SYS_TIME_H
|
||
# include <sys/time.h>
|
||
# endif
|
||
# if HAVE_SYS_AUDIOIO_H
|
||
# include <sys/audioio.h>
|
||
# endif
|
||
# if HAVE_SYS_SOUNDCARD_H
|
||
# include <sys/soundcard.h>
|
||
# endif
|
||
# if HAVE_TERMIOS_H
|
||
# include <termios.h>
|
||
# elif HAVE_TERMIO_H
|
||
# include <termio.h>
|
||
# endif
|
||
# if HAVE_SYNCH_H
|
||
# include <synch.h>
|
||
# elif HAVE_PTHREAD_H
|
||
# include <pthread.h>
|
||
# endif
|
||
# if HAVE_AIO_H
|
||
# include <aio.h>
|
||
# if defined(__LCLINT__)
|
||
/*@-declundef -exportheader -incondefs -constuse -warnmissingglobs @*/
|
||
extern int
|
||
nanosleep (const struct timespec *__requested_time,
|
||
/*@out@*/ /*@null@*/ struct timespec *__remaining)
|
||
/*@modifies errno @*/;
|
||
|
||
extern void
|
||
aio_init (const struct aioinit *__init)
|
||
/*@*/;
|
||
extern int
|
||
aio_read (struct aiocb *__aiocbp)
|
||
/*@modifies errno, fileSystem, systemState @*/;
|
||
extern int
|
||
aio_write (struct aiocb *__aiocbp)
|
||
/*@modifies errno, fileSystem, systemState @*/;
|
||
extern int
|
||
lio_listio (int __mode,
|
||
struct aiocb *const __list[],
|
||
int __nent, struct sigevent *__sig)
|
||
/*@modifies errno, fileSystem, systemState @*/;
|
||
extern int
|
||
aio_error (const struct aiocb *__aiocbp)
|
||
/*@modifies errno @*/;
|
||
extern __ssize_t
|
||
aio_return (struct aiocb *__aiocbp)
|
||
/*@modifies errno, systemState @*/;
|
||
extern int
|
||
aio_cancel (int __fildes, /*@null@*/ struct aiocb *__aiocbp)
|
||
/*@modifies errno, systemState @*/;
|
||
extern int
|
||
aio_suspend (/*@out@*/ const struct aiocb *const __list[], int __nent,
|
||
/*@out@*/ const struct timespec *__timeout)
|
||
/*@modifies errno, systemState @*/;
|
||
extern int
|
||
aio_fsync (int __operation, struct aiocb *__aiocbp)
|
||
/*@modifies errno, fileSystem, systemState @*/;
|
||
|
||
/*@constant int AIO_CANCELED@*/
|
||
/*@constant int AIO_NOTCANCELED@*/
|
||
/*@constant int AIO_ALLDONE@*/
|
||
/*@constant int LIO_READ@*/
|
||
/*@constant int LIO_WRITE@*/
|
||
/*@constant int LIO_NOP@*/
|
||
/*@constant int LIO_WAIT@*/
|
||
/*@constant int LIO_NOWAIT@*/
|
||
/*@constant int SIGEV_SIGNAL@*/
|
||
/*@constant int SIGEV_NONE@*/
|
||
/*@constant int SIGEV_THREAD@*/
|
||
|
||
/*@=declundef =exportheader =incondefs =constuse =warnmissingglobs @*/
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_STDLIB_H
|
||
# include <stdlib.h>
|
||
#endif
|
||
#if HAVE_FCNTL_H
|
||
# include <fcntl.h>
|
||
#endif
|
||
#if HAVE_UNISTD_H
|
||
# include <unistd.h>
|
||
#endif
|
||
#if HAVE_STRING_H
|
||
# include <string.h>
|
||
#endif
|
||
#if HAVE_ERRNO_H
|
||
# include <errno.h>
|
||
#endif
|
||
|
||
#include <stdio.h>
|
||
|
||
#if WIN32
|
||
static HINSTANCE entropy_instance = (HINSTANCE) 0;
|
||
|
||
static HANDLE entropy_wavein_lock;
|
||
static HANDLE entropy_wavein_event;
|
||
|
||
int entropy_provider_setup(HINSTANCE hInst)
|
||
{
|
||
if (!entropy_instance)
|
||
{
|
||
entropy_instance = hInst;
|
||
if (!(entropy_wavein_lock = CreateMutex(NULL, FALSE, NULL)))
|
||
return -1;
|
||
if (!(entropy_wavein_event = CreateEvent(NULL, FALSE, FALSE, NULL)))
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int entropy_provider_cleanup()
|
||
{
|
||
if (entropy_wavein_lock)
|
||
{
|
||
CloseHandle(entropy_wavein_lock);
|
||
entropy_wavein_lock = 0;
|
||
}
|
||
if (entropy_wavein_event)
|
||
{
|
||
CloseHandle(entropy_wavein_event);
|
||
entropy_wavein_event = 0;
|
||
}
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
#if WIN32 || HAVE_DEV_AUDIO || HAVE_DEV_DSP
|
||
/** \ingroup ES_audio_m ES_dsp_m
|
||
* Mask the low-order bit of a bunch of sound samples, analyze them and
|
||
* return an error in case they are all zeroes or ones.
|
||
*/
|
||
static int entropy_noise_filter(void* sampledata, int samplecount, int samplesize, int channels, int swap)
|
||
/*@globals errno @*/
|
||
/*@modifies sampledata, errno @*/
|
||
{
|
||
register int rc = 0, i;
|
||
|
||
switch (samplesize)
|
||
{
|
||
case 1:
|
||
{
|
||
uint8* samples = (uint8*) sampledata;
|
||
|
||
switch (channels)
|
||
{
|
||
case 1:
|
||
{
|
||
int zero_count = 0;
|
||
int ones_count = 0;
|
||
|
||
for (i = 0; i < samplecount; i++)
|
||
{
|
||
if ((samples[i] & 0x1) != 0)
|
||
ones_count++;
|
||
else
|
||
zero_count++;
|
||
}
|
||
|
||
if ((zero_count == 0) || (ones_count == 0))
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
errno = EIO;
|
||
#endif
|
||
rc = -1;
|
||
}
|
||
}
|
||
/*@innerbreak@*/ break;
|
||
|
||
case 2:
|
||
{
|
||
int zero_count_left = 0;
|
||
int ones_count_left = 0;
|
||
int zero_count_right = 0;
|
||
int ones_count_right = 0;
|
||
|
||
for (i = 0; i < samplecount; i++)
|
||
{
|
||
if (i & 1)
|
||
{
|
||
if ((samples[i] & 0x1) != 0)
|
||
ones_count_left++;
|
||
else
|
||
zero_count_left++;
|
||
}
|
||
else
|
||
{
|
||
if ((samples[i] & 0x1) != 0)
|
||
ones_count_right++;
|
||
else
|
||
zero_count_right++;
|
||
}
|
||
}
|
||
|
||
if ((zero_count_left == 0) || (ones_count_left == 0) ||
|
||
(zero_count_right == 0) || (ones_count_right == 0))
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
errno = EIO;
|
||
#endif
|
||
rc = -1;
|
||
}
|
||
}
|
||
/*@innerbreak@*/ break;
|
||
|
||
default:
|
||
#if HAVE_ERRNO_H
|
||
errno = EINVAL;
|
||
#endif
|
||
rc = -1;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 2:
|
||
{
|
||
uint16* samples = (uint16*) sampledata;
|
||
|
||
switch (channels)
|
||
{
|
||
case 1:
|
||
{
|
||
int zero_count = 0;
|
||
int ones_count = 0;
|
||
|
||
for (i = 0; i < samplecount; i++)
|
||
{
|
||
if (swap)
|
||
samples[i] = swapu16(samples[i]);
|
||
|
||
if ((samples[i] & 0x1) != 0)
|
||
ones_count++;
|
||
else
|
||
zero_count++;
|
||
}
|
||
|
||
if ((zero_count == 0) || (ones_count == 0))
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
errno = EIO;
|
||
#endif
|
||
rc = -1;
|
||
}
|
||
}
|
||
/*@innerbreak@*/ break;
|
||
|
||
case 2:
|
||
{
|
||
int zero_count_left = 0;
|
||
int ones_count_left = 0;
|
||
int zero_count_right = 0;
|
||
int ones_count_right = 0;
|
||
|
||
for (i = 0; i < samplecount; i++)
|
||
{
|
||
if (swap)
|
||
samples[i] = swapu16(samples[i]);
|
||
|
||
if (i & 1)
|
||
{
|
||
if ((samples[i] & 0x1) != 0)
|
||
ones_count_left++;
|
||
else
|
||
zero_count_left++;
|
||
}
|
||
else
|
||
{
|
||
if ((samples[i] & 0x1) != 0)
|
||
ones_count_right++;
|
||
else
|
||
zero_count_right++;
|
||
}
|
||
}
|
||
|
||
if ((zero_count_left == 0) || (ones_count_left == 0) ||
|
||
(zero_count_right == 0) || (ones_count_right == 0))
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
errno = EIO;
|
||
#endif
|
||
rc = -1;
|
||
}
|
||
}
|
||
/*@innerbreak@*/ break;
|
||
|
||
default:
|
||
#if HAVE_ERRNO_H
|
||
errno = EINVAL;
|
||
#endif
|
||
rc = -1;
|
||
/*@innerbreak@*/ break;
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
#if HAVE_ERRNO_H
|
||
errno = EINVAL;
|
||
#endif
|
||
rc = -1;
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* Bit deskewing technique: the classical Von Neumann method.
|
||
* - only use the lsb bit of every sample
|
||
* - there is a chance of bias in 0 or 1 bits, so to deskew this:
|
||
* - look at two successive sampled bits
|
||
* - if they are the same, discard them
|
||
* - if they are different, they're either 0-1 or 1-0; use the first bit of the pair as output
|
||
*/
|
||
|
||
#if WIN32
|
||
static int entropy_noise_gather(HWAVEIN wavein, int samplesize, int channels, int swap, int timeout, uint32 *data, int size)
|
||
#else
|
||
/*@-mustmod@*/ /* data is modified, annotations incorrect */
|
||
static int entropy_noise_gather(int fd, int samplesize, int channels, int swap, int timeout, /*@out@*/ uint32 *data, int size)
|
||
/*@globals errno, fileSystem @*/
|
||
/*@modifies data, errno, fileSystem @*/
|
||
#endif
|
||
{
|
||
uint32 randombits = ((unsigned)size) << 5;
|
||
uint32 temp = 0;
|
||
int rc, i;
|
||
|
||
byte* sampledata = (byte*) malloc(1024 * samplesize * channels);
|
||
|
||
#if WIN32
|
||
WAVEHDR header;
|
||
|
||
/* first set up a wave header */
|
||
header.lpData = (LPSTR) sampledata;
|
||
header.dwBufferLength = 1024 * samplesize * channels;
|
||
header.dwFlags = 0;
|
||
|
||
/* do error handling! */
|
||
waveInStart(wavein);
|
||
|
||
/* the first event is the due to the opening of the wave */
|
||
ResetEvent(entropy_wavein_event);
|
||
#else
|
||
# if ENABLE_AIO
|
||
struct aiocb my_aiocb;
|
||
const struct aiocb* my_aiocb_list = &my_aiocb;
|
||
# if HAVE_TIME_H
|
||
struct timespec my_aiocb_timeout;
|
||
# else
|
||
# error
|
||
# endif
|
||
|
||
/*@-nullderef@*/
|
||
*sampledata = 0;
|
||
/*@=nullderef@*/
|
||
memset(&my_aiocb, 0, sizeof(struct aiocb));
|
||
memset(&my_aiocb_timeout, 0, sizeof(struct timespec));
|
||
|
||
my_aiocb.aio_fildes = fd;
|
||
my_aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
|
||
# endif
|
||
#endif
|
||
|
||
if (sampledata == (byte*) 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
errno = ENOMEM;
|
||
#endif
|
||
return -1;
|
||
}
|
||
|
||
/*@-infloops -infloopsuncon -branchstate @*/
|
||
while (randombits)
|
||
{
|
||
#if WIN32
|
||
/* pass the buffer to the wavein and wait for the event */
|
||
waveInPrepareHeader(wavein, &header, sizeof(WAVEHDR));
|
||
waveInAddBuffer(wavein, &header, sizeof(WAVEHDR));
|
||
|
||
/* in case we have to wait more than the specified timeout, bail out */
|
||
if (WaitForSingleObject(entropy_wavein_event, timeout) == WAIT_OBJECT_0)
|
||
{
|
||
rc = header.dwBytesRecorded;
|
||
}
|
||
else
|
||
{
|
||
waveInStop(wavein);
|
||
waveInReset(wavein);
|
||
|
||
free(sampledata);
|
||
return -1;
|
||
}
|
||
#else
|
||
# if ENABLE_AIO
|
||
/*@-mustfree@*/ /* my_aiocb.aio_buf is OK */
|
||
my_aiocb.aio_buf = sampledata;
|
||
/*@=mustfree@*/
|
||
my_aiocb.aio_nbytes = 1024 * samplesize * channels;
|
||
|
||
rc = aio_read(&my_aiocb);
|
||
# else
|
||
rc = read(fd, sampledata, 1024 * samplesize * channels);
|
||
# endif
|
||
|
||
if (rc < 0)
|
||
{
|
||
/*@-kepttrans@*/
|
||
free(sampledata);
|
||
/*@=kepttrans@*/
|
||
return -1;
|
||
}
|
||
|
||
# if ENABLE_AIO
|
||
my_aiocb_timeout.tv_sec = (timeout / 1000);
|
||
my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
|
||
|
||
rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
|
||
|
||
if (rc < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
if (errno == EAGAIN)
|
||
{
|
||
/* certain linux glibc versions are buggy and don't aio_suspend properly */
|
||
(void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
|
||
|
||
my_aiocb_timeout.tv_sec = (timeout / 1000);
|
||
my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
|
||
|
||
/* and try again */
|
||
rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
if (rc < 0)
|
||
{
|
||
/* cancel any remaining reads */
|
||
while (rc != AIO_ALLDONE)
|
||
{
|
||
rc = aio_cancel(fd, (struct aiocb*) 0);
|
||
|
||
if (rc == AIO_NOTCANCELED)
|
||
{
|
||
my_aiocb_timeout.tv_sec = (timeout / 1000);
|
||
my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
|
||
|
||
(void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
|
||
}
|
||
|
||
if (rc < 0)
|
||
/*@innerbreak@*/ break;
|
||
}
|
||
/*@-kepttrans@*/
|
||
free(sampledata);
|
||
/*@=kepttrans@*/
|
||
return -1;
|
||
}
|
||
|
||
rc = aio_error(&my_aiocb);
|
||
|
||
if (rc)
|
||
{
|
||
/*@-kepttrans@*/
|
||
free(sampledata);
|
||
/*@=kepttrans@*/
|
||
return -1;
|
||
}
|
||
|
||
rc = aio_return(&my_aiocb);
|
||
|
||
if (rc < 0)
|
||
{
|
||
/*@-kepttrans@*/
|
||
free(sampledata);
|
||
/*@=kepttrans@*/
|
||
return -1;
|
||
}
|
||
# endif
|
||
#endif
|
||
|
||
if (entropy_noise_filter(sampledata, rc / samplesize, samplesize, channels, swap) < 0)
|
||
{
|
||
fprintf(stderr, "noise filter indicates too much bias in audio samples\n");
|
||
/*@-kepttrans@*/
|
||
free(sampledata);
|
||
/*@=kepttrans@*/
|
||
return -1;
|
||
}
|
||
|
||
switch (samplesize)
|
||
{
|
||
case 1:
|
||
{
|
||
uint8* samples = (uint8*) sampledata;
|
||
|
||
for (i = 0; randombits && (i < 1024); i += 2)
|
||
{
|
||
if ((samples[i] ^ samples[i+1]) != 0)
|
||
{
|
||
temp <<= 1;
|
||
temp |= samples[i];
|
||
randombits--;
|
||
if (!(randombits & 0x1f))
|
||
*(data++) = temp;
|
||
}
|
||
}
|
||
}
|
||
/*@switchbreak@*/ break;
|
||
|
||
case 2:
|
||
{
|
||
uint16* samples = (uint16*) sampledata;
|
||
|
||
for (i = 0; randombits && (i < 1024); i += 2)
|
||
{
|
||
if (samples[i] ^ samples[i+1])
|
||
{
|
||
temp <<= 1;
|
||
temp |= samples[i];
|
||
randombits--;
|
||
if (!(randombits & 0x1f))
|
||
*(data++) = temp;
|
||
}
|
||
}
|
||
}
|
||
/*@switchbreak@*/ break;
|
||
|
||
default:
|
||
/*@-kepttrans@*/
|
||
free(sampledata);
|
||
/*@=kepttrans@*/
|
||
return -1;
|
||
/*@notreached@*/ /*@switchbreak@*/ break;
|
||
}
|
||
}
|
||
/*@=infloops =infloopsuncon =branchstate @*/
|
||
|
||
#if WIN32
|
||
waveInStop(wavein);
|
||
waveInReset(wavein);
|
||
#endif
|
||
|
||
/*@-usereleased -kepttrans@*/
|
||
free(sampledata);
|
||
/*@=usereleased =kepttrans@*/
|
||
return 0;
|
||
}
|
||
/*@=mustmod@*/
|
||
#endif
|
||
|
||
#if WIN32
|
||
int entropy_wavein(uint32* data, int size)
|
||
{
|
||
const char *timeout_env = getenv("BEECRYPT_ENTROPY_WAVEIN_TIMEOUT");
|
||
|
||
WAVEINCAPS waveincaps;
|
||
WAVEFORMATEX waveformatex;
|
||
HWAVEIN wavein;
|
||
MMRESULT rc;
|
||
|
||
rc = waveInGetDevCaps(WAVE_MAPPER, &waveincaps, sizeof(WAVEINCAPS));
|
||
if (rc != MMSYSERR_NOERROR)
|
||
return -1;
|
||
|
||
/* first go for the 16 bits samples -> more chance of noise bits */
|
||
switch (waveformatex.nChannels = waveincaps.wChannels)
|
||
{
|
||
case 1:
|
||
/* mono */
|
||
if (waveincaps.dwFormats & WAVE_FORMAT_4M16)
|
||
{
|
||
waveformatex.nSamplesPerSec = 44100;
|
||
waveformatex.wBitsPerSample = 16;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_2M16)
|
||
{
|
||
waveformatex.nSamplesPerSec = 22050;
|
||
waveformatex.wBitsPerSample = 16;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_1M16)
|
||
{
|
||
waveformatex.nSamplesPerSec = 11025;
|
||
waveformatex.wBitsPerSample = 16;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_4M08)
|
||
{
|
||
waveformatex.nSamplesPerSec = 44100;
|
||
waveformatex.wBitsPerSample = 8;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_2M08)
|
||
{
|
||
waveformatex.nSamplesPerSec = 22050;
|
||
waveformatex.wBitsPerSample = 8;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_1M08)
|
||
{
|
||
waveformatex.nSamplesPerSec = 11025;
|
||
waveformatex.wBitsPerSample = 8;
|
||
}
|
||
else
|
||
return -1;
|
||
|
||
break;
|
||
case 2:
|
||
/* stereo */
|
||
if (waveincaps.dwFormats & WAVE_FORMAT_4S16)
|
||
{
|
||
waveformatex.nSamplesPerSec = 44100;
|
||
waveformatex.wBitsPerSample = 16;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_2S16)
|
||
{
|
||
waveformatex.nSamplesPerSec = 22050;
|
||
waveformatex.wBitsPerSample = 16;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_1S16)
|
||
{
|
||
waveformatex.nSamplesPerSec = 11025;
|
||
waveformatex.wBitsPerSample = 16;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_4S08)
|
||
{
|
||
waveformatex.nSamplesPerSec = 44100;
|
||
waveformatex.wBitsPerSample = 8;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_2S08)
|
||
{
|
||
waveformatex.nSamplesPerSec = 22050;
|
||
waveformatex.wBitsPerSample = 8;
|
||
}
|
||
else if (waveincaps.dwFormats & WAVE_FORMAT_1S08)
|
||
{
|
||
waveformatex.nSamplesPerSec = 11025;
|
||
waveformatex.wBitsPerSample = 8;
|
||
}
|
||
else
|
||
return -1;
|
||
|
||
break;
|
||
}
|
||
|
||
waveformatex.wFormatTag = WAVE_FORMAT_PCM;
|
||
waveformatex.nAvgBytesPerSec = (waveformatex.nSamplesPerSec * waveformatex.nChannels * waveformatex.wBitsPerSample) / 8;
|
||
waveformatex.nBlockAlign = (waveformatex.nChannels * waveformatex.wBitsPerSample) / 8;
|
||
waveformatex.cbSize = 0;
|
||
|
||
/* we now have the wavein's capabilities hammered out; from here on we need to lock */
|
||
|
||
if (WaitForSingleObject(entropy_wavein_lock, INFINITE) != WAIT_OBJECT_0)
|
||
return -1;
|
||
|
||
rc = waveInOpen(&wavein, WAVE_MAPPER, &waveformatex, (DWORD) entropy_wavein_event, (DWORD) 0, CALLBACK_EVENT);
|
||
if (rc != MMSYSERR_NOERROR)
|
||
{
|
||
fprintf(stderr, "waveInOpen failed!\n"); (void) fflush(stderr);
|
||
ReleaseMutex(entropy_wavein_lock);
|
||
return -1;
|
||
}
|
||
|
||
rc = entropy_noise_gather(wavein, waveformatex.wBitsPerSample >> 3, waveformatex.nChannels, 0, timeout_env ? atoi(timeout_env) : 2000, data, size);
|
||
|
||
waveInClose(wavein);
|
||
|
||
ReleaseMutex(entropy_wavein_lock);
|
||
|
||
return rc;
|
||
}
|
||
|
||
int entropy_console(uint32* data, int size)
|
||
{
|
||
register uint32 randombits = size << 5;
|
||
register uint32 temp = 0;
|
||
|
||
HANDLE hStdin;
|
||
DWORD inRet;
|
||
INPUT_RECORD inEvent;
|
||
LARGE_INTEGER hrtsample;
|
||
|
||
hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||
if (hStdin == INVALID_HANDLE_VALUE)
|
||
{
|
||
fprintf(stderr, "GetStdHandle error %d\n", GetLastError());
|
||
return -1;
|
||
}
|
||
|
||
printf("please press random keys on your keyboard\n"); (void) fflush(stdout);
|
||
|
||
while (randombits)
|
||
{
|
||
if (!ReadConsoleInput(hStdin, &inEvent, 1, &inRet))
|
||
{
|
||
fprintf(stderr, "ReadConsoleInput failed\n"); (void) fflush(stderr);
|
||
return -1;
|
||
}
|
||
if ((inRet == 1) && (inEvent.EventType == KEY_EVENT) && inEvent.Event.KeyEvent.bKeyDown)
|
||
{
|
||
printf("."); (void) fflush(stdout);
|
||
if (!QueryPerformanceCounter(&hrtsample))
|
||
{
|
||
fprintf(stderr, "QueryPerformanceCounter failed\n"); (void) fflush(stderr);
|
||
return -1;
|
||
}
|
||
|
||
/* get 8 bits from the sample */
|
||
temp <<= 8;
|
||
/* discard the 2 lowest bits */
|
||
temp |= (uint32)(hrtsample.LowPart >> 2);
|
||
randombits -= 8;
|
||
|
||
if (!(randombits & 0x1f))
|
||
*(data++) = temp;
|
||
}
|
||
}
|
||
|
||
printf("\nthanks\n");
|
||
|
||
Sleep(1000);
|
||
|
||
if (!FlushConsoleInputBuffer(hStdin))
|
||
{
|
||
fprintf(stderr, "FlushConsoleInputBuffer failed\n"); (void) fflush(stderr);
|
||
return -1;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int entropy_wincrypt(uint32* data, int size)
|
||
{
|
||
HCRYPTPROV hCrypt;
|
||
DWORD provType = PROV_RSA_FULL;
|
||
BOOL rc;
|
||
|
||
/* consider using getenv("BEECRYPT_ENTROPY_WINCRYPT_PROVTYPE") to set provType */
|
||
|
||
if (!CryptAcquireContext(&hCrypt, "BeeCrypt", NULL, provType, 0))
|
||
{
|
||
#if defined(NTE_BAD_KEYSET)
|
||
if (GetLastError() == NTE_BAD_KEYSET)
|
||
{
|
||
if (!CryptAcquireContext(&hCrypt, "BeeCrypt", NULL, provType, CRYPT_NEWKEYSET))
|
||
return -1;
|
||
}
|
||
else
|
||
return -1;
|
||
#else
|
||
return -1;
|
||
#endif
|
||
}
|
||
|
||
rc = CryptGenRandom(hCrypt, size << 2, (BYTE*) data);
|
||
|
||
CryptReleaseContext(hCrypt, 0);
|
||
|
||
return rc ? 0 : -1;
|
||
}
|
||
|
||
#else
|
||
|
||
#if HAVE_DEV_AUDIO
|
||
/** \ingroup ES_audio_m
|
||
*/
|
||
/*@observer@*/ /*@unchecked@*/
|
||
static const char* name_dev_audio = "/dev/audio";
|
||
|
||
/** \ingroup ES_audio_m
|
||
*/
|
||
/*@unchecked@*/
|
||
static int dev_audio_fd = -1;
|
||
|
||
/** \ingroup ES_audio_m
|
||
*/
|
||
# ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
/*@unchecked@*/
|
||
static mutex_t dev_audio_lock = DEFAULTMUTEX;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@unchecked@*/
|
||
static pthread_mutex_t dev_audio_lock = PTHREAD_MUTEX_INITIALIZER;
|
||
# else
|
||
# error Need locking mechanism
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_DEV_DSP
|
||
/** \ingroup ES_dsp_m
|
||
*/
|
||
/*@observer@*/ /*@unchecked@*/
|
||
static const char* name_dev_dsp = "/dev/dsp";
|
||
|
||
/** \ingroup ES_dsp_m
|
||
*/
|
||
/*@unchecked@*/
|
||
static int dev_dsp_fd = -1;
|
||
|
||
/** \ingroup ES_dsp_m
|
||
*/
|
||
# ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
/*@unchecked@*/
|
||
static mutex_t dev_dsp_lock = DEFAULTMUTEX;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@unchecked@*/
|
||
static pthread_mutex_t dev_dsp_lock = PTHREAD_MUTEX_INITIALIZER;
|
||
# else
|
||
# error Need locking mechanism
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_DEV_RANDOM
|
||
/** \ingroup ES_random_m
|
||
*/
|
||
/*@observer@*/ /*@unchecked@*/
|
||
static const char* name_dev_random = "/dev/random";
|
||
|
||
/** \ingroup ES_random_m
|
||
*/
|
||
/*@unchecked@*/
|
||
static int dev_random_fd = -1;
|
||
|
||
/** \ingroup ES_random_m
|
||
*/
|
||
# ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
/*@unchecked@*/
|
||
static mutex_t dev_random_lock = DEFAULTMUTEX;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@unchecked@*/
|
||
static pthread_mutex_t dev_random_lock = PTHREAD_MUTEX_INITIALIZER;
|
||
# else
|
||
# error Need locking mechanism
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_DEV_URANDOM
|
||
/** \ingroup ES_urandom_m
|
||
*/
|
||
/*@observer@*/ /*@unchecked@*/
|
||
static const char* name_dev_urandom = "/dev/urandom";
|
||
|
||
/** \ingroup ES_urandom_m
|
||
*/
|
||
/*@unchecked@*/
|
||
static int dev_urandom_fd = -1;
|
||
|
||
/** \ingroup ES_urandom_m
|
||
*/
|
||
# ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
/*@unchecked@*/
|
||
static mutex_t dev_urandom_lock = DEFAULTMUTEX;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@unchecked@*/
|
||
static pthread_mutex_t dev_urandom_lock = PTHREAD_MUTEX_INITIALIZER;
|
||
# else
|
||
# error Need locking mechanism
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_DEV_TTY
|
||
/** \ingroup ES_tty_m
|
||
*/
|
||
/*@observer@*/ /*@unchecked@*/
|
||
static const char *dev_tty_name = "/dev/tty";
|
||
|
||
/** \ingroup ES_tty_m
|
||
*/
|
||
/*@unchecked@*/
|
||
static int dev_tty_fd = -1;
|
||
|
||
/** \ingroup ES_tty_m
|
||
*/
|
||
# ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
/*@unchecked@*/
|
||
static mutex_t dev_tty_lock = DEFAULTMUTEX;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@unchecked@*/
|
||
static pthread_mutex_t dev_tty_lock = PTHREAD_MUTEX_INITIALIZER;
|
||
# else
|
||
# error Need locking mechanism
|
||
# endif
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_SYS_STAT_H
|
||
/**
|
||
* @param device
|
||
* @return
|
||
*/
|
||
static int statdevice(const char *device)
|
||
/*@globals fileSystem @*/
|
||
/*@modifies fileSystem @*/
|
||
{
|
||
struct stat s;
|
||
|
||
if (stat(device, &s) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H && HAVE_STRING_H
|
||
fprintf(stderr, "cannot stat %s: %s\n", device, strerror(errno));
|
||
#endif
|
||
return -1;
|
||
}
|
||
if (!S_ISCHR(s.st_mode))
|
||
{
|
||
fprintf(stderr, "%s is not a device\n", device);
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
/**
|
||
* @param device
|
||
* @return
|
||
*/
|
||
static int opendevice(const char *device)
|
||
/*@globals fileSystem @*/
|
||
/*@modifies fileSystem @*/
|
||
{
|
||
register int fd;
|
||
|
||
if ((fd = open(device, O_RDONLY)) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H && HAVE_STRING_H
|
||
fprintf(stderr, "open of %s failed: %s\n", device, strerror(errno));
|
||
#endif
|
||
return fd;
|
||
}
|
||
|
||
return fd;
|
||
}
|
||
|
||
#if HAVE_DEV_RANDOM || HAVE_DEV_URANDOM
|
||
/** \ingroup ES_random_m ES_urandom_m
|
||
* @param fd
|
||
* @param timeout in milliseconds
|
||
* @retval data
|
||
* @param size
|
||
* @return
|
||
*/
|
||
static int entropy_randombits(int fd, int timeout, uint32* data, int size)
|
||
/*@*/
|
||
{
|
||
register byte* bytedata = (byte*) data;
|
||
register int bytesize = (((unsigned)size) << 2);
|
||
register int rc;
|
||
|
||
#if ENABLE_AIO
|
||
struct aiocb my_aiocb;
|
||
const struct aiocb* my_aiocb_list = &my_aiocb;
|
||
# if HAVE_TIME_H
|
||
struct timespec my_aiocb_timeout;
|
||
# else
|
||
# error
|
||
# endif
|
||
|
||
memset(&my_aiocb, 0, sizeof(struct aiocb));
|
||
memset(&my_aiocb_timeout, 0, sizeof(struct timespec));
|
||
|
||
my_aiocb.aio_fildes = fd;
|
||
my_aiocb.aio_sigevent.sigev_notify = SIGEV_NONE;
|
||
#endif
|
||
|
||
/*@-branchstate@*/
|
||
while (bytesize)
|
||
{
|
||
#if ENABLE_AIO
|
||
/*@-mustfree@*/ /* my_aiocb.aio_buf is OK */
|
||
my_aiocb.aio_buf = bytedata;
|
||
/*@=mustfree@*/
|
||
my_aiocb.aio_nbytes = bytesize;
|
||
|
||
rc = aio_read(&my_aiocb);
|
||
#else
|
||
rc = read(fd, bytedata, bytesize);
|
||
#endif
|
||
|
||
if (rc < 0)
|
||
return -1;
|
||
|
||
#if ENABLE_AIO
|
||
my_aiocb_timeout.tv_sec = (timeout / 1000);
|
||
my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
|
||
|
||
rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
|
||
|
||
if (rc < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
if (errno == EAGAIN)
|
||
{
|
||
/* certain linux glibc versions are buggy and don't aio_suspend properly */
|
||
(void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
|
||
|
||
my_aiocb_timeout.tv_sec = 0;
|
||
my_aiocb_timeout.tv_nsec = 0;
|
||
|
||
/* and try again */
|
||
rc = aio_suspend(&my_aiocb_list, 1, &my_aiocb_timeout);
|
||
}
|
||
#endif
|
||
}
|
||
|
||
if (rc < 0)
|
||
{
|
||
/* cancel any remaining reads */
|
||
while (rc != AIO_ALLDONE)
|
||
{
|
||
rc = aio_cancel(fd, (struct aiocb*) 0);
|
||
|
||
if (rc == AIO_NOTCANCELED)
|
||
{
|
||
my_aiocb_timeout.tv_sec = (timeout / 1000);
|
||
my_aiocb_timeout.tv_nsec = (timeout % 1000) * 1000000;
|
||
|
||
(void) nanosleep(&my_aiocb_timeout, (struct timespec*) 0);
|
||
}
|
||
|
||
if (rc < 0)
|
||
/*@innerbreak@*/ break;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
rc = aio_error(&my_aiocb);
|
||
|
||
if (rc < 0)
|
||
return -1;
|
||
|
||
rc = aio_return(&my_aiocb);
|
||
|
||
if (rc < 0)
|
||
return -1;
|
||
#endif
|
||
|
||
bytedata += rc;
|
||
bytesize -= rc;
|
||
}
|
||
/*@=branchstate@*/
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
#if HAVE_DEV_TTY
|
||
/** \ingroup ES_tty_m
|
||
* @param fd
|
||
* @retval data
|
||
* @param size
|
||
* @return
|
||
*/
|
||
static int entropy_ttybits(int fd, uint32* data, int size)
|
||
/*@globals fileSystem @*/
|
||
/*@modifies fileSystem @*/
|
||
{
|
||
uint32 randombits = ((unsigned)size) << 5;
|
||
uint32 temp = 0;
|
||
byte dummy;
|
||
|
||
#if HAVE_TERMIOS_H
|
||
struct termios tio_save, tio_set;
|
||
#elif HAVE_TERMIO_H
|
||
struct termio tio_save, tio_set;
|
||
#else
|
||
# need alternative
|
||
#endif
|
||
#if HAVE_GETHRTIME
|
||
hrtime_t hrtsample;
|
||
#elif HAVE_GETTIMEOFDAY
|
||
struct timeval tvsample;
|
||
#else
|
||
# error Need alternative high-precision timer
|
||
#endif
|
||
|
||
printf("please press random keys on your keyboard\n");
|
||
|
||
#if HAVE_TERMIOS_H
|
||
if (tcgetattr(fd, &tio_save) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("tcgetattr failed");
|
||
#endif
|
||
return -1;
|
||
}
|
||
|
||
tio_set = tio_save;
|
||
/*@-noeffect@*/ /* LCL: dunno @*/
|
||
tio_set.c_cc[VMIN] = 1; /* read 1 tty character at a time */
|
||
tio_set.c_cc[VTIME] = 0; /* don't timeout the read */
|
||
/*@=noeffect@*/
|
||
tio_set.c_iflag |= IGNBRK; /* ignore <ctrl>-c */
|
||
tio_set.c_lflag &= ~(ECHO|ICANON); /* don't echo characters */
|
||
|
||
/* change the tty settings, and flush input characters */
|
||
if (tcsetattr(fd, TCSAFLUSH, &tio_set) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("tcsetattr failed");
|
||
#endif
|
||
return -1;
|
||
}
|
||
#elif HAVE_TERMIO_H
|
||
if (ioctl(fd, TCGETA, &tio_save) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("ioctl TCGETA failed");
|
||
#endif
|
||
return -1;
|
||
}
|
||
|
||
tio_set = tio_save;
|
||
tio_set.c_cc[VMIN] = 1; /* read 1 tty character at a time */
|
||
tio_set.c_cc[VTIME] = 0; /* don't timeout the read */
|
||
tio_set.c_iflag |= IGNBRK; /* ignore <ctrl>-c */
|
||
tio_set.c_lflag &= ~(ECHO|ICANON); /* don't echo characters */
|
||
|
||
/* change the tty settings, and flush input characters */
|
||
if (ioctl(fd, TCSETAF, &tio_set) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("ioctl TCSETAF failed");
|
||
#endif
|
||
return -1;
|
||
}
|
||
#else
|
||
# error Need alternative tty control library
|
||
#endif
|
||
|
||
while (randombits)
|
||
{
|
||
if (read(fd, &dummy, 1) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("tty read failed");
|
||
#endif
|
||
return -1;
|
||
}
|
||
printf("."); (void) fflush(stdout);
|
||
#if HAVE_GETHRTIME
|
||
hrtsample = gethrtime();
|
||
/* get 16 bits from the sample */
|
||
temp <<= 16;
|
||
/* discard the 10 lowest bits i.e. 1024 nanoseconds */
|
||
temp |= (uint16)(hrtsample >> 10);
|
||
randombits -= 16;
|
||
#elif HAVE_GETTIMEOFDAY
|
||
/* discard the 4 lowest bits i.e. 4 microseconds */
|
||
(void) gettimeofday(&tvsample, 0);
|
||
/* get 8 bits from the sample */
|
||
temp <<= 8;
|
||
temp |= (uint8)(((unsigned)tvsample.tv_usec) >> 2);
|
||
randombits -= 8;
|
||
#else
|
||
# error Need alternative high-precision timer sample
|
||
#endif
|
||
if (!(randombits & 0x1f))
|
||
*(data++) = temp;
|
||
}
|
||
|
||
printf("\nthanks\n");
|
||
|
||
/* give the user 1 second to stop typing */
|
||
(void) sleep(1);
|
||
|
||
#if HAVE_TERMIOS_H
|
||
/* change the tty settings, and flush input characters */
|
||
if (tcsetattr(fd, TCSAFLUSH, &tio_save) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("tcsetattr failed");
|
||
#endif
|
||
return -1;
|
||
}
|
||
#elif HAVE_TERMIO_H
|
||
/* restore the tty settings, and flush input characters */
|
||
if (ioctl(fd, TCSETAF, &tio_save) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("ioctl TCSETAF failed");
|
||
#endif
|
||
return -1;
|
||
}
|
||
#else
|
||
# error Need alternative tty control library
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
#endif
|
||
|
||
#if HAVE_DEV_AUDIO
|
||
int entropy_dev_audio(uint32 *data, int size)
|
||
{
|
||
const char* timeout_env = getenv("BEECRYPT_ENTROPY_AUDIO_TIMEOUT");
|
||
|
||
register int rc;
|
||
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
if (mutex_lock(&dev_audio_lock))
|
||
return -1;
|
||
# elif HAVE_PTHREAD_H
|
||
if (pthread_mutex_lock(&dev_audio_lock))
|
||
return -1;
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_SYS_STAT_H
|
||
if (statdevice(name_dev_audio) < 0)
|
||
goto dev_audio_end;
|
||
#endif
|
||
|
||
if ((rc = dev_audio_fd = opendevice(name_dev_audio)) < 0)
|
||
goto dev_audio_end;
|
||
|
||
#if HAVE_SYS_AUDIOIO_H /* i.e. Solaris */
|
||
{
|
||
struct audio_info info;
|
||
|
||
AUDIO_INITINFO(&info);
|
||
|
||
info.record.sample_rate = 48000;
|
||
info.record.channels = 2;
|
||
info.record.precision = 16;
|
||
info.record.encoding = AUDIO_ENCODING_LINEAR;
|
||
info.record.gain = AUDIO_MAX_GAIN;
|
||
info.record.pause = 0;
|
||
info.record.buffer_size = 4096;
|
||
info.record.samples = 0;
|
||
|
||
if ((rc = ioctl(dev_audio_fd, AUDIO_SETINFO, &info)) < 0)
|
||
{
|
||
if (errno == EINVAL)
|
||
{
|
||
/* use a conservative setting this time */
|
||
info.record.sample_rate = 22050;
|
||
info.record.channels = 1;
|
||
info.record.precision = 8;
|
||
|
||
if ((rc = ioctl(dev_audio_fd, AUDIO_SETINFO, &info)) < 0)
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("ioctl AUDIO_SETINFO failed");
|
||
#endif
|
||
(void) close(dev_audio_fd);
|
||
|
||
goto dev_audio_end;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("ioctl AUDIO_SETINFO failed");
|
||
#endif
|
||
(void) close(dev_audio_fd);
|
||
|
||
goto dev_audio_end;
|
||
}
|
||
}
|
||
|
||
rc = entropy_noise_gather(dev_audio_fd, info.record.precision >> 3, info.record.channels, 0, timeout_env ? atoi(timeout_env) : 1000, data, size);
|
||
}
|
||
#else
|
||
# error Unknown type of /dev/audio interface
|
||
#endif
|
||
|
||
(void) close(dev_audio_fd);
|
||
|
||
dev_audio_end:
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
mutex_unlock(&dev_audio_lock);
|
||
# elif HAVE_PTHREAD_H
|
||
pthread_mutex_unlock(&dev_audio_lock);
|
||
# endif
|
||
#endif
|
||
return rc;
|
||
}
|
||
#endif
|
||
|
||
#if HAVE_DEV_DSP
|
||
int entropy_dev_dsp(uint32 *data, int size)
|
||
/*@globals dev_dsp_fd @*/
|
||
/*@modifies dev_dsp_fd @*/
|
||
{
|
||
const char* timeout_env = getenv("BEECRYPT_ENTROPY_DSP_TIMEOUT");
|
||
|
||
register int rc;
|
||
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
if (mutex_lock(&dev_dsp_lock))
|
||
return -1;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
if (pthread_mutex_lock(&dev_dsp_lock))
|
||
return -1;
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_SYS_STAT_H
|
||
if ((rc = statdevice(name_dev_dsp)) < 0)
|
||
goto dev_dsp_end;
|
||
#endif
|
||
|
||
if ((rc = dev_dsp_fd = opendevice(name_dev_dsp)) < 0)
|
||
goto dev_dsp_end;
|
||
|
||
#if HAVE_SYS_SOUNDCARD_H /* i.e. Linux audio */
|
||
{
|
||
int mask, format, samplesize, stereo, speed, swap;
|
||
|
||
mask = 0;
|
||
/*@-shiftsigned@*/
|
||
if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_GETFMTS, &mask)) < 0)
|
||
/*@=shiftsigned@*/
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("ioctl SNDCTL_DSP_GETFMTS failed");
|
||
#endif
|
||
(void) close (dev_dsp_fd);
|
||
|
||
goto dev_dsp_end;
|
||
}
|
||
|
||
#if WORDS_BIGENDIAN
|
||
if (mask & AFMT_S16_BE)
|
||
{
|
||
format = AFMT_S16_BE;
|
||
samplesize = 2;
|
||
swap = 0;
|
||
}
|
||
else if (mask & AFMT_S16_LE)
|
||
{
|
||
format = AFMT_S16_LE;
|
||
samplesize = 2;
|
||
swap = 1;
|
||
}
|
||
#else
|
||
if (mask & AFMT_S16_LE)
|
||
{
|
||
format = AFMT_S16_LE;
|
||
samplesize = 2;
|
||
swap = 0;
|
||
}
|
||
else if (mask & AFMT_S16_BE)
|
||
{
|
||
format = AFMT_S16_BE;
|
||
samplesize = 2;
|
||
swap = 1;
|
||
}
|
||
#endif
|
||
else if (mask & AFMT_S8)
|
||
{
|
||
format = AFMT_S8;
|
||
samplesize = 1;
|
||
swap = 0;
|
||
}
|
||
else
|
||
{
|
||
/* No linear audio format available */
|
||
rc = -1;
|
||
|
||
(void) close(dev_dsp_fd);
|
||
|
||
goto dev_dsp_end;
|
||
}
|
||
|
||
/*@-shiftsigned@*/
|
||
if ((rc = ioctl(dev_dsp_fd, SNDCTL_DSP_SETFMT, &format)) < 0)
|
||
/*@=shiftsigned@*/
|
||
{
|
||
#if HAVE_ERRNO_H
|
||
perror("ioctl SNDCTL_DSP_SETFMT failed");
|
||
#endif
|
||
(void) close(dev_dsp_fd);
|
||
|
||
goto dev_dsp_end;
|
||
}
|
||
|
||
/* the next two commands are not critical */
|
||
stereo = 1;
|
||
/*@-shiftsigned@*/
|
||
(void) ioctl(dev_dsp_fd, SNDCTL_DSP_STEREO, &stereo);
|
||
/*@=shiftsigned@*/
|
||
|
||
speed = 44100;
|
||
/*@-shiftsigned@*/
|
||
(void) ioctl(dev_dsp_fd, SNDCTL_DSP_SPEED, &speed);
|
||
/*@=shiftsigned@*/
|
||
|
||
rc = entropy_noise_gather(dev_dsp_fd, samplesize, 2, swap, timeout_env ? atoi(timeout_env) : 1000, data, size);
|
||
}
|
||
#else
|
||
# error Unknown type of /dev/dsp interface
|
||
#endif
|
||
|
||
(void) close(dev_dsp_fd);
|
||
|
||
dev_dsp_end:
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
mutex_unlock(&dev_dsp_lock);
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
(void) pthread_mutex_unlock(&dev_dsp_lock);
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
|
||
return rc;
|
||
}
|
||
#endif
|
||
|
||
#if HAVE_DEV_RANDOM
|
||
int entropy_dev_random(uint32* data, int size)
|
||
/*@globals dev_random_fd @*/
|
||
/*@modifies dev_random_fd @*/
|
||
{
|
||
const char* timeout_env = getenv("BEECRYPT_ENTROPY_RANDOM_TIMEOUT");
|
||
|
||
int rc;
|
||
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
if (mutex_lock(&dev_random_lock))
|
||
return -1;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
if (pthread_mutex_lock(&dev_random_lock))
|
||
return -1;
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_SYS_STAT_H
|
||
if ((rc = statdevice(name_dev_random)) < 0)
|
||
goto dev_random_end;
|
||
#endif
|
||
|
||
if ((rc = dev_random_fd = opendevice(name_dev_random)) < 0)
|
||
goto dev_random_end;
|
||
|
||
/* collect entropy, with timeout */
|
||
rc = entropy_randombits(dev_random_fd, timeout_env ? atoi(timeout_env) : 1000, data, size);
|
||
|
||
(void) close(dev_random_fd);
|
||
|
||
dev_random_end:
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
mutex_unlock(&dev_random_lock);
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
(void) pthread_mutex_unlock(&dev_random_lock);
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
return rc;
|
||
}
|
||
#endif
|
||
|
||
#if HAVE_DEV_URANDOM
|
||
int entropy_dev_urandom(uint32* data, int size)
|
||
/*@globals dev_urandom_fd @*/
|
||
/*@modifies dev_urandom_fd @*/
|
||
{
|
||
const char* timeout_env = getenv("BEECRYPT_ENTROPY_URANDOM_TIMEOUT");
|
||
|
||
register int rc;
|
||
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
if (mutex_lock(&dev_urandom_lock))
|
||
return -1;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
if (pthread_mutex_lock(&dev_urandom_lock))
|
||
return -1;
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_SYS_STAT_H
|
||
if ((rc = statdevice(name_dev_urandom)) < 0)
|
||
goto dev_urandom_end;
|
||
#endif
|
||
|
||
if ((rc = dev_urandom_fd = opendevice(name_dev_urandom)) < 0)
|
||
goto dev_urandom_end;
|
||
|
||
/* collect entropy, with timeout */
|
||
rc = entropy_randombits(dev_urandom_fd, timeout_env ? atoi(timeout_env) : 1000, data, size);
|
||
|
||
(void) close(dev_urandom_fd);
|
||
|
||
dev_urandom_end:
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
mutex_unlock(&dev_urandom_lock);
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
(void) pthread_mutex_unlock(&dev_urandom_lock);
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
return rc;
|
||
}
|
||
#endif
|
||
|
||
#if HAVE_DEV_TTY
|
||
int entropy_dev_tty(uint32* data, int size)
|
||
/*@globals dev_tty_fd @*/
|
||
/*@modifies dev_tty_fd @*/
|
||
{
|
||
register int rc;
|
||
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
if (mutex_lock(&dev_tty_lock))
|
||
return -1;
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
if (pthread_mutex_lock(&dev_tty_lock))
|
||
return -1;
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
|
||
#if HAVE_SYS_STAT_H
|
||
if ((rc = statdevice(dev_tty_name)) < 0)
|
||
goto dev_tty_end;
|
||
#endif
|
||
|
||
if ((rc = dev_tty_fd = opendevice(dev_tty_name)) < 0)
|
||
goto dev_tty_end;
|
||
|
||
rc = entropy_ttybits(dev_tty_fd, data, size);
|
||
|
||
(void) close(dev_tty_fd);
|
||
|
||
dev_tty_end:
|
||
#ifdef _REENTRANT
|
||
# if HAVE_SYNCH_H
|
||
mutex_unlock(&dev_tty_lock);
|
||
# elif HAVE_PTHREAD_H
|
||
/*@-moduncon -noeffectuncon @*/ /* FIX: annotate */
|
||
(void) pthread_mutex_unlock(&dev_tty_lock);
|
||
/*@=moduncon =noeffectuncon @*/
|
||
# endif
|
||
#endif
|
||
|
||
return rc;
|
||
}
|
||
#endif
|
||
|
||
#endif
|
||
/*@=sizeoftype =type@*/
|