/* * Copyright (C) 2004, 2005, 2007, 2011 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 2000, 2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ /*! \file * SHA-1 in C * \author By Steve Reid * 100% Public Domain * \verbatim * Test Vectors * "abc" * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 * A million repetitions of "a" * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F * \endverbatim */ #include "config.h" #include "hash.h" #include #include #include #include /* This code is based on the public domain MurmurHash3 from Austin Appleby: * http://code.google.com/p/smhasher/source/browse/trunk/MurmurHash3.cpp * * We use only the 32 bit variant, and slow it down a bit to support unaligned * reads. */ #if !defined(__cplusplus) && (__GNUC__ > 2) #define GNUC_INLINE __attribute__((always_inline)) #else #define GNUC_INLINE #endif GNUC_INLINE static inline uint32_t rotl (uint32_t x, int8_t r) { return (x << r) | (x >> (32 - r)); } /* * Finalization mix - force all bits of a hash block to avalanche */ GNUC_INLINE static inline uint32_t fmix (uint32_t h) { h ^= h >> 16; h *= 0x85ebca6b; h ^= h >> 13; h *= 0xc2b2ae35; h ^= h >> 16; return h; } void p11_hash_murmur3 (void *hash, const void *input, size_t len, ...) { uint8_t overflow[4]; const uint8_t *data; va_list va; uint32_t h1; uint32_t k1; uint32_t c1; uint32_t c2; h1 = 42; /* arbitrary choice of seed */ c1 = 0xcc9e2d51; c2 = 0x1b873593; data = input; /* body */ /* Mix 4 bytes at a time into the hash */ va_start (va, len); for (;;) { if (len >= 4) { memcpy (&k1, data, 4); data += 4; len -= 4; } else { size_t num = len; memcpy (overflow, data, len); while (num < 4) { size_t part; data = va_arg (va, const void *); if (!data) break; /* Combine uint32 from old and new */ len = va_arg (va, size_t); part = 4 - num; if (part > len) part = len; memcpy (overflow + num, data, part); data += part; len -= part; num += part; } if (num < 4) { len = num; break; } memcpy (&k1, overflow, 4); } k1 *= c1; k1 = rotl (k1, 15); k1 *= c2; h1 ^= k1; h1 = rotl (h1, 13); h1 = h1 * 5 + 0xe6546b64; } /* tail */ k1 = 0; switch (len) { case 3: k1 ^= overflow[2] << 16; case 2: k1 ^= overflow[1] << 8; case 1: k1 ^= overflow[0]; k1 *= c1; k1 = rotl (k1, 15); k1 *= c2; h1 ^= k1; default: break; } /* finalization */ h1 ^= len; h1 = fmix(h1); assert (sizeof (h1) == P11_HASH_MURMUR3_LEN); memcpy (hash, &h1, sizeof (h1)); }