diff --git a/cyassl/internal.h b/cyassl/internal.h index a50803f76..241783315 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -563,9 +563,33 @@ struct CYASSL_CIPHER { }; +#ifdef SINGLE_THREADED + typedef int CyaSSL_Mutex; +#else /* MULTI_THREADED */ + #ifdef USE_WINDOWS_API + typedef CRITICAL_SECTION CyaSSL_Mutex; + #elif defined(CYASSL_PTHREADS) + typedef pthread_mutex_t CyaSSL_Mutex; + #elif defined(THREADX) + typedef TX_MUTEX CyaSSL_Mutex; + #elif defined(MICRIUM) + typedef OS_MUTEX CyaSSL_Mutex; + #else + #error Need a mutex type in multithreaded mode + #endif /* USE_WINDOWS_API */ +#endif /* SINGLE_THREADED */ + +CYASSL_LOCAL int InitMutex(CyaSSL_Mutex*); +CYASSL_LOCAL int FreeMutex(CyaSSL_Mutex*); +CYASSL_LOCAL int LockMutex(CyaSSL_Mutex*); +CYASSL_LOCAL int UnLockMutex(CyaSSL_Mutex*); + + /* CyaSSL context type */ struct CYASSL_CTX { CYASSL_METHOD* method; + CyaSSL_Mutex countMutex; /* reference count mutex */ + int refCount; /* reference count */ buffer certificate; buffer certChain; /* chain after self, in DER, with leading size for each cert */ @@ -603,7 +627,7 @@ struct CYASSL_CTX { CYASSL_LOCAL -void InitSSL_Ctx(CYASSL_CTX*, CYASSL_METHOD*); +int InitSSL_Ctx(CYASSL_CTX*, CYASSL_METHOD*); CYASSL_LOCAL void FreeSSL_Ctx(CYASSL_CTX*); CYASSL_LOCAL @@ -1218,29 +1242,6 @@ CYASSL_LOCAL timer_d Timer(void); CYASSL_LOCAL word32 LowResTimer(void); -#ifdef SINGLE_THREADED - typedef int CyaSSL_Mutex; -#else /* MULTI_THREADED */ - #ifdef USE_WINDOWS_API - typedef CRITICAL_SECTION CyaSSL_Mutex; - #elif defined(CYASSL_PTHREADS) - typedef pthread_mutex_t CyaSSL_Mutex; - #elif defined(THREADX) - typedef TX_MUTEX CyaSSL_Mutex; - #elif defined(MICRIUM) - typedef OS_MUTEX CyaSSL_Mutex; - #else - #error Need a mutex type in multithreaded mode - #endif /* USE_WINDOWS_API */ -#endif /* SINGLE_THREADED */ - -CYASSL_LOCAL int InitMutex(CyaSSL_Mutex*); -CYASSL_LOCAL int FreeMutex(CyaSSL_Mutex*); -CYASSL_LOCAL int LockMutex(CyaSSL_Mutex*); -CYASSL_LOCAL int UnLockMutex(CyaSSL_Mutex*); - - - #ifdef __cplusplus } /* extern "C" */ diff --git a/src/internal.c b/src/internal.c index 0d0befb48..a58a67749 100644 --- a/src/internal.c +++ b/src/internal.c @@ -322,9 +322,11 @@ void InitSSL_Method(CYASSL_METHOD* method, ProtocolVersion pv) } -void InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) +/* Initialze SSL context, return 0 on success */ +int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) { ctx->method = method; + ctx->refCount = 1; /* so either CTX_free or SSL_free can release */ ctx->certificate.buffer = 0; ctx->certChain.buffer = 0; ctx->privateKey.buffer = 0; @@ -380,6 +382,11 @@ void InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method) ctx->sendVerify = 0; ctx->quietShutdown = 0; + if (InitMutex(&ctx->countMutex) < 0) { + CYASSL_MSG("Mutex error on CTX init"); + return BAD_MUTEX_ERROR; + } + return 0; } @@ -399,12 +406,29 @@ void SSL_CtxResourceFree(CYASSL_CTX* ctx) void FreeSSL_Ctx(CYASSL_CTX* ctx) { - SSL_CtxResourceFree(ctx); - XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX); + int doFree = 0; + + if (LockMutex(&ctx->countMutex) != 0) { + CYASSL_MSG("Couldn't lock count mutex"); + return; + } + ctx->refCount--; + if (ctx->refCount == 0) + doFree = 1; + UnLockMutex(&ctx->countMutex); + + if (doFree) { + CYASSL_MSG("CTX ref count down to 0, doing full free"); + SSL_CtxResourceFree(ctx); + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX); + } + else { + (void)ctx; + CYASSL_MSG("CTX ref count not 0 yet, no free"); + } } - void InitSuites(Suites* suites, ProtocolVersion pv, byte haveDH, byte havePSK, byte haveNTRU, byte haveECDSA, int side) { @@ -638,6 +662,15 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx) ssl->version = ctx->method->version; ssl->suites = ctx->suites; + /* increment CTX reference count */ + if (LockMutex(&ctx->countMutex) != 0) { + CYASSL_MSG("Couldn't lock CTX count mutex"); + return BAD_MUTEX_ERROR; + } + ctx->refCount++; + UnLockMutex(&ctx->countMutex); + + #ifdef HAVE_LIBZ ssl->didStreamInit = 0; #endif @@ -859,6 +892,7 @@ void SSL_ResourceFree(CYASSL* ssl) void FreeSSL(CYASSL* ssl) { + FreeSSL_Ctx(ssl->ctx); /* will decrement and free underyling CTX if 0 */ SSL_ResourceFree(ssl); XFREE(ssl, ssl->heap, DYNAMIC_TYPE_SSL); } diff --git a/src/ssl.c b/src/ssl.c index c39c5017a..5bdb3ef50 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -74,8 +74,13 @@ CYASSL_CTX* CyaSSL_CTX_new(CYASSL_METHOD* method) return ctx; ctx = (CYASSL_CTX*) XMALLOC(sizeof(CYASSL_CTX), 0, DYNAMIC_TYPE_CTX); - if (ctx) - InitSSL_Ctx(ctx, method); + if (ctx) { + if (InitSSL_Ctx(ctx, method) < 0) { + CYASSL_MSG("Init CTX failed"); + CyaSSL_CTX_free(ctx); + ctx = NULL; + } + } CYASSL_LEAVE("CYASSL_CTX_new", 0); return ctx; @@ -453,7 +458,7 @@ int AddCA(CYASSL_CTX* ctx, buffer der, int force) } else { CYASSL_MSG(" CA Mutex Lock failed"); - ret = -1; + ret = BAD_MUTEX_ERROR; FreeSigners(signer, ctx->heap); } }