security/nss/lib/ckfw/hash.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial