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);