Blame SOURCES/openssl-1.1.1-cve-2023-0215-BIO-UAF.patch

2502e2
From c3829dd8825c654652201e16f8a0a0c46ee3f344 Mon Sep 17 00:00:00 2001
2502e2
From: Matt Caswell <matt@openssl.org>
2502e2
Date: Wed, 14 Dec 2022 16:18:14 +0000
2502e2
Subject: [PATCH 4/6] Fix a UAF resulting from a bug in BIO_new_NDEF
2502e2
2502e2
If the aux->asn1_cb() call fails in BIO_new_NDEF then the "out" BIO will
2502e2
be part of an invalid BIO chain. This causes a "use after free" when the
2502e2
BIO is eventually freed.
2502e2
2502e2
Based on an original patch by Viktor Dukhovni and an idea from Theo
2502e2
Buehler.
2502e2
2502e2
Thanks to Octavio Galland for reporting this issue.
2502e2
2502e2
Reviewed-by: Paul Dale <pauli@openssl.org>
2502e2
Reviewed-by: Tomas Mraz <tomas@openssl.org>
2502e2
---
2502e2
 crypto/asn1/bio_ndef.c | 39 ++++++++++++++++++++++++++++++++-------
2502e2
 1 file changed, 32 insertions(+), 7 deletions(-)
2502e2
2502e2
diff --git a/crypto/asn1/bio_ndef.c b/crypto/asn1/bio_ndef.c
2502e2
index 760e4846a4..f8d4b1b9aa 100644
2502e2
--- a/crypto/asn1/bio_ndef.c
2502e2
+++ b/crypto/asn1/bio_ndef.c
2502e2
@@ -49,12 +49,19 @@ static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
2502e2
 static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen,
2502e2
                             void *parg);
2502e2
 
2502e2
+/*
2502e2
+ * On success, the returned BIO owns the input BIO as part of its BIO chain.
2502e2
+ * On failure, NULL is returned and the input BIO is owned by the caller.
2502e2
+ *
2502e2
+ * Unfortunately cannot constify this due to CMS_stream() and PKCS7_stream()
2502e2
+ */
2502e2
 BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
2502e2
 {
2502e2
     NDEF_SUPPORT *ndef_aux = NULL;
2502e2
     BIO *asn_bio = NULL;
2502e2
     const ASN1_AUX *aux = it->funcs;
2502e2
     ASN1_STREAM_ARG sarg;
2502e2
+    BIO *pop_bio = NULL;
2502e2
 
2502e2
     if (!aux || !aux->asn1_cb) {
2502e2
         ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED);
2502e2
@@ -69,21 +76,39 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
2502e2
     out = BIO_push(asn_bio, out);
2502e2
     if (out == NULL)
2502e2
         goto err;
2502e2
+    pop_bio = asn_bio;
2502e2
 
2502e2
-    BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
2502e2
-    BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
2502e2
+    if (BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free) <= 0
2502e2
+            || BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free) <= 0
2502e2
+            || BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux) <= 0)
2502e2
+        goto err;
2502e2
 
2502e2
     /*
2502e2
-     * Now let callback prepends any digest, cipher etc BIOs ASN1 structure
2502e2
-     * needs.
2502e2
+     * Now let the callback prepend any digest, cipher, etc., that the BIO's
2502e2
+     * ASN1 structure needs.
2502e2
      */
2502e2
 
2502e2
     sarg.out = out;
2502e2
     sarg.ndef_bio = NULL;
2502e2
     sarg.boundary = NULL;
2502e2
 
2502e2
-    if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
2502e2
+    /*
2502e2
+     * The asn1_cb(), must not have mutated asn_bio on error, leaving it in the
2502e2
+     * middle of some partially built, but not returned BIO chain.
2502e2
+     */
2502e2
+    if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) {
2502e2
+        /*
2502e2
+         * ndef_aux is now owned by asn_bio so we must not free it in the err
2502e2
+         * clean up block
2502e2
+         */
2502e2
+        ndef_aux = NULL;
2502e2
         goto err;
2502e2
+    }
2502e2
+
2502e2
+    /*
2502e2
+     * We must not fail now because the callback has prepended additional
2502e2
+     * BIOs to the chain
2502e2
+     */
2502e2
 
2502e2
     ndef_aux->val = val;
2502e2
     ndef_aux->it = it;
2502e2
@@ -91,11 +116,11 @@ BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
2502e2
     ndef_aux->boundary = sarg.boundary;
2502e2
     ndef_aux->out = out;
2502e2
 
2502e2
-    BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
2502e2
-
2502e2
     return sarg.ndef_bio;
2502e2
 
2502e2
  err:
2502e2
+    /* BIO_pop() is NULL safe */
2502e2
+    (void)BIO_pop(pop_bio);
2502e2
     BIO_free(asn_bio);
2502e2
     OPENSSL_free(ndef_aux);
2502e2
     return NULL;
2502e2
-- 
2502e2
2.39.1
2502e2
2502e2
From f040f2577891d2bdb7610566c172233844cf673a Mon Sep 17 00:00:00 2001
2502e2
From: Matt Caswell <matt@openssl.org>
2502e2
Date: Wed, 14 Dec 2022 17:15:18 +0000
2502e2
Subject: [PATCH 5/6] Check CMS failure during BIO setup with -stream is
2502e2
 handled correctly
2502e2
2502e2
Test for the issue fixed in the previous commit
2502e2
2502e2
Reviewed-by: Paul Dale <pauli@openssl.org>
2502e2
Reviewed-by: Tomas Mraz <tomas@openssl.org>
2502e2
---
2502e2
 test/recipes/80-test_cms.t  | 15 +++++++++++++--
2502e2
 test/smime-certs/badrsa.pem | 18 ++++++++++++++++++
2502e2
 2 files changed, 31 insertions(+), 2 deletions(-)
2502e2
 create mode 100644 test/smime-certs/badrsa.pem
2502e2
2502e2
diff --git a/test/recipes/80-test_cms.t b/test/recipes/80-test_cms.t
2502e2
index 5dc6a3aebe..ec11bfc253 100644
2502e2
--- a/test/recipes/80-test_cms.t
2502e2
+++ b/test/recipes/80-test_cms.t
2502e2
@@ -13,7 +13,7 @@ use warnings;
2502e2
 use POSIX;
2502e2
 use File::Spec::Functions qw/catfile/;
2502e2
 use File::Compare qw/compare_text/;
2502e2
-use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file/;
2502e2
+use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file with/;
2502e2
 use OpenSSL::Test::Utils;
2502e2
 
2502e2
 setup("test_cms");
2502e2
@@ -27,7 +27,7 @@ my $smcont   = srctop_file("test", "smcont.txt");
2502e2
 my ($no_des, $no_dh, $no_dsa, $no_ec, $no_ec2m, $no_rc2, $no_zlib)
2502e2
     = disabled qw/des dh dsa ec ec2m rc2 zlib/;
2502e2
 
2502e2
-plan tests => 6;
2502e2
+plan tests => 7;
2502e2
 
2502e2
 my @smime_pkcs7_tests = (
2502e2
 
2502e2
@@ -584,3 +584,14 @@ sub check_availability {
2502e2
 
2502e2
     return "";
2502e2
 }
2502e2
+
2502e2
+# Check that we get the expected failure return code
2502e2
+with({ exit_checker => sub { return shift == 6; } },
2502e2
+    sub {
2502e2
+        ok(run(app(['openssl', 'cms', '-encrypt',
2502e2
+                    '-in', srctop_file("test", "smcont.txt"),
2502e2
+                    '-stream', '-recip',
2502e2
+                    srctop_file("test/smime-certs", "badrsa.pem"),
2502e2
+                   ])),
2502e2
+            "Check failure during BIO setup with -stream is handled correctly");
2502e2
+    });
2502e2
diff --git a/test/smime-certs/badrsa.pem b/test/smime-certs/badrsa.pem
2502e2
new file mode 100644
2502e2
index 0000000000..f824fc2267
2502e2
--- /dev/null
2502e2
+++ b/test/smime-certs/badrsa.pem
2502e2
@@ -0,0 +1,18 @@
2502e2
+-----BEGIN CERTIFICATE-----
2502e2
+MIIDbTCCAlWgAwIBAgIToTV4Z0iuK08vZP20oTh//hC8BDANBgkqhkiG9w0BAQ0FADAtMSswKQYD
2502e2
+VfcDEyJTYW1wbGUgTEFNUFMgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MCAXDTE5MTEyMDA2NTQxOFoY
2502e2
+DzIwNTIwOTI3MDY1NDE4WjAZMRcwFQYDVQQDEw5BbGljZSBMb3ZlbGFjZTCCASIwDQYJKoZIhvcN
2502e2
+AQEBBQADggEPADCCAQoCggEBALT0iehYOBY+TZp/T5K2KNI05Hwr+E3wP6XTvyi6WWyTgBK9LCOw
2502e2
+I2juwdRrjFBmXkk7pWpjXwsA3A5GOtz0FpfgyC7OxsVcF7q4WHWZWleYXFKlQHJD73nQwXP968+A
2502e2
+/3rBX7PhO0DBbZnfitOLPgPEwjTtdg0VQQ6Wz+CRQ/YbHPKaw7aRphZO63dKvIKp4cQVtkWQHi6s
2502e2
+yTjGsgkLcLNau5LZDQUdsGV+SAo3nBdWCRYV+I65x8Kf4hCxqqmjV3d/2NKRu0BXnDe/N+iDz3X0
2502e2
+zEoj0fqXgq4SWcC0nsG1lyyXt1TL270I6ATKRGJWiQVCCpDtc0NT6vdJ45bCSxgCAwEAAaOBlzCB
2502e2
+lDAMBgNVHRMBAf8EAjAAMB4GA1UdEQQXMBWBE2FsaWNlQHNtaW1lLmV4YW1wbGUwEwYDVR0lBAww
2502e2
+CgYIKwYBBQUHAwQwDwYDVR0PAQH/BAUDAwfAADAdBgNVHQ4EFgQUu/bMsi0dBhIcl64papAQ0yBm
2502e2
+ZnMwHwYDVR0jBBgwFoAUeF8OWnjYa+RUcD2z3ez38fL6wEcwDQYJKoZIhvcNAQENBQADggEBABbW
2502e2
+eonR6TMTckehDKNOabwaCIcekahAIL6l9tTzUX5ew6ufiAPlC6I/zQlmUaU0iSyFDG1NW14kNbFt
2502e2
+5CAokyLhMtE4ASHBIHbiOp/ZSbUBTVYJZB61ot7w1/ol5QECSs08b8zrxIncf+t2DHGuVEy/Qq1d
2502e2
+rBz8d4ay8zpqAE1tUyL5Da6ZiKUfWwZQXSI/JlbjQFzYQqTRDnzHWrg1xPeMTO1P2/cplFaseTiv
2502e2
+yk4cYwOp/W9UAWymOZXF8WcJYCIUXkdcG/nEZxr057KlScrJmFXOoh7Y+8ON4iWYYcAfiNgpUFo/
2502e2
+j8BAwrKKaFvdlZS9k1Ypb2+UQY75mKJE9Bg=
2502e2
+-----END CERTIFICATE-----
2502e2
-- 
2502e2
2.39.1
2502e2