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