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
|
/*++
/* NAME
/* hash_fnv 3
/* SUMMARY
/* Fowler/Noll/Vo hash function
/* SYNOPSIS
/* #include <hash_fnv.h>
/*
/* HASH_FNV_T hash_fnv(
/* const void *src,
/* size_t len)
/* DESCRIPTION
/* hash_fnv() implements a modified FNV type 1a hash function.
/*
/* To thwart collision attacks, the hash function is seeded
/* once from /dev/urandom, and if that is unavailable, from
/* wallclock time, monotonic system clocks, and the process
/* ID. To disable seeding (typically, for regression tests),
/* specify the NORANDOMIZE environment variable; the value
/* does not matter.
/*
/* This function implements a workaround for a "sticky state"
/* problem with FNV hash functions: when an input produces a
/* zero intermediate hash state, and the next input byte is
/* zero, then the operations "hash ^= 0" and "hash *= FNV_prime"
/* would not change the hash value. To avoid this, hash_fnv()
/* adds 1 to each input byte. Compile with -DSTRICT_FNV1A to
/* get the standard behavior.
/*
/* The default HASH_FNV_T result type is uint64_t. When compiled
/* with -DUSE_FNV_32BIT, the result type is uint32_t. On ancient
/* systems without <stdint.h>, define HASH_FNV_T on the compiler
/* command line as an unsigned 32-bit or 64-bit integer type,
/* and specify -DUSE_FNV_32BIT when HASH_FNV_T is a 32-bit type.
/* SEE ALSO
/* http://www.isthe.com/chongo/tech/comp/fnv/index.html
/* https://softwareengineering.stackexchange.com/questions/49550/
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
/*
* System library
*/
#include <sys_defs.h>
#include <stdlib.h>
#include <unistd.h>
/*
* Utility library.
*/
#include <msg.h>
#include <ldseed.h>
#include <hash_fnv.h>
/*
* Application-specific.
*/
#ifdef USE_FNV_32BIT
#define FNV_prime 0x01000193UL
#define FNV_offset_basis 0x811c9dc5UL
#else
#define FNV_prime 0x00000100000001B3ULL
#define FNV_offset_basis 0xcbf29ce484222325ULL
#endif
/* hash_fnv - modified FNV 1a hash */
HASH_FNV_T hash_fnv(const void *src, size_t len)
{
static HASH_FNV_T basis = FNV_offset_basis;
static int randomize = 1;
HASH_FNV_T hash;
/*
* Initialize.
*/
if (randomize) {
if (!getenv("NORANDOMIZE")) {
HASH_FNV_T seed;
ldseed(&seed, sizeof(seed));
basis ^= seed;
}
randomize = 0;
}
#ifdef STRICT_FNV1A
#define FNV_NEXT_BYTE(s) ((HASH_FNV_T) * (const unsigned char *) s++)
#else
#define FNV_NEXT_BYTE(s) (1 + (HASH_FNV_T) * (const unsigned char *) s++)
#endif
hash = basis;
while (len-- > 0) {
hash ^= FNV_NEXT_BYTE(src);
hash *= FNV_prime;
}
return (hash);
}
|