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 };