unix_rand.c

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

C
792
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. */#include <stdio.h>#include <string.h>#include <signal.h>#include <unistd.h>#include <errno.h>#include <stdlib.h>#include <sys/time.h>#include <sys/wait.h>#include <sys/stat.h>#include <assert.h>#include "secrng.h"/* * When copying data to the buffer we want the least signicant bytes * from the input since those bits are changing the fastest. The address * of least significant byte depends upon whether we are running on * a big-endian or little-endian machine. * * Does this mean the least signicant bytes are the most significant * to us? :-) */    static size_t CopyLowBits(void *dst, size_t dstlen, void *src, size_t srclen){    union endianness {	int32 i;	char c[4];    } u;    if (srclen <= dstlen) {	memcpy(dst, src, srclen);	return srclen;    }    u.i = 0x01020304;    if (u.c[0] == 0x01) {	/* big-endian case */	memcpy(dst, (char*)src + (srclen - dstlen), dstlen);    } else {	/* little-endian case */	memcpy(dst, src, dstlen);    }    return dstlen;}#if defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(FREEBSD) \    || defined(NETBSD)#include <sys/times.h>#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){    long si;    /*      * Is this really necessary?  Why not use rand48 or something?     */    si = sysconf(_SC_CHILD_MAX);    RNG_RandomUpdate(&si, sizeof(si));    si = sysconf(_SC_STREAM_MAX);    RNG_RandomUpdate(&si, sizeof(si));    si = sysconf(_SC_OPEN_MAX);    RNG_RandomUpdate(&si, sizeof(si));}#endif#if defined(__sun)#if defined(__svr4) || defined(SVR4)#include <sys/systeminfo.h>#include <sys/times.h>#include <wait.h>int gettimeofday(struct timeval *);int gethostname(char *, int);#define getdtablesize() sysconf(_SC_OPEN_MAX)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);    }}static size_tGetHighResClock(void *buf, size_t maxbytes){    hrtime_t t;    t = gethrtime();    if (t) {	return CopyLowBits(buf, maxbytes, &t, sizeof(t));    }    return 0;}#else /* SunOS (Sun, but not SVR4) */#include <sys/wait.h>extern long sysconf(int name);static size_tGetHighResClock(void *buf, size_t maxbytes){    return 0;}static voidGiveSystemInfo(void){    long si;    /* This is not very good */    si = sysconf(_SC_CHILD_MAX);    RNG_RandomUpdate(&si, sizeof(si));}#endif#endif /* Sun */#if defined(__hpux)#include <sys/unistd.h>#include <sys/wait.h>#define getdtablesize() sysconf(_SC_OPEN_MAX)static size_tGetHighResClock(void *buf, size_t maxbytes){    extern int ret_cr16();    int cr16val;    cr16val = ret_cr16();    return CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val));}static voidGiveSystemInfo(void){    long si;    /* This is not very good */    si = sysconf(_AES_OS_VERSION);    RNG_RandomUpdate(&si, sizeof(si));    si = sysconf(_SC_CPU_VERSION);    RNG_RandomUpdate(&si, sizeof(si));}#endif /* HPUX */#if defined(OSF1)#include <sys/types.h>#include <sys/sysinfo.h>#include <sys/wait.h>#include <sys/systeminfo.h>#include <c_asm.h>static voidGiveSystemInfo(void){    char buf[BUFSIZ];    int rv;    int off = 0;    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);    }}/* * Use the "get the cycle counter" instruction on the alpha. * The low 32 bits completely turn over in less than a minute. * The high 32 bits are some non-counter gunk that changes sometimes. */static size_tGetHighResClock(void *buf, size_t maxbytes){    unsigned long t;    t = asm("rpcc %v0");    return CopyLowBits(buf, maxbytes, &t, sizeof(t));}#endif /* Alpha */#if defined(_IBMR2)static size_tGetHighResClock(void *buf, size_t maxbytes){    return 0;}static voidGiveSystemInfo(void){    /* XXX haven't found any yet! */}#endif /* IBM R2 */#if defined(__linux)#include <linux/kernel.h>static size_tGetHighResClock(void *buf, size_t maxbytes){    return 0;}static voidGiveSystemInfo(void){    /* XXX sysinfo() does not seem be implemented anywhwere */#if 0    struct sysinfo si;    char hn[2000];    if (sysinfo(&si) == 0) {	RNG_RandomUpdate(&si, sizeof(si));    }#endif}#endif /* __linux */#if defined(NCR)#include <sys/utsname.h>#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 /* NCR */#if defined(sgi)#include <fcntl.h>#undef PRIVATE#include <sys/mman.h>#include <sys/syssgi.h>#include <sys/immu.h>#include <sys/systeminfo.h>#include <sys/utsname.h>#include <wait.h>static voidGiveSystemInfo(void){    int rv;    char buf[4096];    rv = syssgi(SGI_SYSID, &buf[0]);    if (rv > 0) {	RNG_RandomUpdate(buf, MAXSYSIDSIZE);    }#ifdef SGI_RDUBLK    rv = syssgi(SGI_RDUBLK, getpid(), &buf[0], sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, sizeof(buf));    }#endif /* SGI_RDUBLK */    rv = syssgi(SGI_INVENT, SGI_INV_READ, buf, sizeof(buf));    if (rv > 0) {	RNG_RandomUpdate(buf, sizeof(buf));    }    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);    }}static size_t GetHighResClock(void *buf, size_t maxbuf){    unsigned phys_addr, raddr, cycleval;    static volatile unsigned *iotimer_addr = NULL;    static int tries = 0;    static int cntr_size;    int mfd;    long s0[2];    struct timeval tv;#ifndef SGI_CYCLECNTR_SIZE#define SGI_CYCLECNTR_SIZE      165     /* Size user needs to use to read CC */#endif    if (iotimer_addr == NULL) {	if (tries++ > 1) {	    /* Don't keep trying if it didn't work */	    return 0;	}	/*	** For SGI machines we can use the cycle counter, if it has one,	** to generate some truly random numbers	*/	phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);	if (phys_addr) {	    int pgsz = getpagesize();	    int pgoffmask = pgsz - 1;

⌨️ 快捷键说明

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