noise.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /*
  2. * Copyright (c) 1993-1995 Colin Plumb. All rights reserved.
  3. * For licensing and other legal details, see the file legal.c.
  4. *
  5. * Get environmental noise.
  6. */
  7. #include "first.h"
  8. #include <time.h> /* For time measurement code */
  9. #ifndef MSDOS
  10. #ifdef __MSDOS
  11. #define MSDOS 1
  12. #endif
  13. #endif
  14. #ifndef MSDOS
  15. #ifdef __MSDOS__
  16. #define MSDOS 1
  17. #endif
  18. #endif
  19. #ifndef UNIX
  20. #ifdef unix
  21. #define UNIX 1
  22. #endif
  23. #endif
  24. #ifndef UNIX
  25. #ifdef __unix
  26. #define UNIX 1
  27. #endif
  28. #endif
  29. #ifndef UNIX
  30. #ifdef __unix__
  31. #define UNIX 1
  32. #endif
  33. #endif
  34. #ifdef MSDOS
  35. #if __BORLANDC__
  36. #define far __far /* Borland C++ 3.1's <dos.h> kacks in ANSI mode. Ugh! */
  37. #endif
  38. #include <dos.h> /* for enable() and disable() */
  39. #include <conio.h> /* for inp() and outp() */
  40. /*
  41. * This code gets as much information as possible out of 8253/8254 timer 0,
  42. * which ticks every .84 microseconds. There are three cases:
  43. * 1) Original 8253. 15 bits available, as the low bit is unused.
  44. * 2) 8254, in mode 3. The 16th bit is available from the status register.
  45. * 3) 8254, in mode 2. All 16 bits of the counters are available.
  46. * (This is not documented anywhere, but I've seen it!)
  47. *
  48. * This code repeatedly tries to latch the status (ignored by an 8253) and
  49. * sees if it looks like xx1101x0. If not, it's definitely not an 8254.
  50. * Repeat this a few times to make sure it is an 8254.
  51. */
  52. static int
  53. has8254(void)
  54. {
  55. int i, s1, s2;
  56. for (i = 0; i < 5; i++) {
  57. _disable();
  58. outp(0x43, 0xe2); /* Latch status for timer 0 */
  59. s1 = inp(0x40); /* If 8253, read timer low byte */
  60. outp(0x43, 0xe2); /* Latch status for timer 0 */
  61. s2 = inp(0x40); /* If 8253, read timer high byte */
  62. _enable();
  63. if ((s1 & 0x3d) != 0x34 || (s2 & 0x3d) != 0x34)
  64. return 0; /* Ignoring status latch; 8253 */
  65. }
  66. return 1; /* Status reads as expected; 8254 */
  67. }
  68. /* TODO: It might be better to capture this data in a keyboard ISR */
  69. static unsigned
  70. read8254(void)
  71. {
  72. unsigned status, count;
  73. _disable();
  74. outp(0x43, 0xc2); /* Latch status and count for timer 0 */
  75. status = inp(0x40);
  76. count = inp(0x40);
  77. count |= inp(0x40) << 8;
  78. _enable();
  79. /* The timer is usually in mode 3, but some motherboards use mode 2. */
  80. if (status & 2)
  81. count = count>>1 | (status & 0x80)<<8;
  82. return count;
  83. }
  84. static unsigned
  85. read8253(void)
  86. {
  87. unsigned count;
  88. _disable();
  89. outp(0x43, 0x00); /* Latch count for timer 0 */
  90. count = (inp(0x40) & 0xff);
  91. count |= (inp(0x40) & 0xff) << 8;
  92. _enable();
  93. return count >> 1;
  94. }
  95. #endif /* MSDOS */
  96. #ifdef UNIX
  97. /*
  98. * This code uses five different timers, if available, in decreasing
  99. * priority order:
  100. * - gethrtime(), assumed unavailable unless USE_GETHRTIME=1
  101. * - clock_gettime(), auto-detected unless overridden with USE_CLOCK_GETTIME
  102. * - gettimeofday(), assumed available unless USE_GETTIMEOFDAY=0
  103. * - getitimer(), auto-detected unless overridden with USE_GETITIMER
  104. * - ftime(), assumed available unless USE_FTIME=0
  105. *
  106. * These are all accessed through the gettime(), timetype, and tickdiff()
  107. * macros. The MINTICK constant is something to avoid the gettimeofday()
  108. * glitch wherein it increments the return value even if no tick has occurred.
  109. * When measuring the tick interval, if the difference between two successive
  110. * times is not at least MINTICK ticks, it is ignored.
  111. */
  112. #include <sys/types.h>
  113. #include <sys/times.h> /* for times() */
  114. #include <stdlib.h> /* For qsort() */
  115. #if !USE_GETHRTIME
  116. #ifndef USE_CLOCK_GETTIME /* Detect using CLOCK_REALTIME from <time.h> */
  117. #ifdef CLOCK_REALTIMExxx /* Stupid libc... */
  118. #define USE_CLOCK_GETTIME 1
  119. #else
  120. #define USE_CLOCK_GETTIME 0
  121. #endif
  122. #endif
  123. #if !USE_CLOCK_GETTIME
  124. #include <sys/time.h> /* For gettimeofday(), getitimer(), or ftime() */
  125. #ifndef USE_GETTIMEOFDAY
  126. #define USE_GETTIMEOFDAY 1 /* No way to tell, so assume it's there */
  127. #endif
  128. #if !USE_GETTIMEOFDAY
  129. #ifndef USE_GETITIMER /* Detect using ITIMER_REAL from <sys/time.h> */
  130. #define USE_GETITIMER defined(ITIMER_REAL)
  131. #endif
  132. #if !USE_GETITIMER
  133. #ifndef USE_FTIME
  134. #define USE_FTIME 1
  135. #endif
  136. #endif /* !USE_GETITIMER */
  137. #endif /* !USE_GETTIMEOFDAY */
  138. #endif /* !USE_CLOCK_GETTIME */
  139. #endif /* !USE_GETHRTIME */
  140. #if USE_GETHRTIME
  141. #define CHOICE_GETHRTIME 1
  142. #include <sys/time.h>
  143. typedef hrtime_t timetype;
  144. #define gettime(s) (*(s) = gethrtime())
  145. #define tickdiff(s,t) ((s)-(t))
  146. #define MINTICK 0
  147. #elif USE_CLOCK_GETTIME
  148. #define CHOICE_CLOCK_GETTIME 1
  149. typedef struct timespec timetype;
  150. #define gettime(s) (void)clock_gettime(CLOCK_REALTIME, s)
  151. #define tickdiff(s,t) (((s).tv_sec-(t).tv_sec)*1000000000 + \
  152. (s).tv_nsec - (t).tv_nsec)
  153. #elif USE_GETTIMEOFDAY
  154. #define CHOICE_GETTIMEOFDAY 1
  155. typedef struct timeval timetype;
  156. #define gettime(s) (void)gettimeofday(s, (struct timezone *)0)
  157. #define tickdiff(s,t) (((s).tv_sec-(t).tv_sec)*1000000+(s).tv_usec-(t).tv_usec)
  158. #define MINTICK 1
  159. #elif USE_GETITIMER
  160. #define CHOICE_GETITIMER 1
  161. #include <signal.h> /* For signal(), SIGALRM, SIG_IGN */
  162. typedef struct itimerval timetype;
  163. #define gettime(s) (void)getitimer(ITIMER_REAL, s)
  164. #define tickdiff(s,t) (((t).it_value.tv_sec-(s).it_value.tv_sec)*1000000 + \
  165. (t).it_value.tv_usec - (s).it_value.tv_usec)
  166. #define MINTICK 1
  167. #elif USE_FTIME /* Use ftime() */
  168. #define CHOICE_FTIME 1
  169. #include <sys/timeb.h>
  170. typedef struct timeb timetype;
  171. #define gettime(s) (void)ftime(s)
  172. #define tickdiff(s,t) (((s).time-(t).time)*1000 + (s).millitm - (t).millitm)
  173. #define MINTICK 0
  174. #else
  175. #error No clock available - please define one.
  176. #endif /* End of complex choice of clock conditional */
  177. #if CHOICE_CLOCK_GETTIME
  178. static unsigned
  179. noiseTickSize(void)
  180. {
  181. struct timespec res;
  182. clock_getres(CLOCK_REALTIME, &res);
  183. return res.tv_nsec;
  184. }
  185. #else /* Normal clock resolution estimation */
  186. #if NOISEDEBUG
  187. #include <stdio.h>
  188. #endif
  189. #define N 15 /* Number of deltas to try (at least 5, preferably odd) */
  190. /* Function needed for qsort() */
  191. static int
  192. noiseCompare(void const *p1, void const *p2)
  193. {
  194. return *(unsigned const *)p1 > *(unsigned const *)p2 ? 1 :
  195. *(unsigned const *)p1 < *(unsigned const *)p2 ? -1 : 0;
  196. }
  197. /*
  198. * Find the resolution of the high-resolution clock by sampling successive
  199. * values until a tick boundary, at which point the delta is entered into
  200. * a table. An average near the median of the table is taken and returned
  201. * as the system tick size to eliminate outliers due to descheduling (high)
  202. * or tv0 not being the "zero" time in a given tick (low).
  203. *
  204. * Some trickery is needed to defeat the habit systems have of always
  205. * incrementing the microseconds field from gettimeofday() results so that
  206. * no two calls return the same value. Thus, a "tick boundary" is assumed
  207. * when successive calls return a difference of more than MINTICK ticks.
  208. * (For gettimeofday(), this is set to 2 us.) This catches cases where at
  209. * most one other task reads the clock between successive reads by this task.
  210. * More tasks in between are rare enough that they'll get cut off by the
  211. * median filter.
  212. *
  213. * When a tick boundary is found, the *first* time read during the previous
  214. * tick (tv0) is subtracted from the new time to get microseconds per tick.
  215. *
  216. * Suns have a 1 us timer, and as of SunOS 4.1, they return that timer, but
  217. * there is ~50 us of system-call overhead to get it, so this overestimates
  218. * the tick size considerably. On SunOS 5.x/Solaris, the overhead has been
  219. * cut to about 2.5 us, so the measured time alternates between 2 and 3 us.
  220. * Some better algorithms will be required for future machines that really
  221. * do achieve 1 us granularity.
  222. *
  223. * Current best idea: discard all this hair and use Ueli Maurer's entropy
  224. * estimation scheme. Assign each input event (delta) a sequence number.
  225. * 16 bits should be more than adequate. Make a table of the last time
  226. * (by sequence number) each possibe input event occurred. For practical
  227. * implementation, hash the event to a fixed-size code and consider two
  228. * events identical if they have the same hash code. This will only ever
  229. * underestimate entropy. Then use the number of bits in the difference
  230. * between the current sequence number and the previous one as the entropy
  231. * estimate.
  232. *
  233. * If it's desirable to use longer contexts, Maurer's original technique
  234. * just groups events into non-overlapping pairs and uses the technique on
  235. * the pairs. If you want to increment the entropy numbers on each keystroke
  236. * for user-interface niceness, you can do the operation each time, but you
  237. * have to halve the sequence number difference before starting, and then you
  238. * have to halve the number of bits of entropy computed because you're adding
  239. * them twice.
  240. *
  241. * You can put the even and odd events into separate tables to close Maurer's
  242. * model exactly, or you can just dump them into the same table, which will
  243. * be more conservative.
  244. */
  245. static unsigned
  246. noiseTickSize(void)
  247. {
  248. unsigned i = 0, j = 0, diff, d[N];
  249. timetype tv0, tv1, tv2;
  250. gettime(&tv0);
  251. tv1 = tv0;
  252. do {
  253. gettime(&tv2);
  254. diff = (unsigned)tickdiff(tv2, tv1);
  255. if (diff > MINTICK) {
  256. d[i++] = diff;
  257. tv0 = tv2;
  258. j = 0;
  259. } else if (++j >= 4096) /* Always getting <= MINTICK units */
  260. return MINTICK + !MINTICK;
  261. tv1 = tv2;
  262. } while (i < N);
  263. /* Return average of middle 5 values (rounding up) */
  264. qsort(d, N, sizeof(d[0]), noiseCompare);
  265. diff = (d[N/2-2]+d[N/2-1]+d[N/2]+d[N/2+1]+d[N/2+2]+4)/5;
  266. #if NOISEDEBUG
  267. fprintf(stderr, "Tick size is %u\n", diff);
  268. #endif
  269. return diff;
  270. }
  271. #endif /* Clock resolution measurement condition */
  272. #endif /* UNIX */
  273. #include "usuals.h"
  274. #include "randpool.h"
  275. #include "noise.h"
  276. /*
  277. * Add as much environmentally-derived random noise as possible
  278. * to the randPool. Typically, this involves reading the most
  279. * accurate system clocks available.
  280. *
  281. * Returns the number of ticks that have passed since the last call,
  282. * for entropy estimation purposes.
  283. */
  284. word32
  285. noise(void)
  286. {
  287. word32 delta;
  288. #if defined(MSDOS)
  289. static unsigned deltamask = 0;
  290. static unsigned prevt;
  291. unsigned t;
  292. time_t tnow;
  293. clock_t cnow;
  294. if (deltamask == 0)
  295. deltamask = has8254() ? 0xffff : 0x7fff;
  296. t = (deltamask & 0x8000) ? read8254() : read8253();
  297. randPoolAddBytes((byte const *)&t, sizeof(t));
  298. delta = deltamask & (t - prevt);
  299. prevt = t;
  300. /* Add more-significant time components. */
  301. cnow = clock();
  302. randPoolAddBytes((byte *)&cnow, sizeof(cnow));
  303. tnow = time((time_t *)0);
  304. randPoolAddBytes((byte *)&tnow, sizeof(tnow));
  305. /* END OF DOS */
  306. #elif defined(VMS)
  307. word32 t[2]; /* little-endian 64-bit timer */
  308. word32 d1; /* MSW of difference */
  309. static word32 prevt[2];
  310. SYS$GETTIM(t); /* VMS hardware clock increments by 100000 per tick */
  311. randPoolAddBytes((byte const *)t, sizeof(t));
  312. /* Get difference in d1 and delta, and old time in prevt */
  313. d1 = t[1] - prevt[1] + (t[0] < prevt[0]);
  314. prevt[1] = t[1];
  315. delta = t[0] - prevt[0];
  316. prevt[0] = t[0];
  317. /* Now, divide the 64-bit value by 100000 = 2^5 * 5^5 = 32 * 3125 */
  318. /* Divide value, MSW in d1 and LSW in delta, by 32 */
  319. delta >>= 5;
  320. delta |= d1 << (32-5);
  321. d1 >>= 5;
  322. /*
  323. * Divide by 3125. This fits into 16 bits, so the following
  324. * code is possible. 2^32 = 3125 * 1374389 + 1671.
  325. *
  326. * This code has confused people reading it, so here's a detailed
  327. * explanation. First, since we only want a 32-bit result,
  328. * reduce the input mod 3125 * 2^32 before starting. This
  329. * amounts to reducing the most significant word mod 3125 and
  330. * leaving the least-significant word alone.
  331. *
  332. * Then, using / for mathematical (real, not integer) division, we
  333. * want to compute floor(d1 * 2^32 + d0) / 3125), which I'll denote
  334. * using the old [ ] syntax for floor, so it's
  335. * [ (d1 * 2^32 + d0) / 3125 ]
  336. * = [ (d1 * (3125 * 1374389 + 1671) + d0) / 3125 ]
  337. * = [ d1 * 1374389 + (d1 * 1671 + d0) / 3125 ]
  338. * = d1 * 137438 + [ (d1 * 1671 + d0) / 3125 ]
  339. * = d1 * 137438 + [ d0 / 3125 ] + [ (d1 * 1671 + d0 % 3125) / 3125 ]
  340. *
  341. * The C / operator, applied to integers, performs [ a / b ], so
  342. * this can be implemented in C, and since d1 < 3125 (by the first
  343. * modulo operation), d1 * 1671 + d0 % 3125 < 3125 * 1672, which
  344. * is 5225000, less than 2^32, so it all fits into 32 bits.
  345. */
  346. d1 %= 3125; /* Ignore overflow past 32 bits */
  347. delta = delta/3125 + d1*1374389 + (delta%3125 + d1*1671) / 3125;
  348. /* END OF VMS */
  349. #elif defined(UNIX)
  350. timetype t;
  351. static unsigned ticksize = 0;
  352. static timetype prevt;
  353. gettime(&t);
  354. #if CHOICE_GETITIMER
  355. /* If itimer isn't started, start it */
  356. if (t.it_value.tv_sec == 0 && t.it_value.tv_usec == 0) {
  357. /*
  358. * start the timer - assume that PGP won't be running for
  359. * more than 11 days, 13 hours, 46 minutes and 40 seconds.
  360. */
  361. t.it_value.tv_sec = 1000000;
  362. t.it_interval.tv_sec = 1000000;
  363. t.it_interval.tv_usec = 0;
  364. signal(SIGALRM, SIG_IGN); /* just in case.. */
  365. setitimer(ITIMER_REAL, &t, NULL);
  366. t.it_value.tv_sec = 0;
  367. }
  368. randPoolAddBytes((byte const *)&t.it_value, sizeof(t.it_value));
  369. #else
  370. randPoolAddBytes((byte const *)&t, sizeof(t));
  371. #endif
  372. if (!ticksize)
  373. ticksize = noiseTickSize();
  374. delta = (word32)(tickdiff(t, prevt) / ticksize);
  375. prevt = t;
  376. /* END OF UNIX */
  377. #else
  378. #error Unknown OS - define UNIX or MSDOS or add code for high-resolution timers
  379. #endif
  380. return delta;
  381. }