sslbloom.c (2344B)
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * A bloom filter. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 8 9 #include "sslbloom.h" 10 #include "prnetdb.h" 11 #include "secport.h" 12 13 static inline unsigned int 14 sslBloom_Size(unsigned int bits) 15 { 16 return (bits >= 3) ? (1 << (bits - 3)) : 1; 17 } 18 19 SECStatus 20 sslBloom_Init(sslBloomFilter *filter, unsigned int k, unsigned int bits) 21 { 22 PORT_Assert(filter); 23 PORT_Assert(bits > 0); 24 PORT_Assert(bits <= sizeof(PRUint32) * 8); 25 PORT_Assert(k > 0); 26 27 filter->filter = PORT_ZNewArray(PRUint8, sslBloom_Size(bits)); 28 if (!filter->filter) { 29 return SECFailure; /* Error code already set. */ 30 } 31 32 filter->k = k; 33 filter->bits = bits; 34 return SECSuccess; 35 } 36 37 void 38 sslBloom_Zero(sslBloomFilter *filter) 39 { 40 PORT_Memset(filter->filter, 0, sslBloom_Size(filter->bits)); 41 } 42 43 void 44 sslBloom_Fill(sslBloomFilter *filter) 45 { 46 PORT_Memset(filter->filter, 0xff, sslBloom_Size(filter->bits)); 47 } 48 49 static PRBool 50 sslBloom_AddOrCheck(sslBloomFilter *filter, const PRUint8 *hashes, PRBool add) 51 { 52 unsigned int iteration; 53 unsigned int bitIndex; 54 PRUint32 tmp = 0; 55 PRUint8 mask; 56 unsigned int bytes = (filter->bits + 7) / 8; 57 unsigned int shift = (bytes * 8) - filter->bits; 58 PRBool found = PR_TRUE; 59 60 PORT_Assert(bytes <= sizeof(unsigned int)); 61 62 for (iteration = 0; iteration < filter->k; ++iteration) { 63 PORT_Memcpy(((PRUint8 *)&tmp) + (sizeof(tmp) - bytes), 64 hashes, bytes); 65 hashes += bytes; 66 bitIndex = PR_ntohl(tmp) >> shift; 67 68 mask = 1 << (bitIndex % 8); 69 found = found && filter->filter[bitIndex / 8] & mask; 70 if (add) { 71 filter->filter[bitIndex / 8] |= mask; 72 } 73 } 74 return found; 75 } 76 77 PRBool 78 sslBloom_Add(sslBloomFilter *filter, const PRUint8 *hashes) 79 { 80 return sslBloom_AddOrCheck(filter, hashes, PR_TRUE); 81 } 82 83 PRBool 84 sslBloom_Check(sslBloomFilter *filter, const PRUint8 *hashes) 85 { 86 return sslBloom_AddOrCheck(filter, hashes, PR_FALSE); 87 } 88 89 void 90 sslBloom_Destroy(sslBloomFilter *filter) 91 { 92 PORT_Free(filter->filter); 93 PORT_Memset(filter, 0, sizeof(*filter)); 94 }