Browse Source

Ref count: change to use wolfSSL_Ref

Data structures changed:
WOLFSSL_CERT_MANAGER, WOLFSSL_CTX, WOLFSSL_SESSION, WOLFSSL_X509,
WOLFSSL_X509, WOLFSSL_EVP_PKEY, WOLFSSL_BIO, WOLFSSL_X509_STORE
Sean Parkinson 1 year ago
parent
commit
53dfcd00e2
11 changed files with 107 additions and 232 deletions
  1. 1 0
      m4/ax_atomic.m4
  2. 13 31
      src/bio.c
  3. 16 41
      src/internal.c
  4. 35 57
      src/ssl.c
  5. 6 18
      src/x509.c
  6. 9 20
      src/x509_str.c
  7. 2 2
      tests/api.c
  8. 15 35
      wolfcrypt/src/evp.c
  9. 3 1
      wolfcrypt/src/wc_port.c
  10. 4 15
      wolfssl/internal.h
  11. 3 12
      wolfssl/ssl.h

+ 1 - 0
m4/ax_atomic.m4

@@ -31,5 +31,6 @@ AC_DEFUN([AC_C___ATOMIC],
 if test $ac_cv_c___atomic = yes; then
   AC_DEFINE([HAVE_C___ATOMIC], 1,
            [Define to 1 if __atomic operations work.])
+  AM_CFLAGS="$AM_CFLAGS -DHAVE_C___ATOMIC"
 fi
 ])# AC_C___ATOMIC

+ 13 - 31
src/bio.c

@@ -766,15 +766,11 @@ long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg)
 int wolfSSL_BIO_up_ref(WOLFSSL_BIO* bio)
 {
     if (bio) {
-    #ifndef SINGLE_THREADED
-        if (wc_LockMutex(&bio->refMutex) != 0) {
+        int ret;
+        wolfSSL_RefInc(&bio->ref, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Failed to lock BIO mutex");
         }
-    #endif
-        bio->refCount++;
-    #ifndef SINGLE_THREADED
-        wc_UnLockMutex(&bio->refMutex);
-    #endif
 
         return WOLFSSL_SUCCESS;
     }
@@ -2495,14 +2491,15 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
             }
 
         #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
-            bio->refCount = 1;
-            #ifndef SINGLE_THREADED
-            if (wc_InitMutex(&bio->refMutex) != 0) {
-                wolfSSL_BIO_free(bio);
-                WOLFSSL_MSG("wc_InitMutex failed for WOLFSSL_BIO");
-                return NULL;
+            {
+                int ret;
+                wolfSSL_RefInit(&bio->ref, &ret);
+                if (ret != 0) {
+                    wolfSSL_BIO_free(bio);
+                    WOLFSSL_MSG("wc_InitMutex failed for WOLFSSL_BIO");
+                    return NULL;
+                }
             }
-            #endif
         #endif
 
         }
@@ -2567,29 +2564,14 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
             }
 
         #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
-            #ifndef SINGLE_THREADED
-            if (wc_LockMutex(&bio->refMutex) != 0) {
-                WOLFSSL_MSG("Couldn't lock BIO mutex");
-                return WOLFSSL_FAILURE;
-            }
-            #endif
-
-            /* only free if all references to it are done */
-            bio->refCount--;
-            if (bio->refCount == 0) {
-                doFree = 1;
-            }
-
-            #ifndef SINGLE_THREADED
-            wc_UnLockMutex(&bio->refMutex);
-            #endif
+            wolfSSL_RefDec(&bio->ref, &doFree, &ret);
 
             if (!doFree) {
                 /* return success if BIO ref count is not 1 yet */
                 return WOLFSSL_SUCCESS;
             }
             #ifndef SINGLE_THREADED
-            wc_FreeMutex(&bio->refMutex);
+            wolfSSL_RefFree(&bio->ref);
             #endif
         #endif
 

+ 16 - 41
src/internal.c

@@ -2140,7 +2140,6 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
     XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX));
 
     ctx->method   = method;
-    ctx->refCount = 1;          /* so either CTX_free or SSL_free can release */
     ctx->heap     = ctx;        /* defaults to self */
     ctx->timeout  = WOLFSSL_SESSION_TIMEOUT;
 
@@ -2155,7 +2154,8 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
         ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE;
     }
 
-    if (wc_InitMutex(&ctx->countMutex) < 0) {
+    wolfSSL_RefInit(&ctx->ref, &ret);
+    if (ret < 0) {
         WOLFSSL_MSG("Mutex error on CTX init");
         ctx->err = CTX_INIT_MUTEX_E;
         WOLFSSL_ERROR_VERBOSE(BAD_MUTEX_E);
@@ -2610,7 +2610,8 @@ static void SSL_CtxResourceFreeStaticMem(void* heap)
 
 void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
 {
-    int refCount;
+    int isZero;
+    int ret;
     void* heap = ctx->heap;
 #ifdef WOLFSSL_STATIC_MEMORY
     if (ctx->onHeapHint == 0) {
@@ -2619,7 +2620,8 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
 #endif
 
     /* decrement CTX reference count */
-    if ((refCount = SSL_CTX_RefCount(ctx, -1)) < 0) {
+    wolfSSL_RefDec(&ctx->ref, &isZero, &ret);
+    if (ret < 0) {
         /* check error state, if mutex error code then mutex init failed but
          * CTX was still malloc'd */
         if (ctx->err == CTX_INIT_MUTEX_E) {
@@ -2632,7 +2634,7 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
         return;
     }
 
-    if (refCount == 0) {
+    if (isZero) {
         WOLFSSL_MSG("CTX ref count down to 0, doing full free");
 
         SSL_CtxResourceFree(ctx);
@@ -2640,7 +2642,7 @@ void FreeSSL_Ctx(WOLFSSL_CTX* ctx)
     !defined(WOLFSSL_NO_DEF_TICKET_ENC_CB)
         TicketEncCbCtx_Free(&ctx->ticketKeyCtx);
 #endif
-        wc_FreeMutex(&ctx->countMutex);
+        wolfSSL_RefFree(&ctx->ref);
         XFREE(ctx, heap, DYNAMIC_TYPE_CTX);
     #ifdef WOLFSSL_STATIC_MEMORY
         SSL_CtxResourceFreeStaticMem(heap);
@@ -4203,10 +4205,11 @@ void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap)
     InitX509Name(&x509->subject, 0, heap);
     x509->dynamicMemory  = (byte)dynamicFlag;
 #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
-    x509->refCount = 1;
-#ifndef SINGLE_THREADED
-    (void)wc_InitMutex(&x509->refMutex);
-#endif
+    {
+        int ret;
+        wolfSSL_RefInit(&x509->ref, &ret);
+        (void)ret;
+    }
 #endif
 }
 
@@ -4301,9 +4304,7 @@ void FreeX509(WOLFSSL_X509* x509)
     }
 
     #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)
-    #ifndef SINGLE_THREADED
-        wc_FreeMutex(&x509->refMutex);
-    #endif
+        wolfSSL_RefFree(&x509->ref);
     #endif
 }
 
@@ -6151,33 +6152,6 @@ int InitSSL_Suites(WOLFSSL* ssl)
     return WOLFSSL_SUCCESS;
 }
 
-/* returns new reference count. Arg incr positive=up or negative=down */
-int SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr)
-{
-    int refCount;
-
-    if (ctx == NULL) {
-        return BAD_FUNC_ARG;
-    }
-
-    if (wc_LockMutex(&ctx->countMutex) != 0) {
-        WOLFSSL_MSG("Couldn't lock CTX count mutex");
-        WOLFSSL_ERROR_VERBOSE(BAD_MUTEX_E);
-        return BAD_MUTEX_E;
-    }
-
-    ctx->refCount += incr;
-    /* make sure refCount is never negative */
-    if (ctx->refCount < 0) {
-        ctx->refCount = 0;
-    }
-    refCount = ctx->refCount;
-
-    wc_UnLockMutex(&ctx->countMutex);
-
-    return refCount;
-}
-
 /* This function inherits a WOLFSSL_CTX's fields into an SSL object.
    It is used during initialization and to switch an ssl's CTX with
    wolfSSL_Set_SSL_CTX.  Requires ssl->suites alloc and ssl-arrays with PSK
@@ -6213,7 +6187,8 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
     }
 
     /* increment CTX reference count */
-    if ((ret = SSL_CTX_RefCount(ctx, 1)) < 0) {
+    wolfSSL_RefInc(&ctx->ref, &ret);
+    if (ret < 0) {
         return ret;
     }
     ret = WOLFSSL_SUCCESS; /* set default ret */

+ 35 - 57
src/ssl.c

@@ -1160,8 +1160,9 @@ WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method)
 /* increases CTX reference count to track proper time to "free" */
 int wolfSSL_CTX_up_ref(WOLFSSL_CTX* ctx)
 {
-    int refCount = SSL_CTX_RefCount(ctx, 1);
-    return ((refCount > 1) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE);
+    int ret;
+    wolfSSL_RefInc(&ctx->ref, &ret);
+    return ((ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE);
 }
 
 WOLFSSL_ABI
@@ -4836,21 +4837,22 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap)
     cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap,
                                          DYNAMIC_TYPE_CERT_MANAGER);
     if (cm) {
+        int ret;
+
         XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER));
-        cm->refCount = 1;
 
         if (wc_InitMutex(&cm->caLock) != 0) {
             WOLFSSL_MSG("Bad mutex init");
             wolfSSL_CertManagerFree(cm);
             return NULL;
         }
-        #ifndef SINGLE_THREADED
-        if (wc_InitMutex(&cm->refMutex) != 0) {
+
+        wolfSSL_RefInit(&cm->ref, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Bad mutex init");
             wolfSSL_CertManagerFree(cm);
             return NULL;
         }
-        #endif
 
         #ifdef WOLFSSL_TRUST_PEER_CERT
         if (wc_InitMutex(&cm->tpLock) != 0) {
@@ -4892,20 +4894,14 @@ WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void)
 void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
 {
     int doFree = 0;
+    int ret;
     WOLFSSL_ENTER("wolfSSL_CertManagerFree");
 
     if (cm) {
-        #ifndef SINGLE_THREADED
-        if (wc_LockMutex(&cm->refMutex) != 0) {
+        wolfSSL_RefDec(&cm->ref, &doFree, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Couldn't lock cm mutex");
         }
-        #endif
-        cm->refCount--;
-        if (cm->refCount == 0)
-            doFree = 1;
-        #ifndef SINGLE_THREADED
-        wc_UnLockMutex(&cm->refMutex);
-        #endif
         if (doFree) {
             #ifdef HAVE_CRL
                 if (cm->crl)
@@ -4929,11 +4925,7 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
             FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap);
             wc_FreeMutex(&cm->tpLock);
             #endif
-            #ifndef SINGLE_THREADED
-            if (wc_FreeMutex(&cm->refMutex) != 0) {
-                WOLFSSL_MSG("Couldn't free refMutex mutex");
-            }
-            #endif
+            wolfSSL_RefFree(&cm->ref);
             XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER);
         }
     }
@@ -4943,16 +4935,13 @@ void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm)
 int wolfSSL_CertManager_up_ref(WOLFSSL_CERT_MANAGER* cm)
 {
     if (cm) {
-#ifndef SINGLE_THREADED
-        if (wc_LockMutex(&cm->refMutex) != 0) {
+        int ret;
+
+        wolfSSL_RefInc(&cm->ref, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Failed to lock cm mutex");
             return WOLFSSL_FAILURE;
         }
-#endif
-        cm->refCount++;
-#ifndef SINGLE_THREADED
-        wc_UnLockMutex(&cm->refMutex);
-#endif
 
         return WOLFSSL_SUCCESS;
     }
@@ -20963,15 +20952,14 @@ WOLFSSL_SESSION* wolfSSL_NewSession(void* heap)
     ret = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), heap,
             DYNAMIC_TYPE_SESSION);
     if (ret != NULL) {
+        int err;
         XMEMSET(ret, 0, sizeof(WOLFSSL_SESSION));
-    #ifndef SINGLE_THREADED
-        if (wc_InitMutex(&ret->refMutex) != 0) {
+        wolfSSL_RefInit(&ret->ref, &err);
+        if (err != 0) {
             WOLFSSL_MSG("Error setting up session reference mutex");
             XFREE(ret, ret->heap, DYNAMIC_TYPE_SESSION);
             return NULL;
         }
-    #endif
-        ret->refCount = 1;
 #ifndef NO_SESSION_CACHE
         ret->cacheRow = INVALID_SESSION_ROW; /* not in cache */
 #endif
@@ -21021,21 +21009,19 @@ WOLFSSL_SESSION* wolfSSL_SESSION_new(void)
  * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error */
 int wolfSSL_SESSION_up_ref(WOLFSSL_SESSION* session)
 {
+    int ret;
+
     session = ClientSessionToSession(session);
 
     if (session == NULL || session->type != WOLFSSL_SESSION_TYPE_HEAP)
         return WOLFSSL_FAILURE;
 
-#ifndef SINGLE_THREADED
-    if (wc_LockMutex(&session->refMutex) != 0) {
+    wolfSSL_RefInc(&session->ref, &ret);
+    if (ret != 0) {
         WOLFSSL_MSG("Failed to lock session mutex");
         return WOLFSSL_FAILURE;
     }
-#endif
-    session->refCount++;
-#ifndef SINGLE_THREADED
-    wc_UnLockMutex(&session->refMutex);
-#endif
+
     return WOLFSSL_SUCCESS;
 }
 
@@ -21322,32 +21308,22 @@ WOLFSSL_SESSION* wolfSSL_SESSION_dup(WOLFSSL_SESSION* session)
 
 void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session)
 {
+    int isZero;
+
     session = ClientSessionToSession(session);
     if (session == NULL)
         return;
 
     (void)ctx;
 
-    /* refCount will always be 1 or more if created externally.
-     * Internal cache sessions don't initialize a refMutex. */
-    if (session->refCount > 0) {
-#ifndef SINGLE_THREADED
-        if (wc_LockMutex(&session->refMutex) != 0) {
-            WOLFSSL_MSG("Failed to lock session mutex");
-            return;
-        }
-#endif
-        if (session->refCount > 1) {
-            session->refCount--;
-#ifndef SINGLE_THREADED
-            wc_UnLockMutex(&session->refMutex);
-#endif
+    if (session->ref.count > 0) {
+        int ret;
+        wolfSSL_RefDec(&session->ref, &isZero, &ret);
+        (void)ret;
+        if (!isZero) {
             return;
         }
-#ifndef SINGLE_THREADED
-        wc_UnLockMutex(&session->refMutex);
-        wc_FreeMutex(&session->refMutex);
-#endif
+        wolfSSL_RefFree(&session->ref);
     }
 
 #if defined(HAVE_EXT_CACHE) || defined(HAVE_EX_DATA)
@@ -32436,6 +32412,7 @@ const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type)
 
 WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
 {
+    int ret;
     /* This method requires some explanation. Its sibling is
      *   int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
      * which re-inits the WOLFSSL* with all settings in the new CTX.
@@ -32458,7 +32435,8 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
     if (ssl->ctx == ctx)
         return ssl->ctx;
 
-    if (SSL_CTX_RefCount(ctx, 1) < 0) {
+    wolfSSL_RefInc(&ctx->ref, &ret);
+    if (ret != 0) {
         /* can only fail on serious stuff, like mutex not working
          * or ctx refcount out of whack. */
         return NULL;

+ 6 - 18
src/x509.c

@@ -2946,18 +2946,11 @@ static void ExternalFreeX509(WOLFSSL_X509* x509)
 #endif
         if (x509->dynamicMemory) {
         #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
-        #ifndef SINGLE_THREADED
-            if (wc_LockMutex(&x509->refMutex) != 0) {
+            int ret;
+            wolfSSL_RefDec(&x509->ref, &doFree, &ret);
+            if (ret != 0) {
                 WOLFSSL_MSG("Couldn't lock x509 mutex");
             }
-        #endif
-            /* only free if all references to it are done */
-            x509->refCount--;
-            if (x509->refCount == 0)
-                doFree = 1;
-        #ifndef SINGLE_THREADED
-            wc_UnLockMutex(&x509->refMutex);
-        #endif
         #endif /* OPENSSL_EXTRA_X509_SMALL || OPENSSL_EXTRA */
 
         #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
@@ -9038,21 +9031,16 @@ char*  wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509)
 #endif /* KEEP_PEER_CERT */
 
 #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
-
 /* increments ref count of WOLFSSL_X509. Return 1 on success, 0 on error */
 int wolfSSL_X509_up_ref(WOLFSSL_X509* x509)
 {
     if (x509) {
-#ifndef SINGLE_THREADED
-        if (wc_LockMutex(&x509->refMutex) != 0) {
+        int ret;
+        wolfSSL_RefInc(&x509->ref, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Failed to lock x509 mutex");
             return WOLFSSL_FAILURE;
         }
-#endif
-        x509->refCount++;
-#ifndef SINGLE_THREADED
-        wc_UnLockMutex(&x509->refMutex);
-#endif
 
         return WOLFSSL_SUCCESS;
     }

+ 9 - 20
src/x509_str.c

@@ -713,6 +713,7 @@ int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer,
     defined(WOLFSSL_WPAS_SMALL)
 WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void)
 {
+    int ret;
     WOLFSSL_X509_STORE* store = NULL;
     WOLFSSL_ENTER("SSL_X509_STORE_new");
 
@@ -722,12 +723,10 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void)
 
     XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE));
     store->isDynamic = 1;
-    store->refCount = 1;
 
-#ifndef SINGLE_THREADED
-    if (wc_InitMutex(&store->refMutex) != 0)
+    wolfSSL_RefInit(&store->ref, &ret);
+    if (ret != 0)
         goto err_exit;
-#endif
 
     if ((store->cm = wolfSSL_CertManagerNew()) == NULL)
         goto err_exit;
@@ -774,17 +773,11 @@ void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store)
 {
     int doFree = 0;
     if (store != NULL && store->isDynamic) {
-#ifndef SINGLE_THREADED
-        if (wc_LockMutex(&store->refMutex) != 0) {
+        int ret;
+        wolfSSL_RefDec(&store->ref, &doFree, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Couldn't lock store mutex");
         }
-#endif
-        store->refCount--;
-        if (store->refCount == 0)
-            doFree = 1;
-#ifndef SINGLE_THREADED
-        wc_UnLockMutex(&store->refMutex);
-#endif
 
         if (doFree) {
 #ifdef HAVE_EX_DATA_CLEANUP_HOOKS
@@ -844,16 +837,12 @@ void* wolfSSL_X509_STORE_get_ex_data(WOLFSSL_X509_STORE* store, int idx)
 int wolfSSL_X509_STORE_up_ref(WOLFSSL_X509_STORE* store)
 {
     if (store) {
-#ifndef SINGLE_THREADED
-        if (wc_LockMutex(&store->refMutex) != 0) {
+        int ret;
+        wolfSSL_RefInc(&store->ref, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Failed to lock store mutex");
             return WOLFSSL_FAILURE;
         }
-#endif
-        store->refCount++;
-#ifndef SINGLE_THREADED
-        wc_UnLockMutex(&store->refMutex);
-#endif
 
         return WOLFSSL_SUCCESS;
     }

+ 2 - 2
tests/api.c

@@ -48888,9 +48888,9 @@ static int test_wolfSSL_EVP_PKEY_encrypt(void)
 
     /* Test pkey references count is decremented. pkey shouldn't be destroyed
      since ctx uses it.*/
-    AssertIntEQ(pkey->references, 2);
+    AssertIntEQ(pkey->ref.count, 2);
     EVP_PKEY_free(pkey);
-    AssertIntEQ(pkey->references, 1);
+    AssertIntEQ(pkey->ref.count, 1);
 
     /* Encrypt data */
     /* Check that we can get the required output buffer length by passing in a

+ 15 - 35
wolfcrypt/src/evp.c

@@ -9338,15 +9338,11 @@ WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_EVP_PKEY2PKCS8(const WOLFSSL_EVP_PKEY* pkey
 int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey)
 {
     if (pkey) {
-#ifndef SINGLE_THREADED
-        if (wc_LockMutex(&pkey->refMutex) != 0) {
+        int ret;
+        wolfSSL_RefInc(&pkey->ref, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Failed to lock pkey mutex");
         }
-#endif
-        pkey->references++;
-#ifndef SINGLE_THREADED
-        wc_UnLockMutex(&pkey->refMutex);
-#endif
 
         return WOLFSSL_SUCCESS;
     }
@@ -9444,27 +9440,24 @@ WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_ex(void* heap)
         pkey->heap = heap;
         pkey->type = WOLFSSL_EVP_PKEY_DEFAULT;
 
-#ifndef SINGLE_THREADED
-        /* init of mutex needs to come before wolfSSL_EVP_PKEY_free */
-        ret = wc_InitMutex(&pkey->refMutex);
-        if (ret != 0){
-            XFREE(pkey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
-            WOLFSSL_MSG("Issue initializing mutex");
-            return NULL;
-        }
-#endif
-
 #ifndef HAVE_FIPS
         ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID);
 #else
         ret = wc_InitRng(&pkey->rng);
 #endif
-        pkey->references = 1;
         if (ret != 0){
             wolfSSL_EVP_PKEY_free(pkey);
             WOLFSSL_MSG("Issue initializing RNG");
             return NULL;
         }
+
+        wolfSSL_RefInit(&pkey->ref, &ret);
+        if (ret != 0){
+            wolfSSL_EVP_PKEY_free(pkey);
+            WOLFSSL_MSG("Issue initializing mutex");
+            return NULL;
+        }
+
     }
     else {
         WOLFSSL_MSG("memory failure");
@@ -9478,20 +9471,11 @@ void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
     int doFree = 0;
     WOLFSSL_ENTER("wolfSSL_EVP_PKEY_free");
     if (key != NULL) {
-        #ifndef SINGLE_THREADED
-        if (wc_LockMutex(&key->refMutex) != 0) {
+        int ret;
+        wolfSSL_RefDec(&key->ref, &doFree, &ret);
+        if (ret != 0) {
             WOLFSSL_MSG("Couldn't lock pkey mutex");
         }
-        #endif
-
-        /* only free if all references to it are done */
-        key->references--;
-        if (key->references == 0) {
-            doFree = 1;
-        }
-        #ifndef SINGLE_THREADED
-        wc_UnLockMutex(&key->refMutex);
-        #endif
 
         if (doFree) {
             wc_FreeRng(&key->rng);
@@ -9573,11 +9557,7 @@ void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key)
                     break;
             }
 
-            #ifndef SINGLE_THREADED
-            if (wc_FreeMutex(&key->refMutex) != 0) {
-                WOLFSSL_MSG("Couldn't free pkey mutex");
-            }
-            #endif
+            wolfSSL_RefFree(&key->ref);
             XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY);
         }
     }

+ 3 - 1
wolfcrypt/src/wc_port.c

@@ -1100,7 +1100,9 @@ void wolfSSL_RefDec(wolfSSL_Ref* ref, int* isZero, int* err)
         WOLFSSL_MSG("Failed to lock mutex for reference decrement!");
     }
     else {
-        ref->count--;
+        if (ref->count > 0) {
+            ref->count--;
+        }
         *isZero = (ref->count == 0);
         wc_UnLockMutex(&ref->mutex);
     }

+ 4 - 15
wolfssl/internal.h

@@ -2366,10 +2366,7 @@ struct WOLFSSL_CERT_MANAGER {
                                         /* CTX has ownership and free this   */
                                         /* with CTX free.                    */
 #endif
-#ifndef SINGLE_THREADED
-    wolfSSL_Mutex   refMutex;   /* reference count mutex */
-#endif
-    int             refCount;         /* reference count */
+    wolfSSL_Ref     ref;
 #ifdef HAVE_PQC
     short           minFalconKeySz;      /* minimum allowed Falcon key size */
     short           minDilithiumKeySz;   /* minimum allowed Dilithium key size */
@@ -3179,8 +3176,7 @@ struct WOLFSSL_CTX {
 #ifdef SINGLE_THREADED
     WC_RNG*         rng;          /* to be shared with WOLFSSL w/o locking */
 #endif
-    wolfSSL_Mutex   countMutex;   /* reference count mutex */
-    int         refCount;         /* reference count */
+    wolfSSL_Ref     ref;
     int         err;              /* error code in case of mutex not created */
 #ifndef NO_DH
     buffer      serverDH_P;
@@ -3895,10 +3891,7 @@ struct WOLFSSL_SESSION {
 #ifndef NO_SESSION_CACHE
     int                cacheRow;          /* row in session cache     */
 #endif
-    int                refCount;          /* reference count */
-#ifndef SINGLE_THREADED
-    wolfSSL_Mutex      refMutex;          /* ref count mutex */
-#endif
+    wolfSSL_Ref        ref;
     byte               altSessionID[ID_LEN];
     byte               haveAltSessionID:1;
 #ifdef HAVE_EX_DATA
@@ -4575,10 +4568,7 @@ struct WOLFSSL_X509 {
     int              certPoliciesNb;
 #endif /* WOLFSSL_CERT_EXT */
 #if defined(OPENSSL_EXTRA_X509_SMALL) || defined(OPENSSL_EXTRA)
-#ifndef SINGLE_THREADED
-    wolfSSL_Mutex    refMutex;                       /* ref count mutex */
-#endif
-    int              refCount;                       /* reference count */
+    wolfSSL_Ref      ref;
 #endif
 #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
 #ifdef HAVE_EX_DATA
@@ -5466,7 +5456,6 @@ struct WOLFSSL {
 #define SSL_CA_NAMES(ssl) ((ssl)->ca_names != NULL ? (ssl)->ca_names : \
         (ssl)->ctx->ca_names)
 
-WOLFSSL_LOCAL int  SSL_CTX_RefCount(WOLFSSL_CTX* ctx, int incr);
 WOLFSSL_LOCAL int  SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup);
 WOLFSSL_LOCAL int  InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup);
 WOLFSSL_LOCAL int  ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup);

+ 3 - 12
wolfssl/ssl.h

@@ -382,10 +382,7 @@ struct WOLFSSL_EVP_PKEY {
     int type;         /* openssh dereference */
     int save_type;    /* openssh dereference */
     int pkey_sz;
-    int references;  /*number of times free should be called for complete free*/
-#ifndef SINGLE_THREADED
-    wolfSSL_Mutex    refMutex; /* ref count mutex */
-#endif
+    wolfSSL_Ref ref;
 
     union {
         char* ptr; /* der format of key */
@@ -560,10 +557,7 @@ struct WOLFSSL_BIO {
     WOLFSSL_CRYPTO_EX_DATA ex_data;
 #endif
 #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
-    #ifndef SINGLE_THREADED
-    wolfSSL_Mutex    refMutex;  /* ref count mutex */
-    #endif
-    int              refCount;  /* reference count */
+    wolfSSL_Ref  ref;
 #endif
 };
 
@@ -614,10 +608,7 @@ struct WOLFSSL_X509_STORE {
         defined(WOLFSSL_WPAS_SMALL)) && defined(HAVE_CRL)
     WOLFSSL_X509_CRL *crl; /* points to cm->crl */
 #endif
-#ifndef SINGLE_THREADED
-    wolfSSL_Mutex   refMutex;   /* reference count mutex */
-#endif
-    int             refCount;         /* reference count */
+    wolfSSL_Ref     ref;
 };
 
 #define WOLFSSL_ALWAYS_CHECK_SUBJECT 0x1