1/* 2 * libwebsockets - small server side websockets and web server implementation 3 * 4 * Copyright (C) 2010 - 2021 Andy Green <andy@warmcat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to 8 * deal in the Software without restriction, including without limitation the 9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 10 * sell copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#include "private-lib-core.h" 26#include "private-lib-tls-openssl.h" 27 28extern int openssl_websocket_private_data_index, 29 openssl_SSL_CTX_private_data_index; 30#if defined(LWS_WITH_NETWORK) 31static char openssl_ex_indexes_acquired; 32#endif 33 34void 35lws_tls_err_describe_clear(void) 36{ 37 char buf[160]; 38 unsigned long l; 39 40 do { 41 l = ERR_get_error(); 42 if (!l) 43 break; 44 45 ERR_error_string_n( 46#if defined(LWS_WITH_BORINGSSL) 47 (uint32_t) 48#endif 49 l, buf, sizeof(buf)); 50 lwsl_info(" openssl error: %s\n", buf); 51 } while (l); 52 lwsl_info("\n"); 53} 54 55#if LWS_MAX_SMP != 1 56 57static pthread_mutex_t *openssl_mutexes = NULL; 58 59static void 60lws_openssl_lock_callback(int mode, int type, const char *file, int line) 61{ 62 (void)file; 63 (void)line; 64 65 if (mode & CRYPTO_LOCK) 66 pthread_mutex_lock(&openssl_mutexes[type]); 67 else 68 pthread_mutex_unlock(&openssl_mutexes[type]); 69} 70 71static unsigned long 72lws_openssl_thread_id(void) 73{ 74#ifdef __PTW32_H 75 return (unsigned long)(intptr_t)(pthread_self()).p; 76#else 77 return (unsigned long)pthread_self(); 78#endif 79} 80#endif 81 82int 83lws_context_init_ssl_library(struct lws_context *cx, 84 const struct lws_context_creation_info *info) 85{ 86#ifdef USE_WOLFSSL 87#ifdef USE_OLD_CYASSL 88 lwsl_cx_info(cx, " Compiled with CyaSSL support"); 89#else 90 lwsl_cx_info(cx, " Compiled with wolfSSL support"); 91#endif 92#else 93#if defined(LWS_WITH_BORINGSSL) 94 lwsl_cx_info(cx, " Compiled with BoringSSL support"); 95#else 96 lwsl_cx_info(cx, " Compiled with OpenSSL support"); 97#endif 98#endif 99 if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) { 100 lwsl_cx_info(cx, " SSL disabled: no " 101 "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT"); 102 return 0; 103 } 104 105 /* basic openssl init */ 106 107 lwsl_cx_info(cx, "Doing SSL library init"); 108 109#if OPENSSL_VERSION_NUMBER < 0x10100000L 110 SSL_library_init(); 111 OpenSSL_add_all_algorithms(); 112 SSL_load_error_strings(); 113#else 114 OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL); 115#endif 116#if defined(LWS_WITH_NETWORK) 117 if (!openssl_ex_indexes_acquired) { 118 openssl_websocket_private_data_index = 119 SSL_get_ex_new_index(0, "lws", NULL, NULL, NULL); 120 121 openssl_SSL_CTX_private_data_index = 122 SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); 123 124 openssl_ex_indexes_acquired = 1; 125 } 126#endif 127 128#if LWS_MAX_SMP != 1 129 { 130 int n; 131 132 openssl_mutexes = (pthread_mutex_t *) 133 OPENSSL_malloc((size_t)((unsigned long)CRYPTO_num_locks() * 134 (unsigned long)sizeof(openssl_mutexes[0]))); 135 136 for (n = 0; n < CRYPTO_num_locks(); n++) 137 pthread_mutex_init(&openssl_mutexes[n], NULL); 138 139 /* 140 * These "functions" disappeared in later OpenSSL which is 141 * already threadsafe. 142 */ 143 144 (void)lws_openssl_thread_id; 145 (void)lws_openssl_lock_callback; 146 147 CRYPTO_set_id_callback(lws_openssl_thread_id); 148 CRYPTO_set_locking_callback(lws_openssl_lock_callback); 149 } 150#endif 151 152 return 0; 153} 154 155void 156lws_context_deinit_ssl_library(struct lws_context *context) 157{ 158#if LWS_MAX_SMP != 1 159 int n; 160 161 if (!lws_check_opt(context->options, 162 LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) 163 return; 164 165 CRYPTO_set_locking_callback(NULL); 166 167 if (openssl_mutexes) { 168 for (n = 0; n < CRYPTO_num_locks(); n++) 169 pthread_mutex_destroy(&openssl_mutexes[n]); 170 171 OPENSSL_free(openssl_mutexes); 172 openssl_mutexes = NULL; 173 } 174#endif 175} 176