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 */
10 * \brief Initialize and shut down Tor's crypto library and subsystem.
15 #define CRYPTO_PRIVATE
17 #include "lib/crypt_ops/crypto_init.h"
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"
30 #include "lib/subsys/subsys.h"
32 #include "ext/siphash.h"
34 /** Boolean: has our crypto library been initialized? (early phase) */
35 static int crypto_early_initialized_
= 0;
37 /** Boolean: has our crypto library been initialized? (late phase) */
38 static int crypto_global_initialized_
= 0;
40 static int have_seeded_siphash
= 0;
42 /** Set up the siphash key if we haven't already done so. */
44 crypto_init_siphash_key(void)
47 if (have_seeded_siphash
)
50 crypto_rand((char*) &key
, sizeof(key
));
51 siphash_set_global_key(&key
);
52 have_seeded_siphash
= 1;
56 /** Initialize the crypto library. Return 0 on success, -1 on failure.
59 crypto_early_init(void)
61 if (!crypto_early_initialized_
) {
63 crypto_early_initialized_
= 1;
66 crypto_openssl_early_init();
69 crypto_nss_early_init(0);
72 if (crypto_seed_rng() < 0)
74 if (crypto_init_siphash_key() < 0)
77 crypto_rand_fast_init();
85 /** Initialize the crypto library. Return 0 on success, -1 on failure.
88 crypto_global_init(int useAccel
, const char *accelName
, const char *accelDir
)
90 if (!crypto_global_initialized_
) {
91 if (crypto_early_init() < 0)
94 crypto_global_initialized_
= 1;
99 if (crypto_openssl_late_init(useAccel
, accelName
, accelDir
) < 0)
105 #endif /* defined(ENABLE_OPENSSL) */
107 if (crypto_nss_late_init() < 0)
114 /** Free crypto resources held by this thread. */
116 crypto_thread_cleanup(void)
118 #ifdef ENABLE_OPENSSL
119 crypto_openssl_thread_cleanup();
121 destroy_thread_fast_rng();
125 * Uninitialize the crypto library. Return 0 on success. Does not detect
129 crypto_global_cleanup(void)
131 crypto_dh_free_all();
133 #ifdef ENABLE_OPENSSL
134 crypto_openssl_global_cleanup();
137 crypto_nss_global_cleanup();
140 crypto_rand_fast_shutdown();
142 crypto_early_initialized_
= 0;
143 crypto_global_initialized_
= 0;
144 have_seeded_siphash
= 0;
145 siphash_unset_global_key();
150 /** Run operations that the crypto library requires to be happy again
156 crypto_nss_prefork();
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.
163 destroy_thread_fast_rng();
166 /** Run operations that the crypto library requires to be happy again
169 crypto_postfork(void)
172 crypto_nss_postfork();
176 /** Return the name of the crypto library we're using. */
178 crypto_get_library_name(void)
180 #ifdef ENABLE_OPENSSL
188 /** Return the version of the crypto library we are using, as given in the
191 crypto_get_library_version_string(void)
193 #ifdef ENABLE_OPENSSL
194 return crypto_openssl_get_version_str();
197 return crypto_nss_get_version_str();
201 /** Return the version of the crypto library we're using, as given in the
204 crypto_get_header_version_string(void)
206 #ifdef ENABLE_OPENSSL
207 return crypto_openssl_get_header_version_str();
210 return crypto_nss_get_header_version_str();
214 /** Return true iff Tor is using the NSS library. */
216 tor_is_using_nss(void)
226 subsys_crypto_initialize(void)
228 if (crypto_early_init() < 0)
235 subsys_crypto_shutdown(void)
237 crypto_global_cleanup();
241 subsys_crypto_prefork(void)
247 subsys_crypto_postfork(void)
253 subsys_crypto_thread_cleanup(void)
255 crypto_thread_cleanup();
258 /** Magic number for crypto_options_t. */
259 #define CRYPTO_OPTIONS_MAGIC 0x68757368
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.
266 crypto_options_validate(const void *arg
, char **msg_out
)
268 const crypto_options_t
*opt
= arg
;
269 tor_assert(opt
->magic
== CRYPTO_OPTIONS_MAGIC
);
272 if (opt
->AccelDir
&& !opt
->AccelName
) {
273 *msg_out
= tor_strdup("Can't use hardware crypto accelerator dir "
274 "without engine name.");
281 /* Declare the options field table for crypto_options */
282 #define CONF_CONTEXT LL_TABLE
283 #include "lib/crypt_ops/crypto_options.inc"
287 * Declares the configuration options for this module.
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
,
299 * Invoked from subsysmgr.c when a new set of options arrives.
302 crypto_set_options(void *arg
)
304 const crypto_options_t
*options
= arg
;
305 const bool hardware_accel
= options
->HardwareAccel
|| options
->AccelName
;
307 // This call already checks for crypto_global_initialized_, so it
308 // will only initialize the subsystem the first time it's called.
309 if (crypto_global_init(hardware_accel
,
311 options
->AccelDir
)) {
312 log_err(LD_BUG
, "Unable to initialize the crypto subsystem. Exiting.");
318 const struct subsys_fns_t sys_crypto
= {
320 SUBSYS_DECLARE_LOCATION(),
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
,
329 .options_format
= &crypto_options_fmt
,
330 .set_options
= crypto_set_options
,