netwerk/srtp/src/crypto/math/stat.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial