1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2000-2024 The OpenLDAP Foundation.
* Portions Copyright 2000-2003 Kurt D. Zeilenga.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
/* This implements the Fowler / Noll / Vo (FNV-1) hash algorithm.
* A summary of the algorithm can be found at:
* http://www.isthe.com/chongo/tech/comp/fnv/index.html
*/
#include "portable.h"
#include <lutil_hash.h>
/* offset and prime for 32-bit FNV-1 */
#define HASH_OFFSET 0x811c9dc5U
#define HASH_PRIME 16777619
/*
* Initialize context
*/
void
lutil_HASHInit( lutil_HASH_CTX *ctx )
{
ctx->hash = HASH_OFFSET;
}
/*
* Update hash
*/
void
lutil_HASHUpdate(
lutil_HASH_CTX *ctx,
const unsigned char *buf,
ber_len_t len )
{
const unsigned char *p, *e;
ber_uint_t h;
p = buf;
e = &buf[len];
h = ctx->hash;
while( p < e ) {
h *= HASH_PRIME;
h ^= *p++;
}
ctx->hash = h;
}
/*
* Save hash
*/
void
lutil_HASHFinal( unsigned char *digest, lutil_HASH_CTX *ctx )
{
ber_uint_t h = ctx->hash;
digest[0] = h & 0xffU;
digest[1] = (h>>8) & 0xffU;
digest[2] = (h>>16) & 0xffU;
digest[3] = (h>>24) & 0xffU;
}
#ifdef HAVE_LONG_LONG
/* 64 bit Fowler/Noll/Vo-O FNV-1a hash code */
#define HASH64_OFFSET 0xcbf29ce484222325ULL
/*
* Initialize context
*/
void
lutil_HASH64Init( lutil_HASH_CTX *ctx )
{
ctx->hash64 = HASH64_OFFSET;
}
/*
* Update hash
*/
void
lutil_HASH64Update(
lutil_HASH_CTX *ctx,
const unsigned char *buf,
ber_len_t len )
{
const unsigned char *p, *e;
unsigned long long h;
p = buf;
e = &buf[len];
h = ctx->hash64;
while( p < e ) {
/* xor the bottom with the current octet */
h ^= *p++;
/* multiply by the 64 bit FNV magic prime mod 2^64 */
h += (h << 1) + (h << 4) + (h << 5) +
(h << 7) + (h << 8) + (h << 40);
}
ctx->hash64 = h;
}
/*
* Save hash
*/
void
lutil_HASH64Final( unsigned char *digest, lutil_HASH_CTX *ctx )
{
unsigned long long h = ctx->hash64;
digest[0] = h & 0xffU;
digest[1] = (h>>8) & 0xffU;
digest[2] = (h>>16) & 0xffU;
digest[3] = (h>>24) & 0xffU;
digest[4] = (h>>32) & 0xffU;
digest[5] = (h>>40) & 0xffU;
digest[6] = (h>>48) & 0xffU;
digest[7] = (h>>56) & 0xffU;
}
#endif /* HAVE_LONG_LONG */
|