Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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/** Declare STATIC functions */
49STATIC char * parse_openssl_version_str(const char *raw_version);
50
51/** Log all pending crypto errors at level <b>severity</b>. Use
52 * <b>doing</b> to describe our current activities.
53 */
54void
55crypto_openssl_log_errors(int severity, const char *doing)
56{
57 unsigned long err;
58 const char *msg, *lib, *func;
59 while ((err = ERR_get_error()) != 0) {
60 msg = (const char*)ERR_reason_error_string(err);
61 lib = (const char*)ERR_lib_error_string(err);
62 func = (const char*)ERR_func_error_string(err);
63 if (!msg) msg = "(null)";
64 if (!lib) lib = "(null)";
65 if (!func) func = "(null)";
66 if (BUG(!doing)) doing = "(null)";
67 tor_log(severity, LD_CRYPTO, "crypto error while %s: %s (in %s:%s)",
68 doing, msg, lib, func);
69 }
70}
71
72/* Returns a trimmed and human-readable version of an openssl version string
73* <b>raw_version</b>. They are usually in the form of 'OpenSSL 1.0.0b 10
74* May 2012' and this will parse them into a form similar to '1.0.0b' */
75STATIC char *
76parse_openssl_version_str(const char *raw_version)
77{
78 const char *end_of_version = NULL;
79 /* The output should be something like "OpenSSL 1.0.0b 10 May 2012. Let's
80 trim that down. */
81 if (!strcmpstart(raw_version, "OpenSSL ")) {
82 raw_version += strlen("OpenSSL ");
83 end_of_version = strchr(raw_version, ' ');
84 }
85
86 if (end_of_version)
87 return tor_strndup(raw_version,
88 end_of_version-raw_version);
89 else
90 return tor_strdup(raw_version);
91}
92
93static char *crypto_openssl_version_str = NULL;
94/* Return a human-readable version of the run-time openssl version number. */
95const char *
96crypto_openssl_get_version_str(void)
97{
98 const int query = OPENSSL_VERSION;
99
100 if (crypto_openssl_version_str == NULL) {
101 const char *raw_version = OpenSSL_version(query);
102 crypto_openssl_version_str = parse_openssl_version_str(raw_version);
103 }
104 return crypto_openssl_version_str;
105}
106
107static char *crypto_openssl_header_version_str = NULL;
108/* Return a human-readable version of the compile-time openssl version
109* number. */
110const char *
111crypto_openssl_get_header_version_str(void)
112{
113 if (crypto_openssl_header_version_str == NULL) {
114 crypto_openssl_header_version_str =
115 parse_openssl_version_str(OPENSSL_VERSION_TEXT);
116 }
117 return crypto_openssl_header_version_str;
118}
119
120#ifndef COCCI
121#ifndef OPENSSL_THREADS
122#error "OpenSSL has been built without thread support. Tor requires an \
123 OpenSSL library with thread support enabled."
124#endif
125#endif /* !defined(COCCI) */
126
127/** Helper: Construct mutexes, and set callbacks to help OpenSSL handle being
128 * multithreaded. Returns 0. */
129static int
131{
132 return 0;
133}
134
135/** free OpenSSL variables */
136static void
138{
139 tor_free(crypto_openssl_version_str);
140 tor_free(crypto_openssl_header_version_str);
141}
142
143/** Perform early (pre-configuration) initialization tasks for OpenSSL. */
144void
146{
147 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS |
148 OPENSSL_INIT_LOAD_CRYPTO_STRINGS |
149 OPENSSL_INIT_ADD_ALL_CIPHERS |
150 OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
151
153
154 unsigned long version_num = tor_OpenSSL_version_num();
155 const char *version_str = crypto_openssl_get_version_str();
156 if (version_num == OPENSSL_VERSION_NUMBER &&
157 !strcmp(version_str, OPENSSL_VERSION_TEXT)) {
158 log_info(LD_CRYPTO, "OpenSSL version matches version from headers "
159 "(%lx: %s).", version_num, version_str);
160 } else if ((version_num & 0xffff0000) ==
161 (OPENSSL_VERSION_NUMBER & 0xffff0000)) {
162 log_notice(LD_CRYPTO,
163 "We compiled with OpenSSL %lx: %s and we "
164 "are running with OpenSSL %lx: %s. "
165 "These two versions should be binary compatible.",
166 (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
167 version_num, version_str);
168 } else {
169 log_warn(LD_CRYPTO, "OpenSSL version from headers does not match the "
170 "version we're running with. If you get weird crashes, that "
171 "might be why. (Compiled with %lx: %s; running with %lx: %s).",
172 (unsigned long)OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT,
173 version_num, version_str);
174 }
175
177}
178
179#ifndef DISABLE_ENGINES
180/** Try to load an engine in a shared library via fully qualified path.
181 */
182static ENGINE *
183try_load_engine(const char *path, const char *engine)
184{
185 ENGINE *e = ENGINE_by_id("dynamic");
186 if (e) {
187 if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
188 !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
189 !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
190 !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
191 ENGINE_free(e);
192 e = NULL;
193 }
194 }
195 return e;
196}
197#endif /* !defined(DISABLE_ENGINES) */
198
199#ifndef DISABLE_ENGINES
200/** Log any OpenSSL engines we're using at NOTICE. */
201static void
202log_engine(const char *fn, ENGINE *e)
203{
204 if (e) {
205 const char *name, *id;
206 name = ENGINE_get_name(e);
207 id = ENGINE_get_id(e);
208 log_notice(LD_CRYPTO, "Default OpenSSL engine for %s is %s [%s]",
209 fn, name?name:"?", id?id:"?");
210 } else {
211 log_info(LD_CRYPTO, "Using default implementation for %s", fn);
212 }
213}
214#endif /* !defined(DISABLE_ENGINES) */
215
216/** Initialize engines for openssl (if enabled). Load all the built-in
217 * engines, along with the one called <b>accelName</b> (which may be NULL).
218 * If <b>accelName</b> is prefixed with "!", then it is required: return -1
219 * if it can't be loaded. Otherwise return 0.
220 *
221 * If <b>accelDir</b> is not NULL, it is the path from which the engine should
222 * be loaded. */
223static int
224crypto_openssl_init_engines(const char *accelName,
225 const char *accelDir)
226{
227#ifdef DISABLE_ENGINES
228 (void)accelName;
229 (void)accelDir;
230 log_warn(LD_CRYPTO, "No OpenSSL hardware acceleration support enabled.");
231 if (accelName && accelName[0] == '!') {
232 log_warn(LD_CRYPTO, "Unable to load required dynamic OpenSSL engine "
233 "\"%s\".", accelName+1);
234 return -1;
235 }
236 return 0;
237#else /* !defined(DISABLE_ENGINES) */
238 ENGINE *e = NULL;
239
240 log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
241 ENGINE_load_builtin_engines();
242 ENGINE_register_all_complete();
243
244 if (accelName) {
245 const bool required = accelName[0] == '!';
246 if (required)
247 ++accelName;
248 if (accelDir) {
249 log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
250 " via path \"%s\".", accelName, accelDir);
251 e = try_load_engine(accelName, accelDir);
252 } else {
253 log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
254 " acceleration support.", accelName);
255 e = ENGINE_by_id(accelName);
256 }
257 if (!e) {
258 log_warn(LD_CRYPTO, "Unable to load %sdynamic OpenSSL engine \"%s\".",
259 required?"required ":"",
260 accelName);
261 if (required)
262 return -1;
263 } else {
264 log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
265 accelName);
266 }
267 }
268 if (e) {
269 log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
270 " setting default ciphers.");
271 ENGINE_set_default(e, ENGINE_METHOD_ALL);
272 }
273 /* Log, if available, the intersection of the set of algorithms
274 used by Tor and the set of algorithms available in the engine */
275 log_engine("RSA", ENGINE_get_default_RSA());
276 log_engine("DH", ENGINE_get_default_DH());
277 log_engine("EC", ENGINE_get_default_EC());
278 log_engine("RAND", ENGINE_get_default_RAND());
279 log_engine("RAND (which we will not use)", ENGINE_get_default_RAND());
280 log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
281 log_engine("3DES-CBC", ENGINE_get_cipher_engine(NID_des_ede3_cbc));
282 log_engine("AES-128-ECB", ENGINE_get_cipher_engine(NID_aes_128_ecb));
283 log_engine("AES-128-CBC", ENGINE_get_cipher_engine(NID_aes_128_cbc));
284#ifdef NID_aes_128_ctr
285 log_engine("AES-128-CTR", ENGINE_get_cipher_engine(NID_aes_128_ctr));
286#endif
287#ifdef NID_aes_128_gcm
288 log_engine("AES-128-GCM", ENGINE_get_cipher_engine(NID_aes_128_gcm));
289#endif
290 log_engine("AES-256-CBC", ENGINE_get_cipher_engine(NID_aes_256_cbc));
291#ifdef NID_aes_256_gcm
292 log_engine("AES-256-GCM", ENGINE_get_cipher_engine(NID_aes_256_gcm));
293#endif
294 return 0;
295
296#endif /* defined(DISABLE_ENGINES) */
297}
298
299/** Perform late (post-init) initialization tasks for OpenSSL */
300int
301crypto_openssl_late_init(int useAccel, const char *accelName,
302 const char *accelDir)
303{
304 if (tor_OpenSSL_version_num() < OPENSSL_V_SERIES(3,0,0)) {
305 log_warn(LD_CRYPTO, "Running with OpenSSL version \"%s\", "
306 "which is no longer maintained by the OpenSSL project. "
307 "We recommend that you upgrade to OpenSSL 3.0 or later. "
308 "OpenSSL >=3.5 would be ideal.",
309 OPENSSL_VERSION_TEXT);
310 }
311
312 if (useAccel > 0) {
313 if (crypto_openssl_init_engines(accelName, accelDir) < 0)
314 return -1;
315 } else {
316 log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
317 }
318
320 if (crypto_seed_rng() < 0)
321 return -1;
322 }
323
324 evaluate_evp_for_aes(-1);
325 evaluate_ctr_for_aes();
326
327 return 0;
328}
329
330/** Free crypto resources held by this thread. */
331void
333{
334}
335
336/** Clean up global resources held by openssl. */
337void
339{
340 CONF_modules_unload(1);
341
343}
Headers for aes.c.
Header for compat_mutex.c.
const char * name
Definition: config.c:2471
void crypto_openssl_early_init(void)
static ENGINE * try_load_engine(const char *path, const char *engine)
void crypto_openssl_thread_cleanup(void)
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 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.