tor

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

crypto_init.c (7377B)


      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_init.c
      9 *
     10 * \brief Initialize and shut down Tor's crypto library and subsystem.
     11 **/
     12 
     13 #include "orconfig.h"
     14 
     15 #define CRYPTO_PRIVATE
     16 
     17 #include "lib/crypt_ops/crypto_init.h"
     18 
     19 #include "lib/crypt_ops/crypto_curve25519.h"
     20 #include "lib/crypt_ops/crypto_dh.h"
     21 #include "lib/crypt_ops/crypto_ed25519.h"
     22 #include "lib/crypt_ops/crypto_openssl_mgt.h"
     23 #include "lib/crypt_ops/crypto_nss_mgt.h"
     24 #include "lib/crypt_ops/crypto_rand.h"
     25 #include "lib/crypt_ops/crypto_sys.h"
     26 #include "lib/crypt_ops/crypto_options_st.h"
     27 #include "lib/conf/conftypes.h"
     28 #include "lib/log/util_bug.h"
     29 #include "ext/polyval/polyval.h"
     30 
     31 #include "lib/subsys/subsys.h"
     32 
     33 #include "ext/siphash.h"
     34 
     35 /** Boolean: has our crypto library been initialized? (early phase) */
     36 static int crypto_early_initialized_ = 0;
     37 
     38 /** Boolean: has our crypto library been initialized? (late phase) */
     39 static int crypto_global_initialized_ = 0;
     40 
     41 static int have_seeded_siphash = 0;
     42 
     43 /** Set up the siphash key if we haven't already done so. */
     44 int
     45 crypto_init_siphash_key(void)
     46 {
     47  struct sipkey key;
     48  if (have_seeded_siphash)
     49    return 0;
     50 
     51  crypto_rand((char*) &key, sizeof(key));
     52  siphash_set_global_key(&key);
     53  have_seeded_siphash = 1;
     54  return 0;
     55 }
     56 
     57 /** Initialize the crypto library.  Return 0 on success, -1 on failure.
     58 */
     59 int
     60 crypto_early_init(void)
     61 {
     62  if (!crypto_early_initialized_) {
     63 
     64    crypto_early_initialized_ = 1;
     65 
     66 #ifdef ENABLE_OPENSSL
     67    crypto_openssl_early_init();
     68 #endif
     69 #ifdef ENABLE_NSS
     70    crypto_nss_early_init(0);
     71 #endif
     72 
     73    polyval_detect_implementation();
     74 
     75    if (crypto_seed_rng() < 0)
     76      return -1;
     77    if (crypto_init_siphash_key() < 0)
     78      return -1;
     79 
     80    crypto_rand_fast_init();
     81 
     82    curve25519_init();
     83    ed25519_init();
     84  }
     85  return 0;
     86 }
     87 
     88 /** Initialize the crypto library.  Return 0 on success, -1 on failure.
     89 */
     90 int
     91 crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
     92 {
     93  if (!crypto_global_initialized_) {
     94    if (crypto_early_init() < 0)
     95      return -1;
     96 
     97    crypto_global_initialized_ = 1;
     98 
     99    crypto_dh_init();
    100 
    101 #ifdef ENABLE_OPENSSL
    102    if (crypto_openssl_late_init(useAccel, accelName, accelDir) < 0)
    103      return -1;
    104 #else
    105    (void)useAccel;
    106    (void)accelName;
    107    (void)accelDir;
    108 #endif /* defined(ENABLE_OPENSSL) */
    109 #ifdef ENABLE_NSS
    110    if (crypto_nss_late_init() < 0)
    111      return -1;
    112 #endif
    113  }
    114  return 0;
    115 }
    116 
    117 /** Free crypto resources held by this thread. */
    118 void
    119 crypto_thread_cleanup(void)
    120 {
    121 #ifdef ENABLE_OPENSSL
    122  crypto_openssl_thread_cleanup();
    123 #endif
    124  destroy_thread_fast_rng();
    125 }
    126 
    127 /**
    128 * Uninitialize the crypto library. Return 0 on success. Does not detect
    129 * failure.
    130 */
    131 int
    132 crypto_global_cleanup(void)
    133 {
    134  crypto_dh_free_all();
    135 
    136 #ifdef ENABLE_OPENSSL
    137  crypto_openssl_global_cleanup();
    138 #endif
    139 #ifdef ENABLE_NSS
    140  crypto_nss_global_cleanup();
    141 #endif
    142 
    143  crypto_rand_fast_shutdown();
    144 
    145  crypto_early_initialized_ = 0;
    146  crypto_global_initialized_ = 0;
    147  have_seeded_siphash = 0;
    148  siphash_unset_global_key();
    149 
    150  return 0;
    151 }
    152 
    153 /** Run operations that the crypto library requires to be happy again
    154 * after forking. */
    155 void
    156 crypto_prefork(void)
    157 {
    158 #ifdef ENABLE_NSS
    159  crypto_nss_prefork();
    160 #endif
    161  /* It is not safe to share a fast_rng object across a fork boundary unless
    162   * we actually have zero-on-fork support in map_anon.c.  If we have
    163   * drop-on-fork support, we will crash; if we have neither, we will yield
    164   * a copy of the parent process's rng, which is scary and insecure.
    165   */
    166  destroy_thread_fast_rng();
    167 }
    168 
    169 /** Run operations that the crypto library requires to be happy again
    170 * after forking. */
    171 void
    172 crypto_postfork(void)
    173 {
    174 #ifdef ENABLE_NSS
    175  crypto_nss_postfork();
    176 #endif
    177 }
    178 
    179 /** Return the name of the crypto library we're using. */
    180 const char *
    181 crypto_get_library_name(void)
    182 {
    183 #ifdef ENABLE_OPENSSL
    184  return "OpenSSL";
    185 #endif
    186 #ifdef ENABLE_NSS
    187  return "NSS";
    188 #endif
    189 }
    190 
    191 /** Return the version of the crypto library we are using, as given in the
    192 * library. */
    193 const char *
    194 crypto_get_library_version_string(void)
    195 {
    196 #ifdef ENABLE_OPENSSL
    197  return crypto_openssl_get_version_str();
    198 #endif
    199 #ifdef ENABLE_NSS
    200  return crypto_nss_get_version_str();
    201 #endif
    202 }
    203 
    204 /** Return the version of the crypto library we're using, as given in the
    205 * headers. */
    206 const char *
    207 crypto_get_header_version_string(void)
    208 {
    209 #ifdef ENABLE_OPENSSL
    210  return crypto_openssl_get_header_version_str();
    211 #endif
    212 #ifdef ENABLE_NSS
    213  return crypto_nss_get_header_version_str();
    214 #endif
    215 }
    216 
    217 /** Return true iff Tor is using the NSS library. */
    218 int
    219 tor_is_using_nss(void)
    220 {
    221 #ifdef ENABLE_NSS
    222  return 1;
    223 #else
    224  return 0;
    225 #endif
    226 }
    227 
    228 static int
    229 subsys_crypto_initialize(void)
    230 {
    231  if (crypto_early_init() < 0)
    232    return -1;
    233  crypto_dh_init();
    234  return 0;
    235 }
    236 
    237 static void
    238 subsys_crypto_shutdown(void)
    239 {
    240  crypto_global_cleanup();
    241 }
    242 
    243 static void
    244 subsys_crypto_prefork(void)
    245 {
    246  crypto_prefork();
    247 }
    248 
    249 static void
    250 subsys_crypto_postfork(void)
    251 {
    252  crypto_postfork();
    253 }
    254 
    255 static void
    256 subsys_crypto_thread_cleanup(void)
    257 {
    258  crypto_thread_cleanup();
    259 }
    260 
    261 /** Magic number for crypto_options_t. */
    262 #define CRYPTO_OPTIONS_MAGIC 0x68757368
    263 
    264 /**
    265 * Return 0 if <b>arg</b> is a valid crypto_options_t.  Otherwise return -1
    266 * and set *<b>msg_out</b> to a freshly allocated error string.
    267 **/
    268 static int
    269 crypto_options_validate(const void *arg, char **msg_out)
    270 {
    271  const crypto_options_t *opt = arg;
    272  tor_assert(opt->magic == CRYPTO_OPTIONS_MAGIC);
    273  tor_assert(msg_out);
    274 
    275  if (opt->AccelDir && !opt->AccelName) {
    276    *msg_out = tor_strdup("Can't use hardware crypto accelerator dir "
    277                          "without engine name.");
    278    return -1;
    279  }
    280 
    281  return 0;
    282 }
    283 
    284 /* Declare the options field table for crypto_options */
    285 #define CONF_CONTEXT LL_TABLE
    286 #include "lib/crypt_ops/crypto_options.inc"
    287 #undef CONF_CONTEXT
    288 
    289 /**
    290 * Declares the configuration options for this module.
    291 **/
    292 static const config_format_t crypto_options_fmt = {
    293  .size = sizeof(crypto_options_t),
    294  .magic = { "crypto_options_t",
    295             CRYPTO_OPTIONS_MAGIC,
    296             offsetof(crypto_options_t, magic) },
    297  .vars = crypto_options_t_vars,
    298  .validate_fn = crypto_options_validate,
    299 };
    300 
    301 /**
    302 * Invoked from subsysmgr.c when a new set of options arrives.
    303 **/
    304 static int
    305 crypto_set_options(void *arg)
    306 {
    307  const crypto_options_t *options = arg;
    308  const bool hardware_accel = options->HardwareAccel || options->AccelName;
    309 
    310  // This call already checks for crypto_global_initialized_, so it
    311  // will only initialize the subsystem the first time it's called.
    312  if (crypto_global_init(hardware_accel,
    313                         options->AccelName,
    314                         options->AccelDir)) {
    315    log_err(LD_BUG, "Unable to initialize the crypto subsystem. Exiting.");
    316    return -1;
    317  }
    318  return 0;
    319 }
    320 
    321 const struct subsys_fns_t sys_crypto = {
    322  .name = "crypto",
    323  SUBSYS_DECLARE_LOCATION(),
    324  .supported = true,
    325  .level = -60,
    326  .initialize = subsys_crypto_initialize,
    327  .shutdown = subsys_crypto_shutdown,
    328  .prefork = subsys_crypto_prefork,
    329  .postfork = subsys_crypto_postfork,
    330  .thread_cleanup = subsys_crypto_thread_cleanup,
    331 
    332  .options_format = &crypto_options_fmt,
    333  .set_options = crypto_set_options,
    334 };