LCOV - code coverage report
Current view: top level - src - Hash.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 82 103 79.6 %
Date: 2010-12-13 Functions: 15 30 50.0 %
Branches: 11 16 68.8 %

           Branch data     Line data    Source code
       1                 :            : // $Id: Hash.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : // The hash function works as follows:
       6                 :            : //
       7                 :            : // 1) For short data we have a number of universal hash functions:
       8                 :            : // UHASH_CW (ax + b (mod p)), H3, Dietzfelbinger and UMAC_NH (UMAC_NH is
       9                 :            : // not as strongly universal as the others, but probably enough). All
      10                 :            : // these functions require number of random bits linear to the data
      11                 :            : // length. And we use them for data no longer than UHASH_KEY_SIZE.
      12                 :            : // They are faster than HMAC/MD5 used for longer data, and most hash
      13                 :            : // operations are on short data.
      14                 :            : //
      15                 :            : // 2) As a fall-back, we use HMAC/MD5 (keyed MD5) for data of arbitrary
      16                 :            : // length. MD5 is used as a scrambling scheme so that it is difficult
      17                 :            : // for the adversary to construct conflicts, though I do not know if
      18                 :            : // HMAC/MD5 is provably universal.
      19                 :            : 
      20                 :            : #include "config.h"
      21                 :            : 
      22                 :            : #include "Hash.h"
      23                 :            : 
      24                 :            : // Define *one* of the following as the universal hash function family to use.
      25                 :            : 
      26                 :            : // #define USE_DIETZFELBINGER   // TwoWise
      27                 :            : #define USE_H3
      28                 :            : // #define USE_UHASH_CW
      29                 :            : // #define USE_UMAC_NH
      30                 :            : 
      31                 :            : int hash_cnt_all = 0, hash_cnt_uhash = 0;
      32                 :            : 
      33                 :            : #if defined(USE_DIETZFELBINGER)
      34                 :            : 
      35                 :            : #include "TwoWise.h"
      36                 :            : const TwoWise* two_wise = 0;
      37                 :            : 
      38                 :            : #elif defined(USE_H3)
      39                 :            : 
      40                 :            : #include "H3.h"
      41                 :            : const H3<hash_t, UHASH_KEY_SIZE>* h3;
      42                 :            : 
      43                 :            : #elif defined(USE_UHASH_CW)
      44                 :            : 
      45                 :            : // The Carter-Wegman family of universal hash functions.
      46                 :            : // f(x) = (sum(a_i * x_i) mod p) mod N
      47                 :            : // where p is a prime number between N and 2N.
      48                 :            : // Here N = 2^32.
      49                 :            : 
      50                 :            : class UHashCW {
      51                 :            :         typedef uint32 word_t;
      52                 :            : public:
      53                 :            :         UHashCW(int arg_max_key_size)
      54                 :            :                 {
      55                 :            :                 max_num_words = (arg_max_key_size + sizeof(word_t) - 1) /
      56                 :            :                                 sizeof(word_t);
      57                 :            : 
      58                 :            :                 a = new word_t[max_num_words + 1];
      59                 :            :                 x = new word_t[max_num_words + 1];
      60                 :            : 
      61                 :            :                 for ( int i = 0; i < max_num_words + 1; ++i )
      62                 :            :                         a[i] = rand32bit();
      63                 :            : 
      64                 :            :                 b = rand64bit();
      65                 :            :                 }
      66                 :            : 
      67                 :            :         ~UHashCW()
      68                 :            :                 {
      69                 :            :                 delete [] a;
      70                 :            :                 delete [] x;
      71                 :            :                 }
      72                 :            : 
      73                 :            :         uint32 hash(int len, const u_char* data) const
      74                 :            :                 {
      75                 :            :                 int xlen = (len + sizeof(word_t) - 1) / sizeof(word_t);
      76                 :            :                 ASSERT(xlen <= max_num_words);
      77                 :            : 
      78                 :            :                 x[xlen] = 0;
      79                 :            :                 x[xlen-1] = 0;  // pad with 0
      80                 :            : 
      81                 :            :                 memcpy(static_cast<void *>(x), data, len);
      82                 :            : 
      83                 :            :                 uint64 h = b;
      84                 :            :                 for ( int i = 0; i < xlen; ++i )
      85                 :            :                         h += (static_cast<uint64>(x[i]) * a[i]);
      86                 :            : 
      87                 :            :                 h += static_cast<uint64>(len) * a[xlen];
      88                 :            : 
      89                 :            :                 // h = h % kPrime
      90                 :            :                 //
      91                 :            :                 // Here we use a trick given that h is a Mersenne prime:
      92                 :            :                 //
      93                 :            :                 // Let K = 2^61. Let h = a * K + b.
      94                 :            :                 // Thus, h = a * (K-1) + (a + b).
      95                 :            : 
      96                 :            :                 h = (h & kPrime) + (h >> 61);
      97                 :            :                 if ( h >= kPrime )
      98                 :            :                         h -= kPrime;
      99                 :            : 
     100                 :            :                 // h = h % 2^32
     101                 :            :                 return static_cast<uint32>(0xffffffffUL & h);
     102                 :            :                 }
     103                 :            : 
     104                 :            : protected:
     105                 :            :         static const uint64 kPrime = (static_cast<uint64>(1) << 61) - 1;
     106                 :            : 
     107                 :            :         int max_num_words;
     108                 :            :         word_t* a;
     109                 :            :         uint64 b;
     110                 :            :         word_t* x;
     111                 :            : };
     112                 :            : 
     113                 :            : const UHashCW* uhash_cw = 0;
     114                 :            : 
     115                 :            : #elif defined(USE_UMAC_NH)
     116                 :            : 
     117                 :            : // Use the NH hash function proposed in UMAC.
     118                 :            : // (See http://www.cs.ucdavis.edu/~rogaway/umac/)
     119                 :            : //
     120                 :            : // Essentially, it is computed as:
     121                 :            : //
     122                 :            : //      H = (x_0 +_16 k_0) * (x_1 +_16 k_1) +
     123                 :            : //              (x_2 +_16 k_2) * (x_3 +_16 k_3) + ...
     124                 :            : //
     125                 :            : // where {k_i} are keys for universal hashing,
     126                 :            : // {x_i} are data words, and +_16 means plus mod 2^16.
     127                 :            : //
     128                 :            : // This is faster than UHASH_CW because no modulo operation
     129                 :            : // is needed.  But note that it is 2^-16 universal, while the
     130                 :            : // other universal functions are (almost) 2^-32 universal.
     131                 :            : //
     132                 :            : // Note: UMAC now has a code release under a BSD-like license, and we may want
     133                 :            : // to consider using it instead of our home-grown code.
     134                 :            : 
     135                 :            : #ifndef DEBUG
     136                 :            : #error "UMAC/NH is experimental code."
     137                 :            : #endif
     138                 :            : 
     139                 :            : class UMacNH {
     140                 :            :         // NH uses 16-bit words
     141                 :            :         typedef uint16 word_t;
     142                 :            : public:
     143                 :            :         UMacNH(int arg_max_key_size)
     144                 :            :                 {
     145                 :            :                 max_num_words = (arg_max_key_size + sizeof(word_t) - 1) /
     146                 :            :                                 sizeof(word_t);
     147                 :            : 
     148                 :            :                 // Make max_num_words 2n+1
     149                 :            :                 if ( max_num_words % 2 == 0 )
     150                 :            :                         ++max_num_words;
     151                 :            : 
     152                 :            :                 a = new word_t[max_num_words + 1];
     153                 :            :                 x = new word_t[max_num_words + 1];
     154                 :            : 
     155                 :            :                 for ( int i = 0; i < max_num_words + 1; ++i )
     156                 :            :                         a[i] = rand16bit();
     157                 :            :                 }
     158                 :            : 
     159                 :            :         ~UMacNH()
     160                 :            :                 {
     161                 :            :                 delete [] a;
     162                 :            :                 delete [] x;
     163                 :            :                 }
     164                 :            : 
     165                 :            :         uint32 hash(int len, const u_char* data) const
     166                 :            :                 {
     167                 :            :                 int xlen = (len + sizeof(word_t) - 1) / sizeof(word_t);
     168                 :            :                 if ( xlen % 2 == 0 )
     169                 :            :                         ++xlen;
     170                 :            : 
     171                 :            :                 ASSERT(xlen <= max_num_words);
     172                 :            : 
     173                 :            :                 x[xlen] = len;
     174                 :            :                 x[xlen-1] = 0;  // pad with 0
     175                 :            :                 if ( xlen >= 2 )
     176                 :            :                         x[xlen-2] = 0;
     177                 :            : 
     178                 :            :                 memcpy(static_cast<void *>(x), data, len);
     179                 :            : 
     180                 :            :                 uint32 h = 0;
     181                 :            :                 for ( int i = 0; i <= xlen; i += 2 )
     182                 :            :                         h += (static_cast<uint32>(x[i] + a[i]) *
     183                 :            :                               static_cast<uint32>(x[i+1] + a[i+1]));
     184                 :            : 
     185                 :            :                 return h;
     186                 :            :                 }
     187                 :            : 
     188                 :            : protected:
     189                 :            :         int max_num_words;
     190                 :            :         word_t* a;
     191                 :            :         word_t* x;
     192                 :            : };
     193                 :            : 
     194                 :            : const UMacNH* umac_nh = 0;
     195                 :            : 
     196                 :            : #else
     197                 :            : 
     198                 :            : #ifdef DEBUG
     199                 :            : #error "No universal hash function is used."
     200                 :            : #endif
     201                 :            : 
     202                 :            : #endif
     203                 :            : 
     204                 :          3 : void init_hash_function()
     205                 :            :         {
     206                 :            :         // Make sure we have already called init_random_seed().
     207         [ -  + ]:          3 :         ASSERT(hmac_key_set);
     208                 :            : 
     209                 :            :         // Both Dietzfelbinger and H3 use random() to generate keys
     210                 :            :         // -- is it strong enough?
     211                 :            : #if defined(USE_DIETZFELBINGER)
     212                 :            :         two_wise = new TwoWise((UHASH_KEY_SIZE + 3) >> 2);
     213                 :            : #elif defined(USE_H3)
     214                 :          3 :         h3 = new H3<hash_t, UHASH_KEY_SIZE>();
     215                 :            : #elif defined(USE_UHASH_CW)
     216                 :            :         uhash_cw = new UHashCW(UHASH_KEY_SIZE);
     217                 :            : #elif defined(USE_UMAC_NH)
     218                 :            :         umac_nh = new UMacNH(UHASH_KEY_SIZE);
     219                 :            : #endif
     220                 :          3 :         }
     221                 :            : 
     222                 :      22414 : HashKey::HashKey(bro_int_t i)
     223                 :            :         {
     224                 :      22414 :         key_u.i = i;
     225                 :      22414 :         key = (void*) &key_u;
     226                 :      22414 :         size = sizeof(i);
     227                 :      22414 :         hash = HashBytes(key, size);
     228                 :      22414 :         is_our_dynamic = 0;
     229                 :      22414 :         }
     230                 :            : 
     231                 :          0 : HashKey::HashKey(bro_uint_t u)
     232                 :            :         {
     233                 :          0 :         key_u.i = bro_int_t(u);
     234                 :          0 :         key = (void*) &key_u;
     235                 :          0 :         size = sizeof(u);
     236                 :          0 :         hash = HashBytes(key, size);
     237                 :          0 :         is_our_dynamic = 0;
     238                 :          0 :         }
     239                 :            : 
     240                 :       3893 : HashKey::HashKey(uint32 u)
     241                 :            :         {
     242                 :       3893 :         key_u.u32 = u;
     243                 :       3893 :         key = (void*) &key_u;
     244                 :       3893 :         size = sizeof(u);
     245                 :       3893 :         hash = HashBytes(key, size);
     246                 :       3893 :         is_our_dynamic = 0;
     247                 :       3893 :         }
     248                 :            : 
     249                 :         14 : HashKey::HashKey(const uint32 u[], int n)
     250                 :            :         {
     251                 :         14 :         size = n * sizeof(u[0]);
     252                 :         14 :         key = (void*) u;
     253                 :         14 :         hash = HashBytes(key, size);
     254                 :         14 :         is_our_dynamic = 0;
     255                 :         14 :         }
     256                 :            : 
     257                 :          0 : HashKey::HashKey(double d)
     258                 :            :         {
     259                 :            :         union {
     260                 :            :                 double d;
     261                 :            :                 int i[2];
     262                 :            :         } u;
     263                 :            : 
     264                 :          0 :         key_u.d = u.d = d;
     265                 :          0 :         key = (void*) &key_u;
     266                 :          0 :         size = sizeof(d);
     267                 :          0 :         hash = HashBytes(key, size);
     268                 :          0 :         is_our_dynamic = 0;
     269                 :          0 :         }
     270                 :            : 
     271                 :          0 : HashKey::HashKey(const void* p)
     272                 :            :         {
     273                 :          0 :         key_u.p = p;
     274                 :          0 :         key = (void*) &key_u;
     275                 :          0 :         size = sizeof(p);
     276                 :          0 :         hash = HashBytes(key, size);
     277                 :          0 :         is_our_dynamic = 0;
     278                 :          0 :         }
     279                 :            : 
     280                 :     108568 : HashKey::HashKey(const char* s)
     281                 :            :         {
     282                 :     108568 :         size = strlen(s);       // note - skip final \0
     283                 :     108568 :         key = (void*) s;
     284                 :     108568 :         hash = HashBytes(key, size);
     285                 :     108568 :         is_our_dynamic = 0;
     286                 :     108568 :         }
     287                 :            : 
     288                 :      59006 : HashKey::HashKey(const BroString* s)
     289                 :            :         {
     290                 :      59006 :         size = s->Len();
     291                 :      59006 :         key = (void*) s->Bytes();
     292                 :      59006 :         hash = HashBytes(key, size);
     293                 :      59006 :         is_our_dynamic = 0;
     294                 :      59006 :         }
     295                 :            : 
     296                 :      25536 : HashKey::HashKey(int copy_key, void* arg_key, int arg_size)
     297                 :            :         {
     298                 :      25536 :         size = arg_size;
     299                 :      25536 :         is_our_dynamic = 1;
     300                 :            : 
     301 [ +  + ][ #  # ]:      25536 :         if ( copy_key )
     302                 :            :                 {
     303                 :      24810 :                 key = (void*) new char[size];
     304                 :      24810 :                 memcpy(key, arg_key, size);
     305                 :            :                 }
     306                 :            :         else
     307                 :        726 :                 key = arg_key;
     308                 :            : 
     309                 :      25536 :         hash = HashBytes(key, size);
     310                 :      25536 :         }
     311                 :            : 
     312                 :      13751 : HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash)
     313                 :            :         {
     314                 :      13751 :         size = arg_size;
     315                 :      13751 :         hash = arg_hash;
     316                 :      13751 :         key = CopyKey(arg_key, size);
     317                 :      13751 :         is_our_dynamic = 1;
     318                 :      13751 :         }
     319                 :            : 
     320                 :            : HashKey::HashKey(const void* arg_key, int arg_size, hash_t arg_hash,
     321                 :         61 :                 bool /* dont_copy */)
     322                 :            :         {
     323                 :         61 :         size = arg_size;
     324                 :         61 :         hash = arg_hash;
     325                 :         61 :         key = const_cast<void*>(arg_key);
     326                 :         61 :         is_our_dynamic = 0;
     327                 :         61 :         }
     328                 :            : 
     329                 :      21362 : HashKey::HashKey(const void* bytes, int arg_size)
     330                 :            :         {
     331                 :      21362 :         size = arg_size;
     332                 :      21362 :         key = CopyKey(bytes, size);
     333                 :      21362 :         hash = HashBytes(key, size);
     334                 :      21362 :         is_our_dynamic = 1;
     335                 :      21362 :         }
     336                 :            : 
     337                 :      45428 : void* HashKey::TakeKey()
     338                 :            :         {
     339         [ +  + ]:      45428 :         if ( is_our_dynamic )
     340                 :            :                 {
     341                 :       4343 :                 is_our_dynamic = 0;
     342                 :       4343 :                 return key;
     343                 :            :                 }
     344                 :            :         else
     345                 :      45428 :                 return CopyKey(key, size);
     346                 :            :         }
     347                 :            : 
     348                 :      76198 : void* HashKey::CopyKey(const void* k, int s) const
     349                 :            :         {
     350                 :      76198 :         void* k_copy = (void*) new char[s];
     351                 :      76198 :         memcpy(k_copy, k, s);
     352                 :      76198 :         return k_copy;
     353                 :            :         }
     354                 :            : 
     355                 :     240793 : hash_t HashKey::HashBytes(const void* bytes, int size)
     356                 :            :         {
     357                 :     240793 :         ++hash_cnt_all;
     358                 :            : 
     359         [ +  + ]:     240793 :         if ( size <= UHASH_KEY_SIZE )
     360                 :            :                 {
     361                 :     217750 :                 const uint8* b = reinterpret_cast<const uint8*>(bytes);
     362                 :     217750 :                 ++hash_cnt_uhash;
     363                 :            : #if defined(USE_DIETZFELBINGER)
     364                 :            :                 return two_wise->Hash(size, b);
     365                 :            : #elif defined(USE_H3)
     366                 :            :                 // H3 doesn't check if size is zero
     367         [ +  + ]:     217750 :                 return ( size == 0 ) ? 0 : (*h3)(bytes, size);
     368                 :            : #elif defined(USE_UHASH_CW)
     369                 :            :                 return uhash_cw->hash(size, b);
     370                 :            : #elif defined(USE_UMAC_NH)
     371                 :            :                 return umac_nh->hash(size, b);
     372                 :            : #else
     373                 :            :                 --hash_cnt_uhash;
     374                 :            : #endif
     375                 :            :                 }
     376                 :            : 
     377                 :            :         // Fall back to HMAC/MD5 for longer data (which is usually rare).
     378                 :            :         hash_t digest[16];
     379                 :      23043 :         hmac_md5(size, (unsigned char*) bytes, (unsigned char*) digest);
     380                 :     240793 :         return digest[0];
     381 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8