From: Nick Mathewson Date: Sun, 18 May 2025 14:34:43 +0000 (-0400) Subject: Remove AES support for old OpenSSLs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e95181096ff485a63f7714a1158467b8a3a8316e;p=thirdparty%2Ftor.git Remove AES support for old OpenSSLs --- diff --git a/src/lib/crypt_ops/aes.h b/src/lib/crypt_ops/aes.h index cee14b1838..da79d7bcbd 100644 --- a/src/lib/crypt_ops/aes.h +++ b/src/lib/crypt_ops/aes.h @@ -29,9 +29,6 @@ void aes_cipher_free_(aes_cnt_cipher_t *cipher); FREE_AND_NULL(aes_cnt_cipher_t, aes_cipher_free_, (cipher)) void aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len); -int evaluate_evp_for_aes(int force_value); -int evaluate_ctr_for_aes(void); - #ifdef USE_AES_RAW typedef struct aes_raw_t aes_raw_t; diff --git a/src/lib/crypt_ops/aes_nss.c b/src/lib/crypt_ops/aes_nss.c index ab72c12fe1..a3266e5bf4 100644 --- a/src/lib/crypt_ops/aes_nss.c +++ b/src/lib/crypt_ops/aes_nss.c @@ -141,19 +141,6 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data_, size_t len_) tor_assert(result_len == len); } -int -evaluate_evp_for_aes(int force_value) -{ - (void)force_value; - return 0; -} - -int -evaluate_ctr_for_aes(void) -{ - return 0; -} - aes_raw_t * aes_raw_new(const uint8_t *key, int key_bits, bool encrypt) { diff --git a/src/lib/crypt_ops/aes_openssl.c b/src/lib/crypt_ops/aes_openssl.c index 270712be87..fd481b8758 100644 --- a/src/lib/crypt_ops/aes_openssl.c +++ b/src/lib/crypt_ops/aes_openssl.c @@ -41,37 +41,6 @@ ENABLE_GCC_WARNING("-Wredundant-decls") #include "lib/log/log.h" #include "lib/ctime/di_ops.h" -#ifdef OPENSSL_NO_ENGINE -/* Android's OpenSSL seems to have removed all of its Engine support. */ -#define DISABLE_ENGINES -#endif - -/* We have five strategies for implementing AES counter mode. - * - * Best with x86 and x86_64: Use EVP_aes_*_ctr() and EVP_EncryptUpdate(). - * This is possible with OpenSSL 1.0.1, where the counter-mode implementation - * can use bit-sliced or vectorized AES or AESNI as appropriate. - * - * Otherwise: Pick the best possible AES block implementation that OpenSSL - * gives us, and the best possible counter-mode implementation, and combine - * them. - */ -#if OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0) - -/* With newer OpenSSL versions, the older fallback modes don't compile. So - * don't use them, even if we lack specific acceleration. */ - -#define USE_EVP_AES_CTR - -#elif OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,0,1) && \ - (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64) || defined(__x86_64__) || \ - defined(_M_AMD64) || defined(_M_X64) || defined(__INTEL__)) - -#define USE_EVP_AES_CTR - -#endif /* OPENSSL_VERSION_NUMBER >= OPENSSL_V_NOPATCH(1,1,0) || ... */ - /* Cached values of our EVP_CIPHER items. If we don't pre-fetch them, * then EVP_CipherInit calls EVP_CIPHER_fetch itself, * which is surprisingly expensive. @@ -129,8 +98,6 @@ init_ciphers(void) * make sure that we have a fixed version.) */ -#ifdef USE_EVP_AES_CTR - /* We don't actually define the struct here. */ aes_cnt_cipher_t * @@ -206,253 +173,6 @@ aes_crypt_inplace(aes_cnt_cipher_t *cipher_, char *data, size_t len) EVP_EncryptUpdate(cipher, (unsigned char*)data, &outl, (unsigned char*)data, (int)len); } -int -evaluate_evp_for_aes(int force_val) -{ - (void) force_val; - log_info(LD_CRYPTO, "This version of OpenSSL has a known-good EVP " - "counter-mode implementation. Using it."); - return 0; -} -int -evaluate_ctr_for_aes(void) -{ - return 0; -} -#else /* !defined(USE_EVP_AES_CTR) */ - -/*======================================================================*/ -/* Interface to AES code, and counter implementation */ - -/** Implements an AES counter-mode cipher. */ -struct aes_cnt_cipher_t { -/** This next element (however it's defined) is the AES key. */ - union { - EVP_CIPHER_CTX evp; - AES_KEY aes; - } key; - -#if !defined(WORDS_BIGENDIAN) -#define USING_COUNTER_VARS - /** These four values, together, implement a 128-bit counter, with - * counter0 as the low-order word and counter3 as the high-order word. */ - uint32_t counter3; - uint32_t counter2; - uint32_t counter1; - uint32_t counter0; -#endif /* !defined(WORDS_BIGENDIAN) */ - - union { - /** The counter, in big-endian order, as bytes. */ - uint8_t buf[16]; - /** The counter, in big-endian order, as big-endian words. Note that - * on big-endian platforms, this is redundant with counter3...0, - * so we just use these values instead. */ - uint32_t buf32[4]; - } ctr_buf; - - /** The encrypted value of ctr_buf. */ - uint8_t buf[16]; - /** Our current stream position within buf. */ - unsigned int pos; - - /** True iff we're using the evp implementation of this cipher. */ - uint8_t using_evp; -}; - -/** True iff we should prefer the EVP implementation for AES, either because - * we're testing it or because we have hardware acceleration configured */ -static int should_use_EVP = 0; - -/** Check whether we should use the EVP interface for AES. If force_val - * is nonnegative, we use use EVP iff it is true. Otherwise, we use EVP - * if there is an engine enabled for aes-ecb. */ -int -evaluate_evp_for_aes(int force_val) -{ - ENGINE *e; - - if (force_val >= 0) { - should_use_EVP = force_val; - return 0; - } -#ifdef DISABLE_ENGINES - should_use_EVP = 0; -#else - e = ENGINE_get_cipher_engine(NID_aes_128_ecb); - - if (e) { - log_info(LD_CRYPTO, "AES engine \"%s\" found; using EVP_* functions.", - ENGINE_get_name(e)); - should_use_EVP = 1; - } else { - log_info(LD_CRYPTO, "No AES engine found; using AES_* functions."); - should_use_EVP = 0; - } -#endif /* defined(DISABLE_ENGINES) */ - - return 0; -} - -/** Test the OpenSSL counter mode implementation to see whether it has the - * counter-mode bug from OpenSSL 1.0.0. If the implementation works, then - * we will use it for future encryption/decryption operations. - * - * We can't just look at the OpenSSL version, since some distributions update - * their OpenSSL packages without changing the version number. - **/ -int -evaluate_ctr_for_aes(void) -{ - /* Result of encrypting an all-zero block with an all-zero 128-bit AES key. - * This should be the same as encrypting an all-zero block with an all-zero - * 128-bit AES key in counter mode, starting at position 0 of the stream. - */ - static const unsigned char encrypt_zero[] = - "\x66\xe9\x4b\xd4\xef\x8a\x2c\x3b\x88\x4c\xfa\x59\xca\x34\x2b\x2e"; - unsigned char zero[16]; - unsigned char output[16]; - unsigned char ivec[16]; - unsigned char ivec_tmp[16]; - unsigned int pos, i; - AES_KEY key; - memset(zero, 0, sizeof(zero)); - memset(ivec, 0, sizeof(ivec)); - AES_set_encrypt_key(zero, 128, &key); - - pos = 0; - /* Encrypting a block one byte at a time should make the error manifest - * itself for known bogus openssl versions. */ - for (i=0; i<16; ++i) - AES_ctr128_encrypt(&zero[i], &output[i], 1, &key, ivec, ivec_tmp, &pos); - - if (fast_memneq(output, encrypt_zero, 16)) { - /* Counter mode is buggy */ - /* LCOV_EXCL_START */ - log_err(LD_CRYPTO, "This OpenSSL has a buggy version of counter mode; " - "quitting tor."); - exit(1); // exit ok: openssl is broken. - /* LCOV_EXCL_STOP */ - } - return 0; -} - -#if !defined(USING_COUNTER_VARS) -#define COUNTER(c, n) ((c)->ctr_buf.buf32[3-(n)]) -#else -#define COUNTER(c, n) ((c)->counter ## n) -#endif - -static void aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key, - int key_bits); -static void aes_set_iv(aes_cnt_cipher_t *cipher, const uint8_t *iv); - -/** - * Return a newly allocated counter-mode AES128 cipher implementation, - * using the 128-bit key key and the 128-bit IV iv. - */ -aes_cnt_cipher_t* -aes_new_cipher(const uint8_t *key, const uint8_t *iv, int bits) -{ - aes_cnt_cipher_t* result = tor_malloc_zero(sizeof(aes_cnt_cipher_t)); - - aes_set_key(result, key, bits); - aes_set_iv(result, iv); - - return result; -} - -/** Set the key of cipher to key, which is - * key_bits bits long (must be 128, 192, or 256). Also resets - * the counter to 0. - */ -static void -aes_set_key(aes_cnt_cipher_t *cipher, const uint8_t *key, int key_bits) -{ - if (should_use_EVP) { - const EVP_CIPHER *c = 0; - switch (key_bits) { - case 128: c = aes128ecb; break; - case 192: c = aes192ecb; break; - case 256: c = aes256ecb; break; - default: tor_assert(0); // LCOV_EXCL_LINE - } - EVP_EncryptInit(&cipher->key.evp, c, key, NULL); - cipher->using_evp = 1; - } else { - AES_set_encrypt_key(key, key_bits,&cipher->key.aes); - cipher->using_evp = 0; - } - -#ifdef USING_COUNTER_VARS - cipher->counter0 = 0; - cipher->counter1 = 0; - cipher->counter2 = 0; - cipher->counter3 = 0; -#endif /* defined(USING_COUNTER_VARS) */ - - memset(cipher->ctr_buf.buf, 0, sizeof(cipher->ctr_buf.buf)); - - cipher->pos = 0; - - memset(cipher->buf, 0, sizeof(cipher->buf)); -} - -/** Release storage held by cipher - */ -void -aes_cipher_free_(aes_cnt_cipher_t *cipher) -{ - if (!cipher) - return; - if (cipher->using_evp) { - EVP_CIPHER_CTX_cleanup(&cipher->key.evp); - } - memwipe(cipher, 0, sizeof(aes_cnt_cipher_t)); - tor_free(cipher); -} - -#if defined(USING_COUNTER_VARS) -#define UPDATE_CTR_BUF(c, n) STMT_BEGIN \ - (c)->ctr_buf.buf32[3-(n)] = htonl((c)->counter ## n); \ - STMT_END -#else -#define UPDATE_CTR_BUF(c, n) -#endif /* defined(USING_COUNTER_VARS) */ - -/** Encrypt len bytes from input, storing the results in place. - * Uses the key in cipher, and advances the counter by len bytes - * as it encrypts. - */ -void -aes_crypt_inplace(aes_cnt_cipher_t *cipher, char *data, size_t len) -{ - /* Note that the "128" below refers to the length of the counter, - * not the length of the AES key. */ - if (cipher->using_evp) { - /* In openssl 1.0.0, there's an if'd out EVP_aes_128_ctr in evp.h. If - * it weren't disabled, it might be better just to use that. - */ - CRYPTO_ctr128_encrypt((const unsigned char *)data, - (unsigned char *)data, - len, - &cipher->key.evp, - cipher->ctr_buf.buf, - cipher->buf, - &cipher->pos, - evp_block128_fn); - } else { - AES_ctr128_encrypt((const unsigned char *)data, - (unsigned char *)data, - len, - &cipher->key.aes, - cipher->ctr_buf.buf, - cipher->buf, - &cipher->pos); - } -} - -#endif /* defined(USE_EVP_AES_CTR) */ /* ======== * Functions for "raw" (ECB) AES. diff --git a/src/lib/crypt_ops/crypto_openssl_mgt.c b/src/lib/crypt_ops/crypto_openssl_mgt.c index 426283f47a..b89167a5ec 100644 --- a/src/lib/crypt_ops/crypto_openssl_mgt.c +++ b/src/lib/crypt_ops/crypto_openssl_mgt.c @@ -323,9 +323,6 @@ crypto_openssl_late_init(int useAccel, const char *accelName, return -1; } - evaluate_evp_for_aes(-1); - evaluate_ctr_for_aes(); - return 0; } diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 1281545e29..700c9679f9 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -259,14 +259,12 @@ test_crypto_openssl_version(void *arg) static void test_crypto_aes128(void *arg) { + (void)arg; char *data1 = NULL, *data2 = NULL, *data3 = NULL; crypto_cipher_t *env1 = NULL, *env2 = NULL; int i, j; char *mem_op_hex_tmp=NULL; char key[CIPHER_KEY_LEN]; - int use_evp = !strcmp(arg,"evp"); - evaluate_evp_for_aes(use_evp); - evaluate_ctr_for_aes(); data1 = tor_malloc(1024); data2 = tor_malloc(1024); @@ -1634,14 +1632,12 @@ test_crypto_formats(void *arg) static void test_crypto_aes_iv(void *arg) { + (void)arg; char *plain, *encrypted1, *encrypted2, *decrypted1, *decrypted2; char plain_1[1], plain_15[15], plain_16[16], plain_17[17]; char key1[16], key2[16]; ssize_t encrypted_size, decrypted_size; - int use_evp = !strcmp(arg,"evp"); - evaluate_evp_for_aes(use_evp); - plain = tor_malloc(4095); encrypted1 = tor_malloc(4095 + 1 + 16); encrypted2 = tor_malloc(4095 + 1 + 16); @@ -3454,8 +3450,7 @@ test_crypto_aes_cnt_set_iv(void *arg) struct testcase_t crypto_tests[] = { CRYPTO_LEGACY(formats), { "openssl_version", test_crypto_openssl_version, TT_FORK, NULL, NULL }, - { "aes_AES", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"aes" }, - { "aes_EVP", test_crypto_aes128, TT_FORK, &passthrough_setup, (void*)"evp" }, + { "aes_AES", test_crypto_aes128, TT_FORK, NULL, NULL }, { "aes128_ctr_testvec", test_crypto_aes_ctr_testvec, 0, &passthrough_setup, (void*)"128" }, { "aes192_ctr_testvec", test_crypto_aes_ctr_testvec, 0, @@ -3476,10 +3471,7 @@ struct testcase_t crypto_tests[] = { { "sha3_xof", test_crypto_sha3_xof, TT_FORK, NULL, NULL}, { "mac_sha3", test_crypto_mac_sha3, TT_FORK, NULL, NULL}, CRYPTO_LEGACY(dh), - { "aes_iv_AES", test_crypto_aes_iv, TT_FORK, &passthrough_setup, - (void*)"aes" }, - { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, &passthrough_setup, - (void*)"evp" }, + { "aes_iv_EVP", test_crypto_aes_iv, TT_FORK, NULL, NULL }, CRYPTO_LEGACY(base32_decode), { "kdf_TAP", test_crypto_kdf_TAP, 0, NULL, NULL }, { "hkdf_sha256", test_crypto_hkdf_sha256, 0, NULL, NULL },