diff options
author | ylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68> | 2023-03-20 18:22:56 +0000 |
---|---|---|
committer | ylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68> | 2023-03-20 18:22:56 +0000 |
commit | c6db438a960df30985c6c4de02459c8c114a1f6c (patch) | |
tree | 73c9e2a43de89ba27734e92eb1ec27a597ce42ca | |
parent | e138cf59e8a6efd8200448fcfc3e2b2172acafbd (diff) | |
download | libapr-util-c6db438a960df30985c6c4de02459c8c114a1f6c.tar.gz |
apr_crypto_openssl: use OPENSSL_init_crypto() to initialise OpenSSL
on versions 1.1+.
Backport 1861954.
apr_crypto_openssl: Compatibility with OpenSSL 3+
crypto: Follow up to r1908433: OPENSSL_API_COMPAT to 1.1.1.
crypto_openssl: Fix configure/detection of OPENSSL_init_crypto()
Merges r1862838, r1908581 from 1.7.x (partially).
Merges r1908433, r1908448, r1908453, r1908455, r1908503 from trunk.
Submitted by: minfrin, ylavic
git-svn-id: https://svn.apache.org/repos/asf/apr/apr-util/branches/1.6.x@1908584 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | build/crypto.m4 | 41 | ||||
-rw-r--r-- | crypto/apr_crypto_openssl.c | 155 | ||||
-rw-r--r-- | test/testcrypto.c | 40 |
4 files changed, 182 insertions, 57 deletions
@@ -1,6 +1,9 @@ -*- coding: utf-8 -*- Changes with APR-util 1.6.4 + *) apr_crypto_openssl: use OPENSSL_init_crypto() to initialise OpenSSL + on versions 1.1+. [Graham Leggett] + *) apr_memcache: Fix name lookup to allow IPv6 as well as IPv4. [Lubos Uhliarik <luhliari redhat.com>] diff --git a/build/crypto.m4 b/build/crypto.m4 index 3e856e4c..47bb729e 100644 --- a/build/crypto.m4 +++ b/build/crypto.m4 @@ -53,11 +53,11 @@ AC_DEFUN([APU_CHECK_CRYPTO], [ crypto_library_enabled=1 fi done - if test "$crypto_library_enabled" = "1"; then + if test "$crypto_library_enabled" = "1"; then AC_MSG_NOTICE([Crypto was requested but no crypto library was found; autodetecting possible libraries]) else AC_ERROR([Crypto was requested but all possible crypto libraries were disabled.]) - fi + fi fi APU_CHECK_CRYPTO_OPENSSL @@ -91,15 +91,14 @@ AC_DEFUN([APU_CHECK_CRYPTO_OPENSSL], [ if test "$withval" = "yes"; then AC_CHECK_HEADERS(openssl/x509.h, [openssl_have_headers=1]) AC_CHECK_LIB(crypto, EVP_CIPHER_CTX_new, AC_CHECK_LIB(ssl, SSL_accept, [openssl_have_libs=1],,-lcrypto)) - if test "$openssl_have_headers" != "0" && test "$openssl_have_libs" != "0"; then + if test "$openssl_have_headers" = "1" && test "$openssl_have_libs" = "1"; then apu_have_openssl=1 fi elif test "$withval" = "no"; then apu_have_openssl=0 else - openssl_CPPFLAGS="-I$withval/include" - openssl_LDFLAGS="-L$withval/lib " + openssl_LDFLAGS="-L$withval/lib -L$withval/lib64" APR_ADDTO(CPPFLAGS, [$openssl_CPPFLAGS]) APR_ADDTO(LDFLAGS, [$openssl_LDFLAGS]) @@ -107,15 +106,15 @@ AC_DEFUN([APU_CHECK_CRYPTO_OPENSSL], [ AC_MSG_NOTICE(checking for openssl in $withval) AC_CHECK_HEADERS(openssl/x509.h, [openssl_have_headers=1]) AC_CHECK_LIB(crypto, EVP_CIPHER_CTX_new, AC_CHECK_LIB(ssl, SSL_accept, [openssl_have_libs=1],,-lcrypto)) - if test "$openssl_have_headers" != "0" && test "$openssl_have_libs" != "0"; then + if test "$openssl_have_headers" = "1" && test "$openssl_have_libs" = "1"; then apu_have_openssl=1 - APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib]) - APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include]) + APR_ADDTO(APRUTIL_INCLUDES, [$openssl_CPPFLAGS]) + APR_ADDTO(APRUTIL_LDFLAGS, [$openssl_LDFLAGS]) fi - - AC_CHECK_DECLS([EVP_PKEY_CTX_new], [], [], - [#include <openssl/evp.h>]) - + fi + if test "$apu_have_openssl" = "1"; then + AC_CHECK_LIB(crypto, OPENSSL_init_crypto) + AC_CHECK_FUNCS([OPENSSL_init_crypto]) fi ], [ apu_have_openssl=0 @@ -130,18 +129,12 @@ AC_DEFUN([APU_CHECK_CRYPTO_OPENSSL], [ apu_have_crypto=1 AC_MSG_CHECKING([for const input buffers in OpenSSL]) - AC_TRY_COMPILE([#include <openssl/rsa.h>], - [ const unsigned char * buf; - unsigned char * outbuf; - RSA rsa; - - RSA_private_decrypt(1, - buf, - outbuf, - &rsa, - RSA_PKCS1_PADDING); - - ], + AC_TRY_COMPILE( + [#include <openssl/evp.h>], + [ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + const unsigned char key[128] = {0}, iv[128] = {0}; + EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv); + EVP_CIPHER_CTX_free(ctx); ], [AC_MSG_RESULT([yes])] [AC_DEFINE([CRYPTO_OPENSSL_CONST_BUFFERS], 1, [Define that OpenSSL uses const buffers])], [AC_MSG_RESULT([no])]) diff --git a/crypto/apr_crypto_openssl.c b/crypto/apr_crypto_openssl.c index 310bb2c7..1ee45c8d 100644 --- a/crypto/apr_crypto_openssl.c +++ b/crypto/apr_crypto_openssl.c @@ -17,6 +17,7 @@ #include "apr_lib.h" #include "apu.h" #include "apu_errno.h" +#include "apu_config.h" #include <ctype.h> #include <assert.h> @@ -30,24 +31,69 @@ #if APU_HAVE_CRYPTO +#ifndef OPENSSL_API_COMPAT +#define OPENSSL_API_COMPAT 0x10101000L /* for ENGINE API */ +#endif + #include <openssl/evp.h> #include <openssl/rand.h> #include <openssl/engine.h> +#include <openssl/opensslv.h> +#if OPENSSL_VERSION_NUMBER >= 0x30000000 +#include <openssl/macros.h> +#include <openssl/core_names.h> +#endif -#define LOG_PREFIX "apr_crypto_openssl: " - -#ifndef APR_USE_OPENSSL_PRE_1_1_API #if defined(LIBRESSL_VERSION_NUMBER) + /* LibreSSL declares OPENSSL_VERSION_NUMBER == 2.0 but does not include most * changes from OpenSSL >= 1.1 (new functions, macros, deprecations, ...), so * we have to work around this... */ -#define APR_USE_OPENSSL_PRE_1_1_API (1) +#define APR_USE_OPENSSL_PRE_1_0_API 0 +#if LIBRESSL_VERSION_NUMBER < 0x2070000f +#define APR_USE_OPENSSL_PRE_1_1_API 1 +#else +#define APR_USE_OPENSSL_PRE_1_1_API 0 +#endif +/* TODO: keep up with LibreSSL latest versions */ +#define APR_USE_OPENSSL_PRE_1_1_1_API 1 +#define APR_USE_OPENSSL_PRE_3_0_API 1 + +#else /* defined(LIBRESSL_VERSION_NUMBER) */ + +#if OPENSSL_VERSION_NUMBER < 0x10000000L +#define APR_USE_OPENSSL_PRE_1_0_API 1 #else -#define APR_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L) +#define APR_USE_OPENSSL_PRE_1_0_API 0 #endif +#if OPENSSL_VERSION_NUMBER < 0x10100000L +#define APR_USE_OPENSSL_PRE_1_1_API 1 +#else +#define APR_USE_OPENSSL_PRE_1_1_API 0 +#endif +#if OPENSSL_VERSION_NUMBER < 0x10101000L +#define APR_USE_OPENSSL_PRE_1_1_1_API 1 +#else +#define APR_USE_OPENSSL_PRE_1_1_1_API 0 +#endif +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#define APR_USE_OPENSSL_PRE_3_0_API 1 +#else +#define APR_USE_OPENSSL_PRE_3_0_API 0 +#endif + +#endif /* defined(LIBRESSL_VERSION_NUMBER) */ + +#if APR_USE_OPENSSL_PRE_3_0_API \ + || (defined(OPENSSL_API_LEVEL) && OPENSSL_API_LEVEL < 30000) +#define APR_USE_OPENSSL_ENGINE_API 1 +#else +#define APR_USE_OPENSSL_ENGINE_API 0 #endif +#define LOG_PREFIX "apr_crypto_openssl: " + struct apr_crypto_t { apr_pool_t *pool; const apr_crypto_driver_t *provider; @@ -58,7 +104,11 @@ struct apr_crypto_t { }; struct apr_crypto_config_t { +#if APR_USE_OPENSSL_ENGINE_API ENGINE *engine; +#else + void *engine; +#endif }; struct apr_crypto_key_t { @@ -113,9 +163,21 @@ static apr_status_t crypto_error(const apu_err_t **result, */ static apr_status_t crypto_shutdown(void) { +#if HAVE_OPENSSL_INIT_CRYPTO + /* Openssl v1.1+ handles all termination automatically. Do + * nothing in this case. + */ + +#else + /* Termination below is for legacy Openssl versions v1.0.x and + * older. + */ + ERR_free_strings(); EVP_cleanup(); ENGINE_cleanup(); +#endif + return APR_SUCCESS; } @@ -130,6 +192,19 @@ static apr_status_t crypto_shutdown_helper(void *data) static apr_status_t crypto_init(apr_pool_t *pool, const char *params, const apu_err_t **result) { +#if HAVE_OPENSSL_INIT_CRYPTO + /* Openssl v1.1+ handles all initialisation automatically, apart + * from hints as to how we want to use the library. + * + * We tell openssl we want to include engine support. + */ + OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_ALL_BUILTIN, NULL); + +#else + /* Configuration below is for legacy versions Openssl v1.0 and + * older. + */ + #if APR_USE_OPENSSL_PRE_1_1_API (void)CRYPTO_malloc_init(); #else @@ -140,6 +215,7 @@ static apr_status_t crypto_init(apr_pool_t *pool, const char *params, OpenSSL_add_all_algorithms(); ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); +#endif apr_pool_cleanup_register(pool, pool, crypto_shutdown_helper, apr_pool_cleanup_null); @@ -203,12 +279,13 @@ static apr_status_t crypto_block_cleanup_helper(void *data) */ static apr_status_t crypto_cleanup(apr_crypto_t *f) { - +#if APR_USE_OPENSSL_ENGINE_API if (f->config->engine) { ENGINE_finish(f->config->engine); ENGINE_free(f->config->engine); f->config->engine = NULL; } +#endif return APR_SUCCESS; } @@ -235,11 +312,10 @@ static apr_status_t crypto_make(apr_crypto_t **ff, const apr_crypto_driver_t *provider, const char *params, apr_pool_t *pool) { - apr_crypto_config_t *config = NULL; - apr_crypto_t *f = apr_pcalloc(pool, sizeof(apr_crypto_t)); - + apr_crypto_t *f; + apr_crypto_config_t *config; const char *engine = NULL; - + apr_status_t status = APR_SUCCESS; struct { const char *field; const char *value; @@ -253,7 +329,8 @@ static apr_status_t crypto_make(apr_crypto_t **ff, char **elts = NULL; char *elt; int i = 0, j; - apr_status_t status; + + *ff = NULL; if (params) { if (APR_SUCCESS != (status = apr_tokenize_to_argv(params, &elts, pool))) { @@ -287,25 +364,45 @@ static apr_status_t crypto_make(apr_crypto_t **ff, engine = fields[0].value; } + f = apr_pcalloc(pool, sizeof(apr_crypto_t)); if (!f) { return APR_ENOMEM; } - *ff = f; - f->pool = pool; - f->provider = provider; - config = f->config = apr_pcalloc(pool, sizeof(apr_crypto_config_t)); + f->config = config = apr_pcalloc(pool, sizeof(apr_crypto_config_t)); if (!config) { return APR_ENOMEM; } + f->pool = pool; + f->provider = provider; + + /* The default/builtin "openssl" engine is the same as NULL though with + * openssl-3+ it's called something else, keep NULL for that name. + */ + if (engine && strcasecmp(engine, "openssl") != 0) { +#if APR_USE_OPENSSL_ENGINE_API + config->engine = ENGINE_by_id(engine); + if (!config->engine) { + return APR_ENOENGINE; + } + if (!ENGINE_init(config->engine)) { + status = APR_EINITENGINE; + goto cleanup; + } +#else + return APR_ENOTIMPL; +#endif + } f->result = apr_pcalloc(pool, sizeof(apu_err_t)); if (!f->result) { - return APR_ENOMEM; + status = APR_ENOMEM; + goto cleanup; } f->types = apr_hash_make(pool); if (!f->types) { - return APR_ENOMEM; + status = APR_ENOMEM; + goto cleanup; } apr_hash_set(f->types, "3des192", APR_HASH_KEY_STRING, &(key_types[0])); apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[1])); @@ -314,28 +411,20 @@ static apr_status_t crypto_make(apr_crypto_t **ff, f->modes = apr_hash_make(pool); if (!f->modes) { - return APR_ENOMEM; + status = APR_ENOMEM; + goto cleanup; } apr_hash_set(f->modes, "ecb", APR_HASH_KEY_STRING, &(key_modes[0])); apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[1])); + *ff = f; apr_pool_cleanup_register(pool, f, crypto_cleanup_helper, - apr_pool_cleanup_null); - - if (engine) { - config->engine = ENGINE_by_id(engine); - if (!config->engine) { - return APR_ENOENGINE; - } - if (!ENGINE_init(config->engine)) { - ENGINE_free(config->engine); - config->engine = NULL; - return APR_EINITENGINE; - } - } - + apr_pool_cleanup_null); return APR_SUCCESS; +cleanup: + crypto_cleanup(f); + return status; } /** @@ -435,7 +524,7 @@ static apr_status_t crypto_cipher_mechanism(apr_crypto_key_t *key, return APR_ENOMEM; } apr_crypto_clear(p, key->key, key->keyLen); - + return APR_SUCCESS; } diff --git a/test/testcrypto.c b/test/testcrypto.c index 865cffc6..1fee6026 100644 --- a/test/testcrypto.c +++ b/test/testcrypto.c @@ -483,6 +483,10 @@ static void crypto_block_cross(abts_case *tc, apr_pool_t *pool, f1 = make(tc, pool, driver1); f2 = make(tc, pool, driver2); + if (!f1 || !f2) { + return; + } + key1 = passphrase(tc, pool, driver1, f1, type, mode, doPad, description); key2 = passphrase(tc, pool, driver2, f2, type, mode, doPad, description); @@ -577,6 +581,10 @@ static void test_crypto_key_openssl(abts_case *tc, void *data) driver = get_openssl_driver(tc, pool); f = make(tc, pool, driver); + if (!f) { + return; + } + keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32, "KEY_AES_256/MODE_CBC"); apr_pool_destroy(pool); @@ -596,6 +604,10 @@ static void test_crypto_key_nss(abts_case *tc, void *data) driver = get_nss_driver(tc, pool); f = make(tc, pool, driver); + if (!f) { + return; + } + keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32, "KEY_AES_256/MODE_CBC"); apr_pool_destroy(pool); @@ -615,6 +627,10 @@ static void test_crypto_key_commoncrypto(abts_case *tc, void *data) driver = get_commoncrypto_driver(tc, pool); f = make(tc, pool, driver); + if (!f) { + return; + } + keysecret(tc, pool, driver, f, APR_KEY_AES_256, APR_MODE_CBC, 1, 32, "KEY_AES_256/MODE_CBC"); apr_pool_destroy(pool); @@ -1166,6 +1182,10 @@ static void test_crypto_get_block_key_types_openssl(abts_case *tc, void *data) if (driver) { f = make(tc, pool, driver); + if (!f) { + return; + } + apr_crypto_get_block_key_types(&types, f); key_3des_192 = apr_hash_get(types, "3des192", APR_HASH_KEY_STRING); @@ -1209,6 +1229,10 @@ static void test_crypto_get_block_key_types_nss(abts_case *tc, void *data) if (driver) { f = make(tc, pool, driver); + if (!f) { + return; + } + apr_crypto_get_block_key_types(&types, f); key_3des_192 = apr_hash_get(types, "3des192", APR_HASH_KEY_STRING); @@ -1252,6 +1276,10 @@ static void test_crypto_get_block_key_types_commoncrypto(abts_case *tc, void *da if (driver) { f = make(tc, pool, driver); + if (!f) { + return; + } + apr_crypto_get_block_key_types(&types, f); key_3des_192 = apr_hash_get(types, "3des192", APR_HASH_KEY_STRING); @@ -1293,6 +1321,10 @@ static void test_crypto_get_block_key_modes_openssl(abts_case *tc, void *data) if (driver) { f = make(tc, pool, driver); + if (!f) { + return; + } + apr_crypto_get_block_key_modes(&modes, f); mode_ecb = apr_hash_get(modes, "ecb", APR_HASH_KEY_STRING); @@ -1326,6 +1358,10 @@ static void test_crypto_get_block_key_modes_nss(abts_case *tc, void *data) if (driver) { f = make(tc, pool, driver); + if (!f) { + return; + } + apr_crypto_get_block_key_modes(&modes, f); mode_ecb = apr_hash_get(modes, "ecb", APR_HASH_KEY_STRING); @@ -1359,6 +1395,10 @@ static void test_crypto_get_block_key_modes_commoncrypto(abts_case *tc, void *da if (driver) { f = make(tc, pool, driver); + if (!f) { + return; + } + apr_crypto_get_block_key_modes(&modes, f); mode_ecb = apr_hash_get(modes, "ecb", APR_HASH_KEY_STRING); |