+--- httpd/httpd/trunk/modules/ssl/ssl_engine_init.c 2021/06/29 09:30:24 1891137
++++ httpd/httpd/trunk/modules/ssl/ssl_engine_init.c 2021/06/29 11:24:17 1891138
+@@ -1378,5 +1378,21 @@
+ }
+
++/* SSL_CTX_use_PrivateKey_file() can fail either because the private
++ * key was encrypted, or due to a mismatch between an already-loaded
++ * cert and the key - a common misconfiguration - from calling
++ * X509_check_private_key(). This macro is passed the last error code
++ * off the OpenSSL stack and evaluates to true only for the first
++ * case. With OpenSSL < 3 the second case is identifiable by the
++ * function code, but function codes are not used from 3.0. */
++#if OPENSSL_VERSION_NUMBER < 0x30000000L
++#define CHECK_PRIVKEY_ERROR(ec) (ERR_GET_FUNC(ec) != X509_F_X509_CHECK_PRIVATE_KEY)
++#else
++#define CHECK_PRIVKEY_ERROR(ec) (ERR_GET_LIB != ERR_LIB_X509 \
++ || (ERR_GET_REASON(ec) != X509_R_KEY_TYPE_MISMATCH \
++ && ERR_GET_REASON(ec) != X509_R_KEY_VALUES_MISMATCH \
++ && ERR_GET_REASON(ec) != X509_R_UNKNOWN_KEY_TYPE))
++#endif
++
+ static apr_status_t ssl_init_server_certs(server_rec *s,
+ apr_pool_t *p,
+ apr_pool_t *ptemp,
+@@ -1483,8 +1499,7 @@
+ }
+ else if ((SSL_CTX_use_PrivateKey_file(mctx->ssl_ctx, keyfile,
+ SSL_FILETYPE_PEM) < 1)
+- && (ERR_GET_FUNC(ERR_peek_last_error())
+- != X509_F_X509_CHECK_PRIVATE_KEY)) {
++ && CHECK_PRIVKEY_ERROR(ERR_peek_last_error())) {
+ ssl_asn1_t *asn1;
+ const unsigned char *ptr;
+