diff mbox series

[OpenWrt-Devel,v2] openssl: backport devcrypto changes from master

Message ID mailman.23089.1550777428.2376.openwrt-devel@lists.openwrt.org
State Superseded
Headers show
Series [OpenWrt-Devel,v2] openssl: backport devcrypto changes from master | expand

Commit Message

hurrhnn--- via openwrt-devel Feb. 21, 2019, 7:30 p.m. UTC
The sender domain has a DMARC Reject/Quarantine policy which disallows
sending mailing list messages using the original "From" header.

To mitigate this problem, the original message has been wrapped
automatically by the mailing list software.
The patches to the /dev/crypto engine were commited to openssl master,
and will be in the next major version (3.0).

Changes:
- Optimization in computing a digest in one operation, saving an ioctl
- Runtime configuration options for the choice of algorithms to use
- Command to dump useful information about the algorithms supported by
  the engine and the system.
- Build the devcrypto engine as a dynamic module, like other engines.

The devcrypto engine is built as a separate package by default, but
options were added to allow building the engines into the main library.

Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
---
This should only be merged after
openssl: fix devcrypto engine md blocksize

I forgot to mention it before, but this was run-tested on Linksys
WRT3200ACM, WRT610N (software-only), & ASUS RT-N56U (software-only),
running nginx, bind, unbound, and now openssh.

Changes:
v2: accommodate changes from openssl: fix devcrypto engine md blocksize
    increased PKG_RELEASE
diff mbox series

Patch

diff --git a/package/libs/openssl/Config.in b/package/libs/openssl/Config.in
index 3ad8a66b9e..235f38e787 100644
--- a/package/libs/openssl/Config.in
+++ b/package/libs/openssl/Config.in
@@ -253,18 +253,41 @@  config OPENSSL_ENGINE
 		Note that you need to enable KERNEL_AIO to be able to build the
 		afalg engine package.
 
-config OPENSSL_ENGINE_CRYPTO
+config OPENSSL_ENGINE_BUILTIN
+	bool "Build chosen engines into libcrypto"
+	depends on OPENSSL_ENGINE
+	help
+		This builds all chosen engines into libcrypto.so, instead of building
+		them as dynamic engines in separate packages.
+		The benefit of building the engines into libcrypto is that they won't
+		require any configuration to be used by default.
+
+config OPENSSL_ENGINE_BUILTIN_AFALG
 	bool
-	select OPENSSL_ENGINE
-	select PACKAGE_kmod-cryptodev
+	prompt "Acceleration support through AF_ALG sockets engine"
+	depends on OPENSSL_ENGINE_BUILTIN && KERNEL_AIO && !LINUX_3_18
 	select PACKAGE_libopenssl-conf
+	help
+		This enables use of hardware acceleration through the
+		AF_ALG kenrel interface.
+
+config OPENSSL_ENGINE_BUILTIN_DEVCRYPTO
+	bool
 	prompt "Acceleration support through /dev/crypto"
+	depends on OPENSSL_ENGINE_BUILTIN
+	select PACKAGE_libopenssl-conf
 	help
 		This enables use of hardware acceleration through OpenBSD
 		Cryptodev API (/dev/crypto) interface.
-		You must install kmod-cryptodev (under Kernel modules, Cryptographic
-		API modules) for /dev/crypto to show up and use hardware
-		acceleration; otherwise it falls back to software.
+
+config OPENSSL_ENGINE_BUILTIN_PADLOCK
+	bool
+	prompt "VIA Padlock Acceleration support engine"
+	depends on OPENSSL_ENGINE_BUILTIN && TARGET_x86
+	select PACKAGE_libopenssl-conf
+	help
+		This enables use of hardware acceleration through the
+		VIA Padlock module.
 
 config OPENSSL_WITH_ASYNC
 	bool
diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile
index ab32668cb9..2320ceb714 100644
--- a/package/libs/openssl/Makefile
+++ b/package/libs/openssl/Makefile
@@ -11,7 +11,7 @@  PKG_NAME:=openssl
 PKG_BASE:=1.1.1
 PKG_BUGFIX:=a
 PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX)
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 PKG_USE_MIPS16:=0
 ENGINES_DIR=engines-1.1
 
@@ -32,7 +32,10 @@  PKG_LICENSE_FILES:=LICENSE
 PKG_CPE_ID:=cpe:/a:openssl:openssl
 PKG_CONFIG_DEPENDS:= \
 	CONFIG_OPENSSL_ENGINE \
-	CONFIG_OPENSSL_ENGINE_CRYPTO \
+	CONFIG_OPENSSL_ENGINE_BUILTIN \
+	CONFIG_OPENSSL_ENGINE_BUILTIN_AFALG \
+	CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO \
+	CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK \
 	CONFIG_OPENSSL_NO_DEPRECATED \
 	CONFIG_OPENSSL_OPTIMIZE_SPEED \
 	CONFIG_OPENSSL_PREFER_CHACHA_OVER_GCM \
@@ -89,7 +92,10 @@  endef
 define Package/libopenssl
 $(call Package/openssl/Default)
   SUBMENU:=SSL
-  DEPENDS:=+OPENSSL_WITH_COMPRESSION:zlib
+  DEPENDS:=+OPENSSL_WITH_COMPRESSION:zlib \
+	   +OPENSSL_ENGINE_BUILTIN_AFALG:kmod-crypto-user \
+	   +OPENSSL_ENGINE_BUILTIN_DEVCRYPTO:kmod-cryptodev \
+	   +OPENSSL_ENGINE_BUILTIN_PADLOCK:kmod-crypto-hw-padlock
   TITLE+= (libraries)
   ABI_VERSION:=1.1
   MENU:=1
@@ -134,7 +140,7 @@  define Package/libopenssl-afalg
   SUBMENU:=SSL
   TITLE:=AFALG hardware acceleration engine
   DEPENDS:=libopenssl @OPENSSL_ENGINE @KERNEL_AIO @!LINUX_3_18 +kmod-crypto-user \
-	   +libopenssl-conf
+	   +libopenssl-conf @!OPENSSL_ENGINE_BUILTIN
 endef
 
 define Package/libopenssl-afalg/description
@@ -145,12 +151,28 @@  See https://www.openssl.org/docs/man1.1.1/man5/config.html#Engine-Configuration-
 The engine_id is "afalg"
 endef
 
+define Package/libopenssl-devcrypto
+  $(call Package/openssl/Default)
+  SUBMENU:=SSL
+  TITLE:=/dev/crypto hardware acceleration engine
+  DEPENDS:=libopenssl @OPENSSL_ENGINE +kmod-cryptodev +libopenssl-conf \
+	   @!OPENSSL_ENGINE_BUILTIN
+endef
+
+define Package/libopenssl-devcrypto/description
+This package adds an engine that enables hardware acceleration
+through the /dev/crypto kernel interface.
+To use it, you need to configure the engine in /etc/ssl/openssl.cnf
+See https://www.openssl.org/docs/man1.1.1/man5/config.html#Engine-Configuration-Module
+The engine_id is "devcrypto"
+endef
+
 define Package/libopenssl-padlock
   $(call Package/openssl/Default)
   SUBMENU:=SSL
   TITLE:=VIA Padlock hardware acceleration engine
   DEPENDS:=libopenssl @OPENSSL_ENGINE @TARGET_x86 +kmod-crypto-hw-padlock \
-	   +libopenssl-conf
+	   +libopenssl-conf @!OPENSSL_ENGINE_BUILTIN
 endef
 
 define Package/libopenssl-padlock/description
@@ -241,14 +263,27 @@  else
 endif
 
 ifdef CONFIG_OPENSSL_ENGINE
-  ifdef CONFIG_OPENSSL_ENGINE_CRYPTO
-    OPENSSL_OPTIONS += enable-devcryptoeng
-  endif
-  ifndef CONFIG_PACKAGE_libopenssl-afalg
-    OPENSSL_OPTIONS += no-afalgeng
-  endif
-  ifndef CONFIG_PACKAGE_libopenssl-padlock
-    OPENSSL_OPTIONS += no-hw-padlock
+  ifdef CONFIG_OPENSSL_ENGINE_BUILTIN
+    OPENSSL_OPTIONS += disable-dynamic-engine
+    ifndef CONFIG_OPENSSL_ENGINE_BUILTIN_AFALG
+      OPENSSL_OPTIONS += no-afalgeng
+    endif
+    ifdef CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO
+      OPENSSL_OPTIONS += enable-devcryptoeng
+    endif
+    ifndef CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK
+      OPENSSL_OPTIONS += no-hw-padlock
+    endif
+  else
+    ifdef CONFIG_PACKAGE_libopenssl-devcrypto
+      OPENSSL_OPTIONS += enable-devcryptoeng
+    endif
+    ifndef CONFIG_PACKAGE_libopenssl-afalg
+      OPENSSL_OPTIONS += no-afalgeng
+    endif
+    ifndef CONFIG_PACKAGE_libopenssl-padlock
+      OPENSSL_OPTIONS += no-hw-padlock
+    endif
   endif
 else
   OPENSSL_OPTIONS += no-engine
@@ -364,6 +399,11 @@  define Package/libopenssl-afalg/install
 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/$(ENGINES_DIR)/afalg.so $(1)/usr/lib/$(ENGINES_DIR)
 endef
 
+define Package/libopenssl-devcrypto/install
+	$(INSTALL_DIR) $(1)/usr/lib/$(ENGINES_DIR)
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/$(ENGINES_DIR)/devcrypto.so $(1)/usr/lib/$(ENGINES_DIR)
+endef
+
 define Package/libopenssl-padlock/install
 	$(INSTALL_DIR) $(1)/usr/lib/$(ENGINES_DIR)
 	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/lib/$(ENGINES_DIR)/*padlock.so $(1)/usr/lib/$(ENGINES_DIR)
@@ -372,5 +412,6 @@  endef
 $(eval $(call BuildPackage,libopenssl))
 $(eval $(call BuildPackage,libopenssl-conf))
 $(eval $(call BuildPackage,libopenssl-afalg))
+$(eval $(call BuildPackage,libopenssl-devcrypto))
 $(eval $(call BuildPackage,libopenssl-padlock))
 $(eval $(call BuildPackage,openssl-util))
diff --git a/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch b/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch
new file mode 100644
index 0000000000..9ea3aef6ec
--- /dev/null
+++ b/package/libs/openssl/patches/400-eng_devcrypto-save-ioctl-if-EVP_MD_.FLAG_ONESHOT.patch
@@ -0,0 +1,60 @@ 
+From c50879688edc862213b19ae9993a4ac037af4781 Mon Sep 17 00:00:00 2001
+From: Eneas U de Queiroz <cote2004-github@yahoo.com>
+Date: Mon, 5 Nov 2018 15:54:17 -0200
+Subject: [PATCH 1/4] eng_devcrypto: save ioctl if EVP_MD_..FLAG_ONESHOT
+
+Since each ioctl causes a context switch, slowing things down, if
+EVP_MD_CTX_FLAG_ONESHOT is set, then:
+ - call the ioctl in digest_update, saving the result; and
+ - just copy the result in digest_final, instead of using another ioctl.
+
+Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
+
+Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
+Reviewed-by: Richard Levitte <levitte@openssl.org>
+(Merged from https://github.com/openssl/openssl/pull/7585)
+
+diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c
+index 11ec4393e7..f96cba70d7 100644
+--- a/crypto/engine/eng_devcrypto.c
++++ b/crypto/engine/eng_devcrypto.c
+@@ -460,6 +460,7 @@ struct digest_ctx {
+     struct session_op sess;
+     /* This signals that the init function was called, not that it succeeded. */
+     int init_called;
++    unsigned char digest_res[HASH_MAX_LEN];
+ };
+ 
+ static const struct digest_data_st {
+@@ -562,12 +563,15 @@ static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
+     if (digest_ctx == NULL)
+         return 0;
+ 
+-    if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) < 0) {
+-        SYSerr(SYS_F_IOCTL, errno);
+-        return 0;
++    if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
++        if (digest_op(digest_ctx, data, count, digest_ctx->digest_res, 0) >= 0)
++            return 1;
++    } else if (digest_op(digest_ctx, data, count, NULL, COP_FLAG_UPDATE) >= 0) {
++        return 1;
+     }
+ 
+-    return 1;
++    SYSerr(SYS_F_IOCTL, errno);
++    return 0;
+ }
+ 
+ static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
+@@ -577,7 +581,10 @@ static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
+ 
+     if (md == NULL || digest_ctx == NULL)
+         return 0;
+-    if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
++
++    if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT)) {
++        memcpy(md, digest_ctx->digest_res, EVP_MD_CTX_size(ctx));
++    } else if (digest_op(digest_ctx, NULL, 0, md, COP_FLAG_FINAL) < 0) {
+         SYSerr(SYS_F_IOCTL, errno);
+         return 0;
+     }
diff --git a/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch
new file mode 100644
index 0000000000..bc716a92e2
--- /dev/null
+++ b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch
@@ -0,0 +1,569 @@ 
+From f9e4bf71b6ecff66a19a3594c870cd2f58e23af6 Mon Sep 17 00:00:00 2001
+From: Eneas U de Queiroz <cote2004-github@yahoo.com>
+Date: Sat, 3 Nov 2018 15:41:10 -0300
+Subject: [PATCH 2/4] eng_devcrypto: add configuration options
+
+USE_SOFTDRIVERS: whether to use software (not accelerated) drivers
+CIPHERS: list of ciphers to enable
+DIGESTS: list of digests to enable
+
+Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
+
+Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
+Reviewed-by: Richard Levitte <levitte@openssl.org>
+(Merged from https://github.com/openssl/openssl/pull/7585)
+
+diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c
+index f96cba70d7..0f0aee6b57 100644
+--- a/crypto/engine/eng_devcrypto.c
++++ b/crypto/engine/eng_devcrypto.c
+@@ -16,6 +16,7 @@
+ #include <unistd.h>
+ #include <assert.h>
+ 
++#include <openssl/conf.h>
+ #include <openssl/evp.h>
+ #include <openssl/err.h>
+ #include <openssl/engine.h>
+@@ -34,6 +35,30 @@
+  * saner...  why re-open /dev/crypto for every session?
+  */
+ static int cfd;
++#define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
++#define DEVCRYPTO_USE_SOFTWARE        1 /* allow software drivers */
++#define DEVCRYPTO_REJECT_SOFTWARE     2 /* only disallow confirmed software drivers */
++
++#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE
++static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
++
++/*
++ * cipher/digest status & acceleration definitions
++ * Make sure the defaults are set to 0
++ */
++struct driver_info_st {
++    enum devcrypto_status_t {
++        DEVCRYPTO_STATUS_UNUSABLE       = -1, /* session open failed */
++        DEVCRYPTO_STATUS_UNKNOWN        =  0, /* not tested yet */
++        DEVCRYPTO_STATUS_USABLE         =  1  /* algo can be used */
++    } status;
++
++    enum devcrypto_accelerated_t {
++        DEVCRYPTO_NOT_ACCELERATED       = -1, /* software implemented */
++        DEVCRYPTO_ACCELERATION_UNKNOWN  =  0, /* acceleration support unkown */
++        DEVCRYPTO_ACCELERATED           =  1  /* hardware accelerated */
++    } accelerated;
++};
+ 
+ static int clean_devcrypto_session(struct session_op *sess) {
+     if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
+@@ -117,13 +142,22 @@ static const struct cipher_data_st {
+ #endif
+ };
+ 
+-static size_t get_cipher_data_index(int nid)
++static size_t find_cipher_data_index(int nid)
+ {
+     size_t i;
+ 
+     for (i = 0; i < OSSL_NELEM(cipher_data); i++)
+         if (nid == cipher_data[i].nid)
+             return i;
++    return (size_t)-1;
++}
++
++static size_t get_cipher_data_index(int nid)
++{
++    size_t i = find_cipher_data_index(nid);
++
++    if (i != (size_t)-1)
++        return i;
+ 
+     /*
+      * Code further down must make sure that only NIDs in the table above
+@@ -332,19 +366,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
+ }
+ 
+ /*
+- * Keep a table of known nids and associated methods.
++ * Keep tables of known nids, associated methods, selected ciphers, and driver
++ * info.
+  * Note that known_cipher_nids[] isn't necessarily indexed the same way as
+- * cipher_data[] above, which known_cipher_methods[] is.
++ * cipher_data[] above, which the other tables are.
+  */
+ static int known_cipher_nids[OSSL_NELEM(cipher_data)];
+ static int known_cipher_nids_amount = -1; /* -1 indicates not yet initialised */
+ static EVP_CIPHER *known_cipher_methods[OSSL_NELEM(cipher_data)] = { NULL, };
++static int selected_ciphers[OSSL_NELEM(cipher_data)];
++static struct driver_info_st cipher_driver_info[OSSL_NELEM(cipher_data)];
++
++
++static int devcrypto_test_cipher(size_t cipher_data_index)
++{
++    return (cipher_driver_info[cipher_data_index].status == DEVCRYPTO_STATUS_USABLE
++            && selected_ciphers[cipher_data_index] == 1
++            && (cipher_driver_info[cipher_data_index].accelerated
++                    == DEVCRYPTO_ACCELERATED
++                || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
++                || (cipher_driver_info[cipher_data_index].accelerated
++                        != DEVCRYPTO_NOT_ACCELERATED
++                    && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
++}
+ 
+ static void prepare_cipher_methods(void)
+ {
+     size_t i;
+     struct session_op sess;
+     unsigned long cipher_mode;
++#ifdef CIOCGSESSINFO
++    struct session_info_op siop;
++#endif
++
++    memset(&cipher_driver_info, 0, sizeof(cipher_driver_info));
+ 
+     memset(&sess, 0, sizeof(sess));
+     sess.key = (void *)"01234567890123456789012345678901234567890123456789";
+@@ -352,15 +407,16 @@ static void prepare_cipher_methods(void)
+     for (i = 0, known_cipher_nids_amount = 0;
+          i < OSSL_NELEM(cipher_data); i++) {
+ 
++        selected_ciphers[i] = 1;
+         /*
+-         * Check that the algo is really availably by trying to open and close
+-         * a session.
++         * Check that the cipher is usable
+          */
+         sess.cipher = cipher_data[i].devcryptoid;
+         sess.keylen = cipher_data[i].keylen;
+-        if (ioctl(cfd, CIOCGSESSION, &sess) < 0
+-            || ioctl(cfd, CIOCFSESSION, &sess.ses) < 0)
++        if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
++            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+             continue;
++        }
+ 
+         cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
+ 
+@@ -386,15 +442,41 @@ static void prepare_cipher_methods(void)
+                                             cipher_cleanup)
+             || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
+                                                   sizeof(struct cipher_ctx))) {
++            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+             EVP_CIPHER_meth_free(known_cipher_methods[i]);
+             known_cipher_methods[i] = NULL;
+         } else {
++            cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
++#ifdef CIOCGSESSINFO
++            siop.ses = sess.ses;
++            if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
++                cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
++            else if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
++                cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
++            else
++                cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
++#endif /* CIOCGSESSINFO */
++        }
++        ioctl(cfd, CIOCFSESSION, &sess.ses);
++        if (devcrypto_test_cipher(i)) {
+             known_cipher_nids[known_cipher_nids_amount++] =
+                 cipher_data[i].nid;
+         }
+     }
+ }
+ 
++static void rebuild_known_cipher_nids(ENGINE *e)
++{
++    size_t i;
++
++    for (i = 0, known_cipher_nids_amount = 0; i < OSSL_NELEM(cipher_data); i++) {
++        if (devcrypto_test_cipher(i))
++            known_cipher_nids[known_cipher_nids_amount++] = cipher_data[i].nid;
++    }
++    ENGINE_unregister_ciphers(e);
++    ENGINE_register_ciphers(e);
++}
++
+ static const EVP_CIPHER *get_cipher_method(int nid)
+ {
+     size_t i = get_cipher_data_index(nid);
+@@ -437,6 +519,36 @@ static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+     return *cipher != NULL;
+ }
+ 
++static void devcrypto_select_all_ciphers(int *cipher_list)
++{
++    size_t i;
++
++    for (i = 0; i < OSSL_NELEM(cipher_data); i++)
++        cipher_list[i] = 1;
++}
++
++static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
++{
++    int *cipher_list = (int *)usr;
++    char *name;
++    const EVP_CIPHER *EVP;
++    size_t i;
++
++    if (len == 0)
++        return 1;
++    if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
++        return 0;
++    EVP = EVP_get_cipherbyname(name);
++    if (EVP == NULL)
++        fprintf(stderr, "devcrypto: unknown cipher %s\n", name);
++    else if ((i = find_cipher_data_index(EVP_CIPHER_nid(EVP))) != (size_t)-1)
++        cipher_list[i] = 1;
++    else
++        fprintf(stderr, "devcrypto: cipher %s not available\n", name);
++    OPENSSL_free(name);
++    return 1;
++}
++
+ /*
+  * We only support digests if the cryptodev implementation supports multiple
+  * data updates and session copying.  Otherwise, we would be forced to maintain
+@@ -492,13 +604,22 @@ static const struct digest_data_st {
+ #endif
+ };
+ 
+-static size_t get_digest_data_index(int nid)
++static size_t find_digest_data_index(int nid)
+ {
+     size_t i;
+ 
+     for (i = 0; i < OSSL_NELEM(digest_data); i++)
+         if (nid == digest_data[i].nid)
+             return i;
++    return (size_t)-1;
++}
++
++static size_t get_digest_data_index(int nid)
++{
++    size_t i = find_digest_data_index(nid);
++
++    if (i != (size_t)-1)
++        return i;
+ 
+     /*
+      * Code further down must make sure that only NIDs in the table above
+@@ -515,8 +636,8 @@ static const struct digest_data_st *get_digest_data(int nid)
+ }
+ 
+ /*
+- * Following are the four necessary functions to map OpenSSL functionality
+- * with cryptodev.
++ * Following are the five necessary functions to map OpenSSL functionality
++ * with cryptodev: init, update, final, cleanup, and copy.
+  */
+ 
+ static int digest_init(EVP_MD_CTX *ctx)
+@@ -628,52 +749,94 @@ static int digest_cleanup(EVP_MD_CTX *ctx)
+     return clean_devcrypto_session(&digest_ctx->sess);
+ }
+ 
+-static int devcrypto_test_digest(size_t digest_data_index)
+-{
+-    struct session_op sess1, sess2;
+-    struct cphash_op cphash;
+-    int ret=0;
+-
+-    memset(&sess1, 0, sizeof(sess1));
+-    memset(&sess2, 0, sizeof(sess2));
+-    sess1.mac = digest_data[digest_data_index].devcryptoid;
+-    if (ioctl(cfd, CIOCGSESSION, &sess1) < 0)
+-        return 0;
+-    /* Make sure the driver is capable of hash state copy */
+-    sess2.mac = sess1.mac;
+-    if (ioctl(cfd, CIOCGSESSION, &sess2) >= 0) {
+-        cphash.src_ses = sess1.ses;
+-        cphash.dst_ses = sess2.ses;
+-        if (ioctl(cfd, CIOCCPHASH, &cphash) >= 0)
+-            ret = 1;
+-        ioctl(cfd, CIOCFSESSION, &sess2.ses);
+-    }
+-    ioctl(cfd, CIOCFSESSION, &sess1.ses);
+-    return ret;
+-}
+-
+ /*
+- * Keep a table of known nids and associated methods.
++ * Keep tables of known nids, associated methods, selected digests, and
++ * driver info.
+  * Note that known_digest_nids[] isn't necessarily indexed the same way as
+- * digest_data[] above, which known_digest_methods[] is.
++ * digest_data[] above, which the other tables are.
+  */
+ static int known_digest_nids[OSSL_NELEM(digest_data)];
+ static int known_digest_nids_amount = -1; /* -1 indicates not yet initialised */
+ static EVP_MD *known_digest_methods[OSSL_NELEM(digest_data)] = { NULL, };
++static int selected_digests[OSSL_NELEM(digest_data)];
++static struct driver_info_st digest_driver_info[OSSL_NELEM(digest_data)];
++
++static int devcrypto_test_digest(size_t digest_data_index)
++{
++    return (digest_driver_info[digest_data_index].status == DEVCRYPTO_STATUS_USABLE
++            && selected_digests[digest_data_index] == 1
++            && (digest_driver_info[digest_data_index].accelerated
++                    == DEVCRYPTO_ACCELERATED
++                || use_softdrivers == DEVCRYPTO_USE_SOFTWARE
++                || (digest_driver_info[digest_data_index].accelerated
++                        != DEVCRYPTO_NOT_ACCELERATED
++                    && use_softdrivers == DEVCRYPTO_REJECT_SOFTWARE)));
++}
++
++static void rebuild_known_digest_nids(ENGINE *e)
++{
++    size_t i;
++
++    for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data); i++) {
++        if (devcrypto_test_digest(i))
++            known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
++    }
++    ENGINE_unregister_digests(e);
++    ENGINE_register_digests(e);
++}
+ 
+ static void prepare_digest_methods(void)
+ {
+     size_t i;
++    struct session_op sess1, sess2;
++#ifdef CIOCGSESSINFO
++    struct session_info_op siop;
++#endif
++    struct cphash_op cphash;
++
++    memset(&digest_driver_info, 0, sizeof(digest_driver_info));
++
++    memset(&sess1, 0, sizeof(sess1));
++    memset(&sess2, 0, sizeof(sess2));
+ 
+     for (i = 0, known_digest_nids_amount = 0; i < OSSL_NELEM(digest_data);
+          i++) {
+ 
++        selected_digests[i] = 1;
++
+         /*
+-         * Check that the algo is usable
++         * Check that the digest is usable
+          */
+-        if (!devcrypto_test_digest(i))
+-            continue;
++        sess1.mac = digest_data[i].devcryptoid;
++        sess2.ses = 0;
++        if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            goto finish;
++        }
+ 
++#ifdef CIOCGSESSINFO
++        /* gather hardware acceleration info from the driver */
++        siop.ses = sess1.ses;
++        if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
++            digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
++        else if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
++            digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
++        else
++            digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
++#endif
++
++        /* digest must be capable of hash state copy */
++        sess2.mac = sess1.mac;
++        if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            goto finish;
++        }
++        cphash.src_ses = sess1.ses;
++        cphash.dst_ses = sess2.ses;
++        if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            goto finish;
++        }
+         if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
+                                                        NID_undef)) == NULL
+             || !EVP_MD_meth_set_input_blocksize(known_digest_methods[i],
+@@ -687,11 +850,18 @@ static void prepare_digest_methods(void)
+             || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
+             || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
+                                              sizeof(struct digest_ctx))) {
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
+             EVP_MD_meth_free(known_digest_methods[i]);
+             known_digest_methods[i] = NULL;
+-        } else {
+-            known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
++            goto finish;
+         }
++        digest_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
++finish:
++        ioctl(cfd, CIOCFSESSION, &sess1.ses);
++        if (sess2.ses != 0)
++            ioctl(cfd, CIOCFSESSION, &sess2.ses);
++        if (devcrypto_test_digest(i))
++            known_digest_nids[known_digest_nids_amount++] = digest_data[i].nid;
+     }
+ }
+ 
+@@ -737,8 +907,154 @@ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
+     return *digest != NULL;
+ }
+ 
++static void devcrypto_select_all_digests(int *digest_list)
++{
++    size_t i;
++
++    for (i = 0; i < OSSL_NELEM(digest_data); i++)
++        digest_list[i] = 1;
++}
++
++static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
++{
++    int *digest_list = (int *)usr;
++    char *name;
++    const EVP_MD *EVP;
++    size_t i;
++
++    if (len == 0)
++        return 1;
++    if (usr == NULL || (name = OPENSSL_strndup(str, len)) == NULL)
++        return 0;
++    EVP = EVP_get_digestbyname(name);
++    if (EVP == NULL)
++        fprintf(stderr, "devcrypto: unknown digest %s\n", name);
++    else if ((i = find_digest_data_index(EVP_MD_type(EVP))) != (size_t)-1)
++        digest_list[i] = 1;
++    else
++        fprintf(stderr, "devcrypto: digest %s not available\n", name);
++    OPENSSL_free(name);
++    return 1;
++}
++
++#endif
++
++/******************************************************************************
++ *
++ * CONTROL COMMANDS
++ *
++ *****/
++
++#define DEVCRYPTO_CMD_USE_SOFTDRIVERS ENGINE_CMD_BASE
++#define DEVCRYPTO_CMD_CIPHERS (ENGINE_CMD_BASE + 1)
++#define DEVCRYPTO_CMD_DIGESTS (ENGINE_CMD_BASE + 2)
++#define DEVCRYPTO_CMD_DUMP_INFO (ENGINE_CMD_BASE + 3)
++
++/* Helper macros for CPP string composition */
++#ifndef OPENSSL_MSTR
++# define OPENSSL_MSTR_HELPER(x) #x
++# define OPENSSL_MSTR(x) OPENSSL_MSTR_HELPER(x)
++#endif
++
++static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
++#ifdef CIOCGSESSINFO
++   {DEVCRYPTO_CMD_USE_SOFTDRIVERS,
++    "USE_SOFTDRIVERS",
++    "specifies whether to use software (not accelerated) drivers ("
++        OPENSSL_MSTR(DEVCRYPTO_REQUIRE_ACCELERATED) "=use only accelerated drivers, "
++        OPENSSL_MSTR(DEVCRYPTO_USE_SOFTWARE) "=allow all drivers, "
++        OPENSSL_MSTR(DEVCRYPTO_REJECT_SOFTWARE)
++        "=use if acceleration can't be determined) [default="
++        OPENSSL_MSTR(DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS) "]",
++    ENGINE_CMD_FLAG_NUMERIC},
++#endif
++
++   {DEVCRYPTO_CMD_CIPHERS,
++    "CIPHERS",
++    "either ALL, NONE, or a comma-separated list of ciphers to enable [default=ALL]",
++    ENGINE_CMD_FLAG_STRING},
++
++#ifdef IMPLEMENT_DIGEST
++   {DEVCRYPTO_CMD_DIGESTS,
++    "DIGESTS",
++    "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
++    ENGINE_CMD_FLAG_STRING},
+ #endif
+ 
++   {0, NULL, NULL, 0}
++};
++
++static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
++{
++    int *new_list;
++    switch (cmd) {
++#ifdef CIOCGSESSINFO
++    case DEVCRYPTO_CMD_USE_SOFTDRIVERS:
++        switch (i) {
++        case DEVCRYPTO_REQUIRE_ACCELERATED:
++        case DEVCRYPTO_USE_SOFTWARE:
++        case DEVCRYPTO_REJECT_SOFTWARE:
++            break;
++        default:
++            fprintf(stderr, "devcrypto: invalid value (%ld) for USE_SOFTDRIVERS\n", i);
++            return 0;
++        }
++        if (use_softdrivers == i)
++            return 1;
++        use_softdrivers = i;
++#ifdef IMPLEMENT_DIGEST
++        rebuild_known_digest_nids(e);
++#endif
++        rebuild_known_cipher_nids(e);
++        return 1;
++#endif /* CIOCGSESSINFO */
++
++    case DEVCRYPTO_CMD_CIPHERS:
++        if (p == NULL)
++            return 1;
++        if (strcasecmp((const char *)p, "ALL") == 0) {
++            devcrypto_select_all_ciphers(selected_ciphers);
++        } else if (strcasecmp((const char*)p, "NONE") == 0) {
++            memset(selected_ciphers, 0, sizeof(selected_ciphers));
++        } else {
++            new_list=OPENSSL_zalloc(sizeof(selected_ciphers));
++            if (!CONF_parse_list(p, ',', 1, cryptodev_select_cipher_cb, new_list)) {
++                OPENSSL_free(new_list);
++                return 0;
++            }
++            memcpy(selected_ciphers, new_list, sizeof(selected_ciphers));
++            OPENSSL_free(new_list);
++        }
++        rebuild_known_cipher_nids(e);
++        return 1;
++
++#ifdef IMPLEMENT_DIGEST
++    case DEVCRYPTO_CMD_DIGESTS:
++        if (p == NULL)
++            return 1;
++        if (strcasecmp((const char *)p, "ALL") == 0) {
++            devcrypto_select_all_digests(selected_digests);
++        } else if (strcasecmp((const char*)p, "NONE") == 0) {
++            memset(selected_digests, 0, sizeof(selected_digests));
++        } else {
++            new_list=OPENSSL_zalloc(sizeof(selected_digests));
++            if (!CONF_parse_list(p, ',', 1, cryptodev_select_digest_cb, new_list)) {
++                OPENSSL_free(new_list);
++                return 0;
++            }
++            memcpy(selected_digests, new_list, sizeof(selected_digests));
++            OPENSSL_free(new_list);
++        }
++        rebuild_known_digest_nids(e);
++        return 1;
++#endif /* IMPLEMENT_DIGEST */
++
++    default:
++        break;
++    }
++    return 0;
++}
++
+ /******************************************************************************
+  *
+  * LOAD / UNLOAD
+@@ -788,6 +1104,8 @@ void engine_load_devcrypto_int()
+ 
+     if (!ENGINE_set_id(e, "devcrypto")
+         || !ENGINE_set_name(e, "/dev/crypto engine")
++        || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
++        || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)
+ 
+ /*
+  * Asymmetric ciphers aren't well supported with /dev/crypto.  Among the BSD
diff --git a/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch b/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch
new file mode 100644
index 0000000000..4e3b8597bb
--- /dev/null
+++ b/package/libs/openssl/patches/420-eng_devcrypto-add-command-to-dump-driver-info.patch
@@ -0,0 +1,275 @@ 
+From 8cc22636b95de928f5abaebd0d19e2f040870953 Mon Sep 17 00:00:00 2001
+From: Eneas U de Queiroz <cote2004-github@yahoo.com>
+Date: Tue, 6 Nov 2018 22:54:07 -0200
+Subject: [PATCH 3/4] eng_devcrypto: add command to dump driver info
+
+This is useful to determine the kernel driver running each algorithm.
+
+Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
+
+Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>
+Reviewed-by: Richard Levitte <levitte@openssl.org>
+(Merged from https://github.com/openssl/openssl/pull/7585)
+
+diff --git a/crypto/engine/eng_devcrypto.c b/crypto/engine/eng_devcrypto.c
+index 0f0aee6b57..44e60cbc7b 100644
+--- a/crypto/engine/eng_devcrypto.c
++++ b/crypto/engine/eng_devcrypto.c
+@@ -48,16 +48,20 @@ static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
+  */
+ struct driver_info_st {
+     enum devcrypto_status_t {
+-        DEVCRYPTO_STATUS_UNUSABLE       = -1, /* session open failed */
+-        DEVCRYPTO_STATUS_UNKNOWN        =  0, /* not tested yet */
+-        DEVCRYPTO_STATUS_USABLE         =  1  /* algo can be used */
++        DEVCRYPTO_STATUS_FAILURE         = -3, /* unusable for other reason */
++        DEVCRYPTO_STATUS_NO_CIOCCPHASH   = -2, /* hash state copy not supported */
++        DEVCRYPTO_STATUS_NO_CIOCGSESSION = -1, /* session open failed */
++        DEVCRYPTO_STATUS_UNKNOWN         =  0, /* not tested yet */
++        DEVCRYPTO_STATUS_USABLE          =  1  /* algo can be used */
+     } status;
+ 
+     enum devcrypto_accelerated_t {
+-        DEVCRYPTO_NOT_ACCELERATED       = -1, /* software implemented */
+-        DEVCRYPTO_ACCELERATION_UNKNOWN  =  0, /* acceleration support unkown */
+-        DEVCRYPTO_ACCELERATED           =  1  /* hardware accelerated */
++        DEVCRYPTO_NOT_ACCELERATED        = -1, /* software implemented */
++        DEVCRYPTO_ACCELERATION_UNKNOWN   =  0, /* acceleration support unkown */
++        DEVCRYPTO_ACCELERATED            =  1  /* hardware accelerated */
+     } accelerated;
++
++    char *driver_name;
+ };
+ 
+ static int clean_devcrypto_session(struct session_op *sess) {
+@@ -414,7 +418,7 @@ static void prepare_cipher_methods(void)
+         sess.cipher = cipher_data[i].devcryptoid;
+         sess.keylen = cipher_data[i].keylen;
+         if (ioctl(cfd, CIOCGSESSION, &sess) < 0) {
+-            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            cipher_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
+             continue;
+         }
+ 
+@@ -442,19 +446,24 @@ static void prepare_cipher_methods(void)
+                                             cipher_cleanup)
+             || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
+                                                   sizeof(struct cipher_ctx))) {
+-            cipher_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            cipher_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
+             EVP_CIPHER_meth_free(known_cipher_methods[i]);
+             known_cipher_methods[i] = NULL;
+         } else {
+             cipher_driver_info[i].status = DEVCRYPTO_STATUS_USABLE;
+ #ifdef CIOCGSESSINFO
+             siop.ses = sess.ses;
+-            if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
++            if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
+                 cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
+-            else if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
+-                cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
+-            else
+-                cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
++            } else {
++                cipher_driver_info[i].driver_name =
++                    OPENSSL_strndup(siop.cipher_info.cra_driver_name,
++                                    CRYPTODEV_MAX_ALG_NAME);
++                if (!(siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY))
++                    cipher_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
++                else
++                    cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
++            }
+ #endif /* CIOCGSESSINFO */
+         }
+         ioctl(cfd, CIOCFSESSION, &sess.ses);
+@@ -504,8 +513,11 @@ static void destroy_all_cipher_methods(void)
+ {
+     size_t i;
+ 
+-    for (i = 0; i < OSSL_NELEM(cipher_data); i++)
++    for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
+         destroy_cipher_method(cipher_data[i].nid);
++        OPENSSL_free(cipher_driver_info[i].driver_name);
++        cipher_driver_info[i].driver_name = NULL;
++    }
+ }
+ 
+ static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
+@@ -549,6 +561,40 @@ static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
+     return 1;
+ }
+ 
++static void dump_cipher_info(void)
++{
++    size_t i;
++    const char *name;
++
++    fprintf (stderr, "Information about ciphers supported by the /dev/crypto"
++             " engine:\n");
++#ifndef CIOCGSESSINFO
++    fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
++#endif
++    for (i = 0; i < OSSL_NELEM(cipher_data); i++) {
++        name = OBJ_nid2sn(cipher_data[i].nid);
++        fprintf (stderr, "Cipher %s, NID=%d, /dev/crypto info: id=%d, ",
++                 name ? name : "unknown", cipher_data[i].nid,
++                 cipher_data[i].devcryptoid);
++        if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION ) {
++            fprintf (stderr, "CIOCGSESSION (session open call) failed\n");
++            continue;
++        }
++        fprintf (stderr, "driver=%s ", cipher_driver_info[i].driver_name ?
++                 cipher_driver_info[i].driver_name : "unknown");
++        if (cipher_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
++            fprintf(stderr, "(hw accelerated)");
++        else if (cipher_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
++            fprintf(stderr, "(software)");
++        else
++            fprintf(stderr, "(acceleration status unknown)");
++        if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
++            fprintf (stderr, ". Cipher setup failed");
++        fprintf(stderr, "\n");
++    }
++    fprintf(stderr, "\n");
++}
++
+ /*
+  * We only support digests if the cryptodev implementation supports multiple
+  * data updates and session copying.  Otherwise, we would be forced to maintain
+@@ -810,31 +856,36 @@ static void prepare_digest_methods(void)
+         sess1.mac = digest_data[i].devcryptoid;
+         sess2.ses = 0;
+         if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
+-            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCGSESSION;
+             goto finish;
+         }
+ 
+ #ifdef CIOCGSESSINFO
+         /* gather hardware acceleration info from the driver */
+         siop.ses = sess1.ses;
+-        if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0)
++        if (ioctl(cfd, CIOCGSESSINFO, &siop) < 0) {
+             digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
+-        else if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
+-            digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
+-        else
+-            digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
++        } else {
++            digest_driver_info[i].driver_name =
++                OPENSSL_strndup(siop.hash_info.cra_driver_name,
++                                CRYPTODEV_MAX_ALG_NAME);
++            if (siop.flags & SIOP_FLAG_KERNEL_DRIVER_ONLY)
++                digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATED;
++            else
++                digest_driver_info[i].accelerated = DEVCRYPTO_NOT_ACCELERATED;
++        }
+ #endif
+ 
+         /* digest must be capable of hash state copy */
+         sess2.mac = sess1.mac;
+         if (ioctl(cfd, CIOCGSESSION, &sess2) < 0) {
+-            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
+             goto finish;
+         }
+         cphash.src_ses = sess1.ses;
+         cphash.dst_ses = sess2.ses;
+         if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
+-            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_NO_CIOCCPHASH;
+             goto finish;
+         }
+         if ((known_digest_methods[i] = EVP_MD_meth_new(digest_data[i].nid,
+@@ -850,7 +901,7 @@ static void prepare_digest_methods(void)
+             || !EVP_MD_meth_set_cleanup(known_digest_methods[i], digest_cleanup)
+             || !EVP_MD_meth_set_app_datasize(known_digest_methods[i],
+                                              sizeof(struct digest_ctx))) {
+-            digest_driver_info[i].status = DEVCRYPTO_STATUS_UNUSABLE;
++            digest_driver_info[i].status = DEVCRYPTO_STATUS_FAILURE;
+             EVP_MD_meth_free(known_digest_methods[i]);
+             known_digest_methods[i] = NULL;
+             goto finish;
+@@ -892,8 +943,11 @@ static void destroy_all_digest_methods(void)
+ {
+     size_t i;
+ 
+-    for (i = 0; i < OSSL_NELEM(digest_data); i++)
++    for (i = 0; i < OSSL_NELEM(digest_data); i++) {
+         destroy_digest_method(digest_data[i].nid);
++        OPENSSL_free(digest_driver_info[i].driver_name);
++        digest_driver_info[i].driver_name = NULL;
++    }
+ }
+ 
+ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
+@@ -937,6 +991,43 @@ static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
+     return 1;
+ }
+ 
++static void dump_digest_info(void)
++{
++    size_t i;
++    const char *name;
++
++    fprintf (stderr, "Information about digests supported by the /dev/crypto"
++             " engine:\n");
++#ifndef CIOCGSESSINFO
++    fprintf(stderr, "CIOCGSESSINFO (session info call) unavailable\n");
++#endif
++
++    for (i = 0; i < OSSL_NELEM(digest_data); i++) {
++        name = OBJ_nid2sn(digest_data[i].nid);
++        fprintf (stderr, "Digest %s, NID=%d, /dev/crypto info: id=%d, driver=%s",
++                 name ? name : "unknown", digest_data[i].nid,
++                 digest_data[i].devcryptoid,
++                 digest_driver_info[i].driver_name ? digest_driver_info[i].driver_name : "unknown");
++        if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCGSESSION) {
++            fprintf (stderr, ". CIOCGSESSION (session open) failed\n");
++            continue;
++        }
++        if (digest_driver_info[i].accelerated == DEVCRYPTO_ACCELERATED)
++            fprintf(stderr, " (hw accelerated)");
++        else if (digest_driver_info[i].accelerated == DEVCRYPTO_NOT_ACCELERATED)
++            fprintf(stderr, " (software)");
++        else
++            fprintf(stderr, " (acceleration status unknown)");
++        if (cipher_driver_info[i].status == DEVCRYPTO_STATUS_FAILURE)
++            fprintf (stderr, ". Cipher setup failed\n");
++        else if (digest_driver_info[i].status == DEVCRYPTO_STATUS_NO_CIOCCPHASH)
++            fprintf(stderr, ", CIOCCPHASH failed\n");
++        else
++            fprintf(stderr, ", CIOCCPHASH capable\n");
++    }
++    fprintf(stderr, "\n");
++}
++
+ #endif
+ 
+ /******************************************************************************
+@@ -981,6 +1072,11 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
+     ENGINE_CMD_FLAG_STRING},
+ #endif
+ 
++   {DEVCRYPTO_CMD_DUMP_INFO,
++    "DUMP_INFO",
++    "dump info about each algorithm to stderr; use 'openssl engine -pre DUMP_INFO devcrypto'",
++    ENGINE_CMD_FLAG_NO_INPUT},
++
+    {0, NULL, NULL, 0}
+ };
+ 
+@@ -1049,6 +1145,13 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+         return 1;
+ #endif /* IMPLEMENT_DIGEST */
+ 
++    case DEVCRYPTO_CMD_DUMP_INFO:
++        dump_cipher_info();
++#ifdef IMPLEMENT_DIGEST
++        dump_digest_info();
++#endif
++        return 1;
++
+     default:
+         break;
+     }
diff --git a/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch b/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch
new file mode 100644
index 0000000000..fa5e48f36a
--- /dev/null
+++ b/package/libs/openssl/patches/430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch
@@ -0,0 +1,336 @@ 
+From 9e0ca5fff3fa439fc36fa5374671b91dc5657b6a Mon Sep 17 00:00:00 2001
+From: Eneas U de Queiroz <cote2004-github@yahoo.com>
+Date: Tue, 6 Nov 2018 10:57:03 -0200
+Subject: [PATCH 4/4] e_devcrypto: make the /dev/crypto engine dynamic
+
+Engine has been moved from crypto/engine/eng_devcrypto.c to
+engines/e_devcrypto.c.
+
+Signed-off-by: Eneas U de Queiroz <cote2004-github@yahoo.com>
+
+diff --git a/crypto/engine/build.info b/crypto/engine/build.info
+index e00802a3fd..47fe948966 100644
+--- a/crypto/engine/build.info
++++ b/crypto/engine/build.info
+@@ -6,6 +6,3 @@ SOURCE[../../libcrypto]=\
+         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_rdrand.c
+-IF[{- !$disabled{devcryptoeng} -}]
+-  SOURCE[../../libcrypto]=eng_devcrypto.c
+-ENDIF
+diff --git a/crypto/init.c b/crypto/init.c
+index 209d1a483d..02c609535f 100644
+--- a/crypto/init.c
++++ b/crypto/init.c
+@@ -290,18 +290,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl)
+     engine_load_openssl_int();
+     return 1;
+ }
+-# ifndef OPENSSL_NO_DEVCRYPTOENG
+-static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
+-DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
+-{
+-#  ifdef OPENSSL_INIT_DEBUG
+-    fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
+-                    "engine_load_devcrypto_int()\n");
+-#  endif
+-    engine_load_devcrypto_int();
+-    return 1;
+-}
+-# endif
+ 
+ # ifndef OPENSSL_NO_RDRAND
+ static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
+@@ -326,6 +314,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic)
+     return 1;
+ }
+ # ifndef OPENSSL_NO_STATIC_ENGINE
++#  ifndef OPENSSL_NO_DEVCRYPTOENG
++static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
++DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
++{
++#   ifdef OPENSSL_INIT_DEBUG
++    fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
++                    "engine_load_devcrypto_int()\n");
++#   endif
++    engine_load_devcrypto_int();
++    return 1;
++}
++#  endif
+ #  if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
+ static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT;
+ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
+@@ -645,11 +645,6 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
+     if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
+             && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
+         return 0;
+-# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG)
+-    if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
+-            && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
+-        return 0;
+-# endif
+ # ifndef OPENSSL_NO_RDRAND
+     if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
+             && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
+@@ -659,6 +654,11 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
+             && !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
+         return 0;
+ # ifndef OPENSSL_NO_STATIC_ENGINE
++#  ifndef OPENSSL_NO_DEVCRYPTOENG
++    if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
++            && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
++        return 0;
++#  endif
+ #  if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
+     if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
+             && !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
+diff --git a/engines/build.info b/engines/build.info
+index df173ea69d..dc0cbeb0a3 100644
+--- a/engines/build.info
++++ b/engines/build.info
+@@ -10,6 +10,9 @@ IF[{- !$disabled{"engine"} -}]
+     IF[{- !$disabled{afalgeng} -}]
+       SOURCE[../libcrypto]=e_afalg.c
+     ENDIF
++    IF[{- !$disabled{"devcryptoeng"} -}]
++      SOURCE[../libcrypto]=e_devcrypto.c
++    ENDIF
+   ELSE
+     ENGINES=padlock
+     SOURCE[padlock]=e_padlock.c {- $target{padlock_asm_src} -}
+@@ -27,6 +30,12 @@ IF[{- !$disabled{"engine"} -}]
+       DEPEND[afalg]=../libcrypto
+       INCLUDE[afalg]= ../include
+     ENDIF
++    IF[{- !$disabled{"devcryptoeng"} -}]
++      ENGINES=devcrypto
++      SOURCE[devcrypto]=e_devcrypto.c
++      DEPEND[devcrypto]=../libcrypto
++      INCLUDE[devcrypto]=../include
++    ENDIF
+ 
+     ENGINES_NO_INST=ossltest dasync
+     SOURCE[dasync]=e_dasync.c
+diff --git a/crypto/engine/eng_devcrypto.c b/engines/e_devcrypto.c
+similarity index 95%
+rename from crypto/engine/eng_devcrypto.c
+rename to engines/e_devcrypto.c
+index 44e60cbc7b..9af2ce174a 100644
+--- a/crypto/engine/eng_devcrypto.c
++++ b/engines/e_devcrypto.c
+@@ -7,7 +7,7 @@
+  * https://www.openssl.org/source/license.html
+  */
+ 
+-#include "e_os.h"
++#include "../e_os.h"
+ #include <string.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+@@ -23,24 +23,24 @@
+ #include <openssl/objects.h>
+ #include <crypto/cryptodev.h>
+ 
+-#include "internal/engine.h"
+-
+ #ifdef CRYPTO_ALGORITHM_MIN
+ # define CHECK_BSD_STYLE_MACROS
+ #endif
+ 
++#define engine_devcrypto_id "devcrypto"
++
+ /*
+  * ONE global file descriptor for all sessions.  This allows operations
+  * such as digest session data copying (see digest_copy()), but is also
+  * saner...  why re-open /dev/crypto for every session?
+  */
+-static int cfd;
++static int cfd = -1;
+ #define DEVCRYPTO_REQUIRE_ACCELERATED 0 /* require confirmation of acceleration */
+ #define DEVCRYPTO_USE_SOFTWARE        1 /* allow software drivers */
+ #define DEVCRYPTO_REJECT_SOFTWARE     2 /* only disallow confirmed software drivers */
+ 
+-#define DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS DEVCRYPTO_REJECT_SOFTWARE
+-static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
++#define DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
++static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
+ 
+ /*
+  * cipher/digest status & acceleration definitions
+@@ -73,6 +73,10 @@ static int clean_devcrypto_session(struct session_op *sess) {
+     return 1;
+ }
+ 
++#ifdef OPENSSL_NO_DYNAMIC_ENGINE
++void engine_load_devcrypto_int(void);
++#endif
++
+ /******************************************************************************
+  *
+  * Ciphers
+@@ -1164,6 +1168,37 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+  *
+  *****/
+ 
++/*
++ * Opens /dev/crypto
++ */
++static int open_devcrypto(void)
++{
++    if (cfd >= 0)
++        return 1;
++
++    if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
++        fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
++        return 0;
++    }
++
++    return 1;
++}
++
++static int close_devcrypto(void)
++{
++    int ret;
++
++    if (cfd < 0)
++        return 1;
++    ret = close(cfd);
++    cfd = -1;
++    if (ret != 0) {
++        fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
++        return 0;
++    }
++    return 1;
++}
++
+ static int devcrypto_unload(ENGINE *e)
+ {
+     destroy_all_cipher_methods();
+@@ -1171,45 +1206,29 @@ static int devcrypto_unload(ENGINE *e)
+     destroy_all_digest_methods();
+ #endif
+ 
+-    close(cfd);
++    close_devcrypto();
+ 
+     return 1;
+ }
+-/*
+- * This engine is always built into libcrypto, so it doesn't offer any
+- * ability to be dynamically loadable.
+- */
+-void engine_load_devcrypto_int()
+-{
+-    ENGINE *e = NULL;
+ 
+-    if ((cfd = open("/dev/crypto", O_RDWR, 0)) < 0) {
+-        fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
+-        return;
+-    }
++static int bind_devcrypto(ENGINE *e) {
+ 
+-    if ((e = ENGINE_new()) == NULL
+-        || !ENGINE_set_destroy_function(e, devcrypto_unload)) {
+-        ENGINE_free(e);
+-        /*
+-         * We know that devcrypto_unload() won't be called when one of the
+-         * above two calls have failed, so we close cfd explicitly here to
+-         * avoid leaking resources.
+-         */
+-        close(cfd);
+-        return;
+-    }
++    if (!ENGINE_set_id(e, engine_devcrypto_id)
++        || !ENGINE_set_name(e, "/dev/crypto engine")
++        || !ENGINE_set_destroy_function(e, devcrypto_unload)
++        || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
++        || !ENGINE_set_ctrl_function(e, devcrypto_ctrl))
++        return 0;
+ 
+     prepare_cipher_methods();
+ #ifdef IMPLEMENT_DIGEST
+     prepare_digest_methods();
+ #endif
+ 
+-    if (!ENGINE_set_id(e, "devcrypto")
+-        || !ENGINE_set_name(e, "/dev/crypto engine")
+-        || !ENGINE_set_cmd_defns(e, devcrypto_cmds)
+-        || !ENGINE_set_ctrl_function(e, devcrypto_ctrl)
+-
++    return (ENGINE_set_ciphers(e, devcrypto_ciphers)
++#ifdef IMPLEMENT_DIGEST
++        && ENGINE_set_digests(e, devcrypto_digests)
++#endif
+ /*
+  * Asymmetric ciphers aren't well supported with /dev/crypto.  Among the BSD
+  * implementations, it seems to only exist in FreeBSD, and regarding the
+@@ -1232,23 +1251,36 @@ void engine_load_devcrypto_int()
+  */
+ #if 0
+ # ifndef OPENSSL_NO_RSA
+-        || !ENGINE_set_RSA(e, devcrypto_rsa)
++        && ENGINE_set_RSA(e, devcrypto_rsa)
+ # endif
+ # ifndef OPENSSL_NO_DSA
+-        || !ENGINE_set_DSA(e, devcrypto_dsa)
++        && ENGINE_set_DSA(e, devcrypto_dsa)
+ # endif
+ # ifndef OPENSSL_NO_DH
+-        || !ENGINE_set_DH(e, devcrypto_dh)
++        && ENGINE_set_DH(e, devcrypto_dh)
+ # endif
+ # ifndef OPENSSL_NO_EC
+-        || !ENGINE_set_EC(e, devcrypto_ec)
++        && ENGINE_set_EC(e, devcrypto_ec)
+ # endif
+ #endif
+-        || !ENGINE_set_ciphers(e, devcrypto_ciphers)
+-#ifdef IMPLEMENT_DIGEST
+-        || !ENGINE_set_digests(e, devcrypto_digests)
+-#endif
+-        ) {
++        );
++}
++
++#ifdef OPENSSL_NO_DYNAMIC_ENGINE
++/*
++ * In case this engine is built into libcrypto, then it doesn't offer any
++ * ability to be dynamically loadable.
++ */
++void engine_load_devcrypto_int(void)
++{
++    ENGINE *e = NULL;
++
++    if (!open_devcrypto())
++        return;
++
++    if ((e = ENGINE_new()) == NULL
++        || !bind_devcrypto(e)) {
++        close_devcrypto();
+         ENGINE_free(e);
+         return;
+     }
+@@ -1257,3 +1289,22 @@ void engine_load_devcrypto_int()
+     ENGINE_free(e);          /* Loose our local reference */
+     ERR_clear_error();
+ }
++
++#else
++
++static int bind_helper(ENGINE *e, const char *id)
++{
++    if ((id && (strcmp(id, engine_devcrypto_id) != 0))
++        || !open_devcrypto())
++        return 0;
++    if (!bind_devcrypto(e)) {
++        close_devcrypto();
++        return 0;
++    }
++    return 1;
++}
++
++IMPLEMENT_DYNAMIC_CHECK_FN()
++IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
++
++#endif