ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/tls_openssl.c
Revision: 9122
Committed: Sun Jan 5 17:24:52 2020 UTC (5 years, 7 months ago) by michael
Content type: text/x-csrc
File size: 11462 byte(s)
Log Message:
- OpenSSL now runs with automatic curve selection if no curve is defined in serverinfo::ssl_dh_elliptic_curve

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 9101 * Copyright (c) 2005-2020 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    
38 michael 8664 static bool TLS_initialized;
39 michael 7271
40 michael 7152 /*
41     * report_crypto_errors - Dump crypto error list to log
42     */
43     static void
44     report_crypto_errors(void)
45     {
46     unsigned long e = 0;
47    
48     while ((e = ERR_get_error()))
49     ilog(LOG_TYPE_IRCD, "SSL error: %s", ERR_error_string(e, 0));
50     }
51    
52 michael 7105 static int
53     always_accept_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
54     {
55     return 1;
56     }
57    
58 michael 8664 bool
59 michael 7271 tls_is_initialized(void)
60     {
61     return TLS_initialized;
62     }
63    
64 michael 7105 /* tls_init()
65     *
66     * inputs - nothing
67     * output - nothing
68     * side effects - setups SSL context.
69     */
70     void
71     tls_init(void)
72     {
73     SSL_load_error_strings();
74     SSLeay_add_ssl_algorithms();
75    
76 michael 8961 if ((ConfigServerInfo.tls_ctx.server_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL)
77 michael 7105 {
78     const char *s = ERR_lib_error_string(ERR_get_error());
79    
80 michael 7278 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 8821 SSL_CTX_set_options(ConfigServerInfo.tls_ctx.server_ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TICKET);
86 michael 7105 SSL_CTX_set_options(ConfigServerInfo.tls_ctx.server_ctx, SSL_OP_SINGLE_DH_USE|SSL_OP_CIPHER_SERVER_PREFERENCE);
87     SSL_CTX_set_verify(ConfigServerInfo.tls_ctx.server_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
88     always_accept_verify_cb);
89     SSL_CTX_set_session_cache_mode(ConfigServerInfo.tls_ctx.server_ctx, SSL_SESS_CACHE_OFF);
90     SSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, "EECDH+HIGH:EDH+HIGH:HIGH:!aNULL");
91    
92 michael 7192 #ifndef OPENSSL_NO_ECDH
93 michael 9122 SSL_CTX_set_options(ConfigServerInfo.tls_ctx.server_ctx, SSL_OP_SINGLE_ECDH_USE);
94    
95     #if OPENSSL_VERSION_NUMBER < 0x10002000L
96 michael 7233 EC_KEY *key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
97    
98     if (key)
99 michael 7105 {
100 michael 7233 SSL_CTX_set_tmp_ecdh(ConfigServerInfo.tls_ctx.server_ctx, key);
101     EC_KEY_free(key);
102 michael 7105 }
103 michael 9122 #elif OPENSSL_VERSION_NUMBER < 0x10100000L
104     SSL_CTX_set_ecdh_auto(ConfigServerInfo.tls_ctx.server_ctx, 1);
105 michael 7105 #endif
106 michael 9122 /* SSL_CTX_set_ecdh_auto() no longer exists as of 1.1.0 */
107     #endif
108 michael 7105
109 michael 8961 if ((ConfigServerInfo.tls_ctx.client_ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
110 michael 7105 {
111     const char *s = ERR_lib_error_string(ERR_get_error());
112    
113 michael 7278 ilog(LOG_TYPE_IRCD, "ERROR: Could not initialize the TLS Client context -- %s", s);
114 michael 7105 exit(EXIT_FAILURE);
115     return; /* Not reached */
116     }
117    
118 michael 8821 SSL_CTX_set_options(ConfigServerInfo.tls_ctx.client_ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TICKET);
119 michael 7105 SSL_CTX_set_options(ConfigServerInfo.tls_ctx.client_ctx, SSL_OP_SINGLE_DH_USE);
120     SSL_CTX_set_verify(ConfigServerInfo.tls_ctx.client_ctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
121     always_accept_verify_cb);
122     SSL_CTX_set_session_cache_mode(ConfigServerInfo.tls_ctx.client_ctx, SSL_SESS_CACHE_OFF);
123     }
124    
125 michael 8664 bool
126 michael 7105 tls_new_cred(void)
127     {
128 michael 8664 TLS_initialized = false;
129 michael 7271
130 michael 7105 if (!ConfigServerInfo.ssl_certificate_file || !ConfigServerInfo.rsa_private_key_file)
131 michael 8664 return true;
132 michael 7105
133     if (SSL_CTX_use_certificate_chain_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.ssl_certificate_file) <= 0 ||
134     SSL_CTX_use_certificate_chain_file(ConfigServerInfo.tls_ctx.client_ctx, ConfigServerInfo.ssl_certificate_file) <= 0)
135     {
136     report_crypto_errors();
137 michael 8664 return false;
138 michael 7105 }
139    
140     if (SSL_CTX_use_PrivateKey_file(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) <= 0 ||
141     SSL_CTX_use_PrivateKey_file(ConfigServerInfo.tls_ctx.client_ctx, ConfigServerInfo.rsa_private_key_file, SSL_FILETYPE_PEM) <= 0)
142     {
143     report_crypto_errors();
144 michael 8664 return false;
145 michael 7105 }
146    
147     if (!SSL_CTX_check_private_key(ConfigServerInfo.tls_ctx.server_ctx) ||
148     !SSL_CTX_check_private_key(ConfigServerInfo.tls_ctx.client_ctx))
149     {
150     report_crypto_errors();
151 michael 8664 return false;
152 michael 7105 }
153    
154     if (ConfigServerInfo.ssl_dh_param_file)
155     {
156     BIO *file = BIO_new_file(ConfigServerInfo.ssl_dh_param_file, "r");
157    
158     if (file)
159     {
160     DH *dh = PEM_read_bio_DHparams(file, NULL, NULL, NULL);
161    
162     BIO_free(file);
163    
164     if (dh)
165     {
166 michael 7387 SSL_CTX_set_tmp_dh(ConfigServerInfo.tls_ctx.server_ctx, dh);
167 michael 7105 DH_free(dh);
168     }
169     }
170     else
171     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::ssl_dh_param_file -- could not open/read Diffie-Hellman parameter file");
172     }
173    
174 michael 7192 #ifndef OPENSSL_NO_ECDH
175 michael 7124 if (ConfigServerInfo.ssl_dh_elliptic_curve)
176 michael 7105 {
177     int nid = 0;
178     EC_KEY *key = NULL;
179    
180     if ((nid = OBJ_sn2nid(ConfigServerInfo.ssl_dh_elliptic_curve)) == 0)
181     goto set_default_curve;
182    
183     if ((key = EC_KEY_new_by_curve_name(nid)) == NULL)
184     goto set_default_curve;
185    
186     SSL_CTX_set_tmp_ecdh(ConfigServerInfo.tls_ctx.server_ctx, key);
187     EC_KEY_free(key);
188     }
189     else
190     {
191     EC_KEY *key;
192    
193 michael 9122 set_default_curve: ;
194     #if OPENSSL_VERSION_NUMBER < 0x10002000L
195 michael 7105 key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
196    
197     if (key)
198     {
199     SSL_CTX_set_tmp_ecdh(ConfigServerInfo.tls_ctx.server_ctx, key);
200     EC_KEY_free(key);
201     }
202 michael 9122 #elif OPENSSL_VERSION_NUMBER < 0x10100000L
203     SSL_CTX_set_ecdh_auto(ConfigServerInfo.tls_ctx.server_ctx, 1);
204     #endif
205     /* SSL_CTX_set_ecdh_auto() no longer exists as of 1.1.0 */
206 michael 7105 }
207     #endif
208    
209     if (ConfigServerInfo.ssl_message_digest_algorithm == NULL)
210     ConfigServerInfo.message_digest_algorithm = EVP_sha256();
211     else
212     {
213     ConfigServerInfo.message_digest_algorithm = EVP_get_digestbyname(ConfigServerInfo.ssl_message_digest_algorithm);
214 michael 7124
215 michael 7105 if (ConfigServerInfo.message_digest_algorithm == NULL)
216     {
217     ConfigServerInfo.message_digest_algorithm = EVP_sha256();
218     ilog(LOG_TYPE_IRCD, "Ignoring serverinfo::ssl_message_digest_algorithm -- unknown message digest algorithm");
219     }
220     }
221    
222 michael 7190 if (ConfigServerInfo.ssl_cipher_list)
223     SSL_CTX_set_cipher_list(ConfigServerInfo.tls_ctx.server_ctx, ConfigServerInfo.ssl_cipher_list);
224    
225 michael 8664 TLS_initialized = true;
226     return true;
227 michael 7105 }
228    
229     const char *
230     tls_get_cipher(const tls_data_t *tls_data)
231     {
232     static char buffer[IRCD_BUFSIZE];
233     int bits = 0;
234     SSL *ssl = *tls_data;
235    
236     SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), &bits);
237    
238     snprintf(buffer, sizeof(buffer), "%s-%s-%d", SSL_get_version(ssl),
239     SSL_get_cipher(ssl), bits);
240     return buffer;
241     }
242    
243 michael 7708 const char *
244     tls_get_version(void)
245     {
246     static char buf[IRCD_BUFSIZE];
247    
248     snprintf(buf, sizeof(buf), "OpenSSL version: library: %s, header: %s",
249     SSLeay_version(SSLEAY_VERSION), OPENSSL_VERSION_TEXT);
250     return buf;
251     }
252    
253 michael 8664 bool
254 michael 7105 tls_isusing(tls_data_t *tls_data)
255     {
256     SSL *ssl = *tls_data;
257 michael 7124 return ssl != NULL;
258 michael 7105 }
259    
260     void
261     tls_free(tls_data_t *tls_data)
262     {
263     SSL_free(*tls_data);
264     *tls_data = NULL;
265     }
266    
267 michael 8956 ssize_t
268 michael 8660 tls_read(tls_data_t *tls_data, char *buf, size_t bufsize, bool *want_write)
269 michael 7105 {
270     SSL *ssl = *tls_data;
271 michael 8956 ssize_t length = SSL_read(ssl, buf, bufsize);
272 michael 7105
273     /* Translate openssl error codes, sigh */
274     if (length < 0)
275     {
276     switch (SSL_get_error(ssl, length))
277     {
278     case SSL_ERROR_WANT_WRITE:
279     {
280     /* OpenSSL wants to write, we signal this to the caller and do nothing about that here */
281 michael 8660 *want_write = true;
282 michael 7105 break;
283     }
284     case SSL_ERROR_WANT_READ:
285     errno = EWOULDBLOCK;
286     case SSL_ERROR_SYSCALL:
287     break;
288     case SSL_ERROR_SSL:
289     if (errno == EAGAIN)
290     break;
291     /* Fall through */
292     default:
293     length = errno = 0;
294     }
295     }
296    
297     return length;
298     }
299    
300 michael 8956 ssize_t
301 michael 8660 tls_write(tls_data_t *tls_data, const char *buf, size_t bufsize, bool *want_read)
302 michael 7105 {
303     SSL *ssl = *tls_data;
304 michael 8956 ssize_t retlen = SSL_write(ssl, buf, bufsize);
305 michael 7105
306     /* Translate openssl error codes, sigh */
307     if (retlen < 0)
308     {
309     switch (SSL_get_error(ssl, retlen))
310     {
311     case SSL_ERROR_WANT_READ:
312 michael 8660 *want_read = true;
313 michael 7105 break; /* Retry later, don't register for write events */
314     case SSL_ERROR_WANT_WRITE:
315     errno = EWOULDBLOCK;
316     break;
317     case SSL_ERROR_SYSCALL:
318     break;
319     case SSL_ERROR_SSL:
320     if (errno == EAGAIN)
321     break;
322     /* Fall through */
323     default:
324     retlen = errno = 0; /* Either an SSL-specific error or EOF */
325     }
326     }
327    
328     return retlen;
329     }
330    
331     void
332     tls_shutdown(tls_data_t *tls_data)
333     {
334     SSL *ssl = *tls_data;
335    
336     SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
337    
338     if (!SSL_shutdown(ssl))
339     SSL_shutdown(ssl);
340     }
341    
342 michael 8664 bool
343 michael 7105 tls_new(tls_data_t *tls_data, int fd, tls_role_t role)
344     {
345     SSL *ssl;
346    
347 michael 8664 if (TLS_initialized == false)
348     return false;
349 michael 7274
350 michael 7105 if (role == TLS_ROLE_SERVER)
351     ssl = SSL_new(ConfigServerInfo.tls_ctx.server_ctx);
352     else
353     ssl = SSL_new(ConfigServerInfo.tls_ctx.client_ctx);
354    
355     if (!ssl)
356     {
357     ilog(LOG_TYPE_IRCD, "SSL_new() ERROR! -- %s",
358     ERR_error_string(ERR_get_error(), NULL));
359 michael 8664 return false;
360 michael 7105 }
361    
362     *tls_data = ssl;
363     SSL_set_fd(ssl, fd);
364 michael 8664 return true;
365 michael 7105 }
366    
367 michael 8664 bool
368 michael 7105 tls_set_ciphers(tls_data_t *tls_data, const char *cipher_list)
369     {
370     SSL_set_cipher_list(*tls_data, cipher_list);
371 michael 8664 return true;
372 michael 7105 }
373    
374     tls_handshake_status_t
375     tls_handshake(tls_data_t *tls_data, tls_role_t role, const char **errstr)
376     {
377     SSL *ssl = *tls_data;
378     int ret;
379    
380     if (role == TLS_ROLE_SERVER)
381     ret = SSL_accept(ssl);
382     else
383     ret = SSL_connect(ssl);
384    
385     if (ret > 0)
386     return TLS_HANDSHAKE_DONE;
387    
388     switch (SSL_get_error(ssl, ret))
389     {
390     case SSL_ERROR_WANT_WRITE:
391     return TLS_HANDSHAKE_WANT_WRITE;
392     case SSL_ERROR_WANT_READ:
393     return TLS_HANDSHAKE_WANT_READ;
394     default:
395     {
396     const char *error = ERR_error_string(ERR_get_error(), NULL);
397    
398     if (errstr)
399     *errstr = error;
400    
401     return TLS_HANDSHAKE_ERROR;
402     }
403     }
404     }
405    
406 michael 8664 bool
407 michael 7142 tls_verify_cert(tls_data_t *tls_data, tls_md_t digest, char **fingerprint)
408 michael 7105 {
409     SSL *ssl = *tls_data;
410     unsigned int n;
411     char buf[EVP_MAX_MD_SIZE * 2 + 1];
412     unsigned char md[EVP_MAX_MD_SIZE];
413 michael 8664 bool ret = false;
414 michael 7105
415     /* Accept NULL return from SSL_get_peer_certificate */
416 michael 8961 X509 *cert = SSL_get_peer_certificate(ssl);
417     if (cert == NULL)
418 michael 8664 return true;
419 michael 7105
420 michael 8961 switch (SSL_get_verify_result(ssl))
421 michael 7105 {
422 michael 8961 case X509_V_OK:
423     case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
424     case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
425     case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
426     ret = true;
427 michael 7105
428 michael 8961 if (X509_digest(cert, digest, md, &n))
429     {
430     binary_to_hex(md, buf, n);
431     *fingerprint = xstrdup(buf);
432     }
433     default:
434     break;
435 michael 7105 }
436    
437     X509_free(cert);
438     return ret;
439     }
440     #endif /* HAVE_TLS_OPENSSL */

Properties

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