You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by sh...@apache.org on 2018/03/08 19:02:37 UTC

[trafficserver] branch master updated: Add support for ASYNC_*_job and crypto engine loading

This is an automated email from the ASF dual-hosted git repository.

shinrich pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new e3ce345  Add support for ASYNC_*_job and crypto engine loading
e3ce345 is described below

commit e3ce345a4c0a7e8a3f65586aa718d19d1b7e5c92
Author: Susan Hinrichs <sh...@apache.org>
AuthorDate: Wed Jan 24 09:08:50 2018 -0600

    Add support for ASYNC_*_job and crypto engine loading
    
    The ASYNC_*_job feature requires openssl 1.1 or better. I tested this
    against the crypto engine contrib/openssl that is a wrapper for the normal
    RSA operations, but it adds a 5 second delay in the private key operations.
    By using the ASYNC_*_job feature, the main ET_NET thread is not blocked during the
    5 second sleep.  contrib/openssl also has an example openssl config file to
    to load the crypto engine.
---
 build/crypto.m4                             |  16 ++
 configure.ac                                |   5 +
 contrib/openssl/README.md                   |  10 +
 contrib/openssl/async_engine.c              | 297 ++++++++++++++++++++++++++++
 contrib/openssl/load_engine.cnf             |  35 ++++
 doc/admin-guide/files/records.config.en.rst |  14 ++
 iocore/net/P_SSLConfig.h                    |   3 +
 iocore/net/P_SSLNetVConnection.h            |   3 +
 iocore/net/SSLConfig.cc                     |   5 +-
 iocore/net/SSLNetVConnection.cc             |  37 +++-
 iocore/net/SSLUtils.cc                      |  18 ++
 lib/ts/ink_config.h.in                      |   1 +
 mgmt/RecordsConfig.cc                       |   3 +
 13 files changed, 445 insertions(+), 2 deletions(-)

diff --git a/build/crypto.m4 b/build/crypto.m4
index 4cef872..a8ae5aa 100644
--- a/build/crypto.m4
+++ b/build/crypto.m4
@@ -71,6 +71,22 @@ AC_DEFUN([TS_CHECK_CRYPTO_NEXTPROTONEG], [
   AC_SUBST(use_tls_npn)
 ])
 
+AC_DEFUN([TS_CHECK_CRYPTO_ASYNC], [
+  enable_tls_async=yes
+  _async_saved_LIBS=$LIBS
+
+  TS_ADDTO(LIBS, [$OPENSSL_LIBS])
+  AC_CHECK_FUNCS(SSL_get_all_async_fds ASYNC_init_thread,
+    [], [enable_tls_async=no]
+  )
+  LIBS=$_async_saved_LIBS
+
+  AC_MSG_CHECKING(whether to enable ASYNC job openssl support)
+  AC_MSG_RESULT([$enable_tls_async])
+  TS_ARG_ENABLE_VAR([use], [tls-async])
+  AC_SUBST(use_tls_async)
+])
+
 AC_DEFUN([TS_CHECK_CRYPTO_ALPN], [
   enable_tls_alpn=yes
   _alpn_saved_LIBS=$LIBS
diff --git a/configure.ac b/configure.ac
index 7acee0d..1c18e50 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1149,6 +1149,11 @@ TS_CHECK_CRYPTO_NEXTPROTONEG
 #
 # Check for ALPN TLS extension support.
 TS_CHECK_CRYPTO_ALPN
+
+#
+# Check for openssl ASYNC jobs
+TS_CHECK_CRYPTO_ASYNC
+
 #
 # Check for EC key support.
 TS_CHECK_CRYPTO_EC_KEYS
diff --git a/contrib/openssl/README.md b/contrib/openssl/README.md
new file mode 100644
index 0000000..ab95898
--- /dev/null
+++ b/contrib/openssl/README.md
@@ -0,0 +1,10 @@
+async-test.c is source for a sample openssl crypto engine.  It wraps the standard RSA operations.
+For the private key operations it spawns a thread to sleep for 5 seconds and then pauses the asynchronous job.
+
+It should be built as follows.  It must be build against openssl 1.1 or better for access to the ASYNC_*_job apis.
+
+gcc -fPIC -shared -g -o async-test.so -I<path to openssl headers> -L<path to openssl library> -lssl -lcrypto -lpthread async_engine.c 
+
+load_engine.cnf is an example openssl config file that can be passed to Traffic Server via the proxy.config.ssl.engine_cnf_file setting.
+It describes which crypto engines should be loaded and how they should be used.  In the case of our async-test crypto engine it will be used for
+RSA operations
diff --git a/contrib/openssl/async_engine.c b/contrib/openssl/async_engine.c
new file mode 100644
index 0000000..31fbce3
--- /dev/null
+++ b/contrib/openssl/async_engine.c
@@ -0,0 +1,297 @@
+/** @file
+
+  Test crypto engine
+
+  @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+ */
+
+/*
+ * Test engine to exercise the asynchronous job interface
+ * It performs the standard RSA operations, but for private key 
+ * operations spawns a thread to sleep for 5 seconds before resuming
+ * the asynchronous job
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/engine.h>
+#include <openssl/rsa.h>
+#include <openssl/async.h>
+#include <openssl/crypto.h>
+#include <openssl/ssl.h>
+#include <openssl/modes.h>
+#include <pthread.h>
+#include <unistd.h>
+
+
+/* Engine Id and Name */
+static const char *engine_id = "async-test";
+static const char *engine_name = "Asynchronous test engine";
+
+
+/* Engine Lifetime functions */
+static int async_destroy(ENGINE *e);
+static int engine_async_init(ENGINE *e);
+static int async_finish(ENGINE *e);
+void engine_load_async_int(void);
+
+
+static void async_pause_job(void);
+
+/* RSA */
+
+static int async_pub_enc(int flen, const unsigned char *from,
+                    unsigned char *to, RSA *rsa, int padding);
+static int async_pub_dec(int flen, const unsigned char *from,
+                    unsigned char *to, RSA *rsa, int padding);
+static int async_rsa_priv_enc(int flen, const unsigned char *from,
+                      unsigned char *to, RSA *rsa, int padding);
+static int async_rsa_priv_dec(int flen, const unsigned char *from,
+                      unsigned char *to, RSA *rsa, int padding);
+static int async_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+                              BN_CTX *ctx);
+
+static int async_rsa_init(RSA *rsa);
+static int async_rsa_finish(RSA *rsa);
+
+static RSA_METHOD *async_rsa_method = NULL;
+
+static int bind_async(ENGINE *e)
+{
+    /* Setup RSA_METHOD */
+    if ((async_rsa_method = RSA_meth_new("Async RSA method", 0)) == NULL
+        || RSA_meth_set_pub_enc(async_rsa_method, async_pub_enc) == 0
+        || RSA_meth_set_pub_dec(async_rsa_method, async_pub_dec) == 0
+        || RSA_meth_set_priv_enc(async_rsa_method, async_rsa_priv_enc) == 0
+        || RSA_meth_set_priv_dec(async_rsa_method, async_rsa_priv_dec) == 0
+        || RSA_meth_set_mod_exp(async_rsa_method, async_rsa_mod_exp) == 0
+        || RSA_meth_set_bn_mod_exp(async_rsa_method, BN_mod_exp_mont) == 0
+        || RSA_meth_set_init(async_rsa_method, async_rsa_init) == 0
+        || RSA_meth_set_finish(async_rsa_method, async_rsa_finish) == 0) {
+        fprintf(stderr, "Failed to initialize rsa method\n");
+        return 0;
+    }
+
+    /* Ensure the dasync error handling is set up */
+    ERR_load_ASYNC_strings();
+
+    if (!ENGINE_set_id(e, engine_id)
+        || !ENGINE_set_name(e, engine_name)
+        || !ENGINE_set_RSA(e, async_rsa_method)
+        || !ENGINE_set_destroy_function(e, async_destroy)
+        || !ENGINE_set_init_function(e, engine_async_init)
+        || !ENGINE_set_finish_function(e, async_finish)) {
+        fprintf(stderr, "Failed to initialize\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+# ifndef OPENSSL_NO_DYNAMIC_ENGINE
+static int bind_helper(ENGINE *e, const char *id)
+{
+    if (id && (strcmp(id, engine_id) != 0))
+        return 0;
+    if (!bind_async(e))
+        return 0;
+    return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN()
+    IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
+# endif
+
+static ENGINE *engine_async(void)
+{
+    ENGINE *ret = ENGINE_new();
+    if (!ret)
+        return NULL;
+    if (!bind_async(ret)) {
+        ENGINE_free(ret);
+        return NULL;
+    }
+    return ret;
+}
+
+void engine_load_async_int(void)
+{
+    ENGINE *toadd = engine_async();
+    if (!toadd)
+        return;
+    ENGINE_add(toadd);
+    ENGINE_free(toadd);
+    ERR_clear_error();
+}
+
+static int engine_async_init(ENGINE *e)
+{
+    return 1;
+}
+
+
+static int async_finish(ENGINE *e)
+{
+    return 1;
+}
+
+
+static int async_destroy(ENGINE *e)
+{
+    RSA_meth_free(async_rsa_method);
+    return 1;
+}
+
+static void wait_cleanup(ASYNC_WAIT_CTX *ctx, const void *key,
+                         OSSL_ASYNC_FD readfd, void *pvwritefd)
+{
+    OSSL_ASYNC_FD *pwritefd = (OSSL_ASYNC_FD *)pvwritefd;
+    close(readfd);
+    close(*pwritefd);
+    OPENSSL_free(pwritefd);
+}
+
+#define DUMMY_CHAR 'X'
+
+static void async_pause_job(void) {
+    ASYNC_JOB *job;
+    ASYNC_WAIT_CTX *waitctx;
+    OSSL_ASYNC_FD pipefds[2] = {0, 0};
+    OSSL_ASYNC_FD *writefd;
+    char buf = DUMMY_CHAR;
+
+    if ((job = ASYNC_get_current_job()) == NULL)
+        return;
+
+    waitctx = ASYNC_get_wait_ctx(job);
+
+    if (ASYNC_WAIT_CTX_get_fd(waitctx, engine_id, &pipefds[0],
+                              (void **)&writefd)) {
+        pipefds[1] = *writefd;
+    } else {
+        writefd = (OSSL_ASYNC_FD *)OPENSSL_malloc(sizeof(*writefd));
+        if (writefd == NULL)
+            return;
+        if (pipe(pipefds) != 0) {
+            OPENSSL_free(writefd);
+            return;
+        }
+        *writefd = pipefds[1];
+
+        if(!ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_id, pipefds[0],
+                                       writefd, wait_cleanup)) {
+            wait_cleanup(waitctx, engine_id, pipefds[0], writefd);
+            return;
+        }
+    }
+
+    /* Ignore errors - we carry on anyway */
+    ASYNC_pause_job();
+
+    /* Clear the wake signal */
+    if (read(pipefds[0], &buf, 1) < 0)
+        return;
+}
+
+void *
+delay_method(void *arg)
+{
+  int signal_fd = (intptr_t)arg;
+  sleep(5);
+  uint64_t buf = 1;
+  write(signal_fd, &buf, sizeof(buf));
+}
+
+
+void
+spawn_delay_thread()
+{
+  pthread_t thread_id;
+  OSSL_ASYNC_FD signal_fd;
+  OSSL_ASYNC_FD pipefds[2] = {0, 0};
+  ASYNC_JOB *job;
+  if ((job = ASYNC_get_current_job()) == NULL)
+      return;
+
+  ASYNC_WAIT_CTX *waitctx = ASYNC_get_wait_ctx(job);
+
+  size_t numfds;
+  if (ASYNC_WAIT_CTX_get_all_fds(waitctx, &signal_fd, &numfds) && numfds > 0) {
+  } else {
+    OSSL_ASYNC_FD pipefds[2] = {0,0};
+    OSSL_ASYNC_FD *writefd = OPENSSL_malloc(sizeof(*writefd));
+    pipe(pipefds); 
+    signal_fd = *writefd = pipefds[1];
+    ASYNC_WAIT_CTX_set_wait_fd(waitctx, engine_id, pipefds[0], writefd, wait_cleanup);
+  }
+  
+  pthread_create(&thread_id, NULL, delay_method, (void *)((intptr_t)signal_fd));
+}
+
+
+/*
+ * RSA implementation
+ */
+
+static int async_pub_enc(int flen, const unsigned char *from,
+                    unsigned char *to, RSA *rsa, int padding) {
+    return RSA_meth_get_pub_enc(RSA_PKCS1_OpenSSL())
+        (flen, from, to, rsa, padding);
+}
+
+static int async_pub_dec(int flen, const unsigned char *from,
+                    unsigned char *to, RSA *rsa, int padding) {
+    return RSA_meth_get_pub_dec(RSA_PKCS1_OpenSSL())
+        (flen, from, to, rsa, padding);
+}
+
+static int async_rsa_priv_enc(int flen, const unsigned char *from,
+                      unsigned char *to, RSA *rsa, int padding)
+{
+    //printf("async_priv_enc\n");
+    spawn_delay_thread();
+    async_pause_job();
+    return RSA_meth_get_priv_enc(RSA_PKCS1_OpenSSL())
+        (flen, from, to, rsa, padding);
+}
+
+static int async_rsa_priv_dec(int flen, const unsigned char *from,
+                      unsigned char *to, RSA *rsa, int padding)
+{
+    //printf("async_priv_dec\n");
+    spawn_delay_thread();
+    async_pause_job();
+    return RSA_meth_get_priv_dec(RSA_PKCS1_OpenSSL())
+        (flen, from, to, rsa, padding);
+}
+
+static int async_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+{
+    return RSA_meth_get_mod_exp(RSA_PKCS1_OpenSSL())(r0, I, rsa, ctx);
+}
+
+static int async_rsa_init(RSA *rsa)
+{
+    return RSA_meth_get_init(RSA_PKCS1_OpenSSL())(rsa);
+}
+static int async_rsa_finish(RSA *rsa)
+{
+    return RSA_meth_get_finish(RSA_PKCS1_OpenSSL())(rsa);
+}
+
diff --git a/contrib/openssl/load_engine.cnf b/contrib/openssl/load_engine.cnf
new file mode 100644
index 0000000..e7c5bff
--- /dev/null
+++ b/contrib/openssl/load_engine.cnf
@@ -0,0 +1,35 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+
+openssl_conf = openssl_init
+
+[openssl_init]
+
+engines = engine_section
+
+[engine_section]
+
+async = async_section
+
+[async_section]
+
+dynamic_path = /home/user/async-test.so
+
+engine_id = async-test
+
+default_algorithms = RSA
+
+init = 1
diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst
index 4ae3d88..435b256 100644
--- a/doc/admin-guide/files/records.config.en.rst
+++ b/doc/admin-guide/files/records.config.en.rst
@@ -3420,6 +3420,20 @@ Client-Related Configuration
 
    Enables (``1``) or disables (``0``) TLSv1_2 in the ATS client context. If not specified, enabled by default
 
+.. ts:cv:: CONFIG proxy.config.ssl.async.handshake.enabled INT 0
+
+   Enables the use of openssl async job during the TLS handshake.  Traffic
+   Server must be build against openssl 1.1 or greater or this to take affect.
+   Can be useful if using a crypto engine that communicates off chip.  The
+   thread will be rescheduled for other work until the crypto engine operation
+   completes. A test crypto engine that inserts a 5 second delay on private key
+   operations can be found at :ts:git:`contrib/openssl/async_engine.c`.
+   
+.. ts:cv:: CONFIG proxy.config.ssl.engine.conf_file STRING NULL
+
+   Specify the location of the openssl config file used to load dynamic crypto
+   engines. This setting assumes an absolute path.  An example config file is at
+   :ts:git:`contrib/openssl/load_engine.cnf`.
 
 OCSP Stapling Configuration
 ===========================
diff --git a/iocore/net/P_SSLConfig.h b/iocore/net/P_SSLConfig.h
index 8dee6c8..8ceac41 100644
--- a/iocore/net/P_SSLConfig.h
+++ b/iocore/net/P_SSLConfig.h
@@ -112,6 +112,9 @@ struct SSLConfigParams : public ConfigInfo {
   static init_ssl_ctx_func init_ssl_ctx_cb;
   static load_ssl_file_func load_ssl_file_cb;
 
+  static int async_handshake_enabled;
+  static char *engine_conf_file;
+
   SSL_CTX *client_ctx;
 
   mutable HashMap<cchar *, class StringHashFns, SSL_CTX *> ctx_map;
diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h
index 94f14b1..ac1cd51 100644
--- a/iocore/net/P_SSLNetVConnection.h
+++ b/iocore/net/P_SSLNetVConnection.h
@@ -352,6 +352,9 @@ private:
   SessionAccept *sessionAcceptPtr  = nullptr;
   bool sslTrace                    = false;
   bool SNIMapping                  = false;
+#ifdef SSL_MODE_ASYNC
+  EventIO signalep;
+#endif
 };
 
 typedef int (SSLNetVConnection::*SSLNetVConnHandler)(int, void *);
diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc
index 6918c8e..a6ad219 100644
--- a/iocore/net/SSLConfig.cc
+++ b/iocore/net/SSLConfig.cc
@@ -64,6 +64,8 @@ char *SSLConfigParams::ssl_wire_trace_addr        = nullptr;
 IpAddr *SSLConfigParams::ssl_wire_trace_ip        = nullptr;
 int SSLConfigParams::ssl_wire_trace_percentage    = 0;
 char *SSLConfigParams::ssl_wire_trace_server_name = nullptr;
+int SSLConfigParams::async_handshake_enabled      = 0;
+char *SSLConfigParams::engine_conf_file           = nullptr;
 
 static ConfigUpdateHandler<SSLCertificateConfig> *sslCertUpdate;
 
@@ -299,7 +301,8 @@ SSLConfigParams::initialize()
   REC_EstablishStaticConfigInt32(ssl_ocsp_request_timeout, "proxy.config.ssl.ocsp.request_timeout");
   REC_EstablishStaticConfigInt32(ssl_ocsp_update_period, "proxy.config.ssl.ocsp.update_period");
 
-  REC_ReadConfigInt32(ssl_handshake_timeout_in, "proxy.config.ssl.handshake_timeout_in");
+  REC_ReadConfigInt32(async_handshake_enabled, "proxy.config.ssl.async.handshake.enabled");
+  REC_ReadConfigStringAlloc(engine_conf_file, "proxy.config.ssl.engine.conf_file");
 
   // ++++++++++++++++++++++++ Client part ++++++++++++++++++++
   client_verify_depth = 7;
diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index 6a04822..0bd0bc3 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -37,6 +37,9 @@
 #include <climits>
 #include <string>
 #include <stdbool.h>
+#if TS_USE_TLS_ASYNC
+#include <openssl/async.h>
+#endif
 
 #if !TS_USE_SET_RBIO
 // Defined in SSLInternal.c, should probably make a separate include
@@ -1104,8 +1107,34 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err)
     } // Still data in the BIO
   }
 
+#if TS_USE_TLS_ASYNC
+  if (SSLConfigParams::async_handshake_enabled) {
+    SSL_set_mode(ssl, SSL_MODE_ASYNC);
+  }
+#endif
   ssl_error_t ssl_error = SSLAccept(ssl);
-  bool trace            = getSSLTrace();
+#if TS_USE_TLS_ASYNC
+  if (ssl_error == SSL_ERROR_WANT_ASYNC && this->signalep.type == 0) {
+    size_t numfds;
+    OSSL_ASYNC_FD waitfd;
+    // Set up the epoll entry for the signalling
+    if (SSL_get_all_async_fds(ssl, &waitfd, &numfds) && numfds > 0) {
+      PollDescriptor *pd = get_PollDescriptor(this_ethread());
+      this->signalep.start(pd, waitfd, this, EVENTIO_READ);
+      this->signalep.type = EVENTIO_READWRITE_VC;
+    }
+  } else
+#endif
+    if (ssl_error == SSL_ERROR_NONE || ssl_error == SSL_ERROR_SSL) {
+#if TS_USE_TLS_ASYNC
+    if (SSLConfigParams::async_handshake_enabled) {
+      // Clean up the epoll entry for signalling
+      SSL_clear_mode(ssl, SSL_MODE_ASYNC);
+      this->signalep.stop();
+    }
+#endif
+  }
+  bool trace = getSSLTrace();
 
   if (ssl_error != SSL_ERROR_NONE) {
     err = errno;
@@ -1224,6 +1253,12 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err)
     }
 #endif
 
+#if TS_USE_TLS_ASYNC
+  case SSL_ERROR_WANT_ASYNC:
+    TraceIn(trace, get_remote_addr(), get_remote_port(), "SSL server handshake ERROR_WANT_ASYNC");
+    return EVENT_CONT;
+#endif
+
   case SSL_ERROR_WANT_ACCEPT:
     TraceIn(trace, get_remote_addr(), get_remote_port(), "SSL server handshake ERROR_WANT_ACCEPT");
     return EVENT_CONT;
diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc
index 74dd5c9..ff447dd 100644
--- a/iocore/net/SSLUtils.cc
+++ b/iocore/net/SSLUtils.cc
@@ -40,6 +40,8 @@
 #include <openssl/rand.h>
 #include <openssl/dh.h>
 #include <openssl/bn.h>
+#include <openssl/engine.h>
+#include <openssl/conf.h>
 #include <unistd.h>
 #include <termios.h>
 #include <vector>
@@ -894,6 +896,22 @@ SSLInitializeLibrary()
     SSL_load_error_strings();
     SSL_library_init();
 
+#if TS_USE_TLS_ASYNC
+    if (SSLConfigParams::async_handshake_enabled) {
+      ASYNC_init_thread(0, 0);
+    }
+#endif
+
+    if (SSLConfigParams::engine_conf_file) {
+      ENGINE_load_dynamic();
+
+      OPENSSL_load_builtin_modules();
+      if (CONF_modules_load_file(SSLConfigParams::engine_conf_file, nullptr, 0) <= 0) {
+        Error("FATAL: error loading engine configuration file %s", SSLConfigParams::engine_conf_file);
+        // ERR_print_errors_fp(stderr);
+      }
+    }
+
 #ifdef OPENSSL_FIPS
     // calling FIPS_mode_set() will force FIPS to POST (Power On Self Test)
     // After POST we don't have to lock for FIPS
diff --git a/lib/ts/ink_config.h.in b/lib/ts/ink_config.h.in
index 037b619..664bd3b 100644
--- a/lib/ts/ink_config.h.in
+++ b/lib/ts/ink_config.h.in
@@ -71,6 +71,7 @@
 #define TS_USE_HWLOC @use_hwloc@
 #define TS_USE_TLS_NPN @use_tls_npn@
 #define TS_USE_TLS_ALPN @use_tls_alpn@
+#define TS_USE_TLS_ASYNC @use_tls_async@
 #define TS_USE_CERT_CB @use_cert_cb@
 #define TS_USE_SET_RBIO @use_set_rbio@
 #define TS_USE_GET_DH_2048_256 @use_dh_get_2048_256@
diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc
index 50815e2..a340fe2 100644
--- a/mgmt/RecordsConfig.cc
+++ b/mgmt/RecordsConfig.cc
@@ -1353,6 +1353,9 @@ static const RecordElement RecordsConfig[] =
   //###########
   {RECT_CONFIG, "proxy.config.cache.http.compatibility.4-2-0-fixup", RECD_INT, "1", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL},
 
+  // Controls for TLS ASYN_JOBS and engine loading
+  {RECT_CONFIG, "proxy.config.ssl.async.handshake.enabled", RECD_INT, "0", RECU_RESTART_TS, RR_NULL, RECC_NULL, "[0-1]", RECA_NULL},
+  {RECT_CONFIG, "proxy.config.ssl.engine.conf_file", RECD_STRING, nullptr, RECU_NULL, RR_NULL, RECC_NULL, nullptr, RECA_NULL},
 };
 // clang-format on
 

-- 
To stop receiving notification emails like this one, please contact
shinrich@apache.org.