LCOV - code coverage report
Current view: top level - lib/crypt_ops - crypto_init.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 67 80 83.8 %
Date: 2021-11-24 03:28:48 Functions: 13 18 72.2 %

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

Generated by: LCOV version 1.14