15185a700Sflorian /*
25185a700Sflorian * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian *
45185a700Sflorian * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian * copyright notice and this permission notice appear in all copies.
75185a700Sflorian *
85185a700Sflorian * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian */
165185a700Sflorian
17*1fb015a8Sflorian /* $Id: hash.c,v 1.7 2020/09/14 08:40:44 florian Exp $ */
185185a700Sflorian
195185a700Sflorian /*! \file
205185a700Sflorian * Some portion of this code was derived from universal hash function
215185a700Sflorian * libraries of Rice University.
225185a700Sflorian \section license UH Universal Hashing Library
235185a700Sflorian
245185a700Sflorian Copyright ((c)) 2002, Rice University
255185a700Sflorian All rights reserved.
265185a700Sflorian
275185a700Sflorian Redistribution and use in source and binary forms, with or without
285185a700Sflorian modification, are permitted provided that the following conditions are
295185a700Sflorian met:
305185a700Sflorian
315185a700Sflorian * Redistributions of source code must retain the above copyright
325185a700Sflorian notice, this list of conditions and the following disclaimer.
335185a700Sflorian
345185a700Sflorian * Redistributions in binary form must reproduce the above
355185a700Sflorian copyright notice, this list of conditions and the following
365185a700Sflorian disclaimer in the documentation and/or other materials provided
375185a700Sflorian with the distribution.
385185a700Sflorian
395185a700Sflorian * Neither the name of Rice University (RICE) nor the names of its
405185a700Sflorian contributors may be used to endorse or promote products derived
415185a700Sflorian from this software without specific prior written permission.
425185a700Sflorian
435185a700Sflorian This software is provided by RICE and the contributors on an "as is"
445185a700Sflorian basis, without any representations or warranties of any kind, express
455185a700Sflorian or implied including, but not limited to, representations or
465185a700Sflorian warranties of non-infringement, merchantability or fitness for a
475185a700Sflorian particular purpose. In no event shall RICE or contributors be liable
485185a700Sflorian for any direct, indirect, incidental, special, exemplary, or
495185a700Sflorian consequential damages (including, but not limited to, procurement of
505185a700Sflorian substitute goods or services; loss of use, data, or profits; or
515185a700Sflorian business interruption) however caused and on any theory of liability,
525185a700Sflorian whether in contract, strict liability, or tort (including negligence
535185a700Sflorian or otherwise) arising in any way out of the use of this software, even
545185a700Sflorian if advised of the possibility of such damage.
555185a700Sflorian */
565185a700Sflorian
575185a700Sflorian #include <stdlib.h>
585185a700Sflorian
595185a700Sflorian #include <isc/hash.h>
605185a700Sflorian #include <isc/util.h>
615185a700Sflorian
625185a700Sflorian static unsigned char maptolower[] = {
635185a700Sflorian 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
645185a700Sflorian 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
655185a700Sflorian 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
665185a700Sflorian 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
675185a700Sflorian 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
685185a700Sflorian 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
695185a700Sflorian 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
705185a700Sflorian 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
715185a700Sflorian 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
725185a700Sflorian 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
735185a700Sflorian 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
745185a700Sflorian 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
755185a700Sflorian 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
765185a700Sflorian 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
775185a700Sflorian 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
785185a700Sflorian 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
795185a700Sflorian 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
805185a700Sflorian 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
815185a700Sflorian 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
825185a700Sflorian 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
835185a700Sflorian 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
845185a700Sflorian 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
855185a700Sflorian 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
865185a700Sflorian 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
875185a700Sflorian 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
885185a700Sflorian 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
895185a700Sflorian 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
905185a700Sflorian 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
915185a700Sflorian 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
925185a700Sflorian 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
935185a700Sflorian 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
945185a700Sflorian 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
955185a700Sflorian };
965185a700Sflorian
975185a700Sflorian static uint32_t fnv_offset_basis;
98*1fb015a8Sflorian static int fnv_once = 0;
995185a700Sflorian
1005185a700Sflorian static void
fnv_initialize(void)1015185a700Sflorian fnv_initialize(void) {
1025185a700Sflorian /*
1035185a700Sflorian * This function should not leave fnv_offset_basis set to
1045185a700Sflorian * 0. Also, after this function has been called, if it is called
1055185a700Sflorian * again, it should not change fnv_offset_basis.
1065185a700Sflorian */
1075185a700Sflorian while (fnv_offset_basis == 0) {
1085185a700Sflorian fnv_offset_basis = arc4random();
1095185a700Sflorian }
1105185a700Sflorian }
1115185a700Sflorian
1125185a700Sflorian uint32_t
isc_hash_function_reverse(const void * data,size_t length,int case_sensitive,const uint32_t * previous_hashp)1135185a700Sflorian isc_hash_function_reverse(const void *data, size_t length,
114*1fb015a8Sflorian int case_sensitive,
1155185a700Sflorian const uint32_t *previous_hashp)
1165185a700Sflorian {
1175185a700Sflorian uint32_t hval;
1185185a700Sflorian const unsigned char *bp;
1195185a700Sflorian const unsigned char *be;
1205185a700Sflorian
1215185a700Sflorian REQUIRE(length == 0 || data != NULL);
1225185a700Sflorian if (!fnv_once) {
123*1fb015a8Sflorian fnv_once = 1;
1245185a700Sflorian fnv_initialize();
1255185a700Sflorian }
1265185a700Sflorian
1275185a700Sflorian hval = previous_hashp != NULL ?
1285185a700Sflorian *previous_hashp : fnv_offset_basis;
1295185a700Sflorian
1305185a700Sflorian if (length == 0)
1315185a700Sflorian return (hval);
1325185a700Sflorian
1335185a700Sflorian bp = (const unsigned char *) data;
1345185a700Sflorian be = bp + length;
1355185a700Sflorian
1365185a700Sflorian /*
1375185a700Sflorian * Fowler-Noll-Vo FNV-1a hash function.
1385185a700Sflorian *
1395185a700Sflorian * NOTE: A random fnv_offset_basis is used by default to avoid
1405185a700Sflorian * collision attacks as the hash function is reversible. This
1415185a700Sflorian * makes the mapping non-deterministic, but the distribution in
1425185a700Sflorian * the domain is still uniform.
1435185a700Sflorian */
1445185a700Sflorian
1455185a700Sflorian if (case_sensitive) {
1465185a700Sflorian while (be >= bp + 4) {
1475185a700Sflorian be -= 4;
1485185a700Sflorian hval ^= (uint32_t) be[3];
1495185a700Sflorian hval *= 16777619;
1505185a700Sflorian hval ^= (uint32_t) be[2];
1515185a700Sflorian hval *= 16777619;
1525185a700Sflorian hval ^= (uint32_t) be[1];
1535185a700Sflorian hval *= 16777619;
1545185a700Sflorian hval ^= (uint32_t) be[0];
1555185a700Sflorian hval *= 16777619;
1565185a700Sflorian }
1575185a700Sflorian while (--be >= bp) {
1585185a700Sflorian hval ^= (uint32_t) *be;
1595185a700Sflorian hval *= 16777619;
1605185a700Sflorian }
1615185a700Sflorian } else {
1625185a700Sflorian while (be >= bp + 4) {
1635185a700Sflorian be -= 4;
1645185a700Sflorian hval ^= (uint32_t) maptolower[be[3]];
1655185a700Sflorian hval *= 16777619;
1665185a700Sflorian hval ^= (uint32_t) maptolower[be[2]];
1675185a700Sflorian hval *= 16777619;
1685185a700Sflorian hval ^= (uint32_t) maptolower[be[1]];
1695185a700Sflorian hval *= 16777619;
1705185a700Sflorian hval ^= (uint32_t) maptolower[be[0]];
1715185a700Sflorian hval *= 16777619;
1725185a700Sflorian }
1735185a700Sflorian while (--be >= bp) {
1745185a700Sflorian hval ^= (uint32_t) maptolower[*be];
1755185a700Sflorian hval *= 16777619;
1765185a700Sflorian }
1775185a700Sflorian }
1785185a700Sflorian
1795185a700Sflorian return (hval);
1805185a700Sflorian }
181