From ef777ce646a729d5e8e03656956e5886e16e2748 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Thu, 4 Jun 2026 22:03:54 -0400 Subject: [PATCH 1/3] Expose wc_CryptoCb_GetDevice and add CryptoCb API test coverage --- tests/api.c | 34 ++++++++++++++++++++++++++++++---- wolfcrypt/src/cryptocb.c | 7 +------ wolfssl/version.h | 4 ++-- wolfssl/wolfcrypt/cryptocb.h | 7 +++++++ 4 files changed, 40 insertions(+), 12 deletions(-) diff --git a/tests/api.c b/tests/api.c index 9676c470a3..3247e4cdc1 100644 --- a/tests/api.c +++ b/tests/api.c @@ -29223,13 +29223,39 @@ static int test_wc_CryptoCb(void) (!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \ !defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) && \ !defined(WOLF_CRYPTO_CB_ONLY_SHA512)) +#if defined(HAVE_IO_TESTS_DEPENDENCIES) && \ + (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) + int tlsVer; +#endif /* TODO: Add crypto callback API tests */ -#ifdef HAVE_IO_TESTS_DEPENDENCIES - #if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) - int tlsVer; - #endif + /* Test wc_CryptoCb_GetDevice() lookup behavior. */ + { + int getDevId = 1234; + int getDevCtx = 0; + CryptoCb* dev = NULL; + /* Unregistered devId is not found. */ + ExpectNull(wc_CryptoCb_GetDevice(getDevId)); + + /* After registering, the device is found with matching fields. */ + ExpectIntEQ(wc_CryptoCb_RegisterDevice(getDevId, NULL, &getDevCtx), 0); + ExpectNotNull(dev = wc_CryptoCb_GetDevice(getDevId)); + if (dev != NULL) { + ExpectIntEQ(dev->devId, getDevId); + ExpectNull(dev->cb); + ExpectPtrEq(dev->ctx, &getDevCtx); + } + + /* A different, unregistered devId is still not found. */ + ExpectNull(wc_CryptoCb_GetDevice(getDevId + 1)); + + /* After unregistering, the device is no longer found. */ + wc_CryptoCb_UnRegisterDevice(getDevId); + ExpectNull(wc_CryptoCb_GetDevice(getDevId)); + } + +#ifdef HAVE_IO_TESTS_DEPENDENCIES #ifndef NO_RSA for (tlsVer = WOLFSSL_SSLV3; tlsVer <= WOLFSSL_DTLSV1; tlsVer++) { ExpectIntEQ(test_wc_CryptoCb_TLS(tlsVer, diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 3218e6efb2..c171be8397 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -84,11 +84,6 @@ Crypto Callback Build Options: #define MAX_CRYPTO_DEVID_CALLBACKS 8 #endif -typedef struct CryptoCb { - int devId; - CryptoDevCallbackFunc cb; - void* ctx; -} CryptoCb; static WC_THREADSHARED CryptoCb gCryptoDev[MAX_CRYPTO_DEVID_CALLBACKS]; #ifdef WOLF_CRYPTO_CB_FIND @@ -355,7 +350,7 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info) /* Search through listed devices and return the first matching device ID * found. */ -static CryptoCb* wc_CryptoCb_GetDevice(int devId) +CryptoCb* wc_CryptoCb_GetDevice(int devId) { int i; for (i = 0; i < MAX_CRYPTO_DEVID_CALLBACKS; i++) { diff --git a/wolfssl/version.h b/wolfssl/version.h index 3f8a539dc8..a93c997f46 100644 --- a/wolfssl/version.h +++ b/wolfssl/version.h @@ -28,8 +28,8 @@ extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "5.9.1" -#define LIBWOLFSSL_VERSION_HEX 0x05009001 +#define LIBWOLFSSL_VERSION_STRING "5.8.4" +#define LIBWOLFSSL_VERSION_HEX 0x05008004 #ifdef __cplusplus } diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index b0aaad2f37..34b30e6c69 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -672,12 +672,19 @@ typedef struct wc_CryptoInfo { typedef int (*CryptoDevCallbackFunc)(int devId, struct wc_CryptoInfo* info, void* ctx); +typedef struct CryptoCb { + int devId; + CryptoDevCallbackFunc cb; + void* ctx; +} CryptoCb; + WOLFSSL_LOCAL void wc_CryptoCb_Init(void); WOLFSSL_LOCAL void wc_CryptoCb_Cleanup(void); WOLFSSL_LOCAL int wc_CryptoCb_GetDevIdAtIndex(int startIdx); WOLFSSL_API int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); WOLFSSL_API void wc_CryptoCb_UnRegisterDevice(int devId); WOLFSSL_API int wc_CryptoCb_DefaultDevID(void); +WOLFSSL_API CryptoCb* wc_CryptoCb_GetDevice(int devId); #ifdef WOLF_CRYPTO_CB_FIND typedef int (*CryptoDevCallbackFind)(int devId, int algoType); From 451eaf9cba6efb7b5dd131a075280354e733c463 Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Fri, 5 Jun 2026 14:35:21 -0400 Subject: [PATCH 2/3] Error out when trying to register a a cryptocb with an existing devId --- tests/api.c | 48 +++++++++++++++++++++++++++++++++++++--- wolfcrypt/src/cryptocb.c | 10 +++++---- wolfssl/version.h | 4 ++-- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/tests/api.c b/tests/api.c index 3247e4cdc1..2ebc129a2c 100644 --- a/tests/api.c +++ b/tests/api.c @@ -29227,13 +29227,14 @@ static int test_wc_CryptoCb(void) (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) int tlsVer; #endif - /* TODO: Add crypto callback API tests */ - - /* Test wc_CryptoCb_GetDevice() lookup behavior. */ + /* Exercise the exposed CryptoCb device-management API: + * wc_CryptoCb_RegisterDevice / UnRegisterDevice / GetDevice / + * DefaultDevID (and InfoString when DEBUG_CRYPTOCB is enabled). */ { int getDevId = 1234; int getDevCtx = 0; CryptoCb* dev = NULL; + int i, n, rc; /* Unregistered devId is not found. */ ExpectNull(wc_CryptoCb_GetDevice(getDevId)); @@ -29250,9 +29251,50 @@ static int test_wc_CryptoCb(void) /* A different, unregistered devId is still not found. */ ExpectNull(wc_CryptoCb_GetDevice(getDevId + 1)); + /* Re-registering an already-registered devId is rejected. */ + ExpectIntEQ(wc_CryptoCb_RegisterDevice(getDevId, NULL, &getDevCtx), + WC_NO_ERR_TRACE(ALREADY_E)); + + /* wc_CryptoCb_DefaultDevID behavior depends on the build config. */ + #ifdef WC_NO_DEFAULT_DEVID + ExpectIntEQ(wc_CryptoCb_DefaultDevID(), INVALID_DEVID); + #elif !defined(WOLFSSL_CAAM_DEVID) && !defined(HAVE_ARIA) && \ + !defined(WC_USE_DEVID) + /* "first available" mode: a device is registered, so one is returned. */ + ExpectIntNE(wc_CryptoCb_DefaultDevID(), INVALID_DEVID); + #endif + /* After unregistering, the device is no longer found. */ wc_CryptoCb_UnRegisterDevice(getDevId); ExpectNull(wc_CryptoCb_GetDevice(getDevId)); + + /* Unregistering is a harmless no-op for unknown or invalid devIds. */ + wc_CryptoCb_UnRegisterDevice(getDevId); /* already removed */ + wc_CryptoCb_UnRegisterDevice(INVALID_DEVID); /* never a real devId */ + ExpectNull(wc_CryptoCb_GetDevice(getDevId)); + + /* The device table is finite: once full, registration returns + * BUFFER_E. Register unique devIds until that happens, then clean up. + * The cap (256) just guards against an unexpectedly large table. */ + rc = 0; + for (i = 0; rc == 0 && i < 256; i++) { + rc = wc_CryptoCb_RegisterDevice(0x5000 + i, NULL, NULL); + } + ExpectIntEQ(rc, WC_NO_ERR_TRACE(BUFFER_E)); + /* Every id except the final failed attempt registered; unregister them. */ + for (n = 0; n + 1 < i; n++) { + wc_CryptoCb_UnRegisterDevice(0x5000 + n); + } + + #ifdef DEBUG_CRYPTOCB + /* wc_CryptoCb_InfoString smoke test: must not dereference bad memory. */ + { + wc_CryptoInfo info; + XMEMSET(&info, 0, sizeof(info)); + info.algo_type = WC_ALGO_TYPE_NONE; + wc_CryptoCb_InfoString(&info); + } + #endif } #ifdef HAVE_IO_TESTS_DEPENDENCIES diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index c171be8397..5b4cdf9578 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -446,12 +446,14 @@ void wc_CryptoCb_SetDeviceFindCb(CryptoDevCallbackFind cb) int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx) { int rc = 0; + CryptoCb* dev; - /* find existing or new */ - CryptoCb* dev = wc_CryptoCb_GetDevice(devId); - if (dev == NULL) - dev = wc_CryptoCb_GetDevice(INVALID_DEVID); + /* Reject re-registration of an already-registered device ID. */ + if (wc_CryptoCb_GetDevice(devId) != NULL) + return ALREADY_E; + /* find a free slot */ + dev = wc_CryptoCb_GetDevice(INVALID_DEVID); if (dev == NULL) return BUFFER_E; /* out of devices */ diff --git a/wolfssl/version.h b/wolfssl/version.h index a93c997f46..3f8a539dc8 100644 --- a/wolfssl/version.h +++ b/wolfssl/version.h @@ -28,8 +28,8 @@ extern "C" { #endif -#define LIBWOLFSSL_VERSION_STRING "5.8.4" -#define LIBWOLFSSL_VERSION_HEX 0x05008004 +#define LIBWOLFSSL_VERSION_STRING "5.9.1" +#define LIBWOLFSSL_VERSION_HEX 0x05009001 #ifdef __cplusplus } From c0ec8f39b219d0f5af005457fff5e2e0915a8a4e Mon Sep 17 00:00:00 2001 From: Alex Lanzano Date: Wed, 10 Jun 2026 15:02:22 -0400 Subject: [PATCH 3/3] Address review: narrow CryptoCb introspection to a boolean check - Replace public wc_CryptoCb_GetDevice() with wc_CryptoCb_IsDeviceRegistered() returns 1 or 0. keep the CryptoCb struct and GetDevice private. - Reject RegisterDevice(INVALID_DEVID) with BAD_FUNC_ARG instead of ALREADY_E. - Document the new API and the ALREADY_E/BAD_FUNC_ARG returns. - Fix table-full test to not leak when MAX_CRYPTO_DEVID_CALLBACKS >= 256. --- doc/dox_comments/header_files/cryptocb.h | 30 +++++++++++++++++ tests/api.c | 42 ++++++++++++------------ wolfcrypt/src/cryptocb.c | 23 ++++++++++--- wolfssl/wolfcrypt/cryptocb.h | 11 +++---- 4 files changed, 75 insertions(+), 31 deletions(-) diff --git a/doc/dox_comments/header_files/cryptocb.h b/doc/dox_comments/header_files/cryptocb.h index e236e1271f..2dbd4da572 100644 --- a/doc/dox_comments/header_files/cryptocb.h +++ b/doc/dox_comments/header_files/cryptocb.h @@ -13,6 +13,10 @@ \return CRYPTOCB_UNAVAILABLE to fallback to using software crypto \return 0 for success + \return ALREADY_E if devId is already registered. A devId must be + un-registered with wc_CryptoCb_UnRegisterDevice before it can be + registered again; re-registering an active devId is not an in-place update. + \return BAD_FUNC_ARG if devId is INVALID_DEVID (-2) \return negative value for failure \param devId any unique value, not -2 (INVALID_DEVID) @@ -98,6 +102,32 @@ */ int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); +/*! + \ingroup CryptoCb + + \brief This function reports whether a crypto callback device identifier + (devID) is currently registered. It is useful for checking registration + state before calling wc_CryptoCb_RegisterDevice, which now rejects an + already-registered devID with ALREADY_E. + + \return 1 if the device ID is registered + \return 0 if the device ID is not registered, or if devId is + INVALID_DEVID (-2) + + \param devId the device identifier to query + + _Example_ + \code + if (!wc_CryptoCb_IsDeviceRegistered(devId)) { + wc_CryptoCb_RegisterDevice(devId, myCryptoCb_Func, &myCtx); + } + \endcode + + \sa wc_CryptoCb_RegisterDevice + \sa wc_CryptoCb_UnRegisterDevice +*/ +int wc_CryptoCb_IsDeviceRegistered(int devId); + /*! \ingroup CryptoCb diff --git a/tests/api.c b/tests/api.c index 2ebc129a2c..79be1341e8 100644 --- a/tests/api.c +++ b/tests/api.c @@ -29228,28 +29228,27 @@ static int test_wc_CryptoCb(void) int tlsVer; #endif /* Exercise the exposed CryptoCb device-management API: - * wc_CryptoCb_RegisterDevice / UnRegisterDevice / GetDevice / + * wc_CryptoCb_RegisterDevice / UnRegisterDevice / IsDeviceRegistered / * DefaultDevID (and InfoString when DEBUG_CRYPTOCB is enabled). */ { int getDevId = 1234; int getDevCtx = 0; - CryptoCb* dev = NULL; int i, n, rc; - /* Unregistered devId is not found. */ - ExpectNull(wc_CryptoCb_GetDevice(getDevId)); + /* Unregistered devId is not reported as registered. */ + ExpectIntEQ(wc_CryptoCb_IsDeviceRegistered(getDevId), 0); - /* After registering, the device is found with matching fields. */ + /* Registering with INVALID_DEVID is rejected. */ + ExpectIntEQ(wc_CryptoCb_RegisterDevice(INVALID_DEVID, NULL, &getDevCtx), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_CryptoCb_IsDeviceRegistered(INVALID_DEVID), 0); + + /* After registering, the device is reported registered. */ ExpectIntEQ(wc_CryptoCb_RegisterDevice(getDevId, NULL, &getDevCtx), 0); - ExpectNotNull(dev = wc_CryptoCb_GetDevice(getDevId)); - if (dev != NULL) { - ExpectIntEQ(dev->devId, getDevId); - ExpectNull(dev->cb); - ExpectPtrEq(dev->ctx, &getDevCtx); - } + ExpectIntEQ(wc_CryptoCb_IsDeviceRegistered(getDevId), 1); - /* A different, unregistered devId is still not found. */ - ExpectNull(wc_CryptoCb_GetDevice(getDevId + 1)); + /* A different, unregistered devId is still not reported registered. */ + ExpectIntEQ(wc_CryptoCb_IsDeviceRegistered(getDevId + 1), 0); /* Re-registering an already-registered devId is rejected. */ ExpectIntEQ(wc_CryptoCb_RegisterDevice(getDevId, NULL, &getDevCtx), @@ -29264,25 +29263,26 @@ static int test_wc_CryptoCb(void) ExpectIntNE(wc_CryptoCb_DefaultDevID(), INVALID_DEVID); #endif - /* After unregistering, the device is no longer found. */ + /* After unregistering, the device is no longer registered. */ wc_CryptoCb_UnRegisterDevice(getDevId); - ExpectNull(wc_CryptoCb_GetDevice(getDevId)); + ExpectIntEQ(wc_CryptoCb_IsDeviceRegistered(getDevId), 0); /* Unregistering is a harmless no-op for unknown or invalid devIds. */ wc_CryptoCb_UnRegisterDevice(getDevId); /* already removed */ wc_CryptoCb_UnRegisterDevice(INVALID_DEVID); /* never a real devId */ - ExpectNull(wc_CryptoCb_GetDevice(getDevId)); + ExpectIntEQ(wc_CryptoCb_IsDeviceRegistered(getDevId), 0); /* The device table is finite: once full, registration returns - * BUFFER_E. Register unique devIds until that happens, then clean up. - * The cap (256) just guards against an unexpectedly large table. */ + * BUFFER_E. Registering MAX_CRYPTO_DEVID_CALLBACKS + 1 unique devIds is + * guaranteed to fill the table and hit BUFFER_E regardless of how many + * slots were already in use. Then unregister every id we tried + * (UnRegister is a no-op for the final failed attempt). */ rc = 0; - for (i = 0; rc == 0 && i < 256; i++) { + for (i = 0; rc == 0 && i <= MAX_CRYPTO_DEVID_CALLBACKS; i++) { rc = wc_CryptoCb_RegisterDevice(0x5000 + i, NULL, NULL); } ExpectIntEQ(rc, WC_NO_ERR_TRACE(BUFFER_E)); - /* Every id except the final failed attempt registered; unregister them. */ - for (n = 0; n + 1 < i; n++) { + for (n = 0; n < i; n++) { wc_CryptoCb_UnRegisterDevice(0x5000 + n); } diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 5b4cdf9578..7fdd6227db 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -80,10 +80,12 @@ Crypto Callback Build Options: #include #endif /* TODO: Consider linked list with mutex */ -#ifndef MAX_CRYPTO_DEVID_CALLBACKS -#define MAX_CRYPTO_DEVID_CALLBACKS 8 -#endif +typedef struct CryptoCb { + int devId; + CryptoDevCallbackFunc cb; + void* ctx; +} CryptoCb; static WC_THREADSHARED CryptoCb gCryptoDev[MAX_CRYPTO_DEVID_CALLBACKS]; #ifdef WOLF_CRYPTO_CB_FIND @@ -350,7 +352,7 @@ void wc_CryptoCb_InfoString(wc_CryptoInfo* info) /* Search through listed devices and return the first matching device ID * found. */ -CryptoCb* wc_CryptoCb_GetDevice(int devId) +static CryptoCb* wc_CryptoCb_GetDevice(int devId) { int i; for (i = 0; i < MAX_CRYPTO_DEVID_CALLBACKS; i++) { @@ -360,6 +362,15 @@ CryptoCb* wc_CryptoCb_GetDevice(int devId) return NULL; } +/* Returns 1 if the given device ID is currently registered, 0 otherwise. + * INVALID_DEVID marks free table slots, so it is never reported registered. */ +int wc_CryptoCb_IsDeviceRegistered(int devId) +{ + if (devId == INVALID_DEVID) + return 0; + return wc_CryptoCb_GetDevice(devId) != NULL; +} + /* Filters through find callback set when trying to get the device, * returns the device found on success and null if not found. */ @@ -448,6 +459,10 @@ int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx) int rc = 0; CryptoCb* dev; + /* INVALID_DEVID marks a free slot and cannot be registered as a device. */ + if (devId == INVALID_DEVID) + return BAD_FUNC_ARG; + /* Reject re-registration of an already-registered device ID. */ if (wc_CryptoCb_GetDevice(devId) != NULL) return ALREADY_E; diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 34b30e6c69..a06afa278a 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -672,11 +672,10 @@ typedef struct wc_CryptoInfo { typedef int (*CryptoDevCallbackFunc)(int devId, struct wc_CryptoInfo* info, void* ctx); -typedef struct CryptoCb { - int devId; - CryptoDevCallbackFunc cb; - void* ctx; -} CryptoCb; +/* Maximum number of crypto callback devices that can be registered. */ +#ifndef MAX_CRYPTO_DEVID_CALLBACKS +#define MAX_CRYPTO_DEVID_CALLBACKS 8 +#endif WOLFSSL_LOCAL void wc_CryptoCb_Init(void); WOLFSSL_LOCAL void wc_CryptoCb_Cleanup(void); @@ -684,7 +683,7 @@ WOLFSSL_LOCAL int wc_CryptoCb_GetDevIdAtIndex(int startIdx); WOLFSSL_API int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); WOLFSSL_API void wc_CryptoCb_UnRegisterDevice(int devId); WOLFSSL_API int wc_CryptoCb_DefaultDevID(void); -WOLFSSL_API CryptoCb* wc_CryptoCb_GetDevice(int devId); +WOLFSSL_API int wc_CryptoCb_IsDeviceRegistered(int devId); #ifdef WOLF_CRYPTO_CB_FIND typedef int (*CryptoDevCallbackFind)(int devId, int algoType);