fish: enable the legacy provider if build against OpenSSL3

OpenSSL 3.0 disables a number of "legacy" algorithms by default, and we
need to enable them manually using their provider system. Note that
explicitly loading a provider will disable the implicit default
provider, which is why we need to load it explicitly.

Closes #2629

Signed-off-by: Simon Chopin <simon.chopin@canonical.com>

V2:
  * use a local OSSL_LIB_CTX to avoid leaking the legacy algorithms
    into the main SSL context.
  * Simplify the fish_init() error paths by calling fish_deinit()
This commit is contained in:
Simon Chopin 2021-11-30 13:56:56 +01:00 committed by Patrick
parent 8443755772
commit bbd60a96ec
4 changed files with 68 additions and 1 deletions

View File

@ -87,6 +87,54 @@ static const signed char fish_unbase64[256] = {
dest |= (uint8_t)*((source)++); \ dest |= (uint8_t)*((source)++); \
} while (0); } while (0);
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
#include <openssl/provider.h>
static OSSL_PROVIDER *legacy_provider;
static OSSL_PROVIDER *default_provider;
static OSSL_LIB_CTX* *ossl_ctx;
#endif
int fish_init(void)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
ossl_ctx = OSSL_LIB_CTX_new();
if (!ossl_ctx)
return 0;
legacy_provider = OSSL_PROVIDER_load(ossl_ctx, "legacy");
if (!legacy_provider) {
fish_deinit();
return 0;
}
default_provider = OSSL_PROVIDER_load(ossl_ctx, "default");
if (!default_provider) {
fish_deinit();
return 0;
}
#endif
return 1;
}
void fish_deinit(void)
{
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
if (legacy_provider) {
OSSL_PROVIDER_unload(legacy_provider);
legacy_provider = NULL;
}
if (default_provider) {
OSSL_PROVIDER_unload(default_provider);
default_provider = NULL;
}
if (ossl_ctx) {
OSSL_LIB_CTX_free(ossl_ctx);
ossl_ctx = NULL;
}
#endif
}
/** /**
* Encode ECB FiSH Base64 * Encode ECB FiSH Base64
@ -228,9 +276,19 @@ char *fish_cipher(const char *plaintext, size_t plaintext_len, const char *key,
plaintext_len -= 8; plaintext_len -= 8;
} }
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-CBC", NULL);
#else
cipher = (EVP_CIPHER *) EVP_bf_cbc(); cipher = (EVP_CIPHER *) EVP_bf_cbc();
#endif
} else if (mode == EVP_CIPH_ECB_MODE) { } else if (mode == EVP_CIPH_ECB_MODE) {
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
cipher = EVP_CIPHER_fetch(ossl_ctx, "BF-ECB", NULL);
#else
cipher = (EVP_CIPHER *) EVP_bf_ecb(); cipher = (EVP_CIPHER *) EVP_bf_ecb();
#endif
} }
/* Zero Padding */ /* Zero Padding */

View File

@ -35,6 +35,8 @@ enum fish_mode {
FISH_CBC_MODE = 0x2 FISH_CBC_MODE = 0x2
}; };
int fish_init(void);
void fish_deinit(void);
char *fish_base64_encode(const char *message, size_t message_len); char *fish_base64_encode(const char *message, size_t message_len);
char *fish_base64_decode(const char *message, size_t *final_len); char *fish_base64_decode(const char *message, size_t *final_len);
char *fish_encrypt(const char *key, size_t keylen, const char *message, size_t message_len, enum fish_mode mode); char *fish_encrypt(const char *key, size_t keylen, const char *message, size_t message_len, enum fish_mode mode);

View File

@ -815,6 +815,9 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL); hexchat_hook_server_attrs(ph, "TOPIC", HEXCHAT_PRI_NORM, handle_incoming, NULL);
hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL); hexchat_hook_server_attrs(ph, "332", HEXCHAT_PRI_NORM, handle_incoming, NULL);
if (!fish_init())
return 0;
if (!dh1080_init()) if (!dh1080_init())
return 0; return 0;
@ -828,6 +831,7 @@ int hexchat_plugin_init(hexchat_plugin *plugin_handle,
int hexchat_plugin_deinit(void) { int hexchat_plugin_deinit(void) {
g_clear_pointer(&pending_exchanges, g_hash_table_destroy); g_clear_pointer(&pending_exchanges, g_hash_table_destroy);
dh1080_deinit(); dh1080_deinit();
fish_deinit();
hexchat_printf(ph, "%s plugin unloaded\n", plugin_name); hexchat_printf(ph, "%s plugin unloaded\n", plugin_name);
return 1; return 1;

View File

@ -278,5 +278,8 @@ main(int argc, char *argv[]) {
g_test_add_func("/fishlim/max_text_command_len", test_max_text_command_len); g_test_add_func("/fishlim/max_text_command_len", test_max_text_command_len);
g_test_add_func("/fishlim/foreach_utf8_data_chunks", test_foreach_utf8_data_chunks); g_test_add_func("/fishlim/foreach_utf8_data_chunks", test_foreach_utf8_data_chunks);
return g_test_run(); fish_init();
int ret = g_test_run();
fish_deinit();
return ret;
} }