unix_rand.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:17k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #include <stdio.h>
  34. #include <string.h>
  35. #include <signal.h>
  36. #include <unistd.h>
  37. #include <errno.h>
  38. #include <stdlib.h>
  39. #include <sys/time.h>
  40. #include <sys/wait.h>
  41. #include <sys/stat.h>
  42. #include <assert.h>
  43. #include "secrng.h"
  44. /*
  45.  * When copying data to the buffer we want the least signicant bytes
  46.  * from the input since those bits are changing the fastest. The address
  47.  * of least significant byte depends upon whether we are running on
  48.  * a big-endian or little-endian machine.
  49.  *
  50.  * Does this mean the least signicant bytes are the most significant
  51.  * to us? :-)
  52.  */
  53.     
  54. static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
  55. {
  56.     union endianness {
  57. int32 i;
  58. char c[4];
  59.     } u;
  60.     if (srclen <= dstlen) {
  61. memcpy(dst, src, srclen);
  62. return srclen;
  63.     }
  64.     u.i = 0x01020304;
  65.     if (u.c[0] == 0x01) {
  66. /* big-endian case */
  67. memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
  68.     } else {
  69. /* little-endian case */
  70. memcpy(dst, src, dstlen);
  71.     }
  72.     return dstlen;
  73. }
  74. #if defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(FREEBSD) 
  75.     || defined(NETBSD)
  76. #include <sys/times.h>
  77. #define getdtablesize() sysconf(_SC_OPEN_MAX)
  78. static size_t
  79. GetHighResClock(void *buf, size_t maxbytes)
  80. {
  81.     int ticks;
  82.     struct tms buffer;
  83.     ticks=times(&buffer);
  84.     return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
  85. }
  86. static void
  87. GiveSystemInfo(void)
  88. {
  89.     long si;
  90.     /* 
  91.      * Is this really necessary?  Why not use rand48 or something?
  92.      */
  93.     si = sysconf(_SC_CHILD_MAX);
  94.     RNG_RandomUpdate(&si, sizeof(si));
  95.     si = sysconf(_SC_STREAM_MAX);
  96.     RNG_RandomUpdate(&si, sizeof(si));
  97.     si = sysconf(_SC_OPEN_MAX);
  98.     RNG_RandomUpdate(&si, sizeof(si));
  99. }
  100. #endif
  101. #if defined(__sun)
  102. #if defined(__svr4) || defined(SVR4)
  103. #include <sys/systeminfo.h>
  104. #include <sys/times.h>
  105. #include <wait.h>
  106. int gettimeofday(struct timeval *);
  107. int gethostname(char *, int);
  108. #define getdtablesize() sysconf(_SC_OPEN_MAX)
  109. static void
  110. GiveSystemInfo(void)
  111. {
  112.     int rv;
  113.     char buf[2000];
  114.     rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
  115.     if (rv > 0) {
  116. RNG_RandomUpdate(buf, rv);
  117.     }
  118.     rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
  119.     if (rv > 0) {
  120. RNG_RandomUpdate(buf, rv);
  121.     }
  122.     rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
  123.     if (rv > 0) {
  124. RNG_RandomUpdate(buf, rv);
  125.     }
  126. }
  127. static size_t
  128. GetHighResClock(void *buf, size_t maxbytes)
  129. {
  130.     hrtime_t t;
  131.     t = gethrtime();
  132.     if (t) {
  133. return CopyLowBits(buf, maxbytes, &t, sizeof(t));
  134.     }
  135.     return 0;
  136. }
  137. #else /* SunOS (Sun, but not SVR4) */
  138. #include <sys/wait.h>
  139. extern long sysconf(int name);
  140. static size_t
  141. GetHighResClock(void *buf, size_t maxbytes)
  142. {
  143.     return 0;
  144. }
  145. static void
  146. GiveSystemInfo(void)
  147. {
  148.     long si;
  149.     /* This is not very good */
  150.     si = sysconf(_SC_CHILD_MAX);
  151.     RNG_RandomUpdate(&si, sizeof(si));
  152. }
  153. #endif
  154. #endif /* Sun */
  155. #if defined(__hpux)
  156. #include <sys/unistd.h>
  157. #include <sys/wait.h>
  158. #define getdtablesize() sysconf(_SC_OPEN_MAX)
  159. static size_t
  160. GetHighResClock(void *buf, size_t maxbytes)
  161. {
  162.     extern int ret_cr16();
  163.     int cr16val;
  164.     cr16val = ret_cr16();
  165.     return CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val));
  166. }
  167. static void
  168. GiveSystemInfo(void)
  169. {
  170.     long si;
  171.     /* This is not very good */
  172.     si = sysconf(_AES_OS_VERSION);
  173.     RNG_RandomUpdate(&si, sizeof(si));
  174.     si = sysconf(_SC_CPU_VERSION);
  175.     RNG_RandomUpdate(&si, sizeof(si));
  176. }
  177. #endif /* HPUX */
  178. #if defined(OSF1)
  179. #include <sys/types.h>
  180. #include <sys/sysinfo.h>
  181. #include <sys/wait.h>
  182. #include <sys/systeminfo.h>
  183. #include <c_asm.h>
  184. static void
  185. GiveSystemInfo(void)
  186. {
  187.     char buf[BUFSIZ];
  188.     int rv;
  189.     int off = 0;
  190.     rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
  191.     if (rv > 0) {
  192. RNG_RandomUpdate(buf, rv);
  193.     }
  194.     rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
  195.     if (rv > 0) {
  196. RNG_RandomUpdate(buf, rv);
  197.     }
  198.     rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
  199.     if (rv > 0) {
  200. RNG_RandomUpdate(buf, rv);
  201.     }
  202. }
  203. /*
  204.  * Use the "get the cycle counter" instruction on the alpha.
  205.  * The low 32 bits completely turn over in less than a minute.
  206.  * The high 32 bits are some non-counter gunk that changes sometimes.
  207.  */
  208. static size_t
  209. GetHighResClock(void *buf, size_t maxbytes)
  210. {
  211.     unsigned long t;
  212.     t = asm("rpcc %v0");
  213.     return CopyLowBits(buf, maxbytes, &t, sizeof(t));
  214. }
  215. #endif /* Alpha */
  216. #if defined(_IBMR2)
  217. static size_t
  218. GetHighResClock(void *buf, size_t maxbytes)
  219. {
  220.     return 0;
  221. }
  222. static void
  223. GiveSystemInfo(void)
  224. {
  225.     /* XXX haven't found any yet! */
  226. }
  227. #endif /* IBM R2 */
  228. #if defined(__linux)
  229. #include <linux/kernel.h>
  230. static size_t
  231. GetHighResClock(void *buf, size_t maxbytes)
  232. {
  233.     return 0;
  234. }
  235. static void
  236. GiveSystemInfo(void)
  237. {
  238.     /* XXX sysinfo() does not seem be implemented anywhwere */
  239. #if 0
  240.     struct sysinfo si;
  241.     char hn[2000];
  242.     if (sysinfo(&si) == 0) {
  243. RNG_RandomUpdate(&si, sizeof(si));
  244.     }
  245. #endif
  246. }
  247. #endif /* __linux */
  248. #if defined(NCR)
  249. #include <sys/utsname.h>
  250. #include <sys/systeminfo.h>
  251. #define getdtablesize() sysconf(_SC_OPEN_MAX)
  252. static size_t
  253. GetHighResClock(void *buf, size_t maxbytes)
  254. {
  255.     return 0;
  256. }
  257. static void
  258. GiveSystemInfo(void)
  259. {
  260.     int rv;
  261.     char buf[2000];
  262.     rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
  263.     if (rv > 0) {
  264. RNG_RandomUpdate(buf, rv);
  265.     }
  266.     rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
  267.     if (rv > 0) {
  268. RNG_RandomUpdate(buf, rv);
  269.     }
  270.     rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
  271.     if (rv > 0) {
  272. RNG_RandomUpdate(buf, rv);
  273.     }
  274. }
  275. #endif /* NCR */
  276. #if defined(sgi)
  277. #include <fcntl.h>
  278. #undef PRIVATE
  279. #include <sys/mman.h>
  280. #include <sys/syssgi.h>
  281. #include <sys/immu.h>
  282. #include <sys/systeminfo.h>
  283. #include <sys/utsname.h>
  284. #include <wait.h>
  285. static void
  286. GiveSystemInfo(void)
  287. {
  288.     int rv;
  289.     char buf[4096];
  290.     rv = syssgi(SGI_SYSID, &buf[0]);
  291.     if (rv > 0) {
  292. RNG_RandomUpdate(buf, MAXSYSIDSIZE);
  293.     }
  294. #ifdef SGI_RDUBLK
  295.     rv = syssgi(SGI_RDUBLK, getpid(), &buf[0], sizeof(buf));
  296.     if (rv > 0) {
  297. RNG_RandomUpdate(buf, sizeof(buf));
  298.     }
  299. #endif /* SGI_RDUBLK */
  300.     rv = syssgi(SGI_INVENT, SGI_INV_READ, buf, sizeof(buf));
  301.     if (rv > 0) {
  302. RNG_RandomUpdate(buf, sizeof(buf));
  303.     }
  304.     rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
  305.     if (rv > 0) {
  306. RNG_RandomUpdate(buf, rv);
  307.     }
  308.     rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
  309.     if (rv > 0) {
  310. RNG_RandomUpdate(buf, rv);
  311.     }
  312.     rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
  313.     if (rv > 0) {
  314. RNG_RandomUpdate(buf, rv);
  315.     }
  316. }
  317. static size_t GetHighResClock(void *buf, size_t maxbuf)
  318. {
  319.     unsigned phys_addr, raddr, cycleval;
  320.     static volatile unsigned *iotimer_addr = NULL;
  321.     static int tries = 0;
  322.     static int cntr_size;
  323.     int mfd;
  324.     long s0[2];
  325.     struct timeval tv;
  326. #ifndef SGI_CYCLECNTR_SIZE
  327. #define SGI_CYCLECNTR_SIZE      165     /* Size user needs to use to read CC */
  328. #endif
  329.     if (iotimer_addr == NULL) {
  330. if (tries++ > 1) {
  331.     /* Don't keep trying if it didn't work */
  332.     return 0;
  333. }
  334. /*
  335. ** For SGI machines we can use the cycle counter, if it has one,
  336. ** to generate some truly random numbers
  337. */
  338. phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
  339. if (phys_addr) {
  340.     int pgsz = getpagesize();
  341.     int pgoffmask = pgsz - 1;
  342.     raddr = phys_addr & ~pgoffmask;
  343.     mfd = open("/dev/mmem", O_RDONLY);
  344.     if (mfd < 0) {
  345. return 0;
  346.     }
  347.     iotimer_addr = (unsigned *)
  348. mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
  349.     if (iotimer_addr == (void*)-1) {
  350. close(mfd);
  351. iotimer_addr = NULL;
  352. return 0;
  353.     }
  354.     iotimer_addr = (unsigned*)
  355. ((__psint_t)iotimer_addr | (phys_addr & pgoffmask));
  356.     /*
  357.      * The file 'mfd' is purposefully not closed.
  358.      */
  359.     cntr_size = syssgi(SGI_CYCLECNTR_SIZE);
  360.     if (cntr_size < 0) {
  361. struct utsname utsinfo;
  362. /* 
  363.  * We must be executing on a 6.0 or earlier system, since the
  364.  * SGI_CYCLECNTR_SIZE call is not supported.
  365.  * 
  366.  * The only pre-6.1 platforms with 64-bit counters are
  367.  * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
  368.  */
  369. uname(&utsinfo);
  370. if (!strncmp(utsinfo.machine, "IP19", 4) ||
  371.     !strncmp(utsinfo.machine, "IP21", 4))
  372. cntr_size = 64;
  373. else
  374. cntr_size = 32;
  375.     }
  376.     cntr_size /= 8; /* Convert from bits to bytes */
  377. }
  378.     }
  379.     s0[0] = *iotimer_addr;
  380.     if (cntr_size > 4)
  381. s0[1] = *(iotimer_addr + 1);
  382.     memcpy(buf, (char *)&s0[0], cntr_size);
  383.     return CopyLowBits(buf, maxbuf, &s0, cntr_size);
  384. }
  385. #endif
  386. #if defined(sony)
  387. #include <sys/systeminfo.h>
  388. #define getdtablesize() sysconf(_SC_OPEN_MAX)
  389. static size_t
  390. GetHighResClock(void *buf, size_t maxbytes)
  391. {
  392.     return 0;
  393. }
  394. static void
  395. GiveSystemInfo(void)
  396. {
  397.     int rv;
  398.     char buf[2000];
  399.     rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
  400.     if (rv > 0) {
  401. RNG_RandomUpdate(buf, rv);
  402.     }
  403.     rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
  404.     if (rv > 0) {
  405. RNG_RandomUpdate(buf, rv);
  406.     }
  407.     rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
  408.     if (rv > 0) {
  409. RNG_RandomUpdate(buf, rv);
  410.     }
  411. }
  412. #endif /* sony */
  413. #if defined(sinix)
  414. #include <unistd.h>
  415. #include <sys/systeminfo.h>
  416. #include <sys/times.h>
  417. int gettimeofday(struct timeval *, struct timezone *);
  418. int gethostname(char *, int);
  419. #define getdtablesize() sysconf(_SC_OPEN_MAX)
  420. static size_t
  421. GetHighResClock(void *buf, size_t maxbytes)
  422. {
  423.     int ticks;
  424.     struct tms buffer;
  425.     ticks=times(&buffer);
  426.     return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
  427. }
  428. static void
  429. GiveSystemInfo(void)
  430. {
  431.     int rv;
  432.     char buf[2000];
  433.     rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
  434.     if (rv > 0) {
  435. RNG_RandomUpdate(buf, rv);
  436.     }
  437.     rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
  438.     if (rv > 0) {
  439. RNG_RandomUpdate(buf, rv);
  440.     }
  441.     rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
  442.     if (rv > 0) {
  443. RNG_RandomUpdate(buf, rv);
  444.     }
  445. }
  446. #endif /* sinix */
  447. #if defined(nec_ews)
  448. #include <sys/systeminfo.h>
  449. #define getdtablesize() sysconf(_SC_OPEN_MAX)
  450. static size_t
  451. GetHighResClock(void *buf, size_t maxbytes)
  452. {
  453.     return 0;
  454. }
  455. static void
  456. GiveSystemInfo(void)
  457. {
  458.     int rv;
  459.     char buf[2000];
  460.     rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
  461.     if (rv > 0) {
  462. RNG_RandomUpdate(buf, rv);
  463.     }
  464.     rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
  465.     if (rv > 0) {
  466. RNG_RandomUpdate(buf, rv);
  467.     }
  468.     rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
  469.     if (rv > 0) {
  470. RNG_RandomUpdate(buf, rv);
  471.     }
  472. }
  473. #endif /* nec_ews */
  474. size_t RNG_GetNoise(void *buf, size_t maxbytes)
  475. {
  476.     struct timeval tv;
  477.     int n = 0;
  478.     int c;
  479.     n = GetHighResClock(buf, maxbytes);
  480.     maxbytes -= n;
  481. #if defined(__sun) && (defined(_svr4) || defined(SVR4)) || defined(sony)
  482.     (void)gettimeofday(&tv);
  483. #else
  484.     (void)gettimeofday(&tv, 0);
  485. #endif
  486.     c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_usec, sizeof(tv.tv_usec));
  487.     n += c;
  488.     maxbytes -= c;
  489.     c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_sec, sizeof(tv.tv_sec));
  490.     n += c;
  491.     return n;
  492. }
  493. #define SAFE_POPEN_MAXARGS 10 /* must be at least 2 */
  494. /*
  495.  * safe_popen is static to this module and we know what arguments it is
  496.  * called with. Note that this version only supports a single open child
  497.  * process at any time.
  498.  */
  499. static pid_t safe_popen_pid;
  500. static struct sigaction oldact;
  501. static FILE *
  502. safe_popen(char *cmd)
  503. {
  504.     int p[2], fd, argc;
  505.     pid_t pid;
  506.     char *argv[SAFE_POPEN_MAXARGS + 1];
  507.     FILE *fp;
  508.     static char blank[] = " t";
  509.     static struct sigaction newact;
  510.     if (pipe(p) < 0)
  511. return 0;
  512.     /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
  513.     newact.sa_handler = SIG_DFL;
  514.     newact.sa_flags = 0;
  515.     sigfillset(&newact.sa_mask);
  516.     sigaction (SIGCHLD, &newact, &oldact);
  517.     pid = fork();
  518.     switch (pid) {
  519.       case -1:
  520. close(p[0]);
  521. close(p[1]);
  522. sigaction (SIGCHLD, &oldact, NULL);
  523. return 0;
  524.       case 0:
  525. /* dup write-side of pipe to stderr and stdout */
  526. if (p[1] != 1) dup2(p[1], 1);
  527. if (p[1] != 2) dup2(p[1], 2);
  528. close(0);
  529. for (fd = getdtablesize(); --fd > 2; close(fd))
  530.     ;
  531. /* clean up environment in the child process */
  532. putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc");
  533. putenv("SHELL=/bin/sh");
  534. putenv("IFS= t");
  535. /*
  536.  * The caller may have passed us a string that is in text
  537.  * space. It may be illegal to modify the string
  538.  */
  539. cmd = strdup(cmd);
  540. /* format argv */
  541. argv[0] = strtok(cmd, blank);
  542. argc = 1;
  543. while ((argv[argc] = strtok(0, blank)) != 0) {
  544.     if (++argc == SAFE_POPEN_MAXARGS) {
  545. argv[argc] = 0;
  546. break;
  547.     }
  548. }
  549. /* and away we go */
  550. execvp(argv[0], argv);
  551. exit(127);
  552. break;
  553.       default:
  554. close(p[1]);
  555. fp = fdopen(p[0], "r");
  556. if (fp == 0) {
  557.     close(p[0]);
  558.     sigaction (SIGCHLD, &oldact, NULL);
  559.     return 0;
  560. }
  561. break;
  562.     }
  563.     /* non-zero means there's a cmd running */
  564.     safe_popen_pid = pid;
  565.     return fp;
  566. }
  567. static int
  568. safe_pclose(FILE *fp)
  569. {
  570.     pid_t pid;
  571.     int count, status;
  572.     if ((pid = safe_popen_pid) == 0)
  573. return -1;
  574.     safe_popen_pid = 0;
  575.     /* if the child hasn't exited, kill it -- we're done with its output */
  576.     count = 0;
  577.     while (waitpid(pid, &status, WNOHANG) == 0) {
  578.      if (kill(pid, SIGKILL) < 0 && errno == ESRCH)
  579.     break;
  580. if (++count == 1000)
  581.     break;
  582.     }
  583.     /* Reset SIGCHLD signal hander before returning */
  584.     sigaction(SIGCHLD, &oldact, NULL);
  585.     fclose(fp);
  586.     return status;
  587. }
  588. void RNG_SystemInfoForRNG(void)
  589. {
  590.     FILE *fp;
  591.     char buf[BUFSIZ];
  592.     size_t bytes;
  593.     extern char **environ;
  594.     char **cp;
  595.     char *randfile;
  596.     char *files[] = {
  597. "/etc/passwd",
  598. "/etc/utmp",
  599. "/tmp",
  600. "/var/tmp",
  601. "/usr/tmp",
  602. 0
  603.     };
  604. #ifdef DO_PS
  605. For now it is considered that it is too expensive to run the ps command
  606. for the small amount of entropy it provides.
  607. #if defined(__sun) && (!defined(__svr4) && !defined(SVR4)) || defined(bsdi) || defined(__linux)
  608.     static char ps_cmd[] = "ps aux";
  609. #else
  610.     static char ps_cmd[] = "ps -el";
  611. #endif
  612. #endif /* DO_PS */
  613.     static char netstat_ni_cmd[] = "netstat -ni";
  614.     GiveSystemInfo();
  615.     bytes = RNG_GetNoise(buf, sizeof(buf));
  616.     RNG_RandomUpdate(buf, bytes);
  617. #ifdef DO_PS
  618.     fp = safe_popen(ps_cmd);
  619.     if (fp != NULL) {
  620. while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
  621.     RNG_RandomUpdate(buf, bytes);
  622. safe_pclose(fp);
  623.     }
  624. #endif
  625.     fp = safe_popen(netstat_ni_cmd);
  626.     if (fp != NULL) {
  627. while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
  628.     RNG_RandomUpdate(buf, bytes);
  629. safe_pclose(fp);
  630.     }
  631.     /*
  632.      * Pass the C environment and the addresses of the pointers to the
  633.      * hash function. This makes the random number function depend on the
  634.      * execution environment of the user and on the platform the program
  635.      * is running on.
  636.      */
  637.     cp = environ;
  638.     while (*cp) {
  639. RNG_RandomUpdate(*cp, strlen(*cp));
  640. cp++;
  641.     }
  642.     RNG_RandomUpdate(environ, (char*)cp - (char*)environ);
  643.     /* Give in system information */
  644.     if (gethostname(buf, sizeof(buf)) > 0) {
  645. RNG_RandomUpdate(buf, strlen(buf));
  646.     }
  647.     GiveSystemInfo();
  648.     /* If the user points us to a random file, pass it through the rng */
  649.     randfile = getenv("NSRANDFILE");
  650.     if ( ( randfile != NULL ) && ( randfile[0] != '') ) {
  651. RNG_FileForRNG(randfile);
  652.     }
  653.     /* pass other files through */
  654.     for (cp = files; *cp; cp++)
  655. RNG_FileForRNG(*cp);
  656. }
  657. void RNG_FileForRNG(char *fileName)
  658. {
  659.     struct stat stat_buf;
  660.     unsigned char buffer[BUFSIZ];
  661.     size_t bytes;
  662.     FILE *file;
  663.     static size_t totalFileBytes = 0;
  664.     
  665.     if (stat((char *)fileName, &stat_buf) < 0)
  666. return;
  667.     RNG_RandomUpdate(&stat_buf, sizeof(stat_buf));
  668.     
  669.     file = fopen((char *)fileName, "r");
  670.     if (file != NULL) {
  671. for (;;) {
  672.     bytes = fread(buffer, 1, sizeof(buffer), file);
  673.     if (bytes == 0) break;
  674.     RNG_RandomUpdate(buffer, bytes);
  675.     totalFileBytes += bytes;
  676.     if (totalFileBytes > 1024*1024) break;
  677. }
  678. fclose(file);
  679.     }
  680.     /*
  681.      * Pass yet another snapshot of our highest resolution clock into
  682.      * the hash function.
  683.      */
  684.     bytes = RNG_GetNoise(buffer, sizeof(buffer));
  685.     RNG_RandomUpdate(buffer, bytes);
  686. }