diff --git a/src/ssl.c b/src/ssl.c index a79142b27..ce0ca2361 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -38862,6 +38862,15 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId) InitwolfSSL_ECKey(external); + external->refCount = 1; +#ifndef SINGLE_THREADED + if (wc_InitMutex(&external->refMutex) != 0) { + WOLFSSL_MSG("wc_InitMutex WOLFSSL_EC_KEY failure"); + XFREE(external, heap, DYNAMIC_TYPE_ECC); + return NULL; + } +#endif + external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); if (external->internal == NULL) { @@ -38909,10 +38918,32 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) { + int doFree = 0; + WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); if (key != NULL) { void* heap = key->heap; + + #ifndef SINGLE_THREADED + if (wc_LockMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Could not lock EC_KEY mutex"); + } + #endif + + /* only free if all references to it are done */ + key->refCount--; + if (key->refCount == 0) { + doFree = 1; + } + #ifndef SINGLE_THREADED + wc_UnLockMutex(&key->refMutex); + #endif + + if (doFree == 0) { + return; + } + if (key->internal != NULL) { wc_ecc_free((ecc_key*)key->internal); XFREE(key->internal, heap, DYNAMIC_TYPE_ECC); @@ -38928,6 +38959,26 @@ void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) } } +/* Increments ref count of WOLFSSL_EC_KEY. + * Return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on error */ +int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key) +{ + if (key) { + #ifndef SINGLE_THREADED + if (wc_LockMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock EC_KEY mutex"); + } + #endif + key->refCount++; + #ifndef SINGLE_THREADED + wc_UnLockMutex(&key->refMutex); + #endif + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + /* set the group in WOLFSSL_EC_KEY and return WOLFSSL_SUCCESS on success */ int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) { diff --git a/tests/api.c b/tests/api.c index 06535e3aa..fe844767f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -42909,6 +42909,21 @@ static void test_wolfSSL_EC_KEY_dup(void) wolfSSL_EC_KEY_free(ecKey); wolfSSL_EC_KEY_free(dupKey); + /* Test EC_KEY_up_ref */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(ecKey), WOLFSSL_SUCCESS); + /* reference count doesn't follow duplicate */ + AssertNotNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +1 */ + AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +2 */ + wolfSSL_EC_KEY_free(dupKey); /* 3 */ + wolfSSL_EC_KEY_free(dupKey); /* 2 */ + wolfSSL_EC_KEY_free(dupKey); /* 1, free */ + wolfSSL_EC_KEY_free(ecKey); /* 2 */ + wolfSSL_EC_KEY_free(ecKey); /* 1, free */ + printf(resultFmt, passed); #endif } diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 47ab4defb..fa0ac7a6b 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -119,6 +119,10 @@ struct WOLFSSL_EC_KEY { char form; /* Either POINT_CONVERSION_UNCOMPRESSED or * POINT_CONVERSION_COMPRESSED */ word16 pkcs8HeaderSz; +#ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif + int refCount; /* reference count */ /* option bits */ byte inSet:1; /* internal set from external ? */ @@ -138,6 +142,8 @@ size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r,size_t nitems); WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src); +WOLFSSL_API +int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key); WOLFSSL_API int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve, @@ -307,6 +313,7 @@ typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; #define EC_KEY_new wolfSSL_EC_KEY_new #define EC_KEY_free wolfSSL_EC_KEY_free #define EC_KEY_dup wolfSSL_EC_KEY_dup +#define EC_KEY_up_ref wolfSSL_EC_KEY_up_ref #define EC_KEY_get0_public_key wolfSSL_EC_KEY_get0_public_key #define EC_KEY_get0_group wolfSSL_EC_KEY_get0_group #define EC_KEY_set_private_key wolfSSL_EC_KEY_set_private_key