ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/tls_wolfssl.c
Revision: 9857
Committed: Fri Jan 1 04:43:22 2021 UTC (5 years, 9 months ago) by michael
Content type: text/x-csrc
File size: 11045 byte(s)
Log Message:
- Bump copyright years

File Contents

# User Rev Content
1 michael 9166 /*
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 michael 9857 * Copyright (c) 2005-2021 ircd-hybrid development team
7 michael 9166 *
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 michael 9189 * \version $Id$
27 michael 9166 */
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 michael 9224 tls_new_credentials(void)
104 michael 9166 {
105     TLS_initialized = false;
106    
107 michael 9202 if (ConfigServerInfo.tls_certificate_file == NULL || ConfigServerInfo.rsa_private_key_file == NULL)
108 michael 9166 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 michael 9202 if (wolfSSL_CTX_SetTmpDH_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_dh_param_file, SSL_FILETYPE_PEM) != SSL_SUCCESS)
133 michael 9166 ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_dh_param_file -- could not open/read Diffie-Hellman parameter file");
134    
135 michael 9279 #ifdef SSL_CTX_set1_groups_list
136 michael 9166 if (ConfigServerInfo.tls_supported_groups == NULL)
137 michael 9279 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 michael 9166 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 michael 9279 #endif
152 michael 9166
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 michael 9529 ssize_t ret = wolfSSL_read(ssl, buf, bufsize);
212 michael 9166
213     /* Translate wolfSSL error codes, sigh */
214 michael 9529 if (ret < 0)
215 michael 9166 {
216 michael 9529 switch (wolfSSL_get_error(ssl, ret))
217 michael 9166 {
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 michael 9529 ret = errno = 0;
234 michael 9166 }
235     }
236    
237 michael 9529 return ret;
238 michael 9166 }
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 michael 9529 ssize_t ret = wolfSSL_write(ssl, buf, bufsize);
245 michael 9166
246     /* Translate WolfSSL error codes, sigh */
247 michael 9529 if (ret < 0)
248 michael 9166 {
249 michael 9529 switch (wolfSSL_get_error(ssl, ret))
250 michael 9166 {
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 michael 9529 ret = errno = 0; /* Either an SSL-specific error or EOF */
265 michael 9166 }
266     }
267    
268 michael 9529 return ret;
269 michael 9166 }
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 michael 9224 tls_verify_certificate(tls_data_t *tls_data, tls_md_t digest, char **fingerprint)
347 michael 9166 {
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