-Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.
+Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen and others.
See the AUTHORS file for a complete list.
This program is free software; you can redistribute it and/or modify it under
+Version 1.0.32 not released yet
+
+ * Fix segmentation fault when using Cipher = none.
+
+Version 1.0.31 January 15 2017
+
+ * Remove ExecStop in tinc@.service.
+
+Thanks to Élie Bouttier for his contribution to this version of tinc.
+
+Version 1.0.30 October 30 2016
+
+ * Fix troubles connecting to some HTTP proxies.
+
+ * Add mitigations for the Sweet32 attack when using a 64-bit block cipher.
+
+ * Use AES256 and SHA256 as the default encryption and digest algorithms.
+
Version 1.0.29 October 9 2016
* Fix UDP communication with peers with link-local IPv6 addresses.
-This is the README file for tinc version 1.0.29. Installation
+This is the README file for tinc version 1.0.31. Installation
instructions may be found in the INSTALL file.
-tinc is Copyright (C) 1998-2016 by:
+tinc is Copyright (C) 1998-2017 by:
Ivo Timmermans,
Guus Sliepen <guus@tinc-vpn.org>,
his opinion. We do not know of a way to exploit these weaknesses, but these
issues are being addressed in the tinc 1.1 branch.
+The Sweet32 attack affects versions of tinc prior to 1.0.30.
+
Cryptography is a hard thing to get right. We cannot make any
guarantees. Time, review and feedback are the only things that can
prove the security of any cryptographic product. If you wish to review
should be changed into "Device", and "Device" should be changed into
"BindToDevice".
+
Compatibility
-------------
-Version 1.0.29 is compatible with 1.0pre8, 1.0 and later, but not with older
-versions of tinc.
+Version 1.0.31 is compatible with 1.0pre8, 1.0 and later, but not with older
+versions of tinc. Note that since version 1.0.30, tinc requires all nodes in
+the VPN to be compiled with a version of LibreSSL or OpenSSL that supports the
+AES256 and SHA256 algorithms.
Requirements
------------
-Since 1.0pre3, we use OpenSSL for all cryptographic functions. So you
-need to install this library first; grab it from
-http://www.openssl.org/. You will need version 0.9.7 or later. If
-this library is not installed on you system, configure will fail. The
-manual in doc/tinc.texi contains more detailed information on how to
-install this library.
+Since 1.0pre3, we use OpenSSL for all cryptographic functions. So you need to
+install this library first; grab it from http://www.openssl.org/. You will
+need version 1.0.1 or later with support for AES256 and SHA256 enabled. If
+this library is not installed on you system, configure will fail. The manual
+in doc/tinc.texi contains more detailed information on how to install this
+library. Alternatively, you may also use LibreSSL.
Since 1.0pre6, the zlib library is used for optional compression. You can
find it at http://www.gzip.org/zlib/. Because of a possible exploit in
* David Pflug
* Delf Eldkraft
* dnk
+* Élie Bouttier
* Enrique Zanardi
* Florent Clairambault
* Florian Weik
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT([tinc], [1.0.29])
+AC_INIT([tinc], [1.0.31])
AC_CONFIG_SRCDIR([src/tincd.c])
AM_INIT_AUTOMAKE([1.11 check-news std-options subdir-objects nostdinc silent-rules -Wall])
AC_CONFIG_HEADERS([config.h])
WorkingDirectory=/etc/tinc/%i
ExecStart=/usr/sbin/tincd -n %i -D
ExecReload=/usr/sbin/tincd -n %i -kHUP
-ExecStop=/usr/sbin/tincd -n %i -k
TimeoutStopSec=5
Restart=always
RestartSec=60
-.Dd 2016-04-10
+.Dd 2016-10-29
.Dt TINC.CONF 5
.\" Manual page created by:
.\" Ivo Timmermans
.Va Address
variables can be specified, in which case each address will be tried until a working
connection has been established.
-.It Va Cipher Li = Ar cipher Pq blowfish
+.It Va Cipher Li = Ar cipher Pq aes-256-cbc
The symmetric cipher algorithm used to encrypt UDP packets.
Any cipher supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying
This option sets the level of compression used for UDP packets.
Possible values are 0 (off), 1 (fast zlib) and any integer up to 9 (best zlib),
10 (fast lzo) and 11 (best lzo).
-.It Va Digest Li = Ar digest Pq sha1
+.It Va Digest Li = Ar digest Pq sha256
The digest algorithm used to authenticate UDP packets.
Any digest supported by LibreSSL or OpenSSL is recognised.
Furthermore, specifying
tried until a working connection has been established.
@cindex Cipher
-@item Cipher = <@var{cipher}> (blowfish)
+@item Cipher = <@var{cipher}> (aes-256-cbc)
The symmetric cipher algorithm used to encrypt UDP packets.
Any cipher supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying "none" will turn off packet encryption.
10 (fast lzo) and 11 (best lzo).
@cindex Digest
-@item Digest = <@var{digest}> (sha1)
+@item Digest = <@var{digest}> (sha256)
The digest algorithm used to authenticate UDP packets.
Any digest supported by LibreSSL or OpenSSL is recognized.
Furthermore, specifying "none" will turn off packet authentication.
[AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
)
- AC_CHECK_DECL([OpenSSL_add_all_algorithms], ,
+ AC_CHECK_DECLS([OpenSSL_add_all_algorithms, EVP_aes_256_cfb], ,
[AC_MSG_ERROR([Missing LibreSSL/OpenSSL functionality, make sure you have installed the latest version.]); break],
[#include <openssl/evp.h>]
)
/*
connection.c -- connection list management
- Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
2008 Max Rijevski <maksuf@gmail.com>
c->outbufstart = 0;
c->last_ping_time = 0;
c->last_flushed_time = 0;
+ c->inbudget = 0;
+ c->outbudget = 0;
if(c->inctx) {
EVP_CIPHER_CTX_cleanup(c->inctx);
/*
connection.h -- header for connection.c
- Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
unsigned int encryptout:1; /* 1 if we can encrypt outgoing traffic */
unsigned int decryptin:1; /* 1 if we have to decrypt incoming traffic */
unsigned int mst:1; /* 1 if this connection is part of a minimum spanning tree */
- unsigned int unused:23;
+ unsigned int proxy_passed:1; /* 1 if we are connecting via a proxy and we have finished talking with it */
+ unsigned int unused:22;
} connection_status_t;
#include "edge.h"
const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */
EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */
EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */
+ uint64_t inbudget; /* Encrypted bytes send budget */
+ uint64_t outbudget; /* Encrypted bytes receive budget */
char *inkey; /* His symmetric meta key + iv */
char *outkey; /* Our symmetric meta key + iv */
int inkeylength; /* Length of his key + iv */
/*
meta.c -- handle the meta communication
- Copyright (C) 2000-2015 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2000-2016 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
2006 Scott Lamb <slamb@slamb.org>
/* Add our data to buffer */
if(c->status.encryptout) {
+ /* Check encryption limits */
+ if(length > c->outbudget) {
+ ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname);
+ return false;
+ } else {
+ c->outbudget -= length;
+ }
+
result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen,
&outlen, (unsigned char *)buffer, length);
if(!result || outlen < length) {
/* Decrypt */
if(c->status.decryptin && !decrypted) {
+ /* Check decryption limits */
+ if(lenin > c->inbudget) {
+ ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname);
+ return false;
+ } else {
+ c->inbudget -= lenin;
+ }
+
result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin);
if(!result || lenout != lenin) {
logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s",
/*
net_setup.c -- Setup.
Copyright (C) 1998-2005 Ivo Timmermans,
- 2000-2016 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2006 Scott Lamb <slamb@slamb.org>
2010 Brandon Black <blblack@gmail.com>
}
free(cipher);
} else
- myself->incipher = EVP_bf_cbc();
+ myself->incipher = EVP_aes_256_cbc();
if(myself->incipher)
myself->inkeylength = EVP_CIPHER_key_length(myself->incipher) + EVP_CIPHER_iv_length(myself->incipher);
else
myself->inkeylength = 1;
- myself->connection->outcipher = EVP_bf_ofb();
+ /* We need to use a stream mode for the meta protocol. Use AES for this,
+ but try to match the key size with the one from the cipher selected
+ by Cipher.
+
+ If Cipher is set to none, still use a low level of encryption for the
+ meta protocol.
+ */
+
+ int keylen = myself->incipher ? EVP_CIPHER_key_length(myself->incipher) : 0;
+ if(keylen <= 16)
+ myself->connection->outcipher = EVP_aes_128_cfb();
+ else if(keylen <= 24)
+ myself->connection->outcipher = EVP_aes_192_cfb();
+ else
+ myself->connection->outcipher = EVP_aes_256_cfb();
if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
keylifetime = 3600;
free(digest);
} else
- myself->indigest = EVP_sha1();
+ myself->indigest = EVP_sha256();
- myself->connection->outdigest = EVP_sha1();
+ myself->connection->outdigest = EVP_sha256();
if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) {
if(myself->indigest) {
#include "xalloc.h"
bool send_id(connection_t *c) {
- if(proxytype && c->outgoing)
- if(!send_proxyrequest(c))
- return false;
+ if(proxytype && c->outgoing && !c->status.proxy_passed)
+ return send_proxyrequest(c);
return send_request(c, "%d %s %d", ID, myself->connection->name,
myself->connection->protocol_version);
return send_metakey(c);
}
+static uint64_t byte_budget(const EVP_CIPHER *cipher) {
+ /* Hopefully some failsafe way to calculate the maximum amount of bytes to
+ send/receive with a given cipher before we might run into birthday paradox
+ attacks. Because we might use different modes, the block size of the mode
+ might be 1 byte. In that case, use the IV length. Ensure the whole thing
+ is limited to what can be represented with a 64 bits integer.
+ */
+
+ int ivlen = EVP_CIPHER_iv_length(cipher);
+ int blklen = EVP_CIPHER_block_size(cipher);
+ int len = blklen > 1 ? blklen : ivlen > 1 ? ivlen : 8;
+ int bits = len * 4 - 1;
+ return bits < 64 ? UINT64_C(1) << bits : UINT64_MAX;
+}
+
bool send_metakey(connection_t *c) {
bool x;
return false;
}
+ c->outbudget = byte_budget(c->outcipher);
c->status.encryptout = true;
}
return false;
}
+ c->inbudget = byte_budget(c->incipher);
c->status.decryptin = true;
} else {
c->incipher = NULL;
/*
proxy.c -- Proxy handling functions.
- Copyright (C) 2015 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2015-2016 Guus Sliepen <guus@tinc-vpn.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
c->allow_request = ID;
+ c->status.proxy_passed = true;
+ send_id(c);
return 8;
} else {
logger(LOG_ERR, "Proxy request rejected");
} else {
ifdebug(CONNECTIONS) logger(LOG_DEBUG, "Proxy request granted");
c->allow_request = ID;
+ c->status.proxy_passed = true;
+ send_id(c);
return replen;
}
char *p = memchr(c->buffer, '\n', c->buflen);
if(!p || p - c->buffer >= c->buflen)
return 0;
- p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer));
+
+ while((p = memchr(p + 1, '\n', c->buflen - (p + 1 - c->buffer)))) {
+ if(p > c->buffer + 3 && !memcmp(p - 3, "\r\n\r\n", 4))
+ break;
+ }
+
if(!p)
return 0;
logger(LOG_DEBUG, "Proxy request granted");
replen = p + 1 - c->buffer;
c->allow_request = ID;
+ c->status.proxy_passed = true;
+ send_id(c);
return replen;
} else {
+ p = memchr(c->buffer, '\n', c->buflen);
+ p[-1] = 0;
logger(LOG_ERR, "Proxy request rejected: %s", c->buffer + 9);
return false;
}
/*
tincd.c -- the main file for tincd
Copyright (C) 1998-2005 Ivo Timmermans
- 2000-2016 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2017 Guus Sliepen <guus@tinc-vpn.org>
2008 Max Rijevski <maksuf@gmail.com>
2009 Michael Tokarev <mjt@tls.msk.ru>
2010 Julien Muchembled <jm@jmuchemb.eu>
if(show_version) {
printf("%s version %s\n", PACKAGE, VERSION);
- printf("Copyright (C) 1998-2016 Ivo Timmermans, Guus Sliepen and others.\n"
+ printf("Copyright (C) 1998-2017 Ivo Timmermans, Guus Sliepen and others.\n"
"See the AUTHORS file for a complete list.\n\n"
"tinc comes with ABSOLUTELY NO WARRANTY. This is free software,\n"
"and you are welcome to redistribute it under certain conditions;\n"