From 56fb686e9991e2448231d21c97c9bb37555bbc7d Mon Sep 17 00:00:00 2001 From: Philip Molter Date: Thu, 10 Nov 2022 15:28:44 -0600 Subject: [PATCH] Support OpenSSL 3.0 --- encfs/SSL_Cipher.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++ encfs/openssl.cpp | 6 ++-- encfs/test.cpp | 4 +-- 3 files changed, 88 insertions(+), 5 deletions(-) diff --git a/encfs/SSL_Cipher.cpp b/encfs/SSL_Cipher.cpp index 20dee8b..5f772b7 100644 --- a/encfs/SSL_Cipher.cpp +++ b/encfs/SSL_Cipher.cpp @@ -31,6 +31,11 @@ #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#include +#endif + #include "Cipher.h" #include "Error.h" #include "Interface.h" @@ -48,6 +53,13 @@ const int MAX_KEYLENGTH = 32; // in bytes (256 bit) const int MAX_IVLENGTH = 16; // 128 bit (AES block size, Blowfish has 64) const int KEY_CHECKSUM_BYTES = 4; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +const OSSL_PARAM HMAC_PARAMS[2] = { + OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, OSSL_DIGEST_NAME_SHA1, 0), + OSSL_PARAM_construct_end() +}; +#endif + /** This produces the same result as OpenSSL's EVP_BytesToKey. The difference is that here we can explicitly specify the key size, instead of relying on @@ -159,6 +171,11 @@ static Interface BlowfishInterface("ssl/blowfish", 3, 0, 2); static Interface AESInterface("ssl/aes", 3, 0, 2); static Interface CAMELLIAInterface("ssl/camellia", 3, 0, 2); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static OSSL_PROVIDER *default_provider = NULL; +static OSSL_PROVIDER *legacy_provider = NULL; +#endif + #ifndef OPENSSL_NO_CAMELLIA static Range CAMELLIAKeyRange(128, 256, 64); @@ -207,6 +224,23 @@ static Range BFKeyRange(128, 256, 32); static Range BFBlockRange(64, 4096, 8); static std::shared_ptr NewBFCipher(const Interface &iface, int keyLen) { +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + /** + With OpenSSL 3.0, Blowfish is considered a legacy cipher. + The legacy provider is not normally loaded, and loading it + also disables the default fallback provider, so we load + them both here. + + We should also unload these providers when we finish + with them, but for encfs, that happens when the library + exits anyway. + */ + if (legacy_provider == NULL) { + default_provider = OSSL_PROVIDER_load(NULL, "default"); + legacy_provider = OSSL_PROVIDER_load(NULL, "legacy"); + } +#endif + if (keyLen <= 0) { keyLen = 160; } @@ -286,7 +320,12 @@ class SSLKey : public AbstractCipherKey { EVP_CIPHER_CTX *stream_enc; EVP_CIPHER_CTX *stream_dec; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC *evp_mac; + EVP_MAC_CTX *evp_mac_ctx; +#else HMAC_CTX *mac_ctx; +#endif SSLKey(int keySize, int ivLength); @@ -318,8 +357,14 @@ SSLKey::SSLKey(int keySize_, int ivLength_) { EVP_CIPHER_CTX_init(stream_enc); stream_dec = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(stream_dec); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + evp_mac = EVP_MAC_fetch(NULL, OSSL_MAC_NAME_HMAC, NULL); + evp_mac_ctx = EVP_MAC_CTX_new(evp_mac); +#else mac_ctx = HMAC_CTX_new(); HMAC_CTX_reset(mac_ctx); +#endif } SSLKey::~SSLKey() { @@ -336,7 +381,13 @@ SSLKey::~SSLKey() { EVP_CIPHER_CTX_free(block_dec); EVP_CIPHER_CTX_free(stream_enc); EVP_CIPHER_CTX_free(stream_dec); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_CTX_free(evp_mac_ctx); + EVP_MAC_free(evp_mac); +#else HMAC_CTX_free(mac_ctx); +#endif pthread_mutex_destroy(&mutex); } @@ -373,7 +424,11 @@ void initKey(const std::shared_ptr &key, const EVP_CIPHER *_blockCipher, EVP_EncryptInit_ex(key->stream_enc, nullptr, nullptr, KeyData(key), nullptr); EVP_DecryptInit_ex(key->stream_dec, nullptr, nullptr, KeyData(key), nullptr); +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_init(key->evp_mac_ctx, KeyData(key), _keySize, HMAC_PARAMS); +#else HMAC_Init_ex(key->mac_ctx, KeyData(key), _keySize, EVP_sha1(), nullptr); +#endif } SSL_Cipher::SSL_Cipher(const Interface &iface_, const Interface &realIface_, @@ -515,8 +570,17 @@ static uint64_t _checksum_64(SSLKey *key, const unsigned char *data, unsigned char md[EVP_MAX_MD_SIZE]; unsigned int mdLen = EVP_MAX_MD_SIZE; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#if OPENSSL_VERSION_NUMBER >= 0x30000030L + EVP_MAC_init(key->evp_mac_ctx, NULL, 0, NULL); +#else + EVP_MAC_init(key->evp_mac_ctx, key->buffer, key->keySize, HMAC_PARAMS); +#endif + EVP_MAC_update(key->evp_mac_ctx, data, dataLen); +#else HMAC_Init_ex(key->mac_ctx, nullptr, 0, nullptr, nullptr); HMAC_Update(key->mac_ctx, data, dataLen); +#endif if (chainedIV != nullptr) { // toss in the chained IV as well uint64_t tmp = *chainedIV; @@ -526,10 +590,18 @@ static uint64_t _checksum_64(SSLKey *key, const unsigned char *data, tmp >>= 8; } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_update(key->evp_mac_ctx, h, 8); +#else HMAC_Update(key->mac_ctx, h, 8); +#endif } +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + EVP_MAC_final(key->evp_mac_ctx, md, (size_t *)&mdLen, sizeof(md)); +#else HMAC_Final(key->mac_ctx, md, &mdLen); +#endif rAssert(mdLen >= 8); @@ -698,10 +770,21 @@ void SSL_Cipher::setIVec(unsigned char *ivec, uint64_t seed, } // combine ivec and seed with HMAC +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#if OPENSSL_VERSION_NUMBER >= 0x30000030L + EVP_MAC_init(key->evp_mac_ctx, NULL, 0, NULL); +#else + EVP_MAC_init(key->evp_mac_ctx, key->buffer, key->keySize, HMAC_PARAMS); +#endif + EVP_MAC_update(key->evp_mac_ctx, ivec, _ivLength); + EVP_MAC_update(key->evp_mac_ctx, md, 8); + EVP_MAC_final(key->evp_mac_ctx, md, (size_t *)&mdLen, sizeof(md)); +#else HMAC_Init_ex(key->mac_ctx, nullptr, 0, nullptr, nullptr); HMAC_Update(key->mac_ctx, ivec, _ivLength); HMAC_Update(key->mac_ctx, md, 8); HMAC_Final(key->mac_ctx, md, &mdLen); +#endif rAssert(mdLen >= _ivLength); memcpy(ivec, md, _ivLength); diff --git a/encfs/openssl.cpp b/encfs/openssl.cpp index 3b0f1b3..8411b75 100644 --- a/encfs/openssl.cpp +++ b/encfs/openssl.cpp @@ -27,7 +27,7 @@ #define NO_DES #include #include -#ifndef OPENSSL_NO_ENGINE +#if OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_ENGINE) #include #endif @@ -77,7 +77,7 @@ void openssl_init(bool threaded) { RAND_bytes((unsigned char *)&randSeed, sizeof(randSeed)); srand(randSeed); -#ifndef OPENSSL_NO_ENGINE +#if OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_ENGINE) /* Load all bundled ENGINEs into memory and make them visible */ ENGINE_load_builtin_engines(); /* Register all of them for every algorithm they collectively implement */ @@ -93,7 +93,7 @@ void openssl_init(bool threaded) { } void openssl_shutdown(bool threaded) { -#ifndef OPENSSL_NO_ENGINE +#if OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_ENGINE) ENGINE_cleanup(); #endif diff --git a/encfs/test.cpp b/encfs/test.cpp index 8da058e..f138be8 100644 --- a/encfs/test.cpp +++ b/encfs/test.cpp @@ -42,7 +42,7 @@ #define NO_DES #include -#ifndef OPENSSL_NO_ENGINE +#if OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_ENGINE) #include #endif @@ -402,7 +402,7 @@ int main(int argc, char *argv[]) { SSL_load_error_strings(); SSL_library_init(); -#ifndef OPENSSL_NO_ENGINE +#if OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(OPENSSL_NO_ENGINE) ENGINE_load_builtin_engines(); ENGINE_register_all_ciphers(); ENGINE_register_all_digests();