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