nsprpub/pr/src/md/unix/uxrng.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/nsprpub/pr/src/md/unix/uxrng.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,252 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +
    1.10 +#include "primpl.h"
    1.11 +
    1.12 +#include <string.h>
    1.13 +#include <unistd.h>
    1.14 +#include <errno.h>
    1.15 +#include <sys/time.h>
    1.16 +
    1.17 +
    1.18 +#if defined(SOLARIS)
    1.19 +
    1.20 +static size_t
    1.21 +GetHighResClock(void *buf, size_t maxbytes)
    1.22 +{
    1.23 +    hrtime_t t;
    1.24 +    t = gethrtime();
    1.25 +    if (t) {
    1.26 +	    return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
    1.27 +    }
    1.28 +    return 0;
    1.29 +}
    1.30 +
    1.31 +#elif defined(HPUX)
    1.32 +
    1.33 +#ifdef __ia64
    1.34 +#include <ia64/sys/inline.h>
    1.35 +
    1.36 +static size_t
    1.37 +GetHighResClock(void *buf, size_t maxbytes)
    1.38 +{
    1.39 +    PRUint64 t;
    1.40 +
    1.41 +#ifdef __GNUC__
    1.42 +    __asm__ __volatile__("mov %0 = ar.itc" : "=r" (t));
    1.43 +#else
    1.44 +    t = _Asm_mov_from_ar(_AREG44);
    1.45 +#endif
    1.46 +    return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
    1.47 +}
    1.48 +#else
    1.49 +static size_t
    1.50 +GetHighResClock(void *buf, size_t maxbytes)
    1.51 +{
    1.52 +    extern int ret_cr16();
    1.53 +    int cr16val;
    1.54 +
    1.55 +    cr16val = ret_cr16();
    1.56 +    return(_pr_CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val)));
    1.57 +}
    1.58 +#endif
    1.59 +
    1.60 +#elif defined(OSF1)
    1.61 +
    1.62 +#include <c_asm.h>
    1.63 +
    1.64 +/*
    1.65 + * Use the "get the cycle counter" instruction on the alpha.
    1.66 + * The low 32 bits completely turn over in less than a minute.
    1.67 + * The high 32 bits are some non-counter gunk that changes sometimes.
    1.68 + */
    1.69 +static size_t
    1.70 +GetHighResClock(void *buf, size_t maxbytes)
    1.71 +{
    1.72 +    unsigned long t;
    1.73 +
    1.74 +#ifdef __GNUC__
    1.75 +    __asm__("rpcc %0" : "=r" (t));
    1.76 +#else
    1.77 +    t = asm("rpcc %v0");
    1.78 +#endif
    1.79 +    return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
    1.80 +}
    1.81 +
    1.82 +#elif defined(AIX)
    1.83 +
    1.84 +static size_t
    1.85 +GetHighResClock(void *buf, size_t maxbytes)
    1.86 +{
    1.87 +    return 0;
    1.88 +}
    1.89 +
    1.90 +#elif (defined(LINUX) || defined(FREEBSD) || defined(__FreeBSD_kernel__) \
    1.91 +    || defined(NETBSD) || defined(__NetBSD_kernel__) || defined(OPENBSD) \
    1.92 +    || defined(SYMBIAN) || defined(__GNU__))
    1.93 +#include <sys/types.h>
    1.94 +#include <sys/stat.h>
    1.95 +#include <fcntl.h>
    1.96 +
    1.97 +static int      fdDevURandom;
    1.98 +static PRCallOnceType coOpenDevURandom;
    1.99 +
   1.100 +static PRStatus OpenDevURandom( void )
   1.101 +{
   1.102 +    fdDevURandom = open( "/dev/urandom", O_RDONLY );
   1.103 +    return((-1 == fdDevURandom)? PR_FAILURE : PR_SUCCESS );
   1.104 +} /* end OpenDevURandom() */
   1.105 +
   1.106 +static size_t GetDevURandom( void *buf, size_t size )
   1.107 +{
   1.108 +    int bytesIn;
   1.109 +    int rc;
   1.110 +
   1.111 +    rc = PR_CallOnce( &coOpenDevURandom, OpenDevURandom );
   1.112 +    if ( PR_FAILURE == rc ) {
   1.113 +        _PR_MD_MAP_OPEN_ERROR( errno );
   1.114 +        return(0);
   1.115 +    }
   1.116 +
   1.117 +    bytesIn = read( fdDevURandom, buf, size );
   1.118 +    if ( -1 == bytesIn ) {
   1.119 +        _PR_MD_MAP_READ_ERROR( errno );
   1.120 +        return(0);
   1.121 +    }
   1.122 +
   1.123 +    return( bytesIn );
   1.124 +} /* end GetDevURandom() */
   1.125 +
   1.126 +static size_t
   1.127 +GetHighResClock(void *buf, size_t maxbytes)
   1.128 +{             
   1.129 +    return(GetDevURandom( buf, maxbytes ));
   1.130 +}
   1.131 +
   1.132 +#elif defined(IRIX)
   1.133 +#include <fcntl.h>
   1.134 +#undef PRIVATE
   1.135 +#include <sys/mman.h>
   1.136 +#include <sys/syssgi.h>
   1.137 +#include <sys/immu.h>
   1.138 +#include <sys/systeminfo.h>
   1.139 +#include <sys/utsname.h>
   1.140 +
   1.141 +static size_t GetHighResClock(void *buf, size_t maxbuf)
   1.142 +{
   1.143 +    unsigned phys_addr, raddr, cycleval;
   1.144 +    static volatile unsigned *iotimer_addr = NULL;
   1.145 +    static int tries = 0;
   1.146 +    static int cntr_size;
   1.147 +    int mfd;
   1.148 +    unsigned s0[2];
   1.149 +
   1.150 +#ifndef SGI_CYCLECNTR_SIZE
   1.151 +#define SGI_CYCLECNTR_SIZE      165     /* Size user needs to use to read CC */
   1.152 +#endif
   1.153 +
   1.154 +    if (iotimer_addr == NULL) {
   1.155 +	    if (tries++ > 1) {
   1.156 +	        /* Don't keep trying if it didn't work */
   1.157 +	        return 0;
   1.158 +	    }
   1.159 +
   1.160 +	    /*
   1.161 +	    ** For SGI machines we can use the cycle counter, if it has one,
   1.162 +	    ** to generate some truly random numbers
   1.163 +	    */
   1.164 +	    phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
   1.165 +	    if (phys_addr) {
   1.166 +	        int pgsz = getpagesize();
   1.167 +	        int pgoffmask = pgsz - 1;
   1.168 +
   1.169 +	        raddr = phys_addr & ~pgoffmask;
   1.170 +	        mfd = open("/dev/mmem", O_RDONLY);
   1.171 +	        if (mfd < 0) {
   1.172 +    		    return 0;
   1.173 +	        }
   1.174 +	        iotimer_addr = (unsigned *)
   1.175 +		    mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
   1.176 +	        if (iotimer_addr == (unsigned*)-1) {
   1.177 +	    	    close(mfd);
   1.178 +		        iotimer_addr = NULL;
   1.179 +		        return 0;
   1.180 +	        }
   1.181 +	        iotimer_addr = (unsigned*)
   1.182 +		    ((__psint_t)iotimer_addr | (phys_addr & pgoffmask));
   1.183 +	        /*
   1.184 +	         * The file 'mfd' is purposefully not closed.
   1.185 +	         */
   1.186 +	        cntr_size = syssgi(SGI_CYCLECNTR_SIZE);
   1.187 +	        if (cntr_size < 0) {
   1.188 +    		    struct utsname utsinfo;
   1.189 +
   1.190 +		        /* 
   1.191 +		         * We must be executing on a 6.0 or earlier system, since the
   1.192 +		         * SGI_CYCLECNTR_SIZE call is not supported.
   1.193 +		         * 
   1.194 +		         * The only pre-6.1 platforms with 64-bit counters are
   1.195 +		         * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
   1.196 +		         */
   1.197 +		        uname(&utsinfo);
   1.198 +		        if (!strncmp(utsinfo.machine, "IP19", 4) ||
   1.199 +		            !strncmp(utsinfo.machine, "IP21", 4))
   1.200 +			        cntr_size = 64;
   1.201 +		        else
   1.202 +			        cntr_size = 32;
   1.203 +	        }
   1.204 +	        cntr_size /= 8;	/* Convert from bits to bytes */
   1.205 +	    }
   1.206 +    }
   1.207 +
   1.208 +    s0[0] = *iotimer_addr;
   1.209 +    if (cntr_size > 4)
   1.210 +	s0[1] = *(iotimer_addr + 1);
   1.211 +    memcpy(buf, (char *)&s0[0], cntr_size);
   1.212 +    return _pr_CopyLowBits(buf, maxbuf, &s0, cntr_size);
   1.213 +}
   1.214 +
   1.215 +#elif defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(NTO) \
   1.216 +    || defined(QNX) || defined(DARWIN) || defined(RISCOS)
   1.217 +#include <sys/times.h>
   1.218 +
   1.219 +static size_t
   1.220 +GetHighResClock(void *buf, size_t maxbytes)
   1.221 +{
   1.222 +    int ticks;
   1.223 +    struct tms buffer;
   1.224 +
   1.225 +    ticks=times(&buffer);
   1.226 +    return _pr_CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
   1.227 +}
   1.228 +#else
   1.229 +#error! Platform undefined
   1.230 +#endif /* defined(SOLARIS) */
   1.231 +
   1.232 +extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size )
   1.233 +{
   1.234 +    struct timeval tv;
   1.235 +    int n = 0;
   1.236 +    int s;
   1.237 +
   1.238 +    n += GetHighResClock(buf, size);
   1.239 +    size -= n;
   1.240 +
   1.241 +    GETTIMEOFDAY(&tv);
   1.242 +
   1.243 +    if ( size > 0 ) {
   1.244 +        s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec));
   1.245 +        size -= s;
   1.246 +        n += s;
   1.247 +    }
   1.248 +    if ( size > 0 ) {
   1.249 +        s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec));
   1.250 +        size -= s;
   1.251 +        n += s;
   1.252 +    }
   1.253 +
   1.254 +    return n;
   1.255 +} /* end _PR_MD_GetRandomNoise() */

mercurial