Blame common/hash.c

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