• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
stat_test_monobit(uint8_t * data)60 stat_test_monobit(uint8_t *data) {
61   uint8_t *data_end = data + STAT_TEST_DATA_LEN;
62   uint16_t ones_count;
63 
64   ones_count = 0;
65   while (data < data_end) {
66     ones_count += octet_get_weight(*data);
67     data++;
68   }
69 
70   debug_print(mod_stat, "bit count: %d", ones_count);
71 
72   if ((ones_count < 9725) || (ones_count > 10275))
73     return err_status_algo_fail;
74 
75   return err_status_ok;
76 }
77 
78 err_status_t
stat_test_poker(uint8_t * data)79 stat_test_poker(uint8_t *data) {
80   int i;
81   uint8_t *data_end = data + STAT_TEST_DATA_LEN;
82   double poker;
83   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   while (data < data_end) {
89     f[*data & 0x0f]++;    /* increment freq. count for low nibble  */
90     f[(*data) >> 4]++;    /* increment freq. count for high nibble */
91     data++;
92   }
93 
94   poker = 0.0;
95   for (i=0; i < 16; i++)
96     poker += (double) f[i] * f[i];
97 
98   poker *= (16.0 / 5000.0);
99   poker -= 5000.0;
100 
101   debug_print(mod_stat, "poker test: %f\n", poker);
102 
103   if ((poker < 2.16) || (poker > 46.17))
104     return err_status_algo_fail;
105 
106   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
stat_test_runs(uint8_t * data)115 stat_test_runs(uint8_t *data) {
116   uint8_t *data_end = data + STAT_TEST_DATA_LEN;
117   uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 };
118   uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
119   uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
120   uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
121   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   while (data < data_end) {
131 
132     /* loop over the bits of this byte */
133     for (mask = 1; mask < 256; mask <<= 1) {
134       if (*data & mask) {
135 
136  	/* next bit is a one  */
137 	if (state > 0) {
138 
139 	  /* prefix is a run, so increment the run-count  */
140 	  state++;
141 
142 	  /* check for long runs */
143 	  if (state > 25) {
144 		debug_print(mod_stat, ">25 runs: %d", state);
145 		return err_status_algo_fail;
146 	  }
147 
148 	} else if (state < 0) {
149 
150 	  /* prefix is a gap  */
151 	  if (state < -25) {
152 		debug_print(mod_stat, ">25 gaps: %d", state);
153 	    return err_status_algo_fail;    /* long-runs test failed   */
154 	  }
155 	  if (state < -6) {
156 	    state = -6;                     /* group together gaps > 5 */
157 	  }
158 	  gaps[-1-state]++;                 /* increment gap count      */
159           state = 1;                        /* set state at one set bit */
160 	} else {
161 
162 	  /* state is zero; this happens only at initialization        */
163 	  state = 1;
164 	}
165       } else {
166 
167 	/* next bit is a zero  */
168 	if (state > 0) {
169 
170 	  /* prefix is a run */
171 	  if (state > 25) {
172 		debug_print(mod_stat, ">25 runs (2): %d", state);
173 	    return err_status_algo_fail;    /* long-runs test failed   */
174 	  }
175 	  if (state > 6) {
176 	    state = 6;                      /* group together runs > 5 */
177 	  }
178 	  runs[state-1]++;                  /* increment run count       */
179           state = -1;                       /* set state at one zero bit */
180 	} else if (state < 0) {
181 
182 	  /* prefix is a gap, so increment gap-count (decrement state) */
183 	  state--;
184 
185 	  /* check for long gaps */
186 	  if (state < -25) {
187 		debug_print(mod_stat, ">25 gaps (2): %d", state);
188 	    return err_status_algo_fail;
189 	  }
190 
191 	} else {
192 
193 	  /* state is zero; this happens only at initialization        */
194 	  state = -1;
195 	}
196       }
197     }
198 
199     /* move along to next octet */
200     data++;
201   }
202 
203   if (mod_stat.on) {
204     debug_print(mod_stat, "runs test", NULL);
205     for (i=0; i < 6; i++)
206       debug_print(mod_stat, "  runs[]: %d", runs[i]);
207     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   for (i=0; i < 6; i++)
213     if (   (runs[i] < lo_value[i] ) || (runs[i] > hi_value[i])
214 	|| (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i]))
215       return err_status_algo_fail;
216 
217 
218   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
stat_test_rand_source(rand_source_func_t get_rand_bytes)231 stat_test_rand_source(rand_source_func_t get_rand_bytes) {
232   int i;
233   double poker;
234   uint8_t *data, *data_end;
235   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   int ones_count = 0;
242   uint16_t runs[6] = { 0, 0, 0, 0, 0, 0 };
243   uint16_t gaps[6] = { 0, 0, 0, 0, 0, 0 };
244   uint16_t lo_value[6] = { 2315, 1114, 527, 240, 103, 103 };
245   uint16_t hi_value[6] = { 2685, 1386, 723, 384, 209, 209 };
246   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   for (i=0; i < 2500; i+=RAND_SRC_BUF_OCTETS) {
253 
254     /* fill data buffer */
255     status = get_rand_bytes(buffer, RAND_SRC_BUF_OCTETS);
256     if (status) {
257 	  debug_print(mod_stat, "couldn't get rand bytes: %d",status);
258       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     data = buffer;
267     data_end = data + RAND_SRC_BUF_OCTETS;
268     while (data < data_end) {
269 
270       /* update monobit test counter */
271       ones_count += octet_get_weight(*data);
272 
273       /* update poker test counters */
274       f[*data & 0x0f]++;    /* increment freq. count for low nibble  */
275       f[(*data) >> 4]++;    /* increment freq. count for high nibble */
276 
277       /* update runs test counters */
278       /* loop over the bits of this byte */
279       for (mask = 1; mask < 256; mask <<= 1) {
280 	if (*data & mask) {
281 
282 	  /* next bit is a one  */
283 	  if (state > 0) {
284 
285 	    /* prefix is a run, so increment the run-count  */
286 	    state++;
287 
288 	    /* check for long runs */
289 	    if (state > 25) {
290 		  debug_print(mod_stat, ">25 runs (3): %d", state);
291 	      return err_status_algo_fail;
292 		}
293 
294 	  } else if (state < 0) {
295 
296 	    /* prefix is a gap  */
297 	    if (state < -25) {
298 		  debug_print(mod_stat, ">25 gaps (3): %d", state);
299 	      return err_status_algo_fail;    /* long-runs test failed   */
300 	    }
301 	    if (state < -6) {
302 	      state = -6;                     /* group together gaps > 5 */
303 	    }
304 	    gaps[-1-state]++;                 /* increment gap count      */
305 	    state = 1;                        /* set state at one set bit */
306 	  } else {
307 
308 	    /* state is zero; this happens only at initialization        */
309 	    state = 1;
310 	  }
311 	} else {
312 
313 	  /* next bit is a zero  */
314 	  if (state > 0) {
315 
316 	    /* prefix is a run */
317 	    if (state > 25) {
318 		  debug_print(mod_stat, ">25 runs (4): %d", state);
319 	      return err_status_algo_fail;    /* long-runs test failed   */
320 	    }
321 	    if (state > 6) {
322 	      state = 6;                      /* group together runs > 5 */
323 	    }
324 	    runs[state-1]++;                  /* increment run count       */
325 	    state = -1;                       /* set state at one zero bit */
326 	  } else if (state < 0) {
327 
328 	    /* prefix is a gap, so increment gap-count (decrement state) */
329 	    state--;
330 
331 	    /* check for long gaps */
332 	    if (state < -25) {
333 		  debug_print(mod_stat, ">25 gaps (4): %d", state);
334 	      return err_status_algo_fail;
335 		}
336 
337 	  } else {
338 
339 	    /* state is zero; this happens only at initialization        */
340 	    state = -1;
341 	  }
342 	}
343       }
344 
345       /* advance data pointer */
346       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   if ((ones_count < 9725) || (ones_count > 10275)) {
357     debug_print(mod_stat, "stat: failed monobit test %d", ones_count);
358     return err_status_algo_fail;
359   }
360 
361   /* check poker test data */
362   poker = 0.0;
363   for (i=0; i < 16; i++)
364     poker += (double) f[i] * f[i];
365 
366   poker *= (16.0 / 5000.0);
367   poker -= 5000.0;
368 
369   debug_print(mod_stat, "stat: poker test: %f", poker);
370 
371   if ((poker < 2.16) || (poker > 46.17)) {
372     debug_print(mod_stat, "stat: failed poker test", NULL);
373     return err_status_algo_fail;
374   }
375 
376   /* check run and gap counts against the fixed limits */
377   for (i=0; i < 6; i++)
378     if ((runs[i] < lo_value[i] ) || (runs[i] > hi_value[i])
379 	 || (gaps[i] < lo_value[i] ) || (gaps[i] > hi_value[i])) {
380       debug_print(mod_stat, "stat: failed run/gap test", NULL);
381       return err_status_algo_fail;
382     }
383 
384   debug_print(mod_stat, "passed random stat test", NULL);
385   return err_status_ok;
386 }
387 
388 err_status_t
stat_test_rand_source_with_repetition(rand_source_func_t source,unsigned num_trials)389 stat_test_rand_source_with_repetition(rand_source_func_t source, unsigned num_trials) {
390   unsigned int i;
391   err_status_t err = err_status_algo_fail;
392 
393   for (i=0; i < num_trials; i++) {
394     err = stat_test_rand_source(source);
395     if (err == err_status_ok) {
396       return err_status_ok;
397     }
398     debug_print(mod_stat, "failed stat test (try number %d)\n", i);
399   }
400 
401   return err;
402 }
403