tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

crypto_openssl_mgt.c (10861B)


      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 #ifdef OPENSSL_NO_ENGINE
     44 /* Android's OpenSSL seems to have removed all of its Engine support. */
     45 #define DISABLE_ENGINES
     46 #endif
     47 
     48 /** Declare STATIC functions */
     49 STATIC char * parse_openssl_version_str(const char *raw_version);
     50 
     51 /** Log all pending crypto errors at level <b>severity</b>.  Use
     52 * <b>doing</b> to describe our current activities.
     53 */
     54 void
     55 crypto_openssl_log_errors(int severity, const char *doing)
     56 {
     57  unsigned long err;
     58  const char *msg, *lib, *func;
     59  while ((err = ERR_get_error()) != 0) {
     60    msg = (const char*)ERR_reason_error_string(err);
     61    lib = (const char*)ERR_lib_error_string(err);
     62    func = (const char*)ERR_func_error_string(err);
     63    if (!msg) msg = "(null)";
     64    if (!lib) lib = "(null)";
     65    if (!func) func = "(null)";
     66    if (BUG(!doing)) doing = "(null)";
     67    tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
     68              doing, msg, lib, func);
     69  }
     70 }
     71 
     72 /* Returns a trimmed and human-readable version of an openssl version string
     73 * <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
     74 * May 2012' and this will parse them into a form similar to '1.0.0b' */
     75 STATIC char *
     76 parse_openssl_version_str(const char *raw_version)
     77 {
     78  const char *end_of_version = NULL;
     79  /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
     80     trim that down. */
     81  if (!strcmpstart(raw_version, "OpenSSL ")) {
     82    raw_version += strlen("OpenSSL ");
     83    end_of_version = strchr(raw_version, ' ');
     84  }
     85 
     86  if (end_of_version)
     87    return tor_strndup(raw_version,
     88                      end_of_version-raw_version);
     89  else
     90    return tor_strdup(raw_version);
     91 }
     92 
     93 static char *crypto_openssl_version_str = NULL;
     94 /* Return a human-readable version of the run-time openssl version number. */
     95 const char *
     96 crypto_openssl_get_version_str(void)
     97 {
     98  const int query = OPENSSL_VERSION;
     99 
    100  if (crypto_openssl_version_str == NULL) {
    101    const char *raw_version = OpenSSL_version(query);
    102    crypto_openssl_version_str = parse_openssl_version_str(raw_version);
    103  }
    104  return crypto_openssl_version_str;
    105 }
    106 
    107 static char *crypto_openssl_header_version_str = NULL;
    108 /* Return a human-readable version of the compile-time openssl version
    109 * number. */
    110 const char *
    111 crypto_openssl_get_header_version_str(void)
    112 {
    113  if (crypto_openssl_header_version_str == NULL) {
    114    crypto_openssl_header_version_str =
    115                        parse_openssl_version_str(OPENSSL_VERSION_TEXT);
    116  }
    117  return crypto_openssl_header_version_str;
    118 }
    119 
    120 #ifndef COCCI
    121 #ifndef OPENSSL_THREADS
    122 #error "OpenSSL has been built without thread support. Tor requires an \
    123 OpenSSL library with thread support enabled."
    124 #endif
    125 #endif /* !defined(COCCI) */
    126 
    127 /** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
    128 * multithreaded. Returns 0. */
    129 static int
    130 setup_openssl_threading(void)
    131 {
    132  return 0;
    133 }
    134 
    135 /** free OpenSSL variables */
    136 static void
    137 crypto_openssl_free_all(void)
    138 {
    139  tor_free(crypto_openssl_version_str);
    140  tor_free(crypto_openssl_header_version_str);
    141 }
    142 
    143 /** Perform early (pre-configuration) initialization tasks for OpenSSL. */
    144 void
    145 crypto_openssl_early_init(void)
    146 {
    147    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
    148                     OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
    149                     OPENSSL_INIT_ADD_ALL_CIPHERS |
    150                     OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
    151 
    152    setup_openssl_threading();
    153 
    154    unsigned long version_num = tor_OpenSSL_version_num();
    155    const char *version_str = crypto_openssl_get_version_str();
    156    if (version_num == OPENSSL_VERSION_NUMBER &&
    157        !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
    158      log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
    159                 "(%lx: %s).", version_num, version_str);
    160    } else if ((version_num & 0xffff0000) ==
    161               (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
    162      log_notice(LD_CRYPTO,
    163               "We compiled with OpenSSL %lx: %s and we "
    164               "are running with OpenSSL %lx: %s. "
    165               "These two versions should be binary compatible.",
    166               (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
    167               version_num, version_str);
    168    } else {
    169      log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
    170               "version we're running with. If you get weird crashes, that "
    171               "might be why. (Compiled with %lx: %s; running with %lx: %s).",
    172               (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
    173               version_num, version_str);
    174    }
    175 
    176    crypto_force_rand_ssleay();
    177 }
    178 
    179 #ifndef DISABLE_ENGINES
    180 /** Try to load an engine in a shared library via fully qualified path.
    181 */
    182 static ENGINE *
    183 try_load_engine(const char *path, const char *engine)
    184 {
    185  ENGINE *e = ENGINE_by_id("dynamic");
    186  if (e) {
    187    if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
    188        !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
    189        !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
    190        !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
    191      ENGINE_free(e);
    192      e = NULL;
    193    }
    194  }
    195  return e;
    196 }
    197 #endif /* !defined(DISABLE_ENGINES) */
    198 
    199 #ifndef DISABLE_ENGINES
    200 /** Log any OpenSSL engines we're using at NOTICE. */
    201 static void
    202 log_engine(const char *fn, ENGINE *e)
    203 {
    204  if (e) {
    205    const char *name, *id;
    206    name = ENGINE_get_name(e);
    207    id = ENGINE_get_id(e);
    208    log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
    209               fn, name?name:"?", id?id:"?");
    210  } else {
    211    log_info(LD_CRYPTO, "Using default implementation for %s", fn);
    212  }
    213 }
    214 #endif /* !defined(DISABLE_ENGINES) */
    215 
    216 /** Initialize engines for openssl (if enabled).  Load all the built-in
    217 * engines, along with the one called <b>accelName</b> (which may be NULL).
    218 * If <b>accelName</b> is prefixed with "!", then it is required: return -1
    219 * if it can't be loaded.  Otherwise return 0.
    220 *
    221 * If <b>accelDir</b> is not NULL, it is the path from which the engine should
    222 * be loaded. */
    223 static int
    224 crypto_openssl_init_engines(const char *accelName,
    225                            const char *accelDir)
    226 {
    227 #ifdef DISABLE_ENGINES
    228  (void)accelName;
    229  (void)accelDir;
    230  log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
    231  if (accelName && accelName[0] == '!') {
    232    log_warn(LD_CRYPTO, "Unable to load required dynamic OpenSSL engine "
    233             "\"%s\".", accelName+1);
    234    return -1;
    235  }
    236  return 0;
    237 #else /* !defined(DISABLE_ENGINES) */
    238  ENGINE *e = NULL;
    239 
    240  log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
    241  ENGINE_load_builtin_engines();
    242  ENGINE_register_all_complete();
    243 
    244  if (accelName) {
    245    const bool required = accelName[0] == '!';
    246    if (required)
    247      ++accelName;
    248    if (accelDir) {
    249      log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
    250               " via path \"%s\".", accelName, accelDir);
    251      e = try_load_engine(accelName, accelDir);
    252    } else {
    253      log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
    254               " acceleration support.", accelName);
    255      e = ENGINE_by_id(accelName);
    256    }
    257    if (!e) {
    258      log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
    259               required?"required ":"",
    260               accelName);
    261      if (required)
    262        return -1;
    263    } else {
    264      log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
    265               accelName);
    266    }
    267  }
    268  if (e) {
    269    log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
    270             " setting default ciphers.");
    271    ENGINE_set_default(e, ENGINE_METHOD_ALL);
    272  }
    273  /* Log, if available, the intersection of the set of algorithms
    274     used by Tor and the set of algorithms available in the engine */
    275  log_engine("RSA", ENGINE_get_default_RSA());
    276  log_engine("DH", ENGINE_get_default_DH());
    277  log_engine("EC", ENGINE_get_default_EC());
    278  log_engine("RAND", ENGINE_get_default_RAND());
    279  log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
    280  log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
    281  log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
    282  log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
    283  log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
    284 #ifdef NID_aes_128_ctr
    285  log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
    286 #endif
    287 #ifdef NID_aes_128_gcm
    288  log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
    289 #endif
    290  log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
    291 #ifdef NID_aes_256_gcm
    292  log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
    293 #endif
    294  return 0;
    295 
    296 #endif /* defined(DISABLE_ENGINES) */
    297 }
    298 
    299 /** Perform late (post-init) initialization tasks for OpenSSL */
    300 int
    301 crypto_openssl_late_init(int useAccel, const char *accelName,
    302                         const char *accelDir)
    303 {
    304 #ifndef LIBRESSL_VERSION_NUMBER
    305  if (tor_OpenSSL_version_num() < OPENSSL_V_SERIES(3,0,0)) {
    306    log_warn(LD_CRYPTO, "Running with OpenSSL version \"%s\", "
    307             "which is no longer maintained by the OpenSSL project. "
    308             "We recommend that you upgrade to OpenSSL 3.0 or later. "
    309             "OpenSSL >=3.5 would be ideal.",
    310             OPENSSL_VERSION_TEXT);
    311  }
    312 #endif
    313 
    314  if (useAccel > 0) {
    315    if (crypto_openssl_init_engines(accelName, accelDir) < 0)
    316      return -1;
    317  } else {
    318    log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
    319  }
    320 
    321  if (crypto_force_rand_ssleay()) {
    322    if (crypto_seed_rng() < 0)
    323      return -1;
    324  }
    325 
    326  return 0;
    327 }
    328 
    329 /** Free crypto resources held by this thread. */
    330 void
    331 crypto_openssl_thread_cleanup(void)
    332 {
    333 }
    334 
    335 /** Clean up global resources held by openssl. */
    336 void
    337 crypto_openssl_global_cleanup(void)
    338 {
    339  CONF_modules_unload(1);
    340 
    341  crypto_openssl_free_all();
    342 }