security/nss/lib/ckfw/hash.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 /*
michael@0 6 * hash.c
michael@0 7 *
michael@0 8 * This is merely a couple wrappers around NSPR's PLHashTable, using
michael@0 9 * the identity hash and arena-aware allocators. The reason I did
michael@0 10 * this is that hash tables are used in a few places throughout the
michael@0 11 * NSS Cryptoki Framework in a fairly stereotyped way, and this allows
michael@0 12 * me to pull the commonalities into one place. Should we ever want
michael@0 13 * to change the implementation, it's all right here.
michael@0 14 */
michael@0 15
michael@0 16 #ifndef CK_T
michael@0 17 #include "ck.h"
michael@0 18 #endif /* CK_T */
michael@0 19
michael@0 20 /*
michael@0 21 * nssCKFWHash
michael@0 22 *
michael@0 23 * nssCKFWHash_Create
michael@0 24 * nssCKFWHash_Destroy
michael@0 25 * nssCKFWHash_Add
michael@0 26 * nssCKFWHash_Remove
michael@0 27 * nssCKFWHash_Count
michael@0 28 * nssCKFWHash_Exists
michael@0 29 * nssCKFWHash_Lookup
michael@0 30 * nssCKFWHash_Iterate
michael@0 31 */
michael@0 32
michael@0 33 struct nssCKFWHashStr {
michael@0 34 NSSCKFWMutex *mutex;
michael@0 35
michael@0 36 /*
michael@0 37 * The invariant that mutex protects is:
michael@0 38 * The count accurately reflects the hashtable state.
michael@0 39 */
michael@0 40
michael@0 41 PLHashTable *plHashTable;
michael@0 42 CK_ULONG count;
michael@0 43 };
michael@0 44
michael@0 45 static PLHashNumber
michael@0 46 nss_ckfw_identity_hash
michael@0 47 (
michael@0 48 const void *key
michael@0 49 )
michael@0 50 {
michael@0 51 PRUint32 i = (PRUint32)key;
michael@0 52 PR_ASSERT(sizeof(PLHashNumber) == sizeof(PRUint32));
michael@0 53 return (PLHashNumber)i;
michael@0 54 }
michael@0 55
michael@0 56 /*
michael@0 57 * nssCKFWHash_Create
michael@0 58 *
michael@0 59 */
michael@0 60 NSS_IMPLEMENT nssCKFWHash *
michael@0 61 nssCKFWHash_Create
michael@0 62 (
michael@0 63 NSSCKFWInstance *fwInstance,
michael@0 64 NSSArena *arena,
michael@0 65 CK_RV *pError
michael@0 66 )
michael@0 67 {
michael@0 68 nssCKFWHash *rv;
michael@0 69
michael@0 70 #ifdef NSSDEBUG
michael@0 71 if (!pError) {
michael@0 72 return (nssCKFWHash *)NULL;
michael@0 73 }
michael@0 74
michael@0 75 if( PR_SUCCESS != nssArena_verifyPointer(arena) ) {
michael@0 76 *pError = CKR_ARGUMENTS_BAD;
michael@0 77 return (nssCKFWHash *)NULL;
michael@0 78 }
michael@0 79 #endif /* NSSDEBUG */
michael@0 80
michael@0 81 rv = nss_ZNEW(arena, nssCKFWHash);
michael@0 82 if (!rv) {
michael@0 83 *pError = CKR_HOST_MEMORY;
michael@0 84 return (nssCKFWHash *)NULL;
michael@0 85 }
michael@0 86
michael@0 87 rv->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError);
michael@0 88 if (!rv->mutex) {
michael@0 89 if( CKR_OK == *pError ) {
michael@0 90 (void)nss_ZFreeIf(rv);
michael@0 91 *pError = CKR_GENERAL_ERROR;
michael@0 92 }
michael@0 93 return (nssCKFWHash *)NULL;
michael@0 94 }
michael@0 95
michael@0 96 rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash,
michael@0 97 PL_CompareValues, PL_CompareValues, &nssArenaHashAllocOps, arena);
michael@0 98 if (!rv->plHashTable) {
michael@0 99 (void)nssCKFWMutex_Destroy(rv->mutex);
michael@0 100 (void)nss_ZFreeIf(rv);
michael@0 101 *pError = CKR_HOST_MEMORY;
michael@0 102 return (nssCKFWHash *)NULL;
michael@0 103 }
michael@0 104
michael@0 105 rv->count = 0;
michael@0 106
michael@0 107 return rv;
michael@0 108 }
michael@0 109
michael@0 110 /*
michael@0 111 * nssCKFWHash_Destroy
michael@0 112 *
michael@0 113 */
michael@0 114 NSS_IMPLEMENT void
michael@0 115 nssCKFWHash_Destroy
michael@0 116 (
michael@0 117 nssCKFWHash *hash
michael@0 118 )
michael@0 119 {
michael@0 120 (void)nssCKFWMutex_Destroy(hash->mutex);
michael@0 121 PL_HashTableDestroy(hash->plHashTable);
michael@0 122 (void)nss_ZFreeIf(hash);
michael@0 123 }
michael@0 124
michael@0 125 /*
michael@0 126 * nssCKFWHash_Add
michael@0 127 *
michael@0 128 */
michael@0 129 NSS_IMPLEMENT CK_RV
michael@0 130 nssCKFWHash_Add
michael@0 131 (
michael@0 132 nssCKFWHash *hash,
michael@0 133 const void *key,
michael@0 134 const void *value
michael@0 135 )
michael@0 136 {
michael@0 137 CK_RV error = CKR_OK;
michael@0 138 PLHashEntry *he;
michael@0 139
michael@0 140 error = nssCKFWMutex_Lock(hash->mutex);
michael@0 141 if( CKR_OK != error ) {
michael@0 142 return error;
michael@0 143 }
michael@0 144
michael@0 145 he = PL_HashTableAdd(hash->plHashTable, key, (void *)value);
michael@0 146 if (!he) {
michael@0 147 error = CKR_HOST_MEMORY;
michael@0 148 } else {
michael@0 149 hash->count++;
michael@0 150 }
michael@0 151
michael@0 152 (void)nssCKFWMutex_Unlock(hash->mutex);
michael@0 153
michael@0 154 return error;
michael@0 155 }
michael@0 156
michael@0 157 /*
michael@0 158 * nssCKFWHash_Remove
michael@0 159 *
michael@0 160 */
michael@0 161 NSS_IMPLEMENT void
michael@0 162 nssCKFWHash_Remove
michael@0 163 (
michael@0 164 nssCKFWHash *hash,
michael@0 165 const void *it
michael@0 166 )
michael@0 167 {
michael@0 168 PRBool found;
michael@0 169
michael@0 170 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
michael@0 171 return;
michael@0 172 }
michael@0 173
michael@0 174 found = PL_HashTableRemove(hash->plHashTable, it);
michael@0 175 if( found ) {
michael@0 176 hash->count--;
michael@0 177 }
michael@0 178
michael@0 179 (void)nssCKFWMutex_Unlock(hash->mutex);
michael@0 180 return;
michael@0 181 }
michael@0 182
michael@0 183 /*
michael@0 184 * nssCKFWHash_Count
michael@0 185 *
michael@0 186 */
michael@0 187 NSS_IMPLEMENT CK_ULONG
michael@0 188 nssCKFWHash_Count
michael@0 189 (
michael@0 190 nssCKFWHash *hash
michael@0 191 )
michael@0 192 {
michael@0 193 CK_ULONG count;
michael@0 194
michael@0 195 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
michael@0 196 return (CK_ULONG)0;
michael@0 197 }
michael@0 198
michael@0 199 count = hash->count;
michael@0 200
michael@0 201 (void)nssCKFWMutex_Unlock(hash->mutex);
michael@0 202
michael@0 203 return count;
michael@0 204 }
michael@0 205
michael@0 206 /*
michael@0 207 * nssCKFWHash_Exists
michael@0 208 *
michael@0 209 */
michael@0 210 NSS_IMPLEMENT CK_BBOOL
michael@0 211 nssCKFWHash_Exists
michael@0 212 (
michael@0 213 nssCKFWHash *hash,
michael@0 214 const void *it
michael@0 215 )
michael@0 216 {
michael@0 217 void *value;
michael@0 218
michael@0 219 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
michael@0 220 return CK_FALSE;
michael@0 221 }
michael@0 222
michael@0 223 value = PL_HashTableLookup(hash->plHashTable, it);
michael@0 224
michael@0 225 (void)nssCKFWMutex_Unlock(hash->mutex);
michael@0 226
michael@0 227 if (!value) {
michael@0 228 return CK_FALSE;
michael@0 229 } else {
michael@0 230 return CK_TRUE;
michael@0 231 }
michael@0 232 }
michael@0 233
michael@0 234 /*
michael@0 235 * nssCKFWHash_Lookup
michael@0 236 *
michael@0 237 */
michael@0 238 NSS_IMPLEMENT void *
michael@0 239 nssCKFWHash_Lookup
michael@0 240 (
michael@0 241 nssCKFWHash *hash,
michael@0 242 const void *it
michael@0 243 )
michael@0 244 {
michael@0 245 void *rv;
michael@0 246
michael@0 247 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
michael@0 248 return (void *)NULL;
michael@0 249 }
michael@0 250
michael@0 251 rv = PL_HashTableLookup(hash->plHashTable, it);
michael@0 252
michael@0 253 (void)nssCKFWMutex_Unlock(hash->mutex);
michael@0 254
michael@0 255 return rv;
michael@0 256 }
michael@0 257
michael@0 258 struct arg_str {
michael@0 259 nssCKFWHashIterator fcn;
michael@0 260 void *closure;
michael@0 261 };
michael@0 262
michael@0 263 static PRIntn
michael@0 264 nss_ckfwhash_enumerator
michael@0 265 (
michael@0 266 PLHashEntry *he,
michael@0 267 PRIntn index,
michael@0 268 void *arg
michael@0 269 )
michael@0 270 {
michael@0 271 struct arg_str *as = (struct arg_str *)arg;
michael@0 272 as->fcn(he->key, he->value, as->closure);
michael@0 273 return HT_ENUMERATE_NEXT;
michael@0 274 }
michael@0 275
michael@0 276 /*
michael@0 277 * nssCKFWHash_Iterate
michael@0 278 *
michael@0 279 * NOTE that the iteration function will be called with the hashtable locked.
michael@0 280 */
michael@0 281 NSS_IMPLEMENT void
michael@0 282 nssCKFWHash_Iterate
michael@0 283 (
michael@0 284 nssCKFWHash *hash,
michael@0 285 nssCKFWHashIterator fcn,
michael@0 286 void *closure
michael@0 287 )
michael@0 288 {
michael@0 289 struct arg_str as;
michael@0 290 as.fcn = fcn;
michael@0 291 as.closure = closure;
michael@0 292
michael@0 293 if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) {
michael@0 294 return;
michael@0 295 }
michael@0 296
michael@0 297 PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as);
michael@0 298
michael@0 299 (void)nssCKFWMutex_Unlock(hash->mutex);
michael@0 300
michael@0 301 return;
michael@0 302 }

mercurial