scripts: Fix Python3 warnings
[tor.git] / src / lib / crypt_ops / crypto_init.c
blobef9908c893fbb2076b27c9a62967fb308a900bf3
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 */
7 /**
8 * \file crypto_init.c
10 * \brief Initialize and shut down Tor's crypto library and subsystem.
11 **/
13 #include "orconfig.h"
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. */
43 int
44 crypto_init_siphash_key(void)
46 struct sipkey key;
47 if (have_seeded_siphash)
48 return 0;
50 crypto_rand((char*) &key, sizeof(key));
51 siphash_set_global_key(&key);
52 have_seeded_siphash = 1;
53 return 0;
56 /** Initialize the crypto library. Return 0 on success, -1 on failure.
58 int
59 crypto_early_init(void)
61 if (!crypto_early_initialized_) {
63 crypto_early_initialized_ = 1;
65 #ifdef ENABLE_OPENSSL
66 crypto_openssl_early_init();
67 #endif
68 #ifdef ENABLE_NSS
69 crypto_nss_early_init(0);
70 #endif
72 if (crypto_seed_rng() < 0)
73 return -1;
74 if (crypto_init_siphash_key() < 0)
75 return -1;
77 crypto_rand_fast_init();
79 curve25519_init();
80 ed25519_init();
82 return 0;
85 /** Initialize the crypto library. Return 0 on success, -1 on failure.
87 int
88 crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
90 if (!crypto_global_initialized_) {
91 if (crypto_early_init() < 0)
92 return -1;
94 crypto_global_initialized_ = 1;
96 crypto_dh_init();
98 #ifdef ENABLE_OPENSSL
99 if (crypto_openssl_late_init(useAccel, accelName, accelDir) < 0)
100 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
111 return 0;
114 /** Free crypto resources held by this thread. */
115 void
116 crypto_thread_cleanup(void)
118 #ifdef ENABLE_OPENSSL
119 crypto_openssl_thread_cleanup();
120 #endif
121 destroy_thread_fast_rng();
125 * Uninitialize the crypto library. Return 0 on success. Does not detect
126 * failure.
129 crypto_global_cleanup(void)
131 crypto_dh_free_all();
133 #ifdef ENABLE_OPENSSL
134 crypto_openssl_global_cleanup();
135 #endif
136 #ifdef ENABLE_NSS
137 crypto_nss_global_cleanup();
138 #endif
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();
147 return 0;
150 /** Run operations that the crypto library requires to be happy again
151 * after forking. */
152 void
153 crypto_prefork(void)
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.
163 destroy_thread_fast_rng();
166 /** Run operations that the crypto library requires to be happy again
167 * after forking. */
168 void
169 crypto_postfork(void)
171 #ifdef ENABLE_NSS
172 crypto_nss_postfork();
173 #endif
176 /** Return the name of the crypto library we're using. */
177 const char *
178 crypto_get_library_name(void)
180 #ifdef ENABLE_OPENSSL
181 return "OpenSSL";
182 #endif
183 #ifdef ENABLE_NSS
184 return "NSS";
185 #endif
188 /** Return the version of the crypto library we are using, as given in the
189 * library. */
190 const char *
191 crypto_get_library_version_string(void)
193 #ifdef ENABLE_OPENSSL
194 return crypto_openssl_get_version_str();
195 #endif
196 #ifdef ENABLE_NSS
197 return crypto_nss_get_version_str();
198 #endif
201 /** Return the version of the crypto library we're using, as given in the
202 * headers. */
203 const char *
204 crypto_get_header_version_string(void)
206 #ifdef ENABLE_OPENSSL
207 return crypto_openssl_get_header_version_str();
208 #endif
209 #ifdef ENABLE_NSS
210 return crypto_nss_get_header_version_str();
211 #endif
214 /** Return true iff Tor is using the NSS library. */
216 tor_is_using_nss(void)
218 #ifdef ENABLE_NSS
219 return 1;
220 #else
221 return 0;
222 #endif
225 static int
226 subsys_crypto_initialize(void)
228 if (crypto_early_init() < 0)
229 return -1;
230 crypto_dh_init();
231 return 0;
234 static void
235 subsys_crypto_shutdown(void)
237 crypto_global_cleanup();
240 static void
241 subsys_crypto_prefork(void)
243 crypto_prefork();
246 static void
247 subsys_crypto_postfork(void)
249 crypto_postfork();
252 static 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.
265 static int
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);
270 tor_assert(msg_out);
272 if (opt->AccelDir && !opt->AccelName) {
273 *msg_out = tor_strdup("Can't use hardware crypto accelerator dir "
274 "without engine name.");
275 return -1;
278 return 0;
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
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.
301 static int
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,
310 options->AccelName,
311 options->AccelDir)) {
312 log_err(LD_BUG, "Unable to initialize the crypto subsystem. Exiting.");
313 return -1;
315 return 0;
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,
329 .options_format = &crypto_options_fmt,
330 .set_options = crypto_set_options,