--- pgp/src/noise.c 2018/04/24 16:41:02 1.1.1.1 +++ pgp/src/noise.c 2018/04/24 16:45:29 1.1.1.4 @@ -1,7 +1,7 @@ /* * Get environmental noise. * - * (c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved. + * (c) Copyright 1990-1996 by Philip Zimmermann. All rights reserved. * The author assumes no liability for damages resulting from the use * of this software, even if the damage results from defects in this * software. No warranty is expressed or implied. @@ -24,16 +24,34 @@ #ifdef UNIX #include -#include /* For gettimeofday() */ -#include /* for times() */ -#include /* For qsort() */ - +#include /* For gettimeofday() */ +#include /* for times() */ +#include /* For qsort() */ #endif /* UNIX */ #include #include "usuals.h" #include "randpool.h" #include "noise.h" +#ifdef MACTC5 +#include "TimeManager.h" +#endif + +#ifdef AMIGA /* RKNOP 940613 */ +#include +#include +#include +extern __far struct Custom custom; /* Custom chips */ +#include +#include + +/* Stuff used in noise.c, defined in random.c -- RKNOP 940613*/ +extern struct timerequest *TimerIO; +extern union { struct timeval t; + struct EClockVal e; + } time0,time1; +extern unsigned short use_eclock; +#endif /* AMIGA */ /* Some machines just don't have clock_t */ #if defined(sun) && defined(i386) @@ -44,7 +62,12 @@ typedef long clock_t; /* Use IBM PC hardware timer (1.19 MHz) */ -#include /* for inp() and outp() */ +#ifdef __GO32__ +#include +#else +#include /* for inp() and outp() */ +#include /* same for Turbo C EWS */ +#endif /* timer0 on 8253-5 on IBM PC or AT tics every .84 usec. */ #define timer0 0x40 /* 8253 timer 0 port */ @@ -82,41 +105,48 @@ typedef long clock_t; * (Which MS-DOS, silly thing that it is, almost certainly uses * internally.) */ -static unsigned -pctimer0(void) +static unsigned pctimer0(void) { - unsigned count; + unsigned count; - inp(timer0); - outp(timercntl, 0xC2); /* Latch status and count for timer 0 */ - count = (inp(timer0) & 0x80) << 8; - outp(timercntl, 0x00); /* Latch count of timer 0 */ - count |= (inp(timer0) & 0xFF) >> 1; - count |= (inp(timer0) & 0xFF) << 7; +#ifdef __GO32__ + inportb(timer0); + outportb(timercntl, 0xC2); /* Latch status and count for timer 0 */ + count = (inportb(timer0) & 0x80) << 8; + outportb(timercntl, 0x00); /* Latch count of timer 0 */ + count |= (inportb(timer0) & 0xFF) >> 1; + count |= (inportb(timer0) & 0xFF) << 7; +#else + inp(timer0); + outp(timercntl, 0xC2); /* Latch status and count for timer 0 */ + count = (inp(timer0) & 0x80) << 8; + outp(timercntl, 0x00); /* Latch count of timer 0 */ + count |= (inp(timer0) & 0xFF) >> 1; + count |= (inp(timer0) & 0xFF) << 7; +#endif - return count; + return count; } -#endif /* MSDOS || __MSDOS__ */ +#endif /* MSDOS || __MSDOS__ */ #ifdef UNIX #define NOISEDEBUG #ifdef NOISEDEBUG -#include "pgp.h" /* for verbose and pgpout */ +#include "pgp.h" /* for verbose and pgpout */ #include #endif /* Function needed for qsort() */ -static int -noiseCompare(void const *p1, void const *p2) +static int noiseCompare(void const *p1, void const *p2) { - return *(int const *)p1 - *(int const *)p2; + return *(int const *) p1 - *(int const *) p2; } -#define DELTAS 15 /* Number of deltas to try */ +#define DELTAS 15 /* Number of deltas to try */ /* * Find the resolution of the gettimeofday() clock by sampling @@ -164,49 +194,78 @@ noiseCompare(void const *p1, void const * latencies and compute the entropy directly. A model considering * the previous interval only should be adequate. */ -static unsigned -noiseTickSize(void) +static unsigned noiseTickSize(void) { - int i; - int j; - unsigned deltas[DELTAS]; - unsigned t; - struct timeval tv_base, tv_old, tv_new; - - i = j = 0; - gettimeofday(&tv_base, 0); - tv_old = tv_base; - do { - gettimeofday(&tv_new, 0); - if (tv_new.tv_usec > tv_old.tv_usec+2) { - deltas[i++] = tv_new.tv_usec - tv_base.tv_usec + - 1000000 * (tv_new.tv_sec - tv_base.tv_sec); - tv_base = tv_new; - j = 0; - } - tv_old = tv_new; - - /* - * If we are forever getting <= 2 us, then just assume - * it's 2 us. - */ - if (j++ > 10000) - return 2; - } while (i < DELTAS); + int i; + int j; + unsigned deltas[DELTAS]; + unsigned t; + struct timeval tv_base, tv_old, tv_new; + + i = j = 0; + gettimeofday(&tv_base, 0); + tv_old = tv_base; + do { + gettimeofday(&tv_new, 0); + if (tv_new.tv_usec > tv_old.tv_usec + 2) { + deltas[i++] = tv_new.tv_usec - tv_base.tv_usec + + 1000000 * (tv_new.tv_sec - tv_base.tv_sec); + tv_base = tv_new; + j = 0; + } + tv_old = tv_new; - qsort(deltas, DELTAS, sizeof(deltas[0]), noiseCompare); + /* + * If we are forever getting <= 2 us, then just assume + * it's 2 us. + */ + if (j++ > 10000) + return 2; + } while (i < DELTAS); - t = deltas[DELTAS/2]; /* Median */ + qsort(deltas, DELTAS, sizeof(deltas[0]), noiseCompare); + + t = deltas[DELTAS / 2]; /* Median */ #ifdef NOISEDEBUG - if (verbose) - fprintf(pgpout, "t = %u, clock frequency is %u Hz\n", t, (2000000+t)/(2*t)); + if (verbose) + fprintf(pgpout, "t = %u, clock frequency is %u Hz\n", + t, (2000000 + t) / (2 * t)); #endif - return t; + return t; } -#endif /* UNIX */ +#endif /* UNIX */ + + +/* (Written by Guy Geens 95/12/07) +This routine gets the 200Hz counter from the system area. +This part of memory is only accessible in supervisor mode. +To add to randomness, also store 50/60/70Hz VBL (Vertical BLank) +counter. (There are two flavours of this one: One counter is +stopped while floppy disk access takes place, the other one keeps +running. Which one to use? Both? No: the elapsed time would be +connected (does this harm randomness? I don't know) and, when +using a hard disk drive, the same! +(I've just picked one.) +*/ + +#ifdef ATARI +#ifdef __PUREC__ +#include +#else +#include +#endif +static word32 counter,vblcount; + +long getcount(void) { + counter= *((long*)0x4baL); /* _hz_200 */ + vblcount= *((long*)0x466L); /* _frlock */ + return counter; +} + +#endif /* @@ -214,82 +273,212 @@ noiseTickSize(void) * to the randPool. Typically, this involves reading the most * accurate system clocks available. * - * Returns the number of ticks that hasve passed since the last call, + * Returns the number of ticks that has passed since the last call, * for entropy estimation purposes. */ word32 noise(void) { - static word32 lastcounter; - word32 delta; - time_t tnow; - clock_t cnow; + static word32 lastcounter; + word32 delta; + time_t tnow; + clock_t cnow; - cnow = clock(); - randPoolAddBytes((byte *)&cnow, sizeof(cnow)); + cnow = clock(); + randPoolAddBytes((byte *) & cnow, sizeof(cnow)); - tnow = time((time_t *)0); - randPoolAddBytes((byte *)&tnow, sizeof(tnow)); + tnow = time((time_t *) 0); + randPoolAddBytes((byte *) & tnow, sizeof(tnow)); #if defined(MSDOS) || defined(__MSDOS__) - { - unsigned t; + { + unsigned t; - t = pctimer0(); + t = pctimer0(); + randPoolAddBytes((byte *) & t, sizeof(t)); + delta = t - (unsigned) lastcounter; + lastcounter = t; + } +#endif + +#ifdef MACTC5 + { + unsigned long t; + + delta = TMTicks(); + t=lastcounter+=delta; randPoolAddBytes((byte *)&t, sizeof(t)); - delta = t - (unsigned)lastcounter; - lastcounter = t; } #endif +#ifdef WIN32 +/* Win32 provides QueryPerformanceCounter(), which does precisely what we need here */ + { + /* What am I doing here ? : We can't #include to get the prototype + for QueryPerformanceCounter() because there are many namespace clashes + between PGP and windows.h. So, we hack in the prototype inline. When we get + a compiler which does namespaces, or someone removes all the clashes in PGP, + this will go. + */ +#if defined(_MSC_VER) /* only valid if we're using the Microsoft compiler */ + __declspec(dllimport) long __stdcall + QueryPerformanceCounter(__int64 *lpPerformanceCount); + unsigned t; + __int64 perf_count; + + QueryPerformanceCounter(&perf_count); + /* it doesn't matter if the return value is zero */ + t = (unsigned) perf_count; + randPoolAddBytes((byte *) & t, sizeof(t)); + delta = t - (unsigned) lastcounter; + lastcounter = t; +#else /* Not Microsoft compiler */ +#include "This compiler is not supported, modify the code above accordingly" +#endif /* _MSC_VER */ + } +#endif /* WIN32 */ + #ifdef VMS - { - word32 t; - /* VMS Hardware Clock */ - extern unsigned long vms_clock_bits[2]; - /* Clock update int. */ - extern const long vms_ticks_per_update; - - /* Capture fast system timer: */ - SYS$GETTIM(vms_clock_bits); - randPoolAddBytes((byte *)&vms_clock_bits, sizeof(vms_clock_bits)); - t = vms_clock_bits[0] / vms_ticks_per_update; - delta = t - lastcounter; - lastcounter = t; - } -#endif /* VMS */ + { + word32 t; + /* VMS Hardware Clock */ + extern unsigned long vms_clock_bits[2]; + /* Clock update int. */ + extern const long vms_ticks_per_update; + + /* Capture fast system timer: */ + SYS$GETTIM(vms_clock_bits); + randPoolAddBytes((byte *) & vms_clock_bits, sizeof(vms_clock_bits)); + t = vms_clock_bits[0] / vms_ticks_per_update; + delta = t - lastcounter; + lastcounter = t; + } +#endif /* VMS */ #ifdef UNIX - /* Get noise from gettimeofday() */ - { - struct timeval tv; - word32 t; - static unsigned ticksize = 0; - - if (!ticksize) - ticksize = noiseTickSize(); - - gettimeofday(&tv, NULL); - randPoolAddBytes((byte *)&tv, sizeof(tv)); - - /* This may wrap, but it's unsigned, so that's okay */ - t = tv.tv_sec * 1000000 + tv.tv_usec; - delta = t-lastcounter; - lastcounter = t; + /* Get noise from gettimeofday() */ + { + struct timeval tv; + word32 t; + static unsigned ticksize = 0; + + if (!ticksize) + ticksize = noiseTickSize(); + + gettimeofday(&tv, NULL); + randPoolAddBytes((byte *) & tv, sizeof(tv)); + + /* This may wrap, but it's unsigned, so that's okay */ + t = tv.tv_sec * 1000000 + tv.tv_usec; + delta = t - lastcounter; + lastcounter = t; + + delta /= ticksize; + } + /* Get noise from times() */ + { + clock_t t; + struct tms tms; + + t = times(&tms); + randPoolAddBytes((byte *) & tms, sizeof(tms)); + randPoolAddBytes((byte *) & t, sizeof(t)); + } +#endif /* UNIX */ + +#ifdef AMIGA /* Whole next section added RKNOP 940613 */ +#define AMIGA_DELTAS 15 + + { + static unsigned long ticksize = 0; + int i=0,j; + unsigned long deltas[AMIGA_DELTAS],swap; + + + /* NOTE -- this next section (reading the Eclock or the + microHz clock) will only happen within the do loop in + trueRandAccum()!! */ + + if (TimerIO && TimerBase) + { if (!ticksize) /* Get tick size, similar to Unix */ + { Forbid(); /* Turn off multitasking to get ticksize */ + if (use_eclock) + ReadEClock(&time0.e); + else + am_GetSysTime(&time0.t); + do + { if (use_eclock) + { ReadEClock(&time1.e); + if (time1.e.ev_lo>time0.e.ev_lo) + deltas[i++]=time1.e.ev_lo-time0.e.ev_lo; + time0.e.ev_lo=time1.e.ev_lo; + time0.e.ev_hi=time1.e.ev_hi; + } + else + { am_GetSysTime(&time1.t); + if (CmpTime(&time0.t,&time1.t)) + deltas[i++]=1000000*(time1.t.tv_secs + -time0.t.tv_secs) + +(time1.t.tv_micro-time0.t.tv_micro); + time0.t.tv_secs=time1.t.tv_secs; + time0.t.tv_micro=time1.t.tv_micro; + } + } while (iDispCount),4); + } +#endif /* AMIGA (RKNOP 940613) */ + +#ifdef ATARI /* Section written by Guy Geens 951207 */ + Supexec(getcount); /* Xbios 38 */ + delta=counter-lastcounter; + lastcounter=counter; - delta /= ticksize; - } - /* Get noise from times() */ - { - clock_t t; - struct tms tms; - - t = times(&tms); - randPoolAddBytes((byte *)&tms, sizeof(tms)); - randPoolAddBytes((byte *)&t, sizeof(t)); - } -#endif /* UNIX */ +#ifndef __PUREC__ + randPoolAddBytes((byte*)&counter,4); +#endif + /* Under Pure C, counter is the same as cnow (returned by clock()), + so it doesn't add to randomness. + I don't have any other C compiler, so I can't check whether they + also use the same counter. Please mail me further details */ + + randPoolAddBytes((byte*)&vblcount,4); + /* Other compilers might require to comment this out and activate + the previous line. */ +#endif /* End of section written by Guy Geens */ - return delta; + return delta; } -