LCOV - code coverage report
Current view: top level - netwerk/srtp/src/crypto/math - stat.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 133 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * stats.c
       3             :  *
       4             :  * statistical tests for randomness (FIPS 140-2, Section 4.9)
       5             :  * 
       6             :  * David A. McGrew
       7             :  * Cisco Systems, Inc.
       8             :  */
       9             : /*
      10             :  *      
      11             :  * Copyright (c) 2001-2006, Cisco Systems, Inc.
      12             :  * All rights reserved.
      13             :  * 
      14             :  * Redistribution and use in source and binary forms, with or without
      15             :  * modification, are permitted provided that the following conditions
      16             :  * are met:
      17             :  * 
      18             :  *   Redistributions of source code must retain the above copyright
      19             :  *   notice, this list of conditions and the following disclaimer.
      20             :  * 
      21             :  *   Redistributions in binary form must reproduce the above
      22             :  *   copyright notice, this list of conditions and the following
      23             :  *   disclaimer in the documentation and/or other materials provided
      24             :  *   with the distribution.
      25             :  * 
      26             :  *   Neither the name of the Cisco Systems, Inc. nor the names of its
      27             :  *   contributors may be used to endorse or promote products derived
      28             :  *   from this software without specific prior written permission.
      29             :  * 
      30             :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      31             :  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      32             :  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      33             :  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      34             :  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      35             :  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      36             :  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      37             :  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      38             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      39             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      40             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
      41             :  * OF THE POSSIBILITY OF SUCH DAMAGE.
      42             :  *
      43             :  */
      44             : 
      45             : #include "stat.h"
      46             : 
      47             : debug_module_t mod_stat = {
      48             :   0,                 /* debugging is off by default */
      49             :   (char *)"stat test"        /* printable module name       */
      50             : };
      51             : 
      52             : /*
      53             :  * each test assumes that 20,000 bits (2500 octets) of data is
      54             :  * provided as input
      55             :  */
      56             : 
      57             : #define STAT_TEST_DATA_LEN 2500
      58             : 
      59             : err_status_t
      60           0 : stat_test_monobit(uint8_t *data) {
      61           0 :   uint8_t *data_end = data + STAT_TEST_DATA_LEN;
      62             :   uint16_t ones_count;
      63             : 
      64           0 :   ones_count = 0;
      65           0 :   while (data < data_end) {
      66           0 :     ones_count += octet_get_weight(*data);
      67           0 :     data++;
      68             :   }
      69             : 
      70             :   debug_print(mod_stat, "bit count: %d", ones_count);
      71             :   
      72           0 :   if ((ones_count < 9725) || (ones_count > 10275))
      73           0 :     return err_status_algo_fail;
      74             : 
      75           0 :   return err_status_ok;
      76             : }
      77             : 
      78             : err_status_t
      79           0 : stat_test_poker(uint8_t *data) {
      80             :   int i;
      81           0 :   uint8_t *data_end = data + STAT_TEST_DATA_LEN;
      82             :   double poker;
      83           0 :   uint16_t f[16] = {
      84             :     0, 0, 0, 0, 0, 0, 0, 0,
      85             :     0, 0, 0, 0, 0, 0, 0, 0
      86             :   };
      87             :   
      88           0 :   while (data < data_end) {
      89           0 :     f[*data & 0x0f]++;    /* increment freq. count for low nibble  */
      90           0 :     f[(*data) >> 4]++;    /* increment freq. count for high nibble */
      91           0 :     data++;
      92             :   }
      93             : 
      94           0 :   poker = 0.0;
      95           0 :   for (i=0; i < 16; i++) 
      96           0 :     poker += (double) f[i] * f[i];
      97             : 
      98           0 :   poker *= (16.0 / 5000.0);
      99           0 :   poker -= 5000.0;
     100             : 
     101             :   debug_print(mod_stat, "poker test: %f\n", poker);
     102             :     
     103           0 :   if ((poker < 2.16) || (poker > 46.17))
     104           0 :     return err_status_algo_fail;
     105             :   
     106           0 :   return err_status_ok;
     107             : }
     108             : 
     109             : 
     110             : /*
     111             :  * runs[i] holds the number of runs of size (i-1)
     112             :  */
     113             : 
     114             : err_status_t
     115           0 : stat_test_runs(uint8_t *data) {
     116           0 :   uint8_t *data_end = data + STAT_TEST_DATA_LEN;
     117           0 :   uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; 
     118           0 :   uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
     119           0 :   uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
     120           0 :   uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
     121           0 :   int state = 0;
     122             :   uint16_t mask;
     123             :   int i;
     124             :   
     125             :   /*
     126             :    * the state variable holds the number of bits in the
     127             :    * current run (or gap, if negative)
     128             :    */
     129             :   
     130           0 :   while (data < data_end) {
     131             : 
     132             :     /* loop over the bits of this byte */
     133           0 :     for (mask = 1; mask < 256; mask <<= 1) {
     134           0 :       if (*data & mask) {
     135             : 
     136             :         /* next bit is a one  */
     137           0 :         if (state > 0) {
     138             : 
     139             :           /* prefix is a run, so increment the run-count  */
     140           0 :           state++;                          
     141             : 
     142             :           /* check for long runs */ 
     143           0 :           if (state > 25) {
     144             :                 debug_print(mod_stat, ">25 runs: %d", state);
     145           0 :                 return err_status_algo_fail;
     146             :           }
     147             : 
     148           0 :         } else if (state < 0) {
     149             : 
     150             :           /* prefix is a gap  */
     151           0 :           if (state < -25) {
     152             :                 debug_print(mod_stat, ">25 gaps: %d", state);
     153           0 :             return err_status_algo_fail;    /* long-runs test failed   */
     154             :           }
     155           0 :           if (state < -6) {
     156           0 :             state = -6;                     /* group together gaps > 5 */
     157             :           }
     158           0 :           gaps[-1-state]++;                 /* increment gap count      */
     159           0 :           state = 1;                        /* set state at one set bit */
     160             :         } else {
     161             : 
     162             :           /* state is zero; this happens only at initialization        */
     163           0 :           state = 1;            
     164             :         }
     165             :       } else {
     166             : 
     167             :         /* next bit is a zero  */
     168           0 :         if (state > 0) {
     169             : 
     170             :           /* prefix is a run */
     171           0 :           if (state > 25) {
     172             :                 debug_print(mod_stat, ">25 runs (2): %d", state);
     173           0 :             return err_status_algo_fail;    /* long-runs test failed   */
     174             :           }
     175           0 :           if (state > 6) {
     176           0 :             state = 6;                      /* group together runs > 5 */
     177             :           }
     178           0 :           runs[state-1]++;                  /* increment run count       */
     179           0 :           state = -1;                       /* set state at one zero bit */
     180           0 :         } else if (state < 0) {
     181             : 
     182             :           /* prefix is a gap, so increment gap-count (decrement state) */
     183           0 :           state--;
     184             : 
     185             :           /* check for long gaps */ 
     186           0 :           if (state < -25) {
     187             :                 debug_print(mod_stat, ">25 gaps (2): %d", state);
     188           0 :             return err_status_algo_fail;
     189             :           }
     190             : 
     191             :         } else {
     192             : 
     193             :           /* state is zero; this happens only at initialization        */
     194           0 :           state = -1;
     195             :         }
     196             :       }
     197             :     }
     198             : 
     199             :     /* move along to next octet */
     200           0 :     data++;
     201             :   }
     202             : 
     203           0 :   if (mod_stat.on) {
     204             :     debug_print(mod_stat, "runs test", NULL);
     205           0 :     for (i=0; i < 6; i++)
     206             :       debug_print(mod_stat, "  runs[]: %d", runs[i]);
     207           0 :     for (i=0; i < 6; i++)
     208             :       debug_print(mod_stat, "  gaps[]: %d", gaps[i]);
     209             :   }
     210             : 
     211             :   /* check run and gap counts against the fixed limits */
     212           0 :   for (i=0; i < 6; i++) 
     213           0 :     if (   (runs[i] < lo_value[i] ) || (runs[i] > hi_value[i])
     214           0 :         || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i]))
     215           0 :       return err_status_algo_fail;
     216             : 
     217             :   
     218           0 :   return err_status_ok;
     219             : }
     220             : 
     221             : 
     222             : /*
     223             :  * the function stat_test_rand_source applys the FIPS-140-2 statistical
     224             :  * tests to the random source defined by rs
     225             :  *
     226             :  */
     227             : 
     228             : #define RAND_SRC_BUF_OCTETS 50 /* this value MUST divide 2500! */ 
     229             : 
     230             : err_status_t
     231           0 : stat_test_rand_source(rand_source_func_t get_rand_bytes) {
     232             :   int i;
     233             :   double poker;
     234             :   uint8_t *data, *data_end;
     235           0 :   uint16_t f[16] = {
     236             :     0, 0, 0, 0, 0, 0, 0, 0,
     237             :     0, 0, 0, 0, 0, 0, 0, 0
     238             :   };
     239             :   uint8_t buffer[RAND_SRC_BUF_OCTETS];
     240             :   err_status_t status;
     241           0 :   int ones_count = 0;
     242           0 :   uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; 
     243           0 :   uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
     244           0 :   uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
     245           0 :   uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
     246           0 :   int state = 0;
     247             :   uint16_t mask;
     248             :   
     249             :   /* counters for monobit, poker, and runs tests are initialized above */
     250             : 
     251             :   /* main loop: fill buffer, update counters for stat tests */
     252           0 :   for (i=0; i < 2500; i+=RAND_SRC_BUF_OCTETS) {
     253             :     
     254             :     /* fill data buffer */
     255           0 :     status = get_rand_bytes(buffer, RAND_SRC_BUF_OCTETS);
     256           0 :     if (status) {
     257             :           debug_print(mod_stat, "couldn't get rand bytes: %d",status);
     258           0 :       return status;
     259             :         }
     260             : 
     261             : #if 0
     262             :     debug_print(mod_stat, "%s", 
     263             :                 octet_string_hex_string(buffer, RAND_SRC_BUF_OCTETS));
     264             : #endif
     265             :   
     266           0 :     data = buffer;
     267           0 :     data_end = data + RAND_SRC_BUF_OCTETS;
     268           0 :     while (data < data_end) {
     269             : 
     270             :       /* update monobit test counter */
     271           0 :       ones_count += octet_get_weight(*data);
     272             : 
     273             :       /* update poker test counters */
     274           0 :       f[*data & 0x0f]++;    /* increment freq. count for low nibble  */
     275           0 :       f[(*data) >> 4]++;    /* increment freq. count for high nibble */
     276             : 
     277             :       /* update runs test counters */
     278             :       /* loop over the bits of this byte */
     279           0 :       for (mask = 1; mask < 256; mask <<= 1) {
     280           0 :         if (*data & mask) {
     281             :           
     282             :           /* next bit is a one  */
     283           0 :           if (state > 0) {
     284             :             
     285             :             /* prefix is a run, so increment the run-count  */
     286           0 :             state++;                          
     287             :             
     288             :             /* check for long runs */ 
     289           0 :             if (state > 25) {
     290             :                   debug_print(mod_stat, ">25 runs (3): %d", state);
     291           0 :               return err_status_algo_fail;
     292             :                 }
     293             :             
     294           0 :           } else if (state < 0) {
     295             :             
     296             :             /* prefix is a gap  */
     297           0 :             if (state < -25) {
     298             :                   debug_print(mod_stat, ">25 gaps (3): %d", state);
     299           0 :               return err_status_algo_fail;    /* long-runs test failed   */
     300             :             }
     301           0 :             if (state < -6) {
     302           0 :               state = -6;                     /* group together gaps > 5 */
     303             :             }
     304           0 :             gaps[-1-state]++;                 /* increment gap count      */
     305           0 :             state = 1;                        /* set state at one set bit */
     306             :           } else {
     307             :             
     308             :             /* state is zero; this happens only at initialization        */
     309           0 :             state = 1;            
     310             :           }
     311             :         } else {
     312             :           
     313             :           /* next bit is a zero  */
     314           0 :           if (state > 0) {
     315             :             
     316             :             /* prefix is a run */
     317           0 :             if (state > 25) {
     318             :                   debug_print(mod_stat, ">25 runs (4): %d", state);
     319           0 :               return err_status_algo_fail;    /* long-runs test failed   */
     320             :             }
     321           0 :             if (state > 6) {
     322           0 :               state = 6;                      /* group together runs > 5 */
     323             :             }
     324           0 :             runs[state-1]++;                  /* increment run count       */
     325           0 :             state = -1;                       /* set state at one zero bit */
     326           0 :           } else if (state < 0) {
     327             :             
     328             :             /* prefix is a gap, so increment gap-count (decrement state) */
     329           0 :             state--;
     330             :             
     331             :             /* check for long gaps */ 
     332           0 :             if (state < -25) {
     333             :                   debug_print(mod_stat, ">25 gaps (4): %d", state);
     334           0 :               return err_status_algo_fail;
     335             :                 }
     336             :             
     337             :           } else {
     338             :             
     339             :             /* state is zero; this happens only at initialization        */
     340           0 :             state = -1;
     341             :           }
     342             :         }
     343             :       }
     344             :       
     345             :       /* advance data pointer */
     346           0 :       data++;
     347             :     }
     348             :   }
     349             : 
     350             :   /* check to see if test data is within bounds */
     351             : 
     352             :   /* check monobit test data */
     353             : 
     354             :   debug_print(mod_stat, "stat: bit count: %d", ones_count);
     355             :   
     356           0 :   if ((ones_count < 9725) || (ones_count > 10275)) {
     357             :     debug_print(mod_stat, "stat: failed monobit test %d", ones_count);
     358           0 :     return err_status_algo_fail;
     359             :   }
     360             :   
     361             :   /* check poker test data */
     362           0 :   poker = 0.0;
     363           0 :   for (i=0; i < 16; i++) 
     364           0 :     poker += (double) f[i] * f[i];
     365             : 
     366           0 :   poker *= (16.0 / 5000.0);
     367           0 :   poker -= 5000.0;
     368             : 
     369             :   debug_print(mod_stat, "stat: poker test: %f", poker);
     370             :     
     371           0 :   if ((poker < 2.16) || (poker > 46.17)) {
     372             :     debug_print(mod_stat, "stat: failed poker test", NULL);
     373           0 :     return err_status_algo_fail;
     374             :   }
     375             : 
     376             :   /* check run and gap counts against the fixed limits */
     377           0 :   for (i=0; i < 6; i++) 
     378           0 :     if ((runs[i] < lo_value[i] ) || (runs[i] > hi_value[i])
     379           0 :          || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i])) {
     380             :       debug_print(mod_stat, "stat: failed run/gap test", NULL);
     381           0 :       return err_status_algo_fail; 
     382             :     }
     383             : 
     384             :   debug_print(mod_stat, "passed random stat test", NULL);
     385           0 :   return err_status_ok;
     386             : }
     387             : 
     388             : err_status_t
     389           0 : stat_test_rand_source_with_repetition(rand_source_func_t source, unsigned num_trials) {
     390             :   unsigned int i;
     391           0 :   err_status_t err = err_status_algo_fail;
     392             : 
     393           0 :   for (i=0; i < num_trials; i++) {
     394           0 :     err = stat_test_rand_source(source);
     395           0 :     if (err == err_status_ok) {
     396           0 :       return err_status_ok;  
     397             :     }
     398             :     debug_print(mod_stat, "failed stat test (try number %d)\n", i);
     399             :   }
     400             :   
     401           0 :   return err;
     402             : }

Generated by: LCOV version 1.13