OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * stats.c |
| 3 * |
| 4 * statistical tests |
| 5 * |
| 6 * David A. McGrew |
| 7 * Cisco Systems, Inc. |
| 8 */ |
| 9 |
| 10 /* |
| 11 * |
| 12 * Copyright (c) 2001-2006, Cisco Systems, Inc. |
| 13 * All rights reserved. |
| 14 * |
| 15 * Redistribution and use in source and binary forms, with or without |
| 16 * modification, are permitted provided that the following conditions |
| 17 * are met: |
| 18 * |
| 19 * Redistributions of source code must retain the above copyright |
| 20 * notice, this list of conditions and the following disclaimer. |
| 21 * |
| 22 * Redistributions in binary form must reproduce the above |
| 23 * copyright notice, this list of conditions and the following |
| 24 * disclaimer in the documentation and/or other materials provided |
| 25 * with the distribution. |
| 26 * |
| 27 * Neither the name of the Cisco Systems, Inc. nor the names of its |
| 28 * contributors may be used to endorse or promote products derived |
| 29 * from this software without specific prior written permission. |
| 30 * |
| 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 34 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| 35 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| 36 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 38 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 41 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
| 42 * OF THE POSSIBILITY OF SUCH DAMAGE. |
| 43 * |
| 44 */ |
| 45 |
| 46 #ifdef HAVE_CONFIG_H |
| 47 #include <config.h> |
| 48 #endif |
| 49 |
| 50 #include "stat.h" |
| 51 |
| 52 srtp_debug_module_t mod_stat = { |
| 53 0, /* debugging is off by default */ |
| 54 (char *)"stat test" /* printable module name */ |
| 55 }; |
| 56 |
| 57 /* |
| 58 * each test assumes that 20,000 bits (2500 octets) of data is |
| 59 * provided as input |
| 60 */ |
| 61 |
| 62 #define STAT_TEST_DATA_LEN 2500 |
| 63 |
| 64 srtp_err_status_t |
| 65 stat_test_monobit(uint8_t *data) { |
| 66 uint8_t *data_end = data + STAT_TEST_DATA_LEN; |
| 67 uint16_t ones_count; |
| 68 |
| 69 ones_count = 0; |
| 70 while (data < data_end) { |
| 71 ones_count += octet_get_weight(*data); |
| 72 data++; |
| 73 } |
| 74 |
| 75 debug_print(mod_stat, "bit count: %d", ones_count); |
| 76 |
| 77 if ((ones_count < 9725) || (ones_count > 10275)) |
| 78 return srtp_err_status_algo_fail; |
| 79 |
| 80 return srtp_err_status_ok; |
| 81 } |
| 82 |
| 83 srtp_err_status_t |
| 84 stat_test_poker(uint8_t *data) { |
| 85 int i; |
| 86 uint8_t *data_end = data + STAT_TEST_DATA_LEN; |
| 87 double poker; |
| 88 uint16_t f[16] = { |
| 89 0, 0, 0, 0, 0, 0, 0, 0, |
| 90 0, 0, 0, 0, 0, 0, 0, 0 |
| 91 }; |
| 92 |
| 93 while (data < data_end) { |
| 94 f[*data & 0x0f]++; /* increment freq. count for low nibble */ |
| 95 f[(*data) >> 4]++; /* increment freq. count for high nibble */ |
| 96 data++; |
| 97 } |
| 98 |
| 99 poker = 0.0; |
| 100 for (i=0; i < 16; i++) |
| 101 poker += (double) f[i] * f[i]; |
| 102 |
| 103 poker *= (16.0 / 5000.0); |
| 104 poker -= 5000.0; |
| 105 |
| 106 debug_print(mod_stat, "poker test: %f\n", poker); |
| 107 |
| 108 if ((poker < 2.16) || (poker > 46.17)) |
| 109 return srtp_err_status_algo_fail; |
| 110 |
| 111 return srtp_err_status_ok; |
| 112 } |
| 113 |
| 114 |
| 115 /* |
| 116 * runs[i] holds the number of runs of size (i-1) |
| 117 */ |
| 118 |
| 119 srtp_err_status_t |
| 120 stat_test_runs(uint8_t *data) { |
| 121 uint8_t *data_end = data + STAT_TEST_DATA_LEN; |
| 122 uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 }; |
| 123 uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 }; |
| 124 uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 }; |
| 125 uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 }; |
| 126 int state = 0; |
| 127 uint16_t mask; |
| 128 int i; |
| 129 |
| 130 /* |
| 131 * the state variable holds the number of bits in the |
| 132 * current run (or gap, if negative) |
| 133 */ |
| 134 |
| 135 while (data < data_end) { |
| 136 |
| 137 /* loop over the bits of this byte */ |
| 138 for (mask = 1; mask < 256; mask <<= 1) { |
| 139 if (*data & mask) { |
| 140 |
| 141 /* next bit is a one */ |
| 142 if (state > 0) { |
| 143 |
| 144 /* prefix is a run, so increment the run-count */ |
| 145 state++; |
| 146 |
| 147 /* check for long runs */ |
| 148 if (state > 25) { |
| 149 debug_print(mod_stat, ">25 runs: %d", state); |
| 150 return srtp_err_status_algo_fail; |
| 151 } |
| 152 |
| 153 } else if (state < 0) { |
| 154 |
| 155 /* prefix is a gap */ |
| 156 if (state < -25) { |
| 157 debug_print(mod_stat, ">25 gaps: %d", state); |
| 158 return srtp_err_status_algo_fail; /* long-runs test failed */ |
| 159 } |
| 160 if (state < -6) { |
| 161 state = -6; /* group together gaps > 5 */ |
| 162 } |
| 163 gaps[-1-state]++; /* increment gap count */ |
| 164 state = 1; /* set state at one set bit */ |
| 165 } else { |
| 166 |
| 167 /* state is zero; this happens only at initialization */ |
| 168 state = 1; |
| 169 } |
| 170 } else { |
| 171 |
| 172 /* next bit is a zero */ |
| 173 if (state > 0) { |
| 174 |
| 175 /* prefix is a run */ |
| 176 if (state > 25) { |
| 177 debug_print(mod_stat, ">25 runs (2): %d", state); |
| 178 return srtp_err_status_algo_fail; /* long-runs test failed */ |
| 179 } |
| 180 if (state > 6) { |
| 181 state = 6; /* group together runs > 5 */ |
| 182 } |
| 183 runs[state-1]++; /* increment run count */ |
| 184 state = -1; /* set state at one zero bit */ |
| 185 } else if (state < 0) { |
| 186 |
| 187 /* prefix is a gap, so increment gap-count (decrement state) */ |
| 188 state--; |
| 189 |
| 190 /* check for long gaps */ |
| 191 if (state < -25) { |
| 192 debug_print(mod_stat, ">25 gaps (2): %d", state); |
| 193 return srtp_err_status_algo_fail; |
| 194 } |
| 195 |
| 196 } else { |
| 197 |
| 198 /* state is zero; this happens only at initialization */ |
| 199 state = -1; |
| 200 } |
| 201 } |
| 202 } |
| 203 |
| 204 /* move along to next octet */ |
| 205 data++; |
| 206 } |
| 207 |
| 208 if (mod_stat.on) { |
| 209 debug_print(mod_stat, "runs test", NULL); |
| 210 for (i=0; i < 6; i++) |
| 211 debug_print(mod_stat, " runs[]: %d", runs[i]); |
| 212 for (i=0; i < 6; i++) |
| 213 debug_print(mod_stat, " gaps[]: %d", gaps[i]); |
| 214 } |
| 215 |
| 216 /* check run and gap counts against the fixed limits */ |
| 217 for (i=0; i < 6; i++) |
| 218 if ( (runs[i] < lo_value[i] ) || (runs[i] > hi_value[i]) |
| 219 || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i])) |
| 220 return srtp_err_status_algo_fail; |
| 221 |
| 222 |
| 223 return srtp_err_status_ok; |
| 224 } |
| 225 |
| 226 |
OLD | NEW |