[OpenWrt-Devel] [PATCH v3] openssl: backport devcrypto changes from master
Rosen Penev
rosenp at gmail.com
Mon Feb 25 14:09:27 EST 2019
On Mon, Feb 25, 2019 at 10:01 AM Eneas U de Queiroz via openwrt-devel
<openwrt-devel at lists.openwrt.org> wrote:
>
> 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.
>
>
> ---------- Forwarded message ----------
> From: Eneas U de Queiroz <cote2004-github at yahoo.com>
> To: openwrt-devel at lists.openwrt.org
> Cc: Eneas U de Queiroz <cote2004-github at yahoo.com>
> Bcc:
> Date: Mon, 25 Feb 2019 15:00:58 -0300
> Subject: [PATCH v3] openssl: backport devcrypto changes from master
> The patches to the /dev/crypto engine were commited to openssl master,
> and will be in the next major version (3.0).
This version does not apply to master.
>
> 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 at 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:
> v3: remove PKG_BUILD_DEPENDS:=cryptodev-linux, as it has been properly
> added to DEPENDS now.
>
> v2: accommodate changes from openssl: fix devcrypto engine md blocksize
> increased PKG_RELEASE
>
> 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..a7dbbae2b1 100644
> --- a/package/libs/openssl/Makefile
> +++ b/package/libs/openssl/Makefile
> @@ -11,12 +11,11 @@ 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
>
> PKG_BUILD_PARALLEL:=0
> -PKG_BUILD_DEPENDS:=cryptodev-linux
>
> PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
> PKG_SOURCE_URL:= \
> @@ -32,7 +31,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 +91,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 +139,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 +150,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 +262,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 +398,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 +411,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 at 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 at yahoo.com>
> +
> +Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre at ncp-e.com>
> +Reviewed-by: Richard Levitte <levitte at 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 at 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 at yahoo.com>
> +
> +Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre at ncp-e.com>
> +Reviewed-by: Richard Levitte <levitte at 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 at 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 at yahoo.com>
> +
> +Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre at ncp-e.com>
> +Reviewed-by: Richard Levitte <levitte at 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 at 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 at 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
>
> _______________________________________________
> openwrt-devel mailing list
> openwrt-devel at lists.openwrt.org
> https://lists.openwrt.org/mailman/listinfo/openwrt-devel
_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel
More information about the openwrt-devel
mailing list