crypto_openssl_mgt.c (10861B)
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" 14 #include "lib/crypt_ops/crypto_openssl_mgt.h" 15 #include "lib/crypt_ops/crypto_rand.h" 16 #include "lib/crypt_ops/aes.h" 17 #include "lib/string/util_string.h" 18 #include "lib/lock/compat_mutex.h" 19 #include "lib/log/log.h" 20 #include "lib/log/util_bug.h" 21 #include "lib/testsupport/testsupport.h" 22 #include "lib/thread/threads.h" 23 24 DISABLE_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 39 ENABLE_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 */ 49 STATIC 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 */ 54 void 55 crypto_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' */ 75 STATIC char * 76 parse_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 93 static char *crypto_openssl_version_str = NULL; 94 /* Return a human-readable version of the run-time openssl version number. */ 95 const char * 96 crypto_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 107 static char *crypto_openssl_header_version_str = NULL; 108 /* Return a human-readable version of the compile-time openssl version 109 * number. */ 110 const char * 111 crypto_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. */ 129 static int 130 setup_openssl_threading(void) 131 { 132 return 0; 133 } 134 135 /** free OpenSSL variables */ 136 static void 137 crypto_openssl_free_all(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. */ 144 void 145 crypto_openssl_early_init(void) 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 152 setup_openssl_threading(); 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 176 crypto_force_rand_ssleay(); 177 } 178 179 #ifndef DISABLE_ENGINES 180 /** Try to load an engine in a shared library via fully qualified path. 181 */ 182 static ENGINE * 183 try_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. */ 201 static void 202 log_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. */ 223 static int 224 crypto_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 */ 300 int 301 crypto_openssl_late_init(int useAccel, const char *accelName, 302 const char *accelDir) 303 { 304 #ifndef LIBRESSL_VERSION_NUMBER 305 if (tor_OpenSSL_version_num() < OPENSSL_V_SERIES(3,0,0)) { 306 log_warn(LD_CRYPTO, "Running with OpenSSL version \"%s\", " 307 "which is no longer maintained by the OpenSSL project. " 308 "We recommend that you upgrade to OpenSSL 3.0 or later. " 309 "OpenSSL >=3.5 would be ideal.", 310 OPENSSL_VERSION_TEXT); 311 } 312 #endif 313 314 if (useAccel > 0) { 315 if (crypto_openssl_init_engines(accelName, accelDir) < 0) 316 return -1; 317 } else { 318 log_info(LD_CRYPTO, "NOT using OpenSSL engine support."); 319 } 320 321 if (crypto_force_rand_ssleay()) { 322 if (crypto_seed_rng() < 0) 323 return -1; 324 } 325 326 return 0; 327 } 328 329 /** Free crypto resources held by this thread. */ 330 void 331 crypto_openssl_thread_cleanup(void) 332 { 333 } 334 335 /** Clean up global resources held by openssl. */ 336 void 337 crypto_openssl_global_cleanup(void) 338 { 339 CONF_modules_unload(1); 340 341 crypto_openssl_free_all(); 342 }