Tor 0.4.9.0-alpha-dev
crypto_openssl_mgt.c
Go to the documentation of this file.
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_openssl_mgt.c
9 *
10 * \brief Block of functions related to operations from OpenSSL.
11 **/
12
13#include "lib/crypt_ops/compat_openssl.h"
16#include "lib/crypt_ops/aes.h"
19#include "lib/log/log.h"
20#include "lib/log/util_bug.h"
22#include "lib/thread/threads.h"
23
24DISABLE_GCC_WARNING("-Wredundant-decls")
25
26#include <openssl/err.h>
27#include <openssl/rsa.h>
28#include <openssl/pem.h>
29#include <openssl/evp.h>
30#include <openssl/engine.h>
31#include <openssl/rand.h>
32#include <openssl/bn.h>
33#include <openssl/dh.h>
34#include <openssl/conf.h>
35#include <openssl/hmac.h>
36#include <openssl/crypto.h>
37#include <openssl/ssl.h>
38
39ENABLE_GCC_WARNING("-Wredundant-decls")
40
41#include <string.h>
42
43#ifdef OPENSSL_NO_ENGINE
44/* Android's OpenSSL seems to have removed all of its Engine support. */
45#define DISABLE_ENGINES
46#endif
47
48#ifndef NEW_THREAD_API
49/** A number of preallocated mutexes for use by OpenSSL. */
51/** How many mutexes have we allocated for use by OpenSSL? */
52static int n_openssl_mutexes_ = 0;
53#endif /* !defined(NEW_THREAD_API) */
54
55/** Declare STATIC functions */
56STATIC char * parse_openssl_version_str(const char *raw_version);
57#ifndef NEW_THREAD_API
58STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line);
59STATIC void tor_set_openssl_thread_id(CRYPTO_THREADID *threadid);
60#endif
61
62/** Log all pending crypto errors at level <b>severity</b>. Use
63 * <b>doing</b> to describe our current activities.
64 */
65void
66crypto_openssl_log_errors(int severity, const char *doing)
67{
68 unsigned long err;
69 const char *msg, *lib, *func;
70 while ((err = ERR_get_error()) != 0) {
71 msg = (const char*)ERR_reason_error_string(err);
72 lib = (const char*)ERR_lib_error_string(err);
73 func = (const char*)ERR_func_error_string(err);
74 if (!msg) msg = "(null)";
75 if (!lib) lib = "(null)";
76 if (!func) func = "(null)";
77 if (BUG(!doing)) doing = "(null)";
78 tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
79 doing, msg, lib, func);
80 }
81}
82
83/* Returns a trimmed and human-readable version of an openssl version string
84* <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
85* May 2012' and this will parse them into a form similar to '1.0.0b' */
86STATIC char *
87parse_openssl_version_str(const char *raw_version)
88{
89 const char *end_of_version = NULL;
90 /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
91 trim that down. */
92 if (!strcmpstart(raw_version, "OpenSSL ")) {
93 raw_version += strlen("OpenSSL ");
94 end_of_version = strchr(raw_version, ' ');
95 }
96
97 if (end_of_version)
98 return tor_strndup(raw_version,
99 end_of_version-raw_version);
100 else
101 return tor_strdup(raw_version);
102}
103
104static char *crypto_openssl_version_str = NULL;
105/* Return a human-readable version of the run-time openssl version number. */
106const char *
107crypto_openssl_get_version_str(void)
108{
109#ifdef OPENSSL_VERSION
110 const int query = OPENSSL_VERSION;
111#else
112 /* This old name was changed around OpenSSL 1.1.0 */
113 const int query = SSLEAY_VERSION;
114#endif /* defined(OPENSSL_VERSION) */
115
116 if (crypto_openssl_version_str == NULL) {
117 const char *raw_version = OpenSSL_version(query);
118 crypto_openssl_version_str = parse_openssl_version_str(raw_version);
119 }
120 return crypto_openssl_version_str;
121}
122
123#undef QUERY_OPENSSL_VERSION
124
125static char *crypto_openssl_header_version_str = NULL;
126/* Return a human-readable version of the compile-time openssl version
127* number. */
128const char *
129crypto_openssl_get_header_version_str(void)
130{
131 if (crypto_openssl_header_version_str == NULL) {
132 crypto_openssl_header_version_str =
133 parse_openssl_version_str(OPENSSL_VERSION_TEXT);
134 }
135 return crypto_openssl_header_version_str;
136}
137
138#ifndef COCCI
139#ifndef OPENSSL_THREADS
140#error "OpenSSL has been built without thread support. Tor requires an \
141 OpenSSL library with thread support enabled."
142#endif
143#endif /* !defined(COCCI) */
144
145#ifndef NEW_THREAD_API
146/** Helper: OpenSSL uses this callback to manipulate mutexes. */
147STATIC void
148openssl_locking_cb_(int mode, int n, const char *file, int line)
149{
150 (void)file;
151 (void)line;
152 if (!openssl_mutexes_)
153 /* This is not a really good fix for the
154 * "release-freed-lock-from-separate-thread-on-shutdown" problem, but
155 * it can't hurt. */
156 return;
157 if (mode & CRYPTO_LOCK)
159 else
161}
162
163STATIC void
164tor_set_openssl_thread_id(CRYPTO_THREADID *threadid)
165{
166 CRYPTO_THREADID_set_numeric(threadid, tor_get_thread_id());
167}
168#endif /* !defined(NEW_THREAD_API) */
169
170/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
171 * multithreaded. Returns 0. */
172static int
174{
175#ifndef NEW_THREAD_API
176 int i;
177 int n = CRYPTO_num_locks();
179 openssl_mutexes_ = tor_calloc(n, sizeof(tor_mutex_t *));
180 for (i=0; i < n; ++i)
182 CRYPTO_set_locking_callback(openssl_locking_cb_);
183 CRYPTO_THREADID_set_callback(tor_set_openssl_thread_id);
184#endif /* !defined(NEW_THREAD_API) */
185 return 0;
186}
187
188/** free OpenSSL variables */
189static void
191{
192 tor_free(crypto_openssl_version_str);
193 tor_free(crypto_openssl_header_version_str);
194
195 /* Destroying a locked mutex is undefined behaviour. This mutex may be
196 * locked, because multiple threads can access it. But we need to destroy
197 * it, otherwise re-initialisation will trigger undefined behaviour.
198 * See #31735 for details. */
199#ifndef NEW_THREAD_API
200 if (n_openssl_mutexes_) {
201 int n = n_openssl_mutexes_;
203 int i;
204 openssl_mutexes_ = NULL;
206 for (i=0;i<n;++i) {
207 tor_mutex_free(ms[i]);
208 }
209 tor_free(ms);
210 }
211#endif /* !defined(NEW_THREAD_API) */
212}
213
214/** Perform early (pre-configuration) initialization tasks for OpenSSL. */
215void
217{
218#ifdef OPENSSL_1_1_API
219 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
220 OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
221 OPENSSL_INIT_ADD_ALL_CIPHERS |
222 OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
223#else /* !defined(OPENSSL_1_1_API) */
224 ERR_load_crypto_strings();
225 OpenSSL_add_all_algorithms();
226#endif /* defined(OPENSSL_1_1_API) */
227
229
230 unsigned long version_num = tor_OpenSSL_version_num();
231 const char *version_str = crypto_openssl_get_version_str();
232 if (version_num == OPENSSL_VERSION_NUMBER &&
233 !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
234 log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
235 "(%lx: %s).", version_num, version_str);
236 } else if ((version_num & 0xffff0000) ==
237 (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
238 log_notice(LD_CRYPTO,
239 "We compiled with OpenSSL %lx: %s and we "
240 "are running with OpenSSL %lx: %s. "
241 "These two versions should be binary compatible.",
242 (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
243 version_num, version_str);
244 } else {
245 log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
246 "version we're running with. If you get weird crashes, that "
247 "might be why. (Compiled with %lx: %s; running with %lx: %s).",
248 (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
249 version_num, version_str);
250 }
251
253}
254
255#ifndef DISABLE_ENGINES
256/** Try to load an engine in a shared library via fully qualified path.
257 */
258static ENGINE *
259try_load_engine(const char *path, const char *engine)
260{
261 ENGINE *e = ENGINE_by_id("dynamic");
262 if (e) {
263 if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
264 !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
265 !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
266 !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
267 ENGINE_free(e);
268 e = NULL;
269 }
270 }
271 return e;
272}
273#endif /* !defined(DISABLE_ENGINES) */
274
275#ifndef DISABLE_ENGINES
276/** Log any OpenSSL engines we're using at NOTICE. */
277static void
278log_engine(const char *fn, ENGINE *e)
279{
280 if (e) {
281 const char *name, *id;
282 name = ENGINE_get_name(e);
283 id = ENGINE_get_id(e);
284 log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
285 fn, name?name:"?", id?id:"?");
286 } else {
287 log_info(LD_CRYPTO, "Using default implementation for %s", fn);
288 }
289}
290#endif /* !defined(DISABLE_ENGINES) */
291
292/** Initialize engines for openssl (if enabled). Load all the built-in
293 * engines, along with the one called <b>accelName</b> (which may be NULL).
294 * If <b>accelName</b> is prefixed with "!", then it is required: return -1
295 * if it can't be loaded. Otherwise return 0.
296 *
297 * If <b>accelDir</b> is not NULL, it is the path from which the engine should
298 * be loaded. */
299static int
300crypto_openssl_init_engines(const char *accelName,
301 const char *accelDir)
302{
303#ifdef DISABLE_ENGINES
304 (void)accelName;
305 (void)accelDir;
306 log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
307 if (accelName && accelName[0] == '!') {
308 log_warn(LD_CRYPTO, "Unable to load required dynamic OpenSSL engine "
309 "\"%s\".", accelName+1);
310 return -1;
311 }
312 return 0;
313#else /* !defined(DISABLE_ENGINES) */
314 ENGINE *e = NULL;
315
316 log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
317 ENGINE_load_builtin_engines();
318 ENGINE_register_all_complete();
319
320 if (accelName) {
321 const bool required = accelName[0] == '!';
322 if (required)
323 ++accelName;
324 if (accelDir) {
325 log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
326 " via path \"%s\".", accelName, accelDir);
327 e = try_load_engine(accelName, accelDir);
328 } else {
329 log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
330 " acceleration support.", accelName);
331 e = ENGINE_by_id(accelName);
332 }
333 if (!e) {
334 log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
335 required?"required ":"",
336 accelName);
337 if (required)
338 return -1;
339 } else {
340 log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
341 accelName);
342 }
343 }
344 if (e) {
345 log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
346 " setting default ciphers.");
347 ENGINE_set_default(e, ENGINE_METHOD_ALL);
348 }
349 /* Log, if available, the intersection of the set of algorithms
350 used by Tor and the set of algorithms available in the engine */
351 log_engine("RSA", ENGINE_get_default_RSA());
352 log_engine("DH", ENGINE_get_default_DH());
353#ifdef OPENSSL_1_1_API
354 log_engine("EC", ENGINE_get_default_EC());
355#else
356 log_engine("ECDH", ENGINE_get_default_ECDH());
357 log_engine("ECDSA", ENGINE_get_default_ECDSA());
358#endif /* defined(OPENSSL_1_1_API) */
359 log_engine("RAND", ENGINE_get_default_RAND());
360 log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
361 log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
362 log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
363 log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
364 log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
365#ifdef NID_aes_128_ctr
366 log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
367#endif
368#ifdef NID_aes_128_gcm
369 log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
370#endif
371 log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
372#ifdef NID_aes_256_gcm
373 log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
374#endif
375 return 0;
376
377#endif /* defined(DISABLE_ENGINES) */
378}
379
380/** Perform late (post-init) initialization tasks for OpenSSL */
381int
382crypto_openssl_late_init(int useAccel, const char *accelName,
383 const char *accelDir)
384{
385 if (useAccel > 0) {
386 if (crypto_openssl_init_engines(accelName, accelDir) < 0)
387 return -1;
388 } else {
389 log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
390 }
391
393 if (crypto_seed_rng() < 0)
394 return -1;
395 }
396
397 evaluate_evp_for_aes(-1);
398 evaluate_ctr_for_aes();
399
400 return 0;
401}
402
403/** Free crypto resources held by this thread. */
404void
406{
407#ifndef NEW_THREAD_API
408 ERR_remove_thread_state(NULL);
409#endif
410}
411
412/** Clean up global resources held by openssl. */
413void
415{
416#ifndef OPENSSL_1_1_API
417 EVP_cleanup();
418#endif
419#ifndef NEW_THREAD_API
420 ERR_remove_thread_state(NULL);
421#endif
422#ifndef OPENSSL_1_1_API
423 ERR_free_strings();
424#endif
425
426#ifndef DISABLE_ENGINES
427#ifndef OPENSSL_1_1_API
428 ENGINE_cleanup();
429#endif
430#endif
431
432 CONF_modules_unload(1);
433#ifndef OPENSSL_1_1_API
434 CRYPTO_cleanup_all_ex_data();
435#endif
436
438}
Headers for aes.c.
tor_mutex_t * tor_mutex_new(void)
Definition: compat_mutex.c:17
Header for compat_mutex.c.
void tor_mutex_release(tor_mutex_t *m)
void tor_mutex_acquire(tor_mutex_t *m)
#define tor_mutex_free(m)
Definition: compat_mutex.h:73
unsigned long tor_get_thread_id(void)
const char * name
Definition: config.c:2462
static tor_mutex_t ** openssl_mutexes_
void crypto_openssl_early_init(void)
static ENGINE * try_load_engine(const char *path, const char *engine)
void crypto_openssl_thread_cleanup(void)
static int n_openssl_mutexes_
int crypto_openssl_late_init(int useAccel, const char *accelName, const char *accelDir)
static int crypto_openssl_init_engines(const char *accelName, const char *accelDir)
static void log_engine(const char *fn, ENGINE *e)
static int setup_openssl_threading(void)
void crypto_openssl_global_cleanup(void)
STATIC char * parse_openssl_version_str(const char *raw_version)
STATIC void openssl_locking_cb_(int mode, int n, const char *file, int line)
static void crypto_openssl_free_all(void)
void crypto_openssl_log_errors(int severity, const char *doing)
Headers for crypto_openssl_mgt.c.
int crypto_seed_rng(void)
Definition: crypto_rand.c:454
int crypto_force_rand_ssleay(void)
Definition: crypto_rand.c:622
Common functions for using (pseudo-)random number generators.
void tor_log(int severity, log_domain_mask_t domain, const char *format,...)
Definition: log.c:591
Headers for log.c.
#define LD_CRYPTO
Definition: log.h:64
#define tor_free(p)
Definition: malloc.h:56
Macros to implement mocking and selective exposure for the test code.
#define STATIC
Definition: testsupport.h:32
Header for threads.c.
Macros to manage assertions, fatal and non-fatal.
int strcmpstart(const char *s1, const char *s2)
Definition: util_string.c:217
Header for util_string.c.