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

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #include "primpl.h"
     9 #include <string.h>
    10 #include <unistd.h>
    11 #include <errno.h>
    12 #include <sys/time.h>
    15 #if defined(SOLARIS)
    17 static size_t
    18 GetHighResClock(void *buf, size_t maxbytes)
    19 {
    20     hrtime_t t;
    21     t = gethrtime();
    22     if (t) {
    23 	    return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
    24     }
    25     return 0;
    26 }
    28 #elif defined(HPUX)
    30 #ifdef __ia64
    31 #include <ia64/sys/inline.h>
    33 static size_t
    34 GetHighResClock(void *buf, size_t maxbytes)
    35 {
    36     PRUint64 t;
    38 #ifdef __GNUC__
    39     __asm__ __volatile__("mov %0 = ar.itc" : "=r" (t));
    40 #else
    41     t = _Asm_mov_from_ar(_AREG44);
    42 #endif
    43     return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
    44 }
    45 #else
    46 static size_t
    47 GetHighResClock(void *buf, size_t maxbytes)
    48 {
    49     extern int ret_cr16();
    50     int cr16val;
    52     cr16val = ret_cr16();
    53     return(_pr_CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val)));
    54 }
    55 #endif
    57 #elif defined(OSF1)
    59 #include <c_asm.h>
    61 /*
    62  * Use the "get the cycle counter" instruction on the alpha.
    63  * The low 32 bits completely turn over in less than a minute.
    64  * The high 32 bits are some non-counter gunk that changes sometimes.
    65  */
    66 static size_t
    67 GetHighResClock(void *buf, size_t maxbytes)
    68 {
    69     unsigned long t;
    71 #ifdef __GNUC__
    72     __asm__("rpcc %0" : "=r" (t));
    73 #else
    74     t = asm("rpcc %v0");
    75 #endif
    76     return _pr_CopyLowBits(buf, maxbytes, &t, sizeof(t));
    77 }
    79 #elif defined(AIX)
    81 static size_t
    82 GetHighResClock(void *buf, size_t maxbytes)
    83 {
    84     return 0;
    85 }
    87 #elif (defined(LINUX) || defined(FREEBSD) || defined(__FreeBSD_kernel__) \
    88     || defined(NETBSD) || defined(__NetBSD_kernel__) || defined(OPENBSD) \
    89     || defined(SYMBIAN) || defined(__GNU__))
    90 #include <sys/types.h>
    91 #include <sys/stat.h>
    92 #include <fcntl.h>
    94 static int      fdDevURandom;
    95 static PRCallOnceType coOpenDevURandom;
    97 static PRStatus OpenDevURandom( void )
    98 {
    99     fdDevURandom = open( "/dev/urandom", O_RDONLY );
   100     return((-1 == fdDevURandom)? PR_FAILURE : PR_SUCCESS );
   101 } /* end OpenDevURandom() */
   103 static size_t GetDevURandom( void *buf, size_t size )
   104 {
   105     int bytesIn;
   106     int rc;
   108     rc = PR_CallOnce( &coOpenDevURandom, OpenDevURandom );
   109     if ( PR_FAILURE == rc ) {
   110         _PR_MD_MAP_OPEN_ERROR( errno );
   111         return(0);
   112     }
   114     bytesIn = read( fdDevURandom, buf, size );
   115     if ( -1 == bytesIn ) {
   116         _PR_MD_MAP_READ_ERROR( errno );
   117         return(0);
   118     }
   120     return( bytesIn );
   121 } /* end GetDevURandom() */
   123 static size_t
   124 GetHighResClock(void *buf, size_t maxbytes)
   125 {             
   126     return(GetDevURandom( buf, maxbytes ));
   127 }
   129 #elif defined(IRIX)
   130 #include <fcntl.h>
   131 #undef PRIVATE
   132 #include <sys/mman.h>
   133 #include <sys/syssgi.h>
   134 #include <sys/immu.h>
   135 #include <sys/systeminfo.h>
   136 #include <sys/utsname.h>
   138 static size_t GetHighResClock(void *buf, size_t maxbuf)
   139 {
   140     unsigned phys_addr, raddr, cycleval;
   141     static volatile unsigned *iotimer_addr = NULL;
   142     static int tries = 0;
   143     static int cntr_size;
   144     int mfd;
   145     unsigned s0[2];
   147 #ifndef SGI_CYCLECNTR_SIZE
   148 #define SGI_CYCLECNTR_SIZE      165     /* Size user needs to use to read CC */
   149 #endif
   151     if (iotimer_addr == NULL) {
   152 	    if (tries++ > 1) {
   153 	        /* Don't keep trying if it didn't work */
   154 	        return 0;
   155 	    }
   157 	    /*
   158 	    ** For SGI machines we can use the cycle counter, if it has one,
   159 	    ** to generate some truly random numbers
   160 	    */
   161 	    phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &cycleval);
   162 	    if (phys_addr) {
   163 	        int pgsz = getpagesize();
   164 	        int pgoffmask = pgsz - 1;
   166 	        raddr = phys_addr & ~pgoffmask;
   167 	        mfd = open("/dev/mmem", O_RDONLY);
   168 	        if (mfd < 0) {
   169     		    return 0;
   170 	        }
   171 	        iotimer_addr = (unsigned *)
   172 		    mmap(0, pgoffmask, PROT_READ, MAP_PRIVATE, mfd, (int)raddr);
   173 	        if (iotimer_addr == (unsigned*)-1) {
   174 	    	    close(mfd);
   175 		        iotimer_addr = NULL;
   176 		        return 0;
   177 	        }
   178 	        iotimer_addr = (unsigned*)
   179 		    ((__psint_t)iotimer_addr | (phys_addr & pgoffmask));
   180 	        /*
   181 	         * The file 'mfd' is purposefully not closed.
   182 	         */
   183 	        cntr_size = syssgi(SGI_CYCLECNTR_SIZE);
   184 	        if (cntr_size < 0) {
   185     		    struct utsname utsinfo;
   187 		        /* 
   188 		         * We must be executing on a 6.0 or earlier system, since the
   189 		         * SGI_CYCLECNTR_SIZE call is not supported.
   190 		         * 
   191 		         * The only pre-6.1 platforms with 64-bit counters are
   192 		         * IP19 and IP21 (Challenge, PowerChallenge, Onyx).
   193 		         */
   194 		        uname(&utsinfo);
   195 		        if (!strncmp(utsinfo.machine, "IP19", 4) ||
   196 		            !strncmp(utsinfo.machine, "IP21", 4))
   197 			        cntr_size = 64;
   198 		        else
   199 			        cntr_size = 32;
   200 	        }
   201 	        cntr_size /= 8;	/* Convert from bits to bytes */
   202 	    }
   203     }
   205     s0[0] = *iotimer_addr;
   206     if (cntr_size > 4)
   207 	s0[1] = *(iotimer_addr + 1);
   208     memcpy(buf, (char *)&s0[0], cntr_size);
   209     return _pr_CopyLowBits(buf, maxbuf, &s0, cntr_size);
   210 }
   212 #elif defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(NTO) \
   213     || defined(QNX) || defined(DARWIN) || defined(RISCOS)
   214 #include <sys/times.h>
   216 static size_t
   217 GetHighResClock(void *buf, size_t maxbytes)
   218 {
   219     int ticks;
   220     struct tms buffer;
   222     ticks=times(&buffer);
   223     return _pr_CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
   224 }
   225 #else
   226 #error! Platform undefined
   227 #endif /* defined(SOLARIS) */
   229 extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size )
   230 {
   231     struct timeval tv;
   232     int n = 0;
   233     int s;
   235     n += GetHighResClock(buf, size);
   236     size -= n;
   238     GETTIMEOFDAY(&tv);
   240     if ( size > 0 ) {
   241         s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec));
   242         size -= s;
   243         n += s;
   244     }
   245     if ( size > 0 ) {
   246         s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec));
   247         size -= s;
   248         n += s;
   249     }
   251     return n;
   252 } /* end _PR_MD_GetRandomNoise() */

mercurial