1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/ckfw/hash.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,302 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * hash.c 1.10 + * 1.11 + * This is merely a couple wrappers around NSPR's PLHashTable, using 1.12 + * the identity hash and arena-aware allocators. The reason I did 1.13 + * this is that hash tables are used in a few places throughout the 1.14 + * NSS Cryptoki Framework in a fairly stereotyped way, and this allows 1.15 + * me to pull the commonalities into one place. Should we ever want 1.16 + * to change the implementation, it's all right here. 1.17 + */ 1.18 + 1.19 +#ifndef CK_T 1.20 +#include "ck.h" 1.21 +#endif /* CK_T */ 1.22 + 1.23 +/* 1.24 + * nssCKFWHash 1.25 + * 1.26 + * nssCKFWHash_Create 1.27 + * nssCKFWHash_Destroy 1.28 + * nssCKFWHash_Add 1.29 + * nssCKFWHash_Remove 1.30 + * nssCKFWHash_Count 1.31 + * nssCKFWHash_Exists 1.32 + * nssCKFWHash_Lookup 1.33 + * nssCKFWHash_Iterate 1.34 + */ 1.35 + 1.36 +struct nssCKFWHashStr { 1.37 + NSSCKFWMutex *mutex; 1.38 + 1.39 + /* 1.40 + * The invariant that mutex protects is: 1.41 + * The count accurately reflects the hashtable state. 1.42 + */ 1.43 + 1.44 + PLHashTable *plHashTable; 1.45 + CK_ULONG count; 1.46 +}; 1.47 + 1.48 +static PLHashNumber 1.49 +nss_ckfw_identity_hash 1.50 +( 1.51 + const void *key 1.52 +) 1.53 +{ 1.54 + PRUint32 i = (PRUint32)key; 1.55 + PR_ASSERT(sizeof(PLHashNumber) == sizeof(PRUint32)); 1.56 + return (PLHashNumber)i; 1.57 +} 1.58 + 1.59 +/* 1.60 + * nssCKFWHash_Create 1.61 + * 1.62 + */ 1.63 +NSS_IMPLEMENT nssCKFWHash * 1.64 +nssCKFWHash_Create 1.65 +( 1.66 + NSSCKFWInstance *fwInstance, 1.67 + NSSArena *arena, 1.68 + CK_RV *pError 1.69 +) 1.70 +{ 1.71 + nssCKFWHash *rv; 1.72 + 1.73 +#ifdef NSSDEBUG 1.74 + if (!pError) { 1.75 + return (nssCKFWHash *)NULL; 1.76 + } 1.77 + 1.78 + if( PR_SUCCESS != nssArena_verifyPointer(arena) ) { 1.79 + *pError = CKR_ARGUMENTS_BAD; 1.80 + return (nssCKFWHash *)NULL; 1.81 + } 1.82 +#endif /* NSSDEBUG */ 1.83 + 1.84 + rv = nss_ZNEW(arena, nssCKFWHash); 1.85 + if (!rv) { 1.86 + *pError = CKR_HOST_MEMORY; 1.87 + return (nssCKFWHash *)NULL; 1.88 + } 1.89 + 1.90 + rv->mutex = nssCKFWInstance_CreateMutex(fwInstance, arena, pError); 1.91 + if (!rv->mutex) { 1.92 + if( CKR_OK == *pError ) { 1.93 + (void)nss_ZFreeIf(rv); 1.94 + *pError = CKR_GENERAL_ERROR; 1.95 + } 1.96 + return (nssCKFWHash *)NULL; 1.97 + } 1.98 + 1.99 + rv->plHashTable = PL_NewHashTable(0, nss_ckfw_identity_hash, 1.100 + PL_CompareValues, PL_CompareValues, &nssArenaHashAllocOps, arena); 1.101 + if (!rv->plHashTable) { 1.102 + (void)nssCKFWMutex_Destroy(rv->mutex); 1.103 + (void)nss_ZFreeIf(rv); 1.104 + *pError = CKR_HOST_MEMORY; 1.105 + return (nssCKFWHash *)NULL; 1.106 + } 1.107 + 1.108 + rv->count = 0; 1.109 + 1.110 + return rv; 1.111 +} 1.112 + 1.113 +/* 1.114 + * nssCKFWHash_Destroy 1.115 + * 1.116 + */ 1.117 +NSS_IMPLEMENT void 1.118 +nssCKFWHash_Destroy 1.119 +( 1.120 + nssCKFWHash *hash 1.121 +) 1.122 +{ 1.123 + (void)nssCKFWMutex_Destroy(hash->mutex); 1.124 + PL_HashTableDestroy(hash->plHashTable); 1.125 + (void)nss_ZFreeIf(hash); 1.126 +} 1.127 + 1.128 +/* 1.129 + * nssCKFWHash_Add 1.130 + * 1.131 + */ 1.132 +NSS_IMPLEMENT CK_RV 1.133 +nssCKFWHash_Add 1.134 +( 1.135 + nssCKFWHash *hash, 1.136 + const void *key, 1.137 + const void *value 1.138 +) 1.139 +{ 1.140 + CK_RV error = CKR_OK; 1.141 + PLHashEntry *he; 1.142 + 1.143 + error = nssCKFWMutex_Lock(hash->mutex); 1.144 + if( CKR_OK != error ) { 1.145 + return error; 1.146 + } 1.147 + 1.148 + he = PL_HashTableAdd(hash->plHashTable, key, (void *)value); 1.149 + if (!he) { 1.150 + error = CKR_HOST_MEMORY; 1.151 + } else { 1.152 + hash->count++; 1.153 + } 1.154 + 1.155 + (void)nssCKFWMutex_Unlock(hash->mutex); 1.156 + 1.157 + return error; 1.158 +} 1.159 + 1.160 +/* 1.161 + * nssCKFWHash_Remove 1.162 + * 1.163 + */ 1.164 +NSS_IMPLEMENT void 1.165 +nssCKFWHash_Remove 1.166 +( 1.167 + nssCKFWHash *hash, 1.168 + const void *it 1.169 +) 1.170 +{ 1.171 + PRBool found; 1.172 + 1.173 + if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { 1.174 + return; 1.175 + } 1.176 + 1.177 + found = PL_HashTableRemove(hash->plHashTable, it); 1.178 + if( found ) { 1.179 + hash->count--; 1.180 + } 1.181 + 1.182 + (void)nssCKFWMutex_Unlock(hash->mutex); 1.183 + return; 1.184 +} 1.185 + 1.186 +/* 1.187 + * nssCKFWHash_Count 1.188 + * 1.189 + */ 1.190 +NSS_IMPLEMENT CK_ULONG 1.191 +nssCKFWHash_Count 1.192 +( 1.193 + nssCKFWHash *hash 1.194 +) 1.195 +{ 1.196 + CK_ULONG count; 1.197 + 1.198 + if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { 1.199 + return (CK_ULONG)0; 1.200 + } 1.201 + 1.202 + count = hash->count; 1.203 + 1.204 + (void)nssCKFWMutex_Unlock(hash->mutex); 1.205 + 1.206 + return count; 1.207 +} 1.208 + 1.209 +/* 1.210 + * nssCKFWHash_Exists 1.211 + * 1.212 + */ 1.213 +NSS_IMPLEMENT CK_BBOOL 1.214 +nssCKFWHash_Exists 1.215 +( 1.216 + nssCKFWHash *hash, 1.217 + const void *it 1.218 +) 1.219 +{ 1.220 + void *value; 1.221 + 1.222 + if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { 1.223 + return CK_FALSE; 1.224 + } 1.225 + 1.226 + value = PL_HashTableLookup(hash->plHashTable, it); 1.227 + 1.228 + (void)nssCKFWMutex_Unlock(hash->mutex); 1.229 + 1.230 + if (!value) { 1.231 + return CK_FALSE; 1.232 + } else { 1.233 + return CK_TRUE; 1.234 + } 1.235 +} 1.236 + 1.237 +/* 1.238 + * nssCKFWHash_Lookup 1.239 + * 1.240 + */ 1.241 +NSS_IMPLEMENT void * 1.242 +nssCKFWHash_Lookup 1.243 +( 1.244 + nssCKFWHash *hash, 1.245 + const void *it 1.246 +) 1.247 +{ 1.248 + void *rv; 1.249 + 1.250 + if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { 1.251 + return (void *)NULL; 1.252 + } 1.253 + 1.254 + rv = PL_HashTableLookup(hash->plHashTable, it); 1.255 + 1.256 + (void)nssCKFWMutex_Unlock(hash->mutex); 1.257 + 1.258 + return rv; 1.259 +} 1.260 + 1.261 +struct arg_str { 1.262 + nssCKFWHashIterator fcn; 1.263 + void *closure; 1.264 +}; 1.265 + 1.266 +static PRIntn 1.267 +nss_ckfwhash_enumerator 1.268 +( 1.269 + PLHashEntry *he, 1.270 + PRIntn index, 1.271 + void *arg 1.272 +) 1.273 +{ 1.274 + struct arg_str *as = (struct arg_str *)arg; 1.275 + as->fcn(he->key, he->value, as->closure); 1.276 + return HT_ENUMERATE_NEXT; 1.277 +} 1.278 + 1.279 +/* 1.280 + * nssCKFWHash_Iterate 1.281 + * 1.282 + * NOTE that the iteration function will be called with the hashtable locked. 1.283 + */ 1.284 +NSS_IMPLEMENT void 1.285 +nssCKFWHash_Iterate 1.286 +( 1.287 + nssCKFWHash *hash, 1.288 + nssCKFWHashIterator fcn, 1.289 + void *closure 1.290 +) 1.291 +{ 1.292 + struct arg_str as; 1.293 + as.fcn = fcn; 1.294 + as.closure = closure; 1.295 + 1.296 + if( CKR_OK != nssCKFWMutex_Lock(hash->mutex) ) { 1.297 + return; 1.298 + } 1.299 + 1.300 + PL_HashTableEnumerateEntries(hash->plHashTable, nss_ckfwhash_enumerator, &as); 1.301 + 1.302 + (void)nssCKFWMutex_Unlock(hash->mutex); 1.303 + 1.304 + return; 1.305 +}