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() */