LCOV - code coverage report
Current view: directory - src/shared/platform/linux - nacl_secure_random.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 42 40 95.2 %
Date: 2012-02-16 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 implementation.
       9                 :  */
      10                 : 
      11                 : #include <string.h>
      12                 : 
      13                 : #include <unistd.h>
      14                 : #include <sys/types.h>
      15                 : #include <sys/stat.h>
      16                 : #include <fcntl.h>
      17                 : 
      18                 : #include "native_client/src/shared/platform/nacl_check.h"
      19                 : #include "native_client/src/shared/platform/nacl_log.h"
      20                 : #include "native_client/src/shared/platform/nacl_secure_random.h"
      21                 : 
      22                 : #ifndef NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE
      23                 : # define NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE "/dev/urandom"
      24                 : #endif
      25                 : 
      26                 : static struct NaClSecureRngIfVtbl const kNaClSecureRngVtbl;
      27                 : 
      28                 : /* use -1 to ensure a fast failure if module initializer is not called */
      29                 : static int  urandom_d = -1;
      30                 : 
      31                 : #define SANDBOXED_INITIALIZATION (!defined(NACL_STANDALONE))
      32                 : 
      33                 : #if SANDBOXED_INITIALIZATION
      34                 : 
      35                 : # include "base/rand_util_c.h"
      36                 : 
      37                 : void NaClSecureRngModuleInit(void) {
      38                 :   urandom_d = dup(GetUrandomFD());
      39                 : }
      40                 : 
      41                 : #else
      42                 : 
      43              45 : void NaClSecureRngModuleInit(void) {
      44              45 :   urandom_d = open(NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE, O_RDONLY, 0);
      45              45 :   if (-1 == urandom_d) {
      46               0 :     NaClLog(LOG_FATAL, "Cannot open system random source %s\n",
      47                 :             NACL_SECURE_RANDOM_SYSTEM_RANDOM_SOURCE);
      48                 :   }
      49              45 : }
      50                 : 
      51                 : #endif  /* !SANDBOXED_INITIALIZATION */
      52                 : 
      53              29 : void NaClSecureRngModuleFini(void) {
      54              29 :   (void) close(urandom_d);
      55              29 :   urandom_d = -1;
      56              29 : }
      57                 : 
      58                 : #if USE_CRYPTO
      59                 : 
      60                 : static int NaClSecureRngCtorCommon(struct NaClSecureRng *self,
      61              66 :                                    unsigned char        *key) {
      62              66 :   self->base.vtbl = &kNaClSecureRngVtbl;
      63              66 :   AES_set_encrypt_key(key, AES_BLOCK_SIZE * 8, &self->expanded_key);
      64              66 :   memset(self->counter, 0, sizeof self->counter);
      65              66 :   self->nvalid = 0;
      66                 : 
      67              66 :   memset(key, 0, AES_BLOCK_SIZE);
      68              66 :   return 1;
      69                 : }
      70                 : 
      71              65 : int NaClSecureRngCtor(struct NaClSecureRng *self) {
      72                 :   unsigned char key[AES_BLOCK_SIZE];
      73                 : 
      74              65 :   self->base.vtbl = NULL;
      75                 :   /*
      76                 :    * Windows version should get seed bytes from CryptoAPI's
      77                 :    * CryptGenRandom.  Whether we want to use that as seed as here, or
      78                 :    * as the generator for everything depends on how expensive it is
      79                 :    * (and whether it matters for our usage).
      80                 :    */
      81                 : 
      82              65 :   VCHECK(-1 != urandom_d,
      83                 :          ("NaClSecureRngCtor: random descriptor invalid;"
      84                 :           " module initialization failed?\n"));
      85              65 :   if (sizeof key != read(urandom_d, key, sizeof key)) {
      86               0 :     return 0;
      87                 :   }
      88              65 :   return NaClSecureRngCtorCommon(self, key);
      89                 : }
      90                 : 
      91                 : int NaClSecureRngTestingCtor(struct NaClSecureRng *self,
      92                 :                              uint8_t              *seed_material,
      93               1 :                              size_t               seed_bytes) {
      94                 :   unsigned char key[AES_BLOCK_SIZE];
      95                 : 
      96               1 :   self->base.vtbl = NULL;
      97               1 :   memset(key, 0, sizeof key);
      98               1 :   memcpy(key, seed_material, seed_bytes > sizeof key ? sizeof key : seed_bytes);
      99               1 :   return NaClSecureRngCtorCommon(self, key);
     100                 : }
     101                 : 
     102              31 : static void NaClSecureRngDtor(struct NaClSecureRngIf *self) {
     103              31 :   memset(self, 0, sizeof(struct NaClSecureRng));
     104                 :   /* self->base.vtbl = NULL; */
     105              31 : }
     106                 : 
     107          182994 : static void NaClSecureRngCycle(struct NaClSecureRng *self) {
     108                 :   int ix;
     109                 : 
     110          182994 :   AES_encrypt(self->counter, self->randbytes, &self->expanded_key);
     111          182994 :   self->nvalid = NACL_RANDOM_EXPOSE_BYTES;
     112                 :   /*
     113                 :    * odometric counter, low probability of carry, and byte order
     114                 :    * independent as opposed to loading as words, incrementing, and
     115                 :    * storing back, etc.
     116                 :    *
     117                 :    * counter value v = \sum_{i=0}{AES_BLOCK_SIZE-1} self->counter[i] * 256^{i}
     118                 :    */
     119          183710 :   for (ix = 0; ix < AES_BLOCK_SIZE; ++ix) {
     120          183710 :     if (0 != ++self->counter[ix]) {
     121          182994 :       break;
     122                 :     }
     123                 :   }
     124          182994 : }
     125                 : 
     126         1463940 : static uint8_t NaClSecureRngGenByte(struct NaClSecureRngIf *vself) {
     127         1463940 :   struct NaClSecureRng *self = (struct NaClSecureRng *) vself;
     128                 : 
     129         1463940 :   if (self->nvalid <= 0) {
     130          182994 :     NaClSecureRngCycle(self);
     131                 :   }
     132                 :   /*
     133                 :    * 0 < self->nvalid <= NACL_RANDOM_EXPOSE_BYTES <= AES_BLOCK_SIZE
     134                 :    */
     135         1463940 :   return (char) self->randbytes[--self->nvalid];
     136                 : }
     137                 : 
     138                 : #else
     139                 : 
     140                 : int NaClSecureRngCtor(struct NaClSecureRng *self) {
     141                 :   self->base.vtbl = &kNaClSecureRngVtbl;
     142                 :   self->nvalid = 0;
     143                 :   return 1;
     144                 : }
     145                 : 
     146                 : int NaClSecureRngTestingCtor(struct NaClSecureRng *self,
     147                 :                              uint8_t              *seed_material,
     148                 :                              size_t               seed_bytes) {
     149                 :   UNREFERENCED_PARAMETER(self);
     150                 :   UNREFERENCED_PARAMETER(seed_material);
     151                 :   UNREFERENCED_PARAMETER(seed_bytes);
     152                 :   return 0;
     153                 : }
     154                 : 
     155                 : static void NaClSecureRngDtor(struct NaClSecureRngIf *vself) {
     156                 :   vself->vtbl = NULL;
     157                 :   return;
     158                 : }
     159                 : 
     160                 : static void NaClSecureRngFilbuf(struct NaClSecureRng *self) {
     161                 :   VCHECK(-1 != urandom_d,
     162                 :          ("NaClSecureRngCtor: random descriptor invalid;"
     163                 :           " module initialization failed?\n"));
     164                 :   self->nvalid = read(urandom_d, self->buf, sizeof self->buf);
     165                 :   if (self->nvalid <= 0) {
     166                 :     NaClLog(LOG_FATAL, "NaClSecureRngFilbuf failed, read returned %d\n",
     167                 :             self->nvalid);
     168                 :   }
     169                 : }
     170                 : 
     171                 : static uint8_t NaClSecureRngGenByte(struct NaClSecureRngIf *vself) {
     172                 :   struct NaClSecureRng *self = (struct NaClSecureRng *) vself;
     173                 : 
     174                 :   if (0 > self->nvalid) {
     175                 :     NaClLog(LOG_FATAL,
     176                 :             "NaClSecureRngGenByte: illegal buffer state, nvalid = %d\n",
     177                 :             self->nvalid);
     178                 :   }
     179                 :   if (0 == self->nvalid) {
     180                 :     NaClSecureRngFilbuf(self);
     181                 :   }
     182                 :   /* 0 < self->nvalid <= sizeof self->buf */
     183                 :   return self->buf[--self->nvalid];
     184                 : }
     185                 : 
     186                 : #endif
     187                 : 
     188                 : static struct NaClSecureRngIfVtbl const kNaClSecureRngVtbl = {
     189                 :   NaClSecureRngDtor,
     190                 :   NaClSecureRngGenByte,
     191                 :   NaClSecureRngDefaultGenUint32,
     192                 :   NaClSecureRngDefaultGenBytes,
     193                 :   NaClSecureRngDefaultUniform,
     194                 : };

Generated by: LCOV version 1.7