unix_rand.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 792 行 · 第 1/2 页

C
792
字号
	    raddr = phys_addr & ~pgoffmask;	    mfd = open("/dev/mmem", O_RDONLY);	    if (mfd < 0) {		return 0;	    }	    iotimer_addr = (unsigned *)		mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);	    if (iotimer_addr == (void*)-1) {		close(mfd);		iotimer_addr = NULL;		return 0;	    }	    iotimer_addr = (unsigned*)		((__psint_t)iotimer_addr | (phys_addr & pgoffmask));	    /*	     * The file 'mfd' is purposefully not closed.	     */	    cntr_size = syssgi(SGI_CYCLECNTR_SIZE);	    if (cntr_size < 0) {		struct utsname utsinfo;		/* 		 * We must be executing on a 6.0 or earlier system, since the		 * SGI_CYCLECNTR_SIZE call is not supported.		 * 		 * The only pre-6.1 platforms with 64-bit counters are		 * IP19 and IP21 (Challenge, PowerChallenge, Onyx).		 */		uname(&utsinfo);		if (!strncmp(utsinfo.machine, "IP19", 4) ||		    !strncmp(utsinfo.machine, "IP21", 4))			cntr_size = 64;		else			cntr_size = 32;	    }	    cntr_size /= 8;	/* Convert from bits to bytes */	}    }    s0[0] = *iotimer_addr;    if (cntr_size > 4)	s0[1] = *(iotimer_addr + 1);    memcpy(buf, (char *)&s0[0], cntr_size);    return CopyLowBits(buf, maxbuf, &s0, cntr_size);}#endif#if defined(sony)#include <sys/systeminfo.h>#define getdtablesize() sysconf(_SC_OPEN_MAX)static size_tGetHighResClock(void *buf, size_t maxbytes){    return 0;}static voidGiveSystemInfo(void){    int rv;    char buf[2000];    rv = sysinfo(SI_MACHINE, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }    rv = sysinfo(SI_RELEASE, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }    rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }}#endif /* sony */#if defined(sinix)#include <unistd.h>#include <sys/systeminfo.h>#include <sys/times.h>int gettimeofday(struct timeval *, struct timezone *);int gethostname(char *, int);#define getdtablesize() sysconf(_SC_OPEN_MAX)static size_tGetHighResClock(void *buf, size_t maxbytes){    int ticks;    struct tms buffer;    ticks=times(&buffer);    return CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));}static voidGiveSystemInfo(void){    int rv;    char buf[2000];    rv = sysinfo(SI_MACHINE, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }    rv = sysinfo(SI_RELEASE, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }    rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }}#endif /* sinix */#if defined(nec_ews)#include <sys/systeminfo.h>#define getdtablesize() sysconf(_SC_OPEN_MAX)static size_tGetHighResClock(void *buf, size_t maxbytes){    return 0;}static voidGiveSystemInfo(void){    int rv;    char buf[2000];    rv = sysinfo(SI_MACHINE, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }    rv = sysinfo(SI_RELEASE, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }    rv = sysinfo(SI_HW_SERIAL, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, rv);    }}#endif /* nec_ews */size_t RNG_GetNoise(void *buf, size_t maxbytes){    struct timeval tv;    int n = 0;    int c;    n = GetHighResClock(buf, maxbytes);    maxbytes -= n;#if defined(__sun) && (defined(_svr4) || defined(SVR4)) || defined(sony)    (void)gettimeofday(&tv);#else    (void)gettimeofday(&tv, 0);#endif    c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_usec, sizeof(tv.tv_usec));    n += c;    maxbytes -= c;    c = CopyLowBits((char*)buf+n, maxbytes, &tv.tv_sec, sizeof(tv.tv_sec));    n += c;    return n;}#define SAFE_POPEN_MAXARGS	10	/* must be at least 2 *//* * safe_popen is static to this module and we know what arguments it is * called with. Note that this version only supports a single open child * process at any time. */static pid_t safe_popen_pid;static struct sigaction oldact;static FILE *safe_popen(char *cmd){    int p[2], fd, argc;    pid_t pid;    char *argv[SAFE_POPEN_MAXARGS + 1];    FILE *fp;    static char blank[] = " \t";    static struct sigaction newact;    if (pipe(p) < 0)	return 0;    /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */    newact.sa_handler = SIG_DFL;    newact.sa_flags = 0;    sigfillset(&newact.sa_mask);    sigaction (SIGCHLD, &newact, &oldact);    pid = fork();    switch (pid) {      case -1:	close(p[0]);	close(p[1]);	sigaction (SIGCHLD, &oldact, NULL);	return 0;      case 0:	/* dup write-side of pipe to stderr and stdout */	if (p[1] != 1) dup2(p[1], 1);	if (p[1] != 2) dup2(p[1], 2);	close(0);	for (fd = getdtablesize(); --fd > 2; close(fd))	    ;	/* clean up environment in the child process */	putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc:/usr/etc");	putenv("SHELL=/bin/sh");	putenv("IFS= \t");	/*	 * The caller may have passed us a string that is in text	 * space. It may be illegal to modify the string	 */	cmd = strdup(cmd);	/* format argv */	argv[0] = strtok(cmd, blank);	argc = 1;	while ((argv[argc] = strtok(0, blank)) != 0) {	    if (++argc == SAFE_POPEN_MAXARGS) {		argv[argc] = 0;		break;	    }	}	/* and away we go */	execvp(argv[0], argv);	exit(127);	break;      default:	close(p[1]);	fp = fdopen(p[0], "r");	if (fp == 0) {	    close(p[0]);	    sigaction (SIGCHLD, &oldact, NULL);	    return 0;	}	break;    }    /* non-zero means there's a cmd running */    safe_popen_pid = pid;    return fp;}static intsafe_pclose(FILE *fp){    pid_t pid;    int count, status;    if ((pid = safe_popen_pid) == 0)	return -1;    safe_popen_pid = 0;    /* if the child hasn't exited, kill it -- we're done with its output */    count = 0;    while (waitpid(pid, &status, WNOHANG) == 0) {    	if (kill(pid, SIGKILL) < 0 && errno == ESRCH)	    break;	if (++count == 1000)	    break;    }    /* Reset SIGCHLD signal hander before returning */    sigaction(SIGCHLD, &oldact, NULL);    fclose(fp);    return status;}void RNG_SystemInfoForRNG(void){    FILE *fp;    char buf[BUFSIZ];    size_t bytes;    extern char **environ;    char **cp;    char *randfile;    char *files[] = {	"/etc/passwd",	"/etc/utmp",	"/tmp",	"/var/tmp",	"/usr/tmp",	0    };#ifdef DO_PSFor now it is considered that it is too expensive to run the ps commandfor the small amount of entropy it provides.#if defined(__sun) && (!defined(__svr4) && !defined(SVR4)) || defined(bsdi) || defined(__linux)    static char ps_cmd[] = "ps aux";#else    static char ps_cmd[] = "ps -el";#endif#endif /* DO_PS */    static char netstat_ni_cmd[] = "netstat -ni";    GiveSystemInfo();    bytes = RNG_GetNoise(buf, sizeof(buf));    RNG_RandomUpdate(buf, bytes);#ifdef DO_PS    fp = safe_popen(ps_cmd);    if (fp != NULL) {	while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)	    RNG_RandomUpdate(buf, bytes);	safe_pclose(fp);    }#endif    fp = safe_popen(netstat_ni_cmd);    if (fp != NULL) {	while ((bytes = fread(buf, 1, sizeof(buf), fp)) > 0)	    RNG_RandomUpdate(buf, bytes);	safe_pclose(fp);    }    /*     * Pass the C environment and the addresses of the pointers to the     * hash function. This makes the random number function depend on the     * execution environment of the user and on the platform the program     * is running on.     */    cp = environ;    while (*cp) {	RNG_RandomUpdate(*cp, strlen(*cp));	cp++;    }    RNG_RandomUpdate(environ, (char*)cp - (char*)environ);    /* Give in system information */    if (gethostname(buf, sizeof(buf)) > 0) {	RNG_RandomUpdate(buf, strlen(buf));    }    GiveSystemInfo();    /* If the user points us to a random file, pass it through the rng */    randfile = getenv("NSRANDFILE");    if ( ( randfile != NULL ) && ( randfile[0] != '\0') ) {	RNG_FileForRNG(randfile);    }    /* pass other files through */    for (cp = files; *cp; cp++)	RNG_FileForRNG(*cp);}void RNG_FileForRNG(char *fileName){    struct stat stat_buf;    unsigned char buffer[BUFSIZ];    size_t bytes;    FILE *file;    static size_t totalFileBytes = 0;        if (stat((char *)fileName, &stat_buf) < 0)	return;    RNG_RandomUpdate(&stat_buf, sizeof(stat_buf));        file = fopen((char *)fileName, "r");    if (file != NULL) {	for (;;) {	    bytes = fread(buffer, 1, sizeof(buffer), file);	    if (bytes == 0) break;	    RNG_RandomUpdate(buffer, bytes);	    totalFileBytes += bytes;	    if (totalFileBytes > 1024*1024) break;	}	fclose(file);    }    /*     * Pass yet another snapshot of our highest resolution clock into     * the hash function.     */    bytes = RNG_GetNoise(buffer, sizeof(buffer));    RNG_RandomUpdate(buffer, bytes);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?