ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/tls_wolfssl.c
Revision: 9202
Committed: Fri Jan 24 23:52:04 2020 UTC (6 years, 8 months ago) by michael
Content type: text/x-csrc
File size: 10543 byte(s)
Log Message:
- Stylistic changes

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     * 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 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     tls_new_cred(void)
104     {
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     if (ConfigServerInfo.tls_supported_groups == NULL)
136     wolfSSL_CTX_set1_curves_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
137     else if (wolfSSL_CTX_set1_curves_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_supported_groups) != SSL_SUCCESS)
138     {
139     wolfSSL_CTX_set1_curves_list(ConfigServerInfo.tls_ctx.server_ctx, "X25519:P-256");
140     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_supported_groups -- could not set supported group(s)");
141     }
142    
143     if (ConfigServerInfo.tls_message_digest_algorithm == NULL)
144     ConfigServerInfo.message_digest_algorithm = wolfSSL_EVP_sha256();
145     else if ((ConfigServerInfo.message_digest_algorithm = wolfSSL_EVP_get_digestbyname(ConfigServerInfo.tls_message_digest_algorithm)) == NULL)
146     {
147     ConfigServerInfo.message_digest_algorithm = wolfSSL_EVP_sha256();
148     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_message_digest_algorithm -- unknown message digest algorithm");
149     }
150    
151     if (ConfigServerInfo.tls_cipher_list == NULL)
152     wolfSSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
153     else if (wolfSSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.tls_cipher_list) != SSL_SUCCESS)
154     {
155     wolfSSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
156     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::tls_cipher_list -- could not set supported cipher(s)");
157     }
158    
159     TLS_initialized = true;
160     return true;
161     }
162    
163     const char *
164     tls_get_cipher(const tls_data_t *tls_data)
165     {
166     static char buf[128];
167     WOLFSSL *ssl = *tls_data;
168    
169     snprintf(buf, sizeof(buf), "%s-%s", wolfSSL_get_version(ssl), wolfSSL_get_cipher(ssl));
170     return buf;
171     }
172    
173     const char *
174     tls_get_version(void)
175     {
176     static char buf[256];
177    
178     snprintf(buf, sizeof(buf), "wolfSSL version: library: %s, header: %s",
179     wolfSSL_lib_version(), LIBWOLFSSL_VERSION_STRING);
180     return buf;
181     }
182    
183     bool
184     tls_isusing(tls_data_t *tls_data)
185     {
186     WOLFSSL *ssl = *tls_data;
187     return ssl != NULL;
188     }
189    
190     void
191     tls_free(tls_data_t *tls_data)
192     {
193     wolfSSL_free(*tls_data);
194     *tls_data = NULL;
195     }
196    
197     ssize_t
198     tls_read(tls_data_t *tls_data, char *buf, size_t bufsize, bool *want_write)
199     {
200     WOLFSSL *ssl = *tls_data;
201     ssize_t length = wolfSSL_read(ssl, buf, bufsize);
202    
203     /* Translate wolfSSL error codes, sigh */
204     if (length < 0)
205     {
206     switch (wolfSSL_get_error(ssl, length))
207     {
208     case SSL_ERROR_WANT_WRITE:
209     {
210     /* wolfSSL wants to write, we signal this to the caller and do nothing about that here */
211     *want_write = true;
212     break;
213     }
214     case SSL_ERROR_WANT_READ:
215     errno = EWOULDBLOCK;
216     case SSL_ERROR_SYSCALL:
217     break;
218     case SSL_ERROR_SSL:
219     if (errno == EAGAIN)
220     break;
221     /* Fall through */
222     default:
223     length = errno = 0;
224     }
225     }
226    
227     return length;
228     }
229    
230     ssize_t
231     tls_write(tls_data_t *tls_data, const char *buf, size_t bufsize, bool *want_read)
232     {
233     WOLFSSL *ssl = *tls_data;
234     ssize_t retlen = wolfSSL_write(ssl, buf, bufsize);
235    
236     /* Translate WolfSSL error codes, sigh */
237     if (retlen < 0)
238     {
239     switch (wolfSSL_get_error(ssl, retlen))
240     {
241     case SSL_ERROR_WANT_READ:
242     *want_read = true;
243     break; /* Retry later, don't register for write events */
244     case SSL_ERROR_WANT_WRITE:
245     errno = EWOULDBLOCK;
246     break;
247     case SSL_ERROR_SYSCALL:
248     break;
249     case SSL_ERROR_SSL:
250     if (errno == EAGAIN)
251     break;
252     /* Fall through */
253     default:
254     retlen = errno = 0; /* Either an SSL-specific error or EOF */
255     }
256     }
257    
258     return retlen;
259     }
260    
261     void
262     tls_shutdown(tls_data_t *tls_data)
263     {
264     WOLFSSL *ssl = *tls_data;
265     int ret = wolfSSL_shutdown(ssl);
266    
267     if (ret == WOLFSSL_SHUTDOWN_NOT_DONE)
268     wolfSSL_shutdown(ssl);
269     }
270    
271     bool
272     tls_new(tls_data_t *tls_data, int fd, tls_role_t role)
273     {
274     WOLFSSL *ssl;
275    
276     if (TLS_initialized == false)
277     return false;
278    
279     if (role == TLS_ROLE_SERVER)
280     ssl = wolfSSL_new(ConfigServerInfo.tls_ctx.server_ctx);
281     else
282     ssl = wolfSSL_new(ConfigServerInfo.tls_ctx.client_ctx);
283    
284     if (ssl == NULL)
285     {
286     ilog(LOG_TYPE_IRCD, "wolfSSL_new() ERROR! -- %s",
287     wolfSSL_ERR_error_string(wolfSSL_ERR_get_error(), NULL));
288     return false;
289     }
290    
291     *tls_data = ssl;
292     wolfSSL_set_fd(ssl, fd);
293     return true;
294     }
295    
296     bool
297     tls_set_ciphers(tls_data_t *tls_data, const char *cipher_list)
298     {
299     wolfSSL_set_cipher_list(*tls_data, cipher_list);
300     return true;
301     }
302    
303     tls_handshake_status_t
304     tls_handshake(tls_data_t *tls_data, tls_role_t role, const char **errstr)
305     {
306     WOLFSSL *ssl = *tls_data;
307     int ret;
308    
309     if (role == TLS_ROLE_SERVER)
310     ret = wolfSSL_accept(ssl);
311     else
312     ret = wolfSSL_connect(ssl);
313    
314     if (ret == WOLFSSL_SUCCESS)
315     return TLS_HANDSHAKE_DONE;
316    
317     switch (wolfSSL_get_error(ssl, ret))
318     {
319     case WOLFSSL_ERROR_WANT_WRITE:
320     return TLS_HANDSHAKE_WANT_WRITE;
321     case WOLFSSL_ERROR_WANT_READ:
322     return TLS_HANDSHAKE_WANT_READ;
323     default:
324     {
325     const char *error = wolfSSL_ERR_error_string(wolfSSL_ERR_get_error(), NULL);
326    
327     if (errstr)
328     *errstr = error;
329    
330     return TLS_HANDSHAKE_ERROR;
331     }
332     }
333     }
334    
335     bool
336     tls_verify_cert(tls_data_t *tls_data, tls_md_t digest, char **fingerprint)
337     {
338     WOLFSSL *ssl = *tls_data;
339     unsigned int n;
340     char buf[EVP_MAX_MD_SIZE * 2 + 1];
341     unsigned char md[EVP_MAX_MD_SIZE];
342     bool ret = false;
343    
344     /* Accept NULL return from SSL_get_peer_certificate */
345     WOLFSSL_X509 *cert = wolfSSL_get_peer_certificate(ssl);
346     if (cert == NULL)
347     return true;
348    
349     switch (wolfSSL_get_verify_result(ssl))
350     {
351     case X509_V_OK:
352     case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
353     case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
354     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
355     ret = true;
356    
357     if (wolfSSL_X509_digest(cert, digest, md, &n))
358     {
359     binary_to_hex(md, buf, n);
360     *fingerprint = xstrdup(buf);
361     }
362     default:
363     break;
364     }
365    
366     wolfSSL_X509_free(cert);
367     return ret;
368     }
369     #endif /* HAVE_TLS_WOLFSSL */

Properties

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