ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/tls_openssl.c
Revision: 9935
Committed: Thu May 13 07:06:31 2021 UTC (5 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 12261 byte(s)
Log Message:
- tls_openssl: cleanly build with openssl 3.0;  use OSSL_STORE api to retrieve dh parameters;  replace deprecated functions

File Contents

# User Rev Content
1 michael 7105 /*
2     * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3     *
4 michael 7148 * Copyright (c) 2015 Attila Molnar <attilamolnar@hush.com>
5     * Copyright (c) 2015 Adam <Adam@anope.org>
6 michael 9857 * Copyright (c) 2005-2021 ircd-hybrid development team
7 michael 7105 *
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_openssl.c
25     * \brief Includes all OpenSSL-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 michael 7152 #include "misc.h"
34 michael 7105 #include "memory.h"
35    
36     #ifdef HAVE_TLS_OPENSSL
37 michael 9137 #if OPENSSL_VERSION_NUMBER < 0x1010100fL
38 michael 9131 #error "OpenSSL 1.1.1 and above is required to build this module"
39     #endif
40 michael 7105
41 michael 8664 static bool TLS_initialized;
42 michael 7271
43 michael 7152 /*
44     * report_crypto_errors - Dump crypto error list to log
45     */
46     static void
47     report_crypto_errors(void)
48     {
49 michael 9137 unsigned long e;
50 michael 7152
51     while ((e = ERR_get_error()))
52     ilog(LOG_TYPE_IRCD, "SSL error: %s", ERR_error_string(e, 0));
53     }
54    
55 michael 7105 static int
56     always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
57     {
58     return 1;
59     }
60    
61 michael 8664 bool
62 michael 7271 tls_is_initialized(void)
63     {
64     return TLS_initialized;
65     }
66    
67 michael 7105 /* tls_init()
68     *
69     * inputs - nothing
70     * output - nothing
71     * side effects - setups SSL context.
72     */
73     void
74     tls_init(void)
75     {
76 michael 9131 if ((ConfigServerInfo.tls_ctx.server_ctx = SSL_CTX_new(TLS_server_method())) == NULL)
77 michael 7105 {
78     const char *s = ERR_lib_error_string(ERR_get_error());
79    
80 michael 9131 ilog(LOG_TYPE_IRCD, "ERROR: Could not initialize the TLS server context -- %s", s);
81 michael 7105 exit(EXIT_FAILURE);
82     return; /* Not reached */
83     }
84    
85 michael 9131 SSL_CTX_set_min_proto_version(ConfigServerInfo.tls_ctx.server_ctx, TLS1_2_VERSION);
86     SSL_CTX_set_options(ConfigServerInfo.tls_ctx.server_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE|SSL_OP_NO_TICKET);
87     SSL_CTX_set_verify(ConfigServerInfo.tls_ctx.server_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, always_accept_verify_cb);
88 michael 7105 SSL_CTX_set_session_cache_mode(ConfigServerInfo.tls_ctx.server_ctx, SSL_SESS_CACHE_OFF);
89     SSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
90    
91 michael 9131 if ((ConfigServerInfo.tls_ctx.client_ctx = SSL_CTX_new(TLS_client_method())) == NULL)
92 michael 7105 {
93     const char *s = ERR_lib_error_string(ERR_get_error());
94    
95 michael 9131 ilog(LOG_TYPE_IRCD, "ERROR: Could not initialize the TLS client context -- %s", s);
96 michael 7105 exit(EXIT_FAILURE);
97     return; /* Not reached */
98     }
99    
100 michael 9131 SSL_CTX_set_min_proto_version(ConfigServerInfo.tls_ctx.client_ctx, TLS1_2_VERSION);
101     SSL_CTX_set_options(ConfigServerInfo.tls_ctx.client_ctx, SSL_OP_NO_TICKET);
102     SSL_CTX_set_verify(ConfigServerInfo.tls_ctx.client_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE, always_accept_verify_cb);
103 michael 7105 SSL_CTX_set_session_cache_mode(ConfigServerInfo.tls_ctx.client_ctx, SSL_SESS_CACHE_OFF);
104     }
105    
106 michael 8664 bool
107 michael 9224 tls_new_credentials(void)
108 michael 7105 {
109 michael 8664 TLS_initialized = false;
110 michael 7271
111 michael 9202 if (ConfigServerInfo.tls_certificate_file == NULL || ConfigServerInfo.rsa_private_key_file == NULL)
112 michael 8664 return true;
113 michael 7105
114 michael 9202 if (SSL_CTX_use_certificate_chain_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_certificate_file) != 1 ||
115     SSL_CTX_use_certificate_chain_file(ConfigServerInfo.tls_ctx.client_ctx, ConfigServerInfo.tls_certificate_file) != 1)
116 michael 7105 {
117     report_crypto_errors();
118 michael 8664 return false;
119 michael 7105 }
120    
121 michael 9202 if (SSL_CTX_use_PrivateKey_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) != 1 ||
122     SSL_CTX_use_PrivateKey_file(ConfigServerInfo.tls_ctx.client_ctx, ConfigServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) != 1)
123 michael 7105 {
124     report_crypto_errors();
125 michael 8664 return false;
126 michael 7105 }
127    
128 michael 9202 if (SSL_CTX_check_private_key(ConfigServerInfo.tls_ctx.server_ctx) != 1 ||
129     SSL_CTX_check_private_key(ConfigServerInfo.tls_ctx.client_ctx) != 1)
130 michael 7105 {
131     report_crypto_errors();
132 michael 8664 return false;
133 michael 7105 }
134    
135 michael 9145 if (ConfigServerInfo.tls_dh_param_file)
136 michael 7105 {
137 michael 9935 #if OPENSSL_VERSION_NUMBER < 0x30000000L
138 michael 9145 BIO *file = BIO_new_file(ConfigServerInfo.tls_dh_param_file, "r");
139 michael 7105
140     if (file)
141     {
142     DH *dh = PEM_read_bio_DHparams(file, NULL, NULL, NULL);
143    
144     BIO_free(file);
145    
146     if (dh)
147     {
148 michael 7387 SSL_CTX_set_tmp_dh(ConfigServerInfo.tls_ctx.server_ctx, dh);
149 michael 7105 DH_free(dh);
150     }
151     }
152     else
153 michael 9145 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_dh_param_file -- could not open/read Diffie-Hellman parameter file");
154 michael 9935 #else
155     EVP_PKEY *dhpkey = NULL;
156     OSSL_STORE_CTX *ctx = OSSL_STORE_open(ConfigServerInfo.tls_dh_param_file, NULL, NULL, NULL, NULL);
157     if (ctx)
158     {
159     if (OSSL_STORE_expect(ctx, OSSL_STORE_INFO_PARAMS))
160     {
161     while (OSSL_STORE_eof(ctx) == 0)
162     {
163     OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
164     if (info)
165     {
166     dhpkey = OSSL_STORE_INFO_get1_PARAMS(info);
167     OSSL_STORE_INFO_free(info);
168    
169     if (dhpkey)
170     {
171     if (EVP_PKEY_is_a(dhpkey, "DH"))
172     if (SSL_CTX_set0_tmp_dh_pkey(ConfigServerInfo.tls_ctx.server_ctx, dhpkey))
173     break;
174    
175     EVP_PKEY_free(dhpkey);
176     dhpkey = NULL;
177     }
178     }
179     }
180     }
181    
182     OSSL_STORE_close(ctx);
183     }
184    
185     if (dhpkey == NULL)
186     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_dh_param_file -- could not open/read Diffie-Hellman parameter file");
187     #endif
188 michael 7105 }
189    
190 michael 9145 if (ConfigServerInfo.tls_supported_groups == NULL)
191 michael 9143 SSL_CTX_set1_groups_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
192 michael 9145 else if (SSL_CTX_set1_groups_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_supported_groups) == 0)
193 michael 9143 {
194 michael 9153 SSL_CTX_set1_groups_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
195 michael 9145 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_supported_groups -- could not set supported group(s)");
196 michael 9143 }
197 michael 7105
198 michael 9145 if (ConfigServerInfo.tls_message_digest_algorithm == NULL)
199 michael 7105 ConfigServerInfo.message_digest_algorithm = EVP_sha256();
200 michael 9153 else if ((ConfigServerInfo.message_digest_algorithm = EVP_get_digestbyname(ConfigServerInfo.tls_message_digest_algorithm)) == NULL)
201 michael 7105 {
202 michael 9153 ConfigServerInfo.message_digest_algorithm = EVP_sha256();
203     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_message_digest_algorithm -- unknown message digest algorithm");
204 michael 7105 }
205    
206 michael 9159 if (ConfigServerInfo.tls_cipher_list == NULL)
207     SSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
208     else if (SSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_cipher_list) == 0)
209     {
210     SSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
211     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_cipher_list -- could not set supported cipher(s)");
212     }
213 michael 7190
214 michael 9139 #ifndef LIBRESSL_VERSION_NUMBER
215     if (ConfigServerInfo.tls_cipher_suites == NULL)
216 michael 9151 SSL_CTX_set_ciphersuites(ConfigServerInfo.tls_ctx.server_ctx, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256");
217 michael 9139 else if (SSL_CTX_set_ciphersuites(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_cipher_suites) == 0)
218     {
219 michael 9153 SSL_CTX_set_ciphersuites(ConfigServerInfo.tls_ctx.server_ctx, "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256");
220 michael 9139 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_cipher_suites -- could not set supported cipher suite(s)");
221     }
222     #endif
223    
224 michael 8664 TLS_initialized = true;
225     return true;
226 michael 7105 }
227    
228     const char *
229     tls_get_cipher(const tls_data_t *tls_data)
230     {
231 michael 9165 static char buf[128];
232 michael 7105 SSL *ssl = *tls_data;
233    
234 michael 9165 snprintf(buf, sizeof(buf), "%s-%s", SSL_get_version(ssl), SSL_get_cipher(ssl));
235     return buf;
236 michael 7105 }
237    
238 michael 7708 const char *
239     tls_get_version(void)
240     {
241 michael 9165 static char buf[256];
242 michael 7708
243     snprintf(buf, sizeof(buf), "OpenSSL version: library: %s, header: %s",
244 michael 9131 OpenSSL_version(OPENSSL_VERSION), OPENSSL_VERSION_TEXT);
245 michael 7708 return buf;
246     }
247    
248 michael 8664 bool
249 michael 7105 tls_isusing(tls_data_t *tls_data)
250     {
251     SSL *ssl = *tls_data;
252 michael 7124 return ssl != NULL;
253 michael 7105 }
254    
255     void
256     tls_free(tls_data_t *tls_data)
257     {
258     SSL_free(*tls_data);
259     *tls_data = NULL;
260     }
261    
262 michael 8956 ssize_t
263 michael 8660 tls_read(tls_data_t *tls_data, char *buf, size_t bufsize, bool *want_write)
264 michael 7105 {
265 michael 9527 ERR_clear_error();
266    
267 michael 7105 SSL *ssl = *tls_data;
268 michael 9529 ssize_t ret = SSL_read(ssl, buf, bufsize);
269 michael 7105 /* Translate openssl error codes, sigh */
270 michael 9529 if (ret < 0)
271 michael 7105 {
272 michael 9529 switch (SSL_get_error(ssl, ret))
273 michael 7105 {
274     case SSL_ERROR_WANT_WRITE:
275     {
276     /* OpenSSL wants to write, we signal this to the caller and do nothing about that here */
277 michael 8660 *want_write = true;
278 michael 7105 break;
279     }
280     case SSL_ERROR_WANT_READ:
281     errno = EWOULDBLOCK;
282     case SSL_ERROR_SYSCALL:
283     break;
284     case SSL_ERROR_SSL:
285     if (errno == EAGAIN)
286     break;
287     /* Fall through */
288     default:
289 michael 9529 ret = errno = 0;
290 michael 7105 }
291     }
292    
293 michael 9529 return ret;
294 michael 7105 }
295    
296 michael 8956 ssize_t
297 michael 8660 tls_write(tls_data_t *tls_data, const char *buf, size_t bufsize, bool *want_read)
298 michael 7105 {
299 michael 9527 ERR_clear_error();
300    
301 michael 7105 SSL *ssl = *tls_data;
302 michael 9529 ssize_t ret = SSL_write(ssl, buf, bufsize);
303 michael 7105 /* Translate openssl error codes, sigh */
304 michael 9529 if (ret < 0)
305 michael 7105 {
306 michael 9529 switch (SSL_get_error(ssl, ret))
307 michael 7105 {
308     case SSL_ERROR_WANT_READ:
309 michael 8660 *want_read = true;
310 michael 7105 break; /* Retry later, don't register for write events */
311     case SSL_ERROR_WANT_WRITE:
312     errno = EWOULDBLOCK;
313     break;
314     case SSL_ERROR_SYSCALL:
315     break;
316     case SSL_ERROR_SSL:
317     if (errno == EAGAIN)
318     break;
319     /* Fall through */
320     default:
321 michael 9529 ret = errno = 0; /* Either an SSL-specific error or EOF */
322 michael 7105 }
323     }
324    
325 michael 9529 return ret;
326 michael 7105 }
327    
328     void
329     tls_shutdown(tls_data_t *tls_data)
330     {
331     SSL *ssl = *tls_data;
332    
333     SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
334    
335 michael 9137 if (SSL_shutdown(ssl) == 0)
336 michael 7105 SSL_shutdown(ssl);
337     }
338    
339 michael 8664 bool
340 michael 7105 tls_new(tls_data_t *tls_data, int fd, tls_role_t role)
341     {
342     SSL *ssl;
343    
344 michael 8664 if (TLS_initialized == false)
345     return false;
346 michael 7274
347 michael 7105 if (role == TLS_ROLE_SERVER)
348     ssl = SSL_new(ConfigServerInfo.tls_ctx.server_ctx);
349     else
350     ssl = SSL_new(ConfigServerInfo.tls_ctx.client_ctx);
351    
352 michael 9137 if (ssl == NULL)
353 michael 7105 {
354     ilog(LOG_TYPE_IRCD, "SSL_new() ERROR! -- %s",
355     ERR_error_string(ERR_get_error(), NULL));
356 michael 8664 return false;
357 michael 7105 }
358    
359     *tls_data = ssl;
360     SSL_set_fd(ssl, fd);
361 michael 8664 return true;
362 michael 7105 }
363    
364 michael 8664 bool
365 michael 7105 tls_set_ciphers(tls_data_t *tls_data, const char *cipher_list)
366     {
367     SSL_set_cipher_list(*tls_data, cipher_list);
368 michael 8664 return true;
369 michael 7105 }
370    
371     tls_handshake_status_t
372     tls_handshake(tls_data_t *tls_data, tls_role_t role, const char **errstr)
373     {
374     SSL *ssl = *tls_data;
375     int ret;
376    
377 michael 9527 ERR_clear_error();
378    
379 michael 7105 if (role == TLS_ROLE_SERVER)
380     ret = SSL_accept(ssl);
381     else
382     ret = SSL_connect(ssl);
383    
384     if (ret > 0)
385     return TLS_HANDSHAKE_DONE;
386    
387     switch (SSL_get_error(ssl, ret))
388     {
389     case SSL_ERROR_WANT_WRITE:
390     return TLS_HANDSHAKE_WANT_WRITE;
391     case SSL_ERROR_WANT_READ:
392     return TLS_HANDSHAKE_WANT_READ;
393     default:
394     {
395     const char *error = ERR_error_string(ERR_get_error(), NULL);
396    
397     if (errstr)
398     *errstr = error;
399    
400     return TLS_HANDSHAKE_ERROR;
401     }
402     }
403     }
404    
405 michael 8664 bool
406 michael 9224 tls_verify_certificate(tls_data_t *tls_data, tls_md_t digest, char **fingerprint)
407 michael 7105 {
408     SSL *ssl = *tls_data;
409     unsigned int n;
410     char buf[EVP_MAX_MD_SIZE * 2 + 1];
411     unsigned char md[EVP_MAX_MD_SIZE];
412 michael 8664 bool ret = false;
413 michael 7105
414     /* Accept NULL return from SSL_get_peer_certificate */
415 michael 8961 X509 *cert = SSL_get_peer_certificate(ssl);
416     if (cert == NULL)
417 michael 8664 return true;
418 michael 7105
419 michael 8961 switch (SSL_get_verify_result(ssl))
420 michael 7105 {
421 michael 8961 case X509_V_OK:
422     case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
423     case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
424     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
425     ret = true;
426 michael 7105
427 michael 8961 if (X509_digest(cert, digest, md, &n))
428     {
429     binary_to_hex(md, buf, n);
430     *fingerprint = xstrdup(buf);
431     }
432     default:
433     break;
434 michael 7105 }
435    
436     X509_free(cert);
437     return ret;
438     }
439     #endif /* HAVE_TLS_OPENSSL */

Properties

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