Commit 32f5a5183c for openssl.org
commit 32f5a5183c7f55d5dcf42f433d38c5946c1d0b7e
Author: Abel Thomas <abeltom.kernel@gmail.com>
Date: Thu Jul 9 14:22:50 2026 +0200
pkcs7: null-guard enveloped and signedAndEnveloped arms in PKCS7_stream
Dereferences of `p7->d.enveloped->enc_data` and
`p7->d.signed_and_enveloped->enc_data` crash with UBSan when the union
member is NULL after parsing a minimal/malformed input. Mirror the guard
added for the signed arm in PR #30351.
Added unit-tests to validate the change.
Fixes: #31682
Reviewed-by: Andrew Dinh <andrewd@openssl.org>
Reviewed-by: Jakub Zelenka <jakub.zelenka@openssl.foundation>
MergeDate: Wed Jul 29 16:51:46 2026
(Merged from https://github.com/openssl/openssl/pull/31716)
diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c
index a9640769cf..d2a9f0cea8 100644
--- a/crypto/pkcs7/pk7_lib.c
+++ b/crypto/pkcs7/pk7_lib.c
@@ -727,6 +727,10 @@ int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7)
break;
case NID_pkcs7_signedAndEnveloped:
+ if (p7->d.signed_and_enveloped == NULL || p7->d.signed_and_enveloped->enc_data == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
+ break;
+ }
os = p7->d.signed_and_enveloped->enc_data->enc_data;
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
@@ -735,6 +739,10 @@ int PKCS7_stream(unsigned char ***boundary, PKCS7 *p7)
break;
case NID_pkcs7_enveloped:
+ if (p7->d.enveloped == NULL || p7->d.enveloped->enc_data == NULL) {
+ ERR_raise(ERR_LIB_PKCS7, PKCS7_R_NO_CONTENT);
+ break;
+ }
os = p7->d.enveloped->enc_data->enc_data;
if (os == NULL) {
os = ASN1_OCTET_STRING_new();
diff --git a/test/pkcs7_test.c b/test/pkcs7_test.c
index 8514101121..6362645e47 100644
--- a/test/pkcs7_test.c
+++ b/test/pkcs7_test.c
@@ -411,6 +411,54 @@ end:
}
#endif /* OPENSSL_NO_EC */
+static int pkcs7_stream_enveloped_no_content_test(void)
+{
+ int ret = 0;
+ PKCS7 *p7 = NULL;
+ BIO *sink = NULL;
+ BIO *bio = NULL;
+
+ const unsigned char data_enveloped_no_body[] = { 0x30, 0x0b, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03 };
+ const unsigned char *ptr_env_no_body = data_enveloped_no_body;
+
+ ret = TEST_ptr(p7 = d2i_PKCS7(NULL, &ptr_env_no_body,
+ sizeof(data_enveloped_no_body)))
+ && TEST_ptr(sink = BIO_new(BIO_s_null()))
+ && TEST_ptr_null(bio = BIO_new_PKCS7(sink, p7))
+ && TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()),
+ PKCS7_R_NO_CONTENT);
+
+ BIO_free(bio);
+ BIO_free(sink);
+ PKCS7_free(p7);
+ return ret;
+}
+
+static int pkcs7_stream_enveloped_signed_no_content_test(void)
+{
+ int ret = 0;
+ PKCS7 *p7 = NULL;
+ BIO *sink = NULL;
+ BIO *bio = NULL;
+
+ const unsigned char data_enveloped_signed_no_body[] = { 0x30, 0x0b, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x04 };
+ const unsigned char *ptr_env_signed_no_body = data_enveloped_signed_no_body;
+
+ ret = TEST_ptr(p7 = d2i_PKCS7(NULL, &ptr_env_signed_no_body,
+ sizeof(data_enveloped_signed_no_body)))
+ && TEST_ptr(sink = BIO_new(BIO_s_null()))
+ && TEST_ptr_null(bio = BIO_new_PKCS7(sink, p7))
+ && TEST_int_eq(ERR_GET_REASON(ERR_peek_last_error()),
+ PKCS7_R_NO_CONTENT);
+
+ BIO_free(bio);
+ BIO_free(sink);
+ PKCS7_free(p7);
+ return ret;
+}
+
int setup_tests(void)
{
ADD_TEST(pkcs7_issuer_and_serial_negative_idx_test);
@@ -418,5 +466,7 @@ int setup_tests(void)
ADD_TEST(pkcs7_verify_test);
ADD_TEST(pkcs7_inner_content_verify_test);
#endif /* OPENSSL_NO_EC */
+ ADD_TEST(pkcs7_stream_enveloped_no_content_test);
+ ADD_TEST(pkcs7_stream_enveloped_signed_no_content_test);
return 1;
}