[openssl] master update

tomas at openssl.org tomas at openssl.org
Wed May 26 15:18:44 UTC 2021


The branch master has been updated
       via  0800318a0c1f80ed838838951b0478cb977d40a6 (commit)
      from  022411112dd19420f0df51818322a216d914a0fb (commit)


- Log -----------------------------------------------------------------
commit 0800318a0c1f80ed838838951b0478cb977d40a6
Author: Tomas Mraz <tomas at openssl.org>
Date:   Mon May 24 18:15:57 2021 +0200

    Deprecate old style BIO callback calls
    
    New style BIO_debug_callback_ex() function added to provide
    replacement for BIO_debug_callback().
    
    Reviewed-by: Paul Dale <pauli at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15440)

-----------------------------------------------------------------------

Summary of changes:
 CHANGES.md                    |   5 ++
 apps/dgst.c                   |   2 +-
 apps/enc.c                    |  10 +--
 apps/include/s_apps.h         |   4 +-
 apps/lib/s_cb.c               |  27 ++++---
 apps/s_client.c               |   2 +-
 apps/s_server.c               |   6 +-
 crypto/bio/bio_cb.c           |  70 +++++++++-------
 crypto/bio/bio_lib.c          |  44 ++++++----
 crypto/bio/bio_local.h        |   2 +
 crypto/bio/bss_acpt.c         |   6 +-
 crypto/evp/bio_enc.c          |  31 +++++--
 doc/man3/BIO_set_callback.pod |  32 ++++++--
 doc/man7/migration_guide.pod  |   6 ++
 include/openssl/bio.h.in      |  16 ++--
 test/bio_callback_test.c      | 182 ++++++++++++++++++++++++++++++++++++++++++
 util/libcrypto.num            |   7 +-
 17 files changed, 365 insertions(+), 87 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 82c027bc73..65f3c88ece 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -189,6 +189,11 @@ breaking changes, and mappings for the large list of deprecated functions.
 
    *Jon Spillett*
 
+ * Deprecated obsolete BIO_set_callback(), BIO_get_callback(), and
+   BIO_debug_callback() functions.
+
+   *Tomáš Mráz*
+
  * Deprecated obsolete EVP_PKEY_CTX_get0_dh_kdf_ukm() and
    EVP_PKEY_CTX_get0_ecdh_kdf_ukm() functions.
 
diff --git a/apps/dgst.c b/apps/dgst.c
index 0fa668511a..e39d645cb8 100644
--- a/apps/dgst.c
+++ b/apps/dgst.c
@@ -248,7 +248,7 @@ int dgst_main(int argc, char **argv)
         goto end;
 
     if (debug) {
-        BIO_set_callback(in, BIO_debug_callback);
+        BIO_set_callback_ex(in, BIO_debug_callback_ex);
         /* needed for windows 3.1 */
         BIO_set_callback_arg(in, (char *)bio_err);
     }
diff --git a/apps/enc.c b/apps/enc.c
index 32ed08d943..cda0022ebb 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -389,8 +389,8 @@ int enc_main(int argc, char **argv)
         goto end;
 
     if (debug) {
-        BIO_set_callback(in, BIO_debug_callback);
-        BIO_set_callback(out, BIO_debug_callback);
+        BIO_set_callback_ex(in, BIO_debug_callback_ex);
+        BIO_set_callback_ex(out, BIO_debug_callback_ex);
         BIO_set_callback_arg(in, (char *)bio_err);
         BIO_set_callback_arg(out, (char *)bio_err);
     }
@@ -403,7 +403,7 @@ int enc_main(int argc, char **argv)
         if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
             goto end;
         if (debug) {
-            BIO_set_callback(bzl, BIO_debug_callback);
+            BIO_set_callback_ex(bzl, BIO_debug_callback_ex);
             BIO_set_callback_arg(bzl, (char *)bio_err);
         }
         if (enc)
@@ -417,7 +417,7 @@ int enc_main(int argc, char **argv)
         if ((b64 = BIO_new(BIO_f_base64())) == NULL)
             goto end;
         if (debug) {
-            BIO_set_callback(b64, BIO_debug_callback);
+            BIO_set_callback_ex(b64, BIO_debug_callback_ex);
             BIO_set_callback_arg(b64, (char *)bio_err);
         }
         if (olb64)
@@ -579,7 +579,7 @@ int enc_main(int argc, char **argv)
         }
 
         if (debug) {
-            BIO_set_callback(benc, BIO_debug_callback);
+            BIO_set_callback_ex(benc, BIO_debug_callback_ex);
             BIO_set_callback_arg(benc, (char *)bio_err);
         }
 
diff --git a/apps/include/s_apps.h b/apps/include/s_apps.h
index a5e9762aed..18dbd50d31 100644
--- a/apps/include/s_apps.h
+++ b/apps/include/s_apps.h
@@ -36,8 +36,8 @@ int init_client(int *sock, const char *host, const char *port,
 int should_retry(int i);
 void do_ssl_shutdown(SSL *ssl);
 
-long bio_dump_callback(BIO *bio, int cmd, const char *argp,
-                       int argi, long argl, long ret);
+long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len,
+                       int argi, long argl, int ret, size_t *processed);
 
 void apps_ssl_info_callback(const SSL *s, int where, int ret);
 void msg_cb(int write_p, int version, int content_type, const void *buf,
diff --git a/apps/lib/s_cb.c b/apps/lib/s_cb.c
index e3d9ec1916..ba883996ba 100644
--- a/apps/lib/s_cb.c
+++ b/apps/lib/s_cb.c
@@ -415,8 +415,8 @@ int ssl_print_tmp_key(BIO *out, SSL *s)
     return 1;
 }
 
-long bio_dump_callback(BIO *bio, int cmd, const char *argp,
-                       int argi, long argl, long ret)
+long bio_dump_callback(BIO *bio, int cmd, const char *argp, size_t len,
+                       int argi, long argl, int ret, size_t *processed)
 {
     BIO *out;
 
@@ -425,14 +425,23 @@ long bio_dump_callback(BIO *bio, int cmd, const char *argp,
         return ret;
 
     if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
-        BIO_printf(out, "read from %p [%p] (%lu bytes => %ld (0x%lX))\n",
-                   (void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
-        BIO_dump(out, argp, (int)ret);
-        return ret;
+        if (ret > 0 && processed != NULL) {
+            BIO_printf(out, "read from %p [%p] (%zu bytes => %zu (0x%zX))\n",
+                       (void *)bio, (void *)argp, len, *processed, *processed);
+            BIO_dump(out, argp, (int)*processed);
+        } else {
+            BIO_printf(out, "read from %p [%p] (%zu bytes => %d)\n",
+                       (void *)bio, (void *)argp, len, ret);
+        }
     } else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
-        BIO_printf(out, "write to %p [%p] (%lu bytes => %ld (0x%lX))\n",
-                   (void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
-        BIO_dump(out, argp, (int)ret);
+        if (ret > 0 && processed != NULL) {
+            BIO_printf(out, "write to %p [%p] (%zu bytes => %zu (0x%zX))\n",
+                       (void *)bio, (void *)argp, len, *processed, *processed);
+            BIO_dump(out, argp, (int)*processed);
+        } else {
+            BIO_printf(out, "write to %p [%p] (%zu bytes => %d)\n",
+                       (void *)bio, (void *)argp, len, ret);
+        }
     }
     return ret;
 }
diff --git a/apps/s_client.c b/apps/s_client.c
index 1754d3e1a4..85789eed23 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -2076,7 +2076,7 @@ int s_client_main(int argc, char **argv)
     }
 
     if (c_debug) {
-        BIO_set_callback(sbio, bio_dump_callback);
+        BIO_set_callback_ex(sbio, bio_dump_callback);
         BIO_set_callback_arg(sbio, (char *)bio_c_out);
     }
     if (c_msg) {
diff --git a/apps/s_server.c b/apps/s_server.c
index 0ff436be1e..644fe1a905 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -2392,7 +2392,7 @@ static int sv_body(int s, int stype, int prot, unsigned char *context)
     /* SSL_set_fd(con,s); */
 
     if (s_debug) {
-        BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+        BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
     if (s_msg) {
@@ -3025,7 +3025,7 @@ static int www_body(int s, int stype, int prot, unsigned char *context)
 #endif
 
     if (s_debug) {
-        BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+        BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
     if (s_msg) {
@@ -3429,7 +3429,7 @@ static int rev_body(int s, int stype, int prot, unsigned char *context)
 #endif
 
     if (s_debug) {
-        BIO_set_callback(SSL_get_rbio(con), bio_dump_callback);
+        BIO_set_callback_ex(SSL_get_rbio(con), bio_dump_callback);
         BIO_set_callback_arg(SSL_get_rbio(con), (char *)bio_s_out);
     }
     if (s_msg) {
diff --git a/crypto/bio/bio_cb.c b/crypto/bio/bio_cb.c
index 154fb5c9f0..dfe15c5f24 100644
--- a/crypto/bio/bio_cb.c
+++ b/crypto/bio/bio_cb.c
@@ -7,6 +7,8 @@
  * https://www.openssl.org/source/license.html
  */
 
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -14,25 +16,25 @@
 #include "internal/cryptlib.h"
 #include <openssl/err.h>
 
-long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
-                        int argi, long argl, long ret)
+long BIO_debug_callback_ex(BIO *bio, int cmd, const char *argp, size_t len,
+                           int argi, long argl, int ret, size_t *processed)
 {
     BIO *b;
     char buf[256];
     char *p;
-    long r = 1;
-    int len, left;
+    int left;
+    size_t l = 0;
 
-    if (BIO_CB_RETURN & cmd)
-        r = ret;
+    if (processed != NULL)
+        l = *processed;
 
-    len = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio);
+    left = BIO_snprintf(buf, sizeof(buf), "BIO[%p]: ", (void *)bio);
 
     /* Ignore errors and continue printing the other information. */
-    if (len < 0)
-        len = 0;
-    p = buf + len;
-    left = sizeof(buf) - len;
+    if (left < 0)
+        left = 0;
+    p = buf + left;
+    left = sizeof(buf) - left;
 
     switch (cmd) {
     case BIO_CB_FREE:
@@ -40,47 +42,47 @@ long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
         break;
     case BIO_CB_READ:
         if (bio->method->type & BIO_TYPE_DESCRIPTOR)
-            BIO_snprintf(p, left, "read(%d,%lu) - %s fd=%d\n",
-                         bio->num, (unsigned long)argi,
+            BIO_snprintf(p, left, "read(%d,%zu) - %s fd=%d\n",
+                         bio->num, len,
                          bio->method->name, bio->num);
         else
-            BIO_snprintf(p, left, "read(%d,%lu) - %s\n",
-                    bio->num, (unsigned long)argi, bio->method->name);
+            BIO_snprintf(p, left, "read(%d,%zu) - %s\n",
+                    bio->num, len, bio->method->name);
         break;
     case BIO_CB_WRITE:
         if (bio->method->type & BIO_TYPE_DESCRIPTOR)
-            BIO_snprintf(p, left, "write(%d,%lu) - %s fd=%d\n",
-                         bio->num, (unsigned long)argi,
+            BIO_snprintf(p, left, "write(%d,%zu) - %s fd=%d\n",
+                         bio->num, len,
                          bio->method->name, bio->num);
         else
-            BIO_snprintf(p, left, "write(%d,%lu) - %s\n",
-                         bio->num, (unsigned long)argi, bio->method->name);
+            BIO_snprintf(p, left, "write(%d,%zu) - %s\n",
+                         bio->num, len, bio->method->name);
         break;
     case BIO_CB_PUTS:
         BIO_snprintf(p, left, "puts() - %s\n", bio->method->name);
         break;
     case BIO_CB_GETS:
-        BIO_snprintf(p, left, "gets(%lu) - %s\n", (unsigned long)argi,
+        BIO_snprintf(p, left, "gets(%zu) - %s\n", len,
                      bio->method->name);
         break;
     case BIO_CB_CTRL:
-        BIO_snprintf(p, left, "ctrl(%lu) - %s\n", (unsigned long)argi,
+        BIO_snprintf(p, left, "ctrl(%d) - %s\n", argi,
                      bio->method->name);
         break;
     case BIO_CB_RETURN | BIO_CB_READ:
-        BIO_snprintf(p, left, "read return %ld\n", ret);
+        BIO_snprintf(p, left, "read return %d processed: %zu\n", ret, l);
         break;
     case BIO_CB_RETURN | BIO_CB_WRITE:
-        BIO_snprintf(p, left, "write return %ld\n", ret);
+        BIO_snprintf(p, left, "write return %d processed: %zu\n", ret, l);
         break;
     case BIO_CB_RETURN | BIO_CB_GETS:
-        BIO_snprintf(p, left, "gets return %ld\n", ret);
+        BIO_snprintf(p, left, "gets return %d processed: %zu\n", ret, l);
         break;
     case BIO_CB_RETURN | BIO_CB_PUTS:
-        BIO_snprintf(p, left, "puts return %ld\n", ret);
+        BIO_snprintf(p, left, "puts return %d processed: %zu\n", ret, l);
         break;
     case BIO_CB_RETURN | BIO_CB_CTRL:
-        BIO_snprintf(p, left, "ctrl return %ld\n", ret);
+        BIO_snprintf(p, left, "ctrl return %d\n", ret);
         break;
     default:
         BIO_snprintf(p, left, "bio callback - unknown type (%d)\n", cmd);
@@ -94,5 +96,19 @@ long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
     else
         fputs(buf, stderr);
 #endif
-    return r;
+    return ret;
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+long BIO_debug_callback(BIO *bio, int cmd, const char *argp,
+                        int argi, long argl, long ret)
+{
+    size_t processed = 0;
+
+    if (ret > 0)
+        processed = (size_t)ret;
+    BIO_debug_callback_ex(bio, cmd, argp, (size_t)argi,
+                          argi, argl, ret > 0 ? 1 : (int)ret, &processed);
+    return ret;
 }
+#endif
diff --git a/crypto/bio/bio_lib.c b/crypto/bio/bio_lib.c
index 9f25376e95..91db2290c4 100644
--- a/crypto/bio/bio_lib.c
+++ b/crypto/bio/bio_lib.c
@@ -7,6 +7,8 @@
  * https://www.openssl.org/source/license.html
  */
 
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <stdio.h>
 #include <errno.h>
 #include <openssl/crypto.h>
@@ -19,6 +21,11 @@
 #define HAS_LEN_OPER(o) ((o) == BIO_CB_READ || (o) == BIO_CB_WRITE \
                          || (o) == BIO_CB_GETS)
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+# define HAS_CALLBACK(b) ((b)->callback != NULL || (b)->callback_ex != NULL)
+#else
+# define HAS_CALLBACK(b) ((b)->callback_ex != NULL)
+#endif
 /*
  * Helper function to work out whether to call the new style callback or the old
  * one, and translate between the two.
@@ -30,12 +37,15 @@ static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
                               int argi, long argl, long inret,
                               size_t *processed)
 {
-    long ret;
+    long ret = inret;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     int bareoper;
 
     if (b->callback_ex != NULL)
+#endif
         return b->callback_ex(b, oper, argp, len, argi, argl, inret, processed);
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     /* Strip off any BIO_CB_RETURN flag */
     bareoper = oper & ~BIO_CB_RETURN;
 
@@ -63,7 +73,7 @@ static long bio_call_callback(BIO *b, int oper, const char *argp, size_t len,
         *processed = (size_t)ret;
         ret = 1;
     }
-
+#endif
     return ret;
 }
 
@@ -127,7 +137,7 @@ int BIO_free(BIO *a)
         return 1;
     REF_ASSERT_ISNT(ret < 0);
 
-    if (a->callback != NULL || a->callback_ex != NULL) {
+    if (HAS_CALLBACK(a)) {
         ret = (int)bio_call_callback(a, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
         if (ret <= 0)
             return ret;
@@ -207,6 +217,7 @@ void BIO_set_flags(BIO *b, int flags)
     b->flags |= flags;
 }
 
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 BIO_callback_fn BIO_get_callback(const BIO *b)
 {
     return b->callback;
@@ -216,6 +227,7 @@ void BIO_set_callback(BIO *b, BIO_callback_fn cb)
 {
     b->callback = cb;
 }
+#endif
 
 BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b)
 {
@@ -266,7 +278,7 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
         return -2;
     }
 
-    if ((b->callback != NULL || b->callback_ex != NULL) &&
+    if (HAS_CALLBACK(b) &&
         ((ret = (int)bio_call_callback(b, BIO_CB_READ, data, dlen, 0, 0L, 1L,
                                        NULL)) <= 0))
         return ret;
@@ -281,7 +293,7 @@ static int bio_read_intern(BIO *b, void *data, size_t dlen, size_t *readbytes)
     if (ret > 0)
         b->num_read += (uint64_t)*readbytes;
 
-    if (b->callback != NULL || b->callback_ex != NULL)
+    if (HAS_CALLBACK(b))
         ret = (int)bio_call_callback(b, BIO_CB_READ | BIO_CB_RETURN, data,
                                      dlen, 0, 0L, ret, readbytes);
 
@@ -331,7 +343,7 @@ static int bio_write_intern(BIO *b, const void *data, size_t dlen,
         return -2;
     }
 
-    if ((b->callback != NULL || b->callback_ex != NULL) &&
+    if (HAS_CALLBACK(b) &&
         ((ret = (int)bio_call_callback(b, BIO_CB_WRITE, data, dlen, 0, 0L, 1L,
                                        NULL)) <= 0))
         return ret;
@@ -346,7 +358,7 @@ static int bio_write_intern(BIO *b, const void *data, size_t dlen,
     if (ret > 0)
         b->num_write += (uint64_t)*written;
 
-    if (b->callback != NULL || b->callback_ex != NULL)
+    if (HAS_CALLBACK(b))
         ret = (int)bio_call_callback(b, BIO_CB_WRITE | BIO_CB_RETURN, data,
                                      dlen, 0, 0L, ret, written);
 
@@ -390,7 +402,7 @@ int BIO_puts(BIO *b, const char *buf)
         return -2;
     }
 
-    if (b->callback != NULL || b->callback_ex != NULL) {
+    if (HAS_CALLBACK(b)) {
         ret = (int)bio_call_callback(b, BIO_CB_PUTS, buf, 0, 0, 0L, 1L, NULL);
         if (ret <= 0)
             return ret;
@@ -409,7 +421,7 @@ int BIO_puts(BIO *b, const char *buf)
         ret = 1;
     }
 
-    if (b->callback != NULL || b->callback_ex != NULL)
+    if (HAS_CALLBACK(b))
         ret = (int)bio_call_callback(b, BIO_CB_PUTS | BIO_CB_RETURN, buf, 0, 0,
                                      0L, ret, &written);
 
@@ -444,7 +456,7 @@ int BIO_gets(BIO *b, char *buf, int size)
         return -1;
     }
 
-    if (b->callback != NULL || b->callback_ex != NULL) {
+    if (HAS_CALLBACK(b)) {
         ret = (int)bio_call_callback(b, BIO_CB_GETS, buf, size, 0, 0L, 1, NULL);
         if (ret <= 0)
             return ret;
@@ -462,7 +474,7 @@ int BIO_gets(BIO *b, char *buf, int size)
         ret = 1;
     }
 
-    if (b->callback != NULL || b->callback_ex != NULL)
+    if (HAS_CALLBACK(b))
         ret = (int)bio_call_callback(b, BIO_CB_GETS | BIO_CB_RETURN, buf, size,
                                      0, 0L, ret, &readbytes);
 
@@ -551,7 +563,7 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
         return -2;
     }
 
-    if (b->callback != NULL || b->callback_ex != NULL) {
+    if (HAS_CALLBACK(b)) {
         ret = bio_call_callback(b, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
         if (ret <= 0)
             return ret;
@@ -559,7 +571,7 @@ long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
 
     ret = b->method->ctrl(b, cmd, larg, parg);
 
-    if (b->callback != NULL || b->callback_ex != NULL)
+    if (HAS_CALLBACK(b))
         ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd,
                                 larg, ret, NULL);
 
@@ -580,7 +592,7 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
         return -2;
     }
 
-    if (b->callback != NULL || b->callback_ex != NULL) {
+    if (HAS_CALLBACK(b)) {
         ret = bio_call_callback(b, BIO_CB_CTRL, (void *)&fp, 0, cmd, 0, 1L,
                                 NULL);
         if (ret <= 0)
@@ -589,7 +601,7 @@ long BIO_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
 
     ret = b->method->callback_ctrl(b, cmd, fp);
 
-    if (b->callback != NULL || b->callback_ex != NULL)
+    if (HAS_CALLBACK(b))
         ret = bio_call_callback(b, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, 0,
                                 cmd, 0, ret, NULL);
 
@@ -742,7 +754,9 @@ BIO *BIO_dup_chain(BIO *in)
     for (bio = in; bio != NULL; bio = bio->next_bio) {
         if ((new_bio = BIO_new(bio->method)) == NULL)
             goto err;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
         new_bio->callback = bio->callback;
+#endif
         new_bio->callback_ex = bio->callback_ex;
         new_bio->cb_arg = bio->cb_arg;
         new_bio->init = bio->init;
diff --git a/crypto/bio/bio_local.h b/crypto/bio/bio_local.h
index 581b19c0c1..134ad748a1 100644
--- a/crypto/bio/bio_local.h
+++ b/crypto/bio/bio_local.h
@@ -116,7 +116,9 @@ struct bio_st {
     OSSL_LIB_CTX *libctx;
     const BIO_METHOD *method;
     /* bio, mode, argp, argi, argl, ret */
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     BIO_callback_fn callback;
+#endif
     BIO_callback_fn_ex callback_ex;
     char *cb_arg;               /* first argument for the callback */
     int init;
diff --git a/crypto/bio/bss_acpt.c b/crypto/bio/bss_acpt.c
index 5b776224d6..aff92223af 100644
--- a/crypto/bio/bss_acpt.c
+++ b/crypto/bio/bss_acpt.c
@@ -7,6 +7,8 @@
  * https://www.openssl.org/source/license.html
  */
 
+#define OPENSSL_SUPPRESS_DEPRECATED
+
 #include <stdio.h>
 #include <errno.h>
 #include "bio_local.h"
@@ -305,9 +307,11 @@ static int acpt_state(BIO *b, BIO_ACCEPT *c)
             if (bio == NULL)
                 goto exit_loop;
 
+            BIO_set_callback_ex(bio, BIO_get_callback_ex(b));
+#ifndef OPENSSL_NO_DEPRECATED_3_0
             BIO_set_callback(bio, BIO_get_callback(b));
+#endif
             BIO_set_callback_arg(bio, BIO_get_callback_arg(b));
-
             /*
              * If the accept BIO has an bio_chain, we dup it and put the new
              * socket at the end.
diff --git a/crypto/evp/bio_enc.c b/crypto/evp/bio_enc.c
index df669245f3..9d7a9eafef 100644
--- a/crypto/evp/bio_enc.c
+++ b/crypto/evp/bio_enc.c
@@ -7,6 +7,8 @@
  * https://www.openssl.org/source/license.html
  */
 
+#define OPENSSL_SUPPRESS_DEPRECATED /* for BIO_get_callback */
+
 #include <stdio.h>
 #include <errno.h>
 #include "internal/cryptlib.h"
@@ -392,7 +394,7 @@ static long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
 
     if (next == NULL)
         return 0;
-    
+
     return BIO_callback_ctrl(next, cmd, fp);
 }
 
@@ -400,25 +402,42 @@ int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k,
                    const unsigned char *i, int e)
 {
     BIO_ENC_CTX *ctx;
-    long (*callback) (struct bio_st *, int, const char *, int, long, long);
+    BIO_callback_fn_ex callback_ex;
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+    long (*callback) (struct bio_st *, int, const char *, int, long, long) = NULL;
+#endif
 
     ctx = BIO_get_data(b);
     if (ctx == NULL)
         return 0;
 
-    callback = BIO_get_callback(b);
+    if ((callback_ex = BIO_get_callback_ex(b)) != NULL) {
+        if (callback_ex(b, BIO_CB_CTRL, (const char *)c, 0, BIO_CTRL_SET,
+                        e, 1, NULL) <= 0)
+            return 0;
+    }
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+    else {
+        callback = BIO_get_callback(b);
 
-    if ((callback != NULL) &&
+        if ((callback != NULL) &&
             (callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e,
                       0L) <= 0))
-        return 0;
+            return 0;
+    }
+#endif
 
     BIO_set_init(b, 1);
 
     if (!EVP_CipherInit_ex(ctx->cipher, c, NULL, k, i, e))
         return 0;
 
-    if (callback != NULL)
+    if (callback_ex != NULL)
+        return callback_ex(b, BIO_CB_CTRL | BIO_CB_RETURN, (const char *)c, 0,
+                           BIO_CTRL_SET, e, 1, NULL);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
+    else if (callback != NULL)
         return callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L);
+#endif
     return 1;
 }
diff --git a/doc/man3/BIO_set_callback.pod b/doc/man3/BIO_set_callback.pod
index 975fef78d2..e3b86c095c 100644
--- a/doc/man3/BIO_set_callback.pod
+++ b/doc/man3/BIO_set_callback.pod
@@ -4,7 +4,7 @@
 
 BIO_set_callback_ex, BIO_get_callback_ex, BIO_set_callback, BIO_get_callback,
 BIO_set_callback_arg, BIO_get_callback_arg, BIO_debug_callback,
-BIO_callback_fn_ex, BIO_callback_fn
+BIO_debug_callback_ex, BIO_callback_fn_ex, BIO_callback_fn
 - BIO callback functions
 
 =head1 SYNOPSIS
@@ -14,17 +14,24 @@ BIO_callback_fn_ex, BIO_callback_fn
  typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
                                     size_t len, int argi,
                                     long argl, int ret, size_t *processed);
- typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
-                                 long argl, long ret);
 
  void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
  BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
 
- void BIO_set_callback(BIO *b, BIO_callback_fn cb);
- BIO_callback_fn BIO_get_callback(BIO *b);
  void BIO_set_callback_arg(BIO *b, char *arg);
  char *BIO_get_callback_arg(const BIO *b);
 
+ long BIO_debug_callback_ex(BIO *bio, int oper, const char *argp, size_t len,
+                            int argi, long argl, int ret, size_t *processed);
+
+ Deprecated since OpenSSL 3.0, can be hidden entirely by defining
+ OPENSSL_API_COMPAT with a suitable version value, see
+ openssl_user_macros(7):
+
+ typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
+                                 long argl, long ret);
+ void BIO_set_callback(BIO *b, BIO_callback_fn cb);
+ BIO_callback_fn BIO_get_callback(BIO *b);
  long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi,
                          long argl, long ret);
 
@@ -43,10 +50,12 @@ called in preference to any set by BIO_set_callback().
 BIO_set_callback_arg() and BIO_get_callback_arg() are macros which can be
 used to set and retrieve an argument for use in the callback.
 
-BIO_debug_callback() is a standard debugging callback which prints
+BIO_debug_callback_ex() is a standard debugging callback which prints
 out information relating to each BIO operation. If the callback
 argument is set it is interpreted as a BIO to send the information
-to, otherwise stderr is used.
+to, otherwise stderr is used. The BIO_debug_callback() function is the
+deprecated version of the same callback for use with the old callback
+format BIO_set_callback() function.
 
 BIO_callback_fn_ex is the type of the callback function and BIO_callback_fn
 is the type of the old format callback function. The meaning of each argument
@@ -225,9 +234,16 @@ operations.
 
 =head1 EXAMPLES
 
-The BIO_debug_callback() function is a good example, its source is
+The BIO_debug_callback_ex() function is an example, its source is
 in crypto/bio/bio_cb.c
 
+=head1 HISTORY
+
+The BIO_debug_callback_ex() function was added in OpenSSL 3.0.
+
+BIO_set_callback(), BIO_get_callback(), and BIO_debug_callback() were
+deprecated in OpenSSL 3.0. Use the non-deprecated _ex functions instead.
+
 =head1 COPYRIGHT
 
 Copyright 2000-2020 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man7/migration_guide.pod b/doc/man7/migration_guide.pod
index 022ac88207..89ef74f0a1 100644
--- a/doc/man7/migration_guide.pod
+++ b/doc/man7/migration_guide.pod
@@ -1085,6 +1085,12 @@ There is no replacement. This option returned a constant string.
 
 =item -
 
+BIO_get_callback(), BIO_set_callback(), BIO_debug_callback()
+
+Use the respective non-deprecated _ex() functions.
+
+=item -
+
 BN_is_prime_ex(), BN_is_prime_fasttest_ex()
 
 Use L<BN_check_prime(3)> which that avoids possible misuse and always uses at least
diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in
index 4e2fbb5f07..2c65b7e1a7 100644
--- a/include/openssl/bio.h.in
+++ b/include/openssl/bio.h.in
@@ -271,16 +271,23 @@ void BIO_clear_flags(BIO *b, int flags);
 # define BIO_cb_pre(a)   (!((a)&BIO_CB_RETURN))
 # define BIO_cb_post(a)  ((a)&BIO_CB_RETURN)
 
+# ifndef OPENSSL_NO_DEPRECATED_3_0
 typedef long (*BIO_callback_fn)(BIO *b, int oper, const char *argp, int argi,
                                 long argl, long ret);
+OSSL_DEPRECATEDIN_3_0 BIO_callback_fn BIO_get_callback(const BIO *b);
+OSSL_DEPRECATEDIN_3_0 void BIO_set_callback(BIO *b, BIO_callback_fn callback);
+OSSL_DEPRECATEDIN_3_0 long BIO_debug_callback(BIO *bio, int cmd,
+                                               const char *argp, int argi,
+                                               long argl, long ret);
+# endif
+
 typedef long (*BIO_callback_fn_ex)(BIO *b, int oper, const char *argp,
                                    size_t len, int argi,
                                    long argl, int ret, size_t *processed);
-BIO_callback_fn BIO_get_callback(const BIO *b);
-void BIO_set_callback(BIO *b, BIO_callback_fn callback);
-
 BIO_callback_fn_ex BIO_get_callback_ex(const BIO *b);
 void BIO_set_callback_ex(BIO *b, BIO_callback_fn_ex callback);
+long BIO_debug_callback_ex(BIO *bio, int oper, const char *argp, size_t len,
+                           int argi, long argl, int ret, size_t *processed);
 
 char *BIO_get_callback_arg(const BIO *b);
 void BIO_set_callback_arg(BIO *b, char *arg);
@@ -634,9 +641,6 @@ int BIO_nread(BIO *bio, char **buf, int num);
 int BIO_nwrite0(BIO *bio, char **buf);
 int BIO_nwrite(BIO *bio, char **buf, int num);
 
-long BIO_debug_callback(BIO *bio, int cmd, const char *argp, int argi,
-                        long argl, long ret);
-
 const BIO_METHOD *BIO_s_mem(void);
 const BIO_METHOD *BIO_s_secmem(void);
 BIO *BIO_new_mem_buf(const void *buf, int len);
diff --git a/test/bio_callback_test.c b/test/bio_callback_test.c
index 9b9c305205..66cf0e7974 100644
--- a/test/bio_callback_test.c
+++ b/test/bio_callback_test.c
@@ -6,6 +6,7 @@
  * in the file LICENSE in the source distribution or at
  * https://www.openssl.org/source/license.html
  */
+#define OPENSSL_SUPPRESS_DEPRECATED
 #include <stdio.h>
 #include <string.h>
 #include <openssl/bio.h>
@@ -20,7 +21,184 @@ static const char *my_param_argp[MAXCOUNT];
 static int         my_param_argi[MAXCOUNT];
 static long        my_param_argl[MAXCOUNT];
 static long        my_param_ret[MAXCOUNT];
+static size_t      my_param_len[MAXCOUNT];
+static size_t      my_param_processed[MAXCOUNT];
 
+static long my_bio_cb_ex(BIO *b, int oper, const char *argp, size_t len,
+                         int argi, long argl, int ret, size_t *processed)
+{
+    if (my_param_count >= MAXCOUNT)
+        return -1;
+    my_param_b[my_param_count]    = b;
+    my_param_oper[my_param_count] = oper;
+    my_param_argp[my_param_count] = argp;
+    my_param_argi[my_param_count] = argi;
+    my_param_argl[my_param_count] = argl;
+    my_param_ret[my_param_count]  = ret;
+    my_param_len[my_param_count]  = len;
+    my_param_processed[my_param_count] = processed != NULL ? *processed : 0;
+
+    my_param_count++;
+    return ret;
+}
+
+static int test_bio_callback_ex(void)
+{
+    int ok = 0;
+    BIO *bio;
+    int i;
+    char test1[] = "test";
+    const size_t test1len = sizeof(test1) - 1;
+    char test2[] = "hello";
+    const size_t test2len = sizeof(test2) - 1;
+    char buf[16];
+
+    my_param_count = 0;
+
+    bio = BIO_new(BIO_s_mem());
+    if (bio == NULL)
+        goto err;
+
+    BIO_set_callback_ex(bio, my_bio_cb_ex);
+    i = BIO_write(bio, test1, test1len);
+    if (!TEST_int_eq(i, test1len)
+            || !TEST_int_eq(my_param_count, 2)
+            || !TEST_ptr_eq(my_param_b[0], bio)
+            || !TEST_int_eq(my_param_oper[0], BIO_CB_WRITE)
+            || !TEST_ptr_eq(my_param_argp[0], test1)
+            || !TEST_size_t_eq(my_param_len[0], test1len)
+            || !TEST_long_eq(my_param_argl[0], 0L)
+            || !TEST_int_eq((int)my_param_ret[0], 1)
+            || !TEST_ptr_eq(my_param_b[1], bio)
+            || !TEST_int_eq(my_param_oper[1], BIO_CB_WRITE | BIO_CB_RETURN)
+            || !TEST_ptr_eq(my_param_argp[1], test1)
+            || !TEST_size_t_eq(my_param_len[1], test1len)
+            || !TEST_long_eq(my_param_argl[1], 0L)
+            || !TEST_size_t_eq(my_param_processed[1], test1len)
+            || !TEST_int_eq((int)my_param_ret[1], 1))
+        goto err;
+
+    my_param_count = 0;
+    i = BIO_read(bio, buf, sizeof(buf));
+    if (!TEST_mem_eq(buf, i, test1, test1len)
+            || !TEST_int_eq(my_param_count, 2)
+            || !TEST_ptr_eq(my_param_b[0], bio)
+            || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
+            || !TEST_ptr_eq(my_param_argp[0], buf)
+            || !TEST_size_t_eq(my_param_len[0], sizeof(buf))
+            || !TEST_long_eq(my_param_argl[0], 0L)
+            || !TEST_int_eq((int)my_param_ret[0], 1)
+            || !TEST_ptr_eq(my_param_b[1], bio)
+            || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
+            || !TEST_ptr_eq(my_param_argp[1], buf)
+            || !TEST_size_t_eq(my_param_len[1], sizeof(buf))
+            || !TEST_long_eq(my_param_argl[1], 0L)
+            || !TEST_size_t_eq(my_param_processed[1], test1len)
+            || !TEST_int_eq((int)my_param_ret[1], 1))
+        goto err;
+
+    /* By default a mem bio returns -1 if it has run out of data */
+    my_param_count = 0;
+    i = BIO_read(bio, buf, sizeof(buf));
+    if (!TEST_int_eq(i, -1)
+            || !TEST_int_eq(my_param_count, 2)
+            || !TEST_ptr_eq(my_param_b[0], bio)
+            || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
+            || !TEST_ptr_eq(my_param_argp[0], buf)
+            || !TEST_size_t_eq(my_param_len[0], sizeof(buf))
+            || !TEST_long_eq(my_param_argl[0], 0L)
+            || !TEST_int_eq((int)my_param_ret[0], 1)
+            || !TEST_ptr_eq(my_param_b[1], bio)
+            || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
+            || !TEST_ptr_eq(my_param_argp[1], buf)
+            || !TEST_size_t_eq(my_param_len[1], sizeof(buf))
+            || !TEST_long_eq(my_param_argl[1], 0L)
+            || !TEST_size_t_eq(my_param_processed[1], 0)
+            || !TEST_int_eq((int)my_param_ret[1], -1))
+        goto err;
+
+    /* Force the mem bio to return 0 if it has run out of data */
+    my_param_count = 0;
+    i = BIO_set_mem_eof_return(bio, 0);
+    if (!TEST_int_eq(i, 1)
+            || !TEST_int_eq(my_param_count, 2)
+            || !TEST_ptr_eq(my_param_b[0], bio)
+            || !TEST_int_eq(my_param_oper[0], BIO_CB_CTRL)
+            || !TEST_ptr_eq(my_param_argp[0], NULL)
+            || !TEST_int_eq(my_param_argi[0], BIO_C_SET_BUF_MEM_EOF_RETURN)
+            || !TEST_long_eq(my_param_argl[0], 0L)
+            || !TEST_int_eq((int)my_param_ret[0], 1)
+            || !TEST_ptr_eq(my_param_b[1], bio)
+            || !TEST_int_eq(my_param_oper[1], BIO_CB_CTRL | BIO_CB_RETURN)
+            || !TEST_ptr_eq(my_param_argp[1], NULL)
+            || !TEST_int_eq(my_param_argi[1], BIO_C_SET_BUF_MEM_EOF_RETURN)
+            || !TEST_long_eq(my_param_argl[1], 0L)
+            || !TEST_int_eq((int)my_param_ret[1], 1))
+        goto err;
+    my_param_count = 0;
+    i = BIO_read(bio, buf, sizeof(buf));
+    if (!TEST_int_eq(i, 0)
+            || !TEST_int_eq(my_param_count, 2)
+            || !TEST_ptr_eq(my_param_b[0], bio)
+            || !TEST_int_eq(my_param_oper[0], BIO_CB_READ)
+            || !TEST_ptr_eq(my_param_argp[0], buf)
+            || !TEST_size_t_eq(my_param_len[0], sizeof(buf))
+            || !TEST_long_eq(my_param_argl[0], 0L)
+            || !TEST_int_eq((int)my_param_ret[0], 1)
+            || !TEST_ptr_eq(my_param_b[1], bio)
+            || !TEST_int_eq(my_param_oper[1], BIO_CB_READ | BIO_CB_RETURN)
+            || !TEST_ptr_eq(my_param_argp[1], buf)
+            || !TEST_size_t_eq(my_param_len[1], sizeof(buf))
+            || !TEST_long_eq(my_param_argl[1], 0L)
+            || !TEST_size_t_eq(my_param_processed[1], 0)
+            || !TEST_int_eq((int)my_param_ret[1], 0))
+        goto err;
+
+    my_param_count = 0;
+    i = BIO_puts(bio, test2);
+    if (!TEST_int_eq(i, 5)
+            || !TEST_int_eq(my_param_count, 2)
+            || !TEST_ptr_eq(my_param_b[0], bio)
+            || !TEST_int_eq(my_param_oper[0], BIO_CB_PUTS)
+            || !TEST_ptr_eq(my_param_argp[0], test2)
+            || !TEST_int_eq(my_param_argi[0], 0)
+            || !TEST_long_eq(my_param_argl[0], 0L)
+            || !TEST_int_eq((int)my_param_ret[0], 1)
+            || !TEST_ptr_eq(my_param_b[1], bio)
+            || !TEST_int_eq(my_param_oper[1], BIO_CB_PUTS | BIO_CB_RETURN)
+            || !TEST_ptr_eq(my_param_argp[1], test2)
+            || !TEST_int_eq(my_param_argi[1], 0)
+            || !TEST_long_eq(my_param_argl[1], 0L)
+            || !TEST_size_t_eq(my_param_processed[1], test2len)
+            || !TEST_int_eq((int)my_param_ret[1], 1))
+        goto err;
+
+    my_param_count = 0;
+    i = BIO_free(bio);
+    if (!TEST_int_eq(i, 1)
+            || !TEST_int_eq(my_param_count, 1)
+            || !TEST_ptr_eq(my_param_b[0], bio)
+            || !TEST_int_eq(my_param_oper[0], BIO_CB_FREE)
+            || !TEST_ptr_eq(my_param_argp[0], NULL)
+            || !TEST_int_eq(my_param_argi[0], 0)
+            || !TEST_long_eq(my_param_argl[0], 0L)
+            || !TEST_int_eq((int)my_param_ret[0], 1))
+        goto finish;
+
+    ok = 1;
+    goto finish;
+
+err:
+    BIO_free(bio);
+
+finish:
+    /* This helps finding memory leaks with ASAN */
+    memset(my_param_b, 0, sizeof(my_param_b));
+    memset(my_param_argp, 0, sizeof(my_param_argp));
+    return ok;
+}
+
+#ifndef OPENSSL_NO_DEPRECATED_3_0
 static long my_bio_callback(BIO *b, int oper, const char *argp, int argi,
                             long argl, long ret)
 {
@@ -170,9 +348,13 @@ finish:
     memset(my_param_argp, 0, sizeof(my_param_argp));
     return ok;
 }
+#endif
 
 int setup_tests(void)
 {
+    ADD_TEST(test_bio_callback_ex);
+#ifndef OPENSSL_NO_DEPRECATED_3_0
     ADD_TEST(test_bio_callback);
+#endif
     return 1;
 }
diff --git a/util/libcrypto.num b/util/libcrypto.num
index b20c18d782..1016d9c327 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -1226,7 +1226,7 @@ UI_method_get_opener                    1254	3_0_0	EXIST::FUNCTION:
 EVP_aes_192_gcm                         1255	3_0_0	EXIST::FUNCTION:
 TS_CONF_set_tsa_name                    1256	3_0_0	EXIST::FUNCTION:TS
 X509_email_free                         1257	3_0_0	EXIST::FUNCTION:
-BIO_get_callback                        1258	3_0_0	EXIST::FUNCTION:
+BIO_get_callback                        1258	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0
 OPENSSL_sk_shift                        1259	3_0_0	EXIST::FUNCTION:
 i2d_X509_REVOKED                        1260	3_0_0	EXIST::FUNCTION:
 CMS_sign                                1261	3_0_0	EXIST::FUNCTION:CMS
@@ -3060,7 +3060,7 @@ ASN1_STRING_print                       3126	3_0_0	EXIST::FUNCTION:
 CRYPTO_THREAD_lock_free                 3127	3_0_0	EXIST::FUNCTION:
 TS_ACCURACY_get_seconds                 3128	3_0_0	EXIST::FUNCTION:TS
 BN_options                              3129	3_0_0	EXIST::FUNCTION:
-BIO_debug_callback                      3130	3_0_0	EXIST::FUNCTION:
+BIO_debug_callback                      3130	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0
 EVP_MD_meth_get_update                  3131	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0
 GENERAL_NAME_set0_othername             3132	3_0_0	EXIST::FUNCTION:
 ASN1_BIT_STRING_set_bit                 3133	3_0_0	EXIST::FUNCTION:
@@ -3671,7 +3671,7 @@ X509v3_get_ext_count                    3753	3_0_0	EXIST::FUNCTION:
 UI_OpenSSL                              3754	3_0_0	EXIST::FUNCTION:UI_CONSOLE
 CRYPTO_ccm128_decrypt                   3755	3_0_0	EXIST::FUNCTION:
 d2i_OCSP_RESPDATA                       3756	3_0_0	EXIST::FUNCTION:OCSP
-BIO_set_callback                        3757	3_0_0	EXIST::FUNCTION:
+BIO_set_callback                        3757	3_0_0	EXIST::FUNCTION:DEPRECATEDIN_3_0
 BN_GF2m_poly2arr                        3758	3_0_0	EXIST::FUNCTION:EC2M
 CMS_unsigned_get_attr_count             3759	3_0_0	EXIST::FUNCTION:CMS
 EVP_aes_256_gcm                         3760	3_0_0	EXIST::FUNCTION:
@@ -5415,3 +5415,4 @@ OSSL_LIB_CTX_new_child                  5542	3_0_0	EXIST::FUNCTION:
 OSSL_PROVIDER_get0_dispatch             5543	3_0_0	EXIST::FUNCTION:
 PKCS5_PBE_keyivgen_ex                   5544	3_0_0	EXIST::FUNCTION:
 EVP_MAC_CTX_get_block_size              5545	3_0_0	EXIST::FUNCTION:
+BIO_debug_callback_ex                   5546	3_0_0	EXIST::FUNCTION:


More information about the openssl-commits mailing list