1386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 2386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * stats.c 3386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 4386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * statistical tests for randomness (FIPS 140-2, Section 4.9) 5386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 6386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * David A. McGrew 7386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * Cisco Systems, Inc. 8386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 9386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 10386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#include "stat.h" 11386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 12386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaridebug_module_t mod_stat = { 13386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 0, /* debugging is off by default */ 14386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari (char *)"stat test" /* printable module name */ 15386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari}; 16386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 17386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 18386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * each test assumes that 20,000 bits (2500 octets) of data is 19386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * provided as input 20386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 21386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 22386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define STAT_TEST_DATA_LEN 2500 23386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 24386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t 25386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaristat_test_monobit(uint8_t *data) { 26386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t *data_end = data + STAT_TEST_DATA_LEN; 27386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t ones_count; 28386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 29386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari ones_count = 0; 30386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari while (data < data_end) { 31386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari ones_count += octet_get_weight(*data); 32386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari data++; 33386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 34386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 35386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "bit count: %d", ones_count); 36386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 37386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if ((ones_count < 9725) || (ones_count > 10275)) 38386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 39386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 40386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_ok; 41386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 42386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 43386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t 44386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaristat_test_poker(uint8_t *data) { 45386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int i; 46386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t *data_end = data + STAT_TEST_DATA_LEN; 47386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari double poker; 48386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t f[16] = { 49386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 0, 0, 0, 0, 0, 0, 0, 0, 50386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 0, 0, 0, 0, 0, 0, 0, 0 51386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari }; 52386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 53386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari while (data < data_end) { 54386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari f[*data & 0x0f]++; /* increment freq. count for low nibble */ 55386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari f[(*data) >> 4]++; /* increment freq. count for high nibble */ 56386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari data++; 57386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 58386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 59386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker = 0.0; 60386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < 16; i++) 61386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker += (double) f[i] * f[i]; 62386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 63386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker *= (16.0 / 5000.0); 64386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker -= 5000.0; 65386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 66386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "poker test: %f\n", poker); 67386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 68386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if ((poker < 2.16) || (poker > 46.17)) 69386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 70386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 71386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_ok; 72386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 73386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 74386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 75386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 76386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * runs[i] holds the number of runs of size (i-1) 77386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 78386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 79386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t 80386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaristat_test_runs(uint8_t *data) { 81386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t *data_end = data + STAT_TEST_DATA_LEN; 82386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; 83386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 }; 84386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 }; 85386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 }; 86386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int state = 0; 87386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t mask; 88386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int i; 89386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 90386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* 91386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the state variable holds the number of bits in the 92386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * current run (or gap, if negative) 93386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 94386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 95386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari while (data < data_end) { 96386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 97386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* loop over the bits of this byte */ 98386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (mask = 1; mask < 256; mask <<= 1) { 99386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (*data & mask) { 100386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 101386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* next bit is a one */ 102386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 0) { 103386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 104386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a run, so increment the run-count */ 105386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state++; 106386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 107386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check for long runs */ 108386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 25) { 109386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 runs: %d", state); 110386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 111386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 112386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 113386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else if (state < 0) { 114386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 115386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a gap */ 116386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state < -25) { 117386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 gaps: %d", state); 118386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; /* long-runs test failed */ 119386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 120386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state < -6) { 121386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = -6; /* group together gaps > 5 */ 122386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 123386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari gaps[-1-state]++; /* increment gap count */ 124386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = 1; /* set state at one set bit */ 125386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else { 126386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 127386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* state is zero; this happens only at initialization */ 128386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = 1; 129386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 130386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else { 131386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 132386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* next bit is a zero */ 133386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 0) { 134386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 135386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a run */ 136386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 25) { 137386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 runs (2): %d", state); 138386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; /* long-runs test failed */ 139386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 140386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 6) { 141386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = 6; /* group together runs > 5 */ 142386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 143386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari runs[state-1]++; /* increment run count */ 144386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = -1; /* set state at one zero bit */ 145386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else if (state < 0) { 146386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 147386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a gap, so increment gap-count (decrement state) */ 148386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state--; 149386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 150386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check for long gaps */ 151386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state < -25) { 152386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 gaps (2): %d", state); 153386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 154386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 155386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 156386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else { 157386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 158386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* state is zero; this happens only at initialization */ 159386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = -1; 160386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 161386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 162386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 163386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 164386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* move along to next octet */ 165386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari data++; 166386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 167386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 168386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (mod_stat.on) { 169386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "runs test", NULL); 170386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < 6; i++) 171386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, " runs[]: %d", runs[i]); 172386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < 6; i++) 173386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, " gaps[]: %d", gaps[i]); 174386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 175386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 176386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check run and gap counts against the fixed limits */ 177386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < 6; i++) 178386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if ( (runs[i] < lo_value[i] ) || (runs[i] > hi_value[i]) 179386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i])) 180386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 181386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 182386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 183386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_ok; 184386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 185386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 186386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 187386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari/* 188386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * the function stat_test_rand_source applys the FIPS-140-2 statistical 189386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * tests to the random source defined by rs 190386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari * 191386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari */ 192386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 193386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#define RAND_SRC_BUF_OCTETS 50 /* this value MUST divide 2500! */ 194386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 195386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t 196386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaristat_test_rand_source(rand_source_func_t get_rand_bytes) { 197386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int i; 198386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari double poker; 199386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t *data, *data_end; 200386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t f[16] = { 201386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 0, 0, 0, 0, 0, 0, 0, 0, 202386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 0, 0, 0, 0, 0, 0, 0, 0 203386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari }; 204386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint8_t buffer[RAND_SRC_BUF_OCTETS]; 205386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari err_status_t status; 206386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int ones_count = 0; 207386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; 208386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 }; 209386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 }; 210386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 }; 211386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari int state = 0; 212386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari uint16_t mask; 213386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 214386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* counters for monobit, poker, and runs tests are initialized above */ 215386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 216386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* main loop: fill buffer, update counters for stat tests */ 217386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < 2500; i+=RAND_SRC_BUF_OCTETS) { 218386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 219386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* fill data buffer */ 220386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari status = get_rand_bytes(buffer, RAND_SRC_BUF_OCTETS); 221386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (status) { 222386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "couldn't get rand bytes: %d",status); 223386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return status; 224386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 225386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 226386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#if 0 227386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "%s", 228386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari octet_string_hex_string(buffer, RAND_SRC_BUF_OCTETS)); 229386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari#endif 230386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 231386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari data = buffer; 232386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari data_end = data + RAND_SRC_BUF_OCTETS; 233386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari while (data < data_end) { 234386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 235386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* update monobit test counter */ 236386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari ones_count += octet_get_weight(*data); 237386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 238386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* update poker test counters */ 239386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari f[*data & 0x0f]++; /* increment freq. count for low nibble */ 240386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari f[(*data) >> 4]++; /* increment freq. count for high nibble */ 241386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 242386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* update runs test counters */ 243386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* loop over the bits of this byte */ 244386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (mask = 1; mask < 256; mask <<= 1) { 245386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (*data & mask) { 246386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 247386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* next bit is a one */ 248386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 0) { 249386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 250386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a run, so increment the run-count */ 251386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state++; 252386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 253386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check for long runs */ 254386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 25) { 255386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 runs (3): %d", state); 256386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 257386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 258386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 259386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else if (state < 0) { 260386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 261386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a gap */ 262386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state < -25) { 263386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 gaps (3): %d", state); 264386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; /* long-runs test failed */ 265386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 266386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state < -6) { 267386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = -6; /* group together gaps > 5 */ 268386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 269386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari gaps[-1-state]++; /* increment gap count */ 270386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = 1; /* set state at one set bit */ 271386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else { 272386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 273386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* state is zero; this happens only at initialization */ 274386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = 1; 275386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 276386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else { 277386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 278386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* next bit is a zero */ 279386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 0) { 280386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 281386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a run */ 282386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 25) { 283386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 runs (4): %d", state); 284386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; /* long-runs test failed */ 285386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 286386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state > 6) { 287386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = 6; /* group together runs > 5 */ 288386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 289386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari runs[state-1]++; /* increment run count */ 290386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = -1; /* set state at one zero bit */ 291386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else if (state < 0) { 292386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 293386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* prefix is a gap, so increment gap-count (decrement state) */ 294386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state--; 295386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 296386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check for long gaps */ 297386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (state < -25) { 298386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, ">25 gaps (4): %d", state); 299386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 300386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 301386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 302386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } else { 303386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 304386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* state is zero; this happens only at initialization */ 305386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari state = -1; 306386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 307386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 308386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 309386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 310386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* advance data pointer */ 311386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari data++; 312386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 313386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 314386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 315386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check to see if test data is within bounds */ 316386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 317386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check monobit test data */ 318386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 319386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "stat: bit count: %d", ones_count); 320386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 321386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if ((ones_count < 9725) || (ones_count > 10275)) { 322386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "stat: failed monobit test %d", ones_count); 323386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 324386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 325386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 326386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check poker test data */ 327386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker = 0.0; 328386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < 16; i++) 329386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker += (double) f[i] * f[i]; 330386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 331386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker *= (16.0 / 5000.0); 332386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari poker -= 5000.0; 333386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 334386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "stat: poker test: %f", poker); 335386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 336386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if ((poker < 2.16) || (poker > 46.17)) { 337386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "stat: failed poker test", NULL); 338386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 339386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 340386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 341386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari /* check run and gap counts against the fixed limits */ 342386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < 6; i++) 343386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if ((runs[i] < lo_value[i] ) || (runs[i] > hi_value[i]) 344386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i])) { 345386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "stat: failed run/gap test", NULL); 346386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_algo_fail; 347386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 348386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 349386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "passed random stat test", NULL); 350386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_ok; 351386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 352386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 353386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagarierr_status_t 354386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagaristat_test_rand_source_with_repetition(rand_source_func_t source, unsigned num_trials) { 355386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari unsigned int i; 356386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari err_status_t err = err_status_algo_fail; 357386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 358386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari for (i=0; i < num_trials; i++) { 359386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari err = stat_test_rand_source(source); 360386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari if (err == err_status_ok) { 361386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err_status_ok; 362386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 363386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari debug_print(mod_stat, "failed stat test (try number %d)\n", i); 364386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari } 365386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari 366386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari return err; 367386ce4d9144fc190797f4e43a31aeaf76ca2e373Param Reddappagari} 368