aboutsummaryrefslogtreecommitdiff
path: root/openssl-1.1.0h/crypto/engine
diff options
context:
space:
mode:
Diffstat (limited to 'openssl-1.1.0h/crypto/engine')
-rw-r--r--openssl-1.1.0h/crypto/engine/README211
-rw-r--r--openssl-1.1.0h/crypto/engine/build.info8
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_all.c31
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_cnf.c192
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_cryptodev.c1757
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_ctrl.c338
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_dyn.c510
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_err.c123
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_fat.c128
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_init.c108
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_int.h183
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_lib.c290
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_list.c354
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_openssl.c652
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_pkey.c140
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_rdrand.c110
-rw-r--r--openssl-1.1.0h/crypto/engine/eng_table.c308
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_asnmth.c207
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_cipher.c91
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_dh.c72
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_digest.c91
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_dsa.c72
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_eckey.c72
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_pkmeth.c114
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_rand.c72
-rw-r--r--openssl-1.1.0h/crypto/engine/tb_rsa.c72
26 files changed, 6306 insertions, 0 deletions
diff --git a/openssl-1.1.0h/crypto/engine/README b/openssl-1.1.0h/crypto/engine/README
new file mode 100644
index 0000000..41baa18
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/README
@@ -0,0 +1,211 @@
+Notes: 2001-09-24
+-----------------
+
+This "description" (if one chooses to call it that) needed some major updating
+so here goes. This update addresses a change being made at the same time to
+OpenSSL, and it pretty much completely restructures the underlying mechanics of
+the "ENGINE" code. So it serves a double purpose of being a "ENGINE internals
+for masochists" document *and* a rather extensive commit log message. (I'd get
+lynched for sticking all this in CHANGES or the commit mails :-).
+
+ENGINE_TABLE underlies this restructuring, as described in the internal header
+"eng_int.h", implemented in eng_table.c, and used in each of the "class" files;
+tb_rsa.c, tb_dsa.c, etc.
+
+However, "EVP_CIPHER" underlies the motivation and design of ENGINE_TABLE so
+I'll mention a bit about that first. EVP_CIPHER (and most of this applies
+equally to EVP_MD for digests) is both a "method" and a algorithm/mode
+identifier that, in the current API, "lingers". These cipher description +
+implementation structures can be defined or obtained directly by applications,
+or can be loaded "en masse" into EVP storage so that they can be catalogued and
+searched in various ways, ie. two ways of encrypting with the "des_cbc"
+algorithm/mode pair are;
+
+(i) directly;
+ const EVP_CIPHER *cipher = EVP_des_cbc();
+ EVP_EncryptInit(&ctx, cipher, key, iv);
+ [ ... use EVP_EncryptUpdate() and EVP_EncryptFinal() ...]
+
+(ii) indirectly;
+ OpenSSL_add_all_ciphers();
+ cipher = EVP_get_cipherbyname("des_cbc");
+ EVP_EncryptInit(&ctx, cipher, key, iv);
+ [ ... etc ... ]
+
+The latter is more generally used because it also allows ciphers/digests to be
+looked up based on other identifiers which can be useful for automatic cipher
+selection, eg. in SSL/TLS, or by user-controllable configuration.
+
+The important point about this is that EVP_CIPHER definitions and structures are
+passed around with impunity and there is no safe way, without requiring massive
+rewrites of many applications, to assume that EVP_CIPHERs can be reference
+counted. One an EVP_CIPHER is exposed to the caller, neither it nor anything it
+comes from can "safely" be destroyed. Unless of course the way of getting to
+such ciphers is via entirely distinct API calls that didn't exist before.
+However existing API usage cannot be made to understand when an EVP_CIPHER
+pointer, that has been passed to the caller, is no longer being used.
+
+The other problem with the existing API w.r.t. to hooking EVP_CIPHER support
+into ENGINE is storage - the OBJ_NAME-based storage used by EVP to register
+ciphers simultaneously registers cipher *types* and cipher *implementations* -
+they are effectively the same thing, an "EVP_CIPHER" pointer. The problem with
+hooking in ENGINEs is that multiple ENGINEs may implement the same ciphers. The
+solution is necessarily that ENGINE-provided ciphers simply are not registered,
+stored, or exposed to the caller in the same manner as existing ciphers. This is
+especially necessary considering the fact ENGINE uses reference counts to allow
+for cleanup, modularity, and DSO support - yet EVP_CIPHERs, as exposed to
+callers in the current API, support no such controls.
+
+Another sticking point for integrating cipher support into ENGINE is linkage.
+Already there is a problem with the way ENGINE supports RSA, DSA, etc whereby
+they are available *because* they're part of a giant ENGINE called "openssl".
+Ie. all implementations *have* to come from an ENGINE, but we get round that by
+having a giant ENGINE with all the software support encapsulated. This creates
+linker hassles if nothing else - linking a 1-line application that calls 2 basic
+RSA functions (eg. "RSA_free(RSA_new());") will result in large quantities of
+ENGINE code being linked in *and* because of that DSA, DH, and RAND also. If we
+continue with this approach for EVP_CIPHER support (even if it *was* possible)
+we would lose our ability to link selectively by selectively loading certain
+implementations of certain functionality. Touching any part of any kind of
+crypto would result in massive static linkage of everything else. So the
+solution is to change the way ENGINE feeds existing "classes", ie. how the
+hooking to ENGINE works from RSA, DSA, DH, RAND, as well as adding new hooking
+for EVP_CIPHER, and EVP_MD.
+
+The way this is now being done is by mostly reverting back to how things used to
+work prior to ENGINE :-). Ie. RSA now has a "RSA_METHOD" pointer again - this
+was previously replaced by an "ENGINE" pointer and all RSA code that required
+the RSA_METHOD would call ENGINE_get_RSA() each time on its ENGINE handle to
+temporarily get and use the ENGINE's RSA implementation. Apart from being more
+efficient, switching back to each RSA having an RSA_METHOD pointer also allows
+us to conceivably operate with *no* ENGINE. As we'll see, this removes any need
+for a fallback ENGINE that encapsulates default implementations - we can simply
+have our RSA structure pointing its RSA_METHOD pointer to the software
+implementation and have its ENGINE pointer set to NULL.
+
+A look at the EVP_CIPHER hooking is most explanatory, the RSA, DSA (etc) cases
+turn out to be degenerate forms of the same thing. The EVP storage of ciphers,
+and the existing EVP API functions that return "software" implementations and
+descriptions remain untouched. However, the storage takes more meaning in terms
+of "cipher description" and less meaning in terms of "implementation". When an
+EVP_CIPHER_CTX is actually initialised with an EVP_CIPHER method and is about to
+begin en/decryption, the hooking to ENGINE comes into play. What happens is that
+cipher-specific ENGINE code is asked for an ENGINE pointer (a functional
+reference) for any ENGINE that is registered to perform the algo/mode that the
+provided EVP_CIPHER structure represents. Under normal circumstances, that
+ENGINE code will return NULL because no ENGINEs will have had any cipher
+implementations *registered*. As such, a NULL ENGINE pointer is stored in the
+EVP_CIPHER_CTX context, and the EVP_CIPHER structure is left hooked into the
+context and so is used as the implementation. Pretty much how things work now
+except we'd have a redundant ENGINE pointer set to NULL and doing nothing.
+
+Conversely, if an ENGINE *has* been registered to perform the algorithm/mode
+combination represented by the provided EVP_CIPHER, then a functional reference
+to that ENGINE will be returned to the EVP_CIPHER_CTX during initialisation.
+That functional reference will be stored in the context (and released on
+cleanup) - and having that reference provides a *safe* way to use an EVP_CIPHER
+definition that is private to the ENGINE. Ie. the EVP_CIPHER provided by the
+application will actually be replaced by an EVP_CIPHER from the registered
+ENGINE - it will support the same algorithm/mode as the original but will be a
+completely different implementation. Because this EVP_CIPHER isn't stored in the
+EVP storage, nor is it returned to applications from traditional API functions,
+there is no associated problem with it not having reference counts. And of
+course, when one of these "private" cipher implementations is hooked into
+EVP_CIPHER_CTX, it is done whilst the EVP_CIPHER_CTX holds a functional
+reference to the ENGINE that owns it, thus the use of the ENGINE's EVP_CIPHER is
+safe.
+
+The "cipher-specific ENGINE code" I mentioned is implemented in tb_cipher.c but
+in essence it is simply an instantiation of "ENGINE_TABLE" code for use by
+EVP_CIPHER code. tb_digest.c is virtually identical but, of course, it is for
+use by EVP_MD code. Ditto for tb_rsa.c, tb_dsa.c, etc. These instantiations of
+ENGINE_TABLE essentially provide linker-separation of the classes so that even
+if ENGINEs implement *all* possible algorithms, an application using only
+EVP_CIPHER code will link at most code relating to EVP_CIPHER, tb_cipher.c, core
+ENGINE code that is independent of class, and of course the ENGINE
+implementation that the application loaded. It will *not* however link any
+class-specific ENGINE code for digests, RSA, etc nor will it bleed over into
+other APIs, such as the RSA/DSA/etc library code.
+
+ENGINE_TABLE is a little more complicated than may seem necessary but this is
+mostly to avoid a lot of "init()"-thrashing on ENGINEs (that may have to load
+DSOs, and other expensive setup that shouldn't be thrashed unnecessarily) *and*
+to duplicate "default" behaviour. Basically an ENGINE_TABLE instantiation, for
+example tb_cipher.c, implements a hash-table keyed by integer "nid" values.
+These nids provide the uniquenness of an algorithm/mode - and each nid will hash
+to a potentially NULL "ENGINE_PILE". An ENGINE_PILE is essentially a list of
+pointers to ENGINEs that implement that particular 'nid'. Each "pile" uses some
+caching tricks such that requests on that 'nid' will be cached and all future
+requests will return immediately (well, at least with minimal operation) unless
+a change is made to the pile, eg. perhaps an ENGINE was unloaded. The reason is
+that an application could have support for 10 ENGINEs statically linked
+in, and the machine in question may not have any of the hardware those 10
+ENGINEs support. If each of those ENGINEs has a "des_cbc" implementation, we
+want to avoid every EVP_CIPHER_CTX setup from trying (and failing) to initialise
+each of those 10 ENGINEs. Instead, the first such request will try to do that
+and will either return (and cache) a NULL ENGINE pointer or will return a
+functional reference to the first that successfully initialised. In the latter
+case it will also cache an extra functional reference to the ENGINE as a
+"default" for that 'nid'. The caching is acknowledged by a 'uptodate' variable
+that is unset only if un/registration takes place on that pile. Ie. if
+implementations of "des_cbc" are added or removed. This behaviour can be
+tweaked; the ENGINE_TABLE_FLAG_NOINIT value can be passed to
+ENGINE_set_table_flags(), in which case the only ENGINEs that tb_cipher.c will
+try to initialise from the "pile" will be those that are already initialised
+(ie. it's simply an increment of the functional reference count, and no real
+"initialisation" will take place).
+
+RSA, DSA, DH, and RAND all have their own ENGINE_TABLE code as well, and the
+difference is that they all use an implicit 'nid' of 1. Whereas EVP_CIPHERs are
+actually qualitatively different depending on 'nid' (the "des_cbc" EVP_CIPHER is
+not an interoperable implementation of "aes_256_cbc"), RSA_METHODs are
+necessarily interoperable and don't have different flavours, only different
+implementations. In other words, the ENGINE_TABLE for RSA will either be empty,
+or will have a single ENGING_PILE hashed to by the 'nid' 1 and that pile
+represents ENGINEs that implement the single "type" of RSA there is.
+
+Cleanup - the registration and unregistration may pose questions about how
+cleanup works with the ENGINE_PILE doing all this caching nonsense (ie. when the
+application or EVP_CIPHER code releases its last reference to an ENGINE, the
+ENGINE_PILE code may still have references and thus those ENGINEs will stay
+hooked in forever). The way this is handled is via "unregistration". With these
+new ENGINE changes, an abstract ENGINE can be loaded and initialised, but that
+is an algorithm-agnostic process. Even if initialised, it will not have
+registered any of its implementations (to do so would link all class "table"
+code despite the fact the application may use only ciphers, for example). This
+is deliberately a distinct step. Moreover, registration and unregistration has
+nothing to do with whether an ENGINE is *functional* or not (ie. you can even
+register an ENGINE and its implementations without it being operational, you may
+not even have the drivers to make it operate). What actually happens with
+respect to cleanup is managed inside eng_lib.c with the "engine_cleanup_***"
+functions. These functions are internal-only and each part of ENGINE code that
+could require cleanup will, upon performing its first allocation, register a
+callback with the "engine_cleanup" code. The other part of this that makes it
+tick is that the ENGINE_TABLE instantiations (tb_***.c) use NULL as their
+initialised state. So if RSA code asks for an ENGINE and no ENGINE has
+registered an implementation, the code will simply return NULL and the tb_rsa.c
+state will be unchanged. Thus, no cleanup is required unless registration takes
+place. ENGINE_cleanup() will simply iterate across a list of registered cleanup
+callbacks calling each in turn, and will then internally delete its own storage
+(a STACK). When a cleanup callback is next registered (eg. if the cleanup() is
+part of a gracefull restart and the application wants to cleanup all state then
+start again), the internal STACK storage will be freshly allocated. This is much
+the same as the situation in the ENGINE_TABLE instantiations ... NULL is the
+initialised state, so only modification operations (not queries) will cause that
+code to have to register a cleanup.
+
+What else? The bignum callbacks and associated ENGINE functions have been
+removed for two obvious reasons; (i) there was no way to generalise them to the
+mechanism now used by RSA/DSA/..., because there's no such thing as a BIGNUM
+method, and (ii) because of (i), there was no meaningful way for library or
+application code to automatically hook and use ENGINE supplied bignum functions
+anyway. Also, ENGINE_cpy() has been removed (although an internal-only version
+exists) - the idea of providing an ENGINE_cpy() function probably wasn't a good
+one and now certainly doesn't make sense in any generalised way. Some of the
+RSA, DSA, DH, and RAND functions that were fiddled during the original ENGINE
+changes have now, as a consequence, been reverted back. This is because the
+hooking of ENGINE is now automatic (and passive, it can interally use a NULL
+ENGINE pointer to simply ignore ENGINE from then on).
+
+Hell, that should be enough for now ... comments welcome: geoff@openssl.org
+
diff --git a/openssl-1.1.0h/crypto/engine/build.info b/openssl-1.1.0h/crypto/engine/build.info
new file mode 100644
index 0000000..161dad4
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/build.info
@@ -0,0 +1,8 @@
+LIBS=../../libcrypto
+SOURCE[../../libcrypto]=\
+ eng_err.c eng_lib.c eng_list.c eng_init.c eng_ctrl.c \
+ eng_table.c eng_pkey.c eng_fat.c eng_all.c \
+ tb_rsa.c tb_dsa.c tb_dh.c tb_rand.c \
+ tb_cipher.c tb_digest.c tb_pkmeth.c tb_asnmth.c tb_eckey.c \
+ eng_openssl.c eng_cnf.c eng_dyn.c eng_cryptodev.c \
+ eng_rdrand.c
diff --git a/openssl-1.1.0h/crypto/engine/eng_all.c b/openssl-1.1.0h/crypto/engine/eng_all.c
new file mode 100644
index 0000000..ebe0277
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_all.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2001-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 "internal/cryptlib.h"
+#include "eng_int.h"
+
+void ENGINE_load_builtin_engines(void)
+{
+ /* Some ENGINEs need this */
+ OPENSSL_cpuid_setup();
+
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL);
+}
+
+#if (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) && !defined(OPENSSL_NO_DEPRECATED)
+void ENGINE_setup_bsd_cryptodev(void)
+{
+ static int bsd_cryptodev_default_loaded = 0;
+ if (!bsd_cryptodev_default_loaded) {
+ OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_CRYPTODEV, NULL);
+ ENGINE_register_all_complete();
+ }
+ bsd_cryptodev_default_loaded = 1;
+}
+#endif
diff --git a/openssl-1.1.0h/crypto/engine/eng_cnf.c b/openssl-1.1.0h/crypto/engine/eng_cnf.c
new file mode 100644
index 0000000..6f0a066
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_cnf.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2002-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 "eng_int.h"
+#include <openssl/conf.h>
+
+/* #define ENGINE_CONF_DEBUG */
+
+/* ENGINE config module */
+
+static const char *skip_dot(const char *name)
+{
+ const char *p = strchr(name, '.');
+
+ if (p != NULL)
+ return p + 1;
+ return name;
+}
+
+static STACK_OF(ENGINE) *initialized_engines = NULL;
+
+static int int_engine_init(ENGINE *e)
+{
+ if (!ENGINE_init(e))
+ return 0;
+ if (!initialized_engines)
+ initialized_engines = sk_ENGINE_new_null();
+ if (!initialized_engines || !sk_ENGINE_push(initialized_engines, e)) {
+ ENGINE_finish(e);
+ return 0;
+ }
+ return 1;
+}
+
+static int int_engine_configure(const char *name, const char *value, const CONF *cnf)
+{
+ int i;
+ int ret = 0;
+ long do_init = -1;
+ STACK_OF(CONF_VALUE) *ecmds;
+ CONF_VALUE *ecmd = NULL;
+ const char *ctrlname, *ctrlvalue;
+ ENGINE *e = NULL;
+ int soft = 0;
+
+ name = skip_dot(name);
+#ifdef ENGINE_CONF_DEBUG
+ fprintf(stderr, "Configuring engine %s\n", name);
+#endif
+ /* Value is a section containing ENGINE commands */
+ ecmds = NCONF_get_section(cnf, value);
+
+ if (!ecmds) {
+ ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
+ ENGINE_R_ENGINE_SECTION_ERROR);
+ return 0;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++) {
+ ecmd = sk_CONF_VALUE_value(ecmds, i);
+ ctrlname = skip_dot(ecmd->name);
+ ctrlvalue = ecmd->value;
+#ifdef ENGINE_CONF_DEBUG
+ fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname,
+ ctrlvalue);
+#endif
+
+ /* First handle some special pseudo ctrls */
+
+ /* Override engine name to use */
+ if (strcmp(ctrlname, "engine_id") == 0)
+ name = ctrlvalue;
+ else if (strcmp(ctrlname, "soft_load") == 0)
+ soft = 1;
+ /* Load a dynamic ENGINE */
+ else if (strcmp(ctrlname, "dynamic_path") == 0) {
+ e = ENGINE_by_id("dynamic");
+ if (!e)
+ goto err;
+ if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
+ goto err;
+ if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0))
+ goto err;
+ if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
+ goto err;
+ }
+ /* ... add other pseudos here ... */
+ else {
+ /*
+ * At this point we need an ENGINE structural reference if we
+ * don't already have one.
+ */
+ if (!e) {
+ e = ENGINE_by_id(name);
+ if (!e && soft) {
+ ERR_clear_error();
+ return 1;
+ }
+ if (!e)
+ goto err;
+ }
+ /*
+ * Allow "EMPTY" to mean no value: this allows a valid "value" to
+ * be passed to ctrls of type NO_INPUT
+ */
+ if (strcmp(ctrlvalue, "EMPTY") == 0)
+ ctrlvalue = NULL;
+ if (strcmp(ctrlname, "init") == 0) {
+ if (!NCONF_get_number_e(cnf, value, "init", &do_init))
+ goto err;
+ if (do_init == 1) {
+ if (!int_engine_init(e))
+ goto err;
+ } else if (do_init != 0) {
+ ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
+ ENGINE_R_INVALID_INIT_VALUE);
+ goto err;
+ }
+ } else if (strcmp(ctrlname, "default_algorithms") == 0) {
+ if (!ENGINE_set_default_string(e, ctrlvalue))
+ goto err;
+ } else if (!ENGINE_ctrl_cmd_string(e, ctrlname, ctrlvalue, 0))
+ goto err;
+ }
+
+ }
+ if (e && (do_init == -1) && !int_engine_init(e)) {
+ ecmd = NULL;
+ goto err;
+ }
+ ret = 1;
+ err:
+ if (ret != 1) {
+ ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE,
+ ENGINE_R_ENGINE_CONFIGURATION_ERROR);
+ if (ecmd)
+ ERR_add_error_data(6, "section=", ecmd->section,
+ ", name=", ecmd->name,
+ ", value=", ecmd->value);
+ }
+ ENGINE_free(e);
+ return ret;
+}
+
+static int int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
+{
+ STACK_OF(CONF_VALUE) *elist;
+ CONF_VALUE *cval;
+ int i;
+#ifdef ENGINE_CONF_DEBUG
+ fprintf(stderr, "Called engine module: name %s, value %s\n",
+ CONF_imodule_get_name(md), CONF_imodule_get_value(md));
+#endif
+ /* Value is a section containing ENGINEs to configure */
+ elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));
+
+ if (!elist) {
+ ENGINEerr(ENGINE_F_INT_ENGINE_MODULE_INIT,
+ ENGINE_R_ENGINES_SECTION_ERROR);
+ return 0;
+ }
+
+ for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
+ cval = sk_CONF_VALUE_value(elist, i);
+ if (!int_engine_configure(cval->name, cval->value, cnf))
+ return 0;
+ }
+
+ return 1;
+}
+
+static void int_engine_module_finish(CONF_IMODULE *md)
+{
+ ENGINE *e;
+
+ while ((e = sk_ENGINE_pop(initialized_engines)))
+ ENGINE_finish(e);
+ sk_ENGINE_free(initialized_engines);
+ initialized_engines = NULL;
+}
+
+void ENGINE_add_conf_module(void)
+{
+ CONF_module_add("engines",
+ int_engine_module_init, int_engine_module_finish);
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_cryptodev.c b/openssl-1.1.0h/crypto/engine/eng_cryptodev.c
new file mode 100644
index 0000000..5572735
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_cryptodev.c
@@ -0,0 +1,1757 @@
+/*
+ * Copyright 2002-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
+ */
+
+/*
+ * Copyright (c) 2002 Bob Beck <beck@openbsd.org>
+ * Copyright (c) 2002 Theo de Raadt
+ * Copyright (c) 2002 Markus Friedl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <openssl/objects.h>
+#include <internal/engine.h>
+#include <openssl/evp.h>
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+
+#if (defined(__unix__) || defined(unix)) && !defined(USG) && \
+ (defined(OpenBSD) || defined(__FreeBSD__))
+# include <sys/param.h>
+# if (defined(OpenBSD) && (OpenBSD >= 200112)) || \
+ (defined(__FreeBSD_version) && \
+ ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || \
+ __FreeBSD_version >= 500041))
+# define HAVE_CRYPTODEV
+# endif
+# if defined(OpenBSD) && (OpenBSD >= 200110)
+# define HAVE_SYSLOG_R
+# endif
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_CRYPTODEV
+# include <crypto/cryptodev.h>
+# include <sys/ioctl.h>
+# include <errno.h>
+# include <stdio.h>
+# include <unistd.h>
+# include <fcntl.h>
+# include <stdarg.h>
+# include <syslog.h>
+# include <errno.h>
+# include <string.h>
+#endif
+#include <openssl/dh.h>
+#include <openssl/dsa.h>
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+
+#ifndef HAVE_CRYPTODEV
+
+void engine_load_cryptodev_int(void)
+{
+ /* This is a NOP on platforms without /dev/crypto */
+ return;
+}
+
+#else
+
+struct dev_crypto_state {
+ struct session_op d_sess;
+ int d_fd;
+# ifdef USE_CRYPTODEV_DIGESTS
+ char dummy_mac_key[HASH_MAX_LEN];
+ unsigned char digest_res[HASH_MAX_LEN];
+ char *mac_data;
+ int mac_len;
+# endif
+};
+
+static u_int32_t cryptodev_asymfeat = 0;
+
+static RSA_METHOD *cryptodev_rsa;
+#ifndef OPENSSL_NO_DSA
+static DSA_METHOD *cryptodev_dsa = NULL;
+#endif
+#ifndef OPENSSL_NO_DH
+static DH_METHOD *cryptodev_dh;
+#endif
+
+static int get_asym_dev_crypto(void);
+static int open_dev_crypto(void);
+static int get_dev_crypto(void);
+static int get_cryptodev_ciphers(const int **cnids);
+# ifdef USE_CRYPTODEV_DIGESTS
+static int get_cryptodev_digests(const int **cnids);
+# endif
+static int cryptodev_usable_ciphers(const int **nids);
+static int cryptodev_usable_digests(const int **nids);
+static int cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
+static int cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx);
+static int cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid);
+static int cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid);
+static int bn2crparam(const BIGNUM *a, struct crparam *crp);
+static int crparam2bn(struct crparam *crp, BIGNUM *a);
+static void zapparams(struct crypt_kop *kop);
+static int cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r,
+ int slen, BIGNUM *s);
+
+static int cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+static int cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+ BN_CTX *ctx);
+static int cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+ BN_CTX *ctx);
+#ifndef OPENSSL_NO_DSA
+static int cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m,
+ BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+static int cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, const BIGNUM *g,
+ const BIGNUM *u1, const BIGNUM *pub_key,
+ const BIGNUM *u2, const BIGNUM *p,
+ BN_CTX *ctx, BN_MONT_CTX *mont);
+static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen,
+ DSA *dsa);
+static int cryptodev_dsa_verify(const unsigned char *dgst, int dgst_len,
+ DSA_SIG *sig, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_DH
+static int cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx);
+static int cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key,
+ DH *dh);
+#endif
+static int cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p,
+ void (*f) (void));
+void engine_load_cryptodev_int(void);
+
+static const ENGINE_CMD_DEFN cryptodev_defns[] = {
+ {0, NULL, NULL, 0}
+};
+
+static struct {
+ int id;
+ int nid;
+ int ivmax;
+ int keylen;
+} ciphers[] = {
+ {
+ CRYPTO_ARC4, NID_rc4, 0, 16,
+ },
+ {
+ CRYPTO_DES_CBC, NID_des_cbc, 8, 8,
+ },
+ {
+ CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24,
+ },
+ {
+ CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16,
+ },
+ {
+ CRYPTO_AES_CBC, NID_aes_192_cbc, 16, 24,
+ },
+ {
+ CRYPTO_AES_CBC, NID_aes_256_cbc, 16, 32,
+ },
+# ifdef CRYPTO_AES_CTR
+ {
+ CRYPTO_AES_CTR, NID_aes_128_ctr, 14, 16,
+ },
+ {
+ CRYPTO_AES_CTR, NID_aes_192_ctr, 14, 24,
+ },
+ {
+ CRYPTO_AES_CTR, NID_aes_256_ctr, 14, 32,
+ },
+# endif
+ {
+ CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16,
+ },
+ {
+ CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16,
+ },
+ {
+ CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0,
+ },
+ {
+ 0, NID_undef, 0, 0,
+ },
+};
+
+# ifdef USE_CRYPTODEV_DIGESTS
+static struct {
+ int id;
+ int nid;
+ int keylen;
+} digests[] = {
+ {
+ CRYPTO_MD5_HMAC, NID_hmacWithMD5, 16
+ },
+ {
+ CRYPTO_SHA1_HMAC, NID_hmacWithSHA1, 20
+ },
+ {
+ CRYPTO_RIPEMD160_HMAC, NID_ripemd160, 16
+ /* ? */
+ },
+ {
+ CRYPTO_MD5_KPDK, NID_undef, 0
+ },
+ {
+ CRYPTO_SHA1_KPDK, NID_undef, 0
+ },
+ {
+ CRYPTO_MD5, NID_md5, 16
+ },
+ {
+ CRYPTO_SHA1, NID_sha1, 20
+ },
+ {
+ 0, NID_undef, 0
+ },
+};
+# endif
+
+/*
+ * Return a fd if /dev/crypto seems usable, 0 otherwise.
+ */
+static int open_dev_crypto(void)
+{
+ static int fd = -1;
+
+ if (fd == -1) {
+ if ((fd = open("/dev/crypto", O_RDWR, 0)) == -1)
+ return (-1);
+ /* close on exec */
+ if (fcntl(fd, F_SETFD, 1) == -1) {
+ close(fd);
+ fd = -1;
+ return (-1);
+ }
+ }
+ return (fd);
+}
+
+static int get_dev_crypto(void)
+{
+ int fd, retfd;
+
+ if ((fd = open_dev_crypto()) == -1)
+ return (-1);
+# ifndef CRIOGET_NOT_NEEDED
+ if (ioctl(fd, CRIOGET, &retfd) == -1)
+ return (-1);
+
+ /* close on exec */
+ if (fcntl(retfd, F_SETFD, 1) == -1) {
+ close(retfd);
+ return (-1);
+ }
+# else
+ retfd = fd;
+# endif
+ return (retfd);
+}
+
+static void put_dev_crypto(int fd)
+{
+# ifndef CRIOGET_NOT_NEEDED
+ close(fd);
+# endif
+}
+
+/* Caching version for asym operations */
+static int get_asym_dev_crypto(void)
+{
+ static int fd = -1;
+
+ if (fd == -1)
+ fd = get_dev_crypto();
+ return fd;
+}
+
+/*
+ * Find out what ciphers /dev/crypto will let us have a session for.
+ * XXX note, that some of these openssl doesn't deal with yet!
+ * returning them here is harmless, as long as we return NULL
+ * when asked for a handler in the cryptodev_engine_ciphers routine
+ */
+static int get_cryptodev_ciphers(const int **cnids)
+{
+ static int nids[CRYPTO_ALGORITHM_MAX];
+ struct session_op sess;
+ int fd, i, count = 0;
+
+ if ((fd = get_dev_crypto()) < 0) {
+ *cnids = NULL;
+ return (0);
+ }
+ memset(&sess, 0, sizeof(sess));
+ sess.key = (caddr_t) "123456789abcdefghijklmno";
+
+ for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
+ if (ciphers[i].nid == NID_undef)
+ continue;
+ sess.cipher = ciphers[i].id;
+ sess.keylen = ciphers[i].keylen;
+ sess.mac = 0;
+ if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
+ ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
+ nids[count++] = ciphers[i].nid;
+ }
+ put_dev_crypto(fd);
+
+ if (count > 0)
+ *cnids = nids;
+ else
+ *cnids = NULL;
+ return (count);
+}
+
+# ifdef USE_CRYPTODEV_DIGESTS
+/*
+ * Find out what digests /dev/crypto will let us have a session for.
+ * XXX note, that some of these openssl doesn't deal with yet!
+ * returning them here is harmless, as long as we return NULL
+ * when asked for a handler in the cryptodev_engine_digests routine
+ */
+static int get_cryptodev_digests(const int **cnids)
+{
+ static int nids[CRYPTO_ALGORITHM_MAX];
+ struct session_op sess;
+ int fd, i, count = 0;
+
+ if ((fd = get_dev_crypto()) < 0) {
+ *cnids = NULL;
+ return (0);
+ }
+ memset(&sess, 0, sizeof(sess));
+ sess.mackey = (caddr_t) "123456789abcdefghijklmno";
+ for (i = 0; digests[i].id && count < CRYPTO_ALGORITHM_MAX; i++) {
+ if (digests[i].nid == NID_undef)
+ continue;
+ sess.mac = digests[i].id;
+ sess.mackeylen = digests[i].keylen;
+ sess.cipher = 0;
+ if (ioctl(fd, CIOCGSESSION, &sess) != -1 &&
+ ioctl(fd, CIOCFSESSION, &sess.ses) != -1)
+ nids[count++] = digests[i].nid;
+ }
+ put_dev_crypto(fd);
+
+ if (count > 0)
+ *cnids = nids;
+ else
+ *cnids = NULL;
+ return (count);
+}
+# endif /* 0 */
+
+/*
+ * Find the useable ciphers|digests from dev/crypto - this is the first
+ * thing called by the engine init crud which determines what it
+ * can use for ciphers from this engine. We want to return
+ * only what we can do, anything else is handled by software.
+ *
+ * If we can't initialize the device to do anything useful for
+ * any reason, we want to return a NULL array, and 0 length,
+ * which forces everything to be done is software. By putting
+ * the initialization of the device in here, we ensure we can
+ * use this engine as the default, and if for whatever reason
+ * /dev/crypto won't do what we want it will just be done in
+ * software
+ *
+ * This can (should) be greatly expanded to perhaps take into
+ * account speed of the device, and what we want to do.
+ * (although the disabling of particular alg's could be controlled
+ * by the device driver with sysctl's.) - this is where we
+ * want most of the decisions made about what we actually want
+ * to use from /dev/crypto.
+ */
+static int cryptodev_usable_ciphers(const int **nids)
+{
+ return (get_cryptodev_ciphers(nids));
+}
+
+static int cryptodev_usable_digests(const int **nids)
+{
+# ifdef USE_CRYPTODEV_DIGESTS
+ return (get_cryptodev_digests(nids));
+# else
+ /*
+ * XXXX just disable all digests for now, because it sucks.
+ * we need a better way to decide this - i.e. I may not
+ * want digests on slow cards like hifn on fast machines,
+ * but might want them on slow or loaded machines, etc.
+ * will also want them when using crypto cards that don't
+ * suck moose gonads - would be nice to be able to decide something
+ * as reasonable default without having hackery that's card dependent.
+ * of course, the default should probably be just do everything,
+ * with perhaps a sysctl to turn algorithms off (or have them off
+ * by default) on cards that generally suck like the hifn.
+ */
+ *nids = NULL;
+ return (0);
+# endif
+}
+
+static int
+cryptodev_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = EVP_CIPHER_CTX_get_cipher_data(ctx);
+ struct session_op *sess = &state->d_sess;
+ const void *iiv;
+ unsigned char save_iv[EVP_MAX_IV_LENGTH];
+
+ if (state->d_fd < 0)
+ return (0);
+ if (!inl)
+ return (1);
+ if ((inl % EVP_CIPHER_CTX_block_size(ctx)) != 0)
+ return (0);
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = inl;
+ cryp.src = (caddr_t) in;
+ cryp.dst = (caddr_t) out;
+ cryp.mac = 0;
+
+ cryp.op = EVP_CIPHER_CTX_encrypting(ctx) ? COP_ENCRYPT : COP_DECRYPT;
+
+ if (EVP_CIPHER_CTX_iv_length(ctx) > 0) {
+ cryp.iv = (caddr_t) EVP_CIPHER_CTX_iv(ctx);
+ if (!EVP_CIPHER_CTX_encrypting(ctx)) {
+ iiv = in + inl - EVP_CIPHER_CTX_iv_length(ctx);
+ memcpy(save_iv, iiv, EVP_CIPHER_CTX_iv_length(ctx));
+ }
+ } else
+ cryp.iv = NULL;
+
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) == -1) {
+ /*
+ * XXX need better error handling this can fail for a number of
+ * different reasons.
+ */
+ return (0);
+ }
+
+ if (EVP_CIPHER_CTX_iv_length(ctx) > 0) {
+ if (EVP_CIPHER_CTX_encrypting(ctx))
+ iiv = out + inl - EVP_CIPHER_CTX_iv_length(ctx);
+ else
+ iiv = save_iv;
+ memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iiv,
+ EVP_CIPHER_CTX_iv_length(ctx));
+ }
+ return (1);
+}
+
+static int
+cryptodev_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+ struct dev_crypto_state *state = EVP_CIPHER_CTX_get_cipher_data(ctx);
+ struct session_op *sess = &state->d_sess;
+ int cipher = -1, i;
+
+ for (i = 0; ciphers[i].id; i++)
+ if (EVP_CIPHER_CTX_nid(ctx) == ciphers[i].nid &&
+ EVP_CIPHER_CTX_iv_length(ctx) <= ciphers[i].ivmax &&
+ EVP_CIPHER_CTX_key_length(ctx) == ciphers[i].keylen) {
+ cipher = ciphers[i].id;
+ break;
+ }
+
+ if (!ciphers[i].id) {
+ state->d_fd = -1;
+ return (0);
+ }
+
+ memset(sess, 0, sizeof(*sess));
+
+ if ((state->d_fd = get_dev_crypto()) < 0)
+ return (0);
+
+ sess->key = (caddr_t) key;
+ sess->keylen = EVP_CIPHER_CTX_key_length(ctx);
+ sess->cipher = cipher;
+
+ if (ioctl(state->d_fd, CIOCGSESSION, sess) == -1) {
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * free anything we allocated earlier when initing a
+ * session, and close the session.
+ */
+static int cryptodev_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ int ret = 0;
+ struct dev_crypto_state *state = EVP_CIPHER_CTX_get_cipher_data(ctx);
+ struct session_op *sess = &state->d_sess;
+
+ if (state->d_fd < 0)
+ return (0);
+
+ /*
+ * XXX if this ioctl fails, something's wrong. the invoker may have called
+ * us with a bogus ctx, or we could have a device that for whatever
+ * reason just doesn't want to play ball - it's not clear what's right
+ * here - should this be an error? should it just increase a counter,
+ * hmm. For right now, we return 0 - I don't believe that to be "right".
+ * we could call the gorpy openssl lib error handlers that print messages
+ * to users of the library. hmm..
+ */
+
+ if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) == -1) {
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+
+ return (ret);
+}
+
+/*
+ * libcrypto EVP stuff - this is how we get wired to EVP so the engine
+ * gets called when libcrypto requests a cipher NID.
+ */
+
+/* RC4 */
+static EVP_CIPHER *rc4_cipher = NULL;
+static const EVP_CIPHER *cryptodev_rc4(void)
+{
+ if (rc4_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_rc4, 1, 16)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 0)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_VARIABLE_LENGTH)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ rc4_cipher = cipher;
+ }
+ return rc4_cipher;
+}
+
+/* DES CBC EVP */
+static EVP_CIPHER *des_cbc_cipher = NULL;
+static const EVP_CIPHER *cryptodev_des_cbc(void)
+{
+ if (des_cbc_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_des_cbc, 8, 8)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 8)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ des_cbc_cipher = cipher;
+ }
+ return des_cbc_cipher;
+}
+
+/* 3DES CBC EVP */
+static EVP_CIPHER *des3_cbc_cipher = NULL;
+static const EVP_CIPHER *cryptodev_3des_cbc(void)
+{
+ if (des3_cbc_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_des_ede3_cbc, 8, 24)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 8)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ des3_cbc_cipher = cipher;
+ }
+ return des3_cbc_cipher;
+}
+
+static EVP_CIPHER *bf_cbc_cipher = NULL;
+static const EVP_CIPHER *cryptodev_bf_cbc(void)
+{
+ if (bf_cbc_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_bf_cbc, 8, 16)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 8)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ bf_cbc_cipher = cipher;
+ }
+ return bf_cbc_cipher;
+}
+
+static EVP_CIPHER *cast_cbc_cipher = NULL;
+static const EVP_CIPHER *cryptodev_cast_cbc(void)
+{
+ if (cast_cbc_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_cast5_cbc, 8, 16)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 8)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ cast_cbc_cipher = cipher;
+ }
+ return cast_cbc_cipher;
+}
+
+static EVP_CIPHER *aes_cbc_cipher = NULL;
+static const EVP_CIPHER *cryptodev_aes_cbc(void)
+{
+ if (aes_cbc_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_aes_128_cbc, 16, 16)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 16)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ aes_cbc_cipher = cipher;
+ }
+ return aes_cbc_cipher;
+}
+
+static EVP_CIPHER *aes_192_cbc_cipher = NULL;
+static const EVP_CIPHER *cryptodev_aes_192_cbc(void)
+{
+ if (aes_192_cbc_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_aes_192_cbc, 16, 24)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 16)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ aes_192_cbc_cipher = cipher;
+ }
+ return aes_192_cbc_cipher;
+}
+
+static EVP_CIPHER *aes_256_cbc_cipher = NULL;
+static const EVP_CIPHER *cryptodev_aes_256_cbc(void)
+{
+ if (aes_256_cbc_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_aes_256_cbc, 16, 32)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 16)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CBC_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ aes_256_cbc_cipher = cipher;
+ }
+ return aes_256_cbc_cipher;
+}
+
+# ifdef CRYPTO_AES_CTR
+static EVP_CIPHER *aes_ctr_cipher = NULL;
+static const EVP_CIPHER *cryptodev_aes_ctr(void)
+{
+ if (aes_ctr_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_aes_128_ctr, 16, 16)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 14)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CTR_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ aes_ctr_cipher = cipher;
+ }
+ return aes_ctr_cipher;
+}
+
+static EVP_CIPHER *aes_192_ctr_cipher = NULL;
+static const EVP_CIPHER *cryptodev_aes_192_ctr(void)
+{
+ if (aes_192_ctr_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_aes_192_ctr, 16, 24)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 14)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CTR_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ aes_192_ctr_cipher = cipher;
+ }
+ return aes_192_ctr_cipher;
+}
+
+static EVP_CIPHER *aes_256_ctr_cipher = NULL;
+static const EVP_CIPHER *cryptodev_aes_256_ctr(void)
+{
+ if (aes_256_ctr_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_aes_256_ctr, 16, 32)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 14)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_CTR_MODE)
+ || !EVP_CIPHER_meth_set_init(cipher, cryptodev_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, cryptodev_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, cryptodev_cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(struct dev_crypto_state))
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, EVP_CIPHER_set_asn1_iv)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, EVP_CIPHER_get_asn1_iv)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ aes_256_ctr_cipher = cipher;
+ }
+ return aes_256_ctr_cipher;
+}
+# endif
+/*
+ * Registered by the ENGINE when used to find out how to deal with
+ * a particular NID in the ENGINE. this says what we'll do at the
+ * top level - note, that list is restricted by what we answer with
+ */
+static int
+cryptodev_engine_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid)
+{
+ if (!cipher)
+ return (cryptodev_usable_ciphers(nids));
+
+ switch (nid) {
+ case NID_rc4:
+ *cipher = cryptodev_rc4();
+ break;
+ case NID_des_ede3_cbc:
+ *cipher = cryptodev_3des_cbc();
+ break;
+ case NID_des_cbc:
+ *cipher = cryptodev_des_cbc();
+ break;
+ case NID_bf_cbc:
+ *cipher = cryptodev_bf_cbc();
+ break;
+ case NID_cast5_cbc:
+ *cipher = cryptodev_cast_cbc();
+ break;
+ case NID_aes_128_cbc:
+ *cipher = cryptodev_aes_cbc();
+ break;
+ case NID_aes_192_cbc:
+ *cipher = cryptodev_aes_192_cbc();
+ break;
+ case NID_aes_256_cbc:
+ *cipher = cryptodev_aes_256_cbc();
+ break;
+# ifdef CRYPTO_AES_CTR
+ case NID_aes_128_ctr:
+ *cipher = cryptodev_aes_ctr();
+ break;
+ case NID_aes_192_ctr:
+ *cipher = cryptodev_aes_192_ctr();
+ break;
+ case NID_aes_256_ctr:
+ *cipher = cryptodev_aes_256_ctr();
+ break;
+# endif
+ default:
+ *cipher = NULL;
+ break;
+ }
+ return (*cipher != NULL);
+}
+
+# ifdef USE_CRYPTODEV_DIGESTS
+
+/* convert digest type to cryptodev */
+static int digest_nid_to_cryptodev(int nid)
+{
+ int i;
+
+ for (i = 0; digests[i].id; i++)
+ if (digests[i].nid == nid)
+ return (digests[i].id);
+ return (0);
+}
+
+static int digest_key_length(int nid)
+{
+ int i;
+
+ for (i = 0; digests[i].id; i++)
+ if (digests[i].nid == nid)
+ return digests[i].keylen;
+ return (0);
+}
+
+static int cryptodev_digest_init(EVP_MD_CTX *ctx)
+{
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+ int digest;
+
+ if ((digest = digest_nid_to_cryptodev(EVP_MD_CTX_type(ctx))) == NID_undef) {
+ printf("cryptodev_digest_init: Can't get digest \n");
+ return (0);
+ }
+
+ memset(state, 0, sizeof(*state));
+
+ if ((state->d_fd = get_dev_crypto()) < 0) {
+ printf("cryptodev_digest_init: Can't get Dev \n");
+ return (0);
+ }
+
+ sess->mackey = state->dummy_mac_key;
+ sess->mackeylen = digest_key_length(EVP_MD_CTX_type(ctx));
+ sess->mac = digest;
+
+ if (ioctl(state->d_fd, CIOCGSESSION, sess) < 0) {
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+ printf("cryptodev_digest_init: Open session failed\n");
+ return (0);
+ }
+
+ return (1);
+}
+
+static int cryptodev_digest_update(EVP_MD_CTX *ctx, const void *data,
+ size_t count)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+ char *new_mac_data;
+
+ if (!data || state->d_fd < 0) {
+ printf("cryptodev_digest_update: illegal inputs \n");
+ return (0);
+ }
+
+ if (!count) {
+ return (0);
+ }
+
+ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ /* if application doesn't support one buffer */
+ new_mac_data =
+ OPENSSL_realloc(state->mac_data, state->mac_len + count);
+
+ if (!new_mac_data) {
+ printf("cryptodev_digest_update: realloc failed\n");
+ return (0);
+ }
+ state->mac_data = new_mac_data;
+
+ memcpy(state->mac_data + state->mac_len, data, count);
+ state->mac_len += count;
+
+ return (1);
+ }
+
+ memset(&cryp, 0, sizeof(cryp));
+
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = count;
+ cryp.src = (caddr_t) data;
+ cryp.dst = NULL;
+ cryp.mac = (caddr_t) state->digest_res;
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
+ printf("cryptodev_digest_update: digest failed\n");
+ return (0);
+ }
+ return (1);
+}
+
+static int cryptodev_digest_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+ struct crypt_op cryp;
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+
+ int ret = 1;
+
+ if (!md || state->d_fd < 0) {
+ printf("cryptodev_digest_final: illegal input\n");
+ return (0);
+ }
+
+ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
+ /* if application doesn't support one buffer */
+ memset(&cryp, 0, sizeof(cryp));
+ cryp.ses = sess->ses;
+ cryp.flags = 0;
+ cryp.len = state->mac_len;
+ cryp.src = state->mac_data;
+ cryp.dst = NULL;
+ cryp.mac = (caddr_t) md;
+ if (ioctl(state->d_fd, CIOCCRYPT, &cryp) < 0) {
+ printf("cryptodev_digest_final: digest failed\n");
+ return (0);
+ }
+
+ return 1;
+ }
+
+ memcpy(md, state->digest_res, EVP_MD_CTX_size(ctx));
+
+ return (ret);
+}
+
+static int cryptodev_digest_cleanup(EVP_MD_CTX *ctx)
+{
+ int ret = 1;
+ struct dev_crypto_state *state = EVP_MD_CTX_md_data(ctx);
+ struct session_op *sess = &state->d_sess;
+
+ if (state == NULL)
+ return 0;
+
+ if (state->d_fd < 0) {
+ printf("cryptodev_digest_cleanup: illegal input\n");
+ return (0);
+ }
+
+ OPENSSL_free(state->mac_data);
+ state->mac_data = NULL;
+ state->mac_len = 0;
+
+ if (ioctl(state->d_fd, CIOCFSESSION, &sess->ses) < 0) {
+ printf("cryptodev_digest_cleanup: failed to close session\n");
+ ret = 0;
+ } else {
+ ret = 1;
+ }
+ put_dev_crypto(state->d_fd);
+ state->d_fd = -1;
+
+ return (ret);
+}
+
+static int cryptodev_digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
+{
+ struct dev_crypto_state *fstate = EVP_MD_CTX_md_data(from);
+ struct dev_crypto_state *dstate = EVP_MD_CTX_md_data(to);
+ struct session_op *sess;
+ int digest;
+
+ if (dstate == NULL || fstate == NULL)
+ return 1;
+
+ memcpy(dstate, fstate, sizeof(struct dev_crypto_state));
+
+ sess = &dstate->d_sess;
+
+ digest = digest_nid_to_cryptodev(EVP_MD_CTX_type(to));
+
+ sess->mackey = dstate->dummy_mac_key;
+ sess->mackeylen = digest_key_length(EVP_MD_CTX_type(to));
+ sess->mac = digest;
+
+ dstate->d_fd = get_dev_crypto();
+
+ if (ioctl(dstate->d_fd, CIOCGSESSION, sess) < 0) {
+ put_dev_crypto(dstate->d_fd);
+ dstate->d_fd = -1;
+ printf("cryptodev_digest_copy: Open session failed\n");
+ return (0);
+ }
+
+ if (fstate->mac_len != 0) {
+ if (fstate->mac_data != NULL) {
+ dstate->mac_data = OPENSSL_malloc(fstate->mac_len);
+ if (dstate->mac_data == NULL) {
+ printf("cryptodev_digest_copy: mac_data allocation failed\n");
+ return (0);
+ }
+ memcpy(dstate->mac_data, fstate->mac_data, fstate->mac_len);
+ dstate->mac_len = fstate->mac_len;
+ }
+ }
+
+ return 1;
+}
+
+static EVP_MD *sha1_md = NULL;
+static const EVP_MD *cryptodev_sha1(void)
+{
+ if (sha1_md == NULL) {
+ EVP_MD *md;
+
+ if ((md = EVP_MD_meth_new(NID_sha1, NID_undef)) == NULL
+ || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+ || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+ || !EVP_MD_meth_set_app_datasize(md,
+ sizeof(struct dev_crypto_state))
+ || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+ || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+ || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+ || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+ || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+ EVP_MD_meth_free(md);
+ md = NULL;
+ }
+ sha1_md = md;
+ }
+ return sha1_md;
+}
+
+static EVP_MD *md5_md = NULL;
+static const EVP_MD *cryptodev_md5(void)
+{
+ if (md5_md == NULL) {
+ EVP_MD *md;
+
+ if ((md = EVP_MD_meth_new(NID_md5, NID_undef)) == NULL
+ || !EVP_MD_meth_set_result_size(md, 16 /* MD5_DIGEST_LENGTH */)
+ || !EVP_MD_meth_set_flags(md, EVP_MD_FLAG_ONESHOT)
+ || !EVP_MD_meth_set_input_blocksize(md, 64 /* MD5_CBLOCK */)
+ || !EVP_MD_meth_set_app_datasize(md,
+ sizeof(struct dev_crypto_state))
+ || !EVP_MD_meth_set_init(md, cryptodev_digest_init)
+ || !EVP_MD_meth_set_update(md, cryptodev_digest_update)
+ || !EVP_MD_meth_set_final(md, cryptodev_digest_final)
+ || !EVP_MD_meth_set_copy(md, cryptodev_digest_copy)
+ || !EVP_MD_meth_set_cleanup(md, cryptodev_digest_cleanup)) {
+ EVP_MD_meth_free(md);
+ md = NULL;
+ }
+ md5_md = md;
+ }
+ return md5_md;
+}
+
+# endif /* USE_CRYPTODEV_DIGESTS */
+
+static int
+cryptodev_engine_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid)
+{
+ if (!digest)
+ return (cryptodev_usable_digests(nids));
+
+ switch (nid) {
+# ifdef USE_CRYPTODEV_DIGESTS
+ case NID_md5:
+ *digest = cryptodev_md5();
+ break;
+ case NID_sha1:
+ *digest = cryptodev_sha1();
+ break;
+ default:
+# endif /* USE_CRYPTODEV_DIGESTS */
+ *digest = NULL;
+ break;
+ }
+ return (*digest != NULL);
+}
+
+static int cryptodev_engine_destroy(ENGINE *e)
+{
+ EVP_CIPHER_meth_free(rc4_cipher);
+ rc4_cipher = NULL;
+ EVP_CIPHER_meth_free(des_cbc_cipher);
+ des_cbc_cipher = NULL;
+ EVP_CIPHER_meth_free(des3_cbc_cipher);
+ des3_cbc_cipher = NULL;
+ EVP_CIPHER_meth_free(bf_cbc_cipher);
+ bf_cbc_cipher = NULL;
+ EVP_CIPHER_meth_free(cast_cbc_cipher);
+ cast_cbc_cipher = NULL;
+ EVP_CIPHER_meth_free(aes_cbc_cipher);
+ aes_cbc_cipher = NULL;
+ EVP_CIPHER_meth_free(aes_192_cbc_cipher);
+ aes_192_cbc_cipher = NULL;
+ EVP_CIPHER_meth_free(aes_256_cbc_cipher);
+ aes_256_cbc_cipher = NULL;
+# ifdef CRYPTO_AES_CTR
+ EVP_CIPHER_meth_free(aes_ctr_cipher);
+ aes_ctr_cipher = NULL;
+ EVP_CIPHER_meth_free(aes_192_ctr_cipher);
+ aes_192_ctr_cipher = NULL;
+ EVP_CIPHER_meth_free(aes_256_ctr_cipher);
+ aes_256_ctr_cipher = NULL;
+# endif
+# ifdef USE_CRYPTODEV_DIGESTS
+ EVP_MD_meth_free(sha1_md);
+ sha1_md = NULL;
+ EVP_MD_meth_free(md5_md);
+ md5_md = NULL;
+# endif
+ RSA_meth_free(cryptodev_rsa);
+ cryptodev_rsa = NULL;
+#ifndef OPENSSL_NO_DSA
+ DSA_meth_free(cryptodev_dsa);
+ cryptodev_dsa = NULL;
+#endif
+#ifndef OPENSSL_NO_DH
+ DH_meth_free(cryptodev_dh);
+ cryptodev_dh = NULL;
+#endif
+ return 1;
+}
+
+/*
+ * Convert a BIGNUM to the representation that /dev/crypto needs.
+ * Upon completion of use, the caller is responsible for freeing
+ * crp->crp_p.
+ */
+static int bn2crparam(const BIGNUM *a, struct crparam *crp)
+{
+ ssize_t bytes, bits;
+ u_char *b;
+
+ crp->crp_p = NULL;
+ crp->crp_nbits = 0;
+
+ bits = BN_num_bits(a);
+ bytes = BN_num_bytes(a);
+
+ b = OPENSSL_zalloc(bytes);
+ if (b == NULL)
+ return (1);
+
+ crp->crp_p = (caddr_t) b;
+ crp->crp_nbits = bits;
+
+ BN_bn2bin(a, b);
+ return (0);
+}
+
+/* Convert a /dev/crypto parameter to a BIGNUM */
+static int crparam2bn(struct crparam *crp, BIGNUM *a)
+{
+ u_int8_t *pd;
+ int i, bytes;
+
+ bytes = (crp->crp_nbits + 7) / 8;
+
+ if (bytes == 0)
+ return (-1);
+
+ if ((pd = OPENSSL_malloc(bytes)) == NULL)
+ return (-1);
+
+ for (i = 0; i < bytes; i++)
+ pd[i] = crp->crp_p[bytes - i - 1];
+
+ BN_bin2bn(pd, bytes, a);
+ free(pd);
+
+ return (0);
+}
+
+static void zapparams(struct crypt_kop *kop)
+{
+ int i;
+
+ for (i = 0; i < kop->crk_iparams + kop->crk_oparams; i++) {
+ OPENSSL_free(kop->crk_param[i].crp_p);
+ kop->crk_param[i].crp_p = NULL;
+ kop->crk_param[i].crp_nbits = 0;
+ }
+}
+
+static int
+cryptodev_asym(struct crypt_kop *kop, int rlen, BIGNUM *r, int slen,
+ BIGNUM *s)
+{
+ int fd, ret = -1;
+
+ if ((fd = get_asym_dev_crypto()) < 0)
+ return ret;
+
+ if (r) {
+ kop->crk_param[kop->crk_iparams].crp_p = OPENSSL_zalloc(rlen);
+ if (kop->crk_param[kop->crk_iparams].crp_p == NULL)
+ return ret;
+ kop->crk_param[kop->crk_iparams].crp_nbits = rlen * 8;
+ kop->crk_oparams++;
+ }
+ if (s) {
+ kop->crk_param[kop->crk_iparams + 1].crp_p =
+ OPENSSL_zalloc(slen);
+ /* No need to free the kop->crk_iparams parameter if it was allocated,
+ * callers of this routine have to free allocated parameters through
+ * zapparams both in case of success and failure
+ */
+ if (kop->crk_param[kop->crk_iparams+1].crp_p == NULL)
+ return ret;
+ kop->crk_param[kop->crk_iparams + 1].crp_nbits = slen * 8;
+ kop->crk_oparams++;
+ }
+
+ if (ioctl(fd, CIOCKEY, kop) == 0) {
+ if (r)
+ crparam2bn(&kop->crk_param[kop->crk_iparams], r);
+ if (s)
+ crparam2bn(&kop->crk_param[kop->crk_iparams + 1], s);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static int
+cryptodev_bn_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
+{
+ struct crypt_kop kop;
+ int ret = 1;
+
+ /*
+ * Currently, we know we can do mod exp iff we can do any asymmetric
+ * operations at all.
+ */
+ if (cryptodev_asymfeat == 0) {
+ ret = BN_mod_exp(r, a, p, m, ctx);
+ return (ret);
+ }
+
+ memset(&kop, 0, sizeof(kop));
+ kop.crk_op = CRK_MOD_EXP;
+
+ /* inputs: a^p % m */
+ if (bn2crparam(a, &kop.crk_param[0]))
+ goto err;
+ if (bn2crparam(p, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(m, &kop.crk_param[2]))
+ goto err;
+ kop.crk_iparams = 3;
+
+ if (cryptodev_asym(&kop, BN_num_bytes(m), r, 0, NULL)) {
+ const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
+ printf("OCF asym process failed, Running in software\n");
+ ret = RSA_meth_get_bn_mod_exp(meth)(r, a, p, m, ctx, in_mont);
+
+ } else if (ECANCELED == kop.crk_status) {
+ const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
+ printf("OCF hardware operation cancelled. Running in Software\n");
+ ret = RSA_meth_get_bn_mod_exp(meth)(r, a, p, m, ctx, in_mont);
+ }
+ /* else cryptodev operation worked ok ==> ret = 1 */
+
+ err:
+ zapparams(&kop);
+ return (ret);
+}
+
+static int
+cryptodev_rsa_nocrt_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
+ BN_CTX *ctx)
+{
+ int r;
+ const BIGNUM *n = NULL;
+ const BIGNUM *d = NULL;
+
+ ctx = BN_CTX_new();
+ RSA_get0_key(rsa, &n, NULL, &d);
+ r = cryptodev_bn_mod_exp(r0, I, d, n, ctx, NULL);
+ BN_CTX_free(ctx);
+ return (r);
+}
+
+static int
+cryptodev_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
+{
+ struct crypt_kop kop;
+ int ret = 1;
+ const BIGNUM *p = NULL;
+ const BIGNUM *q = NULL;
+ const BIGNUM *dmp1 = NULL;
+ const BIGNUM *dmq1 = NULL;
+ const BIGNUM *iqmp = NULL;
+ const BIGNUM *n = NULL;
+
+ RSA_get0_factors(rsa, &p, &q);
+ RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
+ RSA_get0_key(rsa, &n, NULL, NULL);
+
+ if (!p || !q || !dmp1 || !dmq1 || !iqmp) {
+ /* XXX 0 means failure?? */
+ return (0);
+ }
+
+ memset(&kop, 0, sizeof(kop));
+ kop.crk_op = CRK_MOD_EXP_CRT;
+ /* inputs: rsa->p rsa->q I rsa->dmp1 rsa->dmq1 rsa->iqmp */
+ if (bn2crparam(p, &kop.crk_param[0]))
+ goto err;
+ if (bn2crparam(q, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(I, &kop.crk_param[2]))
+ goto err;
+ if (bn2crparam(dmp1, &kop.crk_param[3]))
+ goto err;
+ if (bn2crparam(dmq1, &kop.crk_param[4]))
+ goto err;
+ if (bn2crparam(iqmp, &kop.crk_param[5]))
+ goto err;
+ kop.crk_iparams = 6;
+
+ if (cryptodev_asym(&kop, BN_num_bytes(n), r0, 0, NULL)) {
+ const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
+ printf("OCF asym process failed, running in Software\n");
+ ret = RSA_meth_get_mod_exp(meth)(r0, I, rsa, ctx);
+
+ } else if (ECANCELED == kop.crk_status) {
+ const RSA_METHOD *meth = RSA_PKCS1_OpenSSL();
+ printf("OCF hardware operation cancelled. Running in Software\n");
+ ret = RSA_meth_get_mod_exp(meth)(r0, I, rsa, ctx);
+ }
+ /* else cryptodev operation worked ok ==> ret = 1 */
+
+ err:
+ zapparams(&kop);
+ return (ret);
+}
+
+#ifndef OPENSSL_NO_DSA
+static int
+cryptodev_dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+ const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+{
+ return cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx);
+}
+
+static int
+cryptodev_dsa_dsa_mod_exp(DSA *dsa, BIGNUM *t1, const BIGNUM *g,
+ const BIGNUM *u1, const BIGNUM *pub_key,
+ const BIGNUM *u2, const BIGNUM *p, BN_CTX *ctx,
+ BN_MONT_CTX *mont)
+{
+ const BIGNUM *dsag, *dsap, *dsapub_key;
+ BIGNUM *t2;
+ int ret = 0;
+ const DSA_METHOD *meth;
+ int (*bn_mod_exp)(DSA *, BIGNUM *, const BIGNUM *, const BIGNUM *, const BIGNUM *,
+ BN_CTX *, BN_MONT_CTX *);
+
+ t2 = BN_new();
+ if (t2 == NULL)
+ goto err;
+
+ /* v = ( g^u1 * y^u2 mod p ) mod q */
+ /* let t1 = g ^ u1 mod p */
+ ret = 0;
+
+ DSA_get0_pqg(dsa, &dsap, NULL, &dsag);
+ DSA_get0_key(dsa, &dsapub_key, NULL);
+
+ meth = DSA_get_method(dsa);
+ if (meth == NULL)
+ goto err;
+ bn_mod_exp = DSA_meth_get_bn_mod_exp(meth);
+ if (bn_mod_exp == NULL)
+ goto err;
+
+ if (!bn_mod_exp(dsa, t1, dsag, u1, dsap, ctx, mont))
+ goto err;
+
+ /* let t2 = y ^ u2 mod p */
+ if (!bn_mod_exp(dsa, t2, dsapub_key, u2, dsap, ctx, mont))
+ goto err;
+ /* let t1 = t1 * t2 mod p */
+ if (!BN_mod_mul(t1, t1, t2, dsap, ctx))
+ goto err;
+
+ ret = 1;
+ err:
+ BN_free(t2);
+ return (ret);
+}
+
+static DSA_SIG *cryptodev_dsa_do_sign(const unsigned char *dgst, int dlen,
+ DSA *dsa)
+{
+ struct crypt_kop kop;
+ BIGNUM *r, *s;
+ const BIGNUM *dsap = NULL, *dsaq = NULL, *dsag = NULL;
+ const BIGNUM *priv_key = NULL;
+ DSA_SIG *dsasig, *dsaret = NULL;
+
+ dsasig = DSA_SIG_new();
+ if (dsasig == NULL)
+ goto err;
+
+ memset(&kop, 0, sizeof(kop));
+ kop.crk_op = CRK_DSA_SIGN;
+
+ /* inputs: dgst dsa->p dsa->q dsa->g dsa->priv_key */
+ kop.crk_param[0].crp_p = (caddr_t) dgst;
+ kop.crk_param[0].crp_nbits = dlen * 8;
+ DSA_get0_pqg(dsa, &dsap, &dsaq, &dsag);
+ DSA_get0_key(dsa, NULL, &priv_key);
+ if (bn2crparam(dsap, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(dsaq, &kop.crk_param[2]))
+ goto err;
+ if (bn2crparam(dsag, &kop.crk_param[3]))
+ goto err;
+ if (bn2crparam(priv_key, &kop.crk_param[4]))
+ goto err;
+ kop.crk_iparams = 5;
+
+ r = BN_new();
+ if (r == NULL)
+ goto err;
+ s = BN_new();
+ if (s == NULL)
+ goto err;
+ if (cryptodev_asym(&kop, BN_num_bytes(dsaq), r,
+ BN_num_bytes(dsaq), s) == 0) {
+ DSA_SIG_set0(dsasig, r, s);
+ dsaret = dsasig;
+ } else {
+ dsaret = DSA_meth_get_sign(DSA_OpenSSL())(dgst, dlen, dsa);
+ }
+ err:
+ if (dsaret != dsasig)
+ DSA_SIG_free(dsasig);
+ kop.crk_param[0].crp_p = NULL;
+ zapparams(&kop);
+ return dsaret;
+}
+
+static int
+cryptodev_dsa_verify(const unsigned char *dgst, int dlen,
+ DSA_SIG *sig, DSA *dsa)
+{
+ struct crypt_kop kop;
+ int dsaret = 1;
+ const BIGNUM *pr, *ps, *p = NULL, *q = NULL, *g = NULL, *pub_key = NULL;
+
+ memset(&kop, 0, sizeof(kop));
+ kop.crk_op = CRK_DSA_VERIFY;
+
+ /* inputs: dgst dsa->p dsa->q dsa->g dsa->pub_key sig->r sig->s */
+ kop.crk_param[0].crp_p = (caddr_t) dgst;
+ kop.crk_param[0].crp_nbits = dlen * 8;
+ DSA_get0_pqg(dsa, &p, &q, &g);
+ if (bn2crparam(p, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(q, &kop.crk_param[2]))
+ goto err;
+ if (bn2crparam(g, &kop.crk_param[3]))
+ goto err;
+ DSA_get0_key(dsa, &pub_key, NULL);
+ if (bn2crparam(pub_key, &kop.crk_param[4]))
+ goto err;
+ DSA_SIG_get0(sig, &pr, &ps);
+ if (bn2crparam(pr, &kop.crk_param[5]))
+ goto err;
+ if (bn2crparam(ps, &kop.crk_param[6]))
+ goto err;
+ kop.crk_iparams = 7;
+
+ if (cryptodev_asym(&kop, 0, NULL, 0, NULL) == 0) {
+ /*
+ * OCF success value is 0, if not zero, change dsaret to fail
+ */
+ if (0 != kop.crk_status)
+ dsaret = 0;
+ } else {
+ dsaret = DSA_meth_get_verify(DSA_OpenSSL())(dgst, dlen, sig, dsa);
+ }
+ err:
+ kop.crk_param[0].crp_p = NULL;
+ zapparams(&kop);
+ return (dsaret);
+}
+#endif
+
+#ifndef OPENSSL_NO_DH
+static int
+cryptodev_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
+ const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+ BN_MONT_CTX *m_ctx)
+{
+ return (cryptodev_bn_mod_exp(r, a, p, m, ctx, m_ctx));
+}
+
+static int
+cryptodev_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
+{
+ struct crypt_kop kop;
+ int dhret = 1;
+ int fd, keylen;
+ const BIGNUM *p = NULL;
+ const BIGNUM *priv_key = NULL;
+
+ if ((fd = get_asym_dev_crypto()) < 0) {
+ const DH_METHOD *meth = DH_OpenSSL();
+
+ return DH_meth_get_compute_key(meth)(key, pub_key, dh);
+ }
+
+ DH_get0_pqg(dh, &p, NULL, NULL);
+ DH_get0_key(dh, NULL, &priv_key);
+
+ keylen = BN_num_bits(p);
+
+ memset(&kop, 0, sizeof(kop));
+ kop.crk_op = CRK_DH_COMPUTE_KEY;
+
+ /* inputs: dh->priv_key pub_key dh->p key */
+ if (bn2crparam(priv_key, &kop.crk_param[0]))
+ goto err;
+ if (bn2crparam(pub_key, &kop.crk_param[1]))
+ goto err;
+ if (bn2crparam(p, &kop.crk_param[2]))
+ goto err;
+ kop.crk_iparams = 3;
+
+ kop.crk_param[3].crp_p = (caddr_t) key;
+ kop.crk_param[3].crp_nbits = keylen * 8;
+ kop.crk_oparams = 1;
+
+ if (ioctl(fd, CIOCKEY, &kop) == -1) {
+ const DH_METHOD *meth = DH_OpenSSL();
+
+ dhret = DH_meth_get_compute_key(meth)(key, pub_key, dh);
+ }
+ err:
+ kop.crk_param[3].crp_p = NULL;
+ zapparams(&kop);
+ return (dhret);
+}
+
+#endif /* ndef OPENSSL_NO_DH */
+
+/*
+ * ctrl right now is just a wrapper that doesn't do much
+ * but I expect we'll want some options soon.
+ */
+static int
+cryptodev_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+{
+# ifdef HAVE_SYSLOG_R
+ struct syslog_data sd = SYSLOG_DATA_INIT;
+# endif
+
+ switch (cmd) {
+ default:
+# ifdef HAVE_SYSLOG_R
+ syslog_r(LOG_ERR, &sd, "cryptodev_ctrl: unknown command %d", cmd);
+# else
+ syslog(LOG_ERR, "cryptodev_ctrl: unknown command %d", cmd);
+# endif
+ break;
+ }
+ return (1);
+}
+
+void engine_load_cryptodev_int(void)
+{
+ ENGINE *engine = ENGINE_new();
+ int fd;
+
+ if (engine == NULL)
+ return;
+ if ((fd = get_dev_crypto()) < 0) {
+ ENGINE_free(engine);
+ return;
+ }
+
+ /*
+ * find out what asymmetric crypto algorithms we support
+ */
+ if (ioctl(fd, CIOCASYMFEAT, &cryptodev_asymfeat) == -1) {
+ put_dev_crypto(fd);
+ ENGINE_free(engine);
+ return;
+ }
+ put_dev_crypto(fd);
+
+ if (!ENGINE_set_id(engine, "cryptodev") ||
+ !ENGINE_set_name(engine, "BSD cryptodev engine") ||
+ !ENGINE_set_destroy_function(engine, cryptodev_engine_destroy) ||
+ !ENGINE_set_ciphers(engine, cryptodev_engine_ciphers) ||
+ !ENGINE_set_digests(engine, cryptodev_engine_digests) ||
+ !ENGINE_set_ctrl_function(engine, cryptodev_ctrl) ||
+ !ENGINE_set_cmd_defns(engine, cryptodev_defns)) {
+ ENGINE_free(engine);
+ return;
+ }
+
+ cryptodev_rsa = RSA_meth_dup(RSA_PKCS1_OpenSSL());
+ if (cryptodev_rsa != NULL) {
+ RSA_meth_set1_name(cryptodev_rsa, "cryptodev RSA method");
+ RSA_meth_set_flags(cryptodev_rsa, 0);
+ if (ENGINE_set_RSA(engine, cryptodev_rsa)) {
+ if (cryptodev_asymfeat & CRF_MOD_EXP) {
+ RSA_meth_set_bn_mod_exp(cryptodev_rsa, cryptodev_bn_mod_exp);
+ if (cryptodev_asymfeat & CRF_MOD_EXP_CRT)
+ RSA_meth_set_mod_exp(cryptodev_rsa, cryptodev_rsa_mod_exp);
+ else
+ RSA_meth_set_mod_exp(cryptodev_rsa,
+ cryptodev_rsa_nocrt_mod_exp);
+ }
+ }
+ } else {
+ ENGINE_free(engine);
+ return;
+ }
+
+#ifndef OPENSSL_NO_DSA
+ cryptodev_dsa = DSA_meth_dup(DSA_OpenSSL());
+ if (cryptodev_dsa != NULL) {
+ DSA_meth_set1_name(cryptodev_dsa, "cryptodev DSA method");
+ DSA_meth_set_flags(cryptodev_dsa, 0);
+ if (ENGINE_set_DSA(engine, cryptodev_dsa)) {
+ if (cryptodev_asymfeat & CRF_DSA_SIGN)
+ DSA_meth_set_sign(cryptodev_dsa, cryptodev_dsa_do_sign);
+ if (cryptodev_asymfeat & CRF_MOD_EXP) {
+ DSA_meth_set_bn_mod_exp(cryptodev_dsa,
+ cryptodev_dsa_bn_mod_exp);
+ DSA_meth_set_mod_exp(cryptodev_dsa, cryptodev_dsa_dsa_mod_exp);
+ }
+ if (cryptodev_asymfeat & CRF_DSA_VERIFY)
+ DSA_meth_set_verify(cryptodev_dsa, cryptodev_dsa_verify);
+ }
+ } else {
+ ENGINE_free(engine);
+ return;
+ }
+#endif
+
+#ifndef OPENSSL_NO_DH
+ cryptodev_dh = DH_meth_dup(DH_OpenSSL());
+ if (cryptodev_dh != NULL) {
+ DH_meth_set1_name(cryptodev_dh, "cryptodev DH method");
+ DH_meth_set_flags(cryptodev_dh, 0);
+ if (ENGINE_set_DH(engine, cryptodev_dh)) {
+ if (cryptodev_asymfeat & CRF_MOD_EXP) {
+ DH_meth_set_bn_mod_exp(cryptodev_dh, cryptodev_mod_exp_dh);
+ if (cryptodev_asymfeat & CRF_DH_COMPUTE_KEY)
+ DH_meth_set_compute_key(cryptodev_dh,
+ cryptodev_dh_compute_key);
+ }
+ }
+ } else {
+ ENGINE_free(engine);
+ return;
+ }
+#endif
+
+ ENGINE_add(engine);
+ ENGINE_free(engine);
+ ERR_clear_error();
+}
+
+#endif /* HAVE_CRYPTODEV */
diff --git a/openssl-1.1.0h/crypto/engine/eng_ctrl.c b/openssl-1.1.0h/crypto/engine/eng_ctrl.c
new file mode 100644
index 0000000..7925f4f
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_ctrl.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+/*
+ * When querying a ENGINE-specific control command's 'description', this
+ * string is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL.
+ */
+static const char *int_no_description = "";
+
+/*
+ * These internal functions handle 'CMD'-related control commands when the
+ * ENGINE in question has asked us to take care of it (ie. the ENGINE did not
+ * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag.
+ */
+
+static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN *defn)
+{
+ if ((defn->cmd_num == 0) || (defn->cmd_name == NULL))
+ return 1;
+ return 0;
+}
+
+static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN *defn, const char *s)
+{
+ int idx = 0;
+ while (!int_ctrl_cmd_is_null(defn) && (strcmp(defn->cmd_name, s) != 0)) {
+ idx++;
+ defn++;
+ }
+ if (int_ctrl_cmd_is_null(defn))
+ /* The given name wasn't found */
+ return -1;
+ return idx;
+}
+
+static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num)
+{
+ int idx = 0;
+ /*
+ * NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So
+ * our searches don't need to take any longer than necessary.
+ */
+ while (!int_ctrl_cmd_is_null(defn) && (defn->cmd_num < num)) {
+ idx++;
+ defn++;
+ }
+ if (defn->cmd_num == num)
+ return idx;
+ /* The given cmd_num wasn't found */
+ return -1;
+}
+
+static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p,
+ void (*f) (void))
+{
+ int idx;
+ char *s = (char *)p;
+ /* Take care of the easy one first (eg. it requires no searches) */
+ if (cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE) {
+ if ((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns))
+ return 0;
+ return e->cmd_defns->cmd_num;
+ }
+ /* One or two commands require that "p" be a valid string buffer */
+ if ((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) ||
+ (cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) ||
+ (cmd == ENGINE_CTRL_GET_DESC_FROM_CMD)) {
+ if (s == NULL) {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ERR_R_PASSED_NULL_PARAMETER);
+ return -1;
+ }
+ }
+ /* Now handle cmd_name -> cmd_num conversion */
+ if (cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) {
+ if ((e->cmd_defns == NULL)
+ || ((idx = int_ctrl_cmd_by_name(e->cmd_defns, s)) < 0)) {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NAME);
+ return -1;
+ }
+ return e->cmd_defns[idx].cmd_num;
+ }
+ /*
+ * For the rest of the commands, the 'long' argument must specify a valid
+ * command number - so we need to conduct a search.
+ */
+ if ((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_num(e->cmd_defns,
+ (unsigned int)
+ i)) < 0)) {
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NUMBER);
+ return -1;
+ }
+ /* Now the logic splits depending on command type */
+ switch (cmd) {
+ case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
+ idx++;
+ if (int_ctrl_cmd_is_null(e->cmd_defns + idx))
+ /* end-of-list */
+ return 0;
+ else
+ return e->cmd_defns[idx].cmd_num;
+ case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
+ return strlen(e->cmd_defns[idx].cmd_name);
+ case ENGINE_CTRL_GET_NAME_FROM_CMD:
+ return BIO_snprintf(s, strlen(e->cmd_defns[idx].cmd_name) + 1,
+ "%s", e->cmd_defns[idx].cmd_name);
+ case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
+ if (e->cmd_defns[idx].cmd_desc)
+ return strlen(e->cmd_defns[idx].cmd_desc);
+ return strlen(int_no_description);
+ case ENGINE_CTRL_GET_DESC_FROM_CMD:
+ if (e->cmd_defns[idx].cmd_desc)
+ return BIO_snprintf(s,
+ strlen(e->cmd_defns[idx].cmd_desc) + 1,
+ "%s", e->cmd_defns[idx].cmd_desc);
+ return BIO_snprintf(s, strlen(int_no_description) + 1, "%s",
+ int_no_description);
+ case ENGINE_CTRL_GET_CMD_FLAGS:
+ return e->cmd_defns[idx].cmd_flags;
+ }
+ /* Shouldn't really be here ... */
+ ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INTERNAL_LIST_ERROR);
+ return -1;
+}
+
+int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+{
+ int ctrl_exists, ref_exists;
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ ref_exists = ((e->struct_ref > 0) ? 1 : 0);
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ ctrl_exists = ((e->ctrl == NULL) ? 0 : 1);
+ if (!ref_exists) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_REFERENCE);
+ return 0;
+ }
+ /*
+ * Intercept any "root-level" commands before trying to hand them on to
+ * ctrl() handlers.
+ */
+ switch (cmd) {
+ case ENGINE_CTRL_HAS_CTRL_FUNCTION:
+ return ctrl_exists;
+ case ENGINE_CTRL_GET_FIRST_CMD_TYPE:
+ case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
+ case ENGINE_CTRL_GET_CMD_FROM_NAME:
+ case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
+ case ENGINE_CTRL_GET_NAME_FROM_CMD:
+ case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
+ case ENGINE_CTRL_GET_DESC_FROM_CMD:
+ case ENGINE_CTRL_GET_CMD_FLAGS:
+ if (ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL))
+ return int_ctrl_helper(e, cmd, i, p, f);
+ if (!ctrl_exists) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION);
+ /*
+ * For these cmd-related functions, failure is indicated by a -1
+ * return value (because 0 is used as a valid return in some
+ * places).
+ */
+ return -1;
+ }
+ default:
+ break;
+ }
+ /* Anything else requires a ctrl() handler to exist. */
+ if (!ctrl_exists) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION);
+ return 0;
+ }
+ return e->ctrl(e, cmd, i, p, f);
+}
+
+int ENGINE_cmd_is_executable(ENGINE *e, int cmd)
+{
+ int flags;
+ if ((flags =
+ ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0) {
+ ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE,
+ ENGINE_R_INVALID_CMD_NUMBER);
+ return 0;
+ }
+ if (!(flags & ENGINE_CMD_FLAG_NO_INPUT) &&
+ !(flags & ENGINE_CMD_FLAG_NUMERIC) &&
+ !(flags & ENGINE_CMD_FLAG_STRING))
+ return 0;
+ return 1;
+}
+
+int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name,
+ long i, void *p, void (*f) (void), int cmd_optional)
+{
+ int num;
+
+ if (e == NULL || cmd_name == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (e->ctrl == NULL
+ || (num = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) <= 0) {
+ /*
+ * If the command didn't *have* to be supported, we fake success.
+ * This allows certain settings to be specified for multiple ENGINEs
+ * and only require a change of ENGINE id (without having to
+ * selectively apply settings). Eg. changing from a hardware device
+ * back to the regular software ENGINE without editing the config
+ * file, etc.
+ */
+ if (cmd_optional) {
+ ERR_clear_error();
+ return 1;
+ }
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ENGINE_R_INVALID_CMD_NAME);
+ return 0;
+ }
+ /*
+ * Force the result of the control command to 0 or 1, for the reasons
+ * mentioned before.
+ */
+ if (ENGINE_ctrl(e, num, i, p, f) > 0)
+ return 1;
+ return 0;
+}
+
+int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
+ int cmd_optional)
+{
+ int num, flags;
+ long l;
+ char *ptr;
+
+ if (e == NULL || cmd_name == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (e->ctrl == NULL
+ || (num = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FROM_NAME,
+ 0, (void *)cmd_name, NULL)) <= 0) {
+ /*
+ * If the command didn't *have* to be supported, we fake success.
+ * This allows certain settings to be specified for multiple ENGINEs
+ * and only require a change of ENGINE id (without having to
+ * selectively apply settings). Eg. changing from a hardware device
+ * back to the regular software ENGINE without editing the config
+ * file, etc.
+ */
+ if (cmd_optional) {
+ ERR_clear_error();
+ return 1;
+ }
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ENGINE_R_INVALID_CMD_NAME);
+ return 0;
+ }
+ if (!ENGINE_cmd_is_executable(e, num)) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_CMD_NOT_EXECUTABLE);
+ return 0;
+ }
+
+ flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL);
+ if (flags < 0) {
+ /*
+ * Shouldn't happen, given that ENGINE_cmd_is_executable() returned
+ * success.
+ */
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ /*
+ * If the command takes no input, there must be no input. And vice versa.
+ */
+ if (flags & ENGINE_CMD_FLAG_NO_INPUT) {
+ if (arg != NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_COMMAND_TAKES_NO_INPUT);
+ return 0;
+ }
+ /*
+ * We deliberately force the result of ENGINE_ctrl() to 0 or 1 rather
+ * than returning it as "return data". This is to ensure usage of
+ * these commands is consistent across applications and that certain
+ * applications don't understand it one way, and others another.
+ */
+ if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0)
+ return 1;
+ return 0;
+ }
+ /* So, we require input */
+ if (arg == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_COMMAND_TAKES_INPUT);
+ return 0;
+ }
+ /* If it takes string input, that's easy */
+ if (flags & ENGINE_CMD_FLAG_STRING) {
+ /* Same explanation as above */
+ if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0)
+ return 1;
+ return 0;
+ }
+ /*
+ * If it doesn't take numeric either, then it is unsupported for use in a
+ * config-setting situation, which is what this function is for. This
+ * should never happen though, because ENGINE_cmd_is_executable() was
+ * used.
+ */
+ if (!(flags & ENGINE_CMD_FLAG_NUMERIC)) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ l = strtol(arg, &ptr, 10);
+ if ((arg == ptr) || (*ptr != '\0')) {
+ ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
+ ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER);
+ return 0;
+ }
+ /*
+ * Force the result of the control command to 0 or 1, for the reasons
+ * mentioned before.
+ */
+ if (ENGINE_ctrl(e, num, l, NULL, NULL) > 0)
+ return 1;
+ return 0;
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_dyn.c b/openssl-1.1.0h/crypto/engine/eng_dyn.c
new file mode 100644
index 0000000..843226c
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_dyn.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+#include "internal/dso.h"
+#include <openssl/crypto.h>
+
+/*
+ * Shared libraries implementing ENGINEs for use by the "dynamic" ENGINE
+ * loader should implement the hook-up functions with the following
+ * prototypes.
+ */
+
+/* Our ENGINE handlers */
+static int dynamic_init(ENGINE *e);
+static int dynamic_finish(ENGINE *e);
+static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p,
+ void (*f) (void));
+/* Predeclare our context type */
+typedef struct st_dynamic_data_ctx dynamic_data_ctx;
+/* The implementation for the important control command */
+static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx);
+
+#define DYNAMIC_CMD_SO_PATH ENGINE_CMD_BASE
+#define DYNAMIC_CMD_NO_VCHECK (ENGINE_CMD_BASE + 1)
+#define DYNAMIC_CMD_ID (ENGINE_CMD_BASE + 2)
+#define DYNAMIC_CMD_LIST_ADD (ENGINE_CMD_BASE + 3)
+#define DYNAMIC_CMD_DIR_LOAD (ENGINE_CMD_BASE + 4)
+#define DYNAMIC_CMD_DIR_ADD (ENGINE_CMD_BASE + 5)
+#define DYNAMIC_CMD_LOAD (ENGINE_CMD_BASE + 6)
+
+/* The constants used when creating the ENGINE */
+static const char *engine_dynamic_id = "dynamic";
+static const char *engine_dynamic_name = "Dynamic engine loading support";
+static const ENGINE_CMD_DEFN dynamic_cmd_defns[] = {
+ {DYNAMIC_CMD_SO_PATH,
+ "SO_PATH",
+ "Specifies the path to the new ENGINE shared library",
+ ENGINE_CMD_FLAG_STRING},
+ {DYNAMIC_CMD_NO_VCHECK,
+ "NO_VCHECK",
+ "Specifies to continue even if version checking fails (boolean)",
+ ENGINE_CMD_FLAG_NUMERIC},
+ {DYNAMIC_CMD_ID,
+ "ID",
+ "Specifies an ENGINE id name for loading",
+ ENGINE_CMD_FLAG_STRING},
+ {DYNAMIC_CMD_LIST_ADD,
+ "LIST_ADD",
+ "Whether to add a loaded ENGINE to the internal list (0=no,1=yes,2=mandatory)",
+ ENGINE_CMD_FLAG_NUMERIC},
+ {DYNAMIC_CMD_DIR_LOAD,
+ "DIR_LOAD",
+ "Specifies whether to load from 'DIR_ADD' directories (0=no,1=yes,2=mandatory)",
+ ENGINE_CMD_FLAG_NUMERIC},
+ {DYNAMIC_CMD_DIR_ADD,
+ "DIR_ADD",
+ "Adds a directory from which ENGINEs can be loaded",
+ ENGINE_CMD_FLAG_STRING},
+ {DYNAMIC_CMD_LOAD,
+ "LOAD",
+ "Load up the ENGINE specified by other settings",
+ ENGINE_CMD_FLAG_NO_INPUT},
+ {0, NULL, NULL, 0}
+};
+
+/*
+ * Loading code stores state inside the ENGINE structure via the "ex_data"
+ * element. We load all our state into a single structure and use that as a
+ * single context in the "ex_data" stack.
+ */
+struct st_dynamic_data_ctx {
+ /* The DSO object we load that supplies the ENGINE code */
+ DSO *dynamic_dso;
+ /*
+ * The function pointer to the version checking shared library function
+ */
+ dynamic_v_check_fn v_check;
+ /*
+ * The function pointer to the engine-binding shared library function
+ */
+ dynamic_bind_engine bind_engine;
+ /* The default name/path for loading the shared library */
+ char *DYNAMIC_LIBNAME;
+ /* Whether to continue loading on a version check failure */
+ int no_vcheck;
+ /* If non-NULL, stipulates the 'id' of the ENGINE to be loaded */
+ char *engine_id;
+ /*
+ * If non-zero, a successfully loaded ENGINE should be added to the
+ * internal ENGINE list. If 2, the add must succeed or the entire load
+ * should fail.
+ */
+ int list_add_value;
+ /* The symbol name for the version checking function */
+ const char *DYNAMIC_F1;
+ /* The symbol name for the "initialise ENGINE structure" function */
+ const char *DYNAMIC_F2;
+ /*
+ * Whether to never use 'dirs', use 'dirs' as a fallback, or only use
+ * 'dirs' for loading. Default is to use 'dirs' as a fallback.
+ */
+ int dir_load;
+ /* A stack of directories from which ENGINEs could be loaded */
+ STACK_OF(OPENSSL_STRING) *dirs;
+};
+
+/*
+ * This is the "ex_data" index we obtain and reserve for use with our context
+ * structure.
+ */
+static int dynamic_ex_data_idx = -1;
+
+static void int_free_str(char *s)
+{
+ OPENSSL_free(s);
+}
+
+/*
+ * Because our ex_data element may or may not get allocated depending on
+ * whether a "first-use" occurs before the ENGINE is freed, we have a memory
+ * leak problem to solve. We can't declare a "new" handler for the ex_data as
+ * we don't want a dynamic_data_ctx in *all* ENGINE structures of all types
+ * (this is a bug in the design of CRYPTO_EX_DATA). As such, we just declare
+ * a "free" handler and that will get called if an ENGINE is being destroyed
+ * and there was an ex_data element corresponding to our context type.
+ */
+static void dynamic_data_ctx_free_func(void *parent, void *ptr,
+ CRYPTO_EX_DATA *ad, int idx, long argl,
+ void *argp)
+{
+ if (ptr) {
+ dynamic_data_ctx *ctx = (dynamic_data_ctx *)ptr;
+ DSO_free(ctx->dynamic_dso);
+ OPENSSL_free(ctx->DYNAMIC_LIBNAME);
+ OPENSSL_free(ctx->engine_id);
+ sk_OPENSSL_STRING_pop_free(ctx->dirs, int_free_str);
+ OPENSSL_free(ctx);
+ }
+}
+
+/*
+ * Construct the per-ENGINE context. We create it blindly and then use a lock
+ * to check for a race - if so, all but one of the threads "racing" will have
+ * wasted their time. The alternative involves creating everything inside the
+ * lock which is far worse.
+ */
+static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx)
+{
+ dynamic_data_ctx *c = OPENSSL_zalloc(sizeof(*c));
+ int ret = 1;
+
+ if (c == NULL) {
+ ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ c->dirs = sk_OPENSSL_STRING_new_null();
+ if (c->dirs == NULL) {
+ ENGINEerr(ENGINE_F_DYNAMIC_SET_DATA_CTX, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(c);
+ return 0;
+ }
+ c->DYNAMIC_F1 = "v_check";
+ c->DYNAMIC_F2 = "bind_engine";
+ c->dir_load = 1;
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if ((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e,
+ dynamic_ex_data_idx))
+ == NULL) {
+ /* Good, we're the first */
+ ret = ENGINE_set_ex_data(e, dynamic_ex_data_idx, c);
+ if (ret) {
+ *ctx = c;
+ c = NULL;
+ }
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ /*
+ * If we lost the race to set the context, c is non-NULL and *ctx is the
+ * context of the thread that won.
+ */
+ if (c)
+ sk_OPENSSL_STRING_free(c->dirs);
+ OPENSSL_free(c);
+ return ret;
+}
+
+/*
+ * This function retrieves the context structure from an ENGINE's "ex_data",
+ * or if it doesn't exist yet, sets it up.
+ */
+static dynamic_data_ctx *dynamic_get_data_ctx(ENGINE *e)
+{
+ dynamic_data_ctx *ctx;
+ if (dynamic_ex_data_idx < 0) {
+ /*
+ * Create and register the ENGINE ex_data, and associate our "free"
+ * function with it to ensure any allocated contexts get freed when
+ * an ENGINE goes underground.
+ */
+ int new_idx = ENGINE_get_ex_new_index(0, NULL, NULL, NULL,
+ dynamic_data_ctx_free_func);
+ if (new_idx == -1) {
+ ENGINEerr(ENGINE_F_DYNAMIC_GET_DATA_CTX, ENGINE_R_NO_INDEX);
+ return NULL;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ /* Avoid a race by checking again inside this lock */
+ if (dynamic_ex_data_idx < 0) {
+ /* Good, someone didn't beat us to it */
+ dynamic_ex_data_idx = new_idx;
+ new_idx = -1;
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ /*
+ * In theory we could "give back" the index here if (new_idx>-1), but
+ * it's not possible and wouldn't gain us much if it were.
+ */
+ }
+ ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e, dynamic_ex_data_idx);
+ /* Check if the context needs to be created */
+ if ((ctx == NULL) && !dynamic_set_data_ctx(e, &ctx))
+ /* "set_data" will set errors if necessary */
+ return NULL;
+ return ctx;
+}
+
+static ENGINE *engine_dynamic(void)
+{
+ ENGINE *ret = ENGINE_new();
+ if (ret == NULL)
+ return NULL;
+ if (!ENGINE_set_id(ret, engine_dynamic_id) ||
+ !ENGINE_set_name(ret, engine_dynamic_name) ||
+ !ENGINE_set_init_function(ret, dynamic_init) ||
+ !ENGINE_set_finish_function(ret, dynamic_finish) ||
+ !ENGINE_set_ctrl_function(ret, dynamic_ctrl) ||
+ !ENGINE_set_flags(ret, ENGINE_FLAGS_BY_ID_COPY) ||
+ !ENGINE_set_cmd_defns(ret, dynamic_cmd_defns)) {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+void engine_load_dynamic_int(void)
+{
+ ENGINE *toadd = engine_dynamic();
+ if (!toadd)
+ return;
+ ENGINE_add(toadd);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
+ ENGINE_free(toadd);
+ /*
+ * If the "add" didn't work, it was probably a conflict because it was
+ * already added (eg. someone calling ENGINE_load_blah then calling
+ * ENGINE_load_builtin_engines() perhaps).
+ */
+ ERR_clear_error();
+}
+
+static int dynamic_init(ENGINE *e)
+{
+ /*
+ * We always return failure - the "dynamic" engine itself can't be used
+ * for anything.
+ */
+ return 0;
+}
+
+static int dynamic_finish(ENGINE *e)
+{
+ /*
+ * This should never be called on account of "dynamic_init" always
+ * failing.
+ */
+ return 0;
+}
+
+static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+{
+ dynamic_data_ctx *ctx = dynamic_get_data_ctx(e);
+ int initialised;
+
+ if (!ctx) {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_NOT_LOADED);
+ return 0;
+ }
+ initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1);
+ /* All our control commands require the ENGINE to be uninitialised */
+ if (initialised) {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_ALREADY_LOADED);
+ return 0;
+ }
+ switch (cmd) {
+ case DYNAMIC_CMD_SO_PATH:
+ /* a NULL 'p' or a string of zero-length is the same thing */
+ if (p && (strlen((const char *)p) < 1))
+ p = NULL;
+ OPENSSL_free(ctx->DYNAMIC_LIBNAME);
+ if (p)
+ ctx->DYNAMIC_LIBNAME = OPENSSL_strdup(p);
+ else
+ ctx->DYNAMIC_LIBNAME = NULL;
+ return (ctx->DYNAMIC_LIBNAME ? 1 : 0);
+ case DYNAMIC_CMD_NO_VCHECK:
+ ctx->no_vcheck = ((i == 0) ? 0 : 1);
+ return 1;
+ case DYNAMIC_CMD_ID:
+ /* a NULL 'p' or a string of zero-length is the same thing */
+ if (p && (strlen((const char *)p) < 1))
+ p = NULL;
+ OPENSSL_free(ctx->engine_id);
+ if (p)
+ ctx->engine_id = OPENSSL_strdup(p);
+ else
+ ctx->engine_id = NULL;
+ return (ctx->engine_id ? 1 : 0);
+ case DYNAMIC_CMD_LIST_ADD:
+ if ((i < 0) || (i > 2)) {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
+ return 0;
+ }
+ ctx->list_add_value = (int)i;
+ return 1;
+ case DYNAMIC_CMD_LOAD:
+ return dynamic_load(e, ctx);
+ case DYNAMIC_CMD_DIR_LOAD:
+ if ((i < 0) || (i > 2)) {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
+ return 0;
+ }
+ ctx->dir_load = (int)i;
+ return 1;
+ case DYNAMIC_CMD_DIR_ADD:
+ /* a NULL 'p' or a string of zero-length is the same thing */
+ if (!p || (strlen((const char *)p) < 1)) {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
+ return 0;
+ }
+ {
+ char *tmp_str = OPENSSL_strdup(p);
+ if (tmp_str == NULL) {
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!sk_OPENSSL_STRING_push(ctx->dirs, tmp_str)) {
+ OPENSSL_free(tmp_str);
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ return 1;
+ default:
+ break;
+ }
+ ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+ return 0;
+}
+
+static int int_load(dynamic_data_ctx *ctx)
+{
+ int num, loop;
+ /* Unless told not to, try a direct load */
+ if ((ctx->dir_load != 2) && (DSO_load(ctx->dynamic_dso,
+ ctx->DYNAMIC_LIBNAME, NULL,
+ 0)) != NULL)
+ return 1;
+ /* If we're not allowed to use 'dirs' or we have none, fail */
+ if (!ctx->dir_load || (num = sk_OPENSSL_STRING_num(ctx->dirs)) < 1)
+ return 0;
+ for (loop = 0; loop < num; loop++) {
+ const char *s = sk_OPENSSL_STRING_value(ctx->dirs, loop);
+ char *merge = DSO_merge(ctx->dynamic_dso, ctx->DYNAMIC_LIBNAME, s);
+ if (!merge)
+ return 0;
+ if (DSO_load(ctx->dynamic_dso, merge, NULL, 0)) {
+ /* Found what we're looking for */
+ OPENSSL_free(merge);
+ return 1;
+ }
+ OPENSSL_free(merge);
+ }
+ return 0;
+}
+
+static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
+{
+ ENGINE cpy;
+ dynamic_fns fns;
+
+ if (ctx->dynamic_dso == NULL)
+ ctx->dynamic_dso = DSO_new();
+ if (ctx->dynamic_dso == NULL)
+ return 0;
+ if (!ctx->DYNAMIC_LIBNAME) {
+ if (!ctx->engine_id)
+ return 0;
+ DSO_ctrl(ctx->dynamic_dso, DSO_CTRL_SET_FLAGS,
+ DSO_FLAG_NAME_TRANSLATION_EXT_ONLY, NULL);
+ ctx->DYNAMIC_LIBNAME =
+ DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id);
+ }
+ if (!int_load(ctx)) {
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_NOT_FOUND);
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ return 0;
+ }
+ /* We have to find a bind function otherwise it'll always end badly */
+ if (!
+ (ctx->bind_engine =
+ (dynamic_bind_engine) DSO_bind_func(ctx->dynamic_dso,
+ ctx->DYNAMIC_F2))) {
+ ctx->bind_engine = NULL;
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_FAILURE);
+ return 0;
+ }
+ /* Do we perform version checking? */
+ if (!ctx->no_vcheck) {
+ unsigned long vcheck_res = 0;
+ /*
+ * Now we try to find a version checking function and decide how to
+ * cope with failure if/when it fails.
+ */
+ ctx->v_check =
+ (dynamic_v_check_fn) DSO_bind_func(ctx->dynamic_dso,
+ ctx->DYNAMIC_F1);
+ if (ctx->v_check)
+ vcheck_res = ctx->v_check(OSSL_DYNAMIC_VERSION);
+ /*
+ * We fail if the version checker veto'd the load *or* if it is
+ * deferring to us (by returning its version) and we think it is too
+ * old.
+ */
+ if (vcheck_res < OSSL_DYNAMIC_OLDEST) {
+ /* Fail */
+ ctx->bind_engine = NULL;
+ ctx->v_check = NULL;
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
+ ENGINE_R_VERSION_INCOMPATIBILITY);
+ return 0;
+ }
+ }
+ /*
+ * First binary copy the ENGINE structure so that we can roll back if the
+ * hand-over fails
+ */
+ memcpy(&cpy, e, sizeof(ENGINE));
+ /*
+ * Provide the ERR, "ex_data", memory, and locking callbacks so the
+ * loaded library uses our state rather than its own. FIXME: As noted in
+ * engine.h, much of this would be simplified if each area of code
+ * provided its own "summary" structure of all related callbacks. It
+ * would also increase opaqueness.
+ */
+ fns.static_state = ENGINE_get_static_state();
+ CRYPTO_get_mem_functions(&fns.mem_fns.malloc_fn, &fns.mem_fns.realloc_fn,
+ &fns.mem_fns.free_fn);
+ /*
+ * Now that we've loaded the dynamic engine, make sure no "dynamic"
+ * ENGINE elements will show through.
+ */
+ engine_set_all_null(e);
+
+ /* Try to bind the ENGINE onto our own ENGINE structure */
+ if (!ctx->bind_engine(e, ctx->engine_id, &fns)) {
+ ctx->bind_engine = NULL;
+ ctx->v_check = NULL;
+ DSO_free(ctx->dynamic_dso);
+ ctx->dynamic_dso = NULL;
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_INIT_FAILED);
+ /* Copy the original ENGINE structure back */
+ memcpy(e, &cpy, sizeof(ENGINE));
+ return 0;
+ }
+ /* Do we try to add this ENGINE to the internal list too? */
+ if (ctx->list_add_value > 0) {
+ if (!ENGINE_add(e)) {
+ /* Do we tolerate this or fail? */
+ if (ctx->list_add_value > 1) {
+ /*
+ * Fail - NB: By this time, it's too late to rollback, and
+ * trying to do so allows the bind_engine() code to have
+ * created leaks. We just have to fail where we are, after
+ * the ENGINE has changed.
+ */
+ ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
+ ENGINE_R_CONFLICTING_ENGINE_ID);
+ return 0;
+ }
+ /* Tolerate */
+ ERR_clear_error();
+ }
+ }
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_err.c b/openssl-1.1.0h/crypto/engine/eng_err.c
new file mode 100644
index 0000000..5e9d16f
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_err.c
@@ -0,0 +1,123 @@
+/*
+ * Generated by util/mkerr.pl DO NOT EDIT
+ * Copyright 1995-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 <stdio.h>
+#include <openssl/err.h>
+#include <openssl/engine.h>
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+
+# define ERR_FUNC(func) ERR_PACK(ERR_LIB_ENGINE,func,0)
+# define ERR_REASON(reason) ERR_PACK(ERR_LIB_ENGINE,0,reason)
+
+static ERR_STRING_DATA ENGINE_str_functs[] = {
+ {ERR_FUNC(ENGINE_F_DYNAMIC_CTRL), "dynamic_ctrl"},
+ {ERR_FUNC(ENGINE_F_DYNAMIC_GET_DATA_CTX), "dynamic_get_data_ctx"},
+ {ERR_FUNC(ENGINE_F_DYNAMIC_LOAD), "dynamic_load"},
+ {ERR_FUNC(ENGINE_F_DYNAMIC_SET_DATA_CTX), "dynamic_set_data_ctx"},
+ {ERR_FUNC(ENGINE_F_ENGINE_ADD), "ENGINE_add"},
+ {ERR_FUNC(ENGINE_F_ENGINE_BY_ID), "ENGINE_by_id"},
+ {ERR_FUNC(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE), "ENGINE_cmd_is_executable"},
+ {ERR_FUNC(ENGINE_F_ENGINE_CTRL), "ENGINE_ctrl"},
+ {ERR_FUNC(ENGINE_F_ENGINE_CTRL_CMD), "ENGINE_ctrl_cmd"},
+ {ERR_FUNC(ENGINE_F_ENGINE_CTRL_CMD_STRING), "ENGINE_ctrl_cmd_string"},
+ {ERR_FUNC(ENGINE_F_ENGINE_FINISH), "ENGINE_finish"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_CIPHER), "ENGINE_get_cipher"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_DIGEST), "ENGINE_get_digest"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_FIRST), "ENGINE_get_first"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_LAST), "ENGINE_get_last"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_NEXT), "ENGINE_get_next"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH),
+ "ENGINE_get_pkey_asn1_meth"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_PKEY_METH), "ENGINE_get_pkey_meth"},
+ {ERR_FUNC(ENGINE_F_ENGINE_GET_PREV), "ENGINE_get_prev"},
+ {ERR_FUNC(ENGINE_F_ENGINE_INIT), "ENGINE_init"},
+ {ERR_FUNC(ENGINE_F_ENGINE_LIST_ADD), "engine_list_add"},
+ {ERR_FUNC(ENGINE_F_ENGINE_LIST_REMOVE), "engine_list_remove"},
+ {ERR_FUNC(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY), "ENGINE_load_private_key"},
+ {ERR_FUNC(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY), "ENGINE_load_public_key"},
+ {ERR_FUNC(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT),
+ "ENGINE_load_ssl_client_cert"},
+ {ERR_FUNC(ENGINE_F_ENGINE_NEW), "ENGINE_new"},
+ {ERR_FUNC(ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR),
+ "ENGINE_pkey_asn1_find_str"},
+ {ERR_FUNC(ENGINE_F_ENGINE_REMOVE), "ENGINE_remove"},
+ {ERR_FUNC(ENGINE_F_ENGINE_SET_DEFAULT_STRING),
+ "ENGINE_set_default_string"},
+ {ERR_FUNC(ENGINE_F_ENGINE_SET_ID), "ENGINE_set_id"},
+ {ERR_FUNC(ENGINE_F_ENGINE_SET_NAME), "ENGINE_set_name"},
+ {ERR_FUNC(ENGINE_F_ENGINE_TABLE_REGISTER), "engine_table_register"},
+ {ERR_FUNC(ENGINE_F_ENGINE_UNLOCKED_FINISH), "engine_unlocked_finish"},
+ {ERR_FUNC(ENGINE_F_ENGINE_UP_REF), "ENGINE_up_ref"},
+ {ERR_FUNC(ENGINE_F_INT_CTRL_HELPER), "int_ctrl_helper"},
+ {ERR_FUNC(ENGINE_F_INT_ENGINE_CONFIGURE), "int_engine_configure"},
+ {ERR_FUNC(ENGINE_F_INT_ENGINE_MODULE_INIT), "int_engine_module_init"},
+ {0, NULL}
+};
+
+static ERR_STRING_DATA ENGINE_str_reasons[] = {
+ {ERR_REASON(ENGINE_R_ALREADY_LOADED), "already loaded"},
+ {ERR_REASON(ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER),
+ "argument is not a number"},
+ {ERR_REASON(ENGINE_R_CMD_NOT_EXECUTABLE), "cmd not executable"},
+ {ERR_REASON(ENGINE_R_COMMAND_TAKES_INPUT), "command takes input"},
+ {ERR_REASON(ENGINE_R_COMMAND_TAKES_NO_INPUT), "command takes no input"},
+ {ERR_REASON(ENGINE_R_CONFLICTING_ENGINE_ID), "conflicting engine id"},
+ {ERR_REASON(ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED),
+ "ctrl command not implemented"},
+ {ERR_REASON(ENGINE_R_DSO_FAILURE), "DSO failure"},
+ {ERR_REASON(ENGINE_R_DSO_NOT_FOUND), "dso not found"},
+ {ERR_REASON(ENGINE_R_ENGINES_SECTION_ERROR), "engines section error"},
+ {ERR_REASON(ENGINE_R_ENGINE_CONFIGURATION_ERROR),
+ "engine configuration error"},
+ {ERR_REASON(ENGINE_R_ENGINE_IS_NOT_IN_LIST), "engine is not in the list"},
+ {ERR_REASON(ENGINE_R_ENGINE_SECTION_ERROR), "engine section error"},
+ {ERR_REASON(ENGINE_R_FAILED_LOADING_PRIVATE_KEY),
+ "failed loading private key"},
+ {ERR_REASON(ENGINE_R_FAILED_LOADING_PUBLIC_KEY),
+ "failed loading public key"},
+ {ERR_REASON(ENGINE_R_FINISH_FAILED), "finish failed"},
+ {ERR_REASON(ENGINE_R_ID_OR_NAME_MISSING), "'id' or 'name' missing"},
+ {ERR_REASON(ENGINE_R_INIT_FAILED), "init failed"},
+ {ERR_REASON(ENGINE_R_INTERNAL_LIST_ERROR), "internal list error"},
+ {ERR_REASON(ENGINE_R_INVALID_ARGUMENT), "invalid argument"},
+ {ERR_REASON(ENGINE_R_INVALID_CMD_NAME), "invalid cmd name"},
+ {ERR_REASON(ENGINE_R_INVALID_CMD_NUMBER), "invalid cmd number"},
+ {ERR_REASON(ENGINE_R_INVALID_INIT_VALUE), "invalid init value"},
+ {ERR_REASON(ENGINE_R_INVALID_STRING), "invalid string"},
+ {ERR_REASON(ENGINE_R_NOT_INITIALISED), "not initialised"},
+ {ERR_REASON(ENGINE_R_NOT_LOADED), "not loaded"},
+ {ERR_REASON(ENGINE_R_NO_CONTROL_FUNCTION), "no control function"},
+ {ERR_REASON(ENGINE_R_NO_INDEX), "no index"},
+ {ERR_REASON(ENGINE_R_NO_LOAD_FUNCTION), "no load function"},
+ {ERR_REASON(ENGINE_R_NO_REFERENCE), "no reference"},
+ {ERR_REASON(ENGINE_R_NO_SUCH_ENGINE), "no such engine"},
+ {ERR_REASON(ENGINE_R_UNIMPLEMENTED_CIPHER), "unimplemented cipher"},
+ {ERR_REASON(ENGINE_R_UNIMPLEMENTED_DIGEST), "unimplemented digest"},
+ {ERR_REASON(ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD),
+ "unimplemented public key method"},
+ {ERR_REASON(ENGINE_R_VERSION_INCOMPATIBILITY), "version incompatibility"},
+ {0, NULL}
+};
+
+#endif
+
+int ERR_load_ENGINE_strings(void)
+{
+#ifndef OPENSSL_NO_ERR
+
+ if (ERR_func_error_string(ENGINE_str_functs[0].error) == NULL) {
+ ERR_load_strings(0, ENGINE_str_functs);
+ ERR_load_strings(0, ENGINE_str_reasons);
+ }
+#endif
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_fat.c b/openssl-1.1.0h/crypto/engine/eng_fat.c
new file mode 100644
index 0000000..5cb8187
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_fat.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2001-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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include "eng_int.h"
+#include <openssl/conf.h>
+
+int ENGINE_set_default(ENGINE *e, unsigned int flags)
+{
+ if ((flags & ENGINE_METHOD_CIPHERS) && !ENGINE_set_default_ciphers(e))
+ return 0;
+ if ((flags & ENGINE_METHOD_DIGESTS) && !ENGINE_set_default_digests(e))
+ return 0;
+#ifndef OPENSSL_NO_RSA
+ if ((flags & ENGINE_METHOD_RSA) && !ENGINE_set_default_RSA(e))
+ return 0;
+#endif
+#ifndef OPENSSL_NO_DSA
+ if ((flags & ENGINE_METHOD_DSA) && !ENGINE_set_default_DSA(e))
+ return 0;
+#endif
+#ifndef OPENSSL_NO_DH
+ if ((flags & ENGINE_METHOD_DH) && !ENGINE_set_default_DH(e))
+ return 0;
+#endif
+#ifndef OPENSSL_NO_EC
+ if ((flags & ENGINE_METHOD_EC) && !ENGINE_set_default_EC(e))
+ return 0;
+#endif
+ if ((flags & ENGINE_METHOD_RAND) && !ENGINE_set_default_RAND(e))
+ return 0;
+ if ((flags & ENGINE_METHOD_PKEY_METHS)
+ && !ENGINE_set_default_pkey_meths(e))
+ return 0;
+ if ((flags & ENGINE_METHOD_PKEY_ASN1_METHS)
+ && !ENGINE_set_default_pkey_asn1_meths(e))
+ return 0;
+ return 1;
+}
+
+/* Set default algorithms using a string */
+
+static int int_def_cb(const char *alg, int len, void *arg)
+{
+ unsigned int *pflags = arg;
+ if (alg == NULL)
+ return 0;
+ if (strncmp(alg, "ALL", len) == 0)
+ *pflags |= ENGINE_METHOD_ALL;
+ else if (strncmp(alg, "RSA", len) == 0)
+ *pflags |= ENGINE_METHOD_RSA;
+ else if (strncmp(alg, "DSA", len) == 0)
+ *pflags |= ENGINE_METHOD_DSA;
+ else if (strncmp(alg, "DH", len) == 0)
+ *pflags |= ENGINE_METHOD_DH;
+ else if (strncmp(alg, "EC", len) == 0)
+ *pflags |= ENGINE_METHOD_EC;
+ else if (strncmp(alg, "RAND", len) == 0)
+ *pflags |= ENGINE_METHOD_RAND;
+ else if (strncmp(alg, "CIPHERS", len) == 0)
+ *pflags |= ENGINE_METHOD_CIPHERS;
+ else if (strncmp(alg, "DIGESTS", len) == 0)
+ *pflags |= ENGINE_METHOD_DIGESTS;
+ else if (strncmp(alg, "PKEY", len) == 0)
+ *pflags |= ENGINE_METHOD_PKEY_METHS | ENGINE_METHOD_PKEY_ASN1_METHS;
+ else if (strncmp(alg, "PKEY_CRYPTO", len) == 0)
+ *pflags |= ENGINE_METHOD_PKEY_METHS;
+ else if (strncmp(alg, "PKEY_ASN1", len) == 0)
+ *pflags |= ENGINE_METHOD_PKEY_ASN1_METHS;
+ else
+ return 0;
+ return 1;
+}
+
+int ENGINE_set_default_string(ENGINE *e, const char *def_list)
+{
+ unsigned int flags = 0;
+ if (!CONF_parse_list(def_list, ',', 1, int_def_cb, &flags)) {
+ ENGINEerr(ENGINE_F_ENGINE_SET_DEFAULT_STRING,
+ ENGINE_R_INVALID_STRING);
+ ERR_add_error_data(2, "str=", def_list);
+ return 0;
+ }
+ return ENGINE_set_default(e, flags);
+}
+
+int ENGINE_register_complete(ENGINE *e)
+{
+ ENGINE_register_ciphers(e);
+ ENGINE_register_digests(e);
+#ifndef OPENSSL_NO_RSA
+ ENGINE_register_RSA(e);
+#endif
+#ifndef OPENSSL_NO_DSA
+ ENGINE_register_DSA(e);
+#endif
+#ifndef OPENSSL_NO_DH
+ ENGINE_register_DH(e);
+#endif
+#ifndef OPENSSL_NO_EC
+ ENGINE_register_EC(e);
+#endif
+ ENGINE_register_RAND(e);
+ ENGINE_register_pkey_meths(e);
+ ENGINE_register_pkey_asn1_meths(e);
+ return 1;
+}
+
+int ENGINE_register_all_complete(void)
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ if (!(e->flags & ENGINE_FLAGS_NO_REGISTER_ALL))
+ ENGINE_register_complete(e);
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_init.c b/openssl-1.1.0h/crypto/engine/eng_init.c
new file mode 100644
index 0000000..8be7c6f
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_init.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+/*
+ * Initialise a engine type for use (or up its functional reference count if
+ * it's already in use). This version is only used internally.
+ */
+int engine_unlocked_init(ENGINE *e)
+{
+ int to_return = 1;
+
+ if ((e->funct_ref == 0) && e->init)
+ /*
+ * This is the first functional reference and the engine requires
+ * initialisation so we do it now.
+ */
+ to_return = e->init(e);
+ if (to_return) {
+ /*
+ * OK, we return a functional reference which is also a structural
+ * reference.
+ */
+ e->struct_ref++;
+ e->funct_ref++;
+ engine_ref_debug(e, 0, 1);
+ engine_ref_debug(e, 1, 1);
+ }
+ return to_return;
+}
+
+/*
+ * Free a functional reference to a engine type. This version is only used
+ * internally.
+ */
+int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers)
+{
+ int to_return = 1;
+
+ /*
+ * Reduce the functional reference count here so if it's the terminating
+ * case, we can release the lock safely and call the finish() handler
+ * without risk of a race. We get a race if we leave the count until
+ * after and something else is calling "finish" at the same time -
+ * there's a chance that both threads will together take the count from 2
+ * to 0 without either calling finish().
+ */
+ e->funct_ref--;
+ engine_ref_debug(e, 1, -1);
+ if ((e->funct_ref == 0) && e->finish) {
+ if (unlock_for_handlers)
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ to_return = e->finish(e);
+ if (unlock_for_handlers)
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!to_return)
+ return 0;
+ }
+ REF_ASSERT_ISNT(e->funct_ref < 0);
+ /* Release the structural reference too */
+ if (!engine_free_util(e, 0)) {
+ ENGINEerr(ENGINE_F_ENGINE_UNLOCKED_FINISH, ENGINE_R_FINISH_FAILED);
+ return 0;
+ }
+ return to_return;
+}
+
+/* The API (locked) version of "init" */
+int ENGINE_init(ENGINE *e)
+{
+ int ret;
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
+ ENGINEerr(ENGINE_F_ENGINE_INIT, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ ret = engine_unlocked_init(e);
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return ret;
+}
+
+/* The API (locked) version of "finish" */
+int ENGINE_finish(ENGINE *e)
+{
+ int to_return = 1;
+
+ if (e == NULL)
+ return 1;
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ to_return = engine_unlocked_finish(e, 1);
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ if (!to_return) {
+ ENGINEerr(ENGINE_F_ENGINE_FINISH, ENGINE_R_FINISH_FAILED);
+ return 0;
+ }
+ return to_return;
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_int.h b/openssl-1.1.0h/crypto/engine/eng_int.h
new file mode 100644
index 0000000..c604fad
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_int.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2001-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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#ifndef HEADER_ENGINE_INT_H
+# define HEADER_ENGINE_INT_H
+
+# include "internal/cryptlib.h"
+# include <internal/engine.h>
+# include <internal/thread_once.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern CRYPTO_RWLOCK *global_engine_lock;
+
+/*
+ * If we compile with this symbol defined, then both reference counts in the
+ * ENGINE structure will be monitored with a line of output on stderr for
+ * each change. This prints the engine's pointer address (truncated to
+ * unsigned int), "struct" or "funct" to indicate the reference type, the
+ * before and after reference count, and the file:line-number pair. The
+ * "engine_ref_debug" statements must come *after* the change.
+ */
+# ifdef ENGINE_REF_COUNT_DEBUG
+
+# define engine_ref_debug(e, isfunct, diff) \
+ fprintf(stderr, "engine: %08x %s from %d to %d (%s:%d)\n", \
+ (unsigned int)(e), (isfunct ? "funct" : "struct"), \
+ ((isfunct) ? ((e)->funct_ref - (diff)) : ((e)->struct_ref - (diff))), \
+ ((isfunct) ? (e)->funct_ref : (e)->struct_ref), \
+ (OPENSSL_FILE), (OPENSSL_LINE))
+
+# else
+
+# define engine_ref_debug(e, isfunct, diff)
+
+# endif
+
+/*
+ * Any code that will need cleanup operations should use these functions to
+ * register callbacks. engine_cleanup_int() will call all registered
+ * callbacks in order. NB: both the "add" functions assume the engine lock to
+ * already be held (in "write" mode).
+ */
+typedef void (ENGINE_CLEANUP_CB) (void);
+typedef struct st_engine_cleanup_item {
+ ENGINE_CLEANUP_CB *cb;
+} ENGINE_CLEANUP_ITEM;
+DEFINE_STACK_OF(ENGINE_CLEANUP_ITEM)
+void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb);
+void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb);
+
+/* We need stacks of ENGINEs for use in eng_table.c */
+DEFINE_STACK_OF(ENGINE)
+
+/*
+ * If this symbol is defined then engine_table_select(), the function that is
+ * used by RSA, DSA (etc) code to select registered ENGINEs, cache defaults
+ * and functional references (etc), will display debugging summaries to
+ * stderr.
+ */
+/* #define ENGINE_TABLE_DEBUG */
+
+/*
+ * This represents an implementation table. Dependent code should instantiate
+ * it as a (ENGINE_TABLE *) pointer value set initially to NULL.
+ */
+typedef struct st_engine_table ENGINE_TABLE;
+int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
+ ENGINE *e, const int *nids, int num_nids,
+ int setdefault);
+void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e);
+void engine_table_cleanup(ENGINE_TABLE **table);
+# ifndef ENGINE_TABLE_DEBUG
+ENGINE *engine_table_select(ENGINE_TABLE **table, int nid);
+# else
+ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
+ int l);
+# define engine_table_select(t,n) engine_table_select_tmp(t,n,OPENSSL_FILE,OPENSSL_LINE)
+# endif
+typedef void (engine_table_doall_cb) (int nid, STACK_OF(ENGINE) *sk,
+ ENGINE *def, void *arg);
+void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb,
+ void *arg);
+
+/*
+ * Internal versions of API functions that have control over locking. These
+ * are used between C files when functionality needs to be shared but the
+ * caller may already be controlling of the engine lock.
+ */
+int engine_unlocked_init(ENGINE *e);
+int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers);
+int engine_free_util(ENGINE *e, int locked);
+
+/*
+ * This function will reset all "set"able values in an ENGINE to NULL. This
+ * won't touch reference counts or ex_data, but is equivalent to calling all
+ * the ENGINE_set_***() functions with a NULL value.
+ */
+void engine_set_all_null(ENGINE *e);
+
+/*
+ * NB: Bitwise OR-able values for the "flags" variable in ENGINE are now
+ * exposed in engine.h.
+ */
+
+/* Free up dynamically allocated public key methods associated with ENGINE */
+
+void engine_pkey_meths_free(ENGINE *e);
+void engine_pkey_asn1_meths_free(ENGINE *e);
+
+/* Once initialisation function */
+extern CRYPTO_ONCE engine_lock_init;
+DECLARE_RUN_ONCE(do_engine_lock_init)
+
+/*
+ * This is a structure for storing implementations of various crypto
+ * algorithms and functions.
+ */
+struct engine_st {
+ const char *id;
+ const char *name;
+ const RSA_METHOD *rsa_meth;
+ const DSA_METHOD *dsa_meth;
+ const DH_METHOD *dh_meth;
+ const EC_KEY_METHOD *ec_meth;
+ const RAND_METHOD *rand_meth;
+ /* Cipher handling is via this callback */
+ ENGINE_CIPHERS_PTR ciphers;
+ /* Digest handling is via this callback */
+ ENGINE_DIGESTS_PTR digests;
+ /* Public key handling via this callback */
+ ENGINE_PKEY_METHS_PTR pkey_meths;
+ /* ASN1 public key handling via this callback */
+ ENGINE_PKEY_ASN1_METHS_PTR pkey_asn1_meths;
+ ENGINE_GEN_INT_FUNC_PTR destroy;
+ ENGINE_GEN_INT_FUNC_PTR init;
+ ENGINE_GEN_INT_FUNC_PTR finish;
+ ENGINE_CTRL_FUNC_PTR ctrl;
+ ENGINE_LOAD_KEY_PTR load_privkey;
+ ENGINE_LOAD_KEY_PTR load_pubkey;
+ ENGINE_SSL_CLIENT_CERT_PTR load_ssl_client_cert;
+ const ENGINE_CMD_DEFN *cmd_defns;
+ int flags;
+ /* reference count on the structure itself */
+ int struct_ref;
+ /*
+ * reference count on usability of the engine type. NB: This controls the
+ * loading and initialisation of any functionality required by this
+ * engine, whereas the previous count is simply to cope with
+ * (de)allocation of this structure. Hence, running_ref <= struct_ref at
+ * all times.
+ */
+ int funct_ref;
+ /* A place to store per-ENGINE data */
+ CRYPTO_EX_DATA ex_data;
+ /* Used to maintain the linked-list of engines. */
+ struct engine_st *prev;
+ struct engine_st *next;
+};
+
+typedef struct st_engine_pile ENGINE_PILE;
+
+DEFINE_LHASH_OF(ENGINE_PILE);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HEADER_ENGINE_INT_H */
diff --git a/openssl-1.1.0h/crypto/engine/eng_lib.c b/openssl-1.1.0h/crypto/engine/eng_lib.c
new file mode 100644
index 0000000..cbefc7e
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_lib.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+#include <openssl/rand.h>
+
+CRYPTO_RWLOCK *global_engine_lock;
+
+CRYPTO_ONCE engine_lock_init = CRYPTO_ONCE_STATIC_INIT;
+
+/* The "new"/"free" stuff first */
+
+DEFINE_RUN_ONCE(do_engine_lock_init)
+{
+ OPENSSL_init_crypto(0, NULL);
+ global_engine_lock = CRYPTO_THREAD_lock_new();
+ return global_engine_lock != NULL;
+}
+
+ENGINE *ENGINE_new(void)
+{
+ ENGINE *ret;
+
+ if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)
+ || (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ret->struct_ref = 1;
+ engine_ref_debug(ret, 0, 1);
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data)) {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+/*
+ * Placed here (close proximity to ENGINE_new) so that modifications to the
+ * elements of the ENGINE structure are more likely to be caught and changed
+ * here.
+ */
+void engine_set_all_null(ENGINE *e)
+{
+ e->id = NULL;
+ e->name = NULL;
+ e->rsa_meth = NULL;
+ e->dsa_meth = NULL;
+ e->dh_meth = NULL;
+ e->rand_meth = NULL;
+ e->ciphers = NULL;
+ e->digests = NULL;
+ e->destroy = NULL;
+ e->init = NULL;
+ e->finish = NULL;
+ e->ctrl = NULL;
+ e->load_privkey = NULL;
+ e->load_pubkey = NULL;
+ e->cmd_defns = NULL;
+ e->flags = 0;
+}
+
+int engine_free_util(ENGINE *e, int locked)
+{
+ int i;
+
+ if (e == NULL)
+ return 1;
+ if (locked)
+ CRYPTO_atomic_add(&e->struct_ref, -1, &i, global_engine_lock);
+ else
+ i = --e->struct_ref;
+ engine_ref_debug(e, 0, -1)
+ if (i > 0)
+ return 1;
+ REF_ASSERT_ISNT(i < 0);
+ /* Free up any dynamically allocated public key methods */
+ engine_pkey_meths_free(e);
+ engine_pkey_asn1_meths_free(e);
+ /*
+ * Give the ENGINE a chance to do any structural cleanup corresponding to
+ * allocation it did in its constructor (eg. unload error strings)
+ */
+ if (e->destroy)
+ e->destroy(e);
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data);
+ OPENSSL_free(e);
+ return 1;
+}
+
+int ENGINE_free(ENGINE *e)
+{
+ return engine_free_util(e, 1);
+}
+
+/* Cleanup stuff */
+
+/*
+ * engine_cleanup_int() is coded such that anything that does work that will
+ * need cleanup can register a "cleanup" callback here. That way we don't get
+ * linker bloat by referring to all *possible* cleanups, but any linker bloat
+ * into code "X" will cause X's cleanup function to end up here.
+ */
+static STACK_OF(ENGINE_CLEANUP_ITEM) *cleanup_stack = NULL;
+static int int_cleanup_check(int create)
+{
+ if (cleanup_stack)
+ return 1;
+ if (!create)
+ return 0;
+ cleanup_stack = sk_ENGINE_CLEANUP_ITEM_new_null();
+ return (cleanup_stack ? 1 : 0);
+}
+
+static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb)
+{
+ ENGINE_CLEANUP_ITEM *item = OPENSSL_malloc(sizeof(*item));
+ if (item == NULL)
+ return NULL;
+ item->cb = cb;
+ return item;
+}
+
+void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
+{
+ ENGINE_CLEANUP_ITEM *item;
+ if (!int_cleanup_check(1))
+ return;
+ item = int_cleanup_item(cb);
+ if (item)
+ sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0);
+}
+
+void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
+{
+ ENGINE_CLEANUP_ITEM *item;
+ if (!int_cleanup_check(1))
+ return;
+ item = int_cleanup_item(cb);
+ if (item)
+ sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item);
+}
+
+/* The API function that performs all cleanup */
+static void engine_cleanup_cb_free(ENGINE_CLEANUP_ITEM *item)
+{
+ (*(item->cb)) ();
+ OPENSSL_free(item);
+}
+
+void engine_cleanup_int(void)
+{
+ if (int_cleanup_check(0)) {
+ sk_ENGINE_CLEANUP_ITEM_pop_free(cleanup_stack,
+ engine_cleanup_cb_free);
+ cleanup_stack = NULL;
+ }
+ CRYPTO_THREAD_lock_free(global_engine_lock);
+}
+
+/* Now the "ex_data" support */
+
+int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg)
+{
+ return (CRYPTO_set_ex_data(&e->ex_data, idx, arg));
+}
+
+void *ENGINE_get_ex_data(const ENGINE *e, int idx)
+{
+ return (CRYPTO_get_ex_data(&e->ex_data, idx));
+}
+
+/*
+ * Functions to get/set an ENGINE's elements - mainly to avoid exposing the
+ * ENGINE structure itself.
+ */
+
+int ENGINE_set_id(ENGINE *e, const char *id)
+{
+ if (id == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_SET_ID, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ e->id = id;
+ return 1;
+}
+
+int ENGINE_set_name(ENGINE *e, const char *name)
+{
+ if (name == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_SET_NAME, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ e->name = name;
+ return 1;
+}
+
+int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f)
+{
+ e->destroy = destroy_f;
+ return 1;
+}
+
+int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f)
+{
+ e->init = init_f;
+ return 1;
+}
+
+int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f)
+{
+ e->finish = finish_f;
+ return 1;
+}
+
+int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f)
+{
+ e->ctrl = ctrl_f;
+ return 1;
+}
+
+int ENGINE_set_flags(ENGINE *e, int flags)
+{
+ e->flags = flags;
+ return 1;
+}
+
+int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns)
+{
+ e->cmd_defns = defns;
+ return 1;
+}
+
+const char *ENGINE_get_id(const ENGINE *e)
+{
+ return e->id;
+}
+
+const char *ENGINE_get_name(const ENGINE *e)
+{
+ return e->name;
+}
+
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e)
+{
+ return e->destroy;
+}
+
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e)
+{
+ return e->init;
+}
+
+ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e)
+{
+ return e->finish;
+}
+
+ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e)
+{
+ return e->ctrl;
+}
+
+int ENGINE_get_flags(const ENGINE *e)
+{
+ return e->flags;
+}
+
+const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e)
+{
+ return e->cmd_defns;
+}
+
+/*
+ * eng_lib.o is pretty much linked into anything that touches ENGINE already,
+ * so put the "static_state" hack here.
+ */
+
+static int internal_static_hack = 0;
+
+void *ENGINE_get_static_state(void)
+{
+ return &internal_static_hack;
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_list.c b/openssl-1.1.0h/crypto/engine/eng_list.c
new file mode 100644
index 0000000..934389f
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_list.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2001-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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include "eng_int.h"
+
+/*
+ * The linked-list of pointers to engine types. engine_list_head incorporates
+ * an implicit structural reference but engine_list_tail does not - the
+ * latter is a computational niceity and only points to something that is
+ * already pointed to by its predecessor in the list (or engine_list_head
+ * itself). In the same way, the use of the "prev" pointer in each ENGINE is
+ * to save excessive list iteration, it doesn't correspond to an extra
+ * structural reference. Hence, engine_list_head, and each non-null "next"
+ * pointer account for the list itself assuming exactly 1 structural
+ * reference on each list member.
+ */
+static ENGINE *engine_list_head = NULL;
+static ENGINE *engine_list_tail = NULL;
+
+/*
+ * This cleanup function is only needed internally. If it should be called,
+ * we register it with the "engine_cleanup_int()" stack to be called during
+ * cleanup.
+ */
+
+static void engine_list_cleanup(void)
+{
+ ENGINE *iterator = engine_list_head;
+
+ while (iterator != NULL) {
+ ENGINE_remove(iterator);
+ iterator = engine_list_head;
+ }
+ return;
+}
+
+/*
+ * These static functions starting with a lower case "engine_" always take
+ * place when global_engine_lock has been locked up.
+ */
+static int engine_list_add(ENGINE *e)
+{
+ int conflict = 0;
+ ENGINE *iterator = NULL;
+
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ iterator = engine_list_head;
+ while (iterator && !conflict) {
+ conflict = (strcmp(iterator->id, e->id) == 0);
+ iterator = iterator->next;
+ }
+ if (conflict) {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_CONFLICTING_ENGINE_ID);
+ return 0;
+ }
+ if (engine_list_head == NULL) {
+ /* We are adding to an empty list. */
+ if (engine_list_tail) {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ engine_list_head = e;
+ e->prev = NULL;
+ /*
+ * The first time the list allocates, we should register the cleanup.
+ */
+ engine_cleanup_add_last(engine_list_cleanup);
+ } else {
+ /* We are adding to the tail of an existing list. */
+ if ((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
+ return 0;
+ }
+ engine_list_tail->next = e;
+ e->prev = engine_list_tail;
+ }
+ /*
+ * Having the engine in the list assumes a structural reference.
+ */
+ e->struct_ref++;
+ engine_ref_debug(e, 0, 1);
+ /* However it came to be, e is the last item in the list. */
+ engine_list_tail = e;
+ e->next = NULL;
+ return 1;
+}
+
+static int engine_list_remove(ENGINE *e)
+{
+ ENGINE *iterator;
+
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ /* We need to check that e is in our linked list! */
+ iterator = engine_list_head;
+ while (iterator && (iterator != e))
+ iterator = iterator->next;
+ if (iterator == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_LIST_REMOVE,
+ ENGINE_R_ENGINE_IS_NOT_IN_LIST);
+ return 0;
+ }
+ /* un-link e from the chain. */
+ if (e->next)
+ e->next->prev = e->prev;
+ if (e->prev)
+ e->prev->next = e->next;
+ /* Correct our head/tail if necessary. */
+ if (engine_list_head == e)
+ engine_list_head = e->next;
+ if (engine_list_tail == e)
+ engine_list_tail = e->prev;
+ engine_free_util(e, 0);
+ return 1;
+}
+
+/* Get the first/last "ENGINE" type available. */
+ENGINE *ENGINE_get_first(void)
+{
+ ENGINE *ret;
+
+ if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_FIRST, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ ret = engine_list_head;
+ if (ret) {
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1);
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return ret;
+}
+
+ENGINE *ENGINE_get_last(void)
+{
+ ENGINE *ret;
+
+ if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_LAST, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ ret = engine_list_tail;
+ if (ret) {
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1);
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return ret;
+}
+
+/* Iterate to the next/previous "ENGINE" type (NULL = end of the list). */
+ENGINE *ENGINE_get_next(ENGINE *e)
+{
+ ENGINE *ret = NULL;
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_NEXT, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ ret = e->next;
+ if (ret) {
+ /* Return a valid structural reference to the next ENGINE */
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1);
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ /* Release the structural reference to the previous ENGINE */
+ ENGINE_free(e);
+ return ret;
+}
+
+ENGINE *ENGINE_get_prev(ENGINE *e)
+{
+ ENGINE *ret = NULL;
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_PREV, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ ret = e->prev;
+ if (ret) {
+ /* Return a valid structural reference to the next ENGINE */
+ ret->struct_ref++;
+ engine_ref_debug(ret, 0, 1);
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ /* Release the structural reference to the previous ENGINE */
+ ENGINE_free(e);
+ return ret;
+}
+
+/* Add another "ENGINE" type into the list. */
+int ENGINE_add(ENGINE *e)
+{
+ int to_return = 1;
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_ADD, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ if ((e->id == NULL) || (e->name == NULL)) {
+ ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_ID_OR_NAME_MISSING);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!engine_list_add(e)) {
+ ENGINEerr(ENGINE_F_ENGINE_ADD, ENGINE_R_INTERNAL_LIST_ERROR);
+ to_return = 0;
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return to_return;
+}
+
+/* Remove an existing "ENGINE" type from the array. */
+int ENGINE_remove(ENGINE *e)
+{
+ int to_return = 1;
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_REMOVE, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!engine_list_remove(e)) {
+ ENGINEerr(ENGINE_F_ENGINE_REMOVE, ENGINE_R_INTERNAL_LIST_ERROR);
+ to_return = 0;
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return to_return;
+}
+
+static void engine_cpy(ENGINE *dest, const ENGINE *src)
+{
+ dest->id = src->id;
+ dest->name = src->name;
+#ifndef OPENSSL_NO_RSA
+ dest->rsa_meth = src->rsa_meth;
+#endif
+#ifndef OPENSSL_NO_DSA
+ dest->dsa_meth = src->dsa_meth;
+#endif
+#ifndef OPENSSL_NO_DH
+ dest->dh_meth = src->dh_meth;
+#endif
+#ifndef OPENSSL_NO_EC
+ dest->ec_meth = src->ec_meth;
+#endif
+ dest->rand_meth = src->rand_meth;
+ dest->ciphers = src->ciphers;
+ dest->digests = src->digests;
+ dest->pkey_meths = src->pkey_meths;
+ dest->destroy = src->destroy;
+ dest->init = src->init;
+ dest->finish = src->finish;
+ dest->ctrl = src->ctrl;
+ dest->load_privkey = src->load_privkey;
+ dest->load_pubkey = src->load_pubkey;
+ dest->cmd_defns = src->cmd_defns;
+ dest->flags = src->flags;
+}
+
+ENGINE *ENGINE_by_id(const char *id)
+{
+ ENGINE *iterator;
+ char *load_dir = NULL;
+ if (id == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER);
+ return NULL;
+ }
+ if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
+ ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ iterator = engine_list_head;
+ while (iterator && (strcmp(id, iterator->id) != 0))
+ iterator = iterator->next;
+ if (iterator != NULL) {
+ /*
+ * We need to return a structural reference. If this is an ENGINE
+ * type that returns copies, make a duplicate - otherwise increment
+ * the existing ENGINE's reference count.
+ */
+ if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
+ ENGINE *cp = ENGINE_new();
+ if (cp == NULL)
+ iterator = NULL;
+ else {
+ engine_cpy(cp, iterator);
+ iterator = cp;
+ }
+ } else {
+ iterator->struct_ref++;
+ engine_ref_debug(iterator, 0, 1);
+ }
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ if (iterator != NULL)
+ return iterator;
+ /*
+ * Prevent infinite recursion if we're looking for the dynamic engine.
+ */
+ if (strcmp(id, "dynamic")) {
+ if ((load_dir = getenv("OPENSSL_ENGINES")) == 0)
+ load_dir = ENGINESDIR;
+ iterator = ENGINE_by_id("dynamic");
+ if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
+ !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
+ !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
+ load_dir, 0) ||
+ !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
+ !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
+ goto notfound;
+ return iterator;
+ }
+ notfound:
+ ENGINE_free(iterator);
+ ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE);
+ ERR_add_error_data(2, "id=", id);
+ return NULL;
+ /* EEK! Experimental code ends */
+}
+
+int ENGINE_up_ref(ENGINE *e)
+{
+ int i;
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_UP_REF, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_atomic_add(&e->struct_ref, 1, &i, global_engine_lock);
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_openssl.c b/openssl-1.1.0h/crypto/engine/eng_openssl.c
new file mode 100644
index 0000000..9208f7e
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_openssl.c
@@ -0,0 +1,652 @@
+/*
+ * Copyright 2001-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
+ */
+
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECDH support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "internal/cryptlib.h"
+#include <internal/engine.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
+#include <openssl/dh.h>
+
+#include <openssl/hmac.h>
+#include <openssl/x509v3.h>
+
+/*
+ * This testing gunk is implemented (and explained) lower down. It also
+ * assumes the application explicitly calls "ENGINE_load_openssl()" because
+ * this is no longer automatic in ENGINE_load_builtin_engines().
+ */
+#define TEST_ENG_OPENSSL_RC4
+#ifndef OPENSSL_NO_STDIO
+#define TEST_ENG_OPENSSL_PKEY
+#endif
+/* #define TEST_ENG_OPENSSL_HMAC */
+/* #define TEST_ENG_OPENSSL_HMAC_INIT */
+/* #define TEST_ENG_OPENSSL_RC4_OTHERS */
+#define TEST_ENG_OPENSSL_RC4_P_INIT
+/* #define TEST_ENG_OPENSSL_RC4_P_CIPHER */
+#define TEST_ENG_OPENSSL_SHA
+/* #define TEST_ENG_OPENSSL_SHA_OTHERS */
+/* #define TEST_ENG_OPENSSL_SHA_P_INIT */
+/* #define TEST_ENG_OPENSSL_SHA_P_UPDATE */
+/* #define TEST_ENG_OPENSSL_SHA_P_FINAL */
+
+/* Now check what of those algorithms are actually enabled */
+#ifdef OPENSSL_NO_RC4
+# undef TEST_ENG_OPENSSL_RC4
+# undef TEST_ENG_OPENSSL_RC4_OTHERS
+# undef TEST_ENG_OPENSSL_RC4_P_INIT
+# undef TEST_ENG_OPENSSL_RC4_P_CIPHER
+#endif
+
+static int openssl_destroy(ENGINE *e);
+
+#ifdef TEST_ENG_OPENSSL_RC4
+static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid);
+#endif
+#ifdef TEST_ENG_OPENSSL_SHA
+static int openssl_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid);
+#endif
+
+#ifdef TEST_ENG_OPENSSL_PKEY
+static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
+ UI_METHOD *ui_method,
+ void *callback_data);
+#endif
+
+#ifdef TEST_ENG_OPENSSL_HMAC
+static int ossl_register_hmac_meth(void);
+static int ossl_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
+ const int **nids, int nid);
+#endif
+
+/* The constants used when creating the ENGINE */
+static const char *engine_openssl_id = "openssl";
+static const char *engine_openssl_name = "Software engine support";
+
+/*
+ * This internal function is used by ENGINE_openssl() and possibly by the
+ * "dynamic" ENGINE support too
+ */
+static int bind_helper(ENGINE *e)
+{
+ if (!ENGINE_set_id(e, engine_openssl_id)
+ || !ENGINE_set_name(e, engine_openssl_name)
+ || !ENGINE_set_destroy_function(e, openssl_destroy)
+#ifndef TEST_ENG_OPENSSL_NO_ALGORITHMS
+# ifndef OPENSSL_NO_RSA
+ || !ENGINE_set_RSA(e, RSA_get_default_method())
+# endif
+# ifndef OPENSSL_NO_DSA
+ || !ENGINE_set_DSA(e, DSA_get_default_method())
+# endif
+# ifndef OPENSSL_NO_EC
+ || !ENGINE_set_EC(e, EC_KEY_OpenSSL())
+# endif
+# ifndef OPENSSL_NO_DH
+ || !ENGINE_set_DH(e, DH_get_default_method())
+# endif
+ || !ENGINE_set_RAND(e, RAND_OpenSSL())
+# ifdef TEST_ENG_OPENSSL_RC4
+ || !ENGINE_set_ciphers(e, openssl_ciphers)
+# endif
+# ifdef TEST_ENG_OPENSSL_SHA
+ || !ENGINE_set_digests(e, openssl_digests)
+# endif
+#endif
+#ifdef TEST_ENG_OPENSSL_PKEY
+ || !ENGINE_set_load_privkey_function(e, openssl_load_privkey)
+#endif
+#ifdef TEST_ENG_OPENSSL_HMAC
+ || !ossl_register_hmac_meth()
+ || !ENGINE_set_pkey_meths(e, ossl_pkey_meths)
+#endif
+ )
+ return 0;
+ /*
+ * If we add errors to this ENGINE, ensure the error handling is setup
+ * here
+ */
+ /* openssl_load_error_strings(); */
+ return 1;
+}
+
+static ENGINE *engine_openssl(void)
+{
+ ENGINE *ret = ENGINE_new();
+ if (ret == NULL)
+ return NULL;
+ if (!bind_helper(ret)) {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+void engine_load_openssl_int(void)
+{
+ ENGINE *toadd = engine_openssl();
+ if (!toadd)
+ return;
+ ENGINE_add(toadd);
+ /*
+ * If the "add" worked, it gets a structural reference. So either way, we
+ * release our just-created reference.
+ */
+ ENGINE_free(toadd);
+ ERR_clear_error();
+}
+
+/*
+ * This stuff is needed if this ENGINE is being compiled into a
+ * self-contained shared-library.
+ */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+{
+ if (id && (strcmp(id, engine_openssl_id) != 0))
+ return 0;
+ if (!bind_helper(e))
+ return 0;
+ return 1;
+}
+
+IMPLEMENT_DYNAMIC_CHECK_FN()
+ IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+#ifdef TEST_ENG_OPENSSL_RC4
+/*-
+ * This section of code compiles an "alternative implementation" of two modes of
+ * RC4 into this ENGINE. The result is that EVP_CIPHER operation for "rc4"
+ * should under normal circumstances go via this support rather than the default
+ * EVP support. There are other symbols to tweak the testing;
+ * TEST_ENC_OPENSSL_RC4_OTHERS - print a one line message to stderr each time
+ * we're asked for a cipher we don't support (should not happen).
+ * TEST_ENG_OPENSSL_RC4_P_INIT - print a one line message to stderr each time
+ * the "init_key" handler is called.
+ * TEST_ENG_OPENSSL_RC4_P_CIPHER - ditto for the "cipher" handler.
+ */
+# include <openssl/rc4.h>
+# define TEST_RC4_KEY_SIZE 16
+typedef struct {
+ unsigned char key[TEST_RC4_KEY_SIZE];
+ RC4_KEY ks;
+} TEST_RC4_KEY;
+# define test(ctx) ((TEST_RC4_KEY *)EVP_CIPHER_CTX_get_cipher_data(ctx))
+static int test_rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc)
+{
+# ifdef TEST_ENG_OPENSSL_RC4_P_INIT
+ fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_init_key() called\n");
+# endif
+ memcpy(&test(ctx)->key[0], key, EVP_CIPHER_CTX_key_length(ctx));
+ RC4_set_key(&test(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx),
+ test(ctx)->key);
+ return 1;
+}
+
+static int test_rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl)
+{
+# ifdef TEST_ENG_OPENSSL_RC4_P_CIPHER
+ fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) test_cipher() called\n");
+# endif
+ RC4(&test(ctx)->ks, inl, in, out);
+ return 1;
+}
+
+static EVP_CIPHER *r4_cipher = NULL;
+static const EVP_CIPHER *test_r4_cipher(void)
+{
+ if (r4_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_rc4, 1, TEST_RC4_KEY_SIZE)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 0)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_VARIABLE_LENGTH)
+ || !EVP_CIPHER_meth_set_init(cipher, test_rc4_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, test_rc4_cipher)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(TEST_RC4_KEY))) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ r4_cipher = cipher;
+ }
+ return r4_cipher;
+}
+static void test_r4_cipher_destroy(void)
+{
+ EVP_CIPHER_meth_free(r4_cipher);
+ r4_cipher = NULL;
+}
+
+static EVP_CIPHER *r4_40_cipher = NULL;
+static const EVP_CIPHER *test_r4_40_cipher(void)
+{
+ if (r4_40_cipher == NULL) {
+ EVP_CIPHER *cipher;
+
+ if ((cipher = EVP_CIPHER_meth_new(NID_rc4, 1, 5 /* 40 bits */)) == NULL
+ || !EVP_CIPHER_meth_set_iv_length(cipher, 0)
+ || !EVP_CIPHER_meth_set_flags(cipher, EVP_CIPH_VARIABLE_LENGTH)
+ || !EVP_CIPHER_meth_set_init(cipher, test_rc4_init_key)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, test_rc4_cipher)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, sizeof(TEST_RC4_KEY))) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ r4_40_cipher = cipher;
+ }
+ return r4_40_cipher;
+}
+static void test_r4_40_cipher_destroy(void)
+{
+ EVP_CIPHER_meth_free(r4_40_cipher);
+ r4_40_cipher = NULL;
+}
+static int test_cipher_nids(const int **nids)
+{
+ static int cipher_nids[4] = { 0, 0, 0, 0 };
+ static int pos = 0;
+ static int init = 0;
+
+ if (!init) {
+ const EVP_CIPHER *cipher;
+ if ((cipher = test_r4_cipher()) != NULL)
+ cipher_nids[pos++] = EVP_CIPHER_nid(cipher);
+ if ((cipher = test_r4_40_cipher()) != NULL)
+ cipher_nids[pos++] = EVP_CIPHER_nid(cipher);
+ cipher_nids[pos] = 0;
+ init = 1;
+ }
+ *nids = cipher_nids;
+ return pos;
+}
+
+static int openssl_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+ const int **nids, int nid)
+{
+ if (!cipher) {
+ /* We are returning a list of supported nids */
+ return test_cipher_nids(nids);
+ }
+ /* We are being asked for a specific cipher */
+ if (nid == NID_rc4)
+ *cipher = test_r4_cipher();
+ else if (nid == NID_rc4_40)
+ *cipher = test_r4_40_cipher();
+ else {
+# ifdef TEST_ENG_OPENSSL_RC4_OTHERS
+ fprintf(stderr, "(TEST_ENG_OPENSSL_RC4) returning NULL for "
+ "nid %d\n", nid);
+# endif
+ *cipher = NULL;
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+#ifdef TEST_ENG_OPENSSL_SHA
+/* Much the same sort of comment as for TEST_ENG_OPENSSL_RC4 */
+# include <openssl/sha.h>
+
+static int test_sha1_init(EVP_MD_CTX *ctx)
+{
+# ifdef TEST_ENG_OPENSSL_SHA_P_INIT
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_init() called\n");
+# endif
+ return SHA1_Init(EVP_MD_CTX_md_data(ctx));
+}
+
+static int test_sha1_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+# ifdef TEST_ENG_OPENSSL_SHA_P_UPDATE
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_update() called\n");
+# endif
+ return SHA1_Update(EVP_MD_CTX_md_data(ctx), data, count);
+}
+
+static int test_sha1_final(EVP_MD_CTX *ctx, unsigned char *md)
+{
+# ifdef TEST_ENG_OPENSSL_SHA_P_FINAL
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) test_sha1_final() called\n");
+# endif
+ return SHA1_Final(md, EVP_MD_CTX_md_data(ctx));
+}
+
+static EVP_MD *sha1_md = NULL;
+static const EVP_MD *test_sha_md(void)
+{
+ if (sha1_md == NULL) {
+ EVP_MD *md;
+
+ if ((md = EVP_MD_meth_new(NID_sha1, NID_sha1WithRSAEncryption)) == NULL
+ || !EVP_MD_meth_set_result_size(md, SHA_DIGEST_LENGTH)
+ || !EVP_MD_meth_set_input_blocksize(md, SHA_CBLOCK)
+ || !EVP_MD_meth_set_app_datasize(md,
+ sizeof(EVP_MD *) + sizeof(SHA_CTX))
+ || !EVP_MD_meth_set_flags(md, 0)
+ || !EVP_MD_meth_set_init(md, test_sha1_init)
+ || !EVP_MD_meth_set_update(md, test_sha1_update)
+ || !EVP_MD_meth_set_final(md, test_sha1_final)) {
+ EVP_MD_meth_free(md);
+ md = NULL;
+ }
+ sha1_md = md;
+ }
+ return sha1_md;
+}
+static void test_sha_md_destroy(void)
+{
+ EVP_MD_meth_free(sha1_md);
+ sha1_md = NULL;
+}
+static int test_digest_nids(const int **nids)
+{
+ static int digest_nids[2] = { 0, 0 };
+ static int pos = 0;
+ static int init = 0;
+
+ if (!init) {
+ const EVP_MD *md;
+ if ((md = test_sha_md()) != NULL)
+ digest_nids[pos++] = EVP_MD_type(md);
+ digest_nids[pos] = 0;
+ init = 1;
+ }
+ *nids = digest_nids;
+ return pos;
+}
+
+static int openssl_digests(ENGINE *e, const EVP_MD **digest,
+ const int **nids, int nid)
+{
+ if (!digest) {
+ /* We are returning a list of supported nids */
+ return test_digest_nids(nids);
+ }
+ /* We are being asked for a specific digest */
+ if (nid == NID_sha1)
+ *digest = test_sha_md();
+ else {
+# ifdef TEST_ENG_OPENSSL_SHA_OTHERS
+ fprintf(stderr, "(TEST_ENG_OPENSSL_SHA) returning NULL for "
+ "nid %d\n", nid);
+# endif
+ *digest = NULL;
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+#ifdef TEST_ENG_OPENSSL_PKEY
+static EVP_PKEY *openssl_load_privkey(ENGINE *eng, const char *key_id,
+ UI_METHOD *ui_method,
+ void *callback_data)
+{
+ BIO *in;
+ EVP_PKEY *key;
+ fprintf(stderr, "(TEST_ENG_OPENSSL_PKEY)Loading Private key %s\n",
+ key_id);
+ in = BIO_new_file(key_id, "r");
+ if (!in)
+ return NULL;
+ key = PEM_read_bio_PrivateKey(in, NULL, 0, NULL);
+ BIO_free(in);
+ return key;
+}
+#endif
+
+#ifdef TEST_ENG_OPENSSL_HMAC
+
+/*
+ * Experimental HMAC redirection implementation: mainly copied from
+ * hm_pmeth.c
+ */
+
+/* HMAC pkey context structure */
+
+typedef struct {
+ const EVP_MD *md; /* MD for HMAC use */
+ ASN1_OCTET_STRING ktmp; /* Temp storage for key */
+ HMAC_CTX *ctx;
+} OSSL_HMAC_PKEY_CTX;
+
+static int ossl_hmac_init(EVP_PKEY_CTX *ctx)
+{
+ OSSL_HMAC_PKEY_CTX *hctx;
+
+ hctx = OPENSSL_zalloc(sizeof(*hctx));
+ if (hctx == NULL)
+ return 0;
+ hctx->ktmp.type = V_ASN1_OCTET_STRING;
+ hctx->ctx = HMAC_CTX_new();
+ if (hctx->ctx == NULL) {
+ OPENSSL_free(hctx);
+ return 0;
+ }
+ EVP_PKEY_CTX_set_data(ctx, hctx);
+ EVP_PKEY_CTX_set0_keygen_info(ctx, NULL, 0);
+# ifdef TEST_ENG_OPENSSL_HMAC_INIT
+ fprintf(stderr, "(TEST_ENG_OPENSSL_HMAC) ossl_hmac_init() called\n");
+# endif
+ return 1;
+}
+
+static void ossl_hmac_cleanup(EVP_PKEY_CTX *ctx);
+
+static int ossl_hmac_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
+{
+ OSSL_HMAC_PKEY_CTX *sctx, *dctx;
+
+ /* allocate memory for dst->data and a new HMAC_CTX in dst->data->ctx */
+ if (!ossl_hmac_init(dst))
+ return 0;
+ sctx = EVP_PKEY_CTX_get_data(src);
+ dctx = EVP_PKEY_CTX_get_data(dst);
+ dctx->md = sctx->md;
+ if (!HMAC_CTX_copy(dctx->ctx, sctx->ctx))
+ goto err;
+ if (sctx->ktmp.data) {
+ if (!ASN1_OCTET_STRING_set(&dctx->ktmp,
+ sctx->ktmp.data, sctx->ktmp.length))
+ goto err;
+ }
+ return 1;
+err:
+ /* release HMAC_CTX in dst->data->ctx and memory allocated for dst->data */
+ ossl_hmac_cleanup(dst);
+ return 0;
+}
+
+static void ossl_hmac_cleanup(EVP_PKEY_CTX *ctx)
+{
+ OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+
+ if (hctx) {
+ HMAC_CTX_free(hctx->ctx);
+ OPENSSL_clear_free(hctx->ktmp.data, hctx->ktmp.length);
+ OPENSSL_free(hctx);
+ EVP_PKEY_CTX_set_data(ctx, NULL);
+ }
+}
+
+static int ossl_hmac_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
+{
+ ASN1_OCTET_STRING *hkey = NULL;
+ OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+ if (!hctx->ktmp.data)
+ return 0;
+ hkey = ASN1_OCTET_STRING_dup(&hctx->ktmp);
+ if (!hkey)
+ return 0;
+ EVP_PKEY_assign(pkey, EVP_PKEY_HMAC, hkey);
+
+ return 1;
+}
+
+static int ossl_int_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+{
+ OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(EVP_MD_CTX_pkey_ctx(ctx));
+ if (!HMAC_Update(hctx->ctx, data, count))
+ return 0;
+ return 1;
+}
+
+static int ossl_hmac_signctx_init(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx)
+{
+ EVP_MD_CTX_set_flags(mctx, EVP_MD_CTX_FLAG_NO_INIT);
+ EVP_MD_CTX_set_update_fn(mctx, ossl_int_update);
+ return 1;
+}
+
+static int ossl_hmac_signctx(EVP_PKEY_CTX *ctx, unsigned char *sig,
+ size_t *siglen, EVP_MD_CTX *mctx)
+{
+ unsigned int hlen;
+ OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+ int l = EVP_MD_CTX_size(mctx);
+
+ if (l < 0)
+ return 0;
+ *siglen = l;
+ if (!sig)
+ return 1;
+
+ if (!HMAC_Final(hctx->ctx, sig, &hlen))
+ return 0;
+ *siglen = (size_t)hlen;
+ return 1;
+}
+
+static int ossl_hmac_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
+{
+ OSSL_HMAC_PKEY_CTX *hctx = EVP_PKEY_CTX_get_data(ctx);
+ EVP_PKEY *pk;
+ ASN1_OCTET_STRING *key;
+ switch (type) {
+
+ case EVP_PKEY_CTRL_SET_MAC_KEY:
+ if ((!p2 && p1 > 0) || (p1 < -1))
+ return 0;
+ if (!ASN1_OCTET_STRING_set(&hctx->ktmp, p2, p1))
+ return 0;
+ break;
+
+ case EVP_PKEY_CTRL_MD:
+ hctx->md = p2;
+ break;
+
+ case EVP_PKEY_CTRL_DIGESTINIT:
+ pk = EVP_PKEY_CTX_get0_pkey(ctx);
+ key = EVP_PKEY_get0(pk);
+ if (!HMAC_Init_ex(hctx->ctx, key->data, key->length, hctx->md, NULL))
+ return 0;
+ break;
+
+ default:
+ return -2;
+
+ }
+ return 1;
+}
+
+static int ossl_hmac_ctrl_str(EVP_PKEY_CTX *ctx,
+ const char *type, const char *value)
+{
+ if (!value) {
+ return 0;
+ }
+ if (strcmp(type, "key") == 0) {
+ void *p = (void *)value;
+ return ossl_hmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, -1, p);
+ }
+ if (strcmp(type, "hexkey") == 0) {
+ unsigned char *key;
+ int r;
+ long keylen;
+ key = OPENSSL_hexstr2buf(value, &keylen);
+ if (!key)
+ return 0;
+ r = ossl_hmac_ctrl(ctx, EVP_PKEY_CTRL_SET_MAC_KEY, keylen, key);
+ OPENSSL_free(key);
+ return r;
+ }
+ return -2;
+}
+
+static EVP_PKEY_METHOD *ossl_hmac_meth;
+
+static int ossl_register_hmac_meth(void)
+{
+ EVP_PKEY_METHOD *meth;
+ meth = EVP_PKEY_meth_new(EVP_PKEY_HMAC, 0);
+ if (meth == NULL)
+ return 0;
+ EVP_PKEY_meth_set_init(meth, ossl_hmac_init);
+ EVP_PKEY_meth_set_copy(meth, ossl_hmac_copy);
+ EVP_PKEY_meth_set_cleanup(meth, ossl_hmac_cleanup);
+
+ EVP_PKEY_meth_set_keygen(meth, 0, ossl_hmac_keygen);
+
+ EVP_PKEY_meth_set_signctx(meth, ossl_hmac_signctx_init,
+ ossl_hmac_signctx);
+
+ EVP_PKEY_meth_set_ctrl(meth, ossl_hmac_ctrl, ossl_hmac_ctrl_str);
+ ossl_hmac_meth = meth;
+ return 1;
+}
+
+static int ossl_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
+ const int **nids, int nid)
+{
+ static int ossl_pkey_nids[] = {
+ EVP_PKEY_HMAC,
+ 0
+ };
+ if (!pmeth) {
+ *nids = ossl_pkey_nids;
+ return 1;
+ }
+
+ if (nid == EVP_PKEY_HMAC) {
+ *pmeth = ossl_hmac_meth;
+ return 1;
+ }
+
+ *pmeth = NULL;
+ return 0;
+}
+
+#endif
+
+int openssl_destroy(ENGINE *e)
+{
+ test_sha_md_destroy();
+#ifdef TEST_ENG_OPENSSL_RC4
+ test_r4_cipher_destroy();
+ test_r4_40_cipher_destroy();
+#endif
+ return 1;
+}
+
diff --git a/openssl-1.1.0h/crypto/engine/eng_pkey.c b/openssl-1.1.0h/crypto/engine/eng_pkey.c
new file mode 100644
index 0000000..305a648
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_pkey.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+/* Basic get/set stuff */
+
+int ENGINE_set_load_privkey_function(ENGINE *e,
+ ENGINE_LOAD_KEY_PTR loadpriv_f)
+{
+ e->load_privkey = loadpriv_f;
+ return 1;
+}
+
+int ENGINE_set_load_pubkey_function(ENGINE *e, ENGINE_LOAD_KEY_PTR loadpub_f)
+{
+ e->load_pubkey = loadpub_f;
+ return 1;
+}
+
+int ENGINE_set_load_ssl_client_cert_function(ENGINE *e,
+ ENGINE_SSL_CLIENT_CERT_PTR
+ loadssl_f)
+{
+ e->load_ssl_client_cert = loadssl_f;
+ return 1;
+}
+
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_privkey_function(const ENGINE *e)
+{
+ return e->load_privkey;
+}
+
+ENGINE_LOAD_KEY_PTR ENGINE_get_load_pubkey_function(const ENGINE *e)
+{
+ return e->load_pubkey;
+}
+
+ENGINE_SSL_CLIENT_CERT_PTR ENGINE_get_ssl_client_cert_function(const ENGINE
+ *e)
+{
+ return e->load_ssl_client_cert;
+}
+
+/* API functions to load public/private keys */
+
+EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data)
+{
+ EVP_PKEY *pkey;
+
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (e->funct_ref == 0) {
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY, ENGINE_R_NOT_INITIALISED);
+ return 0;
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ if (!e->load_privkey) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
+ ENGINE_R_NO_LOAD_FUNCTION);
+ return 0;
+ }
+ pkey = e->load_privkey(e, key_id, ui_method, callback_data);
+ if (!pkey) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PRIVATE_KEY,
+ ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
+ return 0;
+ }
+ return pkey;
+}
+
+EVP_PKEY *ENGINE_load_public_key(ENGINE *e, const char *key_id,
+ UI_METHOD *ui_method, void *callback_data)
+{
+ EVP_PKEY *pkey;
+
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (e->funct_ref == 0) {
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, ENGINE_R_NOT_INITIALISED);
+ return 0;
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ if (!e->load_pubkey) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY, ENGINE_R_NO_LOAD_FUNCTION);
+ return 0;
+ }
+ pkey = e->load_pubkey(e, key_id, ui_method, callback_data);
+ if (!pkey) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_PUBLIC_KEY,
+ ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
+ return 0;
+ }
+ return pkey;
+}
+
+int ENGINE_load_ssl_client_cert(ENGINE *e, SSL *s,
+ STACK_OF(X509_NAME) *ca_dn, X509 **pcert,
+ EVP_PKEY **ppkey, STACK_OF(X509) **pother,
+ UI_METHOD *ui_method, void *callback_data)
+{
+
+ if (e == NULL) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+ ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (e->funct_ref == 0) {
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+ ENGINE_R_NOT_INITIALISED);
+ return 0;
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ if (!e->load_ssl_client_cert) {
+ ENGINEerr(ENGINE_F_ENGINE_LOAD_SSL_CLIENT_CERT,
+ ENGINE_R_NO_LOAD_FUNCTION);
+ return 0;
+ }
+ return e->load_ssl_client_cert(e, s, ca_dn, pcert, ppkey, pother,
+ ui_method, callback_data);
+}
diff --git a/openssl-1.1.0h/crypto/engine/eng_rdrand.c b/openssl-1.1.0h/crypto/engine/eng_rdrand.c
new file mode 100644
index 0000000..b3defcb
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_rdrand.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2011-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/opensslconf.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <internal/engine.h>
+#include <openssl/rand.h>
+#include <openssl/err.h>
+#include <openssl/crypto.h>
+
+#if (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(__x86_64) || defined(__x86_64__) || \
+ defined(_M_AMD64) || defined (_M_X64)) && defined(OPENSSL_CPUID_OBJ)
+
+size_t OPENSSL_ia32_rdrand(void);
+
+static int get_random_bytes(unsigned char *buf, int num)
+{
+ size_t rnd;
+
+ while (num >= (int)sizeof(size_t)) {
+ if ((rnd = OPENSSL_ia32_rdrand()) == 0)
+ return 0;
+
+ *((size_t *)buf) = rnd;
+ buf += sizeof(size_t);
+ num -= sizeof(size_t);
+ }
+ if (num) {
+ if ((rnd = OPENSSL_ia32_rdrand()) == 0)
+ return 0;
+
+ memcpy(buf, &rnd, num);
+ }
+
+ return 1;
+}
+
+static int random_status(void)
+{
+ return 1;
+}
+
+static RAND_METHOD rdrand_meth = {
+ NULL, /* seed */
+ get_random_bytes,
+ NULL, /* cleanup */
+ NULL, /* add */
+ get_random_bytes,
+ random_status,
+};
+
+static int rdrand_init(ENGINE *e)
+{
+ return 1;
+}
+
+static const char *engine_e_rdrand_id = "rdrand";
+static const char *engine_e_rdrand_name = "Intel RDRAND engine";
+
+static int bind_helper(ENGINE *e)
+{
+ if (!ENGINE_set_id(e, engine_e_rdrand_id) ||
+ !ENGINE_set_name(e, engine_e_rdrand_name) ||
+ !ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL) ||
+ !ENGINE_set_init_function(e, rdrand_init) ||
+ !ENGINE_set_RAND(e, &rdrand_meth))
+ return 0;
+
+ return 1;
+}
+
+static ENGINE *ENGINE_rdrand(void)
+{
+ ENGINE *ret = ENGINE_new();
+ if (ret == NULL)
+ return NULL;
+ if (!bind_helper(ret)) {
+ ENGINE_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+void engine_load_rdrand_int(void)
+{
+ extern unsigned int OPENSSL_ia32cap_P[];
+
+ if (OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) {
+ ENGINE *toadd = ENGINE_rdrand();
+ if (!toadd)
+ return;
+ ENGINE_add(toadd);
+ ENGINE_free(toadd);
+ ERR_clear_error();
+ }
+}
+#else
+void engine_load_rdrand_int(void)
+{
+}
+#endif
diff --git a/openssl-1.1.0h/crypto/engine/eng_table.c b/openssl-1.1.0h/crypto/engine/eng_table.c
new file mode 100644
index 0000000..ac4b02f
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/eng_table.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2001-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 "internal/cryptlib.h"
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include "eng_int.h"
+
+/* The type of the items in the table */
+struct st_engine_pile {
+ /* The 'nid' of this algorithm/mode */
+ int nid;
+ /* ENGINEs that implement this algorithm/mode. */
+ STACK_OF(ENGINE) *sk;
+ /* The default ENGINE to perform this algorithm/mode. */
+ ENGINE *funct;
+ /*
+ * Zero if 'sk' is newer than the cached 'funct', non-zero otherwise
+ */
+ int uptodate;
+};
+
+/* The type exposed in eng_int.h */
+struct st_engine_table {
+ LHASH_OF(ENGINE_PILE) piles;
+}; /* ENGINE_TABLE */
+
+typedef struct st_engine_pile_doall {
+ engine_table_doall_cb *cb;
+ void *arg;
+} ENGINE_PILE_DOALL;
+
+/* Global flags (ENGINE_TABLE_FLAG_***). */
+static unsigned int table_flags = 0;
+
+/* API function manipulating 'table_flags' */
+unsigned int ENGINE_get_table_flags(void)
+{
+ return table_flags;
+}
+
+void ENGINE_set_table_flags(unsigned int flags)
+{
+ table_flags = flags;
+}
+
+/* Internal functions for the "piles" hash table */
+static unsigned long engine_pile_hash(const ENGINE_PILE *c)
+{
+ return c->nid;
+}
+
+static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b)
+{
+ return a->nid - b->nid;
+}
+
+static int int_table_check(ENGINE_TABLE **t, int create)
+{
+ LHASH_OF(ENGINE_PILE) *lh;
+
+ if (*t)
+ return 1;
+ if (!create)
+ return 0;
+ if ((lh = lh_ENGINE_PILE_new(engine_pile_hash, engine_pile_cmp)) == NULL)
+ return 0;
+ *t = (ENGINE_TABLE *)lh;
+ return 1;
+}
+
+/*
+ * Privately exposed (via eng_int.h) functions for adding and/or removing
+ * ENGINEs from the implementation table
+ */
+int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
+ ENGINE *e, const int *nids, int num_nids,
+ int setdefault)
+{
+ int ret = 0, added = 0;
+ ENGINE_PILE tmplate, *fnd;
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (!(*table))
+ added = 1;
+ if (!int_table_check(table, 1))
+ goto end;
+ if (added)
+ /* The cleanup callback needs to be added */
+ engine_cleanup_add_first(cleanup);
+ while (num_nids--) {
+ tmplate.nid = *nids;
+ fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
+ if (!fnd) {
+ fnd = OPENSSL_malloc(sizeof(*fnd));
+ if (fnd == NULL)
+ goto end;
+ fnd->uptodate = 1;
+ fnd->nid = *nids;
+ fnd->sk = sk_ENGINE_new_null();
+ if (!fnd->sk) {
+ OPENSSL_free(fnd);
+ goto end;
+ }
+ fnd->funct = NULL;
+ (void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd);
+ if (lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate) != fnd) {
+ sk_ENGINE_free(fnd->sk);
+ OPENSSL_free(fnd);
+ goto end;
+ }
+ }
+ /* A registration shouldn't add duplicate entries */
+ (void)sk_ENGINE_delete_ptr(fnd->sk, e);
+ /*
+ * if 'setdefault', this ENGINE goes to the head of the list
+ */
+ if (!sk_ENGINE_push(fnd->sk, e))
+ goto end;
+ /* "touch" this ENGINE_PILE */
+ fnd->uptodate = 0;
+ if (setdefault) {
+ if (!engine_unlocked_init(e)) {
+ ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER,
+ ENGINE_R_INIT_FAILED);
+ goto end;
+ }
+ if (fnd->funct)
+ engine_unlocked_finish(fnd->funct, 0);
+ fnd->funct = e;
+ fnd->uptodate = 1;
+ }
+ nids++;
+ }
+ ret = 1;
+ end:
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return ret;
+}
+
+static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e)
+{
+ int n;
+ /* Iterate the 'c->sk' stack removing any occurrence of 'e' */
+ while ((n = sk_ENGINE_find(pile->sk, e)) >= 0) {
+ (void)sk_ENGINE_delete(pile->sk, n);
+ pile->uptodate = 0;
+ }
+ if (pile->funct == e) {
+ engine_unlocked_finish(e, 0);
+ pile->funct = NULL;
+ }
+}
+
+IMPLEMENT_LHASH_DOALL_ARG(ENGINE_PILE, ENGINE);
+
+void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
+{
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (int_table_check(table, 0))
+ lh_ENGINE_PILE_doall_ENGINE(&(*table)->piles, int_unregister_cb, e);
+ CRYPTO_THREAD_unlock(global_engine_lock);
+}
+
+static void int_cleanup_cb_doall(ENGINE_PILE *p)
+{
+ if (!p)
+ return;
+ sk_ENGINE_free(p->sk);
+ if (p->funct)
+ engine_unlocked_finish(p->funct, 0);
+ OPENSSL_free(p);
+}
+
+void engine_table_cleanup(ENGINE_TABLE **table)
+{
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ if (*table) {
+ lh_ENGINE_PILE_doall(&(*table)->piles, int_cleanup_cb_doall);
+ lh_ENGINE_PILE_free(&(*table)->piles);
+ *table = NULL;
+ }
+ CRYPTO_THREAD_unlock(global_engine_lock);
+}
+
+/* return a functional reference for a given 'nid' */
+#ifndef ENGINE_TABLE_DEBUG
+ENGINE *engine_table_select(ENGINE_TABLE **table, int nid)
+#else
+ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f,
+ int l)
+#endif
+{
+ ENGINE *ret = NULL;
+ ENGINE_PILE tmplate, *fnd = NULL;
+ int initres, loop = 0;
+
+ if (!(*table)) {
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
+ "registered!\n", f, l, nid);
+#endif
+ return NULL;
+ }
+ ERR_set_mark();
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ /*
+ * Check again inside the lock otherwise we could race against cleanup
+ * operations. But don't worry about a fprintf(stderr).
+ */
+ if (!int_table_check(table, 0))
+ goto end;
+ tmplate.nid = nid;
+ fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
+ if (!fnd)
+ goto end;
+ if (fnd->funct && engine_unlocked_init(fnd->funct)) {
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
+ "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);
+#endif
+ ret = fnd->funct;
+ goto end;
+ }
+ if (fnd->uptodate) {
+ ret = fnd->funct;
+ goto end;
+ }
+ trynext:
+ ret = sk_ENGINE_value(fnd->sk, loop++);
+ if (!ret) {
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "
+ "registered implementations would initialise\n", f, l, nid);
+#endif
+ goto end;
+ }
+ /* Try to initialise the ENGINE? */
+ if ((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT))
+ initres = engine_unlocked_init(ret);
+ else
+ initres = 0;
+ if (initres) {
+ /* Update 'funct' */
+ if ((fnd->funct != ret) && engine_unlocked_init(ret)) {
+ /* If there was a previous default we release it. */
+ if (fnd->funct)
+ engine_unlocked_finish(fnd->funct, 0);
+ fnd->funct = ret;
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "
+ "setting default to '%s'\n", f, l, nid, ret->id);
+#endif
+ }
+#ifdef ENGINE_TABLE_DEBUG
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
+ "newly initialised '%s'\n", f, l, nid, ret->id);
+#endif
+ goto end;
+ }
+ goto trynext;
+ end:
+ /*
+ * If it failed, it is unlikely to succeed again until some future
+ * registrations have taken place. In all cases, we cache.
+ */
+ if (fnd)
+ fnd->uptodate = 1;
+#ifdef ENGINE_TABLE_DEBUG
+ if (ret)
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
+ "ENGINE '%s'\n", f, l, nid, ret->id);
+ else
+ fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
+ "'no matching ENGINE'\n", f, l, nid);
+#endif
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ /*
+ * Whatever happened, any failed init()s are not failures in this
+ * context, so clear our error state.
+ */
+ ERR_pop_to_mark();
+ return ret;
+}
+
+/* Table enumeration */
+
+static void int_dall(const ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall)
+{
+ dall->cb(pile->nid, pile->sk, pile->funct, dall->arg);
+}
+
+IMPLEMENT_LHASH_DOALL_ARG_CONST(ENGINE_PILE, ENGINE_PILE_DOALL);
+
+void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb,
+ void *arg)
+{
+ ENGINE_PILE_DOALL dall;
+ dall.cb = cb;
+ dall.arg = arg;
+ if (table)
+ lh_ENGINE_PILE_doall_ENGINE_PILE_DOALL(&table->piles, int_dall, &dall);
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_asnmth.c b/openssl-1.1.0h/crypto/engine/tb_asnmth.c
new file mode 100644
index 0000000..480267d
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_asnmth.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2006-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 "eng_int.h"
+#include <openssl/evp.h>
+#include "internal/asn1_int.h"
+
+/*
+ * If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the
+ * function that is used by EVP to hook in pkey_asn1_meth code and cache
+ * defaults (etc), will display brief debugging summaries to stderr with the
+ * 'nid'.
+ */
+/* #define ENGINE_PKEY_ASN1_METH_DEBUG */
+
+static ENGINE_TABLE *pkey_asn1_meth_table = NULL;
+
+void ENGINE_unregister_pkey_asn1_meths(ENGINE *e)
+{
+ engine_table_unregister(&pkey_asn1_meth_table, e);
+}
+
+static void engine_unregister_all_pkey_asn1_meths(void)
+{
+ engine_table_cleanup(&pkey_asn1_meth_table);
+}
+
+int ENGINE_register_pkey_asn1_meths(ENGINE *e)
+{
+ if (e->pkey_asn1_meths) {
+ const int *nids;
+ int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&pkey_asn1_meth_table,
+ engine_unregister_all_pkey_asn1_meths,
+ e, nids, num_nids, 0);
+ }
+ return 1;
+}
+
+void ENGINE_register_all_pkey_asn1_meths(void)
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_pkey_asn1_meths(e);
+}
+
+int ENGINE_set_default_pkey_asn1_meths(ENGINE *e)
+{
+ if (e->pkey_asn1_meths) {
+ const int *nids;
+ int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&pkey_asn1_meth_table,
+ engine_unregister_all_pkey_asn1_meths,
+ e, nids, num_nids, 1);
+ }
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given pkey_asn1_meth 'nid'
+ */
+ENGINE *ENGINE_get_pkey_asn1_meth_engine(int nid)
+{
+ return engine_table_select(&pkey_asn1_meth_table, nid);
+}
+
+/*
+ * Obtains a pkey_asn1_meth implementation from an ENGINE functional
+ * reference
+ */
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid)
+{
+ EVP_PKEY_ASN1_METHOD *ret;
+ ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e);
+ if (!fn || !fn(e, &ret, NULL, nid)) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH,
+ ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
+ return NULL;
+ }
+ return ret;
+}
+
+/* Gets the pkey_asn1_meth callback from an ENGINE structure */
+ENGINE_PKEY_ASN1_METHS_PTR ENGINE_get_pkey_asn1_meths(const ENGINE *e)
+{
+ return e->pkey_asn1_meths;
+}
+
+/* Sets the pkey_asn1_meth callback in an ENGINE structure */
+int ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f)
+{
+ e->pkey_asn1_meths = f;
+ return 1;
+}
+
+/*
+ * Internal function to free up EVP_PKEY_ASN1_METHOD structures before an
+ * ENGINE is destroyed
+ */
+
+void engine_pkey_asn1_meths_free(ENGINE *e)
+{
+ int i;
+ EVP_PKEY_ASN1_METHOD *pkm;
+ if (e->pkey_asn1_meths) {
+ const int *pknids;
+ int npknids;
+ npknids = e->pkey_asn1_meths(e, NULL, &pknids, 0);
+ for (i = 0; i < npknids; i++) {
+ if (e->pkey_asn1_meths(e, &pkm, NULL, pknids[i])) {
+ EVP_PKEY_asn1_free(pkm);
+ }
+ }
+ }
+}
+
+/*
+ * Find a method based on a string. This does a linear search through all
+ * implemented algorithms. This is OK in practice because only a small number
+ * of algorithms are likely to be implemented in an engine and it is not used
+ * for speed critical operations.
+ */
+
+const EVP_PKEY_ASN1_METHOD *ENGINE_get_pkey_asn1_meth_str(ENGINE *e,
+ const char *str,
+ int len)
+{
+ int i, nidcount;
+ const int *nids;
+ EVP_PKEY_ASN1_METHOD *ameth;
+ if (!e->pkey_asn1_meths)
+ return NULL;
+ if (len == -1)
+ len = strlen(str);
+ nidcount = e->pkey_asn1_meths(e, NULL, &nids, 0);
+ for (i = 0; i < nidcount; i++) {
+ e->pkey_asn1_meths(e, &ameth, NULL, nids[i]);
+ if (((int)strlen(ameth->pem_str) == len)
+ && strncasecmp(ameth->pem_str, str, len) == 0)
+ return ameth;
+ }
+ return NULL;
+}
+
+typedef struct {
+ ENGINE *e;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ const char *str;
+ int len;
+} ENGINE_FIND_STR;
+
+static void look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg)
+{
+ ENGINE_FIND_STR *lk = arg;
+ int i;
+ if (lk->ameth)
+ return;
+ for (i = 0; i < sk_ENGINE_num(sk); i++) {
+ ENGINE *e = sk_ENGINE_value(sk, i);
+ EVP_PKEY_ASN1_METHOD *ameth;
+ e->pkey_asn1_meths(e, &ameth, NULL, nid);
+ if (((int)strlen(ameth->pem_str) == lk->len)
+ && strncasecmp(ameth->pem_str, lk->str, lk->len) == 0) {
+ lk->e = e;
+ lk->ameth = ameth;
+ return;
+ }
+ }
+}
+
+const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe,
+ const char *str,
+ int len)
+{
+ ENGINE_FIND_STR fstr;
+ fstr.e = NULL;
+ fstr.ameth = NULL;
+ fstr.str = str;
+ fstr.len = len;
+
+ if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)) {
+ ENGINEerr(ENGINE_F_ENGINE_PKEY_ASN1_FIND_STR, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ CRYPTO_THREAD_write_lock(global_engine_lock);
+ engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr);
+ /* If found obtain a structural reference to engine */
+ if (fstr.e) {
+ fstr.e->struct_ref++;
+ engine_ref_debug(fstr.e, 0, 1);
+ }
+ *pe = fstr.e;
+ CRYPTO_THREAD_unlock(global_engine_lock);
+ return fstr.ameth;
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_cipher.c b/openssl-1.1.0h/crypto/engine/tb_cipher.c
new file mode 100644
index 0000000..ac49141
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_cipher.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+static ENGINE_TABLE *cipher_table = NULL;
+
+void ENGINE_unregister_ciphers(ENGINE *e)
+{
+ engine_table_unregister(&cipher_table, e);
+}
+
+static void engine_unregister_all_ciphers(void)
+{
+ engine_table_cleanup(&cipher_table);
+}
+
+int ENGINE_register_ciphers(ENGINE *e)
+{
+ if (e->ciphers) {
+ const int *nids;
+ int num_nids = e->ciphers(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&cipher_table,
+ engine_unregister_all_ciphers, e,
+ nids, num_nids, 0);
+ }
+ return 1;
+}
+
+void ENGINE_register_all_ciphers()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_ciphers(e);
+}
+
+int ENGINE_set_default_ciphers(ENGINE *e)
+{
+ if (e->ciphers) {
+ const int *nids;
+ int num_nids = e->ciphers(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&cipher_table,
+ engine_unregister_all_ciphers, e,
+ nids, num_nids, 1);
+ }
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given cipher 'nid'
+ */
+ENGINE *ENGINE_get_cipher_engine(int nid)
+{
+ return engine_table_select(&cipher_table, nid);
+}
+
+/* Obtains a cipher implementation from an ENGINE functional reference */
+const EVP_CIPHER *ENGINE_get_cipher(ENGINE *e, int nid)
+{
+ const EVP_CIPHER *ret;
+ ENGINE_CIPHERS_PTR fn = ENGINE_get_ciphers(e);
+ if (!fn || !fn(e, &ret, NULL, nid)) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_CIPHER, ENGINE_R_UNIMPLEMENTED_CIPHER);
+ return NULL;
+ }
+ return ret;
+}
+
+/* Gets the cipher callback from an ENGINE structure */
+ENGINE_CIPHERS_PTR ENGINE_get_ciphers(const ENGINE *e)
+{
+ return e->ciphers;
+}
+
+/* Sets the cipher callback in an ENGINE structure */
+int ENGINE_set_ciphers(ENGINE *e, ENGINE_CIPHERS_PTR f)
+{
+ e->ciphers = f;
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_dh.c b/openssl-1.1.0h/crypto/engine/tb_dh.c
new file mode 100644
index 0000000..c6440df
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_dh.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+static ENGINE_TABLE *dh_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_DH(ENGINE *e)
+{
+ engine_table_unregister(&dh_table, e);
+}
+
+static void engine_unregister_all_DH(void)
+{
+ engine_table_cleanup(&dh_table);
+}
+
+int ENGINE_register_DH(ENGINE *e)
+{
+ if (e->dh_meth)
+ return engine_table_register(&dh_table,
+ engine_unregister_all_DH, e, &dummy_nid,
+ 1, 0);
+ return 1;
+}
+
+void ENGINE_register_all_DH()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_DH(e);
+}
+
+int ENGINE_set_default_DH(ENGINE *e)
+{
+ if (e->dh_meth)
+ return engine_table_register(&dh_table,
+ engine_unregister_all_DH, e, &dummy_nid,
+ 1, 1);
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references).
+ */
+ENGINE *ENGINE_get_default_DH(void)
+{
+ return engine_table_select(&dh_table, dummy_nid);
+}
+
+/* Obtains an DH implementation from an ENGINE functional reference */
+const DH_METHOD *ENGINE_get_DH(const ENGINE *e)
+{
+ return e->dh_meth;
+}
+
+/* Sets an DH implementation in an ENGINE structure */
+int ENGINE_set_DH(ENGINE *e, const DH_METHOD *dh_meth)
+{
+ e->dh_meth = dh_meth;
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_digest.c b/openssl-1.1.0h/crypto/engine/tb_digest.c
new file mode 100644
index 0000000..194b9c7
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_digest.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+static ENGINE_TABLE *digest_table = NULL;
+
+void ENGINE_unregister_digests(ENGINE *e)
+{
+ engine_table_unregister(&digest_table, e);
+}
+
+static void engine_unregister_all_digests(void)
+{
+ engine_table_cleanup(&digest_table);
+}
+
+int ENGINE_register_digests(ENGINE *e)
+{
+ if (e->digests) {
+ const int *nids;
+ int num_nids = e->digests(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&digest_table,
+ engine_unregister_all_digests, e,
+ nids, num_nids, 0);
+ }
+ return 1;
+}
+
+void ENGINE_register_all_digests()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_digests(e);
+}
+
+int ENGINE_set_default_digests(ENGINE *e)
+{
+ if (e->digests) {
+ const int *nids;
+ int num_nids = e->digests(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&digest_table,
+ engine_unregister_all_digests, e,
+ nids, num_nids, 1);
+ }
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given digest 'nid'
+ */
+ENGINE *ENGINE_get_digest_engine(int nid)
+{
+ return engine_table_select(&digest_table, nid);
+}
+
+/* Obtains a digest implementation from an ENGINE functional reference */
+const EVP_MD *ENGINE_get_digest(ENGINE *e, int nid)
+{
+ const EVP_MD *ret;
+ ENGINE_DIGESTS_PTR fn = ENGINE_get_digests(e);
+ if (!fn || !fn(e, &ret, NULL, nid)) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_DIGEST, ENGINE_R_UNIMPLEMENTED_DIGEST);
+ return NULL;
+ }
+ return ret;
+}
+
+/* Gets the digest callback from an ENGINE structure */
+ENGINE_DIGESTS_PTR ENGINE_get_digests(const ENGINE *e)
+{
+ return e->digests;
+}
+
+/* Sets the digest callback in an ENGINE structure */
+int ENGINE_set_digests(ENGINE *e, ENGINE_DIGESTS_PTR f)
+{
+ e->digests = f;
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_dsa.c b/openssl-1.1.0h/crypto/engine/tb_dsa.c
new file mode 100644
index 0000000..fdb80cd
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_dsa.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+static ENGINE_TABLE *dsa_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_DSA(ENGINE *e)
+{
+ engine_table_unregister(&dsa_table, e);
+}
+
+static void engine_unregister_all_DSA(void)
+{
+ engine_table_cleanup(&dsa_table);
+}
+
+int ENGINE_register_DSA(ENGINE *e)
+{
+ if (e->dsa_meth)
+ return engine_table_register(&dsa_table,
+ engine_unregister_all_DSA, e, &dummy_nid,
+ 1, 0);
+ return 1;
+}
+
+void ENGINE_register_all_DSA()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_DSA(e);
+}
+
+int ENGINE_set_default_DSA(ENGINE *e)
+{
+ if (e->dsa_meth)
+ return engine_table_register(&dsa_table,
+ engine_unregister_all_DSA, e, &dummy_nid,
+ 1, 1);
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references).
+ */
+ENGINE *ENGINE_get_default_DSA(void)
+{
+ return engine_table_select(&dsa_table, dummy_nid);
+}
+
+/* Obtains an DSA implementation from an ENGINE functional reference */
+const DSA_METHOD *ENGINE_get_DSA(const ENGINE *e)
+{
+ return e->dsa_meth;
+}
+
+/* Sets an DSA implementation in an ENGINE structure */
+int ENGINE_set_DSA(ENGINE *e, const DSA_METHOD *dsa_meth)
+{
+ e->dsa_meth = dsa_meth;
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_eckey.c b/openssl-1.1.0h/crypto/engine/tb_eckey.c
new file mode 100644
index 0000000..75750b2
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_eckey.c
@@ -0,0 +1,72 @@
+/*
+ * 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 "eng_int.h"
+
+static ENGINE_TABLE *dh_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_EC(ENGINE *e)
+{
+ engine_table_unregister(&dh_table, e);
+}
+
+static void engine_unregister_all_EC(void)
+{
+ engine_table_cleanup(&dh_table);
+}
+
+int ENGINE_register_EC(ENGINE *e)
+{
+ if (e->ec_meth != NULL)
+ return engine_table_register(&dh_table,
+ engine_unregister_all_EC, e, &dummy_nid,
+ 1, 0);
+ return 1;
+}
+
+void ENGINE_register_all_EC()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_EC(e);
+}
+
+int ENGINE_set_default_EC(ENGINE *e)
+{
+ if (e->ec_meth != NULL)
+ return engine_table_register(&dh_table,
+ engine_unregister_all_EC, e, &dummy_nid,
+ 1, 1);
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references).
+ */
+ENGINE *ENGINE_get_default_EC(void)
+{
+ return engine_table_select(&dh_table, dummy_nid);
+}
+
+/* Obtains an EC_KEY implementation from an ENGINE functional reference */
+const EC_KEY_METHOD *ENGINE_get_EC(const ENGINE *e)
+{
+ return e->ec_meth;
+}
+
+/* Sets an EC_KEY implementation in an ENGINE structure */
+int ENGINE_set_EC(ENGINE *e, const EC_KEY_METHOD *ec_meth)
+{
+ e->ec_meth = ec_meth;
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_pkmeth.c b/openssl-1.1.0h/crypto/engine/tb_pkmeth.c
new file mode 100644
index 0000000..2e82d85
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_pkmeth.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2006-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 "eng_int.h"
+#include <openssl/evp.h>
+
+static ENGINE_TABLE *pkey_meth_table = NULL;
+
+void ENGINE_unregister_pkey_meths(ENGINE *e)
+{
+ engine_table_unregister(&pkey_meth_table, e);
+}
+
+static void engine_unregister_all_pkey_meths(void)
+{
+ engine_table_cleanup(&pkey_meth_table);
+}
+
+int ENGINE_register_pkey_meths(ENGINE *e)
+{
+ if (e->pkey_meths) {
+ const int *nids;
+ int num_nids = e->pkey_meths(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&pkey_meth_table,
+ engine_unregister_all_pkey_meths, e,
+ nids, num_nids, 0);
+ }
+ return 1;
+}
+
+void ENGINE_register_all_pkey_meths()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_pkey_meths(e);
+}
+
+int ENGINE_set_default_pkey_meths(ENGINE *e)
+{
+ if (e->pkey_meths) {
+ const int *nids;
+ int num_nids = e->pkey_meths(e, NULL, &nids, 0);
+ if (num_nids > 0)
+ return engine_table_register(&pkey_meth_table,
+ engine_unregister_all_pkey_meths, e,
+ nids, num_nids, 1);
+ }
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references) for a given pkey_meth 'nid'
+ */
+ENGINE *ENGINE_get_pkey_meth_engine(int nid)
+{
+ return engine_table_select(&pkey_meth_table, nid);
+}
+
+/* Obtains a pkey_meth implementation from an ENGINE functional reference */
+const EVP_PKEY_METHOD *ENGINE_get_pkey_meth(ENGINE *e, int nid)
+{
+ EVP_PKEY_METHOD *ret;
+ ENGINE_PKEY_METHS_PTR fn = ENGINE_get_pkey_meths(e);
+ if (!fn || !fn(e, &ret, NULL, nid)) {
+ ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_METH,
+ ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
+ return NULL;
+ }
+ return ret;
+}
+
+/* Gets the pkey_meth callback from an ENGINE structure */
+ENGINE_PKEY_METHS_PTR ENGINE_get_pkey_meths(const ENGINE *e)
+{
+ return e->pkey_meths;
+}
+
+/* Sets the pkey_meth callback in an ENGINE structure */
+int ENGINE_set_pkey_meths(ENGINE *e, ENGINE_PKEY_METHS_PTR f)
+{
+ e->pkey_meths = f;
+ return 1;
+}
+
+/*
+ * Internal function to free up EVP_PKEY_METHOD structures before an ENGINE
+ * is destroyed
+ */
+
+void engine_pkey_meths_free(ENGINE *e)
+{
+ int i;
+ EVP_PKEY_METHOD *pkm;
+ if (e->pkey_meths) {
+ const int *pknids;
+ int npknids;
+ npknids = e->pkey_meths(e, NULL, &pknids, 0);
+ for (i = 0; i < npknids; i++) {
+ if (e->pkey_meths(e, &pkm, NULL, pknids[i])) {
+ EVP_PKEY_meth_free(pkm);
+ }
+ }
+ }
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_rand.c b/openssl-1.1.0h/crypto/engine/tb_rand.c
new file mode 100644
index 0000000..225e7c8
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_rand.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+static ENGINE_TABLE *rand_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_RAND(ENGINE *e)
+{
+ engine_table_unregister(&rand_table, e);
+}
+
+static void engine_unregister_all_RAND(void)
+{
+ engine_table_cleanup(&rand_table);
+}
+
+int ENGINE_register_RAND(ENGINE *e)
+{
+ if (e->rand_meth)
+ return engine_table_register(&rand_table,
+ engine_unregister_all_RAND, e,
+ &dummy_nid, 1, 0);
+ return 1;
+}
+
+void ENGINE_register_all_RAND()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_RAND(e);
+}
+
+int ENGINE_set_default_RAND(ENGINE *e)
+{
+ if (e->rand_meth)
+ return engine_table_register(&rand_table,
+ engine_unregister_all_RAND, e,
+ &dummy_nid, 1, 1);
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references).
+ */
+ENGINE *ENGINE_get_default_RAND(void)
+{
+ return engine_table_select(&rand_table, dummy_nid);
+}
+
+/* Obtains an RAND implementation from an ENGINE functional reference */
+const RAND_METHOD *ENGINE_get_RAND(const ENGINE *e)
+{
+ return e->rand_meth;
+}
+
+/* Sets an RAND implementation in an ENGINE structure */
+int ENGINE_set_RAND(ENGINE *e, const RAND_METHOD *rand_meth)
+{
+ e->rand_meth = rand_meth;
+ return 1;
+}
diff --git a/openssl-1.1.0h/crypto/engine/tb_rsa.c b/openssl-1.1.0h/crypto/engine/tb_rsa.c
new file mode 100644
index 0000000..e2cc680
--- /dev/null
+++ b/openssl-1.1.0h/crypto/engine/tb_rsa.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2001-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 "eng_int.h"
+
+static ENGINE_TABLE *rsa_table = NULL;
+static const int dummy_nid = 1;
+
+void ENGINE_unregister_RSA(ENGINE *e)
+{
+ engine_table_unregister(&rsa_table, e);
+}
+
+static void engine_unregister_all_RSA(void)
+{
+ engine_table_cleanup(&rsa_table);
+}
+
+int ENGINE_register_RSA(ENGINE *e)
+{
+ if (e->rsa_meth)
+ return engine_table_register(&rsa_table,
+ engine_unregister_all_RSA, e, &dummy_nid,
+ 1, 0);
+ return 1;
+}
+
+void ENGINE_register_all_RSA()
+{
+ ENGINE *e;
+
+ for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
+ ENGINE_register_RSA(e);
+}
+
+int ENGINE_set_default_RSA(ENGINE *e)
+{
+ if (e->rsa_meth)
+ return engine_table_register(&rsa_table,
+ engine_unregister_all_RSA, e, &dummy_nid,
+ 1, 1);
+ return 1;
+}
+
+/*
+ * Exposed API function to get a functional reference from the implementation
+ * table (ie. try to get a functional reference from the tabled structural
+ * references).
+ */
+ENGINE *ENGINE_get_default_RSA(void)
+{
+ return engine_table_select(&rsa_table, dummy_nid);
+}
+
+/* Obtains an RSA implementation from an ENGINE functional reference */
+const RSA_METHOD *ENGINE_get_RSA(const ENGINE *e)
+{
+ return e->rsa_meth;
+}
+
+/* Sets an RSA implementation in an ENGINE structure */
+int ENGINE_set_RSA(ENGINE *e, const RSA_METHOD *rsa_meth)
+{
+ e->rsa_meth = rsa_meth;
+ return 1;
+}