LCOV - code coverage report
Current view: top level - lib/crypt_ops - crypto_openssl_mgt.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 92 117 78.6 %
Date: 2021-11-24 03:28:48 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /* Copyright (c) 2001, Matej Pfajfar.
       2             :  * Copyright (c) 2001-2004, Roger Dingledine.
       3             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       4             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       5             : /* See LICENSE for licensing information */
       6             : 
       7             : /**
       8             :  * \file crypto_openssl_mgt.c
       9             :  *
      10             :  * \brief Block of functions related to operations from OpenSSL.
      11             :  **/
      12             : 
      13             : #include "lib/crypt_ops/compat_openssl.h"
      14             : #include "lib/crypt_ops/crypto_openssl_mgt.h"
      15             : #include "lib/crypt_ops/crypto_rand.h"
      16             : #include "lib/crypt_ops/aes.h"
      17             : #include "lib/string/util_string.h"
      18             : #include "lib/lock/compat_mutex.h"
      19             : #include "lib/log/log.h"
      20             : #include "lib/log/util_bug.h"
      21             : #include "lib/testsupport/testsupport.h"
      22             : #include "lib/thread/threads.h"
      23             : 
      24             : DISABLE_GCC_WARNING("-Wredundant-decls")
      25             : 
      26             : #include <openssl/err.h>
      27             : #include <openssl/rsa.h>
      28             : #include <openssl/pem.h>
      29             : #include <openssl/evp.h>
      30             : #include <openssl/engine.h>
      31             : #include <openssl/rand.h>
      32             : #include <openssl/bn.h>
      33             : #include <openssl/dh.h>
      34             : #include <openssl/conf.h>
      35             : #include <openssl/hmac.h>
      36             : #include <openssl/crypto.h>
      37             : #include <openssl/ssl.h>
      38             : 
      39             : ENABLE_GCC_WARNING("-Wredundant-decls")
      40             : 
      41             : #include <string.h>
      42             : 
      43             : #ifndef NEW_THREAD_API
      44             : /** A number of preallocated mutexes for use by OpenSSL. */
      45             : static tor_mutex_t **openssl_mutexes_ = NULL;
      46             : /** How many mutexes have we allocated for use by OpenSSL? */
      47             : static int n_openssl_mutexes_ = 0;
      48             : #endif /* !defined(NEW_THREAD_API) */
      49             : 
      50             : /** Declare STATIC functions */
      51             : STATIC char * parse_openssl_version_str(const char *raw_version);
      52             : #ifndef NEW_THREAD_API
      53             : STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line);
      54             : STATIC void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid);
      55             : #endif
      56             : 
      57             : /** Log all pending crypto errors at level <b>severity</b>.  Use
      58             :  * <b>doing</b> to describe our current activities.
      59             :  */
      60             : void
      61          49 : crypto_openssl_log_errors(int severity, const char *doing)
      62             : {
      63          49 :   unsigned long err;
      64          49 :   const char *msg, *lib, *func;
      65          95 :   while ((err = ERR_get_error()) != 0) {
      66          46 :     msg = (const char*)ERR_reason_error_string(err);
      67          46 :     lib = (const char*)ERR_lib_error_string(err);
      68          46 :     func = (const char*)ERR_func_error_string(err);
      69          46 :     if (!msg) msg = "(null)";
      70          46 :     if (!lib) lib = "(null)";
      71          46 :     if (!func) func = "(null)";
      72          46 :     if (BUG(!doing)) doing = "(null)";
      73          46 :     tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
      74             :               doing, msg, lib, func);
      75             :   }
      76          49 : }
      77             : 
      78             : /* Returns a trimmed and human-readable version of an openssl version string
      79             : * <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
      80             : * May 2012' and this will parse them into a form similar to '1.0.0b' */
      81             : STATIC char *
      82        5562 : parse_openssl_version_str(const char *raw_version)
      83             : {
      84        5562 :   const char *end_of_version = NULL;
      85             :   /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
      86             :      trim that down. */
      87        5562 :   if (!strcmpstart(raw_version, "OpenSSL ")) {
      88        5562 :     raw_version += strlen("OpenSSL ");
      89        5562 :     end_of_version = strchr(raw_version, ' ');
      90             :   }
      91             : 
      92        5562 :   if (end_of_version)
      93        5562 :     return tor_strndup(raw_version,
      94             :                       end_of_version-raw_version);
      95             :   else
      96           0 :     return tor_strdup(raw_version);
      97             : }
      98             : 
      99             : static char *crypto_openssl_version_str = NULL;
     100             : /* Return a human-readable version of the run-time openssl version number. */
     101             : const char *
     102        5797 : crypto_openssl_get_version_str(void)
     103             : {
     104             : #ifdef OPENSSL_VERSION
     105        5797 :   const int query = OPENSSL_VERSION;
     106             : #else
     107             :   /* This old name was changed around OpenSSL 1.1.0 */
     108             :   const int query = SSLEAY_VERSION;
     109             : #endif /* defined(OPENSSL_VERSION) */
     110             : 
     111        5797 :   if (crypto_openssl_version_str == NULL) {
     112        5561 :     const char *raw_version = OpenSSL_version(query);
     113        5561 :     crypto_openssl_version_str = parse_openssl_version_str(raw_version);
     114             :   }
     115        5797 :   return crypto_openssl_version_str;
     116             : }
     117             : 
     118             : #undef QUERY_OPENSSL_VERSION
     119             : 
     120             : static char *crypto_openssl_header_version_str = NULL;
     121             : /* Return a human-readable version of the compile-time openssl version
     122             : * number. */
     123             : const char *
     124           1 : crypto_openssl_get_header_version_str(void)
     125             : {
     126           1 :   if (crypto_openssl_header_version_str == NULL) {
     127           1 :     crypto_openssl_header_version_str =
     128           1 :                         parse_openssl_version_str(OPENSSL_VERSION_TEXT);
     129             :   }
     130           1 :   return crypto_openssl_header_version_str;
     131             : }
     132             : 
     133             : #ifndef COCCI
     134             : #ifndef OPENSSL_THREADS
     135             : #error "OpenSSL has been built without thread support. Tor requires an \
     136             :  OpenSSL library with thread support enabled."
     137             : #endif
     138             : #endif /* !defined(COCCI) */
     139             : 
     140             : #ifndef NEW_THREAD_API
     141             : /** Helper: OpenSSL uses this callback to manipulate mutexes. */
     142             : STATIC void
     143             : openssl_locking_cb_(int mode, int n, const char *file, int line)
     144             : {
     145             :   (void)file;
     146             :   (void)line;
     147             :   if (!openssl_mutexes_)
     148             :     /* This is not a really good fix for the
     149             :      * "release-freed-lock-from-separate-thread-on-shutdown" problem, but
     150             :      * it can't hurt. */
     151             :     return;
     152             :   if (mode & CRYPTO_LOCK)
     153             :     tor_mutex_acquire(openssl_mutexes_[n]);
     154             :   else
     155             :     tor_mutex_release(openssl_mutexes_[n]);
     156             : }
     157             : 
     158             : STATIC void
     159             : tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
     160             : {
     161             :   CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
     162             : }
     163             : #endif /* !defined(NEW_THREAD_API) */
     164             : 
     165             : /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
     166             :  * multithreaded. Returns 0. */
     167             : static int
     168             : setup_openssl_threading(void)
     169             : {
     170             : #ifndef NEW_THREAD_API
     171             :   int i;
     172             :   int n = CRYPTO_num_locks();
     173             :   n_openssl_mutexes_ = n;
     174             :   openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
     175             :   for (i=0; i < n; ++i)
     176             :     openssl_mutexes_[i] = tor_mutex_new();
     177             :   CRYPTO_set_locking_callback(openssl_locking_cb_);
     178             :   CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
     179             : #endif /* !defined(NEW_THREAD_API) */
     180             :   return 0;
     181             : }
     182             : 
     183             : /** free OpenSSL variables */
     184             : static void
     185         235 : crypto_openssl_free_all(void)
     186             : {
     187         235 :   tor_free(crypto_openssl_version_str);
     188         235 :   tor_free(crypto_openssl_header_version_str);
     189             : 
     190             :   /* Destroying a locked mutex is undefined behaviour. This mutex may be
     191             :    * locked, because multiple threads can access it. But we need to destroy
     192             :    * it, otherwise re-initialisation will trigger undefined behaviour.
     193             :    * See #31735 for details. */
     194             : #ifndef NEW_THREAD_API
     195             :   if (n_openssl_mutexes_) {
     196             :     int n = n_openssl_mutexes_;
     197             :     tor_mutex_t **ms = openssl_mutexes_;
     198             :     int i;
     199             :     openssl_mutexes_ = NULL;
     200             :     n_openssl_mutexes_ = 0;
     201             :     for (i=0;i<n;++i) {
     202             :       tor_mutex_free(ms[i]);
     203             :     }
     204             :     tor_free(ms);
     205             :   }
     206             : #endif /* !defined(NEW_THREAD_API) */
     207         235 : }
     208             : 
     209             : /** Perform early (pre-configuration) initialization tasks for OpenSSL. */
     210             : void
     211        5561 : crypto_openssl_early_init(void)
     212             : {
     213             : #ifdef OPENSSL_1_1_API
     214        5561 :     OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
     215             :                      OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
     216             :                      OPENSSL_INIT_ADD_ALL_CIPHERS |
     217             :                      OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
     218             : #else /* !defined(OPENSSL_1_1_API) */
     219             :     ERR_load_crypto_strings();
     220             :     OpenSSL_add_all_algorithms();
     221             : #endif /* defined(OPENSSL_1_1_API) */
     222             : 
     223        5561 :     setup_openssl_threading();
     224             : 
     225        5561 :     unsigned long version_num = tor_OpenSSL_version_num();
     226        5561 :     const char *version_str = crypto_openssl_get_version_str();
     227        5561 :     if (version_num == OPENSSL_VERSION_NUMBER &&
     228        5561 :         !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
     229           0 :       log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
     230             :                  "(%lx: %s).", version_num, version_str);
     231        5561 :     } else if ((version_num & 0xffff0000) ==
     232             :                (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
     233        5561 :       log_notice(LD_CRYPTO,
     234             :                "We compiled with OpenSSL %lx: %s and we "
     235             :                "are running with OpenSSL %lx: %s. "
     236             :                "These two versions should be binary compatible.",
     237             :                (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
     238             :                version_num, version_str);
     239             :     } else {
     240           0 :       log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
     241             :                "version we're running with. If you get weird crashes, that "
     242             :                "might be why. (Compiled with %lx: %s; running with %lx: %s).",
     243             :                (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
     244             :                version_num, version_str);
     245             :     }
     246             : 
     247        5561 :     crypto_force_rand_ssleay();
     248        5561 : }
     249             : 
     250             : #ifndef DISABLE_ENGINES
     251             : /** Try to load an engine in a shared library via fully qualified path.
     252             :  */
     253             : static ENGINE *
     254           0 : try_load_engine(const char *path, const char *engine)
     255             : {
     256           0 :   ENGINE *e = ENGINE_by_id("dynamic");
     257           0 :   if (e) {
     258           0 :     if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
     259           0 :         !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
     260           0 :         !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
     261           0 :         !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
     262           0 :       ENGINE_free(e);
     263           0 :       e = NULL;
     264             :     }
     265             :   }
     266           0 :   return e;
     267             : }
     268             : #endif /* !defined(DISABLE_ENGINES) */
     269             : 
     270             : #ifndef DISABLE_ENGINES
     271             : /** Log any OpenSSL engines we're using at NOTICE. */
     272             : static void
     273         130 : log_engine(const char *fn, ENGINE *e)
     274             : {
     275         130 :   if (e) {
     276           0 :     const char *name, *id;
     277           0 :     name = ENGINE_get_name(e);
     278           0 :     id = ENGINE_get_id(e);
     279           0 :     log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
     280             :                fn, name?name:"?", id?id:"?");
     281             :   } else {
     282         130 :     log_info(LD_CRYPTO, "Using default implementation for %s", fn);
     283             :   }
     284         130 : }
     285             : #endif /* !defined(DISABLE_ENGINES) */
     286             : 
     287             : /** Initialize engines for openssl (if enabled).  Load all the built-in
     288             :  * engines, along with the one called <b>accelName</b> (which may be NULL).
     289             :  * If <b>accelName</b> is prefixed with "!", then it is required: return -1
     290             :  * if it can't be loaded.  Otherwise return 0.
     291             :  *
     292             :  * If <b>accelDir</b> is not NULL, it is the path from which the engine should
     293             :  * be loaded. */
     294             : static int
     295          11 : crypto_openssl_init_engines(const char *accelName,
     296             :                             const char *accelDir)
     297             : {
     298             : #ifdef DISABLE_ENGINES
     299             :   (void)accelName;
     300             :   (void)accelDir;
     301             :   log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
     302             :   if (accelName && accelName[0] == '!') {
     303             :     log_warn(LD_CRYPTO, "Unable to load required dynamic OpenSSL engine "
     304             :              "\"%s\".", accelName+1);
     305             :     return -1;
     306             :   }
     307             :   return 0;
     308             : #else /* !defined(DISABLE_ENGINES) */
     309          11 :   ENGINE *e = NULL;
     310             : 
     311          11 :   log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
     312          11 :   ENGINE_load_builtin_engines();
     313          11 :   ENGINE_register_all_complete();
     314             : 
     315          11 :   if (accelName) {
     316           4 :     const bool required = accelName[0] == '!';
     317           4 :     if (required)
     318           1 :       ++accelName;
     319           4 :     if (accelDir) {
     320           0 :       log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
     321             :                " via path \"%s\".", accelName, accelDir);
     322           0 :       e = try_load_engine(accelName, accelDir);
     323             :     } else {
     324           4 :       log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
     325             :                " acceleration support.", accelName);
     326           4 :       e = ENGINE_by_id(accelName);
     327             :     }
     328           4 :     if (!e) {
     329           7 :       log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
     330             :                required?"required ":"",
     331             :                accelName);
     332           4 :       if (required)
     333             :         return -1;
     334             :     } else {
     335           0 :       log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
     336             :                accelName);
     337             :     }
     338             :   }
     339           3 :   if (e) {
     340           0 :     log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
     341             :              " setting default ciphers.");
     342           0 :     ENGINE_set_default(e, ENGINE_METHOD_ALL);
     343             :   }
     344             :   /* Log, if available, the intersection of the set of algorithms
     345             :      used by Tor and the set of algorithms available in the engine */
     346          10 :   log_engine("RSA", ENGINE_get_default_RSA());
     347          10 :   log_engine("DH", ENGINE_get_default_DH());
     348             : #ifdef OPENSSL_1_1_API
     349          10 :   log_engine("EC", ENGINE_get_default_EC());
     350             : #else
     351             :   log_engine("ECDH", ENGINE_get_default_ECDH());
     352             :   log_engine("ECDSA", ENGINE_get_default_ECDSA());
     353             : #endif /* defined(OPENSSL_1_1_API) */
     354          10 :   log_engine("RAND", ENGINE_get_default_RAND());
     355          10 :   log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
     356          10 :   log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
     357          10 :   log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
     358          10 :   log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
     359          10 :   log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
     360             : #ifdef NID_aes_128_ctr
     361          10 :   log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
     362             : #endif
     363             : #ifdef NID_aes_128_gcm
     364          10 :   log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
     365             : #endif
     366          10 :   log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
     367             : #ifdef NID_aes_256_gcm
     368          10 :   log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
     369             : #endif
     370          10 :   return 0;
     371             : 
     372             : #endif /* defined(DISABLE_ENGINES) */
     373             : }
     374             : 
     375             : /** Perform late (post-init) initialization tasks for OpenSSL */
     376             : int
     377        5528 : crypto_openssl_late_init(int useAccel, const char *accelName,
     378             :                          const char *accelDir)
     379             : {
     380        5528 :   if (useAccel > 0) {
     381          11 :     if (crypto_openssl_init_engines(accelName, accelDir) < 0)
     382             :       return -1;
     383             :   } else {
     384        5517 :     log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
     385             :   }
     386             : 
     387        5527 :   if (crypto_force_rand_ssleay()) {
     388           0 :     if (crypto_seed_rng() < 0)
     389             :       return -1;
     390             :   }
     391             : 
     392        5527 :   evaluate_evp_for_aes(-1);
     393        5527 :   evaluate_ctr_for_aes();
     394             : 
     395        5527 :   return 0;
     396             : }
     397             : 
     398             : /** Free crypto resources held by this thread. */
     399             : void
     400           0 : crypto_openssl_thread_cleanup(void)
     401             : {
     402             : #ifndef NEW_THREAD_API
     403             :   ERR_remove_thread_state(NULL);
     404             : #endif
     405           0 : }
     406             : 
     407             : /** Clean up global resources held by openssl. */
     408             : void
     409         235 : crypto_openssl_global_cleanup(void)
     410             : {
     411             : #ifndef OPENSSL_1_1_API
     412             :   EVP_cleanup();
     413             : #endif
     414             : #ifndef NEW_THREAD_API
     415             :   ERR_remove_thread_state(NULL);
     416             : #endif
     417             : #ifndef OPENSSL_1_1_API
     418             :   ERR_free_strings();
     419             : #endif
     420             : 
     421             : #ifndef DISABLE_ENGINES
     422             : #ifndef OPENSSL_1_1_API
     423             :   ENGINE_cleanup();
     424             : #endif
     425             : #endif
     426             : 
     427         235 :   CONF_modules_unload(1);
     428             : #ifndef OPENSSL_1_1_API
     429             :   CRYPTO_cleanup_all_ex_data();
     430             : #endif
     431             : 
     432         235 :   crypto_openssl_free_all();
     433         235 : }

Generated by: LCOV version 1.14