From cd5178651242a472071835251119508d0be473be Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Mon, 16 Feb 2026 18:48:51 +0100 Subject: [PATCH 1/3] Fix PKCS11 object leak in Pkcs11ECDH --- wolfcrypt/src/wc_pkcs11.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index 8ad4049804d..37b77faead9 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -2994,6 +2994,7 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) { int ret = 0; int sessionKey = 0; + int destroyPrivKey = 0; unsigned char* point = NULL; word32 pointLen; CK_RV rv; @@ -3038,6 +3039,11 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) else { ret = Pkcs11FindEccKey(&privateKey, CKO_PRIVATE_KEY, session, info->pk.ecdh.public_key, CKA_DERIVE); + if (ret == 0) { + /* Key found by public key match is likely ephemeral (e.g. from + * Pkcs11EcKeyGen for ECDHE), clean it up after use. */ + destroyPrivKey = 1; + } } } if (ret == 0) { @@ -3085,8 +3091,23 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) info->pk.ecdh.outlen); } - if (sessionKey) + if (secret != CK_INVALID_HANDLE) + session->func->C_DestroyObject(session->handle, secret); + + if (sessionKey) { session->func->C_DestroyObject(session->handle, privateKey); + } + else if (destroyPrivKey && privateKey != NULL_PTR) { + /* Only destroy if the key is a non-persistent session object */ + CK_BBOOL isToken = CK_FALSE; + CK_ATTRIBUTE tokenTmpl[] = { + { CKA_TOKEN, &isToken, sizeof(isToken) }, + }; + if (session->func->C_GetAttributeValue(session->handle, privateKey, + tokenTmpl, 1) == CKR_OK && isToken == CK_FALSE) { + session->func->C_DestroyObject(session->handle, privateKey); + } + } if (point != NULL) XFREE(point, info->pk.ecdh.public_key->heap, DYNAMIC_TYPE_ECC_BUFFER); From 1707acee36cfd780045d1303583b4b8373ab374a Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Tue, 17 Feb 2026 16:42:13 +0100 Subject: [PATCH 2/3] Bind PKCS11 ECC key duration to ECC object --- wolfcrypt/src/ecc.c | 7 +++++ wolfcrypt/src/wc_pkcs11.c | 59 ++++++++++++++++++++++-------------- wolfssl/wolfcrypt/settings.h | 3 ++ 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index d4a23f30cab..4aa095de961 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -7891,6 +7891,13 @@ int wc_ecc_free(ecc_key* key) return 0; } +#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) + if (key->devId != INVALID_DEVID) { + wc_CryptoCb_Free(key->devId, WC_ALGO_TYPE_PK, + WC_PK_TYPE_EC_KEYGEN, key); + } +#endif + #if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \ defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \ defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT) diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index 37b77faead9..9b428ab692f 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -2923,8 +2923,12 @@ static int Pkcs11EcKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) if (pubKey != NULL_PTR) session->func->C_DestroyObject(session->handle, pubKey); - if (ret != 0 && privKey != NULL_PTR) + if (ret == 0 && privKey != NULL_PTR) { + key->devCtx = (void*)(uintptr_t)privKey; + } + else if (ret != 0 && privKey != NULL_PTR) { session->func->C_DestroyObject(session->handle, privKey); + } return ret; } @@ -2994,7 +2998,6 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) { int ret = 0; int sessionKey = 0; - int destroyPrivKey = 0; unsigned char* point = NULL; word32 pointLen; CK_RV rv; @@ -3021,7 +3024,11 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) if (ret == 0) { WOLFSSL_MSG("PKCS#11: EC Key Derivation Operation"); - if ((sessionKey = !mp_iszero( + if (info->pk.ecdh.private_key->devCtx != NULL) { + privateKey = (CK_OBJECT_HANDLE)(uintptr_t) + info->pk.ecdh.private_key->devCtx; + } + else if ((sessionKey = !mp_iszero( wc_ecc_key_get_priv(info->pk.ecdh.private_key)))) ret = Pkcs11CreateEccPrivateKey(&privateKey, session, info->pk.ecdh.private_key, CKA_DERIVE); @@ -3039,11 +3046,6 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) else { ret = Pkcs11FindEccKey(&privateKey, CKO_PRIVATE_KEY, session, info->pk.ecdh.public_key, CKA_DERIVE); - if (ret == 0) { - /* Key found by public key match is likely ephemeral (e.g. from - * Pkcs11EcKeyGen for ECDHE), clean it up after use. */ - destroyPrivKey = 1; - } } } if (ret == 0) { @@ -3094,20 +3096,8 @@ static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) if (secret != CK_INVALID_HANDLE) session->func->C_DestroyObject(session->handle, secret); - if (sessionKey) { + if (sessionKey && privateKey != NULL_PTR) session->func->C_DestroyObject(session->handle, privateKey); - } - else if (destroyPrivKey && privateKey != NULL_PTR) { - /* Only destroy if the key is a non-persistent session object */ - CK_BBOOL isToken = CK_FALSE; - CK_ATTRIBUTE tokenTmpl[] = { - { CKA_TOKEN, &isToken, sizeof(isToken) }, - }; - if (session->func->C_GetAttributeValue(session->handle, privateKey, - tokenTmpl, 1) == CKR_OK && isToken == CK_FALSE) { - session->func->C_DestroyObject(session->handle, privateKey); - } - } if (point != NULL) XFREE(point, info->pk.ecdh.public_key->heap, DYNAMIC_TYPE_ECC_BUFFER); @@ -3335,7 +3325,11 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) if (ret == 0) { WOLFSSL_MSG("PKCS#11: EC Signing Operation"); - if ((sessionKey = !mp_iszero( + if (info->pk.eccsign.key->devCtx != NULL) { + privateKey = (CK_OBJECT_HANDLE)(uintptr_t) + info->pk.eccsign.key->devCtx; + } + else if ((sessionKey = !mp_iszero( wc_ecc_key_get_priv(info->pk.eccsign.key)))) ret = Pkcs11CreateEccPrivateKey(&privateKey, session, info->pk.eccsign.key, CKA_SIGN); @@ -3399,7 +3393,7 @@ static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) sz); } - if (sessionKey) + if (sessionKey && privateKey != NULL_PTR) session->func->C_DestroyObject(session->handle, privateKey); return ret; @@ -4750,6 +4744,25 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) else ret = NOT_COMPILED_IN; } +#ifdef WOLF_CRYPTO_CB_FREE + else if (info->algo_type == WC_ALGO_TYPE_FREE) { + #ifdef HAVE_ECC + if (info->free.algo == WC_ALGO_TYPE_PK && + info->free.type == WC_PK_TYPE_EC_KEYGEN) { + ecc_key* key = (ecc_key*)info->free.obj; + if (key != NULL && key->devCtx != NULL) { + if (token->handle != NULL_PTR) { + CK_OBJECT_HANDLE handle = + (CK_OBJECT_HANDLE)(uintptr_t)key->devCtx; + token->func->C_DestroyObject(token->handle, handle); + } + key->devCtx = NULL; + } + ret = 0; + } + #endif + } +#endif /* WOLF_CRYPTO_CB_FREE */ return ret; } diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 49301a4d3af..f37ecab4dc8 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -4962,6 +4962,9 @@ extern void uITRON4_free(void *p) ; " (WC_TEST_NO_CRYPTOCB_SW_TEST)" \ " requires WOLF_CRYPTO_CB" #endif +#if defined(HAVE_PKCS11) && !defined(WOLF_CRYPTO_CB_FREE) + #define WOLF_CRYPTO_CB_FREE +#endif #if (defined(WOLF_CRYPTO_CB_COPY) || defined(WOLF_CRYPTO_CB_FREE)) && \ !defined(WOLF_CRYPTO_CB) #error "Crypto callback utilities" \ From 817523df72a539bdf14ab819b2442cbfa7af90a0 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Wed, 18 Feb 2026 03:52:47 +0100 Subject: [PATCH 3/3] Adjust execution flow --- wolfcrypt/src/wc_pkcs11.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/wolfcrypt/src/wc_pkcs11.c b/wolfcrypt/src/wc_pkcs11.c index 9b428ab692f..de9d507ca5a 100644 --- a/wolfcrypt/src/wc_pkcs11.c +++ b/wolfcrypt/src/wc_pkcs11.c @@ -4741,28 +4741,27 @@ int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) ret = NOT_COMPILED_IN; #endif } - else - ret = NOT_COMPILED_IN; - } -#ifdef WOLF_CRYPTO_CB_FREE - else if (info->algo_type == WC_ALGO_TYPE_FREE) { + else if (info->algo_type == WC_ALGO_TYPE_FREE) { #ifdef HAVE_ECC - if (info->free.algo == WC_ALGO_TYPE_PK && - info->free.type == WC_PK_TYPE_EC_KEYGEN) { - ecc_key* key = (ecc_key*)info->free.obj; - if (key != NULL && key->devCtx != NULL) { - if (token->handle != NULL_PTR) { - CK_OBJECT_HANDLE handle = - (CK_OBJECT_HANDLE)(uintptr_t)key->devCtx; - token->func->C_DestroyObject(token->handle, handle); + if (info->free.algo == WC_ALGO_TYPE_PK && + info->free.type == WC_PK_TYPE_EC_KEYGEN) { + ecc_key* key = (ecc_key*)info->free.obj; + if (key != NULL && key->devCtx != NULL) { + if (token->handle != NULL_PTR) { + CK_OBJECT_HANDLE handle = + (CK_OBJECT_HANDLE)(uintptr_t)key->devCtx; + token->func->C_DestroyObject(token->handle, handle); + } + key->devCtx = NULL; } - key->devCtx = NULL; + ret = 0; } - ret = 0; - } #endif + } + else { + ret = NOT_COMPILED_IN; + } } -#endif /* WOLF_CRYPTO_CB_FREE */ return ret; }