Travis Cross d2edcad66e Merge Phil Zimmermann's libzrtp as a FreeSWITCH library
Thanks to Phil Zimmermann for the code and for the license exception
we needed to include it.

There remains some build system integration work to be done before
this code will build properly in the FreeSWITCH tree.
2012-03-31 23:42:27 +00:00

438 lines
13 KiB
C

/*
* Copyright (c) 1993-1995 Colin Plumb. All rights reserved.
* For licensing and other legal details, see the file legal.c.
*
* Get environmental noise.
*/
#include "first.h"
#include <time.h> /* For time measurement code */
#ifndef MSDOS
#ifdef __MSDOS
#define MSDOS 1
#endif
#endif
#ifndef MSDOS
#ifdef __MSDOS__
#define MSDOS 1
#endif
#endif
#ifndef UNIX
#ifdef unix
#define UNIX 1
#endif
#endif
#ifndef UNIX
#ifdef __unix
#define UNIX 1
#endif
#endif
#ifndef UNIX
#ifdef __unix__
#define UNIX 1
#endif
#endif
#ifdef MSDOS
#if __BORLANDC__
#define far __far /* Borland C++ 3.1's <dos.h> kacks in ANSI mode. Ugh! */
#endif
#include <dos.h> /* for enable() and disable() */
#include <conio.h> /* for inp() and outp() */
/*
* This code gets as much information as possible out of 8253/8254 timer 0,
* which ticks every .84 microseconds. There are three cases:
* 1) Original 8253. 15 bits available, as the low bit is unused.
* 2) 8254, in mode 3. The 16th bit is available from the status register.
* 3) 8254, in mode 2. All 16 bits of the counters are available.
* (This is not documented anywhere, but I've seen it!)
*
* This code repeatedly tries to latch the status (ignored by an 8253) and
* sees if it looks like xx1101x0. If not, it's definitely not an 8254.
* Repeat this a few times to make sure it is an 8254.
*/
static int
has8254(void)
{
int i, s1, s2;
for (i = 0; i < 5; i++) {
_disable();
outp(0x43, 0xe2); /* Latch status for timer 0 */
s1 = inp(0x40); /* If 8253, read timer low byte */
outp(0x43, 0xe2); /* Latch status for timer 0 */
s2 = inp(0x40); /* If 8253, read timer high byte */
_enable();
if ((s1 & 0x3d) != 0x34 || (s2 & 0x3d) != 0x34)
return 0; /* Ignoring status latch; 8253 */
}
return 1; /* Status reads as expected; 8254 */
}
/* TODO: It might be better to capture this data in a keyboard ISR */
static unsigned
read8254(void)
{
unsigned status, count;
_disable();
outp(0x43, 0xc2); /* Latch status and count for timer 0 */
status = inp(0x40);
count = inp(0x40);
count |= inp(0x40) << 8;
_enable();
/* The timer is usually in mode 3, but some motherboards use mode 2. */
if (status & 2)
count = count>>1 | (status & 0x80)<<8;
return count;
}
static unsigned
read8253(void)
{
unsigned count;
_disable();
outp(0x43, 0x00); /* Latch count for timer 0 */
count = (inp(0x40) & 0xff);
count |= (inp(0x40) & 0xff) << 8;
_enable();
return count >> 1;
}
#endif /* MSDOS */
#ifdef UNIX
/*
* This code uses five different timers, if available, in decreasing
* priority order:
* - gethrtime(), assumed unavailable unless USE_GETHRTIME=1
* - clock_gettime(), auto-detected unless overridden with USE_CLOCK_GETTIME
* - gettimeofday(), assumed available unless USE_GETTIMEOFDAY=0
* - getitimer(), auto-detected unless overridden with USE_GETITIMER
* - ftime(), assumed available unless USE_FTIME=0
*
* These are all accessed through the gettime(), timetype, and tickdiff()
* macros. The MINTICK constant is something to avoid the gettimeofday()
* glitch wherein it increments the return value even if no tick has occurred.
* When measuring the tick interval, if the difference between two successive
* times is not at least MINTICK ticks, it is ignored.
*/
#include <sys/types.h>
#include <sys/times.h> /* for times() */
#include <stdlib.h> /* For qsort() */
#if !USE_GETHRTIME
#ifndef USE_CLOCK_GETTIME /* Detect using CLOCK_REALTIME from <time.h> */
#ifdef CLOCK_REALTIMExxx /* Stupid libc... */
#define USE_CLOCK_GETTIME 1
#else
#define USE_CLOCK_GETTIME 0
#endif
#endif
#if !USE_CLOCK_GETTIME
#include <sys/time.h> /* For gettimeofday(), getitimer(), or ftime() */
#ifndef USE_GETTIMEOFDAY
#define USE_GETTIMEOFDAY 1 /* No way to tell, so assume it's there */
#endif
#if !USE_GETTIMEOFDAY
#ifndef USE_GETITIMER /* Detect using ITIMER_REAL from <sys/time.h> */
#define USE_GETITIMER defined(ITIMER_REAL)
#endif
#if !USE_GETITIMER
#ifndef USE_FTIME
#define USE_FTIME 1
#endif
#endif /* !USE_GETITIMER */
#endif /* !USE_GETTIMEOFDAY */
#endif /* !USE_CLOCK_GETTIME */
#endif /* !USE_GETHRTIME */
#if USE_GETHRTIME
#define CHOICE_GETHRTIME 1
#include <sys/time.h>
typedef hrtime_t timetype;
#define gettime(s) (*(s) = gethrtime())
#define tickdiff(s,t) ((s)-(t))
#define MINTICK 0
#elif USE_CLOCK_GETTIME
#define CHOICE_CLOCK_GETTIME 1
typedef struct timespec timetype;
#define gettime(s) (void)clock_gettime(CLOCK_REALTIME, s)
#define tickdiff(s,t) (((s).tv_sec-(t).tv_sec)*1000000000 + \
(s).tv_nsec - (t).tv_nsec)
#elif USE_GETTIMEOFDAY
#define CHOICE_GETTIMEOFDAY 1
typedef struct timeval timetype;
#define gettime(s) (void)gettimeofday(s, (struct timezone *)0)
#define tickdiff(s,t) (((s).tv_sec-(t).tv_sec)*1000000+(s).tv_usec-(t).tv_usec)
#define MINTICK 1
#elif USE_GETITIMER
#define CHOICE_GETITIMER 1
#include <signal.h> /* For signal(), SIGALRM, SIG_IGN */
typedef struct itimerval timetype;
#define gettime(s) (void)getitimer(ITIMER_REAL, s)
#define tickdiff(s,t) (((t).it_value.tv_sec-(s).it_value.tv_sec)*1000000 + \
(t).it_value.tv_usec - (s).it_value.tv_usec)
#define MINTICK 1
#elif USE_FTIME /* Use ftime() */
#define CHOICE_FTIME 1
#include <sys/timeb.h>
typedef struct timeb timetype;
#define gettime(s) (void)ftime(s)
#define tickdiff(s,t) (((s).time-(t).time)*1000 + (s).millitm - (t).millitm)
#define MINTICK 0
#else
#error No clock available - please define one.
#endif /* End of complex choice of clock conditional */
#if CHOICE_CLOCK_GETTIME
static unsigned
noiseTickSize(void)
{
struct timespec res;
clock_getres(CLOCK_REALTIME, &res);
return res.tv_nsec;
}
#else /* Normal clock resolution estimation */
#if NOISEDEBUG
#include <stdio.h>
#endif
#define N 15 /* Number of deltas to try (at least 5, preferably odd) */
/* Function needed for qsort() */
static int
noiseCompare(void const *p1, void const *p2)
{
return *(unsigned const *)p1 > *(unsigned const *)p2 ? 1 :
*(unsigned const *)p1 < *(unsigned const *)p2 ? -1 : 0;
}
/*
* Find the resolution of the high-resolution clock by sampling successive
* values until a tick boundary, at which point the delta is entered into
* a table. An average near the median of the table is taken and returned
* as the system tick size to eliminate outliers due to descheduling (high)
* or tv0 not being the "zero" time in a given tick (low).
*
* Some trickery is needed to defeat the habit systems have of always
* incrementing the microseconds field from gettimeofday() results so that
* no two calls return the same value. Thus, a "tick boundary" is assumed
* when successive calls return a difference of more than MINTICK ticks.
* (For gettimeofday(), this is set to 2 us.) This catches cases where at
* most one other task reads the clock between successive reads by this task.
* More tasks in between are rare enough that they'll get cut off by the
* median filter.
*
* When a tick boundary is found, the *first* time read during the previous
* tick (tv0) is subtracted from the new time to get microseconds per tick.
*
* Suns have a 1 us timer, and as of SunOS 4.1, they return that timer, but
* there is ~50 us of system-call overhead to get it, so this overestimates
* the tick size considerably. On SunOS 5.x/Solaris, the overhead has been
* cut to about 2.5 us, so the measured time alternates between 2 and 3 us.
* Some better algorithms will be required for future machines that really
* do achieve 1 us granularity.
*
* Current best idea: discard all this hair and use Ueli Maurer's entropy
* estimation scheme. Assign each input event (delta) a sequence number.
* 16 bits should be more than adequate. Make a table of the last time
* (by sequence number) each possibe input event occurred. For practical
* implementation, hash the event to a fixed-size code and consider two
* events identical if they have the same hash code. This will only ever
* underestimate entropy. Then use the number of bits in the difference
* between the current sequence number and the previous one as the entropy
* estimate.
*
* If it's desirable to use longer contexts, Maurer's original technique
* just groups events into non-overlapping pairs and uses the technique on
* the pairs. If you want to increment the entropy numbers on each keystroke
* for user-interface niceness, you can do the operation each time, but you
* have to halve the sequence number difference before starting, and then you
* have to halve the number of bits of entropy computed because you're adding
* them twice.
*
* You can put the even and odd events into separate tables to close Maurer's
* model exactly, or you can just dump them into the same table, which will
* be more conservative.
*/
static unsigned
noiseTickSize(void)
{
unsigned i = 0, j = 0, diff, d[N];
timetype tv0, tv1, tv2;
gettime(&tv0);
tv1 = tv0;
do {
gettime(&tv2);
diff = (unsigned)tickdiff(tv2, tv1);
if (diff > MINTICK) {
d[i++] = diff;
tv0 = tv2;
j = 0;
} else if (++j >= 4096) /* Always getting <= MINTICK units */
return MINTICK + !MINTICK;
tv1 = tv2;
} while (i < N);
/* Return average of middle 5 values (rounding up) */
qsort(d, N, sizeof(d[0]), noiseCompare);
diff = (d[N/2-2]+d[N/2-1]+d[N/2]+d[N/2+1]+d[N/2+2]+4)/5;
#if NOISEDEBUG
fprintf(stderr, "Tick size is %u\n", diff);
#endif
return diff;
}
#endif /* Clock resolution measurement condition */
#endif /* UNIX */
#include "usuals.h"
#include "randpool.h"
#include "noise.h"
/*
* Add as much environmentally-derived random noise as possible
* to the randPool. Typically, this involves reading the most
* accurate system clocks available.
*
* Returns the number of ticks that have passed since the last call,
* for entropy estimation purposes.
*/
word32
noise(void)
{
word32 delta;
#if defined(MSDOS)
static unsigned deltamask = 0;
static unsigned prevt;
unsigned t;
time_t tnow;
clock_t cnow;
if (deltamask == 0)
deltamask = has8254() ? 0xffff : 0x7fff;
t = (deltamask & 0x8000) ? read8254() : read8253();
randPoolAddBytes((byte const *)&t, sizeof(t));
delta = deltamask & (t - prevt);
prevt = t;
/* Add more-significant time components. */
cnow = clock();
randPoolAddBytes((byte *)&cnow, sizeof(cnow));
tnow = time((time_t *)0);
randPoolAddBytes((byte *)&tnow, sizeof(tnow));
/* END OF DOS */
#elif defined(VMS)
word32 t[2]; /* little-endian 64-bit timer */
word32 d1; /* MSW of difference */
static word32 prevt[2];
SYS$GETTIM(t); /* VMS hardware clock increments by 100000 per tick */
randPoolAddBytes((byte const *)t, sizeof(t));
/* Get difference in d1 and delta, and old time in prevt */
d1 = t[1] - prevt[1] + (t[0] < prevt[0]);
prevt[1] = t[1];
delta = t[0] - prevt[0];
prevt[0] = t[0];
/* Now, divide the 64-bit value by 100000 = 2^5 * 5^5 = 32 * 3125 */
/* Divide value, MSW in d1 and LSW in delta, by 32 */
delta >>= 5;
delta |= d1 << (32-5);
d1 >>= 5;
/*
* Divide by 3125. This fits into 16 bits, so the following
* code is possible. 2^32 = 3125 * 1374389 + 1671.
*
* This code has confused people reading it, so here's a detailed
* explanation. First, since we only want a 32-bit result,
* reduce the input mod 3125 * 2^32 before starting. This
* amounts to reducing the most significant word mod 3125 and
* leaving the least-significant word alone.
*
* Then, using / for mathematical (real, not integer) division, we
* want to compute floor(d1 * 2^32 + d0) / 3125), which I'll denote
* using the old [ ] syntax for floor, so it's
* [ (d1 * 2^32 + d0) / 3125 ]
* = [ (d1 * (3125 * 1374389 + 1671) + d0) / 3125 ]
* = [ d1 * 1374389 + (d1 * 1671 + d0) / 3125 ]
* = d1 * 137438 + [ (d1 * 1671 + d0) / 3125 ]
* = d1 * 137438 + [ d0 / 3125 ] + [ (d1 * 1671 + d0 % 3125) / 3125 ]
*
* The C / operator, applied to integers, performs [ a / b ], so
* this can be implemented in C, and since d1 < 3125 (by the first
* modulo operation), d1 * 1671 + d0 % 3125 < 3125 * 1672, which
* is 5225000, less than 2^32, so it all fits into 32 bits.
*/
d1 %= 3125; /* Ignore overflow past 32 bits */
delta = delta/3125 + d1*1374389 + (delta%3125 + d1*1671) / 3125;
/* END OF VMS */
#elif defined(UNIX)
timetype t;
static unsigned ticksize = 0;
static timetype prevt;
gettime(&t);
#if CHOICE_GETITIMER
/* If itimer isn't started, start it */
if (t.it_value.tv_sec == 0 && t.it_value.tv_usec == 0) {
/*
* start the timer - assume that PGP won't be running for
* more than 11 days, 13 hours, 46 minutes and 40 seconds.
*/
t.it_value.tv_sec = 1000000;
t.it_interval.tv_sec = 1000000;
t.it_interval.tv_usec = 0;
signal(SIGALRM, SIG_IGN); /* just in case.. */
setitimer(ITIMER_REAL, &t, NULL);
t.it_value.tv_sec = 0;
}
randPoolAddBytes((byte const *)&t.it_value, sizeof(t.it_value));
#else
randPoolAddBytes((byte const *)&t, sizeof(t));
#endif
if (!ticksize)
ticksize = noiseTickSize();
delta = (word32)(tickdiff(t, prevt) / ticksize);
prevt = t;
/* END OF UNIX */
#else
#error Unknown OS - define UNIX or MSDOS or add code for high-resolution timers
#endif
return delta;
}