1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
53 size_t RNG_FileUpdate(const char *fileName, size_t limit);
56 * When copying data to the buffer we want the least signicant bytes
57 * from the input since those bits are changing the fastest. The address
58 * of least significant byte depends upon whether we are running on
59 * a big-endian or little-endian machine.
61 * Does this mean the least signicant bytes are the most significant
65 static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
72 if (srclen <= dstlen) {
73 memcpy(dst, src, srclen);
79 memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
81 /* little-endian case */
82 memcpy(dst, src, dstlen);
91 static const PRUint32 entropy_buf_len = 4096; /* buffer up to 4 KB */
93 /* Buffer entropy data, and feed it to the RNG, entropy_buf_len bytes at a time.
94 * Returns error if RNG_RandomUpdate fails. Also increments *total_fed
95 * by the number of bytes successfully buffered.
97 static SECStatus BufferEntropy(char* inbuf, PRUint32 inlen,
98 char* entropy_buf, PRUint32* entropy_buffered,
103 SECStatus rv = SECSuccess;
106 avail = entropy_buf_len - *entropy_buffered;
108 /* Buffer is full, time to feed it to the RNG. */
109 rv = RNG_RandomUpdate(entropy_buf, entropy_buf_len);
110 if (SECSuccess != rv) {
113 *entropy_buffered = 0;
114 avail = entropy_buf_len;
116 tocopy = PR_MIN(avail, inlen);
117 memcpy(entropy_buf + *entropy_buffered, inbuf, tocopy);
118 *entropy_buffered += tocopy;
121 *total_fed += tocopy;
126 /* Feed kernel statistics structures and ks_data field to the RNG.
127 * Returns status as well as the number of bytes successfully fed to the RNG.
129 static SECStatus RNG_kstat(PRUint32* fed)
131 kstat_ctl_t* kc = NULL;
133 PRUint32 entropy_buffered = 0;
134 char* entropy_buf = NULL;
135 SECStatus rv = SECSuccess;
148 entropy_buf = (char*) PORT_Alloc(entropy_buf_len);
149 PORT_Assert(entropy_buf);
151 for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
152 if (-1 == kstat_read(kc, ksp, NULL)) {
153 /* missing data from a single kstat shouldn't be fatal */
156 rv = BufferEntropy((char*)ksp, sizeof(kstat_t),
157 entropy_buf, &entropy_buffered,
159 if (SECSuccess != rv) {
163 if (ksp->ks_data && ksp->ks_data_size>0 && ksp->ks_ndata>0) {
164 rv = BufferEntropy((char*)ksp->ks_data, ksp->ks_data_size,
165 entropy_buf, &entropy_buffered,
167 if (SECSuccess != rv) {
172 if (SECSuccess == rv && entropy_buffered) {
173 /* Buffer is not empty, time to feed it to the RNG */
174 rv = RNG_RandomUpdate(entropy_buf, entropy_buffered);
176 PORT_Free(entropy_buf);
180 if (kstat_close(kc)) {
189 #if defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(FREEBSD) \
190 || defined(NETBSD) || defined(DARWIN) || defined(OPENBSD) \
191 || defined(NTO) || defined(__riscos__)
192 #include <sys/times.h>
194 #define getdtablesize() sysconf(_SC_OPEN_MAX)
197 GetHighResClock(void *buf, size_t maxbytes)
202 ticks=times(&buffer);
203 return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
212 * Is this really necessary? Why not use rand48 or something?
214 si = sysconf(_SC_CHILD_MAX);
215 RNG_RandomUpdate(&si, sizeof(si));
217 si = sysconf(_SC_STREAM_MAX);
218 RNG_RandomUpdate(&si, sizeof(si));
220 si = sysconf(_SC_OPEN_MAX);
221 RNG_RandomUpdate(&si, sizeof(si));
226 #if defined(__svr4) || defined(SVR4)
227 #include <sys/systeminfo.h>
228 #include <sys/times.h>
231 int gettimeofday(struct timeval *);
232 int gethostname(char *, int);
234 #define getdtablesize() sysconf(_SC_OPEN_MAX)
242 rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
244 RNG_RandomUpdate(buf, rv);
246 rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
248 RNG_RandomUpdate(buf, rv);
250 rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
252 RNG_RandomUpdate(buf, rv);
257 GetHighResClock(void *buf, size_t maxbytes)
262 return CopyLowBits(buf, maxbytes, &t, sizeof(t));
266 #else /* SunOS (Sun, but not SVR4) */
268 extern long sysconf(int name);
271 GetHighResClock(void *buf, size_t maxbytes)
281 /* This is not very good */
282 si = sysconf(_SC_CHILD_MAX);
283 RNG_RandomUpdate(&si, sizeof(si));
289 #include <sys/unistd.h>
291 #define getdtablesize() sysconf(_SC_OPEN_MAX)
294 #include <ia64/sys/inline.h>
297 GetHighResClock(void *buf, size_t maxbytes)
301 t = _Asm_mov_from_ar(_AREG44);
302 return CopyLowBits(buf, maxbytes, &t, sizeof(t));
306 GetHighResClock(void *buf, size_t maxbytes)
308 extern int ret_cr16();
311 cr16val = ret_cr16();
312 return CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val));
321 /* This is not very good */
322 si = sysconf(_AES_OS_VERSION);
323 RNG_RandomUpdate(&si, sizeof(si));
324 si = sysconf(_SC_CPU_VERSION);
325 RNG_RandomUpdate(&si, sizeof(si));
330 #include <sys/types.h>
331 #include <sys/sysinfo.h>
332 #include <sys/systeminfo.h>
342 rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
344 RNG_RandomUpdate(buf, rv);
346 rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
348 RNG_RandomUpdate(buf, rv);
350 rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
352 RNG_RandomUpdate(buf, rv);
357 * Use the "get the cycle counter" instruction on the alpha.
358 * The low 32 bits completely turn over in less than a minute.
359 * The high 32 bits are some non-counter gunk that changes sometimes.
362 GetHighResClock(void *buf, size_t maxbytes)
367 return CopyLowBits(buf, maxbytes, &t, sizeof(t));
374 GetHighResClock(void *buf, size_t maxbytes)
382 /* XXX haven't found any yet! */
387 #include <sys/sysinfo.h>
390 GetHighResClock(void *buf, size_t maxbytes)
399 if (sysinfo(&si) == 0) {
400 RNG_RandomUpdate(&si, sizeof(si));
407 #include <sys/utsname.h>
408 #include <sys/systeminfo.h>
410 #define getdtablesize() sysconf(_SC_OPEN_MAX)
413 GetHighResClock(void *buf, size_t maxbytes)
424 rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
426 RNG_RandomUpdate(buf, rv);
428 rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
430 RNG_RandomUpdate(buf, rv);
432 rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
434 RNG_RandomUpdate(buf, rv);
443 #include <sys/mman.h>
444 #include <sys/syssgi.h>
445 #include <sys/immu.h>
446 #include <sys/systeminfo.h>
447 #include <sys/utsname.h>
456 rv = syssgi(SGI_SYSID, &buf[0]);
458 RNG_RandomUpdate(buf, MAXSYSIDSIZE);
461 rv = syssgi(SGI_RDUBLK, getpid(), &buf[0], sizeof(buf));
463 RNG_RandomUpdate(buf, sizeof(buf));
465 #endif /* SGI_RDUBLK */
466 rv = syssgi(SGI_INVENT, SGI_INV_READ, buf, sizeof(buf));
468 RNG_RandomUpdate(buf, sizeof(buf));
470 rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
472 RNG_RandomUpdate(buf, rv);
474 rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
476 RNG_RandomUpdate(buf, rv);
478 rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
480 RNG_RandomUpdate(buf, rv);
484 static size_t GetHighResClock(void *buf, size_t maxbuf)
486 unsigned phys_addr, raddr, cycleval;
487 static volatile unsigned *iotimer_addr = NULL;
488 static int tries = 0;
489 static int cntr_size;
494 #ifndef SGI_CYCLECNTR_SIZE
495 #define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */
498 if (iotimer_addr == NULL) {
500 /* Don't keep trying if it didn't work */
505 ** For SGI machines we can use the cycle counter, if it has one,
506 ** to generate some truly random numbers
508 phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
510 int pgsz = getpagesize();
511 int pgoffmask = pgsz - 1;
513 raddr = phys_addr & ~pgoffmask;
514 mfd = open("/dev/mmem", O_RDONLY);
518 iotimer_addr = (unsigned *)
519 mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
520 if (iotimer_addr == (void*)-1) {
525 iotimer_addr = (unsigned*)
526 ((__psint_t)iotimer_addr | (phys_addr & pgoffmask));
528 * The file 'mfd' is purposefully not closed.
530 cntr_size = syssgi(SGI_CYCLECNTR_SIZE);
532 struct utsname utsinfo;
535 * We must be executing on a 6.0 or earlier system, since the
536 * SGI_CYCLECNTR_SIZE call is not supported.
538 * The only pre-6.1 platforms with 64-bit counters are
539 * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
542 if (!strncmp(utsinfo.machine, "IP19", 4) ||
543 !strncmp(utsinfo.machine, "IP21", 4))
548 cntr_size /= 8; /* Convert from bits to bytes */
552 s0[0] = *iotimer_addr;
554 s0[1] = *(iotimer_addr + 1);
555 memcpy(buf, (char *)&s0[0], cntr_size);
556 return CopyLowBits(buf, maxbuf, &s0, cntr_size);
561 #include <sys/systeminfo.h>
563 #define getdtablesize() sysconf(_SC_OPEN_MAX)
566 GetHighResClock(void *buf, size_t maxbytes)
577 rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
579 RNG_RandomUpdate(buf, rv);
581 rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
583 RNG_RandomUpdate(buf, rv);
585 rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
587 RNG_RandomUpdate(buf, rv);
593 #include <sys/systeminfo.h>
594 #include <sys/times.h>
596 int gettimeofday(struct timeval *, struct timezone *);
597 int gethostname(char *, int);
599 #define getdtablesize() sysconf(_SC_OPEN_MAX)
602 GetHighResClock(void *buf, size_t maxbytes)
607 ticks=times(&buffer);
608 return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
617 rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
619 RNG_RandomUpdate(buf, rv);
621 rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
623 RNG_RandomUpdate(buf, rv);
625 rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
627 RNG_RandomUpdate(buf, rv);
634 #include <be/kernel/OS.h>
637 GetHighResClock(void *buf, size_t maxbytes)
639 bigtime_t bigtime; /* Actually an int64 */
641 bigtime = real_time_clock_usecs();
642 return CopyLowBits(buf, maxbytes, &bigtime, sizeof(bigtime));
648 system_info *info = NULL;
650 get_system_info(info);
652 val = info->boot_time;
653 RNG_RandomUpdate(&val, sizeof(val));
654 val = info->used_pages;
655 RNG_RandomUpdate(&val, sizeof(val));
656 val = info->used_ports;
657 RNG_RandomUpdate(&val, sizeof(val));
658 val = info->used_threads;
659 RNG_RandomUpdate(&val, sizeof(val));
660 val = info->used_teams;
661 RNG_RandomUpdate(&val, sizeof(val));
667 #include <sys/systeminfo.h>
669 #define getdtablesize() sysconf(_SC_OPEN_MAX)
672 GetHighResClock(void *buf, size_t maxbytes)
683 rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
685 RNG_RandomUpdate(buf, rv);
687 rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
689 RNG_RandomUpdate(buf, rv);
691 rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
693 RNG_RandomUpdate(buf, rv);
698 size_t RNG_GetNoise(void *buf, size_t maxbytes)
704 n = GetHighResClock(buf, maxbytes);
707 #if defined(__sun) && (defined(_svr4) || defined(SVR4)) || defined(sony)
708 (void)gettimeofday(&tv);
710 (void)gettimeofday(&tv, 0);
712 c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_usec, sizeof(tv.tv_usec));
715 c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_sec, sizeof(tv.tv_sec));
720 #define SAFE_POPEN_MAXARGS 10 /* must be at least 2 */
723 * safe_popen is static to this module and we know what arguments it is
724 * called with. Note that this version only supports a single open child
725 * process at any time.
727 static pid_t safe_popen_pid;
728 static struct sigaction oldact;
731 safe_popen(char *cmd)
735 char *argv[SAFE_POPEN_MAXARGS + 1];
737 static char blank[] = " \t";
738 static struct sigaction newact;
743 fp = fdopen(p[0], "r");
750 /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
751 newact.sa_handler = SIG_DFL;
753 sigfillset(&newact.sa_mask);
754 sigaction (SIGCHLD, &newact, &oldact);
761 fclose(fp); /* this closes p[0], the fd associated with fp */
763 sigaction (SIGCHLD, &oldact, NULL);
767 /* dup write-side of pipe to stderr and stdout */
768 if (p[1] != 1) dup2(p[1], 1);
769 if (p[1] != 2) dup2(p[1], 2);
772 * close the other file descriptors, except stdin which we
773 * try reassociating with /dev/null, first (bug 174993)
775 if (!freopen("/dev/null", "r", stdin))
777 ndesc = getdtablesize();
778 for (fd = PR_MIN(65536, ndesc); --fd > 2; close(fd));
780 /* clean up environment in the child process */
781 putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc");
782 putenv("SHELL=/bin/sh");
786 * The caller may have passed us a string that is in text
787 * space. It may be illegal to modify the string
791 argv[0] = strtok(cmd, blank);
793 while ((argv[argc] = strtok(0, blank)) != 0) {
794 if (++argc == SAFE_POPEN_MAXARGS) {
801 execvp(argv[0], argv);
810 /* non-zero means there's a cmd running */
811 safe_popen_pid = pid;
816 safe_pclose(FILE *fp)
821 if ((pid = safe_popen_pid) == 0)
827 /* yield the processor so the child gets some time to exit normally */
828 PR_Sleep(PR_INTERVAL_NO_WAIT);
830 /* if the child hasn't exited, kill it -- we're done with its output */
831 while ((rv = waitpid(pid, &status, WNOHANG)) == -1 && errno == EINTR)
835 while ((rv = waitpid(pid, &status, 0)) == -1 && errno == EINTR)
839 /* Reset SIGCHLD signal hander before returning */
840 sigaction(SIGCHLD, &oldact, NULL);
846 #include <TargetConditionals.h>
847 #if !TARGET_OS_IPHONE
848 #include <crt_externs.h>
852 /* Fork netstat to collect its output by default. Do not unset this unless
853 * another source of entropy is available
857 void RNG_SystemInfoForRNG(void)
862 const char * const *cp;
866 /* iOS does not expose a way to access environ. */
867 char **environ = NULL;
869 char **environ = *_NSGetEnviron();
872 extern char **environ;
875 static const char * const files[] = {
877 "/boot/var/log/syslog",
879 "/boot/home/config/settings",
884 static const char * const files[] = {
895 static char netstat_ni_cmd[] = "netstat -nis";
897 static char netstat_ni_cmd[] = "netstat -ni";
902 bytes = RNG_GetNoise(buf, sizeof(buf));
903 RNG_RandomUpdate(buf, bytes);
906 * Pass the C environment and the addresses of the pointers to the
907 * hash function. This makes the random number function depend on the
908 * execution environment of the user and on the platform the program
911 if (environ != NULL) {
912 cp = (const char * const *) environ;
914 RNG_RandomUpdate(*cp, strlen(*cp));
917 RNG_RandomUpdate(environ, (char*)cp - (char*)environ);
920 /* Give in system information */
921 if (gethostname(buf, sizeof(buf)) == 0) {
922 RNG_RandomUpdate(buf, strlen(buf));
926 /* grab some data from system's PRNG before any other files. */
927 bytes = RNG_FileUpdate("/dev/urandom", SYSTEM_RNG_SEED_COUNT);
929 /* If the user points us to a random file, pass it through the rng */
930 randfile = getenv("NSRANDFILE");
931 if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {
932 char *randCountString = getenv("NSRANDCOUNT");
933 int randCount = randCountString ? atoi(randCountString) : 0;
934 if (randCount != 0) {
935 RNG_FileUpdate(randfile, randCount);
937 RNG_FileForRNG(randfile);
941 /* pass other files through */
942 for (cp = files; *cp; cp++)
946 * Bug 100447: On BSD/OS 4.2 and 4.3, we have problem calling safe_popen
947 * in a pthreads environment. Therefore, we call safe_popen last and on
948 * BSD/OS we do not call safe_popen when we succeeded in getting data
951 * Bug 174993: On platforms providing /dev/urandom, don't fork netstat
952 * either, if data has been gathered successfully.
955 #if defined(BSDI) || defined(FREEBSD) || defined(NETBSD) \
956 || defined(OPENBSD) || defined(DARWIN) || defined(LINUX) \
965 * On Solaris, NSS may be initialized automatically from libldap in
966 * applications that are unaware of the use of NSS. safe_popen forks, and
967 * sometimes creates issues with some applications' pthread_atfork handlers.
968 * We always have /dev/urandom on Solaris 9 and above as an entropy source,
969 * and for Solaris 8 we have the libkstat interface, so we don't need to
975 /* On Solaris 8, /dev/urandom isn't available, so we use libkstat. */
976 PRUint32 kstat_bytes = 0;
977 if (SECSuccess != RNG_kstat(&kstat_bytes)) {
980 bytes += kstat_bytes;
986 fp = safe_popen(netstat_ni_cmd);
988 while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
989 RNG_RandomUpdate(buf, bytes);
996 #define TOTAL_FILE_LIMIT 1000000 /* one million */
998 size_t RNG_FileUpdate(const char *fileName, size_t limit)
1002 size_t fileBytes = 0;
1003 struct stat stat_buf;
1004 unsigned char buffer[BUFSIZ];
1005 static size_t totalFileBytes = 0;
1007 /* suppress valgrind warnings due to holes in struct stat */
1008 memset(&stat_buf, 0, sizeof(stat_buf));
1010 if (stat((char *)fileName, &stat_buf) < 0)
1012 RNG_RandomUpdate(&stat_buf, sizeof(stat_buf));
1014 file = fopen((char *)fileName, "r");
1016 while (limit > fileBytes) {
1017 bytes = PR_MIN(sizeof buffer, limit - fileBytes);
1018 bytes = fread(buffer, 1, bytes, file);
1021 RNG_RandomUpdate(buffer, bytes);
1023 totalFileBytes += bytes;
1024 /* after TOTAL_FILE_LIMIT has been reached, only read in first
1025 ** buffer of data from each subsequent file.
1027 if (totalFileBytes > TOTAL_FILE_LIMIT)
1033 * Pass yet another snapshot of our highest resolution clock into
1034 * the hash function.
1036 bytes = RNG_GetNoise(buffer, sizeof(buffer));
1037 RNG_RandomUpdate(buffer, bytes);
1041 void RNG_FileForRNG(const char *fileName)
1043 RNG_FileUpdate(fileName, TOTAL_FILE_LIMIT);
1046 void ReadSingleFile(const char *fileName)
1049 unsigned char buffer[BUFSIZ];
1051 file = fopen((char *)fileName, "rb");
1053 while (fread(buffer, 1, sizeof(buffer), file) > 0)
1059 #define _POSIX_PTHREAD_SEMANTICS
1063 ReadFileOK(char *dir, char *file)
1065 struct stat stat_buf;
1066 char filename[PATH_MAX];
1067 int count = snprintf(filename, sizeof filename, "%s/%s",dir, file);
1070 return PR_FALSE; /* name too long, can't read it anyway */
1073 if (stat(filename, &stat_buf) < 0)
1074 return PR_FALSE; /* can't stat, probably can't read it then as well */
1075 return S_ISREG(stat_buf.st_mode) ? PR_TRUE : PR_FALSE;
1079 * read one file out of either /etc or the user's home directory.
1080 * fileToRead tells which file to read.
1082 * return 1 if it's time to reset the fileToRead (no more files to read).
1084 int ReadOneFile(int fileToRead)
1087 DIR *fd = opendir(dir);
1090 /* grumble, Solaris does not define struct dirent to be the full length */
1092 unsigned char space[sizeof(struct dirent) + MAXNAMELEN];
1095 dirent_hack entry, firstEntry;
1097 #define entry_dir entry.dir
1099 struct dirent entry, firstEntry;
1100 #define entry_dir entry
1106 dir = getenv("HOME");
1115 for (i=0; i <= fileToRead; i++) {
1116 struct dirent *result = NULL;
1118 error = readdir_r(fd, &entry_dir, &result);
1119 } while (error == 0 && result != NULL &&
1120 !ReadFileOK(dir,&result->d_name[0]));
1121 if (error != 0 || result == NULL) {
1122 resetCount = 1; /* read to the end, start again at the beginning */
1124 /* ran out of entries in the directory, use the first one */
1129 /* if i== 0, there were no readable entries in the directory */
1133 /* save the first entry in case we run out of entries */
1139 char filename[PATH_MAX];
1140 int count = snprintf(filename, sizeof filename,
1141 "%s/%s",dir, &entry_dir.d_name[0]);
1143 ReadSingleFile(filename);
1152 * do something to try to introduce more noise into the 'GetNoise' call
1154 static void rng_systemJitter(void)
1156 static int fileToRead = 1;
1158 if (ReadOneFile(fileToRead)) {
1165 size_t RNG_SystemRNG(void *dest, size_t maxLen)
1169 size_t fileBytes = 0;
1170 unsigned char *buffer = dest;
1172 file = fopen("/dev/urandom", "r");
1174 return rng_systemFromNoise(dest, maxLen);
1176 while (maxLen > fileBytes) {
1177 bytes = maxLen - fileBytes;
1178 bytes = fread(buffer, 1, bytes, file);
1185 if (fileBytes != maxLen) {
1186 PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */