--- a/modules/ssl/ssl_engine_init.c 2025-11-06 03:09:18.000000000 -0600 +++ b/modules/ssl/ssl_engine_init.c 2026-04-24 00:30:48.000000000 -0500 @@ -1475,6 +1475,22 @@ && ERR_GET_REASON(ec) != X509_R_UNKNOWN_KEY_TYPE)) #endif +/* 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,