[RFC PATCH] openssl: make the patches QUILT-friendly
Rosen Penev
rosenp at gmail.com
Fri Mar 26 19:31:40 GMT 2021
On Fri, Mar 26, 2021 at 11:56 AM Eneas U de Queiroz
<cotequeiroz at gmail.com> wrote:
>
> The patches in this package are all made by git format-patches. If one
> were to run 'make package/openssl/{refresh,update}', then things will
> not work as expected, because quilt QUILT does not deal well with
> patches that rename files. For openssl, the problematic patch is
> 430-e_devcrypto-make-the-dev-crypto-engine-dynamic.patch.
>
> So, I've generated a new patch with 'git format-patch --no-renames', and
> then 'make package/openssl/{refresh,update}'.
NAK. This just bloats the patches for no good reason. It also makes it
harder to deal with upstream changes.
I know that you're fairly competent when dealing with this, but think
about it from a drive by contributor. Getting a setup to properly
refresh patches like these is difficult.
>
> Signed-off-by: Eneas U de Queiroz <cotequeiroz at gmail.com>
> ---
>
> While I really prefer to leave the git-formatted patches as they are, I
> know quilt is the preferred way of handling patches in OpenWRT, so I'm
> presenting this as RFC, so the core developers can decide.
>
> ldir has made a similar commit e27ef2da0d, and then reverted it right away
> in bbb9c1c2be, and I don't know why.
>
> neheb proposed a patch [1] that does the file renaming in Build/Prepare, so
> that it is easier to use quilt while refreshing patches after a package
> bump. It has an undesirable side-effect of not running the renaming
> portion at all when using QUILT, resulting in a build failure.
>
> Some packages in the packages feed are skipping build steps when running
> with QUILT, to speed up automatic refresh of patches, and I've been
> fixing them as I stumble upon some of the failures.
>
> At least to me, being able to quickly build with QUILT=1, without having
> to start from scratch and go through dependencies is an immensively
> useful feature that I would not trade for having tidier patches.
>
> For this package, one could rename the files in Build/Configure when
> compiling with QUILT without a problem. So, if desired, it could be
> done neheb's way instead.
>
> In my opinion, QUILT is not particularly useful for rebasing large
> changes, such as the engine patches here. So even if neheb's proposal
> has a nice intention, it is not appropriate for this package.
>
> If the motivation is just to run make package/openssl/{refresh,update},
> perhaps automatically to keep patches tidy, then this patch will
> suffice.
>
> Cheers,
>
> Eneas
>
> [1] https://patchwork.ozlabs.org/project/openwrt/patch/20210326092548.14019-1-rosenp@gmail.com/
>
> diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile
> index 7ab4c6ccd0..458b064f13 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:=k
> PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX)
> -PKG_RELEASE:=1
> +PKG_RELEASE:=2
> PKG_USE_MIPS16:=0
> ENGINES_DIR=engines-1.1
>
> diff --git a/package/libs/openssl/patches/100-Configure-afalg-support.patch b/package/libs/openssl/patches/100-Configure-afalg-support.patch
> index 98944103b5..2ae5938bdc 100644
> --- a/package/libs/openssl/patches/100-Configure-afalg-support.patch
> +++ b/package/libs/openssl/patches/100-Configure-afalg-support.patch
> @@ -1,4 +1,4 @@
> -From 559fbff13af9ce2fbc0b9bc5727a7323e1db6217 Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
> From: Eneas U de Queiroz <cote2004-github at yahoo.com>
> Date: Thu, 27 Sep 2018 08:29:21 -0300
> Subject: Do not use host kernel version to disable AFALG
> @@ -8,11 +8,9 @@ version to disable building the AFALG engine on openwrt targets.
>
> Signed-off-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
>
> -diff --git a/Configure b/Configure
> -index 5a699836f3..74d057c219 100755
> --- a/Configure
> +++ b/Configure
> -@@ -1545,7 +1545,9 @@ unless ($disabled{"crypto-mdebug-backtrace"})
> +@@ -1545,7 +1545,9 @@ unless ($disabled{"crypto-mdebug-backtra
>
> unless ($disabled{afalgeng}) {
> $config{afalgeng}="";
> diff --git a/package/libs/openssl/patches/110-openwrt_targets.patch b/package/libs/openssl/patches/110-openwrt_targets.patch
> index d0530b4661..50a9ebe2d6 100644
> --- a/package/libs/openssl/patches/110-openwrt_targets.patch
> +++ b/package/libs/openssl/patches/110-openwrt_targets.patch
> @@ -1,4 +1,4 @@
> -From 3d43acc6068f00dbfc0c9a06355e2c8f7d302d0f Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
> From: Eneas U de Queiroz <cote2004-github at yahoo.com>
> Date: Thu, 27 Sep 2018 08:30:24 -0300
> Subject: Add openwrt targets
> @@ -7,9 +7,6 @@ Targets are named: linux-$(CONFIG_ARCH)-openwrt
>
> Signed-off-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
>
> -diff --git a/Configurations/25-openwrt.conf b/Configurations/25-openwrt.conf
> -new file mode 100644
> -index 0000000000..86a86d31e4
> --- /dev/null
> +++ b/Configurations/25-openwrt.conf
> @@ -0,0 +1,48 @@
> diff --git a/package/libs/openssl/patches/120-strip-cflags-from-binary.patch b/package/libs/openssl/patches/120-strip-cflags-from-binary.patch
> index 7faec9ab88..90282706d1 100644
> --- a/package/libs/openssl/patches/120-strip-cflags-from-binary.patch
> +++ b/package/libs/openssl/patches/120-strip-cflags-from-binary.patch
> @@ -1,4 +1,4 @@
> -From 4ad8f2fe6bf3b91df7904fcbe960e5fdfca36336 Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
> From: Eneas U de Queiroz <cote2004-github at yahoo.com>
> Date: Thu, 27 Sep 2018 08:31:38 -0300
> Subject: Avoid exposing build directories
> @@ -8,11 +8,9 @@ OpenSSL_version(OPENSSL_CFLAGS), or running openssl version -a
>
> Signed-off-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
>
> -diff --git a/crypto/build.info b/crypto/build.info
> -index 2c619c62e8..893128345a 100644
> --- a/crypto/build.info
> +++ b/crypto/build.info
> -@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink.c ../ms/applink.c \
> +@@ -10,7 +10,7 @@ EXTRA= ../ms/uplink-x86.pl ../ms/uplink
> ppccpuid.pl pariscid.pl alphacpuid.pl arm64cpuid.pl armv4cpuid.pl
>
> DEPEND[cversion.o]=buildinf.h
> diff --git a/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch b/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch
> index 7f33cb9dae..baf8bca9e1 100644
> --- a/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch
> +++ b/package/libs/openssl/patches/130-dont-build-tests-fuzz.patch
> @@ -1,4 +1,4 @@
> -From ba2fe646f2d9104a18b066e43582154049e9ffcb Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
> From: Eneas U de Queiroz <cote2004-github at yahoo.com>
> Date: Thu, 27 Sep 2018 08:34:38 -0300
> Subject: Do not build tests and fuzz directories
> @@ -7,11 +7,9 @@ This shortens build time.
>
> Signed-off-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
>
> -diff --git a/Configure b/Configure
> -index 74d057c219..5813e9f8fe 100755
> --- a/Configure
> +++ b/Configure
> -@@ -318,7 +318,7 @@ my $auto_threads=1; # enable threads automatically? true by default
> +@@ -318,7 +318,7 @@ my $auto_threads=1; # enable threads
> my $default_ranlib;
>
> # Top level directories to build
> diff --git a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch
> index b293db28f7..58a9d7400c 100644
> --- a/package/libs/openssl/patches/140-allow-prefer-chacha20.patch
> +++ b/package/libs/openssl/patches/140-allow-prefer-chacha20.patch
> @@ -1,4 +1,4 @@
> -From 4f7ab2040bb71f03a8f8388911144559aa2a5b60 Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
> From: Eneas U de Queiroz <cote2004-github at yahoo.com>
> Date: Thu, 27 Sep 2018 08:44:39 -0300
> Subject: Add OPENSSL_PREFER_CHACHA_OVER_GCM option
> @@ -14,8 +14,6 @@ when the client has it on top of its ciphersuite preference.
>
> Signed-off-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
>
> -diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
> -index 6724ccf2d2..96d959427e 100644
> --- a/include/openssl/ssl.h
> +++ b/include/openssl/ssl.h
> @@ -173,9 +173,15 @@ extern "C" {
> @@ -37,11 +35,9 @@ index 6724ccf2d2..96d959427e 100644
> # else
> # define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
> "TLS_AES_128_GCM_SHA256"
> -diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
> -index 27a1b2ec68..7039811323 100644
> --- a/ssl/ssl_ciph.c
> +++ b/ssl/ssl_ciph.c
> -@@ -1467,11 +1467,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
> +@@ -1467,11 +1467,29 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
> ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
> &tail);
>
> @@ -71,7 +67,7 @@ index 27a1b2ec68..7039811323 100644
>
> /*
> * ...and generally, our preferred cipher is AES.
> -@@ -1527,7 +1545,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
> +@@ -1527,7 +1545,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_
> * Within each group, ciphers remain sorted by strength and previous
> * preference, i.e.,
> * 1) ECDHE > DHE
> 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
> index 84c68b16a2..ed8204c339 100644
> --- 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
> @@ -1,4 +1,4 @@
> -From f14345422747a495a52f9237a43b8be189f21912 Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 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: eng_devcrypto: save ioctl if EVP_MD_..FLAG_ONESHOT
> @@ -14,8 +14,6 @@ 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 a727c6f646..a2c9a966f7 100644
> --- a/crypto/engine/eng_devcrypto.c
> +++ b/crypto/engine/eng_devcrypto.c
> @@ -461,6 +461,7 @@ struct digest_ctx {
> @@ -26,7 +24,7 @@ index a727c6f646..a2c9a966f7 100644
> };
>
> static const struct digest_data_st {
> -@@ -564,12 +565,15 @@ static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
> +@@ -564,12 +565,15 @@ static int digest_update(EVP_MD_CTX *ctx
> if (digest_ctx == NULL)
> return 0;
>
> @@ -46,7 +44,7 @@ index a727c6f646..a2c9a966f7 100644
> }
>
> static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
> -@@ -579,7 +583,10 @@ static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
> +@@ -579,7 +583,10 @@ static int digest_final(EVP_MD_CTX *ctx,
>
> if (md == NULL || digest_ctx == NULL)
> 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
> index 8745364cf2..bad7a37256 100644
> --- a/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch
> +++ b/package/libs/openssl/patches/410-eng_devcrypto-add-configuration-options.patch
> @@ -1,4 +1,4 @@
> -From 1c2fabcdb34e436286b4a8760cfbfbff11ea551a Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 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: eng_devcrypto: add configuration options
> @@ -13,8 +13,6 @@ 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 a2c9a966f7..5ec38ca8f3 100644
> --- a/crypto/engine/eng_devcrypto.c
> +++ b/crypto/engine/eng_devcrypto.c
> @@ -16,6 +16,7 @@
> @@ -80,7 +78,7 @@ index a2c9a966f7..5ec38ca8f3 100644
>
> /*
> * Code further down must make sure that only NIDs in the table above
> -@@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
> +@@ -333,19 +367,40 @@ static int cipher_cleanup(EVP_CIPHER_CTX
> }
>
> /*
> @@ -186,7 +184,7 @@ index a2c9a966f7..5ec38ca8f3 100644
> static const EVP_CIPHER *get_cipher_method(int nid)
> {
> size_t i = get_cipher_data_index(nid);
> -@@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
> +@@ -438,6 +520,36 @@ static int devcrypto_ciphers(ENGINE *e,
> return *cipher != NULL;
> }
>
> @@ -247,7 +245,7 @@ index a2c9a966f7..5ec38ca8f3 100644
>
> /*
> * Code further down must make sure that only NIDs in the table above
> -@@ -516,8 +637,8 @@ static const struct digest_data_st *get_digest_data(int nid)
> +@@ -516,8 +637,8 @@ static const struct digest_data_st *get_
> }
>
> /*
> @@ -258,7 +256,7 @@ index a2c9a966f7..5ec38ca8f3 100644
> */
>
> static int digest_init(EVP_MD_CTX *ctx)
> -@@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ctx)
> +@@ -630,52 +751,94 @@ static int digest_cleanup(EVP_MD_CTX *ct
> return clean_devcrypto_session(&digest_ctx->sess);
> }
>
> @@ -403,7 +401,7 @@ index a2c9a966f7..5ec38ca8f3 100644
> }
> }
>
> -@@ -739,8 +909,154 @@ static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
> +@@ -739,7 +909,153 @@ static int devcrypto_digests(ENGINE *e,
> return *digest != NULL;
> }
>
> @@ -479,8 +477,8 @@ index a2c9a966f7..5ec38ca8f3 100644
> + "DIGESTS",
> + "either ALL, NONE, or a comma-separated list of digests to enable [default=ALL]",
> + ENGINE_CMD_FLAG_STRING},
> - #endif
> -
> ++#endif
> ++
> + {0, NULL, NULL, 0}
> +};
> +
> @@ -504,7 +502,7 @@ index a2c9a966f7..5ec38ca8f3 100644
> + use_softdrivers = i;
> +#ifdef IMPLEMENT_DIGEST
> + rebuild_known_digest_nids(e);
> -+#endif
> + #endif
> + rebuild_known_cipher_nids(e);
> + return 1;
> +#endif /* CIOCGSESSINFO */
> @@ -554,11 +552,10 @@ index a2c9a966f7..5ec38ca8f3 100644
> + }
> + return 0;
> +}
> -+
> +
> /******************************************************************************
> *
> - * LOAD / UNLOAD
> -@@ -793,6 +1109,8 @@ void engine_load_devcrypto_int()
> +@@ -806,6 +1122,8 @@ void engine_load_devcrypto_int()
>
> if (!ENGINE_set_id(e, "devcrypto")
> || !ENGINE_set_name(e, "/dev/crypto engine")
> 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
> index ad83a51a10..eee71c6c62 100644
> --- 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
> @@ -1,4 +1,4 @@
> -From 78e7b1cc7119622645bc5a8542c55b6c95dc7868 Mon Sep 17 00:00:00 2001
> +From 0000000000000000000000000000000000000000 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: eng_devcrypto: add command to dump driver info
> @@ -11,11 +11,9 @@ 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 5ec38ca8f3..64dc6b891d 100644
> --- a/crypto/engine/eng_devcrypto.c
> +++ b/crypto/engine/eng_devcrypto.c
> -@@ -50,16 +50,20 @@ static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFDTRIVERS;
> +@@ -50,16 +50,20 @@ static int use_softdrivers = DEVCRYPTO_D
> */
> struct driver_info_st {
> enum devcrypto_status_t {
> @@ -82,7 +80,7 @@ index 5ec38ca8f3..64dc6b891d 100644
> #endif /* CIOCGSESSINFO */
> }
> ioctl(cfd, CIOCFSESSION, &sess.ses);
> -@@ -505,8 +514,11 @@ static void destroy_all_cipher_methods(void)
> +@@ -505,8 +514,11 @@ static void destroy_all_cipher_methods(v
> {
> size_t i;
>
> @@ -95,7 +93,7 @@ index 5ec38ca8f3..64dc6b891d 100644
> }
>
> static int devcrypto_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
> -@@ -550,6 +562,40 @@ static int cryptodev_select_cipher_cb(const char *str, int len, void *usr)
> +@@ -550,6 +562,40 @@ static int cryptodev_select_cipher_cb(co
> return 1;
> }
>
> @@ -190,7 +188,7 @@ index 5ec38ca8f3..64dc6b891d 100644
> EVP_MD_meth_free(known_digest_methods[i]);
> known_digest_methods[i] = NULL;
> goto finish;
> -@@ -894,8 +945,11 @@ static void destroy_all_digest_methods(void)
> +@@ -894,8 +945,11 @@ static void destroy_all_digest_methods(v
> {
> size_t i;
>
> @@ -203,7 +201,7 @@ index 5ec38ca8f3..64dc6b891d 100644
> }
>
> static int devcrypto_digests(ENGINE *e, const EVP_MD **digest,
> -@@ -939,6 +993,43 @@ static int cryptodev_select_digest_cb(const char *str, int len, void *usr)
> +@@ -939,6 +993,43 @@ static int cryptodev_select_digest_cb(co
> return 1;
> }
>
> @@ -247,7 +245,7 @@ index 5ec38ca8f3..64dc6b891d 100644
> #endif
>
> /******************************************************************************
> -@@ -983,6 +1074,11 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
> +@@ -983,6 +1074,11 @@ static const ENGINE_CMD_DEFN devcrypto_c
> ENGINE_CMD_FLAG_STRING},
> #endif
>
> @@ -259,7 +257,7 @@ index 5ec38ca8f3..64dc6b891d 100644
> {0, NULL, NULL, 0}
> };
>
> -@@ -1051,6 +1147,13 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
> +@@ -1051,6 +1147,13 @@ static int devcrypto_ctrl(ENGINE *e, int
> return 1;
> #endif /* IMPLEMENT_DIGEST */
>
> 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
> index ea3f8fb8a7..248099d4d5 100644
> --- 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
> @@ -8,8 +8,6 @@ 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]=\
> @@ -19,209 +17,2578 @@ index e00802a3fd..47fe948966 100644
> -IF[{- !$disabled{devcryptoeng} -}]
> - SOURCE[../../libcrypto]=eng_devcrypto.c
> -ENDIF
> -diff --git a/crypto/init.c b/crypto/init.c
> -index 1b0d523bea..ee3e2eb075 100644
> ---- a/crypto/init.c
> -+++ b/crypto/init.c
> -@@ -329,18 +329,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)
> +--- a/crypto/engine/eng_devcrypto.c
> ++++ /dev/null
> +@@ -1,1277 +0,0 @@
> +-/*
> +- * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
> +- *
> +- * Licensed under the OpenSSL license (the "License"). You may not use
> +- * this file except in compliance with the License. You can obtain a copy
> +- * in the file LICENSE in the source distribution or at
> +- * https://www.openssl.org/source/license.html
> +- */
> +-
> +-#include "e_os.h"
> +-#include <string.h>
> +-#include <sys/types.h>
> +-#include <sys/stat.h>
> +-#include <fcntl.h>
> +-#include <sys/ioctl.h>
> +-#include <unistd.h>
> +-#include <assert.h>
> +-
> +-#include <openssl/conf.h>
> +-#include <openssl/evp.h>
> +-#include <openssl/err.h>
> +-#include <openssl/engine.h>
> +-#include <openssl/objects.h>
> +-#include <crypto/cryptodev.h>
> +-
> +-#include "crypto/engine.h"
> +-
> +-/* #define ENGINE_DEVCRYPTO_DEBUG */
> +-
> +-#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
> +-# define CHECK_BSD_STYLE_MACROS
> +-#endif
> +-
> +-/*
> +- * 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;
> +-#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_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 */
> +- } accelerated;
> +-
> +- char *driver_name;
> +-};
> +-
> +-static int clean_devcrypto_session(struct session_op *sess) {
> +- if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
> +- SYSerr(SYS_F_IOCTL, errno);
> +- return 0;
> +- }
> +- memset(sess, 0, sizeof(struct session_op));
> +- return 1;
> +-}
> +-
> +-/******************************************************************************
> +- *
> +- * Ciphers
> +- *
> +- * Because they all do the same basic operation, we have only one set of
> +- * method functions for them all to share, and a mapping table between
> +- * NIDs and cryptodev IDs, with all the necessary size data.
> +- *
> +- *****/
> +-
> +-struct cipher_ctx {
> +- struct session_op sess;
> +- int op; /* COP_ENCRYPT or COP_DECRYPT */
> +- unsigned long mode; /* EVP_CIPH_*_MODE */
> +-
> +- /* to handle ctr mode being a stream cipher */
> +- unsigned char partial[EVP_MAX_BLOCK_LENGTH];
> +- unsigned int blocksize, num;
> +-};
> +-
> +-static const struct cipher_data_st {
> +- int nid;
> +- int blocksize;
> +- int keylen;
> +- int ivlen;
> +- int flags;
> +- int devcryptoid;
> +-} cipher_data[] = {
> +-#ifndef OPENSSL_NO_DES
> +- { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
> +- { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
> +-#endif
> +-#ifndef OPENSSL_NO_BF
> +- { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
> +-#endif
> +-#ifndef OPENSSL_NO_CAST
> +- { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
> +-#endif
> +- { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
> +- { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
> +- { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
> +-#ifndef OPENSSL_NO_RC4
> +- { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
> +-#endif
> +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
> +- { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
> +- { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
> +- { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
> +-#endif
> +-#if 0 /* Not yet supported */
> +- { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
> +- { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
> +-#endif
> +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
> +- { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
> +- { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
> +- { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
> +-#endif
> +-#if 0 /* Not yet supported */
> +- { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
> +- { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
> +- { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
> +-#endif
> +-#ifndef OPENSSL_NO_CAMELLIA
> +- { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
> +- CRYPTO_CAMELLIA_CBC },
> +- { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
> +- CRYPTO_CAMELLIA_CBC },
> +- { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
> +- CRYPTO_CAMELLIA_CBC },
> +-#endif
> +-};
> +-
> +-static size_t find_cipher_data_index(int nid)
> -{
> --# ifdef OPENSSL_INIT_DEBUG
> -- fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
> -- "engine_load_devcrypto_int()\n");
> --# endif
> -- engine_load_devcrypto_int();
> +- 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
> +- * are used. If any other NID reaches this function, there's a grave
> +- * coding error further down.
> +- */
> +- assert("Code that never should be reached" == NULL);
> +- return -1;
> +-}
> +-
> +-static const struct cipher_data_st *get_cipher_data(int nid)
> +-{
> +- return &cipher_data[get_cipher_data_index(nid)];
> +-}
> +-
> +-/*
> +- * Following are the three necessary functions to map OpenSSL functionality
> +- * with cryptodev.
> +- */
> +-
> +-static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
> +- const unsigned char *iv, int enc)
> +-{
> +- struct cipher_ctx *cipher_ctx =
> +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> +- const struct cipher_data_st *cipher_d =
> +- get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
> +-
> +- /* cleanup a previous session */
> +- if (cipher_ctx->sess.ses != 0 &&
> +- clean_devcrypto_session(&cipher_ctx->sess) == 0)
> +- return 0;
> +-
> +- cipher_ctx->sess.cipher = cipher_d->devcryptoid;
> +- cipher_ctx->sess.keylen = cipher_d->keylen;
> +- cipher_ctx->sess.key = (void *)key;
> +- cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
> +- cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
> +- cipher_ctx->blocksize = cipher_d->blocksize;
> +- if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
> +- SYSerr(SYS_F_IOCTL, errno);
> +- return 0;
> +- }
> +-
> +- return 1;
> +-}
> +-
> +-static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
> +- const unsigned char *in, size_t inl)
> +-{
> +- struct cipher_ctx *cipher_ctx =
> +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> +- struct crypt_op cryp;
> +- unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
> +-#if !defined(COP_FLAG_WRITE_IV)
> +- unsigned char saved_iv[EVP_MAX_IV_LENGTH];
> +- const unsigned char *ivptr;
> +- size_t nblocks, ivlen;
> +-#endif
> +-
> +- memset(&cryp, 0, sizeof(cryp));
> +- cryp.ses = cipher_ctx->sess.ses;
> +- cryp.len = inl;
> +- cryp.src = (void *)in;
> +- cryp.dst = (void *)out;
> +- cryp.iv = (void *)iv;
> +- cryp.op = cipher_ctx->op;
> +-#if !defined(COP_FLAG_WRITE_IV)
> +- cryp.flags = 0;
> +-
> +- ivlen = EVP_CIPHER_CTX_iv_length(ctx);
> +- if (ivlen > 0)
> +- switch (cipher_ctx->mode) {
> +- case EVP_CIPH_CBC_MODE:
> +- assert(inl >= ivlen);
> +- if (!EVP_CIPHER_CTX_encrypting(ctx)) {
> +- ivptr = in + inl - ivlen;
> +- memcpy(saved_iv, ivptr, ivlen);
> +- }
> +- break;
> +-
> +- case EVP_CIPH_CTR_MODE:
> +- break;
> +-
> +- default: /* should not happen */
> +- return 0;
> +- }
> +-#else
> +- cryp.flags = COP_FLAG_WRITE_IV;
> +-#endif
> +-
> +- if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
> +- SYSerr(SYS_F_IOCTL, errno);
> +- return 0;
> +- }
> +-
> +-#if !defined(COP_FLAG_WRITE_IV)
> +- if (ivlen > 0)
> +- switch (cipher_ctx->mode) {
> +- case EVP_CIPH_CBC_MODE:
> +- assert(inl >= ivlen);
> +- if (EVP_CIPHER_CTX_encrypting(ctx))
> +- ivptr = out + inl - ivlen;
> +- else
> +- ivptr = saved_iv;
> +-
> +- memcpy(iv, ivptr, ivlen);
> +- break;
> +-
> +- case EVP_CIPH_CTR_MODE:
> +- nblocks = (inl + cipher_ctx->blocksize - 1)
> +- / cipher_ctx->blocksize;
> +- do {
> +- ivlen--;
> +- nblocks += iv[ivlen];
> +- iv[ivlen] = (uint8_t) nblocks;
> +- nblocks >>= 8;
> +- } while (ivlen);
> +- break;
> +-
> +- default: /* should not happen */
> +- return 0;
> +- }
> +-#endif
> +-
> +- return 1;
> +-}
> +-
> +-static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
> +- const unsigned char *in, size_t inl)
> +-{
> +- struct cipher_ctx *cipher_ctx =
> +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> +- size_t nblocks, len;
> +-
> +- /* initial partial block */
> +- while (cipher_ctx->num && inl) {
> +- (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
> +- --inl;
> +- cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
> +- }
> +-
> +- /* full blocks */
> +- if (inl > (unsigned int) cipher_ctx->blocksize) {
> +- nblocks = inl/cipher_ctx->blocksize;
> +- len = nblocks * cipher_ctx->blocksize;
> +- if (cipher_do_cipher(ctx, out, in, len) < 1)
> +- return 0;
> +- inl -= len;
> +- out += len;
> +- in += len;
> +- }
> +-
> +- /* final partial block */
> +- if (inl) {
> +- memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
> +- if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
> +- cipher_ctx->blocksize) < 1)
> +- return 0;
> +- while (inl--) {
> +- out[cipher_ctx->num] = in[cipher_ctx->num]
> +- ^ cipher_ctx->partial[cipher_ctx->num];
> +- cipher_ctx->num++;
> +- }
> +- }
> +-
> +- return 1;
> +-}
> +-
> +-static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
> +-{
> +- struct cipher_ctx *cipher_ctx =
> +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> +- EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
> +- struct cipher_ctx *to_cipher_ctx;
> +-
> +- switch (type) {
> +- case EVP_CTRL_COPY:
> +- if (cipher_ctx == NULL)
> +- return 1;
> +- /* when copying the context, a new session needs to be initialized */
> +- to_cipher_ctx =
> +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
> +- memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
> +- return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
> +- (cipher_ctx->op == COP_ENCRYPT));
> +-
> +- case EVP_CTRL_INIT:
> +- memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
> +- return 1;
> +-
> +- default:
> +- break;
> +- }
> +-
> +- return -1;
> +-}
> +-
> +-static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
> +-{
> +- struct cipher_ctx *cipher_ctx =
> +- (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> +-
> +- return clean_devcrypto_session(&cipher_ctx->sess);
> +-}
> +-
> +-/*
> +- * 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 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";
> +-
> +- for (i = 0, known_cipher_nids_amount = 0;
> +- i < OSSL_NELEM(cipher_data); i++) {
> +-
> +- selected_ciphers[i] = 1;
> +- /*
> +- * Check that the cipher is usable
> +- */
> +- 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_NO_CIOCGSESSION;
> +- continue;
> +- }
> +-
> +- cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
> +-
> +- if ((known_cipher_methods[i] =
> +- EVP_CIPHER_meth_new(cipher_data[i].nid,
> +- cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
> +- cipher_data[i].blocksize,
> +- cipher_data[i].keylen)) == NULL
> +- || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
> +- cipher_data[i].ivlen)
> +- || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
> +- cipher_data[i].flags
> +- | EVP_CIPH_CUSTOM_COPY
> +- | EVP_CIPH_CTRL_INIT
> +- | EVP_CIPH_FLAG_DEFAULT_ASN1)
> +- || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
> +- || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
> +- cipher_mode == EVP_CIPH_CTR_MODE ?
> +- ctr_do_cipher :
> +- cipher_do_cipher)
> +- || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
> +- || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
> +- cipher_cleanup)
> +- || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
> +- sizeof(struct cipher_ctx))) {
> +- 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) {
> +- cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
> +- } 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);
> +- 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);
> +-
> +- if (i == (size_t)-1)
> +- return NULL;
> +- return known_cipher_methods[i];
> +-}
> +-
> +-static int get_cipher_nids(const int **nids)
> +-{
> +- *nids = known_cipher_nids;
> +- return known_cipher_nids_amount;
> +-}
> +-
> +-static void destroy_cipher_method(int nid)
> +-{
> +- size_t i = get_cipher_data_index(nid);
> +-
> +- EVP_CIPHER_meth_free(known_cipher_methods[i]);
> +- known_cipher_methods[i] = NULL;
> +-}
> +-
> +-static void destroy_all_cipher_methods(void)
> +-{
> +- size_t 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,
> +- const int **nids, int nid)
> +-{
> +- if (cipher == NULL)
> +- return get_cipher_nids(nids);
> +-
> +- *cipher = get_cipher_method(nid);
> +-
> +- 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;
> -}
> +-
> +-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
> +- * a cache, which is perilous if there's a lot of data coming in (if someone
> +- * wants to checksum an OpenSSL tarball, for example).
> +- */
> +-#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
> +-#define IMPLEMENT_DIGEST
> +-
> +-/******************************************************************************
> +- *
> +- * Digests
> +- *
> +- * Because they all do the same basic operation, we have only one set of
> +- * method functions for them all to share, and a mapping table between
> +- * NIDs and cryptodev IDs, with all the necessary size data.
> +- *
> +- *****/
> +-
> +-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 {
> +- int nid;
> +- int blocksize;
> +- int digestlen;
> +- int devcryptoid;
> +-} digest_data[] = {
> +-#ifndef OPENSSL_NO_MD5
> +- { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
> +-#endif
> +- { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
> +-#ifndef OPENSSL_NO_RMD160
> +-# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
> +- { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
> -# endif
> -
> - # ifndef OPENSSL_NO_RDRAND
> - static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
> -@@ -365,6 +353,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)
> +-#endif
> +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
> +- { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
> +-#endif
> +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
> +- { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
> +-#endif
> +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
> +- { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
> +-#endif
> +-#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
> +- { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
> +-#endif
> +-};
> +-
> +-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
> +- * are used. If any other NID reaches this function, there's a grave
> +- * coding error further down.
> +- */
> +- assert("Code that never should be reached" == NULL);
> +- return -1;
> +-}
> +-
> +-static const struct digest_data_st *get_digest_data(int nid)
> +-{
> +- return &digest_data[get_digest_data_index(nid)];
> +-}
> +-
> +-/*
> +- * 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)
> +-{
> +- struct digest_ctx *digest_ctx =
> +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> +- const struct digest_data_st *digest_d =
> +- get_digest_data(EVP_MD_CTX_type(ctx));
> +-
> +- digest_ctx->init_called = 1;
> +-
> +- memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
> +- digest_ctx->sess.mac = digest_d->devcryptoid;
> +- if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
> +- SYSerr(SYS_F_IOCTL, errno);
> +- return 0;
> +- }
> +-
> +- return 1;
> +-}
> +-
> +-static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
> +- void *res, unsigned int flags)
> +-{
> +- struct crypt_op cryp;
> +-
> +- memset(&cryp, 0, sizeof(cryp));
> +- cryp.ses = ctx->sess.ses;
> +- cryp.len = srclen;
> +- cryp.src = (void *)src;
> +- cryp.dst = NULL;
> +- cryp.mac = res;
> +- cryp.flags = flags;
> +- return ioctl(cfd, CIOCCRYPT, &cryp);
> +-}
> +-
> +-static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
> +-{
> +- struct digest_ctx *digest_ctx =
> +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> +-
> +- if (count == 0)
> +- return 1;
> +-
> +- if (digest_ctx == NULL)
> +- 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;
> +- }
> +-
> +- SYSerr(SYS_F_IOCTL, errno);
> +- return 0;
> +-}
> +-
> +-static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
> +-{
> +- struct digest_ctx *digest_ctx =
> +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> +-
> +- if (md == NULL || digest_ctx == NULL)
> +- return 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;
> +- }
> +-
> +- return 1;
> +-}
> +-
> +-static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
> +-{
> +- struct digest_ctx *digest_from =
> +- (struct digest_ctx *)EVP_MD_CTX_md_data(from);
> +- struct digest_ctx *digest_to =
> +- (struct digest_ctx *)EVP_MD_CTX_md_data(to);
> +- struct cphash_op cphash;
> +-
> +- if (digest_from == NULL || digest_from->init_called != 1)
> +- return 1;
> +-
> +- if (!digest_init(to)) {
> +- SYSerr(SYS_F_IOCTL, errno);
> +- return 0;
> +- }
> +-
> +- cphash.src_ses = digest_from->sess.ses;
> +- cphash.dst_ses = digest_to->sess.ses;
> +- if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
> +- SYSerr(SYS_F_IOCTL, errno);
> +- return 0;
> +- }
> +- return 1;
> +-}
> +-
> +-static int digest_cleanup(EVP_MD_CTX *ctx)
> +-{
> +- struct digest_ctx *digest_ctx =
> +- (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> +-
> +- if (digest_ctx == NULL)
> +- return 1;
> +-
> +- return clean_devcrypto_session(&digest_ctx->sess);
> +-}
> +-
> +-/*
> +- * 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 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 digest is usable
> +- */
> +- sess1.mac = digest_data[i].devcryptoid;
> +- sess2.ses = 0;
> +- if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
> +- 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) {
> +- digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
> +- } 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_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_NO_CIOCCPHASH;
> +- 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],
> +- digest_data[i].blocksize)
> +- || !EVP_MD_meth_set_result_size(known_digest_methods[i],
> +- digest_data[i].digestlen)
> +- || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
> +- || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
> +- || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
> +- || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
> +- || !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_FAILURE;
> +- EVP_MD_meth_free(known_digest_methods[i]);
> +- known_digest_methods[i] = NULL;
> +- 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;
> +- }
> +-}
> +-
> +-static const EVP_MD *get_digest_method(int nid)
> +-{
> +- size_t i = get_digest_data_index(nid);
> +-
> +- if (i == (size_t)-1)
> +- return NULL;
> +- return known_digest_methods[i];
> +-}
> +-
> +-static int get_digest_nids(const int **nids)
> +-{
> +- *nids = known_digest_nids;
> +- return known_digest_nids_amount;
> +-}
> +-
> +-static void destroy_digest_method(int nid)
> +-{
> +- size_t i = get_digest_data_index(nid);
> +-
> +- EVP_MD_meth_free(known_digest_methods[i]);
> +- known_digest_methods[i] = NULL;
> +-}
> +-
> +-static void destroy_all_digest_methods(void)
> +-{
> +- size_t 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,
> +- const int **nids, int nid)
> +-{
> +- if (digest == NULL)
> +- return get_digest_nids(nids);
> +-
> +- *digest = get_digest_method(nid);
> +-
> +- 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;
> +-}
> +-
> +-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
> +-
> +-/******************************************************************************
> +- *
> +- * 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
> +-
> +- {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}
> +-};
> +-
> +-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 */
> +-
> +- case DEVCRYPTO_CMD_DUMP_INFO:
> +- dump_cipher_info();
> +-#ifdef IMPLEMENT_DIGEST
> +- dump_digest_info();
> +-#endif
> +- return 1;
> +-
> +- default:
> +- break;
> +- }
> +- return 0;
> +-}
> +-
> +-/******************************************************************************
> +- *
> +- * LOAD / UNLOAD
> +- *
> +- *****/
> +-
> +-static int devcrypto_unload(ENGINE *e)
> +-{
> +- destroy_all_cipher_methods();
> +-#ifdef IMPLEMENT_DIGEST
> +- destroy_all_digest_methods();
> +-#endif
> +-
> +- close(cfd);
> +-
> +- 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;
> +- int fd;
> +-
> +- if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
> +-#ifndef ENGINE_DEVCRYPTO_DEBUG
> +- if (errno != ENOENT)
> +-#endif
> +- fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
> +- return;
> +- }
> +-
> +-#ifdef CRIOGET
> +- if (ioctl(fd, CRIOGET, &cfd) < 0) {
> +- fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
> +- close(fd);
> +- cfd = -1;
> +- return;
> +- }
> +- close(fd);
> +-#else
> +- cfd = fd;
> +-#endif
> +-
> +- 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;
> +- }
> +-
> +- 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)
> +-
> +-/*
> +- * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
> +- * implementations, it seems to only exist in FreeBSD, and regarding the
> +- * parameters in its crypt_kop, the manual crypto(4) has this to say:
> +- *
> +- * The semantics of these arguments are currently undocumented.
> +- *
> +- * Reading through the FreeBSD source code doesn't give much more than
> +- * their CRK_MOD_EXP implementation for ubsec.
> +- *
> +- * It doesn't look much better with cryptodev-linux. They have the crypt_kop
> +- * structure as well as the command (CRK_*) in cryptodev.h, but no support
> +- * seems to be implemented at all for the moment.
> +- *
> +- * At the time of writing, it seems impossible to write proper support for
> +- * FreeBSD's asym features without some very deep knowledge and access to
> +- * specific kernel modules.
> +- *
> +- * /Richard Levitte, 2017-05-11
> +- */
> +-#if 0
> +-# ifndef OPENSSL_NO_RSA
> +- || !ENGINE_set_RSA(e, devcrypto_rsa)
> +-# endif
> +-# ifndef OPENSSL_NO_DSA
> +- || !ENGINE_set_DSA(e, devcrypto_dsa)
> +-# endif
> +-# ifndef OPENSSL_NO_DH
> +- || !ENGINE_set_DH(e, devcrypto_dh)
> +-# endif
> +-# ifndef OPENSSL_NO_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
> +- ) {
> +- ENGINE_free(e);
> +- return;
> +- }
> +-
> +- ENGINE_add(e);
> +- ENGINE_free(e); /* Loose our local reference */
> +- ERR_clear_error();
> +-}
> +--- a/crypto/init.c
> ++++ b/crypto/init.c
> +@@ -329,18 +329,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_
> + 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;
> +@@ -365,6 +353,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_
> + 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)
> +@@ -713,11 +713,6 @@ int OPENSSL_init_crypto(uint64_t opts, c
> + 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))
> +@@ -727,6 +722,11 @@ int OPENSSL_init_crypto(uint64_t opts, c
> + && !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))
> +--- a/engines/build.info
> ++++ b/engines/build.info
> +@@ -11,6 +11,9 @@ IF[{- !$disabled{"engine"} -}]
> + IF[{- !$disabled{afalgeng} -}]
> + SOURCE[../libcrypto]=e_afalg.c
> + ENDIF
> ++ IF[{- !$disabled{"devcryptoeng"} -}]
> ++ SOURCE[../libcrypto]=e_devcrypto.c
> ++ ENDIF
> + ELSE
> + IF[{- !$disabled{hw} && !$disabled{'hw-padlock'} -}]
> + ENGINES=padlock
> +@@ -30,6 +33,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
> +--- /dev/null
> ++++ b/engines/e_devcrypto.c
> +@@ -0,0 +1,1327 @@
> ++/*
> ++ * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
> ++ *
> ++ * Licensed under the OpenSSL license (the "License"). You may not use
> ++ * this file except in compliance with the License. You can obtain a copy
> ++ * in the file LICENSE in the source distribution or at
> ++ * https://www.openssl.org/source/license.html
> ++ */
> ++
> ++#include "../e_os.h"
> ++#include <string.h>
> ++#include <sys/types.h>
> ++#include <sys/stat.h>
> ++#include <fcntl.h>
> ++#include <sys/ioctl.h>
> ++#include <unistd.h>
> ++#include <assert.h>
> ++
> ++#include <openssl/conf.h>
> ++#include <openssl/evp.h>
> ++#include <openssl/err.h>
> ++#include <openssl/engine.h>
> ++#include <openssl/objects.h>
> ++#include <crypto/cryptodev.h>
> ++
> ++#include "crypto/engine.h"
> ++
> ++/* #define ENGINE_DEVCRYPTO_DEBUG */
> ++
> ++#if CRYPTO_ALGORITHM_MIN < CRYPTO_ALGORITHM_MAX
> ++# 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 = -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_SOFTDRIVERS DEVCRYPTO_REJECT_SOFTWARE
> ++static int use_softdrivers = DEVCRYPTO_DEFAULT_USE_SOFTDRIVERS;
> ++
> ++/*
> ++ * cipher/digest status & acceleration definitions
> ++ * Make sure the defaults are set to 0
> ++ */
> ++struct driver_info_st {
> ++ enum devcrypto_status_t {
> ++ 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 */
> ++ } accelerated;
> ++
> ++ char *driver_name;
> ++};
> ++
> ++static int clean_devcrypto_session(struct session_op *sess) {
> ++ if (ioctl(cfd, CIOCFSESSION, &sess->ses) < 0) {
> ++ SYSerr(SYS_F_IOCTL, errno);
> ++ return 0;
> ++ }
> ++ memset(sess, 0, sizeof(struct session_op));
> ++ return 1;
> ++}
> ++
> ++/******************************************************************************
> ++ *
> ++ * Ciphers
> ++ *
> ++ * Because they all do the same basic operation, we have only one set of
> ++ * method functions for them all to share, and a mapping table between
> ++ * NIDs and cryptodev IDs, with all the necessary size data.
> ++ *
> ++ *****/
> ++
> ++struct cipher_ctx {
> ++ struct session_op sess;
> ++ int op; /* COP_ENCRYPT or COP_DECRYPT */
> ++ unsigned long mode; /* EVP_CIPH_*_MODE */
> ++
> ++ /* to handle ctr mode being a stream cipher */
> ++ unsigned char partial[EVP_MAX_BLOCK_LENGTH];
> ++ unsigned int blocksize, num;
> ++};
> ++
> ++static const struct cipher_data_st {
> ++ int nid;
> ++ int blocksize;
> ++ int keylen;
> ++ int ivlen;
> ++ int flags;
> ++ int devcryptoid;
> ++} cipher_data[] = {
> ++#ifndef OPENSSL_NO_DES
> ++ { NID_des_cbc, 8, 8, 8, EVP_CIPH_CBC_MODE, CRYPTO_DES_CBC },
> ++ { NID_des_ede3_cbc, 8, 24, 8, EVP_CIPH_CBC_MODE, CRYPTO_3DES_CBC },
> ++#endif
> ++#ifndef OPENSSL_NO_BF
> ++ { NID_bf_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_BLF_CBC },
> ++#endif
> ++#ifndef OPENSSL_NO_CAST
> ++ { NID_cast5_cbc, 8, 16, 8, EVP_CIPH_CBC_MODE, CRYPTO_CAST_CBC },
> ++#endif
> ++ { NID_aes_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
> ++ { NID_aes_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
> ++ { NID_aes_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE, CRYPTO_AES_CBC },
> ++#ifndef OPENSSL_NO_RC4
> ++ { NID_rc4, 1, 16, 0, EVP_CIPH_STREAM_CIPHER, CRYPTO_ARC4 },
> ++#endif
> ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_CTR)
> ++ { NID_aes_128_ctr, 16, 128 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
> ++ { NID_aes_192_ctr, 16, 192 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
> ++ { NID_aes_256_ctr, 16, 256 / 8, 16, EVP_CIPH_CTR_MODE, CRYPTO_AES_CTR },
> ++#endif
> ++#if 0 /* Not yet supported */
> ++ { NID_aes_128_xts, 16, 128 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
> ++ { NID_aes_256_xts, 16, 256 / 8 * 2, 16, EVP_CIPH_XTS_MODE, CRYPTO_AES_XTS },
> ++#endif
> ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_AES_ECB)
> ++ { NID_aes_128_ecb, 16, 128 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
> ++ { NID_aes_192_ecb, 16, 192 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
> ++ { NID_aes_256_ecb, 16, 256 / 8, 0, EVP_CIPH_ECB_MODE, CRYPTO_AES_ECB },
> ++#endif
> ++#if 0 /* Not yet supported */
> ++ { NID_aes_128_gcm, 16, 128 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
> ++ { NID_aes_192_gcm, 16, 192 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
> ++ { NID_aes_256_gcm, 16, 256 / 8, 16, EVP_CIPH_GCM_MODE, CRYPTO_AES_GCM },
> ++#endif
> ++#ifndef OPENSSL_NO_CAMELLIA
> ++ { NID_camellia_128_cbc, 16, 128 / 8, 16, EVP_CIPH_CBC_MODE,
> ++ CRYPTO_CAMELLIA_CBC },
> ++ { NID_camellia_192_cbc, 16, 192 / 8, 16, EVP_CIPH_CBC_MODE,
> ++ CRYPTO_CAMELLIA_CBC },
> ++ { NID_camellia_256_cbc, 16, 256 / 8, 16, EVP_CIPH_CBC_MODE,
> ++ CRYPTO_CAMELLIA_CBC },
> ++#endif
> ++};
> ++
> ++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
> ++ * are used. If any other NID reaches this function, there's a grave
> ++ * coding error further down.
> ++ */
> ++ assert("Code that never should be reached" == NULL);
> ++ return -1;
> ++}
> ++
> ++static const struct cipher_data_st *get_cipher_data(int nid)
> ++{
> ++ return &cipher_data[get_cipher_data_index(nid)];
> ++}
> ++
> ++/*
> ++ * Following are the three necessary functions to map OpenSSL functionality
> ++ * with cryptodev.
> ++ */
> ++
> ++static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
> ++ const unsigned char *iv, int enc)
> ++{
> ++ struct cipher_ctx *cipher_ctx =
> ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> ++ const struct cipher_data_st *cipher_d =
> ++ get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
> ++
> ++ /* cleanup a previous session */
> ++ if (cipher_ctx->sess.ses != 0 &&
> ++ clean_devcrypto_session(&cipher_ctx->sess) == 0)
> ++ return 0;
> ++
> ++ cipher_ctx->sess.cipher = cipher_d->devcryptoid;
> ++ cipher_ctx->sess.keylen = cipher_d->keylen;
> ++ cipher_ctx->sess.key = (void *)key;
> ++ cipher_ctx->op = enc ? COP_ENCRYPT : COP_DECRYPT;
> ++ cipher_ctx->mode = cipher_d->flags & EVP_CIPH_MODE;
> ++ cipher_ctx->blocksize = cipher_d->blocksize;
> ++ if (ioctl(cfd, CIOCGSESSION, &cipher_ctx->sess) < 0) {
> ++ SYSerr(SYS_F_IOCTL, errno);
> ++ return 0;
> ++ }
> ++
> ++ return 1;
> ++}
> ++
> ++static int cipher_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
> ++ const unsigned char *in, size_t inl)
> ++{
> ++ struct cipher_ctx *cipher_ctx =
> ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> ++ struct crypt_op cryp;
> ++ unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx);
> ++#if !defined(COP_FLAG_WRITE_IV)
> ++ unsigned char saved_iv[EVP_MAX_IV_LENGTH];
> ++ const unsigned char *ivptr;
> ++ size_t nblocks, ivlen;
> ++#endif
> ++
> ++ memset(&cryp, 0, sizeof(cryp));
> ++ cryp.ses = cipher_ctx->sess.ses;
> ++ cryp.len = inl;
> ++ cryp.src = (void *)in;
> ++ cryp.dst = (void *)out;
> ++ cryp.iv = (void *)iv;
> ++ cryp.op = cipher_ctx->op;
> ++#if !defined(COP_FLAG_WRITE_IV)
> ++ cryp.flags = 0;
> ++
> ++ ivlen = EVP_CIPHER_CTX_iv_length(ctx);
> ++ if (ivlen > 0)
> ++ switch (cipher_ctx->mode) {
> ++ case EVP_CIPH_CBC_MODE:
> ++ assert(inl >= ivlen);
> ++ if (!EVP_CIPHER_CTX_encrypting(ctx)) {
> ++ ivptr = in + inl - ivlen;
> ++ memcpy(saved_iv, ivptr, ivlen);
> ++ }
> ++ break;
> ++
> ++ case EVP_CIPH_CTR_MODE:
> ++ break;
> ++
> ++ default: /* should not happen */
> ++ return 0;
> ++ }
> ++#else
> ++ cryp.flags = COP_FLAG_WRITE_IV;
> ++#endif
> ++
> ++ if (ioctl(cfd, CIOCCRYPT, &cryp) < 0) {
> ++ SYSerr(SYS_F_IOCTL, errno);
> ++ return 0;
> ++ }
> ++
> ++#if !defined(COP_FLAG_WRITE_IV)
> ++ if (ivlen > 0)
> ++ switch (cipher_ctx->mode) {
> ++ case EVP_CIPH_CBC_MODE:
> ++ assert(inl >= ivlen);
> ++ if (EVP_CIPHER_CTX_encrypting(ctx))
> ++ ivptr = out + inl - ivlen;
> ++ else
> ++ ivptr = saved_iv;
> ++
> ++ memcpy(iv, ivptr, ivlen);
> ++ break;
> ++
> ++ case EVP_CIPH_CTR_MODE:
> ++ nblocks = (inl + cipher_ctx->blocksize - 1)
> ++ / cipher_ctx->blocksize;
> ++ do {
> ++ ivlen--;
> ++ nblocks += iv[ivlen];
> ++ iv[ivlen] = (uint8_t) nblocks;
> ++ nblocks >>= 8;
> ++ } while (ivlen);
> ++ break;
> ++
> ++ default: /* should not happen */
> ++ return 0;
> ++ }
> ++#endif
> ++
> ++ return 1;
> ++}
> ++
> ++static int ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
> ++ const unsigned char *in, size_t inl)
> ++{
> ++ struct cipher_ctx *cipher_ctx =
> ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> ++ size_t nblocks, len;
> ++
> ++ /* initial partial block */
> ++ while (cipher_ctx->num && inl) {
> ++ (*out++) = *(in++) ^ cipher_ctx->partial[cipher_ctx->num];
> ++ --inl;
> ++ cipher_ctx->num = (cipher_ctx->num + 1) % cipher_ctx->blocksize;
> ++ }
> ++
> ++ /* full blocks */
> ++ if (inl > (unsigned int) cipher_ctx->blocksize) {
> ++ nblocks = inl/cipher_ctx->blocksize;
> ++ len = nblocks * cipher_ctx->blocksize;
> ++ if (cipher_do_cipher(ctx, out, in, len) < 1)
> ++ return 0;
> ++ inl -= len;
> ++ out += len;
> ++ in += len;
> ++ }
> ++
> ++ /* final partial block */
> ++ if (inl) {
> ++ memset(cipher_ctx->partial, 0, cipher_ctx->blocksize);
> ++ if (cipher_do_cipher(ctx, cipher_ctx->partial, cipher_ctx->partial,
> ++ cipher_ctx->blocksize) < 1)
> ++ return 0;
> ++ while (inl--) {
> ++ out[cipher_ctx->num] = in[cipher_ctx->num]
> ++ ^ cipher_ctx->partial[cipher_ctx->num];
> ++ cipher_ctx->num++;
> ++ }
> ++ }
> ++
> ++ return 1;
> ++}
> ++
> ++static int cipher_ctrl(EVP_CIPHER_CTX *ctx, int type, int p1, void* p2)
> ++{
> ++ struct cipher_ctx *cipher_ctx =
> ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> ++ EVP_CIPHER_CTX *to_ctx = (EVP_CIPHER_CTX *)p2;
> ++ struct cipher_ctx *to_cipher_ctx;
> ++
> ++ switch (type) {
> ++ case EVP_CTRL_COPY:
> ++ if (cipher_ctx == NULL)
> ++ return 1;
> ++ /* when copying the context, a new session needs to be initialized */
> ++ to_cipher_ctx =
> ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(to_ctx);
> ++ memset(&to_cipher_ctx->sess, 0, sizeof(to_cipher_ctx->sess));
> ++ return cipher_init(to_ctx, cipher_ctx->sess.key, EVP_CIPHER_CTX_iv(ctx),
> ++ (cipher_ctx->op == COP_ENCRYPT));
> ++
> ++ case EVP_CTRL_INIT:
> ++ memset(&cipher_ctx->sess, 0, sizeof(cipher_ctx->sess));
> ++ return 1;
> ++
> ++ default:
> ++ break;
> ++ }
> ++
> ++ return -1;
> ++}
> ++
> ++static int cipher_cleanup(EVP_CIPHER_CTX *ctx)
> ++{
> ++ struct cipher_ctx *cipher_ctx =
> ++ (struct cipher_ctx *)EVP_CIPHER_CTX_get_cipher_data(ctx);
> ++
> ++ return clean_devcrypto_session(&cipher_ctx->sess);
> ++}
> ++
> ++/*
> ++ * 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 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";
> ++
> ++ for (i = 0, known_cipher_nids_amount = 0;
> ++ i < OSSL_NELEM(cipher_data); i++) {
> ++
> ++ selected_ciphers[i] = 1;
> ++ /*
> ++ * Check that the cipher is usable
> ++ */
> ++ 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_NO_CIOCGSESSION;
> ++ continue;
> ++ }
> ++
> ++ cipher_mode = cipher_data[i].flags & EVP_CIPH_MODE;
> ++
> ++ if ((known_cipher_methods[i] =
> ++ EVP_CIPHER_meth_new(cipher_data[i].nid,
> ++ cipher_mode == EVP_CIPH_CTR_MODE ? 1 :
> ++ cipher_data[i].blocksize,
> ++ cipher_data[i].keylen)) == NULL
> ++ || !EVP_CIPHER_meth_set_iv_length(known_cipher_methods[i],
> ++ cipher_data[i].ivlen)
> ++ || !EVP_CIPHER_meth_set_flags(known_cipher_methods[i],
> ++ cipher_data[i].flags
> ++ | EVP_CIPH_CUSTOM_COPY
> ++ | EVP_CIPH_CTRL_INIT
> ++ | EVP_CIPH_FLAG_DEFAULT_ASN1)
> ++ || !EVP_CIPHER_meth_set_init(known_cipher_methods[i], cipher_init)
> ++ || !EVP_CIPHER_meth_set_do_cipher(known_cipher_methods[i],
> ++ cipher_mode == EVP_CIPH_CTR_MODE ?
> ++ ctr_do_cipher :
> ++ cipher_do_cipher)
> ++ || !EVP_CIPHER_meth_set_ctrl(known_cipher_methods[i], cipher_ctrl)
> ++ || !EVP_CIPHER_meth_set_cleanup(known_cipher_methods[i],
> ++ cipher_cleanup)
> ++ || !EVP_CIPHER_meth_set_impl_ctx_size(known_cipher_methods[i],
> ++ sizeof(struct cipher_ctx))) {
> ++ 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) {
> ++ cipher_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
> ++ } 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);
> ++ 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);
> ++
> ++ if (i == (size_t)-1)
> ++ return NULL;
> ++ return known_cipher_methods[i];
> ++}
> ++
> ++static int get_cipher_nids(const int **nids)
> ++{
> ++ *nids = known_cipher_nids;
> ++ return known_cipher_nids_amount;
> ++}
> ++
> ++static void destroy_cipher_method(int nid)
> ++{
> ++ size_t i = get_cipher_data_index(nid);
> ++
> ++ EVP_CIPHER_meth_free(known_cipher_methods[i]);
> ++ known_cipher_methods[i] = NULL;
> ++}
> ++
> ++static void destroy_all_cipher_methods(void)
> ++{
> ++ size_t 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,
> ++ const int **nids, int nid)
> ++{
> ++ if (cipher == NULL)
> ++ return get_cipher_nids(nids);
> ++
> ++ *cipher = get_cipher_method(nid);
> ++
> ++ 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;
> ++}
> ++
> ++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
> ++ * a cache, which is perilous if there's a lot of data coming in (if someone
> ++ * wants to checksum an OpenSSL tarball, for example).
> ++ */
> ++#if defined(CIOCCPHASH) && defined(COP_FLAG_UPDATE) && defined(COP_FLAG_FINAL)
> ++#define IMPLEMENT_DIGEST
> ++
> ++/******************************************************************************
> ++ *
> ++ * Digests
> ++ *
> ++ * Because they all do the same basic operation, we have only one set of
> ++ * method functions for them all to share, and a mapping table between
> ++ * NIDs and cryptodev IDs, with all the necessary size data.
> ++ *
> ++ *****/
> ++
> ++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 {
> ++ int nid;
> ++ int blocksize;
> ++ int digestlen;
> ++ int devcryptoid;
> ++} digest_data[] = {
> ++#ifndef OPENSSL_NO_MD5
> ++ { NID_md5, /* MD5_CBLOCK */ 64, 16, CRYPTO_MD5 },
> ++#endif
> ++ { NID_sha1, SHA_CBLOCK, 20, CRYPTO_SHA1 },
> ++#ifndef OPENSSL_NO_RMD160
> ++# if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_RIPEMD160)
> ++ { NID_ripemd160, /* RIPEMD160_CBLOCK */ 64, 20, CRYPTO_RIPEMD160 },
> ++# endif
> ++#endif
> ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_224)
> ++ { NID_sha224, SHA256_CBLOCK, 224 / 8, CRYPTO_SHA2_224 },
> ++#endif
> ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_256)
> ++ { NID_sha256, SHA256_CBLOCK, 256 / 8, CRYPTO_SHA2_256 },
> ++#endif
> ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_384)
> ++ { NID_sha384, SHA512_CBLOCK, 384 / 8, CRYPTO_SHA2_384 },
> ++#endif
> ++#if !defined(CHECK_BSD_STYLE_MACROS) || defined(CRYPTO_SHA2_512)
> ++ { NID_sha512, SHA512_CBLOCK, 512 / 8, CRYPTO_SHA2_512 },
> ++#endif
> ++};
> ++
> ++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
> ++ * are used. If any other NID reaches this function, there's a grave
> ++ * coding error further down.
> ++ */
> ++ assert("Code that never should be reached" == NULL);
> ++ return -1;
> ++}
> ++
> ++static const struct digest_data_st *get_digest_data(int nid)
> ++{
> ++ return &digest_data[get_digest_data_index(nid)];
> ++}
> ++
> ++/*
> ++ * 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)
> ++{
> ++ struct digest_ctx *digest_ctx =
> ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> ++ const struct digest_data_st *digest_d =
> ++ get_digest_data(EVP_MD_CTX_type(ctx));
> ++
> ++ digest_ctx->init_called = 1;
> ++
> ++ memset(&digest_ctx->sess, 0, sizeof(digest_ctx->sess));
> ++ digest_ctx->sess.mac = digest_d->devcryptoid;
> ++ if (ioctl(cfd, CIOCGSESSION, &digest_ctx->sess) < 0) {
> ++ SYSerr(SYS_F_IOCTL, errno);
> ++ return 0;
> ++ }
> ++
> ++ return 1;
> ++}
> ++
> ++static int digest_op(struct digest_ctx *ctx, const void *src, size_t srclen,
> ++ void *res, unsigned int flags)
> ++{
> ++ struct crypt_op cryp;
> ++
> ++ memset(&cryp, 0, sizeof(cryp));
> ++ cryp.ses = ctx->sess.ses;
> ++ cryp.len = srclen;
> ++ cryp.src = (void *)src;
> ++ cryp.dst = NULL;
> ++ cryp.mac = res;
> ++ cryp.flags = flags;
> ++ return ioctl(cfd, CIOCCRYPT, &cryp);
> ++}
> ++
> ++static int digest_update(EVP_MD_CTX *ctx, const void *data, size_t count)
> ++{
> ++ struct digest_ctx *digest_ctx =
> ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> ++
> ++ if (count == 0)
> ++ return 1;
> ++
> ++ if (digest_ctx == NULL)
> ++ 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;
> ++ }
> ++
> ++ SYSerr(SYS_F_IOCTL, errno);
> ++ return 0;
> ++}
> ++
> ++static int digest_final(EVP_MD_CTX *ctx, unsigned char *md)
> ++{
> ++ struct digest_ctx *digest_ctx =
> ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> ++
> ++ if (md == NULL || digest_ctx == NULL)
> ++ return 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;
> ++ }
> ++
> ++ return 1;
> ++}
> ++
> ++static int digest_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from)
> +{
> -+# ifdef OPENSSL_INIT_DEBUG
> -+ fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
> -+ "engine_load_devcrypto_int()\n");
> -+# endif
> -+ engine_load_devcrypto_int();
> ++ struct digest_ctx *digest_from =
> ++ (struct digest_ctx *)EVP_MD_CTX_md_data(from);
> ++ struct digest_ctx *digest_to =
> ++ (struct digest_ctx *)EVP_MD_CTX_md_data(to);
> ++ struct cphash_op cphash;
> ++
> ++ if (digest_from == NULL || digest_from->init_called != 1)
> ++ return 1;
> ++
> ++ if (!digest_init(to)) {
> ++ SYSerr(SYS_F_IOCTL, errno);
> ++ return 0;
> ++ }
> ++
> ++ cphash.src_ses = digest_from->sess.ses;
> ++ cphash.dst_ses = digest_to->sess.ses;
> ++ if (ioctl(cfd, CIOCCPHASH, &cphash) < 0) {
> ++ SYSerr(SYS_F_IOCTL, errno);
> ++ return 0;
> ++ }
> + 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)
> -@@ -713,11 +713,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))
> -@@ -727,6 +722,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))
> ++
> ++static int digest_cleanup(EVP_MD_CTX *ctx)
> ++{
> ++ struct digest_ctx *digest_ctx =
> ++ (struct digest_ctx *)EVP_MD_CTX_md_data(ctx);
> ++
> ++ if (digest_ctx == NULL)
> ++ return 1;
> ++
> ++ return clean_devcrypto_session(&digest_ctx->sess);
> ++}
> ++
> ++/*
> ++ * 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 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 digest is usable
> ++ */
> ++ sess1.mac = digest_data[i].devcryptoid;
> ++ sess2.ses = 0;
> ++ if (ioctl(cfd, CIOCGSESSION, &sess1) < 0) {
> ++ 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) {
> ++ digest_driver_info[i].accelerated = DEVCRYPTO_ACCELERATION_UNKNOWN;
> ++ } 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_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_NO_CIOCCPHASH;
> ++ 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],
> ++ digest_data[i].blocksize)
> ++ || !EVP_MD_meth_set_result_size(known_digest_methods[i],
> ++ digest_data[i].digestlen)
> ++ || !EVP_MD_meth_set_init(known_digest_methods[i], digest_init)
> ++ || !EVP_MD_meth_set_update(known_digest_methods[i], digest_update)
> ++ || !EVP_MD_meth_set_final(known_digest_methods[i], digest_final)
> ++ || !EVP_MD_meth_set_copy(known_digest_methods[i], digest_copy)
> ++ || !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_FAILURE;
> ++ EVP_MD_meth_free(known_digest_methods[i]);
> ++ known_digest_methods[i] = NULL;
> ++ 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;
> ++ }
> ++}
> ++
> ++static const EVP_MD *get_digest_method(int nid)
> ++{
> ++ size_t i = get_digest_data_index(nid);
> ++
> ++ if (i == (size_t)-1)
> ++ return NULL;
> ++ return known_digest_methods[i];
> ++}
> ++
> ++static int get_digest_nids(const int **nids)
> ++{
> ++ *nids = known_digest_nids;
> ++ return known_digest_nids_amount;
> ++}
> ++
> ++static void destroy_digest_method(int nid)
> ++{
> ++ size_t i = get_digest_data_index(nid);
> ++
> ++ EVP_MD_meth_free(known_digest_methods[i]);
> ++ known_digest_methods[i] = NULL;
> ++}
> ++
> ++static void destroy_all_digest_methods(void)
> ++{
> ++ size_t 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,
> ++ const int **nids, int nid)
> ++{
> ++ if (digest == NULL)
> ++ return get_digest_nids(nids);
> ++
> ++ *digest = get_digest_method(nid);
> ++
> ++ 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;
> -+# 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 1db771971c..33a25d7004 100644
> ---- a/engines/build.info
> -+++ b/engines/build.info
> -@@ -11,6 +11,9 @@ IF[{- !$disabled{"engine"} -}]
> - IF[{- !$disabled{afalgeng} -}]
> - SOURCE[../libcrypto]=e_afalg.c
> - ENDIF
> -+ IF[{- !$disabled{"devcryptoeng"} -}]
> -+ SOURCE[../libcrypto]=e_devcrypto.c
> -+ ENDIF
> - ELSE
> - IF[{- !$disabled{hw} && !$disabled{'hw-padlock'} -}]
> - ENGINES=padlock
> -@@ -30,6 +33,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 2c1b52d572..eff1ed3a7d 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>
> -@@ -31,18 +31,20 @@
> - # define CHECK_BSD_STYLE_MACROS
> - #endif
> -
> -+#define engine_devcrypto_id "devcrypto"
> ++ 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;
> ++}
> +
> - /*
> - * 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
> -@@ -1058,7 +1060,7 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
> - 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) "]",
> ++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
> ++
> ++/******************************************************************************
> ++ *
> ++ * 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_SOFTDRIVERS) "]",
> - ENGINE_CMD_FLAG_NUMERIC},
> - #endif
> -
> -@@ -1166,32 +1168,22 @@ static int devcrypto_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
> - *
> - *****/
> -
> --static int devcrypto_unload(ENGINE *e)
> --{
> -- destroy_all_cipher_methods();
> --#ifdef IMPLEMENT_DIGEST
> -- destroy_all_digest_methods();
> --#endif
> --
> -- close(cfd);
> --
> -- return 1;
> --}
> - /*
> -- * This engine is always built into libcrypto, so it doesn't offer any
> -- * ability to be dynamically loadable.
> ++ 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
> ++
> ++ {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}
> ++};
> ++
> ++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 */
> ++
> ++ case DEVCRYPTO_CMD_DUMP_INFO:
> ++ dump_cipher_info();
> ++#ifdef IMPLEMENT_DIGEST
> ++ dump_digest_info();
> ++#endif
> ++ return 1;
> ++
> ++ default:
> ++ break;
> ++ }
> ++ return 0;
> ++}
> ++
> ++/******************************************************************************
> ++ *
> ++ * LOAD / UNLOAD
> ++ *
> ++ *****/
> ++
> ++/*
> + * Opens /dev/crypto
> - */
> --void engine_load_devcrypto_int()
> ++ */
> +static int open_devcrypto(void)
> - {
> -- ENGINE *e = NULL;
> - int fd;
> -
> ++{
> ++ int fd;
> ++
> + if (cfd >= 0)
> + return 1;
> +
> - if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
> - #ifndef ENGINE_DEVCRYPTO_DEBUG
> - if (errno != ENOENT)
> - #endif
> - fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
> -- return;
> ++ if ((fd = open("/dev/crypto", O_RDWR, 0)) < 0) {
> ++#ifndef ENGINE_DEVCRYPTO_DEBUG
> ++ if (errno != ENOENT)
> ++#endif
> ++ fprintf(stderr, "Could not open /dev/crypto: %s\n", strerror(errno));
> + return 0;
> - }
> -
> - #ifdef CRIOGET
> -@@ -1199,35 +1191,61 @@ void engine_load_devcrypto_int()
> - fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
> - close(fd);
> - cfd = -1;
> -- return;
> ++ }
> ++
> ++#ifdef CRIOGET
> ++ if (ioctl(fd, CRIOGET, &cfd) < 0) {
> ++ fprintf(stderr, "Could not create crypto fd: %s\n", strerror(errno));
> ++ close(fd);
> ++ cfd = -1;
> + return 0;
> - }
> - close(fd);
> - #else
> - cfd = fd;
> - #endif
> -
> -- 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;
> ++ }
> ++ close(fd);
> ++#else
> ++ cfd = fd;
> ++#endif
> ++
> + return 1;
> +}
> +
> @@ -236,20 +2603,17 @@ index 2c1b52d572..eff1ed3a7d 100644
> + if (ret != 0) {
> + fprintf(stderr, "Error closing /dev/crypto: %s\n", strerror(errno));
> + return 0;
> - }
> ++ }
> + return 1;
> +}
> -
> -- prepare_cipher_methods();
> ++
> +static int devcrypto_unload(ENGINE *e)
> +{
> + destroy_all_cipher_methods();
> - #ifdef IMPLEMENT_DIGEST
> -- prepare_digest_methods();
> ++#ifdef IMPLEMENT_DIGEST
> + destroy_all_digest_methods();
> - #endif
> -
> -- if (!ENGINE_set_id(e, "devcrypto")
> ++#endif
> ++
> + close_devcrypto();
> +
> + return 1;
> @@ -258,13 +2622,12 @@ index 2c1b52d572..eff1ed3a7d 100644
> +static int bind_devcrypto(ENGINE *e) {
> +
> + if (!ENGINE_set_id(e, engine_devcrypto_id)
> - || !ENGINE_set_name(e, "/dev/crypto engine")
> ++ || !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)
> ++ || !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();
> @@ -274,34 +2637,40 @@ index 2c1b52d572..eff1ed3a7d 100644
> +#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
> -@@ -1250,23 +1268,36 @@ void engine_load_devcrypto_int()
> - */
> - #if 0
> - # ifndef OPENSSL_NO_RSA
> -- || !ENGINE_set_RSA(e, devcrypto_rsa)
> ++/*
> ++ * Asymmetric ciphers aren't well supported with /dev/crypto. Among the BSD
> ++ * implementations, it seems to only exist in FreeBSD, and regarding the
> ++ * parameters in its crypt_kop, the manual crypto(4) has this to say:
> ++ *
> ++ * The semantics of these arguments are currently undocumented.
> ++ *
> ++ * Reading through the FreeBSD source code doesn't give much more than
> ++ * their CRK_MOD_EXP implementation for ubsec.
> ++ *
> ++ * It doesn't look much better with cryptodev-linux. They have the crypt_kop
> ++ * structure as well as the command (CRK_*) in cryptodev.h, but no support
> ++ * seems to be implemented at all for the moment.
> ++ *
> ++ * At the time of writing, it seems impossible to write proper support for
> ++ * FreeBSD's asym features without some very deep knowledge and access to
> ++ * specific kernel modules.
> ++ *
> ++ * /Richard Levitte, 2017-05-11
> ++ */
> ++#if 0
> ++# ifndef OPENSSL_NO_RSA
> + && ENGINE_set_RSA(e, devcrypto_rsa)
> - # endif
> - # ifndef OPENSSL_NO_DSA
> -- || !ENGINE_set_DSA(e, devcrypto_dsa)
> ++# endif
> ++# ifndef OPENSSL_NO_DSA
> + && ENGINE_set_DSA(e, devcrypto_dsa)
> - # endif
> - # ifndef OPENSSL_NO_DH
> -- || !ENGINE_set_DH(e, devcrypto_dh)
> ++# endif
> ++# ifndef OPENSSL_NO_DH
> + && ENGINE_set_DH(e, devcrypto_dh)
> - # endif
> - # ifndef OPENSSL_NO_EC
> -- || !ENGINE_set_EC(e, devcrypto_ec)
> ++# endif
> ++# ifndef OPENSSL_NO_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
> -- ) {
> ++# endif
> ++#endif
> + );
> +}
> +
> @@ -320,13 +2689,14 @@ index 2c1b52d572..eff1ed3a7d 100644
> + if ((e = ENGINE_new()) == NULL
> + || !bind_devcrypto(e)) {
> + close_devcrypto();
> - ENGINE_free(e);
> - return;
> - }
> -@@ -1275,3 +1306,22 @@ void engine_load_devcrypto_int()
> - ENGINE_free(e); /* Loose our local reference */
> - ERR_clear_error();
> - }
> ++ ENGINE_free(e);
> ++ return;
> ++ }
> ++
> ++ ENGINE_add(e);
> ++ ENGINE_free(e); /* Loose our local reference */
> ++ ERR_clear_error();
> ++}
> +
> +#else
> +
> diff --git a/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch b/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch
> index 1f1cd7a582..df5c16d8d2 100644
> --- a/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch
> +++ b/package/libs/openssl/patches/500-e_devcrypto-default-to-not-use-digests-in-engine.patch
> @@ -19,8 +19,6 @@ turn them on if it is safe and fast enough.
>
> Signed-off-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
>
> -diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c
> -index 3fcd81de7a..d25230d366 100644
> --- a/engines/e_devcrypto.c
> +++ b/engines/e_devcrypto.c
> @@ -852,7 +852,7 @@ static void prepare_digest_methods(void)
> @@ -32,7 +30,7 @@ index 3fcd81de7a..d25230d366 100644
>
> /*
> * Check that the digest is usable
> -@@ -1072,7 +1072,7 @@ static const ENGINE_CMD_DEFN devcrypto_cmds[] = {
> +@@ -1072,7 +1072,7 @@ static const ENGINE_CMD_DEFN devcrypto_c
> #ifdef IMPLEMENT_DIGEST
> {DEVCRYPTO_CMD_DIGESTS,
> "DIGESTS",
> diff --git a/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch b/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch
> index bc514b88c9..87792cf9d0 100644
> --- a/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch
> +++ b/package/libs/openssl/patches/510-e_devcrypto-ignore-error-when-closing-session.patch
> @@ -8,11 +8,9 @@ session. It may have been closed by another process after a fork.
>
> Signed-off-by: Eneas U de Queiroz <cote2004-github at yahoo.com>
>
> -diff --git a/engines/e_devcrypto.c b/engines/e_devcrypto.c
> -index d25230d366..f4570f1666 100644
> --- a/engines/e_devcrypto.c
> +++ b/engines/e_devcrypto.c
> -@@ -195,9 +195,8 @@ static int cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
> +@@ -195,9 +195,8 @@ static int cipher_init(EVP_CIPHER_CTX *c
> get_cipher_data(EVP_CIPHER_CTX_nid(ctx));
>
> /* cleanup a previous session */
More information about the openwrt-devel
mailing list