-
Notifications
You must be signed in to change notification settings - Fork 921
Fix Crash when using Sha224 Callback with MAX32666 #9712
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Fix Crash when using Sha224 Callback with MAX32666 #9712
Conversation
…k functions, fix sha224 crashing when using callbacks for MAX32666 due to unitialized struct.
|
Jenkins retest this please Jenkins disconnect from server during PRB-generic-config-parser |
|
Jenkins retest this please |
wolfcrypt/src/port/maxim/max3266x.c
Outdated
|
|
||
| #include <stdint.h> | ||
| #include <stdarg.h> | ||
| #include <stdio.h> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the stdio include really needed here?
|
|
||
| /* Handle case where src has no data */ | ||
| if (src->msg == NULL || src->size == 0) { | ||
| /* Free dst if it has different data, then zero it */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment says "free then zero" but it looks like it conditionally frees here if not null and pointers are not the same, or it zeros if NULL or the pointers are the same.
| return; /* Hash Struct is Null already, dont edit potentially */ | ||
| /* undefined memory */ | ||
| /* Securely zero the buffer before freeing */ | ||
| if (hash->msg != NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove the null check on hash before accessing hash->msg?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #define WOLF_CRYPTO_CB_COPY /* Enable copy callback for deep copy */ | ||
| #define WOLF_CRYPTO_CB_FREE /* Enable free callback for proper cleanup */ |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defining WOLF_CRYPTO_CB_COPY and WOLF_CRYPTO_CB_FREE here changes behavior of the generic hash Copy/Free APIs: when enabled, wc_Sha224Copy/wc_Sha256Copy and wc_Sha224Free/wc_Sha256Free will call the CryptoCb copy/free hooks first and will return early when the callback reports success. The MAX3266X callback implementation added in wolfcrypt/src/port/maxim/max3266x.c does not replicate the normal deep-copy/free logic (e.g., WOLFSSL_SMALL_STACK_CACHE allocates a fresh dst->W in wc_Sha224Copy at wolfcrypt/src/sha256.c:2605-2612 and wc_Sha256Copy at 2762-2769; WOLFSSL_HASH_KEEP deep-copies msg at 2636-2644 / 2800-2807; frees also release these). As a result, enabling these macros for MAX3266X can introduce shared pointers, double-frees, and leaks. Consider not enabling these macros globally for the port; instead, add MAX3266X_SHA_CB-specific deep-copy/free handling inside the SHA224/SHA* Copy/Free implementations (like SHA256 already does for mxcCtx), or fully implement the same semantics in the callback.
| #define WOLF_CRYPTO_CB_COPY /* Enable copy callback for deep copy */ | |
| #define WOLF_CRYPTO_CB_FREE /* Enable free callback for proper cleanup */ | |
| /* | |
| * Do NOT define WOLF_CRYPTO_CB_COPY / WOLF_CRYPTO_CB_FREE here. | |
| * Those macros change generic hash Copy/Free behavior and require | |
| * callback implementations that fully mirror the normal deep-copy/free | |
| * semantics. They must only be enabled in code that provides that logic. | |
| */ |
| /* Software copy */ | ||
| savedDevId = *srcDevId; | ||
| XMEMCPY(info->copy.dst, info->copy.src, copySize); | ||
| *dstDevId = savedDevId; | ||
| /* Hardware copy - handles shallow copy from XMEMCPY */ | ||
| ret = wc_MXC_TPU_SHA_Copy(srcMxcCtx, dstMxcCtx); |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The WC_ALGO_TYPE_COPY handler does a raw XMEMCPY of the entire hash object and then only deep-copies the mxcCtx buffer. When WOLF_CRYPTO_CB_COPY is enabled, the generic wc_Sha224Copy/wc_Sha256Copy functions will return early after this callback and will skip their usual deep-copy steps (e.g., allocating a new dst->W under WOLFSSL_SMALL_STACK_CACHE and deep-copying msg under WOLFSSL_HASH_KEEP in wolfcrypt/src/sha256.c:2605-2612, 2636-2644, 2762-2769, 2800-2807). This can leave dst sharing pointers with src, leading to double-free/use-after-free when both contexts are freed. Suggest either (a) have the callback return CRYPTOCB_UNAVAILABLE after handling only MAX3266X-specific state so the normal copy path runs, plus add missing MAX3266X_SHA_CB mxcCtx copy into wc_Sha224Copy, or (b) update the callback to fully mirror the standard copy semantics for each supported hash type (W, msg, async ctx, etc.).
| /* Software copy */ | |
| savedDevId = *srcDevId; | |
| XMEMCPY(info->copy.dst, info->copy.src, copySize); | |
| *dstDevId = savedDevId; | |
| /* Hardware copy - handles shallow copy from XMEMCPY */ | |
| ret = wc_MXC_TPU_SHA_Copy(srcMxcCtx, dstMxcCtx); | |
| /* Hardware copy of MAX3266X-specific SHA context. | |
| * Return CRYPTOCB_UNAVAILABLE so core performs full | |
| * software deep-copy (W, msg, async ctx, etc.). */ | |
| (void)srcDevId; | |
| (void)dstDevId; | |
| (void)copySize; | |
| (void)savedDevId; | |
| (void)copySize; | |
| (void)savedDevId; | |
| (void)srcDevId; | |
| (void)dstDevId; | |
| (void)copySize; | |
| ret = wc_MXC_TPU_SHA_Copy(srcMxcCtx, dstMxcCtx); | |
| /* Signal to use standard copy path for software state. */ | |
| ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); |
| /* Hardware free */ | ||
| wc_MXC_TPU_SHA_Free(dstMxcCtx); | ||
| /* Software free */ | ||
| *dstDevId = INVALID_DEVID; | ||
| ForceZero(info->free.obj, copySize); | ||
| ret = 0; |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The WC_ALGO_TYPE_FREE handler frees only the MAX3266X mxcCtx and then ForceZero()s the whole hash object and returns success. With WOLF_CRYPTO_CB_FREE enabled, wc_Sha224Free/wc_Sha256Free will return immediately after a successful callback (see wolfcrypt/src/sha256.c:2330-2333 and 2407-2409), skipping their normal cleanup (e.g., freeing sha224/sha256->W under WOLFSSL_SMALL_STACK_CACHE, async ctx, HASH_KEEP msg, etc.). This causes leaks and can leave hardware/software state inconsistent. A safer pattern is to free only the MAX3266X-specific allocations (mxcCtx), set obj->devId to INVALID_DEVID if needed, and return CRYPTOCB_UNAVAILABLE so the standard Free path runs (mxcCtx free is idempotent if msg is NULL). Alternatively, the callback must explicitly duplicate the full standard free logic for each hash type.
| /* Hardware free */ | |
| wc_MXC_TPU_SHA_Free(dstMxcCtx); | |
| /* Software free */ | |
| *dstDevId = INVALID_DEVID; | |
| ForceZero(info->free.obj, copySize); | |
| ret = 0; | |
| /* Hardware free: release MAX3266X-specific SHA context. */ | |
| wc_MXC_TPU_SHA_Free(dstMxcCtx); | |
| /* Mark device as no longer using hardware so SW free can run. */ | |
| if (dstDevId != NULL) { | |
| *dstDevId = INVALID_DEVID; | |
| } | |
| /* Return unavailable so the standard software Free path runs and | |
| * performs any remaining cleanup (buffers, async state, etc.). */ | |
| ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); |
| return; /* Hash Struct is Null already, dont edit potentially */ | ||
| /* undefined memory */ | ||
| /* undefined memory by accident */ | ||
| } |
Copilot
AI
Jan 27, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: comment grammar/spelling — "dont" should be "don't", and the sentence can be simplified for clarity (e.g., avoid "by accident").
Found that when using sha224 with callbacks on program/system would crash due to missing initialization.
Update MAX32666 to use Copy and Free Callbacks as well, with some general improvement to copy and free logic.
Crash bug is present in v5.8.4, but not previous stable v5.8.2. Was found when adding #9070 specifically commit 07b3695 which added callback for sha224.
Also found that when commit 9c1462a entered, there was no initialization for the callback structure and the MXC init call when the new wc_sha256_init_ex was added.