diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 81ed0d81af..0f67dc173e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -320,6 +320,7 @@ set(bro_SRCS PrefixTable.cc PriorityQueue.cc Queue.cc + RandTest.cc RE.cc RPC.cc Reassem.cc diff --git a/src/RandTest.cc b/src/RandTest.cc index f779a23f94..638cc6c765 100644 --- a/src/RandTest.cc +++ b/src/RandTest.cc @@ -1,9 +1,13 @@ /* + Apply various randomness tests to a stream of bytes - Apply various randomness tests to a stream of bytes + by John Walker -- September 1996 + http://www.fourmilab.ch/random - by John Walker -- September 1996 - http://www.fourmilab.ch/ + This software is in the public domain. Permission to use, copy, modify, + and distribute this software and its documentation for any purpose and + without fee is hereby granted, without any conditions or restrictions. + This software is provided “as is” without express or implied warranty. Modified for Bro by Seth Hall - July 2010 */ @@ -17,8 +21,8 @@ RandTest::RandTest() sccfirst = 1; inmont = mcount = 0; cexp = montex = montey = montepi = sccu0 = scclast = scct1 = scct2 = scct3 = 0.0; - - for (int i = 0; i < 256; i++) + + for (int i = 0; i < 256; i++) { ccount[i] = 0; } @@ -44,7 +48,7 @@ void RandTest::add(void *buf, int bufl) mcount++; montex = 0; montey = 0; - for (int mj=0; mj < RT_MONTEN/2; mj++) + for (int mj=0; mj < RT_MONTEN/2; mj++) { montex = (montex * 256.0) + monte[mj]; montey = (montey * 256.0) + monte[(RT_MONTEN / 2) + mj]; @@ -61,8 +65,8 @@ void RandTest::add(void *buf, int bufl) sccfirst = 0; scclast = 0; sccu0 = oc; - } - else + } + else { scct1 = scct1 + scclast * oc; } @@ -90,22 +94,22 @@ void RandTest::end(double *r_ent, double *r_chisq, scc = -100000; else scc = (totalc * scct1 - scct2) / scc; - + /* Scan bins and calculate probability for each bin and Chi-Square distribution. The probability will be reused in the entropy calculation below. While we're at it, we sum of all the data which will be used to compute the mean. */ cexp = totalc / 256.0; /* Expected count per bin */ - for (i = 0; i < 256; i++) + for (i = 0; i < 256; i++) { double a = ccount[i] - cexp; - + prob[i] = ((double) ccount[i]) / totalc; chisq += (a * a) / cexp; datasum += ((double) i) * ccount[i]; } - + /* Calculate entropy */ for (i = 0; i < 256; i++) { @@ -114,139 +118,11 @@ void RandTest::end(double *r_ent, double *r_chisq, ent += prob[i] * rt_log2(1 / prob[i]); } } - + /* Calculate Monte Carlo value for PI from percentage of hits within the circle */ montepi = 4.0 * (((double) inmont) / mcount); - - /* Return results through arguments */ - *r_ent = ent; - *r_chisq = chisq; - *r_mean = datasum / totalc; - *r_montepicalc = montepi; - *r_scc = scc; - } -/* - - Apply various randomness tests to a stream of bytes - - by John Walker -- September 1996 - http://www.fourmilab.ch/ - - Modified for Bro by Seth Hall - July 2010 -*/ - -#include - -RandTest::RandTest() - { - totalc = 0; - mp = 0; - sccfirst = 1; - inmont = mcount = 0; - cexp = montex = montey = montepi = sccu0 = scclast = scct1 = scct2 = scct3 = 0.0; - - for (int i = 0; i < 256; i++) - { - ccount[i] = 0; - } - } - -void RandTest::add(void *buf, int bufl) - { - unsigned char *bp = (unsigned char*)buf; - int oc; - - while (bufl-- > 0) - { - oc = *bp++; - ccount[oc]++; /* Update counter for this bin */ - totalc++; - - /* Update inside / outside circle counts for Monte Carlo - computation of PI */ - monte[mp++] = oc; /* Save character for Monte Carlo */ - if (mp >= RT_MONTEN) /* Calculate every RT_MONTEN character */ - { - mp = 0; - mcount++; - montex = 0; - montey = 0; - for (int mj=0; mj < RT_MONTEN/2; mj++) - { - montex = (montex * 256.0) + monte[mj]; - montey = (montey * 256.0) + monte[(RT_MONTEN / 2) + mj]; - } - if (montex*montex + montey*montey <= RT_INCIRC) - { - inmont++; - } - } - - /* Update calculation of serial correlation coefficient */ - if (sccfirst) - { - sccfirst = 0; - scclast = 0; - sccu0 = oc; - } - else - { - scct1 = scct1 + scclast * oc; - } - - scct2 = scct2 + oc; - scct3 = scct3 + (oc * oc); - scclast = oc; - oc <<= 1; - } - } - -void RandTest::end(double *r_ent, double *r_chisq, - double *r_mean, double *r_montepicalc, double *r_scc) - { - int i; - double ent, chisq, scc, datasum; - ent = 0.0; chisq = 0.0; scc = 0.0; datasum = 0.0; - double prob[256]; /* Probabilities per bin for entropy */ - - /* Complete calculation of serial correlation coefficient */ - scct1 = scct1 + scclast * sccu0; - scct2 = scct2 * scct2; - scc = totalc * scct3 - scct2; - if (scc == 0.0) - scc = -100000; - else - scc = (totalc * scct1 - scct2) / scc; - - /* Scan bins and calculate probability for each bin and - Chi-Square distribution. The probability will be reused - in the entropy calculation below. While we're at it, - we sum of all the data which will be used to compute the - mean. */ - cexp = totalc / 256.0; /* Expected count per bin */ - for (i = 0; i < 256; i++) - { - double a = ccount[i] - cexp; - - prob[i] = ((double) ccount[i]) / totalc; - chisq += (a * a) / cexp; - datasum += ((double) i) * ccount[i]; - } - - /* Calculate entropy */ - for (i = 0; i < 256; i++) - { - if (prob[i] > 0.0) - { - ent += prob[i] * rt_log2(1 / prob[i]); - } - } - - /* Calculate Monte Carlo value for PI from percentage of hits - within the circle */ - montepi = 4.0 * (((double) inmont) / mcount); - + /* Return results through arguments */ *r_ent = ent; *r_chisq = chisq; diff --git a/src/RandTest.h b/src/RandTest.h index bed4d93f00..a4f551b602 100644 --- a/src/RandTest.h +++ b/src/RandTest.h @@ -21,7 +21,7 @@ class RandTest { void add(void *buf, int bufl); void end(double *r_ent, double *r_chisq, double *r_mean, double *r_montepicalc, double *r_scc); - + private: long ccount[256]; /* Bins to count occurrences of values */ long totalc; /* Total bytes counted */ @@ -29,40 +29,6 @@ class RandTest { int sccfirst; unsigned int monte[RT_MONTEN]; long inmont, mcount; - double cexp, montex, montey, montepi, + double cexp, montex, montey, montepi, sccu0, scclast, scct1, scct2, scct3; }; -#include - -#define log2of10 3.32192809488736234787 -/* RT_LOG2 -- Calculate log to the base 2 */ -static double rt_log2(double x) -{ - return log2of10 * log10(x); -} - -#define RT_MONTEN 6 /* Bytes used as Monte Carlo - co-ordinates. This should be no more - bits than the mantissa of your "double" - floating point type. */ - -// RT_INCIRC = pow(pow(256.0, (double) (RT_MONTEN / 2)) - 1, 2.0); -#define RT_INCIRC 281474943156225.0 - -class RandTest { - public: - RandTest(); - void add(void *buf, int bufl); - void end(double *r_ent, double *r_chisq, double *r_mean, - double *r_montepicalc, double *r_scc); - - private: - long ccount[256]; /* Bins to count occurrences of values */ - long totalc; /* Total bytes counted */ - int mp; - int sccfirst; - unsigned int monte[RT_MONTEN]; - long inmont, mcount; - double cexp, montex, montey, montepi, - sccu0, scclast, scct1, scct2, scct3; - }; \ No newline at end of file diff --git a/src/bro.bif b/src/bro.bif index a9d76ba462..5acd958316 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -3201,7 +3201,7 @@ function disable_event_group%(group: string%) : any %%{ #include static map entropy_states; -%%} +%%} function find_entropy%(data: string%): entropy_test_result %{ @@ -3241,13 +3241,13 @@ function entropy_test_add%(index: any, data: string%): bool %{ BroString* s = convert_index_to_string(index); int status = 0; - + if ( entropy_states.count(*s) > 0 ) { entropy_states[*s]->add((char*) data->Bytes(), data->Len()); status = 1; } - + delete s; return new Val(status, TYPE_BOOL); %} @@ -3258,11 +3258,10 @@ function entropy_test_finish%(index: any%): entropy_test_result double montepi, scc, ent, mean, chisq; montepi = scc = ent = mean = chisq = 0.0; RecordVal* ent_result = new RecordVal(entropy_test_result); - + if ( entropy_states.count(*s) > 0 ) { - RandTest *rt; - rt = entropy_states[*s]; + RandTest *rt = entropy_states[*s]; rt->end(&ent, &chisq, &mean, &montepi, &scc); entropy_states.erase(*s); delete rt;