ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/tls_wolfssl.c
Revision: 9279
Committed: Sun Feb 16 10:48:30 2020 UTC (5 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 11075 byte(s)
Log Message:
- tls_wolfssl.c: make use of recently added wolfSSL_CTX_set1_groups_list if available. Kudos to the guys at wolfSSL for implementing it that fast.

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 *
4 * Copyright (c) 2015 Attila Molnar <attilamolnar@hush.com>
5 * Copyright (c) 2015 Adam <Adam@anope.org>
6 * Copyright (c) 2005-2020 ircd-hybrid development team
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
21 * USA
22 */
23
24 /*! \file tls_wolfssl.c
25 * \brief Includes all wolfSSL-specific TLS functions
26 * \version $Id$
27 */
28
29 #include "stdinc.h"
30 #include "tls.h"
31 #include "conf.h"
32 #include "log.h"
33 #include "misc.h"
34 #include "memory.h"
35
36 #ifdef HAVE_TLS_WOLFSSL
37 #if LIBWOLFSSL_VERSION_HEX < 0x04003000
38 #error "wolfSSL 4.3.0 and above is required to build this module"
39 #endif
40
41 static bool TLS_initialized;
42
43 /*
44 * report_crypto_errors - Dump crypto error list to log
45 */
46 static void
47 report_crypto_errors(void)
48 {
49 unsigned long e;
50
51 while ((e = wolfSSL_ERR_get_error()))
52 ilog(LOG_TYPE_IRCD, "SSL error: %s", wolfSSL_ERR_error_string(e, 0));
53 }
54
55 static int
56 always_accept_verify_cb(int preverify_ok, WOLFSSL_X509_STORE_CTX *x509_ctx)
57 {
58 return 1;
59 }
60
61 bool
62 tls_is_initialized(void)
63 {
64 return TLS_initialized;
65 }
66
67 /* tls_init()
68 *
69 * inputs - nothing
70 * output - nothing
71 * side effects - setups SSL context.
72 */
73 void
74 tls_init(void)
75 {
76 wolfSSL_Init();
77
78 if ((ConfigServerInfo.tls_ctx.server_ctx = wolfSSL_CTX_new(wolfTLS_server_method())) == NULL)
79 {
80 ilog(LOG_TYPE_IRCD, "ERROR: Could not initialize the TLS server context -- wolfSSL_CTX_new failed");
81 exit(EXIT_FAILURE);
82 return; /* Not reached */
83 }
84
85 wolfSSL_CTX_SetMinVersion(ConfigServerInfo.tls_ctx.server_ctx, WOLFSSL_TLSV1_2);
86 wolfSSL_CTX_set_session_cache_mode(ConfigServerInfo.tls_ctx.server_ctx, SSL_SESS_CACHE_OFF);
87 wolfSSL_CTX_set_verify(ConfigServerInfo.tls_ctx.server_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, always_accept_verify_cb);
88 wolfSSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
89
90 if ((ConfigServerInfo.tls_ctx.client_ctx = wolfSSL_CTX_new(wolfTLS_client_method())) == NULL)
91 {
92 ilog(LOG_TYPE_IRCD, "ERROR: Could not initialize the TLS client context -- wolfSSL_CTX_new failed");
93 exit(EXIT_FAILURE);
94 return; /* Not reached */
95 }
96
97 wolfSSL_CTX_SetMinVersion(ConfigServerInfo.tls_ctx.client_ctx, WOLFSSL_TLSV1_2);
98 wolfSSL_CTX_set_session_cache_mode(ConfigServerInfo.tls_ctx.client_ctx, SSL_SESS_CACHE_OFF);
99 wolfSSL_CTX_set_verify(ConfigServerInfo.tls_ctx.client_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, always_accept_verify_cb);
100 }
101
102 bool
103 tls_new_credentials(void)
104 {
105 TLS_initialized = false;
106
107 if (ConfigServerInfo.tls_certificate_file == NULL || ConfigServerInfo.rsa_private_key_file == NULL)
108 return true;
109
110 if (wolfSSL_CTX_use_certificate_chain_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_certificate_file) != SSL_SUCCESS ||
111 wolfSSL_CTX_use_certificate_chain_file(ConfigServerInfo.tls_ctx.client_ctx, ConfigServerInfo.tls_certificate_file) != SSL_SUCCESS)
112 {
113 report_crypto_errors();
114 return false;
115 }
116
117 if (wolfSSL_CTX_use_PrivateKey_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) != SSL_SUCCESS ||
118 wolfSSL_CTX_use_PrivateKey_file(ConfigServerInfo.tls_ctx.client_ctx, ConfigServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) != SSL_SUCCESS)
119 {
120 report_crypto_errors();
121 return false;
122 }
123
124 if (wolfSSL_CTX_check_private_key(ConfigServerInfo.tls_ctx.server_ctx) != SSL_SUCCESS ||
125 wolfSSL_CTX_check_private_key(ConfigServerInfo.tls_ctx.client_ctx) != SSL_SUCCESS)
126 {
127 report_crypto_errors();
128 return false;
129 }
130
131 if (ConfigServerInfo.tls_dh_param_file)
132 if (wolfSSL_CTX_SetTmpDH_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_dh_param_file, SSL_FILETYPE_PEM) != SSL_SUCCESS)
133 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_dh_param_file -- could not open/read Diffie-Hellman parameter file");
134
135 #ifdef SSL_CTX_set1_groups_list
136 if (ConfigServerInfo.tls_supported_groups == NULL)
137 wolfSSL_CTX_set1_groups_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
138 else if (wolfSSL_CTX_set1_groups_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_supported_groups) != SSL_SUCCESS)
139 {
140 wolfSSL_CTX_set1_groups_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
141 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_supported_groups -- could not set supported group(s)");
142 }
143 #else
144 if (ConfigServerInfo.tls_supported_groups == NULL)
145 wolfSSL_CTX_set1_curves_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
146 else if (wolfSSL_CTX_set1_curves_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_supported_groups) != SSL_SUCCESS)
147 {
148 wolfSSL_CTX_set1_curves_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
149 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_supported_groups -- could not set supported group(s)");
150 }
151 #endif
152
153 if (ConfigServerInfo.tls_message_digest_algorithm == NULL)
154 ConfigServerInfo.message_digest_algorithm = wolfSSL_EVP_sha256();
155 else if ((ConfigServerInfo.message_digest_algorithm = wolfSSL_EVP_get_digestbyname(ConfigServerInfo.tls_message_digest_algorithm)) == NULL)
156 {
157 ConfigServerInfo.message_digest_algorithm = wolfSSL_EVP_sha256();
158 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_message_digest_algorithm -- unknown message digest algorithm");
159 }
160
161 if (ConfigServerInfo.tls_cipher_list == NULL)
162 wolfSSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
163 else if (wolfSSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_cipher_list) != SSL_SUCCESS)
164 {
165 wolfSSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
166 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_cipher_list -- could not set supported cipher(s)");
167 }
168
169 TLS_initialized = true;
170 return true;
171 }
172
173 const char *
174 tls_get_cipher(const tls_data_t *tls_data)
175 {
176 static char buf[128];
177 WOLFSSL *ssl = *tls_data;
178
179 snprintf(buf, sizeof(buf), "%s-%s", wolfSSL_get_version(ssl), wolfSSL_get_cipher(ssl));
180 return buf;
181 }
182
183 const char *
184 tls_get_version(void)
185 {
186 static char buf[256];
187
188 snprintf(buf, sizeof(buf), "wolfSSL version: library: %s, header: %s",
189 wolfSSL_lib_version(), LIBWOLFSSL_VERSION_STRING);
190 return buf;
191 }
192
193 bool
194 tls_isusing(tls_data_t *tls_data)
195 {
196 WOLFSSL *ssl = *tls_data;
197 return ssl != NULL;
198 }
199
200 void
201 tls_free(tls_data_t *tls_data)
202 {
203 wolfSSL_free(*tls_data);
204 *tls_data = NULL;
205 }
206
207 ssize_t
208 tls_read(tls_data_t *tls_data, char *buf, size_t bufsize, bool *want_write)
209 {
210 WOLFSSL *ssl = *tls_data;
211 ssize_t length = wolfSSL_read(ssl, buf, bufsize);
212
213 /* Translate wolfSSL error codes, sigh */
214 if (length < 0)
215 {
216 switch (wolfSSL_get_error(ssl, length))
217 {
218 case SSL_ERROR_WANT_WRITE:
219 {
220 /* wolfSSL wants to write, we signal this to the caller and do nothing about that here */
221 *want_write = true;
222 break;
223 }
224 case SSL_ERROR_WANT_READ:
225 errno = EWOULDBLOCK;
226 case SSL_ERROR_SYSCALL:
227 break;
228 case SSL_ERROR_SSL:
229 if (errno == EAGAIN)
230 break;
231 /* Fall through */
232 default:
233 length = errno = 0;
234 }
235 }
236
237 return length;
238 }
239
240 ssize_t
241 tls_write(tls_data_t *tls_data, const char *buf, size_t bufsize, bool *want_read)
242 {
243 WOLFSSL *ssl = *tls_data;
244 ssize_t retlen = wolfSSL_write(ssl, buf, bufsize);
245
246 /* Translate WolfSSL error codes, sigh */
247 if (retlen < 0)
248 {
249 switch (wolfSSL_get_error(ssl, retlen))
250 {
251 case SSL_ERROR_WANT_READ:
252 *want_read = true;
253 break; /* Retry later, don't register for write events */
254 case SSL_ERROR_WANT_WRITE:
255 errno = EWOULDBLOCK;
256 break;
257 case SSL_ERROR_SYSCALL:
258 break;
259 case SSL_ERROR_SSL:
260 if (errno == EAGAIN)
261 break;
262 /* Fall through */
263 default:
264 retlen = errno = 0; /* Either an SSL-specific error or EOF */
265 }
266 }
267
268 return retlen;
269 }
270
271 void
272 tls_shutdown(tls_data_t *tls_data)
273 {
274 WOLFSSL *ssl = *tls_data;
275 int ret = wolfSSL_shutdown(ssl);
276
277 if (ret == WOLFSSL_SHUTDOWN_NOT_DONE)
278 wolfSSL_shutdown(ssl);
279 }
280
281 bool
282 tls_new(tls_data_t *tls_data, int fd, tls_role_t role)
283 {
284 WOLFSSL *ssl;
285
286 if (TLS_initialized == false)
287 return false;
288
289 if (role == TLS_ROLE_SERVER)
290 ssl = wolfSSL_new(ConfigServerInfo.tls_ctx.server_ctx);
291 else
292 ssl = wolfSSL_new(ConfigServerInfo.tls_ctx.client_ctx);
293
294 if (ssl == NULL)
295 {
296 ilog(LOG_TYPE_IRCD, "wolfSSL_new() ERROR! -- %s",
297 wolfSSL_ERR_error_string(wolfSSL_ERR_get_error(), NULL));
298 return false;
299 }
300
301 *tls_data = ssl;
302 wolfSSL_set_fd(ssl, fd);
303 return true;
304 }
305
306 bool
307 tls_set_ciphers(tls_data_t *tls_data, const char *cipher_list)
308 {
309 wolfSSL_set_cipher_list(*tls_data, cipher_list);
310 return true;
311 }
312
313 tls_handshake_status_t
314 tls_handshake(tls_data_t *tls_data, tls_role_t role, const char **errstr)
315 {
316 WOLFSSL *ssl = *tls_data;
317 int ret;
318
319 if (role == TLS_ROLE_SERVER)
320 ret = wolfSSL_accept(ssl);
321 else
322 ret = wolfSSL_connect(ssl);
323
324 if (ret == WOLFSSL_SUCCESS)
325 return TLS_HANDSHAKE_DONE;
326
327 switch (wolfSSL_get_error(ssl, ret))
328 {
329 case WOLFSSL_ERROR_WANT_WRITE:
330 return TLS_HANDSHAKE_WANT_WRITE;
331 case WOLFSSL_ERROR_WANT_READ:
332 return TLS_HANDSHAKE_WANT_READ;
333 default:
334 {
335 const char *error = wolfSSL_ERR_error_string(wolfSSL_ERR_get_error(), NULL);
336
337 if (errstr)
338 *errstr = error;
339
340 return TLS_HANDSHAKE_ERROR;
341 }
342 }
343 }
344
345 bool
346 tls_verify_certificate(tls_data_t *tls_data, tls_md_t digest, char **fingerprint)
347 {
348 WOLFSSL *ssl = *tls_data;
349 unsigned int n;
350 char buf[EVP_MAX_MD_SIZE * 2 + 1];
351 unsigned char md[EVP_MAX_MD_SIZE];
352 bool ret = false;
353
354 /* Accept NULL return from SSL_get_peer_certificate */
355 WOLFSSL_X509 *cert = wolfSSL_get_peer_certificate(ssl);
356 if (cert == NULL)
357 return true;
358
359 switch (wolfSSL_get_verify_result(ssl))
360 {
361 case X509_V_OK:
362 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
363 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
364 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
365 ret = true;
366
367 if (wolfSSL_X509_digest(cert, digest, md, &n))
368 {
369 binary_to_hex(md, buf, n);
370 *fingerprint = xstrdup(buf);
371 }
372 default:
373 break;
374 }
375
376 wolfSSL_X509_free(cert);
377 return ret;
378 }
379 #endif /* HAVE_TLS_WOLFSSL */

Properties

Name Value
svn:eol-style native
svn:keywords Id