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 ***** */
50
size_t RNG_FileUpdate(const char *fileName, size_t limit);
53
* When copying data to the buffer we want the least signicant bytes
54
* from the input since those bits are changing the fastest. The address
55
* of least significant byte depends upon whether we are running on
56
* a big-endian or little-endian machine.
58
* Does this mean the least signicant bytes are the most significant
62
static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen)
69
if (srclen <= dstlen) {
70
memcpy(dst, src, srclen);
76
memcpy(dst, (char*)src + (srclen - dstlen), dstlen);
78
/* little-endian case */
79
memcpy(dst, src, dstlen);
88
static const PRUint32 entropy_buf_len = 4096; /* buffer up to 4 KB */
90
/* Buffer entropy data, and feed it to the RNG, entropy_buf_len bytes at a time.
91
* Returns error if RNG_RandomUpdate fails. Also increments *total_fed
92
* by the number of bytes successfully buffered.
94
static SECStatus BufferEntropy(char* inbuf, PRUint32 inlen,
95
char* entropy_buf, PRUint32* entropy_buffered,
100
SECStatus rv = SECSuccess;
103
avail = entropy_buf_len - *entropy_buffered;
105
/* Buffer is full, time to feed it to the RNG. */
106
rv = RNG_RandomUpdate(entropy_buf, entropy_buf_len);
107
if (SECSuccess != rv) {
110
*entropy_buffered = 0;
111
avail = entropy_buf_len;
113
tocopy = PR_MIN(avail, inlen);
114
memcpy(entropy_buf + *entropy_buffered, inbuf, tocopy);
115
*entropy_buffered += tocopy;
118
*total_fed += tocopy;
123
/* Feed kernel statistics structures and ks_data field to the RNG.
124
* Returns status as well as the number of bytes successfully fed to the RNG.
126
static SECStatus RNG_kstat(PRUint32* fed)
128
kstat_ctl_t* kc = NULL;
130
PRUint32 entropy_buffered = 0;
131
char* entropy_buf = NULL;
132
SECStatus rv = SECSuccess;
145
entropy_buf = (char*) PORT_Alloc(entropy_buf_len);
146
PORT_Assert(entropy_buf);
148
for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) {
149
if (-1 == kstat_read(kc, ksp, NULL)) {
150
/* missing data from a single kstat shouldn't be fatal */
153
rv = BufferEntropy((char*)ksp, sizeof(kstat_t),
154
entropy_buf, &entropy_buffered,
156
if (SECSuccess != rv) {
160
if (ksp->ks_data && ksp->ks_data_size>0 && ksp->ks_ndata>0) {
161
rv = BufferEntropy((char*)ksp->ks_data, ksp->ks_data_size,
162
entropy_buf, &entropy_buffered,
164
if (SECSuccess != rv) {
169
if (SECSuccess == rv && entropy_buffered) {
170
/* Buffer is not empty, time to feed it to the RNG */
171
rv = RNG_RandomUpdate(entropy_buf, entropy_buffered);
173
PORT_Free(entropy_buf);
177
if (kstat_close(kc)) {
186
#if defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(FREEBSD) \
187
|| defined(NETBSD) || defined(NTO) || defined(DARWIN) || defined(OPENBSD)
188
#include <sys/times.h>
190
#define getdtablesize() sysconf(_SC_OPEN_MAX)
193
GetHighResClock(void *buf, size_t maxbytes)
198
ticks=times(&buffer);
199
return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
208
* Is this really necessary? Why not use rand48 or something?
210
si = sysconf(_SC_CHILD_MAX);
211
RNG_RandomUpdate(&si, sizeof(si));
213
si = sysconf(_SC_STREAM_MAX);
214
RNG_RandomUpdate(&si, sizeof(si));
216
si = sysconf(_SC_OPEN_MAX);
217
RNG_RandomUpdate(&si, sizeof(si));
222
#if defined(__svr4) || defined(SVR4)
223
#include <sys/systeminfo.h>
224
#include <sys/times.h>
227
int gettimeofday(struct timeval *);
228
int gethostname(char *, int);
230
#define getdtablesize() sysconf(_SC_OPEN_MAX)
238
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
240
RNG_RandomUpdate(buf, rv);
242
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
244
RNG_RandomUpdate(buf, rv);
246
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
248
RNG_RandomUpdate(buf, rv);
253
GetHighResClock(void *buf, size_t maxbytes)
258
return CopyLowBits(buf, maxbytes, &t, sizeof(t));
262
#else /* SunOS (Sun, but not SVR4) */
264
extern long sysconf(int name);
267
GetHighResClock(void *buf, size_t maxbytes)
277
/* This is not very good */
278
si = sysconf(_SC_CHILD_MAX);
279
RNG_RandomUpdate(&si, sizeof(si));
285
#include <sys/unistd.h>
287
#define getdtablesize() sysconf(_SC_OPEN_MAX)
290
#include <ia64/sys/inline.h>
293
GetHighResClock(void *buf, size_t maxbytes)
297
t = _Asm_mov_from_ar(_AREG44);
298
return CopyLowBits(buf, maxbytes, &t, sizeof(t));
302
GetHighResClock(void *buf, size_t maxbytes)
304
extern int ret_cr16();
307
cr16val = ret_cr16();
308
return CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val));
317
/* This is not very good */
318
si = sysconf(_AES_OS_VERSION);
319
RNG_RandomUpdate(&si, sizeof(si));
320
si = sysconf(_SC_CPU_VERSION);
321
RNG_RandomUpdate(&si, sizeof(si));
326
#include <sys/types.h>
327
#include <sys/sysinfo.h>
328
#include <sys/systeminfo.h>
338
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
340
RNG_RandomUpdate(buf, rv);
342
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
344
RNG_RandomUpdate(buf, rv);
346
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
348
RNG_RandomUpdate(buf, rv);
353
* Use the "get the cycle counter" instruction on the alpha.
354
* The low 32 bits completely turn over in less than a minute.
355
* The high 32 bits are some non-counter gunk that changes sometimes.
358
GetHighResClock(void *buf, size_t maxbytes)
363
return CopyLowBits(buf, maxbytes, &t, sizeof(t));
370
GetHighResClock(void *buf, size_t maxbytes)
378
/* XXX haven't found any yet! */
383
#include <sys/sysinfo.h>
386
GetHighResClock(void *buf, size_t maxbytes)
395
if (sysinfo(&si) == 0) {
396
RNG_RandomUpdate(&si, sizeof(si));
403
#include <sys/utsname.h>
404
#include <sys/systeminfo.h>
406
#define getdtablesize() sysconf(_SC_OPEN_MAX)
409
GetHighResClock(void *buf, size_t maxbytes)
420
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
422
RNG_RandomUpdate(buf, rv);
424
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
426
RNG_RandomUpdate(buf, rv);
428
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
430
RNG_RandomUpdate(buf, rv);
440
#include <sys/mman.h>
441
#include <sys/syssgi.h>
442
#include <sys/immu.h>
443
#include <sys/systeminfo.h>
444
#include <sys/utsname.h>
453
rv = syssgi(SGI_SYSID, &buf[0]);
455
RNG_RandomUpdate(buf, MAXSYSIDSIZE);
458
rv = syssgi(SGI_RDUBLK, getpid(), &buf[0], sizeof(buf));
460
RNG_RandomUpdate(buf, sizeof(buf));
462
#endif /* SGI_RDUBLK */
463
rv = syssgi(SGI_INVENT, SGI_INV_READ, buf, sizeof(buf));
465
RNG_RandomUpdate(buf, sizeof(buf));
467
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
469
RNG_RandomUpdate(buf, rv);
471
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
473
RNG_RandomUpdate(buf, rv);
475
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
477
RNG_RandomUpdate(buf, rv);
481
static size_t GetHighResClock(void *buf, size_t maxbuf)
483
unsigned phys_addr, raddr, cycleval;
484
static volatile unsigned *iotimer_addr = NULL;
485
static int tries = 0;
486
static int cntr_size;
491
#ifndef SGI_CYCLECNTR_SIZE
492
#define SGI_CYCLECNTR_SIZE 165 /* Size user needs to use to read CC */
495
if (iotimer_addr == NULL) {
497
/* Don't keep trying if it didn't work */
502
** For SGI machines we can use the cycle counter, if it has one,
503
** to generate some truly random numbers
505
phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
507
int pgsz = getpagesize();
508
int pgoffmask = pgsz - 1;
510
raddr = phys_addr & ~pgoffmask;
511
mfd = open("/dev/mmem", O_RDONLY);
515
iotimer_addr = (unsigned *)
516
mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
517
if (iotimer_addr == (void*)-1) {
522
iotimer_addr = (unsigned*)
523
((__psint_t)iotimer_addr | (phys_addr & pgoffmask));
525
* The file 'mfd' is purposefully not closed.
527
cntr_size = syssgi(SGI_CYCLECNTR_SIZE);
529
struct utsname utsinfo;
532
* We must be executing on a 6.0 or earlier system, since the
533
* SGI_CYCLECNTR_SIZE call is not supported.
535
* The only pre-6.1 platforms with 64-bit counters are
536
* IP19 and IP21 (Challenge, PowerChallenge, Onyx).
539
if (!strncmp(utsinfo.machine, "IP19", 4) ||
540
!strncmp(utsinfo.machine, "IP21", 4))
545
cntr_size /= 8; /* Convert from bits to bytes */
549
s0[0] = *iotimer_addr;
551
s0[1] = *(iotimer_addr + 1);
552
memcpy(buf, (char *)&s0[0], cntr_size);
553
return CopyLowBits(buf, maxbuf, &s0, cntr_size);
558
#include <sys/systeminfo.h>
560
#define getdtablesize() sysconf(_SC_OPEN_MAX)
563
GetHighResClock(void *buf, size_t maxbytes)
574
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
576
RNG_RandomUpdate(buf, rv);
578
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
580
RNG_RandomUpdate(buf, rv);
582
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
584
RNG_RandomUpdate(buf, rv);
590
#include <sys/systeminfo.h>
591
#include <sys/times.h>
593
int gettimeofday(struct timeval *, struct timezone *);
594
int gethostname(char *, int);
596
#define getdtablesize() sysconf(_SC_OPEN_MAX)
599
GetHighResClock(void *buf, size_t maxbytes)
604
ticks=times(&buffer);
605
return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
614
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
616
RNG_RandomUpdate(buf, rv);
618
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
620
RNG_RandomUpdate(buf, rv);
622
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
624
RNG_RandomUpdate(buf, rv);
638
* This is copied from the SCO/UNIXWARE etc section. And like the comment
639
* there says, what's the point? This isn't random, it generates the same
640
* stuff every time its run!
642
si = sysconf(_SC_CHILD_MAX);
643
RNG_RandomUpdate(&si, sizeof(si));
645
si = sysconf(_SC_STREAM_MAX);
646
RNG_RandomUpdate(&si, sizeof(si));
648
si = sysconf(_SC_OPEN_MAX);
649
RNG_RandomUpdate(&si, sizeof(si));
653
* Use the "get the cycle counter" instruction on the alpha.
654
* The low 32 bits completely turn over in less than a minute.
655
* The high 32 bits are some non-counter gunk that changes sometimes.
658
GetHighResClock(void *buf, size_t maxbytes)
663
return CopyLowBits(buf, maxbytes, &t, sizeof(t));
669
#include <be/kernel/OS.h>
672
GetHighResClock(void *buf, size_t maxbytes)
674
bigtime_t bigtime; /* Actually an int64 */
676
bigtime = real_time_clock_usecs();
677
return CopyLowBits(buf, maxbytes, &bigtime, sizeof(bigtime));
683
system_info *info = NULL;
685
get_system_info(info);
687
val = info->boot_time;
688
RNG_RandomUpdate(&val, sizeof(val));
689
val = info->used_pages;
690
RNG_RandomUpdate(&val, sizeof(val));
691
val = info->used_ports;
692
RNG_RandomUpdate(&val, sizeof(val));
693
val = info->used_threads;
694
RNG_RandomUpdate(&val, sizeof(val));
695
val = info->used_teams;
696
RNG_RandomUpdate(&val, sizeof(val));
702
#include <sys/systeminfo.h>
704
#define getdtablesize() sysconf(_SC_OPEN_MAX)
707
GetHighResClock(void *buf, size_t maxbytes)
718
rv = sysinfo(SI_MACHINE, buf, sizeof(buf));
720
RNG_RandomUpdate(buf, rv);
722
rv = sysinfo(SI_RELEASE, buf, sizeof(buf));
724
RNG_RandomUpdate(buf, rv);
726
rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));
728
RNG_RandomUpdate(buf, rv);
733
size_t RNG_GetNoise(void *buf, size_t maxbytes)
739
n = GetHighResClock(buf, maxbytes);
742
#if defined(__sun) && (defined(_svr4) || defined(SVR4)) || defined(sony)
743
(void)gettimeofday(&tv);
745
(void)gettimeofday(&tv, 0);
747
c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_usec, sizeof(tv.tv_usec));
750
c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_sec, sizeof(tv.tv_sec));
755
#define SAFE_POPEN_MAXARGS 10 /* must be at least 2 */
758
* safe_popen is static to this module and we know what arguments it is
759
* called with. Note that this version only supports a single open child
760
* process at any time.
762
static pid_t safe_popen_pid;
763
static struct sigaction oldact;
766
safe_popen(char *cmd)
770
char *argv[SAFE_POPEN_MAXARGS + 1];
772
static char blank[] = " \t";
773
static struct sigaction newact;
778
/* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
779
newact.sa_handler = SIG_DFL;
781
sigfillset(&newact.sa_mask);
782
sigaction (SIGCHLD, &newact, &oldact);
789
sigaction (SIGCHLD, &oldact, NULL);
793
/* dup write-side of pipe to stderr and stdout */
794
if (p[1] != 1) dup2(p[1], 1);
795
if (p[1] != 2) dup2(p[1], 2);
798
int ndesc = getdtablesize();
799
for (fd = PR_MIN(65536, ndesc); --fd > 2; close(fd));
802
/* clean up environment in the child process */
803
putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc");
804
putenv("SHELL=/bin/sh");
808
* The caller may have passed us a string that is in text
809
* space. It may be illegal to modify the string
813
argv[0] = strtok(cmd, blank);
815
while ((argv[argc] = strtok(0, blank)) != 0) {
816
if (++argc == SAFE_POPEN_MAXARGS) {
823
execvp(argv[0], argv);
829
fp = fdopen(p[0], "r");
832
sigaction (SIGCHLD, &oldact, NULL);
838
/* non-zero means there's a cmd running */
839
safe_popen_pid = pid;
844
safe_pclose(FILE *fp)
849
if ((pid = safe_popen_pid) == 0)
853
/* if the child hasn't exited, kill it -- we're done with its output */
855
while (waitpid(pid, &status, WNOHANG) == 0) {
856
if (kill(pid, SIGKILL) < 0 && errno == ESRCH)
862
/* Reset SIGCHLD signal hander before returning */
863
sigaction(SIGCHLD, &oldact, NULL);
873
#include <crt_externs.h>
876
/* Fork netstat to collect its output by default. Do not unset this unless
877
* another source of entropy is available
881
void RNG_SystemInfoForRNG(void)
886
const char * const *cp;
889
char **environ = *_NSGetEnviron();
891
extern char **environ;
894
static const char * const files[] = {
896
"/boot/var/log/syslog",
898
"/boot/home/config/settings",
903
static const char * const files[] = {
914
For now it is considered that it is too expensive to run the ps command
915
for the small amount of entropy it provides.
916
#if defined(__sun) && (!defined(__svr4) && !defined(SVR4)) || defined(bsdi) || defined(LINUX)
917
static char ps_cmd[] = "ps aux";
919
static char ps_cmd[] = "ps -el";
923
static char netstat_ni_cmd[] = "netstat -nis";
925
static char netstat_ni_cmd[] = "netstat -ni";
930
bytes = RNG_GetNoise(buf, sizeof(buf));
931
RNG_RandomUpdate(buf, bytes);
934
* Pass the C environment and the addresses of the pointers to the
935
* hash function. This makes the random number function depend on the
936
* execution environment of the user and on the platform the program
939
if (environ != NULL) {
940
cp = (const char * const *) environ;
942
RNG_RandomUpdate(*cp, strlen(*cp));
945
RNG_RandomUpdate(environ, (char*)cp - (char*)environ);
948
/* Give in system information */
949
if (gethostname(buf, sizeof(buf)) == 0) {
950
RNG_RandomUpdate(buf, strlen(buf));
954
/* grab some data from system's PRNG before any other files. */
955
bytes = RNG_FileUpdate("/dev/urandom", SYSTEM_RNG_SEED_COUNT);
957
/* If the user points us to a random file, pass it through the rng */
958
randfile = getenv("NSRANDFILE");
959
if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {
960
RNG_FileForRNG(randfile);
963
/* pass other files through */
964
for (cp = files; *cp; cp++)
968
* Bug 100447: On BSD/OS 4.2 and 4.3, we have problem calling safe_popen
969
* in a pthreads environment. Therefore, we call safe_popen last and on
970
* BSD/OS we do not call safe_popen when we succeeded in getting data
982
* On Solaris, NSS may be initialized automatically from libldap in
983
* applications that are unaware of the use of NSS. safe_popen forks, and
984
* sometimes creates issues with some applications' pthread_atfork handlers.
985
* We always have /dev/urandom on Solaris 9 and above as an entropy source,
986
* and for Solaris 8 we have the libkstat interface, so we don't need to
992
/* On Solaris 8, /dev/urandom isn't available, so we use libkstat. */
993
PRUint32 kstat_bytes = 0;
994
if (SECSuccess != RNG_kstat(&kstat_bytes)) {
997
bytes += kstat_bytes;
1003
fp = safe_popen(ps_cmd);
1005
while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
1006
RNG_RandomUpdate(buf, bytes);
1012
fp = safe_popen(netstat_ni_cmd);
1014
while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)
1015
RNG_RandomUpdate(buf, bytes);
1022
void RNG_SystemInfoForRNG(void)
1029
extern char **environ;
1034
bytes = RNG_GetNoise(buf, sizeof(buf));
1035
RNG_RandomUpdate(buf, bytes);
1038
* Pass the C environment and the addresses of the pointers to the
1039
* hash function. This makes the random number function depend on the
1040
* execution environment of the user and on the platform the program
1045
RNG_RandomUpdate(*cp, strlen(*cp));
1048
RNG_RandomUpdate(environ, (char*)cp - (char*)environ);
1050
/* Give in system information */
1051
if (gethostname(buf, sizeof(buf)) > 0) {
1052
RNG_RandomUpdate(buf, strlen(buf));
1056
/* If the user points us to a random file, pass it through the rng */
1057
randfile = getenv("NSRANDFILE");
1058
if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {
1059
RNG_FileForRNG(randfile);
1063
** We need to generate at least 1024 bytes of seed data. Since we don't
1064
** do the file stuff for VMS, and because the environ list is so short
1065
** on VMS, we need to make sure we generate enough. So do another 1000
1066
** bytes to be sure.
1072
int n = strlen(*cp);
1073
RNG_RandomUpdate(*cp, n);
1081
#define TOTAL_FILE_LIMIT 1000000 /* one million */
1083
size_t RNG_FileUpdate(const char *fileName, size_t limit)
1087
size_t fileBytes = 0;
1088
struct stat stat_buf;
1089
unsigned char buffer[BUFSIZ];
1090
static size_t totalFileBytes = 0;
1092
/* suppress valgrind warnings due to holes in struct stat */
1093
memset(&stat_buf, 0, sizeof(stat_buf));
1095
if (stat((char *)fileName, &stat_buf) < 0)
1097
RNG_RandomUpdate(&stat_buf, sizeof(stat_buf));
1099
file = fopen((char *)fileName, "r");
1101
while (limit > fileBytes) {
1102
bytes = PR_MIN(sizeof buffer, limit - fileBytes);
1103
bytes = fread(buffer, 1, bytes, file);
1106
RNG_RandomUpdate(buffer, bytes);
1108
totalFileBytes += bytes;
1109
/* after TOTAL_FILE_LIMIT has been reached, only read in first
1110
** buffer of data from each subsequent file.
1112
if (totalFileBytes > TOTAL_FILE_LIMIT)
1118
* Pass yet another snapshot of our highest resolution clock into
1119
* the hash function.
1121
bytes = RNG_GetNoise(buffer, sizeof(buffer));
1122
RNG_RandomUpdate(buffer, bytes);
1126
void RNG_FileForRNG(const char *fileName)
1128
RNG_FileUpdate(fileName, TOTAL_FILE_LIMIT);
1131
size_t RNG_SystemRNG(void *dest, size_t maxLen)
1135
size_t fileBytes = 0;
1136
unsigned char *buffer = dest;
1138
file = fopen("/dev/urandom", "r");
1140
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
1143
while (maxLen > fileBytes) {
1144
bytes = maxLen - fileBytes;
1145
bytes = fread(buffer, 1, bytes, file);
1152
if (fileBytes != maxLen) {
1153
PORT_SetError(SEC_ERROR_NEED_RANDOM); /* system RNG failed */