LCOV - code coverage report
Current view: directory - src/shared/platform - nacl_global_secure_random.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 39 22 56.4 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright (c) 2011 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * NaCl Service Runtime.  Secure RNG abstraction.
       9                 :  */
      10                 : 
      11                 : #include "native_client/src/shared/platform/nacl_global_secure_random.h"
      12                 : #include "native_client/src/shared/platform/nacl_log.h"
      13                 : #include "native_client/src/shared/platform/nacl_secure_random.h"
      14                 : #include "native_client/src/shared/platform/nacl_sync.h"
      15                 : #include "native_client/src/shared/platform/nacl_sync_checked.h"
      16                 : 
      17                 : static struct NaClMutex          nacl_global_rng_mu;
      18                 : static struct NaClSecureRng      nacl_global_rng;
      19                 : 
      20                 : static struct NaClSecureRng      *nacl_grngp = &nacl_global_rng;
      21                 : 
      22              15 : void NaClGlobalSecureRngInit(void) {
      23              15 :   NaClXMutexCtor(&nacl_global_rng_mu);
      24              15 :   if (!NaClSecureRngCtor(nacl_grngp)) {
      25                 :     NaClLog(LOG_FATAL,
      26               0 :             "Could not construct global random number generator.\n");
      27                 :   }
      28              15 : }
      29                 : 
      30              11 : void NaClGlobalSecureRngFini(void) {
      31              11 :   (*nacl_grngp->base.vtbl->Dtor)(&nacl_grngp->base);
      32              11 :   NaClMutexDtor(&nacl_global_rng_mu);
      33              11 : }
      34                 : 
      35               0 : void NaClGlobalSecureRngSwitchRngForTesting(struct NaClSecureRng  *rng) {
      36               0 :   NaClXMutexLock(&nacl_global_rng_mu);
      37               0 :   nacl_grngp = rng;
      38               0 :   NaClXMutexUnlock(&nacl_global_rng_mu);
      39               0 : }
      40                 : 
      41               2 : int32_t NaClGlobalSecureRngUniform(int32_t range_max) {
      42                 :   int32_t  rv;
      43                 : 
      44               2 :   NaClXMutexLock(&nacl_global_rng_mu);
      45               2 :   rv = (*nacl_grngp->base.vtbl->Uniform)(&nacl_grngp->base, range_max);
      46               2 :   NaClXMutexUnlock(&nacl_global_rng_mu);
      47               2 :   return rv;
      48               2 : }
      49                 : 
      50               0 : uint32_t NaClGlobalSecureRngUint32(void) {
      51                 :   uint32_t rv;
      52               0 :   NaClXMutexLock(&nacl_global_rng_mu);
      53               0 :   rv = (*nacl_grngp->base.vtbl->GenUint32)(&nacl_grngp->base);
      54               0 :   NaClXMutexUnlock(&nacl_global_rng_mu);
      55               0 :   return rv;
      56               0 : }
      57                 : 
      58               0 : void NaClGlobalSecureRngGenerateBytes(uint8_t *buf, size_t buf_size) {
      59               0 :   NaClXMutexLock(&nacl_global_rng_mu);
      60               0 :   (*nacl_grngp->base.vtbl->GenBytes)(&nacl_grngp->base, buf, buf_size);
      61               0 :   NaClXMutexUnlock(&nacl_global_rng_mu);
      62               0 : }
      63                 : 
      64               2 : void NaClGenerateRandomPath(char *path, int length) {
      65                 :   /*
      66                 :    * This function is used for generating random paths and names,
      67                 :    * e.g. for IMC sockets and semaphores.
      68                 :    *
      69                 :    * IMC sockets note: the IMC header file omits some important
      70                 :    * details.  The alphabet cannot include backslash for Windows.  For
      71                 :    * Linux, it uses the abstract namespace (see unix(7)), and can
      72                 :    * contain arbitrary characters.  The limitations for OSX are the
      73                 :    * same as for pathname components, since the IMC library uses
      74                 :    * unix-domain sockets there.
      75                 :    *
      76                 :    * We uniformly generate from an alphabet of digits and uppercase
      77                 :    * and lowercase alphabetic characters on case-sensitive platforms
      78                 :    * (non-Windows), and uniformly generate from an alphabet of digits
      79                 :    * and lowercase characters on case-insensitive platforms (Windows).
      80                 :    * Since IMC allows 27 characters (plus a '\0' terminator), we can
      81                 :    * compute the (apparent) entropy which gives the effort required by
      82                 :    * an attacker who cannot enumerate the namespace but must probe
      83                 :    * blindly.  ("Apparent", since the actual amount of entropy
      84                 :    * available is the entropy in the cryptographically secure
      85                 :    * pseudorandom number generator's seed.)
      86                 :    *
      87                 :    * For case sensitive names (linux, osx), we have an alphabet size
      88                 :    * of 62 characters, so assuming that the underlying generator is
      89                 :    * ideal, we have a total entropy of the name is
      90                 :    *
      91                 :    *  H_{27} = 27 * H_1 = 27 * -\log_2(1/62)
      92                 :    *         \approx 160.76 bits
      93                 :    *
      94                 :    * For case insensitive names (windows), we have an alphabet size of
      95                 :    * 36 characters, and we have
      96                 :    *
      97                 :    *  H_{27} = 27 * H_1 = 27 * -log_2(1/36)
      98                 :    *         \approx 137.59 bits
      99                 :    *
     100                 :    * If we used the 62-character alphabet in a case insensitive
     101                 :    * environment then the case folding means that an attacker will
     102                 :    * encounter an entropy of
     103                 :    *
     104                 :    *  H_{27} = 27 * H_1 = 27 * (10/62 * -log_2(1/62) + 26*2/62 * -log_2(2/62))
     105                 :    *         \approx 138.12 bits
     106                 :    *
     107                 :    * which reduces security by 1.47 bits.  So, using an equiprobable
     108                 :    * alphabet rather than case folding is slightly better in a case
     109                 :    * insensitive environment, and using a larger alphabet is much
     110                 :    * better than always case folding in a case sensitive environment
     111                 :    * (23.48 bits).
     112                 :    *
     113                 :    * TODO(bsy): determine if the alphabets can be enlarged, and by how
     114                 :    * much.
     115                 :    */
     116                 :   static char const alphabet[] =
     117                 :       "abcdefghijklmnopqrstuvwxyz"
     118                 : #if !NACL_WINDOWS
     119                 :       "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     120                 : #endif  /* !NACL_WINDOWS */
     121                 :       "0123456789";
     122               2 :   int const         alphabet_size = sizeof alphabet - 1;  /* NUL termination */
     123                 : 
     124                 :   int               i;
     125                 :   int               r;
     126                 : 
     127               2 :   for (i = 0; i < length-1; ++i) {
     128               2 :     r = NaClGlobalSecureRngUniform(alphabet_size);
     129               2 :     path[i] = alphabet[r];
     130               2 :   }
     131               2 :   path[length-1] = '\0';
     132               2 : }

Generated by: LCOV version 1.7