OpenSSL: Unload providers only at process exit

The previous mechanism of unloaded the providers from tls_deinit() did
not work correctly for some cases. In particular, it was possible for
hostapd to end up unloading both providers and not being able to recover
from this if TLS server was not enabled.

Address this more cleanly by introducing a new crypto_unload() function
that will be called when the process is exiting.

Fixes: 097ca6bf0b ("OpenSSL: Unload providers on deinit")
Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2022-04-16 18:48:29 +03:00
parent 33c4dd26cd
commit f5c711c855
14 changed files with 58 additions and 4 deletions

View file

@ -15,6 +15,7 @@
#include "utils/common.h"
#include "utils/eloop.h"
#include "utils/uuid.h"
#include "crypto/crypto.h"
#include "crypto/random.h"
#include "crypto/tls.h"
#include "common/version.h"
@ -933,6 +934,7 @@ int main(int argc, char *argv[])
fst_global_deinit();
crypto_unload();
os_program_deinit();
return ret;

View file

@ -1275,4 +1275,12 @@ struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
struct crypto_ec_key *key,
enum crypto_hash_alg algo);
/**
* crypto_unload - Unload crypto resources
*
* This function is called just before the process exits to allow dynamic
* resource allocations to be freed.
*/
void crypto_unload(void);
#endif /* CRYPTO_H */

View file

@ -504,3 +504,8 @@ void crypto_cipher_deinit(struct crypto_cipher *ctx)
gcry_cipher_close(ctx->dec);
os_free(ctx);
}
void crypto_unload(void)
{
}

View file

@ -326,3 +326,8 @@ int crypto_global_init(void)
void crypto_global_deinit(void)
{
}
void crypto_unload(void)
{
}

View file

@ -766,3 +766,8 @@ fail:
}
#endif /* CONFIG_MODEXP */
void crypto_unload(void)
{
}

View file

@ -1007,3 +1007,8 @@ int crypto_global_init(void)
void crypto_global_deinit(void)
{
}
void crypto_unload(void)
{
}

View file

@ -467,3 +467,8 @@ void crypto_cipher_deinit(struct crypto_cipher *ctx)
{
bin_clear_free(ctx, sizeof(*ctx));
}
void crypto_unload(void)
{
}

View file

@ -22,3 +22,8 @@ int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
{
return 0;
}
void crypto_unload(void)
{
}

View file

@ -152,7 +152,7 @@ void openssl_load_legacy_provider(void)
}
void openssl_unload_legacy_provider(void)
static void openssl_unload_legacy_provider(void)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (openssl_legacy_provider) {
@ -3797,3 +3797,9 @@ struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
}
#endif /* CONFIG_ECC */
void crypto_unload(void)
{
openssl_unload_legacy_provider();
}

View file

@ -1823,3 +1823,8 @@ size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
}
#endif /* CONFIG_ECC */
void crypto_unload(void)
{
}

View file

@ -1128,8 +1128,6 @@ void tls_deinit(void *ssl_ctx)
tls_openssl_ref_count--;
if (tls_openssl_ref_count == 0) {
void openssl_unload_legacy_provider(void);
#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
(defined(LIBRESSL_VERSION_NUMBER) && \
LIBRESSL_VERSION_NUMBER < 0x20700000L)
@ -1145,7 +1143,6 @@ void tls_deinit(void *ssl_ctx)
tls_global->ocsp_stapling_response = NULL;
os_free(tls_global);
tls_global = NULL;
openssl_unload_legacy_provider();
}
os_free(data->check_cert_subject);

View file

@ -15,6 +15,7 @@
#include "common.h"
#include "utils/ext_password.h"
#include "common/version.h"
#include "crypto/crypto.h"
#include "crypto/tls.h"
#include "config.h"
#include "eapol_supp/eapol_supp_sm.h"
@ -1549,6 +1550,7 @@ int main(int argc, char *argv[])
else
printf("SUCCESS\n");
crypto_unload();
os_program_deinit();
return ret;

View file

@ -12,6 +12,7 @@
#endif /* __linux__ */
#include "common.h"
#include "crypto/crypto.h"
#include "fst/fst.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
@ -403,6 +404,7 @@ out:
#endif /* CONFIG_MATCH_IFACE */
os_free(params.pid_file);
crypto_unload();
os_program_deinit();
return exitcode;

View file

@ -13,6 +13,7 @@
#include <assert.h>
#include "common.h"
#include "crypto/crypto.h"
#include "config.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "eloop.h"
@ -365,6 +366,7 @@ int main(int argc, char *argv[])
eloop_destroy();
crypto_unload();
os_program_deinit();
return ret;