summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2023-03-20 18:22:56 +0000
committerylavic <ylavic@13f79535-47bb-0310-9956-ffa450edef68>2023-03-20 18:22:56 +0000
commitc6db438a960df30985c6c4de02459c8c114a1f6c (patch)
tree73c9e2a43de89ba27734e92eb1ec27a597ce42ca
parente138cf59e8a6efd8200448fcfc3e2b2172acafbd (diff)
downloadlibapr-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--CHANGES3
-rw-r--r--build/crypto.m441
-rw-r--r--crypto/apr_crypto_openssl.c155
-rw-r--r--test/testcrypto.c40
4 files changed, 182 insertions, 57 deletions
diff --git a/CHANGES b/CHANGES
index b8703dbc..a865c93b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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);