fuzz/provider.c: fix API call order in do_evp_cipher and do_evp_md#30331
fuzz/provider.c: fix API call order in do_evp_cipher and do_evp_md#30331OwenSanzas wants to merge 5 commits into
Conversation
Both do_evp_cipher() and do_evp_md() call the parameter-setting function (EVP_CIPHER_CTX_set_params / EVP_MD_CTX_set_params) before initializing the algorithm context (EVP_EncryptInit_ex2 / EVP_DigestInit_ex2). Since the context has no algorithm associated at that point, set_params always returns 0 and the function early-returns, making the cipher and digest paths dead code (~20% of all fuzzer inputs). Fix by swapping the call order so the context is initialized first. Additionally, heap-allocate key/iv buffers sized to the cipher's actual key and IV length, since some ciphers (e.g. DES-EDE3-OFB) require buffers larger than the previous fixed 16/8-byte arrays. Fixes openssl#30281
|
given that this is a non-trivial change, we will need you to submit a CLA prior to reviewing/accepting this change. If you could please fill out the form here: If you could submit the online form on that page, we will get you into our CLA database, and start taking a look at this. Thank you! |
| if (!EVP_CIPHER_CTX_set_params(ctx, param)) { | ||
| EVP_CIPHER_CTX_free(ctx); | ||
| OPENSSL_free(key); | ||
| OPENSSL_free(iv); |
There was a problem hiding this comment.
nitpick: iv, key, and ctx can be set to NULL in the declaration, and then at the end of the function, you can have
err:
EVP_CIPHER_CTX_free(ctx);
OPENSSL_free(key);
OPENSSL_free(iv);
return 0;
}that will make the err path slightly nicer.
There was a problem hiding this comment.
Thanks for the suggestion! I've updated the code — key, iv, and ctx are now initialized to NULL and all error paths go through a single err: label. Please take a look when you get a chance.
Initialize key, iv, and ctx to NULL at declaration and consolidate all cleanup into a single err label, as suggested by @npajkovsky.
| iv = OPENSSL_zalloc(iv_len); | ||
| if (key == NULL || iv == NULL) | ||
| goto err; | ||
| for (i = 0; i < key_len && i < 16; i++) |
Drop the `&& i < 16` and `&& i < 8` guards that were carried over from the original fixed-size arrays. The loops now fill the entire heap-allocated buffer, with values wrapping naturally via unsigned char.
|
The check style CI failure is relevant. |
|
@OwenSanzas as @t8m notes, this still needs to be fixed up: |
|
Done, thanks for pointing that out. |
|
This pull request is ready to merge |
|
merged to master, thank you! |
Both do_evp_cipher() and do_evp_md() call the parameter-setting function (EVP_CIPHER_CTX_set_params / EVP_MD_CTX_set_params) before initializing the algorithm context (EVP_EncryptInit_ex2 / EVP_DigestInit_ex2). Since the context has no algorithm associated at that point, set_params always returns 0 and the function early-returns, making the cipher and digest paths dead code (~20% of all fuzzer inputs). Fix by swapping the call order so the context is initialized first. Additionally, heap-allocate key/iv buffers sized to the cipher's actual key and IV length, since some ciphers (e.g. DES-EDE3-OFB) require buffers larger than the previous fixed 16/8-byte arrays. Fixes #30281 Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Kurt Roeckx <[email protected]> MergeDate: Wed Mar 11 20:58:44 2026 (Merged from #30331)
Initialize key, iv, and ctx to NULL at declaration and consolidate all cleanup into a single err label, as suggested by @npajkovsky. Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Kurt Roeckx <[email protected]> MergeDate: Wed Mar 11 20:58:47 2026 (Merged from #30331)
Drop the `&& i < 16` and `&& i < 8` guards that were carried over from the original fixed-size arrays. The loops now fill the entire heap-allocated buffer, with values wrapping naturally via unsigned char. Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Kurt Roeckx <[email protected]> MergeDate: Wed Mar 11 20:58:49 2026 (Merged from #30331)
Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Kurt Roeckx <[email protected]> MergeDate: Wed Mar 11 20:58:51 2026 (Merged from #30331)
Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Kurt Roeckx <[email protected]> MergeDate: Wed Mar 11 20:58:54 2026 (Merged from #30331)
Summary
do_evp_cipher()anddo_evp_md()call parameter-setting functions (EVP_CIPHER_CTX_set_params/EVP_MD_CTX_set_params) before initializing the algorithm context (EVP_EncryptInit_ex2/EVP_DigestInit_ex2). Since the context has no algorithm associated at that point,set_paramsalways returns 0 and the function early-returns, making the cipher and digest paths dead code (~20% of all fuzzer inputs).This PR swaps the call order so the context is initialized before parameters are set.
Additionally, key/iv buffers are now heap-allocated and sized to the cipher's actual key and IV length, since some ciphers (e.g. DES-EDE3-OFB) require buffers larger than the previous fixed 16/8-byte stack arrays.
Verification
PoC (single input, cipher path
operation % 10 == 1):set_paramsfails, function returns immediatelySame for digest path (
operation % 10 == 0): 0 ms → 23 ms.Fuzzing (60s, ASan, fork mode):
stack-use-after-returnin DES OFBKDF path (unmodified control): identical behavior in both versions (18–19 ms).
Fixes #30281