LCOV - code coverage report
Current view: top level - nsprpub/pr/src/md/unix - uxrng.c (source / functions) Hit Total Coverage
Test: output.info Lines: 19 29 65.5 %
Date: 2017-07-14 16:53:18 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : 
       7             : #include "primpl.h"
       8             : 
       9             : #include <string.h>
      10             : #include <unistd.h>
      11             : #include <errno.h>
      12             : #include <sys/time.h>
      13             : 
      14             : 
      15             : #if defined(SOLARIS)
      16             : 
      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             : }
      27             : 
      28             : #elif defined(HPUX)
      29             : 
      30             : #ifdef __ia64
      31             : #include <ia64/sys/inline.h>
      32             : 
      33             : static size_t
      34             : GetHighResClock(void *buf, size_t maxbytes)
      35             : {
      36             :     PRUint64 t;
      37             : 
      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;
      51             : 
      52             :     cr16val = ret_cr16();
      53             :     return(_pr_CopyLowBits(buf, maxbytes, &cr16val, sizeof(cr16val)));
      54             : }
      55             : #endif
      56             : 
      57             : #elif defined(OSF1)
      58             : 
      59             : #include <c_asm.h>
      60             : 
      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;
      70             : 
      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             : }
      78             : 
      79             : #elif defined(AIX)
      80             : 
      81             : static size_t
      82             : GetHighResClock(void *buf, size_t maxbytes)
      83             : {
      84             :     return 0;
      85             : }
      86             : 
      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>
      93             : 
      94             : static int      fdDevURandom;
      95             : static PRCallOnceType coOpenDevURandom;
      96             : 
      97           3 : static PRStatus OpenDevURandom( void )
      98             : {
      99           3 :     fdDevURandom = open( "/dev/urandom", O_RDONLY );
     100           3 :     return((-1 == fdDevURandom)? PR_FAILURE : PR_SUCCESS );
     101             : } /* end OpenDevURandom() */
     102             : 
     103           3 : static size_t GetDevURandom( void *buf, size_t size )
     104             : {
     105             :     int bytesIn;
     106             :     int rc;
     107             : 
     108           3 :     rc = PR_CallOnce( &coOpenDevURandom, OpenDevURandom );
     109           3 :     if ( PR_FAILURE == rc ) {
     110           0 :         _PR_MD_MAP_OPEN_ERROR( errno );
     111           0 :         return(0);
     112             :     }
     113             : 
     114           3 :     bytesIn = read( fdDevURandom, buf, size );
     115           3 :     if ( -1 == bytesIn ) {
     116           0 :         _PR_MD_MAP_READ_ERROR( errno );
     117           0 :         return(0);
     118             :     }
     119             : 
     120           3 :     return( bytesIn );
     121             : } /* end GetDevURandom() */
     122             : 
     123             : static size_t
     124           3 : GetHighResClock(void *buf, size_t maxbytes)
     125             : {             
     126           3 :     return(GetDevURandom( buf, maxbytes ));
     127             : }
     128             : 
     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>
     137             : 
     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];
     146             : 
     147             : #ifndef SGI_CYCLECNTR_SIZE
     148             : #define SGI_CYCLECNTR_SIZE      165     /* Size user needs to use to read CC */
     149             : #endif
     150             : 
     151             :     if (iotimer_addr == NULL) {
     152             :             if (tries++ > 1) {
     153             :                 /* Don't keep trying if it didn't work */
     154             :                 return 0;
     155             :             }
     156             : 
     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;
     165             : 
     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;
     186             : 
     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             :     }
     204             : 
     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             : }
     211             : 
     212             : #elif defined(SCO) || defined(UNIXWARE) || defined(BSDI) || defined(NTO) \
     213             :     || defined(QNX) || defined(DARWIN) || defined(RISCOS)
     214             : #include <sys/times.h>
     215             : 
     216             : static size_t
     217             : GetHighResClock(void *buf, size_t maxbytes)
     218             : {
     219             :     int ticks;
     220             :     struct tms buffer;
     221             : 
     222             :     ticks=times(&buffer);
     223             :     return _pr_CopyLowBits(buf, maxbytes, &ticks, sizeof(ticks));
     224             : }
     225             : #else
     226             : #error! Platform undefined
     227             : #endif /* defined(SOLARIS) */
     228             : 
     229           3 : extern PRSize _PR_MD_GetRandomNoise( void *buf, PRSize size )
     230             : {
     231             :     struct timeval tv;
     232           3 :     int n = 0;
     233             :     int s;
     234             : 
     235           3 :     n += GetHighResClock(buf, size);
     236           3 :     size -= n;
     237             : 
     238           3 :     GETTIMEOFDAY(&tv);
     239             : 
     240           3 :     if ( size > 0 ) {
     241           0 :         s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_usec, sizeof(tv.tv_usec));
     242           0 :         size -= s;
     243           0 :         n += s;
     244             :     }
     245           3 :     if ( size > 0 ) {
     246           0 :         s = _pr_CopyLowBits((char*)buf+n, size, &tv.tv_sec, sizeof(tv.tv_usec));
     247           0 :         size -= s;
     248           0 :         n += s;
     249             :     }
     250             : 
     251           3 :     return n;
     252             : } /* end _PR_MD_GetRandomNoise() */

Generated by: LCOV version 1.13