[T106][ZXW-22]7520V3SCV2.01.01.02P42U09_VEC_V0.8_AP_VEC origin source commit

Change-Id: Ic6e05d89ecd62fc34f82b23dcf306c93764aec4b
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_null.c b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_null.c
new file mode 100644
index 0000000..26801f8
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_null.c
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This must be the first #include file */
+#include "../async_local.h"
+
+#ifdef ASYNC_NULL
+int ASYNC_is_capable(void)
+{
+    return 0;
+}
+
+void async_local_cleanup(void)
+{
+}
+#endif
+
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_null.h b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_null.h
new file mode 100644
index 0000000..aef40b5
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_null.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/async.h>
+
+/*
+ * If we haven't managed to detect any other async architecture then we default
+ * to NULL.
+ */
+#ifndef ASYNC_ARCH
+# define ASYNC_NULL
+# define ASYNC_ARCH
+
+typedef struct async_fibre_st {
+    int dummy;
+} async_fibre;
+
+
+# define async_fibre_swapcontext(o,n,r)         0
+# define async_fibre_makecontext(c)             0
+# define async_fibre_free(f)
+# define async_fibre_init_dispatcher(f)
+
+#endif
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_posix.c b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_posix.c
new file mode 100644
index 0000000..95678d4
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_posix.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This must be the first #include file */
+#include "../async_local.h"
+
+#ifdef ASYNC_POSIX
+
+# include <stddef.h>
+# include <unistd.h>
+
+#define STACKSIZE       32768
+
+int ASYNC_is_capable(void)
+{
+    ucontext_t ctx;
+
+    /*
+     * Some platforms provide getcontext() but it does not work (notably
+     * MacOSX PPC64). Check for a working getcontext();
+     */
+    return getcontext(&ctx) == 0;
+}
+
+void async_local_cleanup(void)
+{
+}
+
+int async_fibre_makecontext(async_fibre *fibre)
+{
+    fibre->env_init = 0;
+    if (getcontext(&fibre->fibre) == 0) {
+        fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE);
+        if (fibre->fibre.uc_stack.ss_sp != NULL) {
+            fibre->fibre.uc_stack.ss_size = STACKSIZE;
+            fibre->fibre.uc_link = NULL;
+            makecontext(&fibre->fibre, async_start_func, 0);
+            return 1;
+        }
+    } else {
+        fibre->fibre.uc_stack.ss_sp = NULL;
+    }
+    return 0;
+}
+
+void async_fibre_free(async_fibre *fibre)
+{
+    OPENSSL_free(fibre->fibre.uc_stack.ss_sp);
+    fibre->fibre.uc_stack.ss_sp = NULL;
+}
+
+#endif
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_posix.h b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_posix.h
new file mode 100644
index 0000000..873c031
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_posix.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_CRYPTO_ASYNC_POSIX_H
+#define OSSL_CRYPTO_ASYNC_POSIX_H
+#include <openssl/e_os2.h>
+
+#if defined(OPENSSL_SYS_UNIX) \
+    && defined(OPENSSL_THREADS) && !defined(OPENSSL_NO_ASYNC) \
+    && !defined(__ANDROID__) && !defined(__OpenBSD__)
+
+# include <unistd.h>
+
+# if _POSIX_VERSION >= 200112L \
+     && (_POSIX_VERSION < 200809L || defined(__GLIBC__))
+
+# include <pthread.h>
+
+#  define ASYNC_POSIX
+#  define ASYNC_ARCH
+
+#  include <ucontext.h>
+#  include <setjmp.h>
+
+typedef struct async_fibre_st {
+    ucontext_t fibre;
+    jmp_buf env;
+    int env_init;
+} async_fibre;
+
+static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r)
+{
+    o->env_init = 1;
+
+    if (!r || !_setjmp(o->env)) {
+        if (n->env_init)
+            _longjmp(n->env, 1);
+        else
+            setcontext(&n->fibre);
+    }
+
+    return 1;
+}
+
+#  define async_fibre_init_dispatcher(d)
+
+int async_fibre_makecontext(async_fibre *fibre);
+void async_fibre_free(async_fibre *fibre);
+
+# endif
+#endif
+#endif /* OSSL_CRYPTO_ASYNC_POSIX_H */
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_win.c b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_win.c
new file mode 100644
index 0000000..1f360d8
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_win.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This must be the first #include file */
+#include "../async_local.h"
+
+#ifdef ASYNC_WIN
+
+# include <windows.h>
+# include "internal/cryptlib.h"
+
+int ASYNC_is_capable(void)
+{
+    return 1;
+}
+
+void async_local_cleanup(void)
+{
+    async_ctx *ctx = async_get_ctx();
+    if (ctx != NULL) {
+        async_fibre *fibre = &ctx->dispatcher;
+        if (fibre != NULL && fibre->fibre != NULL && fibre->converted) {
+            ConvertFiberToThread();
+            fibre->fibre = NULL;
+        }
+    }
+}
+
+int async_fibre_init_dispatcher(async_fibre *fibre)
+{
+    fibre->fibre = ConvertThreadToFiber(NULL);
+    if (fibre->fibre == NULL) {
+        fibre->converted = 0;
+        fibre->fibre = GetCurrentFiber();
+        if (fibre->fibre == NULL)
+            return 0;
+    } else {
+        fibre->converted = 1;
+    }
+
+    return 1;
+}
+
+VOID CALLBACK async_start_func_win(PVOID unused)
+{
+    async_start_func();
+}
+
+#endif
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_win.h b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_win.h
new file mode 100644
index 0000000..61cfdd7
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/arch/async_win.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * This is the same detection used in cryptlib to set up the thread local
+ * storage that we depend on, so just copy that
+ */
+#if defined(_WIN32) && !defined(OPENSSL_NO_ASYNC)
+#include <openssl/async.h>
+# define ASYNC_WIN
+# define ASYNC_ARCH
+
+# include <windows.h>
+# include "internal/cryptlib.h"
+
+typedef struct async_fibre_st {
+    LPVOID fibre;
+    int converted;
+} async_fibre;
+
+# define async_fibre_swapcontext(o,n,r) \
+        (SwitchToFiber((n)->fibre), 1)
+# define async_fibre_makecontext(c) \
+        ((c)->fibre = CreateFiber(0, async_start_func_win, 0))
+# define async_fibre_free(f)             (DeleteFiber((f)->fibre))
+
+int async_fibre_init_dispatcher(async_fibre *fibre);
+VOID CALLBACK async_start_func_win(PVOID unused);
+
+#endif
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/async.c b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async.c
new file mode 100644
index 0000000..326015c
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async.c
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Without this we start getting longjmp crashes because it thinks we're jumping
+ * up the stack when in fact we are jumping to an entirely different stack. The
+ * cost of this is not having certain buffer overrun/underrun checks etc for
+ * this source file :-(
+ */
+#undef _FORTIFY_SOURCE
+
+/* This must be the first #include file */
+#include "async_local.h"
+
+#include <openssl/err.h>
+#include "crypto/cryptlib.h"
+#include <string.h>
+
+#define ASYNC_JOB_RUNNING   0
+#define ASYNC_JOB_PAUSING   1
+#define ASYNC_JOB_PAUSED    2
+#define ASYNC_JOB_STOPPING  3
+
+static CRYPTO_THREAD_LOCAL ctxkey;
+static CRYPTO_THREAD_LOCAL poolkey;
+
+static async_ctx *async_ctx_new(void)
+{
+    async_ctx *nctx;
+
+    if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC))
+        return NULL;
+
+    nctx = OPENSSL_malloc(sizeof(*nctx));
+    if (nctx == NULL) {
+        ASYNCerr(ASYNC_F_ASYNC_CTX_NEW, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+
+    async_fibre_init_dispatcher(&nctx->dispatcher);
+    nctx->currjob = NULL;
+    nctx->blocked = 0;
+    if (!CRYPTO_THREAD_set_local(&ctxkey, nctx))
+        goto err;
+
+    return nctx;
+err:
+    OPENSSL_free(nctx);
+
+    return NULL;
+}
+
+async_ctx *async_get_ctx(void)
+{
+    return (async_ctx *)CRYPTO_THREAD_get_local(&ctxkey);
+}
+
+static int async_ctx_free(void)
+{
+    async_ctx *ctx;
+
+    ctx = async_get_ctx();
+
+    if (!CRYPTO_THREAD_set_local(&ctxkey, NULL))
+        return 0;
+
+    OPENSSL_free(ctx);
+
+    return 1;
+}
+
+static ASYNC_JOB *async_job_new(void)
+{
+    ASYNC_JOB *job = NULL;
+
+    job = OPENSSL_zalloc(sizeof(*job));
+    if (job == NULL) {
+        ASYNCerr(ASYNC_F_ASYNC_JOB_NEW, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+
+    job->status = ASYNC_JOB_RUNNING;
+
+    return job;
+}
+
+static void async_job_free(ASYNC_JOB *job)
+{
+    if (job != NULL) {
+        OPENSSL_free(job->funcargs);
+        async_fibre_free(&job->fibrectx);
+        OPENSSL_free(job);
+    }
+}
+
+static ASYNC_JOB *async_get_pool_job(void) {
+    ASYNC_JOB *job;
+    async_pool *pool;
+
+    pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
+    if (pool == NULL) {
+        /*
+         * Pool has not been initialised, so init with the defaults, i.e.
+         * no max size and no pre-created jobs
+         */
+        if (ASYNC_init_thread(0, 0) == 0)
+            return NULL;
+        pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
+    }
+
+    job = sk_ASYNC_JOB_pop(pool->jobs);
+    if (job == NULL) {
+        /* Pool is empty */
+        if ((pool->max_size != 0) && (pool->curr_size >= pool->max_size))
+            return NULL;
+
+        job = async_job_new();
+        if (job != NULL) {
+            if (! async_fibre_makecontext(&job->fibrectx)) {
+                async_job_free(job);
+                return NULL;
+            }
+            pool->curr_size++;
+        }
+    }
+    return job;
+}
+
+static void async_release_job(ASYNC_JOB *job) {
+    async_pool *pool;
+
+    pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
+    OPENSSL_free(job->funcargs);
+    job->funcargs = NULL;
+    sk_ASYNC_JOB_push(pool->jobs, job);
+}
+
+void async_start_func(void)
+{
+    ASYNC_JOB *job;
+    async_ctx *ctx = async_get_ctx();
+
+    while (1) {
+        /* Run the job */
+        job = ctx->currjob;
+        job->ret = job->func(job->funcargs);
+
+        /* Stop the job */
+        job->status = ASYNC_JOB_STOPPING;
+        if (!async_fibre_swapcontext(&job->fibrectx,
+                                     &ctx->dispatcher, 1)) {
+            /*
+             * Should not happen. Getting here will close the thread...can't do
+             * much about it
+             */
+            ASYNCerr(ASYNC_F_ASYNC_START_FUNC, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+        }
+    }
+}
+
+int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret,
+                    int (*func)(void *), void *args, size_t size)
+{
+    async_ctx *ctx;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
+        return ASYNC_ERR;
+
+    ctx = async_get_ctx();
+    if (ctx == NULL)
+        ctx = async_ctx_new();
+    if (ctx == NULL)
+        return ASYNC_ERR;
+
+    if (*job)
+        ctx->currjob = *job;
+
+    for (;;) {
+        if (ctx->currjob != NULL) {
+            if (ctx->currjob->status == ASYNC_JOB_STOPPING) {
+                *ret = ctx->currjob->ret;
+                ctx->currjob->waitctx = NULL;
+                async_release_job(ctx->currjob);
+                ctx->currjob = NULL;
+                *job = NULL;
+                return ASYNC_FINISH;
+            }
+
+            if (ctx->currjob->status == ASYNC_JOB_PAUSING) {
+                *job = ctx->currjob;
+                ctx->currjob->status = ASYNC_JOB_PAUSED;
+                ctx->currjob = NULL;
+                return ASYNC_PAUSE;
+            }
+
+            if (ctx->currjob->status == ASYNC_JOB_PAUSED) {
+                ctx->currjob = *job;
+                /* Resume previous job */
+                if (!async_fibre_swapcontext(&ctx->dispatcher,
+                        &ctx->currjob->fibrectx, 1)) {
+                    ASYNCerr(ASYNC_F_ASYNC_START_JOB,
+                             ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+                    goto err;
+                }
+                continue;
+            }
+
+            /* Should not happen */
+            ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_INTERNAL_ERROR);
+            async_release_job(ctx->currjob);
+            ctx->currjob = NULL;
+            *job = NULL;
+            return ASYNC_ERR;
+        }
+
+        /* Start a new job */
+        if ((ctx->currjob = async_get_pool_job()) == NULL)
+            return ASYNC_NO_JOBS;
+
+        if (args != NULL) {
+            ctx->currjob->funcargs = OPENSSL_malloc(size);
+            if (ctx->currjob->funcargs == NULL) {
+                ASYNCerr(ASYNC_F_ASYNC_START_JOB, ERR_R_MALLOC_FAILURE);
+                async_release_job(ctx->currjob);
+                ctx->currjob = NULL;
+                return ASYNC_ERR;
+            }
+            memcpy(ctx->currjob->funcargs, args, size);
+        } else {
+            ctx->currjob->funcargs = NULL;
+        }
+
+        ctx->currjob->func = func;
+        ctx->currjob->waitctx = wctx;
+        if (!async_fibre_swapcontext(&ctx->dispatcher,
+                &ctx->currjob->fibrectx, 1)) {
+            ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+            goto err;
+        }
+    }
+
+err:
+    async_release_job(ctx->currjob);
+    ctx->currjob = NULL;
+    *job = NULL;
+    return ASYNC_ERR;
+}
+
+int ASYNC_pause_job(void)
+{
+    ASYNC_JOB *job;
+    async_ctx *ctx = async_get_ctx();
+
+    if (ctx == NULL
+            || ctx->currjob == NULL
+            || ctx->blocked) {
+        /*
+         * Could be we've deliberately not been started within a job so this is
+         * counted as success.
+         */
+        return 1;
+    }
+
+    job = ctx->currjob;
+    job->status = ASYNC_JOB_PAUSING;
+
+    if (!async_fibre_swapcontext(&job->fibrectx,
+                                 &ctx->dispatcher, 1)) {
+        ASYNCerr(ASYNC_F_ASYNC_PAUSE_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT);
+        return 0;
+    }
+    /* Reset counts of added and deleted fds */
+    async_wait_ctx_reset_counts(job->waitctx);
+
+    return 1;
+}
+
+static void async_empty_pool(async_pool *pool)
+{
+    ASYNC_JOB *job;
+
+    if (!pool || !pool->jobs)
+        return;
+
+    do {
+        job = sk_ASYNC_JOB_pop(pool->jobs);
+        async_job_free(job);
+    } while (job);
+}
+
+int async_init(void)
+{
+    if (!CRYPTO_THREAD_init_local(&ctxkey, NULL))
+        return 0;
+
+    if (!CRYPTO_THREAD_init_local(&poolkey, NULL)) {
+        CRYPTO_THREAD_cleanup_local(&ctxkey);
+        return 0;
+    }
+
+    return 1;
+}
+
+void async_deinit(void)
+{
+    CRYPTO_THREAD_cleanup_local(&ctxkey);
+    CRYPTO_THREAD_cleanup_local(&poolkey);
+}
+
+int ASYNC_init_thread(size_t max_size, size_t init_size)
+{
+    async_pool *pool;
+    size_t curr_size = 0;
+
+    if (init_size > max_size) {
+        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_INVALID_POOL_SIZE);
+        return 0;
+    }
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
+        return 0;
+
+    if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ASYNC))
+        return 0;
+
+    pool = OPENSSL_zalloc(sizeof(*pool));
+    if (pool == NULL) {
+        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    pool->jobs = sk_ASYNC_JOB_new_reserve(NULL, init_size);
+    if (pool->jobs == NULL) {
+        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ERR_R_MALLOC_FAILURE);
+        OPENSSL_free(pool);
+        return 0;
+    }
+
+    pool->max_size = max_size;
+
+    /* Pre-create jobs as required */
+    while (init_size--) {
+        ASYNC_JOB *job;
+        job = async_job_new();
+        if (job == NULL || !async_fibre_makecontext(&job->fibrectx)) {
+            /*
+             * Not actually fatal because we already created the pool, just
+             * skip creation of any more jobs
+             */
+            async_job_free(job);
+            break;
+        }
+        job->funcargs = NULL;
+        sk_ASYNC_JOB_push(pool->jobs, job); /* Cannot fail due to reserve */
+        curr_size++;
+    }
+    pool->curr_size = curr_size;
+    if (!CRYPTO_THREAD_set_local(&poolkey, pool)) {
+        ASYNCerr(ASYNC_F_ASYNC_INIT_THREAD, ASYNC_R_FAILED_TO_SET_POOL);
+        goto err;
+    }
+
+    return 1;
+err:
+    async_empty_pool(pool);
+    sk_ASYNC_JOB_free(pool->jobs);
+    OPENSSL_free(pool);
+    return 0;
+}
+
+void async_delete_thread_state(void)
+{
+    async_pool *pool = (async_pool *)CRYPTO_THREAD_get_local(&poolkey);
+
+    if (pool != NULL) {
+        async_empty_pool(pool);
+        sk_ASYNC_JOB_free(pool->jobs);
+        OPENSSL_free(pool);
+        CRYPTO_THREAD_set_local(&poolkey, NULL);
+    }
+    async_local_cleanup();
+    async_ctx_free();
+}
+
+void ASYNC_cleanup_thread(void)
+{
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
+        return;
+
+    async_delete_thread_state();
+}
+
+ASYNC_JOB *ASYNC_get_current_job(void)
+{
+    async_ctx *ctx;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
+        return NULL;
+
+    ctx = async_get_ctx();
+    if (ctx == NULL)
+        return NULL;
+
+    return ctx->currjob;
+}
+
+ASYNC_WAIT_CTX *ASYNC_get_wait_ctx(ASYNC_JOB *job)
+{
+    return job->waitctx;
+}
+
+void ASYNC_block_pause(void)
+{
+    async_ctx *ctx;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
+        return;
+
+    ctx = async_get_ctx();
+    if (ctx == NULL || ctx->currjob == NULL) {
+        /*
+         * We're not in a job anyway so ignore this
+         */
+        return;
+    }
+    ctx->blocked++;
+}
+
+void ASYNC_unblock_pause(void)
+{
+    async_ctx *ctx;
+
+    if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL))
+        return;
+
+    ctx = async_get_ctx();
+    if (ctx == NULL || ctx->currjob == NULL) {
+        /*
+         * We're not in a job anyway so ignore this
+         */
+        return;
+    }
+    if (ctx->blocked > 0)
+        ctx->blocked--;
+}
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_err.c b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_err.c
new file mode 100644
index 0000000..fd5527a
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_err.c
@@ -0,0 +1,51 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/err.h>
+#include <openssl/asyncerr.h>
+
+#ifndef OPENSSL_NO_ERR
+
+static const ERR_STRING_DATA ASYNC_str_functs[] = {
+    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_CTX_NEW, 0), "async_ctx_new"},
+    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_INIT_THREAD, 0),
+     "ASYNC_init_thread"},
+    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_JOB_NEW, 0), "async_job_new"},
+    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_PAUSE_JOB, 0), "ASYNC_pause_job"},
+    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_FUNC, 0), "async_start_func"},
+    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_START_JOB, 0), "ASYNC_start_job"},
+    {ERR_PACK(ERR_LIB_ASYNC, ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, 0),
+     "ASYNC_WAIT_CTX_set_wait_fd"},
+    {0, NULL}
+};
+
+static const ERR_STRING_DATA ASYNC_str_reasons[] = {
+    {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_FAILED_TO_SET_POOL),
+    "failed to set pool"},
+    {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_FAILED_TO_SWAP_CONTEXT),
+    "failed to swap context"},
+    {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_INIT_FAILED), "init failed"},
+    {ERR_PACK(ERR_LIB_ASYNC, 0, ASYNC_R_INVALID_POOL_SIZE),
+    "invalid pool size"},
+    {0, NULL}
+};
+
+#endif
+
+int ERR_load_ASYNC_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+    if (ERR_func_error_string(ASYNC_str_functs[0].error) == NULL) {
+        ERR_load_strings_const(ASYNC_str_functs);
+        ERR_load_strings_const(ASYNC_str_reasons);
+    }
+#endif
+    return 1;
+}
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_local.h b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_local.h
new file mode 100644
index 0000000..dd1a85e
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_local.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * Must do this before including any header files, because on MacOS/X <stlib.h>
+ * includes <signal.h> which includes <ucontext.h>
+ */
+#if defined(__APPLE__) && defined(__MACH__) && !defined(_XOPEN_SOURCE)
+# define _XOPEN_SOURCE          /* Otherwise incomplete ucontext_t structure */
+# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
+#if defined(_WIN32)
+# include <windows.h>
+#endif
+
+#include "crypto/async.h"
+#include <openssl/crypto.h>
+
+typedef struct async_ctx_st async_ctx;
+typedef struct async_pool_st async_pool;
+
+#include "arch/async_win.h"
+#include "arch/async_posix.h"
+#include "arch/async_null.h"
+
+struct async_ctx_st {
+    async_fibre dispatcher;
+    ASYNC_JOB *currjob;
+    unsigned int blocked;
+};
+
+struct async_job_st {
+    async_fibre fibrectx;
+    int (*func) (void *);
+    void *funcargs;
+    int ret;
+    int status;
+    ASYNC_WAIT_CTX *waitctx;
+};
+
+struct fd_lookup_st {
+    const void *key;
+    OSSL_ASYNC_FD fd;
+    void *custom_data;
+    void (*cleanup)(ASYNC_WAIT_CTX *, const void *, OSSL_ASYNC_FD, void *);
+    int add;
+    int del;
+    struct fd_lookup_st *next;
+};
+
+struct async_wait_ctx_st {
+    struct fd_lookup_st *fds;
+    size_t numadd;
+    size_t numdel;
+};
+
+DEFINE_STACK_OF(ASYNC_JOB)
+
+struct async_pool_st {
+    STACK_OF(ASYNC_JOB) *jobs;
+    size_t curr_size;
+    size_t max_size;
+};
+
+void async_local_cleanup(void);
+void async_start_func(void);
+async_ctx *async_get_ctx(void);
+
+void async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx);
+
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_wait.c b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_wait.c
new file mode 100644
index 0000000..7723f94
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/async_wait.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/* This must be the first #include file */
+#include "async_local.h"
+
+#include <openssl/err.h>
+
+ASYNC_WAIT_CTX *ASYNC_WAIT_CTX_new(void)
+{
+    return OPENSSL_zalloc(sizeof(ASYNC_WAIT_CTX));
+}
+
+void ASYNC_WAIT_CTX_free(ASYNC_WAIT_CTX *ctx)
+{
+    struct fd_lookup_st *curr;
+    struct fd_lookup_st *next;
+
+    if (ctx == NULL)
+        return;
+
+    curr = ctx->fds;
+    while (curr != NULL) {
+        if (!curr->del) {
+            /* Only try and cleanup if it hasn't been marked deleted */
+            if (curr->cleanup != NULL)
+                curr->cleanup(ctx, curr->key, curr->fd, curr->custom_data);
+        }
+        /* Always free the fd_lookup_st */
+        next = curr->next;
+        OPENSSL_free(curr);
+        curr = next;
+    }
+
+    OPENSSL_free(ctx);
+}
+int ASYNC_WAIT_CTX_set_wait_fd(ASYNC_WAIT_CTX *ctx, const void *key,
+                               OSSL_ASYNC_FD fd, void *custom_data,
+                               void (*cleanup)(ASYNC_WAIT_CTX *, const void *,
+                                               OSSL_ASYNC_FD, void *))
+{
+    struct fd_lookup_st *fdlookup;
+
+    if ((fdlookup = OPENSSL_zalloc(sizeof(*fdlookup))) == NULL) {
+        ASYNCerr(ASYNC_F_ASYNC_WAIT_CTX_SET_WAIT_FD, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+
+    fdlookup->key = key;
+    fdlookup->fd = fd;
+    fdlookup->custom_data = custom_data;
+    fdlookup->cleanup = cleanup;
+    fdlookup->add = 1;
+    fdlookup->next = ctx->fds;
+    ctx->fds = fdlookup;
+    ctx->numadd++;
+    return 1;
+}
+
+int ASYNC_WAIT_CTX_get_fd(ASYNC_WAIT_CTX *ctx, const void *key,
+                          OSSL_ASYNC_FD *fd, void **custom_data)
+{
+    struct fd_lookup_st *curr;
+
+    curr = ctx->fds;
+    while (curr != NULL) {
+        if (curr->del) {
+            /* This one has been marked deleted so do nothing */
+            curr = curr->next;
+            continue;
+        }
+        if (curr->key == key) {
+            *fd = curr->fd;
+            *custom_data = curr->custom_data;
+            return 1;
+        }
+        curr = curr->next;
+    }
+    return 0;
+}
+
+int ASYNC_WAIT_CTX_get_all_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *fd,
+                               size_t *numfds)
+{
+    struct fd_lookup_st *curr;
+
+    curr = ctx->fds;
+    *numfds = 0;
+    while (curr != NULL) {
+        if (curr->del) {
+            /* This one has been marked deleted so do nothing */
+            curr = curr->next;
+            continue;
+        }
+        if (fd != NULL) {
+            *fd = curr->fd;
+            fd++;
+        }
+        (*numfds)++;
+        curr = curr->next;
+    }
+    return 1;
+}
+
+int ASYNC_WAIT_CTX_get_changed_fds(ASYNC_WAIT_CTX *ctx, OSSL_ASYNC_FD *addfd,
+                                   size_t *numaddfds, OSSL_ASYNC_FD *delfd,
+                                   size_t *numdelfds)
+{
+    struct fd_lookup_st *curr;
+
+    *numaddfds = ctx->numadd;
+    *numdelfds = ctx->numdel;
+    if (addfd == NULL && delfd == NULL)
+        return 1;
+
+    curr = ctx->fds;
+
+    while (curr != NULL) {
+        /* We ignore fds that have been marked as both added and deleted */
+        if (curr->del && !curr->add && (delfd != NULL)) {
+            *delfd = curr->fd;
+            delfd++;
+        }
+        if (curr->add && !curr->del && (addfd != NULL)) {
+            *addfd = curr->fd;
+            addfd++;
+        }
+        curr = curr->next;
+    }
+
+    return 1;
+}
+
+int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key)
+{
+    struct fd_lookup_st *curr, *prev;
+
+    curr = ctx->fds;
+    prev = NULL;
+    while (curr != NULL) {
+        if (curr->del == 1) {
+            /* This one has been marked deleted already so do nothing */
+            prev = curr;
+            curr = curr->next;
+            continue;
+        }
+        if (curr->key == key) {
+            /* If fd has just been added, remove it from the list */
+            if (curr->add == 1) {
+                if (ctx->fds == curr) {
+                    ctx->fds = curr->next;
+                } else {
+                    prev->next = curr->next;
+                }
+
+                /* It is responsibility of the caller to cleanup before calling
+                 * ASYNC_WAIT_CTX_clear_fd
+                 */
+                OPENSSL_free(curr);
+                ctx->numadd--;
+                return 1;
+            }
+
+            /*
+             * Mark it as deleted. We don't call cleanup if explicitly asked
+             * to clear an fd. We assume the caller is going to do that (if
+             * appropriate).
+             */
+            curr->del = 1;
+            ctx->numdel++;
+            return 1;
+        }
+        prev = curr;
+        curr = curr->next;
+    }
+    return 0;
+}
+
+void async_wait_ctx_reset_counts(ASYNC_WAIT_CTX *ctx)
+{
+    struct fd_lookup_st *curr, *prev = NULL;
+
+    ctx->numadd = 0;
+    ctx->numdel = 0;
+
+    curr = ctx->fds;
+
+    while (curr != NULL) {
+        if (curr->del) {
+            if (prev == NULL)
+                ctx->fds = curr->next;
+            else
+                prev->next = curr->next;
+            OPENSSL_free(curr);
+            if (prev == NULL)
+                curr = ctx->fds;
+            else
+                curr = prev->next;
+            continue;
+        }
+        if (curr->add) {
+            curr->add = 0;
+        }
+        prev = curr;
+        curr = curr->next;
+    }
+}
diff --git a/ap/lib/libssl/openssl-1.1.1o/crypto/async/build.info b/ap/lib/libssl/openssl-1.1.1o/crypto/async/build.info
new file mode 100644
index 0000000..278e3e9
--- /dev/null
+++ b/ap/lib/libssl/openssl-1.1.1o/crypto/async/build.info
@@ -0,0 +1,4 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=\
+        async.c async_wait.c async_err.c arch/async_posix.c arch/async_win.c \
+        arch/async_null.c