|
|
1.1.1.4 ! root 1: /* ! 2: * Get environmental noise. ! 3: * ! 4: * (c) Copyright 1990-1996 by Philip Zimmermann. All rights reserved. ! 5: * The author assumes no liability for damages resulting from the use ! 6: * of this software, even if the damage results from defects in this ! 7: * software. No warranty is expressed or implied. ! 8: * ! 9: * Note that while most PGP source modules bear Philip Zimmermann's ! 10: * copyright notice, many of them have been revised or entirely written ! 11: * by contributors who frequently failed to put their names in their ! 12: * code. Code that has been incorporated into PGP from other authors ! 13: * was either originally published in the public domain or is used with ! 14: * permission from the various authors. ! 15: * ! 16: * PGP is available for free to the public under certain restrictions. ! 17: * See the PGP User's Guide (included in the release package) for ! 18: * important information about licensing, patent restrictions on ! 19: * certain algorithms, trademarks, copyrights, and export controls. ! 20: * ! 21: * Written by Colin Plumb. ! 22: */ ! 23: ! 24: ! 25: #ifdef UNIX ! 26: #include <sys/types.h> ! 27: #include <sys/time.h> /* For gettimeofday() */ ! 28: #include <sys/times.h> /* for times() */ ! 29: #include <stdlib.h> /* For qsort() */ ! 30: #endif /* UNIX */ ! 31: ! 32: #include <time.h> ! 33: #include "usuals.h" ! 34: #include "randpool.h" ! 35: #include "noise.h" ! 36: #ifdef MACTC5 ! 37: #include "TimeManager.h" ! 38: #endif ! 39: ! 40: #ifdef AMIGA /* RKNOP 940613 */ ! 41: #include <devices/timer.h> ! 42: #include <hardware/custom.h> ! 43: #include <exec/execbase.h> ! 44: extern __far struct Custom custom; /* Custom chips */ ! 45: #include <proto/exec.h> ! 46: #include <proto/timer.h> ! 47: ! 48: /* Stuff used in noise.c, defined in random.c -- RKNOP 940613*/ ! 49: extern struct timerequest *TimerIO; ! 50: extern union { struct timeval t; ! 51: struct EClockVal e; ! 52: } time0,time1; ! 53: extern unsigned short use_eclock; ! 54: #endif /* AMIGA */ ! 55: ! 56: /* Some machines just don't have clock_t */ ! 57: #if defined(sun) && defined(i386) ! 58: typedef long clock_t; ! 59: #endif ! 60: ! 61: #if defined(MSDOS) || defined(__MSDOS__) ! 62: ! 63: /* Use IBM PC hardware timer (1.19 MHz) */ ! 64: ! 65: #ifdef __GO32__ ! 66: #include <pc.h> ! 67: #else ! 68: #include <conio.h> /* for inp() and outp() */ ! 69: #include <dos.h> /* same for Turbo C EWS */ ! 70: #endif ! 71: ! 72: /* timer0 on 8253-5 on IBM PC or AT tics every .84 usec. */ ! 73: #define timer0 0x40 /* 8253 timer 0 port */ ! 74: #define timercntl 0x43 /* 8253 control register */ ! 75: ! 76: /* ! 77: * On an IBM PC, timer 0 ticks every .84 usec. It counts down ! 78: * from 65536 by twos, toggling its output line after each ! 79: * step. On an original IBM PC, we can thus only get 15 bits ! 80: * of the timer. On a PC-AT or later, with an 8284 timer chip, ! 81: * we can get all 16 bits by reading the status, which has the ! 82: * state of the output bit in bit 7, and is effectively the ! 83: * high bit of the counter. ! 84: * ! 85: * But latching the status is a command which the 8283 does not ! 86: * recognize; the subsequent load is interpreted as one of ! 87: * a pair to read the counter instead of the status. (We get a ! 88: * garbage bit instead of the one we expected, but that's no worse ! 89: * than constant 0.) But the 8283 doesn't like single reads. ! 90: * (The 8284 is more forgiving.) ! 91: * ! 92: * So, to resolve all this, the following sequence is used: ! 93: * ! 94: * - Dummy read from counter 0 (low byte) ! 95: * - Latch status and count (ignored by 8283) ! 96: * - Read status (high byte on 8283) ! 97: * - Latch count (ignored by 8284, as count is already latched) ! 98: * - Read count (low) ! 99: * - Read count (high) ! 100: * ! 101: * It would be better (a project for the future) to capture the counter ! 102: * in a keyboard ISR, put it in a global variable, and have noise() read ! 103: * the global. This gets the most accurate possible time, and avoids ! 104: * possible harmonic relationships with a keyboard polling loop. ! 105: * (Which MS-DOS, silly thing that it is, almost certainly uses ! 106: * internally.) ! 107: */ ! 108: static unsigned pctimer0(void) ! 109: { ! 110: unsigned count; ! 111: ! 112: #ifdef __GO32__ ! 113: inportb(timer0); ! 114: outportb(timercntl, 0xC2); /* Latch status and count for timer 0 */ ! 115: count = (inportb(timer0) & 0x80) << 8; ! 116: outportb(timercntl, 0x00); /* Latch count of timer 0 */ ! 117: count |= (inportb(timer0) & 0xFF) >> 1; ! 118: count |= (inportb(timer0) & 0xFF) << 7; ! 119: #else ! 120: inp(timer0); ! 121: outp(timercntl, 0xC2); /* Latch status and count for timer 0 */ ! 122: count = (inp(timer0) & 0x80) << 8; ! 123: outp(timercntl, 0x00); /* Latch count of timer 0 */ ! 124: count |= (inp(timer0) & 0xFF) >> 1; ! 125: count |= (inp(timer0) & 0xFF) << 7; ! 126: #endif ! 127: ! 128: return count; ! 129: } ! 130: ! 131: #endif /* MSDOS || __MSDOS__ */ ! 132: ! 133: ! 134: #ifdef UNIX ! 135: ! 136: #define NOISEDEBUG ! 137: #ifdef NOISEDEBUG ! 138: #include "pgp.h" /* for verbose and pgpout */ ! 139: #include <stdio.h> ! 140: #endif ! 141: ! 142: /* Function needed for qsort() */ ! 143: static int noiseCompare(void const *p1, void const *p2) ! 144: { ! 145: return *(int const *) p1 - *(int const *) p2; ! 146: } ! 147: ! 148: ! 149: #define DELTAS 15 /* Number of deltas to try */ ! 150: ! 151: /* ! 152: * Find the resolution of the gettimeofday() clock by sampling ! 153: * successive values until a tick boundary, at which point ! 154: * the delta is entered into a table. The median of the table is ! 155: * returned as the system tick size. ! 156: * ! 157: * Some trickery is needed to defeat the habit systems have of ! 158: * always incrementing the microseconds field so that no two calls ! 159: * return the same value. Thus, a "tick boundary" is assumed ! 160: * when successive calls return a difference of >2 us. ! 161: * (This catches cases where we make successive calls and one ! 162: * other task sneaks in between. More tasks in between are ! 163: * sufficiently unlikely that they'll get cut off by the median ! 164: * filter. ! 165: * ! 166: * When a tick boundary is found, the *first* time read during ! 167: * the previous tick (tv_base) is subtracted from the new time ! 168: * to get the microseconds per tick. ! 169: * ! 170: * The median of the ticks is taken to eliminate outliers due to ! 171: * descheduling (extra large) or tv_base not being the "zero" time ! 172: * in a given tick (slightly small). ! 173: * ! 174: * Note that Suns have a 1 us timer, and in SunOS 4.1, they return ! 175: * that timer, but there is ~50 us of system-call overhead to get ! 176: * it, so this overestimates the tick size consdierably. On ! 177: * SunOS 5.x/Solaris, the overhead has been cut to about 2.5 us, ! 178: * so the inter-call time alternates between 2 and 3 us. Some ! 179: * better algorithms are required to cope with potentially faster ! 180: * machines that really do return 1 us granularity. ! 181: * ! 182: * Current best idea (unimplemented): Sample a large number, and ! 183: * track small (< 100 us) deltas in an array of counters, and ! 184: * large ones in an array of deltas. There should be three ! 185: * bumps: 1 us auto-increment, the tick size (which may blend into ! 186: * the previous bump), and time-slicing. We want to throw out ! 187: * the latter, then compute the average delta as the average cost ! 188: * of making a call, then throw out the small values if they ! 189: * are suspisciously smaller than this value. Then some average ! 190: * of the remainder should provide a good value for the cost of ! 191: * making a call. ! 192: * ! 193: * The alternative to all this is to actually model the keystroke ! 194: * latencies and compute the entropy directly. A model considering ! 195: * the previous interval only should be adequate. ! 196: */ ! 197: static unsigned noiseTickSize(void) ! 198: { ! 199: int i; ! 200: int j; ! 201: unsigned deltas[DELTAS]; ! 202: unsigned t; ! 203: struct timeval tv_base, tv_old, tv_new; ! 204: ! 205: i = j = 0; ! 206: gettimeofday(&tv_base, 0); ! 207: tv_old = tv_base; ! 208: do { ! 209: gettimeofday(&tv_new, 0); ! 210: if (tv_new.tv_usec > tv_old.tv_usec + 2) { ! 211: deltas[i++] = tv_new.tv_usec - tv_base.tv_usec + ! 212: 1000000 * (tv_new.tv_sec - tv_base.tv_sec); ! 213: tv_base = tv_new; ! 214: j = 0; ! 215: } ! 216: tv_old = tv_new; ! 217: ! 218: /* ! 219: * If we are forever getting <= 2 us, then just assume ! 220: * it's 2 us. ! 221: */ ! 222: if (j++ > 10000) ! 223: return 2; ! 224: } while (i < DELTAS); ! 225: ! 226: qsort(deltas, DELTAS, sizeof(deltas[0]), noiseCompare); ! 227: ! 228: t = deltas[DELTAS / 2]; /* Median */ ! 229: ! 230: #ifdef NOISEDEBUG ! 231: if (verbose) ! 232: fprintf(pgpout, "t = %u, clock frequency is %u Hz\n", ! 233: t, (2000000 + t) / (2 * t)); ! 234: #endif ! 235: ! 236: return t; ! 237: } ! 238: ! 239: #endif /* UNIX */ ! 240: ! 241: ! 242: /* (Written by Guy Geens 95/12/07) ! 243: This routine gets the 200Hz counter from the system area. ! 244: This part of memory is only accessible in supervisor mode. ! 245: To add to randomness, also store 50/60/70Hz VBL (Vertical BLank) ! 246: counter. (There are two flavours of this one: One counter is ! 247: stopped while floppy disk access takes place, the other one keeps ! 248: running. Which one to use? Both? No: the elapsed time would be ! 249: connected (does this harm randomness? I don't know) and, when ! 250: using a hard disk drive, the same! ! 251: (I've just picked one.) ! 252: */ ! 253: ! 254: #ifdef ATARI ! 255: #ifdef __PUREC__ ! 256: #include <tos.h> ! 257: #else ! 258: #include <osbind.h> ! 259: #endif ! 260: static word32 counter,vblcount; ! 261: ! 262: long getcount(void) { ! 263: counter= *((long*)0x4baL); /* _hz_200 */ ! 264: vblcount= *((long*)0x466L); /* _frlock */ ! 265: return counter; ! 266: } ! 267: ! 268: #endif ! 269: ! 270: ! 271: /* ! 272: * Add as much environmentally-derived random noise as possible ! 273: * to the randPool. Typically, this involves reading the most ! 274: * accurate system clocks available. ! 275: * ! 276: * Returns the number of ticks that has passed since the last call, ! 277: * for entropy estimation purposes. ! 278: */ ! 279: word32 ! 280: noise(void) ! 281: { ! 282: static word32 lastcounter; ! 283: word32 delta; ! 284: time_t tnow; ! 285: clock_t cnow; ! 286: ! 287: cnow = clock(); ! 288: randPoolAddBytes((byte *) & cnow, sizeof(cnow)); ! 289: ! 290: tnow = time((time_t *) 0); ! 291: randPoolAddBytes((byte *) & tnow, sizeof(tnow)); ! 292: ! 293: #if defined(MSDOS) || defined(__MSDOS__) ! 294: { ! 295: unsigned t; ! 296: ! 297: t = pctimer0(); ! 298: randPoolAddBytes((byte *) & t, sizeof(t)); ! 299: delta = t - (unsigned) lastcounter; ! 300: lastcounter = t; ! 301: } ! 302: #endif ! 303: ! 304: #ifdef MACTC5 ! 305: { ! 306: unsigned long t; ! 307: ! 308: delta = TMTicks(); ! 309: t=lastcounter+=delta; ! 310: randPoolAddBytes((byte *)&t, sizeof(t)); ! 311: } ! 312: #endif ! 313: ! 314: #ifdef WIN32 ! 315: /* Win32 provides QueryPerformanceCounter(), which does precisely what we need here */ ! 316: { ! 317: /* What am I doing here ? : We can't #include <windows.h> to get the prototype ! 318: for QueryPerformanceCounter() because there are many namespace clashes ! 319: between PGP and windows.h. So, we hack in the prototype inline. When we get ! 320: a compiler which does namespaces, or someone removes all the clashes in PGP, ! 321: this will go. ! 322: */ ! 323: #if defined(_MSC_VER) /* only valid if we're using the Microsoft compiler */ ! 324: __declspec(dllimport) long __stdcall ! 325: QueryPerformanceCounter(__int64 *lpPerformanceCount); ! 326: unsigned t; ! 327: __int64 perf_count; ! 328: ! 329: QueryPerformanceCounter(&perf_count); ! 330: /* it doesn't matter if the return value is zero */ ! 331: t = (unsigned) perf_count; ! 332: randPoolAddBytes((byte *) & t, sizeof(t)); ! 333: delta = t - (unsigned) lastcounter; ! 334: lastcounter = t; ! 335: #else /* Not Microsoft compiler */ ! 336: #include "This compiler is not supported, modify the code above accordingly" ! 337: #endif /* _MSC_VER */ ! 338: } ! 339: #endif /* WIN32 */ ! 340: ! 341: #ifdef VMS ! 342: { ! 343: word32 t; ! 344: /* VMS Hardware Clock */ ! 345: extern unsigned long vms_clock_bits[2]; ! 346: /* Clock update int. */ ! 347: extern const long vms_ticks_per_update; ! 348: ! 349: /* Capture fast system timer: */ ! 350: SYS$GETTIM(vms_clock_bits); ! 351: randPoolAddBytes((byte *) & vms_clock_bits, sizeof(vms_clock_bits)); ! 352: t = vms_clock_bits[0] / vms_ticks_per_update; ! 353: delta = t - lastcounter; ! 354: lastcounter = t; ! 355: } ! 356: #endif /* VMS */ ! 357: ! 358: #ifdef UNIX ! 359: /* Get noise from gettimeofday() */ ! 360: { ! 361: struct timeval tv; ! 362: word32 t; ! 363: static unsigned ticksize = 0; ! 364: ! 365: if (!ticksize) ! 366: ticksize = noiseTickSize(); ! 367: ! 368: gettimeofday(&tv, NULL); ! 369: randPoolAddBytes((byte *) & tv, sizeof(tv)); ! 370: ! 371: /* This may wrap, but it's unsigned, so that's okay */ ! 372: t = tv.tv_sec * 1000000 + tv.tv_usec; ! 373: delta = t - lastcounter; ! 374: lastcounter = t; ! 375: ! 376: delta /= ticksize; ! 377: } ! 378: /* Get noise from times() */ ! 379: { ! 380: clock_t t; ! 381: struct tms tms; ! 382: ! 383: t = times(&tms); ! 384: randPoolAddBytes((byte *) & tms, sizeof(tms)); ! 385: randPoolAddBytes((byte *) & t, sizeof(t)); ! 386: } ! 387: #endif /* UNIX */ ! 388: ! 389: #ifdef AMIGA /* Whole next section added RKNOP 940613 */ ! 390: #define AMIGA_DELTAS 15 ! 391: ! 392: { ! 393: static unsigned long ticksize = 0; ! 394: int i=0,j; ! 395: unsigned long deltas[AMIGA_DELTAS],swap; ! 396: ! 397: ! 398: /* NOTE -- this next section (reading the Eclock or the ! 399: microHz clock) will only happen within the do loop in ! 400: trueRandAccum()!! */ ! 401: ! 402: if (TimerIO && TimerBase) ! 403: { if (!ticksize) /* Get tick size, similar to Unix */ ! 404: { Forbid(); /* Turn off multitasking to get ticksize */ ! 405: if (use_eclock) ! 406: ReadEClock(&time0.e); ! 407: else ! 408: am_GetSysTime(&time0.t); ! 409: do ! 410: { if (use_eclock) ! 411: { ReadEClock(&time1.e); ! 412: if (time1.e.ev_lo>time0.e.ev_lo) ! 413: deltas[i++]=time1.e.ev_lo-time0.e.ev_lo; ! 414: time0.e.ev_lo=time1.e.ev_lo; ! 415: time0.e.ev_hi=time1.e.ev_hi; ! 416: } ! 417: else ! 418: { am_GetSysTime(&time1.t); ! 419: if (CmpTime(&time0.t,&time1.t)) ! 420: deltas[i++]=1000000*(time1.t.tv_secs ! 421: -time0.t.tv_secs) ! 422: +(time1.t.tv_micro-time0.t.tv_micro); ! 423: time0.t.tv_secs=time1.t.tv_secs; ! 424: time0.t.tv_micro=time1.t.tv_micro; ! 425: } ! 426: } while (i<AMIGA_DELTAS); ! 427: for (i=0;i<AMIGA_DELTAS-1;i++) ! 428: for (j=i+1;j<AMIGA_DELTAS;j++) ! 429: if (deltas[j]<deltas[i]) ! 430: { swap=deltas[j]; ! 431: deltas[j]=deltas[i]; ! 432: deltas[i]=swap; ! 433: } ! 434: if ((ticksize=deltas[AMIGA_DELTAS/2])==0) ticksize=1; ! 435: Permit(); ! 436: } ! 437: ! 438: if (use_eclock) ! 439: { ReadEClock(&time1.e); ! 440: randPoolAddBytes((byte *)&time1.e.ev_lo,4); ! 441: delta=time1.e.ev_lo-time0.e.ev_lo; /* wrap ok?, unsigned */ ! 442: time0.e.ev_hi=time1.e.ev_hi; ! 443: time0.e.ev_lo=time1.e.ev_lo; ! 444: } ! 445: else ! 446: { am_GetSysTime(&time1.t); ! 447: randPoolAddBytes((byte *)&time1.t,sizeof(time1.t)); ! 448: delta=1000000*(time1.t.tv_secs - time0.t.tv_secs) + ! 449: time1.t.tv_micro - time0.t.tv_micro; ! 450: time0.t.tv_secs=time1.t.tv_secs; ! 451: time0.t.tv_micro=time1.t.tv_micro; ! 452: } ! 453: delta/=ticksize; ! 454: } ! 455: ! 456: /* Get some additional noise from the video beam poisition */ ! 457: randPoolAddBytes((byte *)&custom.vhposr,2); ! 458: ! 459: /* Pull the ExecBase dispatch count */ ! 460: randPoolAddBytes((byte *) ! 461: &((*(struct ExecBase **)4)->DispCount),4); ! 462: } ! 463: #endif /* AMIGA (RKNOP 940613) */ ! 464: ! 465: #ifdef ATARI /* Section written by Guy Geens <[email protected]> 951207 */ ! 466: Supexec(getcount); /* Xbios 38 */ ! 467: delta=counter-lastcounter; ! 468: lastcounter=counter; ! 469: ! 470: #ifndef __PUREC__ ! 471: randPoolAddBytes((byte*)&counter,4); ! 472: #endif ! 473: /* Under Pure C, counter is the same as cnow (returned by clock()), ! 474: so it doesn't add to randomness. ! 475: I don't have any other C compiler, so I can't check whether they ! 476: also use the same counter. Please mail me further details */ ! 477: ! 478: randPoolAddBytes((byte*)&vblcount,4); ! 479: /* Other compilers might require to comment this out and activate ! 480: the previous line. */ ! 481: #endif /* End of section written by Guy Geens */ ! 482: ! 483: return delta; ! 484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.