You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by yl...@apache.org on 2023/03/20 17:12:45 UTC

svn commit: r1908581 - in /apr/apr-util/branches/1.7.x: ./ build/crypto.m4 crypto/ crypto/apr_crypto_openssl.c test/testcrypto.c

Author: ylavic
Date: Mon Mar 20 17:12:44 2023
New Revision: 1908581

URL: http://svn.apache.org/viewvc?rev=1908581&view=rev
Log:
apr_crypto_openssl: Compatibility with OpenSSL 3+


crypto: Follow up to r1908433: Fix EVP_MAC usage w/ openssl < 3.0.


crypto: Follow up to r1908433: streamline cleanups.

The crypto_*_init() functions can be called multiple times with the returned
structure already allocated/initialized, or not. So rather than cleaning up
after each operation (which was removed in r1908433 but is now leaky), let's
instead either allocate+register or cleanup existing structure in _init().


crypto: Follow up to r1908433: OPENSSL_API_COMPAT to 1.1.1.


crypto_openssl: Fix configure/detection of OPENSSL_init_crypto()


Merges r1908433, r1908448, r1908453, r1908455, r1908503 from ^/apr/apr/trunk.
Submitted by: ylavic

Modified:
    apr/apr-util/branches/1.7.x/   (props changed)
    apr/apr-util/branches/1.7.x/build/crypto.m4
    apr/apr-util/branches/1.7.x/crypto/   (props changed)
    apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c
    apr/apr-util/branches/1.7.x/test/testcrypto.c

Propchange: apr/apr-util/branches/1.7.x/
------------------------------------------------------------------------------
  Merged /apr/apr/trunk:r1908433,1908448,1908453,1908455,1908503

Modified: apr/apr-util/branches/1.7.x/build/crypto.m4
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/build/crypto.m4?rev=1908581&r1=1908580&r2=1908581&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/build/crypto.m4 (original)
+++ apr/apr-util/branches/1.7.x/build/crypto.m4 Mon Mar 20 17:12:44 2023
@@ -54,11 +54,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
@@ -97,15 +97,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, openssl_have_libs=1)
-      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])
@@ -113,15 +112,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, openssl_have_libs=1)
-      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, OPENSSL_init_crypto], [], [],
-                     [#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
@@ -136,18 +135,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])])

Propchange: apr/apr-util/branches/1.7.x/crypto/
------------------------------------------------------------------------------
  Merged /apr/apr/trunk/crypto:r1908433,1908448,1908453,1908455,1908503

Modified: apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c?rev=1908581&r1=1908580&r2=1908581&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c (original)
+++ apr/apr-util/branches/1.7.x/crypto/apr_crypto_openssl.c Mon Mar 20 17:12:44 2023
@@ -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,29 +31,70 @@
 
 #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/obj_mac.h> /* for NID_* */
+#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_1_1_API (1)
-#define APR_USE_OPENSSL_PRE_1_0_API (0)
-#else
-#define APR_USE_OPENSSL_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L)
-#define APR_USE_OPENSSL_PRE_1_1_1_API (OPENSSL_VERSION_NUMBER < 0x10101000L)
-#define APR_USE_OPENSSL_PRE_1_0_API (OPENSSL_VERSION_NUMBER < 0x10000000L)
+#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_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;
@@ -64,7 +106,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 {
@@ -73,8 +119,11 @@ struct apr_crypto_key_t {
     const apr_crypto_t *f;
     const apr_crypto_key_rec_t *rec;
     const EVP_CIPHER *cipher;
-    const EVP_MD *hmac;
+    const EVP_MD *md;
     EVP_PKEY *pkey;
+#if !APR_USE_OPENSSL_PRE_3_0_API
+    EVP_MAC *mac;
+#endif
     unsigned char *key;
     int keyLen;
     int doPad;
@@ -87,7 +136,6 @@ struct apr_crypto_block_t {
     const apr_crypto_t *f;
     const apr_crypto_key_t *key;
     EVP_CIPHER_CTX *cipherCtx;
-    int initialised;
     int ivSize;
     int blockSize;
     int doPad;
@@ -100,7 +148,9 @@ struct apr_crypto_digest_t {
     const apr_crypto_key_t *key;
     apr_crypto_digest_rec_t *rec;
     EVP_MD_CTX *mdCtx;
-    int initialised;
+#if !APR_USE_OPENSSL_PRE_3_0_API
+    EVP_MAC_CTX *macCtx;
+#endif
     int digestSize;
 };
 
@@ -148,7 +198,7 @@ static apr_status_t crypto_error(const a
  */
 static apr_status_t crypto_shutdown(void)
 {
-#if HAVE_DECL_OPENSSL_INIT_CRYPTO
+#if HAVE_OPENSSL_INIT_CRYPTO
     /* Openssl v1.1+ handles all termination automatically. Do
      * nothing in this case.
      */
@@ -177,7 +227,7 @@ static apr_status_t crypto_shutdown_help
 static apr_status_t crypto_init(apr_pool_t *pool, const char *params,
         const apu_err_t **result)
 {
-#if HAVE_DECL_OPENSSL_INIT_CRYPTO
+#if HAVE_OPENSSL_INIT_CRYPTO
     /* Openssl v1.1+ handles all initialisation automatically, apart
      * from hints as to how we want to use the library.
      *
@@ -246,7 +296,14 @@ static apr_status_t crypto_key_cleanup(a
 {
     if (key->pkey) {
         EVP_PKEY_free(key->pkey);
+        key->pkey = NULL;
+    }
+#if !APR_USE_OPENSSL_PRE_3_0_API
+    if (key->mac) {
+        EVP_MAC_free(key->mac);
+        key->mac = NULL;
     }
+#endif
 
     return APR_SUCCESS;
 }
@@ -266,17 +323,14 @@ static apr_status_t crypto_key_cleanup_h
 static apr_status_t crypto_block_cleanup(apr_crypto_block_t *ctx)
 {
 
-    if (ctx->initialised) {
-        if (ctx->cipherCtx) {
+    if (ctx->cipherCtx) {
 #if APR_USE_OPENSSL_PRE_1_1_API
-            EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
+        EVP_CIPHER_CTX_cleanup(ctx->cipherCtx);
 #else
-            EVP_CIPHER_CTX_reset(ctx->cipherCtx);
-            EVP_CIPHER_CTX_free(ctx->cipherCtx);
+        EVP_CIPHER_CTX_reset(ctx->cipherCtx);
+        EVP_CIPHER_CTX_free(ctx->cipherCtx);
 #endif
-            ctx->cipherCtx = NULL;
-        }
-        ctx->initialised = 0;
+        ctx->cipherCtx = NULL;
     }
 
     return APR_SUCCESS;
@@ -297,14 +351,16 @@ static apr_status_t crypto_block_cleanup
  */
 static apr_status_t crypto_digest_cleanup(apr_crypto_digest_t *ctx)
 {
-
-    if (ctx->initialised) {
-        if (ctx->mdCtx) {
-            EVP_MD_CTX_free(ctx->mdCtx);
-            ctx->mdCtx = NULL;
-        }
-        ctx->initialised = 0;
+    if (ctx->mdCtx) {
+        EVP_MD_CTX_free(ctx->mdCtx);
+        ctx->mdCtx = NULL;
+    }
+#if !APR_USE_OPENSSL_PRE_3_0_API
+    if (ctx->macCtx) {
+        EVP_MAC_CTX_free(ctx->macCtx);
+        ctx->macCtx = NULL;
     }
+#endif
 
     return APR_SUCCESS;
 
@@ -324,12 +380,13 @@ static apr_status_t crypto_digest_cleanu
  */
 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;
 
 }
@@ -356,11 +413,10 @@ static apr_status_t crypto_make(apr_cryp
         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;
@@ -374,7 +430,8 @@ static apr_status_t crypto_make(apr_cryp
     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))) {
@@ -408,25 +465,45 @@ static apr_status_t crypto_make(apr_cryp
         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->digests = apr_hash_make(pool);
     if (!f->digests) {
-        return APR_ENOMEM;
+        status = APR_ENOMEM;
+        goto cleanup;
     }
     apr_hash_set(f->digests, "md5", APR_HASH_KEY_STRING, &(key_digests[i = 0]));
     apr_hash_set(f->digests, "sha1", APR_HASH_KEY_STRING, &(key_digests[++i]));
@@ -437,7 +514,8 @@ static apr_status_t crypto_make(apr_cryp
 
     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[i = 0]));
     apr_hash_set(f->types, "aes128", APR_HASH_KEY_STRING, &(key_types[++i]));
@@ -446,33 +524,26 @@ static apr_status_t crypto_make(apr_cryp
 
     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[i = 0]));
     apr_hash_set(f->modes, "cbc", APR_HASH_KEY_STRING, &(key_modes[++i]));
 
     f->digests = apr_hash_make(pool);
     if (!f->digests) {
-        return APR_ENOMEM;
+        status = APR_ENOMEM;
+        goto cleanup;
     }
 
+    *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;
 }
 
 /**
@@ -586,7 +657,6 @@ static apr_status_t crypto_cipher_mechan
     if (!key->key) {
         return APR_ENOMEM;
     }
-    apr_crypto_clear(p, key->key, key->keyLen);
 
     return APR_SUCCESS;
 }
@@ -618,11 +688,12 @@ static apr_status_t crypto_key(apr_crypt
         if (!key) {
             return APR_ENOMEM;
         }
+        apr_pool_cleanup_register(p, key, crypto_key_cleanup_helper,
+                                  apr_pool_cleanup_null);
+    }
+    else {
+        crypto_key_cleanup(key);
     }
-
-    apr_pool_cleanup_register(p, key, crypto_key_cleanup_helper,
-            apr_pool_cleanup_null);
-
     key->pool = p;
     key->f = f;
     key->provider = f->provider;
@@ -672,22 +743,22 @@ static apr_status_t crypto_key(apr_crypt
 
         switch (rec->k.hash.digest) {
         case APR_CRYPTO_DIGEST_MD5:
-            key->hmac = EVP_md5();
+            key->md = EVP_md5();
             break;
         case APR_CRYPTO_DIGEST_SHA1:
-            key->hmac = EVP_sha1();
+            key->md = EVP_sha1();
             break;
         case APR_CRYPTO_DIGEST_SHA224:
-            key->hmac = EVP_sha224();
+            key->md = EVP_sha224();
             break;
         case APR_CRYPTO_DIGEST_SHA256:
-            key->hmac = EVP_sha256();
+            key->md = EVP_sha256();
             break;
         case APR_CRYPTO_DIGEST_SHA384:
-            key->hmac = EVP_sha384();
+            key->md = EVP_sha384();
             break;
         case APR_CRYPTO_DIGEST_SHA512:
-            key->hmac = EVP_sha512();
+            key->md = EVP_sha512();
             break;
         default:
             return APR_ENODIGEST;
@@ -695,84 +766,70 @@ static apr_status_t crypto_key(apr_crypt
 
         break;
     }
-    case APR_CRYPTO_KTYPE_HMAC: {
-
-        apr_crypto_config_t *config = f->config;
-
-        /* create hmac key */
-        if (!(key->pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, config->engine,
-                rec->k.hmac.secret, rec->k.hmac.secretLen))) {
-            return APR_ENOKEY;
-        }
+    case APR_CRYPTO_KTYPE_HMAC:
+    case APR_CRYPTO_KTYPE_CMAC: {
 
         switch (rec->k.hmac.digest) {
         case APR_CRYPTO_DIGEST_MD5:
-            key->hmac = EVP_md5();
+            key->md = EVP_md5();
             break;
         case APR_CRYPTO_DIGEST_SHA1:
-            key->hmac = EVP_sha1();
+            key->md = EVP_sha1();
             break;
         case APR_CRYPTO_DIGEST_SHA224:
-            key->hmac = EVP_sha224();
+            key->md = EVP_sha224();
             break;
         case APR_CRYPTO_DIGEST_SHA256:
-            key->hmac = EVP_sha256();
+            key->md = EVP_sha256();
             break;
         case APR_CRYPTO_DIGEST_SHA384:
-            key->hmac = EVP_sha384();
+            key->md = EVP_sha384();
             break;
         case APR_CRYPTO_DIGEST_SHA512:
-            key->hmac = EVP_sha512();
+            key->md = EVP_sha512();
             break;
         default:
             return APR_ENODIGEST;
         }
 
-        break;
-    }
-
-    case APR_CRYPTO_KTYPE_CMAC: {
-
+        /* create hmac key */
+#if APR_USE_OPENSSL_PRE_3_0_API
+        if (rec->ktype == APR_CRYPTO_KTYPE_HMAC) {
+            apr_crypto_config_t *config = f->config;
+            key->pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC,
+                                             config->engine,
+                                             rec->k.hmac.secret,
+                                             rec->k.hmac.secretLen);
+        }
+        else {
 #if !APR_USE_OPENSSL_PRE_1_1_1_API
-        apr_crypto_config_t *config = f->config;
-
-        /* decide on what cipher mechanism we will be using */
-        rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
-        if (APR_SUCCESS != rv) {
-            return rv;
+            apr_crypto_config_t *config = f->config;
+            /* decide on what cipher mechanism we will be using */
+            rv = crypto_cipher_mechanism(key, rec->type, rec->mode, rec->pad, p);
+            if (APR_SUCCESS != rv) {
+                return rv;
+            }
+            key->pkey = EVP_PKEY_new_CMAC_key(config->engine,
+                                              rec->k.cmac.secret,
+                                              rec->k.cmac.secretLen,
+                                              key->cipher);
+#else
+            return APR_ENOTIMPL;
+#endif
         }
-
-        /* create cmac key */
-        if (!(key->pkey = EVP_PKEY_new_CMAC_key(config->engine,
-                rec->k.cmac.secret, rec->k.cmac.secretLen, key->cipher))) {
+        if (!key->pkey) {
             return APR_ENOKEY;
         }
-
-        switch (rec->k.hmac.digest) {
-        case APR_CRYPTO_DIGEST_MD5:
-            key->hmac = EVP_md5();
-            break;
-        case APR_CRYPTO_DIGEST_SHA1:
-            key->hmac = EVP_sha1();
-            break;
-        case APR_CRYPTO_DIGEST_SHA224:
-            key->hmac = EVP_sha224();
-            break;
-        case APR_CRYPTO_DIGEST_SHA256:
-            key->hmac = EVP_sha256();
-            break;
-        case APR_CRYPTO_DIGEST_SHA384:
-            key->hmac = EVP_sha384();
-            break;
-        case APR_CRYPTO_DIGEST_SHA512:
-            key->hmac = EVP_sha512();
-            break;
-        default:
-            return APR_ENODIGEST;
-        }
-
 #else
-        return APR_ENOTIMPL;
+        if (rec->ktype == APR_CRYPTO_KTYPE_HMAC) {
+            key->mac = EVP_MAC_fetch(NULL, "HMAC", NULL);
+        }
+        else {
+            key->mac = EVP_MAC_fetch(NULL, "CMAC", NULL);
+        }
+        if (!key->mac) {
+            return APR_ENOMEM;
+        }
 #endif
 
         break;
@@ -900,29 +957,34 @@ static apr_status_t crypto_block_encrypt
     unsigned char *usedIv;
     apr_crypto_config_t *config = key->f->config;
     apr_crypto_block_t *block = *ctx;
+
     if (!block) {
         *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+        if (!block) {
+            return APR_ENOMEM;
+        }
+        apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+                                  apr_pool_cleanup_null);
     }
-    if (!block) {
-        return APR_ENOMEM;
+    else {
+        crypto_block_cleanup(block);
     }
     block->f = key->f;
     block->pool = p;
     block->provider = key->provider;
     block->key = key;
 
-    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
-            apr_pool_cleanup_null);
-
     switch (key->rec->ktype) {
 
     case APR_CRYPTO_KTYPE_PASSPHRASE:
     case APR_CRYPTO_KTYPE_SECRET: {
 
         /* create a new context for encryption */
-        if (!block->initialised) {
+        if (!block->cipherCtx) {
             block->cipherCtx = EVP_CIPHER_CTX_new();
-            block->initialised = 1;
+            if (!block->cipherCtx) {
+                return APR_ENOMEM;
+            }
         }
 
         /* generate an IV, if necessary */
@@ -936,7 +998,6 @@ static apr_status_t crypto_block_encrypt
                 if (!usedIv) {
                     return APR_ENOMEM;
                 }
-                apr_crypto_clear(p, usedIv, key->ivSize);
                 if (!((RAND_status() == 1)
                         && (RAND_bytes(usedIv, key->ivSize) == 1))) {
                     return APR_ENOIV;
@@ -953,7 +1014,8 @@ static apr_status_t crypto_block_encrypt
         if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine,
                 key->key, usedIv)) {
 #else
-        if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) usedIv)) {
+        if (!EVP_EncryptInit_ex(block->cipherCtx, key->cipher, config->engine,
+                                (unsigned char *) key->key, (unsigned char *) usedIv)) {
 #endif
             return APR_EINIT;
         }
@@ -1017,11 +1079,10 @@ static apr_status_t crypto_block_encrypt
 
         /* must we allocate the output buffer from a pool? */
         if (!*out) {
-            buffer = apr_palloc(block->pool, inlen + EVP_MAX_BLOCK_LENGTH);
+            buffer = apr_pcalloc(block->pool, inlen + EVP_MAX_BLOCK_LENGTH);
             if (!buffer) {
                 return APR_ENOMEM;
             }
-            apr_crypto_clear(block->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
             *out = buffer;
         }
 
@@ -1031,7 +1092,6 @@ static apr_status_t crypto_block_encrypt
         if (!EVP_EncryptUpdate(block->cipherCtx, (*out), &outl,
                 (unsigned char *) in, inlen)) {
 #endif
-            crypto_block_cleanup(block);
             return APR_ECRYPT;
         }
         *outlen = outl;
@@ -1083,7 +1143,6 @@ static apr_status_t crypto_block_encrypt
         else {
             *outlen = len;
         }
-        crypto_block_cleanup(block);
 
         return rc;
 
@@ -1118,29 +1177,34 @@ static apr_status_t crypto_block_decrypt
 {
     apr_crypto_config_t *config = key->f->config;
     apr_crypto_block_t *block = *ctx;
+
     if (!block) {
         *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
+        if (!block) {
+            return APR_ENOMEM;
+        }
+        apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
+                                  apr_pool_cleanup_null);
     }
-    if (!block) {
-        return APR_ENOMEM;
+    else {
+        crypto_block_cleanup(block);
     }
     block->f = key->f;
     block->pool = p;
     block->provider = key->provider;
     block->key = key;
 
-    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
-            apr_pool_cleanup_null);
-
     switch (key->rec->ktype) {
 
     case APR_CRYPTO_KTYPE_PASSPHRASE:
     case APR_CRYPTO_KTYPE_SECRET: {
 
         /* create a new context for encryption */
-        if (!block->initialised) {
+        if (!block->cipherCtx) {
             block->cipherCtx = EVP_CIPHER_CTX_new();
-            block->initialised = 1;
+            if (!block->cipherCtx) {
+                return APR_ENOMEM;
+            }
         }
 
         /* generate an IV, if necessary */
@@ -1155,7 +1219,8 @@ static apr_status_t crypto_block_decrypt
         if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine,
                 key->key, iv)) {
 #else
-            if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) {
+            if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine,
+                                    (unsigned char *) key->key, (unsigned char *) iv)) {
 #endif
             return APR_EINIT;
         }
@@ -1219,11 +1284,10 @@ static apr_status_t crypto_block_decrypt
 
         /* must we allocate the output buffer from a pool? */
         if (!(*out)) {
-            buffer = apr_palloc(block->pool, inlen + EVP_MAX_BLOCK_LENGTH);
+            buffer = apr_pcalloc(block->pool, inlen + EVP_MAX_BLOCK_LENGTH);
             if (!buffer) {
                 return APR_ENOMEM;
             }
-            apr_crypto_clear(block->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH);
             *out = buffer;
         }
 
@@ -1233,8 +1297,6 @@ static apr_status_t crypto_block_decrypt
         if (!EVP_DecryptUpdate(block->cipherCtx, *out, &outl, (unsigned char *) in,
                 inlen)) {
 #endif
-            crypto_block_cleanup(block);
-
             return APR_ECRYPT;
         }
         *outlen = outl;
@@ -1286,7 +1348,6 @@ static apr_status_t crypto_block_decrypt
         else {
             *outlen = len;
         }
-        crypto_block_cleanup(block);
 
         return rc;
 
@@ -1305,11 +1366,17 @@ static apr_status_t crypto_digest_init(a
 {
     apr_crypto_config_t *config = key->f->config;
     apr_crypto_digest_t *digest = *d;
+
     if (!digest) {
         *d = digest = apr_pcalloc(p, sizeof(apr_crypto_digest_t));
+        if (!digest) {
+            return APR_ENOMEM;
+        }
+        apr_pool_cleanup_register(p, digest, crypto_digest_cleanup_helper,
+                                  apr_pool_cleanup_null);
     }
-    if (!digest) {
-        return APR_ENOMEM;
+    else {
+        crypto_digest_cleanup(digest);
     }
     digest->f = key->f;
     digest->pool = p;
@@ -1317,22 +1384,16 @@ static apr_status_t crypto_digest_init(a
     digest->key = key;
     digest->rec = rec;
 
-    /* create a new context for digest */
-    if (!digest->initialised) {
-        digest->mdCtx = EVP_MD_CTX_new();
-        digest->initialised = 1;
-    }
-
-    apr_pool_cleanup_register(p, digest, crypto_digest_cleanup_helper,
-            apr_pool_cleanup_null);
-
     switch (key->rec->ktype) {
 
     case APR_CRYPTO_KTYPE_HASH: {
-
-        if (1
-                != EVP_DigestInit_ex(digest->mdCtx, key->hmac,
-                        config->engine)) {
+        if (!digest->mdCtx) {
+            digest->mdCtx = EVP_MD_CTX_new();
+            if (!digest->mdCtx) {
+                return APR_ENOMEM;
+            }
+        }
+        if (!EVP_DigestInit_ex(digest->mdCtx, key->md, config->engine)) {
             return APR_EINIT;
         }
 
@@ -1340,11 +1401,45 @@ static apr_status_t crypto_digest_init(a
     }
     case APR_CRYPTO_KTYPE_HMAC:
     case APR_CRYPTO_KTYPE_CMAC: {
-        if (1
-                != EVP_DigestSignInit(digest->mdCtx, NULL, key->hmac,
-                        config->engine, key->pkey)) {
+#if APR_USE_OPENSSL_PRE_3_0_API
+        if (!digest->mdCtx) {
+            digest->mdCtx = EVP_MD_CTX_new();
+            if (!digest->mdCtx) {
+                return APR_ENOMEM;
+            }
+        }
+        if (!EVP_DigestSignInit(digest->mdCtx, NULL, key->md,
+                                config->engine, key->pkey)) {
             return APR_EINIT;
         }
+#else
+        OSSL_PARAM params[2];
+        if (!digest->macCtx) {
+            digest->macCtx = EVP_MAC_CTX_new(key->mac);
+            if (!digest->macCtx) {
+                return APR_ENOMEM;
+            }
+        }
+        if (key->rec->ktype == APR_CRYPTO_KTYPE_HMAC) {
+            params[0] =
+                OSSL_PARAM_construct_utf8_string("digest",
+                                                 (char *)EVP_MD_name(key->md),
+                                                 0);
+        }
+        else {
+            params[0] =
+                OSSL_PARAM_construct_utf8_string("cipher",
+                                                 (char *)EVP_CIPHER_name(key->cipher),
+                                                 0);
+        }
+        params[1] = OSSL_PARAM_construct_end();
+        if (!EVP_MAC_init(digest->macCtx,
+                          key->rec->k.hmac.secret,
+                          key->rec->k.hmac.secretLen,
+                          params)) {
+            return APR_EINIT;
+        }
+#endif
         break;
     }
     default: {
@@ -1362,23 +1457,24 @@ static apr_status_t crypto_digest_update
     switch (digest->key->rec->ktype) {
 
     case APR_CRYPTO_KTYPE_HASH: {
-
-        if (1 != EVP_DigestUpdate(digest->mdCtx, in, inlen)) {
-            crypto_digest_cleanup(digest);
+        if (!EVP_DigestUpdate(digest->mdCtx, in, inlen)) {
             return APR_ECRYPT;
         }
 
         return APR_SUCCESS;
 
     }
-
     case APR_CRYPTO_KTYPE_HMAC:
     case APR_CRYPTO_KTYPE_CMAC: {
-
-        if (1 != EVP_DigestSignUpdate(digest->mdCtx, in, inlen)) {
-            crypto_digest_cleanup(digest);
+#if APR_USE_OPENSSL_PRE_3_0_API
+        if (!EVP_DigestSignUpdate(digest->mdCtx, in, inlen)) {
             return APR_ECRYPT;
         }
+#else
+        if (!EVP_MAC_update(digest->macCtx, in, inlen)) {
+            return APR_ECRYPT;
+        }
+#endif
 
         return APR_SUCCESS;
 
@@ -1392,31 +1488,29 @@ static apr_status_t crypto_digest_update
 
 static apr_status_t crypto_digest_final(apr_crypto_digest_t *digest)
 {
+    apr_status_t status = APR_SUCCESS;
 
     switch (digest->key->rec->ktype) {
 
     case APR_CRYPTO_KTYPE_HASH: {
-
-        apr_status_t status = APR_SUCCESS;
-
-        unsigned int len = EVP_MD_CTX_size(digest->mdCtx);
-
         switch (digest->rec->dtype) {
         case APR_CRYPTO_DTYPE_HASH: {
+            unsigned int len = EVP_MD_CTX_size(digest->mdCtx);
 
             /* must we allocate the output buffer from a pool? */
             if (!digest->rec->d.hash.s || digest->rec->d.hash.slen != len) {
                 digest->rec->d.hash.slen = len;
-                digest->rec->d.hash.s = apr_palloc(digest->pool, len);
+                digest->rec->d.hash.s = apr_pcalloc(digest->pool, len);
                 if (!digest->rec->d.hash.s) {
                     return APR_ENOMEM;
                 }
-                apr_crypto_clear(digest->pool, digest->rec->d.hash.s, len);
             }
 
             /* then, determine the signature */
             if (EVP_DigestFinal_ex(digest->mdCtx, digest->rec->d.hash.s, &len)
                     == 0) {
+                OPENSSL_cleanse(digest->rec->d.hash.s,
+                                digest->rec->d.hash.slen);
                 status = APR_ECRYPT;
             }
 
@@ -1426,92 +1520,101 @@ static apr_status_t crypto_digest_final(
             status = APR_ENODIGEST;
         }
 
-        crypto_digest_cleanup(digest);
-
-        return status;
-
+        break;
     }
-
     case APR_CRYPTO_KTYPE_HMAC:
     case APR_CRYPTO_KTYPE_CMAC: {
-
-        apr_status_t status = APR_SUCCESS;
-
         size_t len;
 
         /* first, determine the signature length */
-        if (1 != EVP_DigestSignFinal(digest->mdCtx, NULL, &len)) {
+#if APR_USE_OPENSSL_PRE_3_0_API
+        if (!EVP_DigestSignFinal(digest->mdCtx, NULL, &len)) {
             status = APR_ECRYPT;
-        } else {
-
+        }
+#else
+        if (!EVP_MAC_final(digest->macCtx, NULL, &len, 0)) {
+            status = APR_ECRYPT;
+        }
+#endif
+        if (status == APR_SUCCESS) {
             switch (digest->rec->dtype) {
             case APR_CRYPTO_DTYPE_SIGN: {
-
                 /* must we allocate the output buffer from a pool? */
                 if (!digest->rec->d.sign.s || digest->rec->d.sign.slen != len) {
                     digest->rec->d.sign.slen = len;
-                    digest->rec->d.sign.s = apr_palloc(digest->pool, len);
+                    digest->rec->d.sign.s = apr_pcalloc(digest->pool, len);
                     if (!digest->rec->d.sign.s) {
                         return APR_ENOMEM;
                     }
-                    apr_crypto_clear(digest->pool, digest->rec->d.sign.s, len);
                 }
 
                 /* then, determine the signature */
-                if (EVP_DigestSignFinal(digest->mdCtx, digest->rec->d.sign.s,
-                        &len) == 0) {
+#if APR_USE_OPENSSL_PRE_3_0_API
+                if (!EVP_DigestSignFinal(digest->mdCtx,
+                                         digest->rec->d.sign.s, &len)) {
+                    status = APR_ECRYPT;
+                }
+#else
+                if (!EVP_MAC_final(digest->macCtx,
+                                   digest->rec->d.sign.s, &len, len)) {
                     status = APR_ECRYPT;
                 }
+#endif
+                if (status != APR_SUCCESS) {
+                    OPENSSL_cleanse(digest->rec->d.sign.s,
+                                    digest->rec->d.sign.slen);
+                }
 
                 break;
             }
             case APR_CRYPTO_DTYPE_VERIFY: {
-
                 /* must we allocate the output buffer from a pool? */
                 if (!digest->rec->d.verify.s
                         || digest->rec->d.verify.slen != len) {
                     digest->rec->d.verify.slen = len;
-                    digest->rec->d.verify.s = apr_palloc(digest->pool, len);
+                    digest->rec->d.verify.s = apr_pcalloc(digest->pool, len);
                     if (!digest->rec->d.verify.s) {
                         return APR_ENOMEM;
                     }
-                    apr_crypto_clear(digest->pool, digest->rec->d.verify.s,
-                            len);
                 }
 
                 /* then, determine the signature */
-                if (EVP_DigestSignFinal(digest->mdCtx, digest->rec->d.verify.s,
-                        &len) == 0) {
+#if APR_USE_OPENSSL_PRE_3_0_API
+                if (!EVP_DigestSignFinal(digest->mdCtx,
+                                         digest->rec->d.verify.s, &len)) {
                     status = APR_ECRYPT;
-                } else if (digest->rec->d.verify.slen
-                        == digest->rec->d.verify.vlen) {
-                    status =
-                            CRYPTO_memcmp(digest->rec->d.verify.s,
-                                    digest->rec->d.verify.v,
-                                    digest->rec->d.verify.slen) ?
-                            APR_ENOVERIFY : APR_SUCCESS;
-                } else {
+                }
+#else
+                if (!EVP_MAC_final(digest->macCtx,
+                                   digest->rec->d.verify.s, &len, len)) {
+                    status = APR_ECRYPT;
+                }
+#endif
+                if (status == APR_SUCCESS
+                    && (len != digest->rec->d.verify.vlen
+                        || CRYPTO_memcmp(digest->rec->d.verify.v,
+                                         digest->rec->d.verify.s, len))) {
                     status = APR_ENOVERIFY;
                 }
+                if (status != APR_SUCCESS) {
+                    OPENSSL_cleanse(digest->rec->d.verify.s,
+                                    digest->rec->d.verify.slen);
+                }
 
                 break;
             }
             default:
                 status = APR_ENODIGEST;
             }
-
         }
 
-        crypto_digest_cleanup(digest);
-
-        return status;
-
-    }
-    default: {
-        return APR_EINVAL;
+        break;
     }
+    default:
+        status = APR_EINVAL;
     }
 
+    return status;
 }
 
 static apr_status_t crypto_digest(

Modified: apr/apr-util/branches/1.7.x/test/testcrypto.c
URL: http://svn.apache.org/viewvc/apr/apr-util/branches/1.7.x/test/testcrypto.c?rev=1908581&r1=1908580&r2=1908581&view=diff
==============================================================================
--- apr/apr-util/branches/1.7.x/test/testcrypto.c (original)
+++ apr/apr-util/branches/1.7.x/test/testcrypto.c Mon Mar 20 17:12:44 2023
@@ -878,6 +878,10 @@ static void crypto_block_cross(abts_case
 
     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);
 
@@ -973,6 +977,9 @@ static void crypto_cross_hash(abts_case
 
     f1 = make(tc, pool, driver1);
     f2 = make(tc, pool, driver2);
+    if (!f1 || !f2) {
+        return;
+    }
 
     key7 = keyhash(tc, pool, driver1, f1, digest, description);
     key8 = keyhash(tc, pool, driver2, f2, digest, description);
@@ -1038,6 +1045,9 @@ static void crypto_cross_sign(abts_case
 
     f1 = make(tc, pool, driver1);
     f2 = make(tc, pool, driver2);
+    if (!f1 || !f2) {
+        return;
+    }
 
     key7 = keyhmac(tc, pool, driver1, f1, digest, type, mode, doPad, secretLen,
             description);
@@ -1096,6 +1106,10 @@ static void test_crypto_key_openssl(abts
     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);
@@ -1115,6 +1129,10 @@ static void test_crypto_key_nss(abts_cas
     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);
@@ -1134,6 +1152,10 @@ static void test_crypto_key_commoncrypto
     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);
@@ -2080,6 +2102,10 @@ static void test_crypto_get_block_key_ty
     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);
@@ -2123,6 +2149,10 @@ static void test_crypto_get_block_key_ty
     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);
@@ -2166,6 +2196,10 @@ static void test_crypto_get_block_key_ty
     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);
@@ -2207,6 +2241,10 @@ static void test_crypto_get_block_key_mo
     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);
@@ -2240,6 +2278,10 @@ static void test_crypto_get_block_key_mo
     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);
@@ -2273,6 +2315,10 @@ static void test_crypto_get_block_key_mo
     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);