Coverage Report

Created: 2026-07-16 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwebsockets/lib/tls/openssl/openssl-tls.c
Line
Count
Source
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
28
extern int openssl_websocket_private_data_index,
29
     openssl_SSL_CTX_private_data_index;
30
#if defined(LWS_WITH_NETWORK)
31
static char openssl_ex_indexes_acquired;
32
#endif
33
static int openssl_contexts_using_global_init;
34
35
void
36
lws_tls_err_describe_clear(void)
37
0
{
38
0
  char buf[160];
39
0
  unsigned long l;
40
41
0
  do {
42
0
    l = ERR_peek_error();
43
0
    if (!l)
44
0
      break;
45
46
0
    ERR_error_string_n(LWS_TLS_ERR_CAST(ERR_get_error()), buf, sizeof(buf));
47
0
    lwsl_info("   openssl error: %s\n", buf);
48
0
  } while (l);
49
0
  lwsl_info("\n");
50
0
}
51
52
#if LWS_MAX_SMP != 1
53
54
static pthread_mutex_t *openssl_mutexes = NULL;
55
56
static void
57
lws_openssl_lock_callback(int mode, int type, const char *file, int line)
58
{
59
  (void)file;
60
  (void)line;
61
62
  if (mode & CRYPTO_LOCK)
63
    pthread_mutex_lock(&openssl_mutexes[type]);
64
  else
65
    pthread_mutex_unlock(&openssl_mutexes[type]);
66
}
67
68
static unsigned long
69
lws_openssl_thread_id(void)
70
{
71
#ifdef __PTW32_H
72
  return (unsigned long)(intptr_t)(pthread_self()).p;
73
#else
74
  return (unsigned long)pthread_self();
75
#endif
76
}
77
#endif
78
79
int
80
lws_context_init_ssl_library(struct lws_context *cx,
81
                             const struct lws_context_creation_info *info)
82
0
{
83
0
  if (!lws_check_opt(info->options, LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT)) {
84
0
#if !defined(LWS_WITH_MBEDTLS) && defined(LWS_WITH_NETWORK)
85
0
    if (!info->provided_client_ssl_ctx)
86
0
#endif
87
0
      lwsl_cx_info(cx, " SSL disabled: no "
88
0
        "LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT");
89
0
    return 0;
90
0
  }
91
92
  /* basic openssl init */
93
94
0
  if (!openssl_contexts_using_global_init++) {
95
96
#if OPENSSL_VERSION_NUMBER < 0x10100000L
97
    SSL_library_init();
98
    OpenSSL_add_all_algorithms();
99
    SSL_load_error_strings();
100
#else
101
0
    OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);
102
0
#endif
103
0
  }
104
0
#if defined(LWS_WITH_NETWORK)
105
0
  if (!openssl_ex_indexes_acquired) {
106
0
    openssl_websocket_private_data_index =
107
0
      SSL_get_ex_new_index(0, "lws", NULL, NULL, NULL);
108
109
0
    openssl_SSL_CTX_private_data_index =
110
0
      SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
111
112
0
    openssl_ex_indexes_acquired = 1;
113
0
  }
114
0
#endif
115
116
#if LWS_MAX_SMP != 1
117
  {
118
    int n;
119
120
    openssl_mutexes = (pthread_mutex_t *)
121
        OPENSSL_malloc((size_t)((unsigned long)CRYPTO_num_locks() *
122
                 (unsigned long)sizeof(openssl_mutexes[0])));
123
124
    for (n = 0; n < CRYPTO_num_locks(); n++)
125
      pthread_mutex_init(&openssl_mutexes[n], NULL);
126
127
    /*
128
     * These "functions" disappeared in later OpenSSL which is
129
     * already threadsafe.
130
     */
131
132
    (void)lws_openssl_thread_id;
133
    (void)lws_openssl_lock_callback;
134
135
    CRYPTO_set_id_callback(lws_openssl_thread_id);
136
    CRYPTO_set_locking_callback(lws_openssl_lock_callback);
137
  }
138
#endif
139
140
0
  return 0;
141
0
}
142
143
void
144
lws_context_deinit_ssl_library(struct lws_context *context)
145
0
{
146
0
  if (!lws_check_opt(context->options,
147
0
         LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT))
148
0
    return;
149
150
#if LWS_MAX_SMP != 1
151
  int n;
152
153
  CRYPTO_set_locking_callback(NULL);
154
155
  if (openssl_mutexes) {
156
    for (n = 0; n < CRYPTO_num_locks(); n++)
157
      pthread_mutex_destroy(&openssl_mutexes[n]);
158
159
    OPENSSL_free(openssl_mutexes);
160
    openssl_mutexes = NULL;
161
  }
162
#endif
163
164
0
  --openssl_contexts_using_global_init;
165
0
}