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

       1                 : /*
       2                 :  * Copyright 2008 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 implementation.
       9                 :  */
      10                 : 
      11                 : #include "native_client/src/shared/platform/nacl_log.h"
      12                 : #include "native_client/src/shared/platform/nacl_secure_random.h"
      13                 : 
      14               3 : uint32_t NaClSecureRngDefaultGenUint32(struct NaClSecureRngIf *self) {
      15                 :   uint32_t rv;
      16                 : 
      17               3 :   rv  = (*self->vtbl->GenByte)(self);
      18               3 :   rv <<= 8;
      19               3 :   rv |= (*self->vtbl->GenByte)(self);
      20               3 :   rv <<= 8;
      21               3 :   rv |= (*self->vtbl->GenByte)(self);
      22               3 :   rv <<= 8;
      23               3 :   rv |= (*self->vtbl->GenByte)(self);
      24               3 :   return rv;
      25               3 : }
      26                 : 
      27                 : void NaClSecureRngDefaultGenBytes(struct NaClSecureRngIf  *self,
      28                 :                                   uint8_t                 *buf,
      29               0 :                                   size_t                  nbytes) {
      30                 :   size_t i;
      31                 : 
      32               0 :   for (i = 0; i < nbytes; ++i) {
      33               0 :     buf[i] = (*self->vtbl->GenByte)(self);
      34               0 :   }
      35               0 : }
      36                 : 
      37                 : uint32_t NaClSecureRngDefaultUniform(struct NaClSecureRngIf *self,
      38               3 :                                      uint32_t               range_max) {
      39                 :   uint32_t bias;
      40                 :   uint32_t v;
      41                 : 
      42                 :   /*
      43                 :    * First, is range_max a power of 2?  If so, we can just keep the
      44                 :    * low order bits.
      45                 :    */
      46               3 :   if (0 == (range_max & (range_max - 1))) {
      47               0 :     return (*self->vtbl->GenUint32)(self) & (range_max - 1);
      48                 :   }
      49                 :   /* post condition: range_max is not a power of 2 */
      50                 : 
      51                 :   /*
      52                 :    * Generator output range is uniform in [0, ~(uint32_t) 0] or [0, 2^{32}).
      53                 :    *
      54                 :    * NB: Number of integer values in the range [0, n) is n,
      55                 :    * and number of integer values in the range [m, n) is n-m,
      56                 :    * (n and m are integers).
      57                 :    */
      58               3 :   bias = ((~(uint32_t) 0) % range_max) + 1;
      59                 :   /*
      60                 :    * bias = (2^{32}-1 \bmod range_max) + 1
      61                 :    *
      62                 :    * 1 <= bias <= range_max.
      63                 :    *
      64                 :    * Aside: bias = range_max is impossible.  Here's why:
      65                 :    *
      66                 :    * Suppose bias = range_max.  Then,
      67                 :    *
      68                 :    * 2^{32}-1 \bmod range_max + 1 = range_max
      69                 :    * 2^{32}-1 \bmod range_max = range_max - 1
      70                 :    * 2^{32}-1 = k range_max + range_max - 1 for some k \in Z.
      71                 :    * 2^{32}-1 = (k+1) range_max - 1
      72                 :    * 2^{32} = (k+1) range_max
      73                 :    *
      74                 :    * Since range_max evenly divides the right hand side, it must
      75                 :    * divide the left.  However, the only divisors of 2^{32} are powers
      76                 :    * of 2.  Thus, range_max must also be a power of 2.  =><=
      77                 :    *
      78                 :    * Therefore, bias \ne range_max.  QED.
      79                 :    *
      80                 :    * post condition:  1 <= bias < range_max.
      81                 :    */
      82                 : 
      83                 : 
      84                 :   do {
      85               3 :     v = (*self->vtbl->GenUint32)(self);
      86                 :     /* v is uniform in [0, 2^{32}) */
      87               3 :   } while (v < bias);
      88                 :   /*
      89                 :    * v is uniform in [bias, 2^{32}).
      90                 :    *
      91                 :    * the number of integers in the half-open interval is
      92                 :    *
      93                 :    *   2^{32} - bias = 2^{32} - ((2^{32}-1 \bmod range_max + 1))
      94                 :    *                 = 2^{32}-1 - (2^{32}-1 \bmod range_max)
      95                 :    *                 = range_max * \lfloor (2^{32}-1)/range_max \rfloor
      96                 :    *
      97                 :    * and range_max clearly divides the size of the range.
      98                 :    *
      99                 :    * The mapping v \rightarrow v % range_max takes values from [bias,
     100                 :    * 2^{32}) to [0, range_max).  Each integer in the range interval
     101                 :    * [0, range_max) will have exactly \lfloor (2^{32}-1)/range_max
     102                 :    * \rfloor preimages from the domain interval.
     103                 :    *
     104                 :    * Therefore, v % range_max is uniform over [0, range_max).  QED.
     105                 :    */
     106                 : 
     107               3 :   return v % range_max;
     108               3 : }

Generated by: LCOV version 1.7