Allow tinc to be compiled without OpenSSL.

The option "--disable-legacy-protocol" was added to the configure
script. The new protocol does not depend on any external crypto
libraries, so when the option is used tinc is no longer linked to
OpenSSL's libcrypto.
This commit is contained in:
Guus Sliepen 2014-12-29 22:57:18 +01:00
parent 8d32b283b0
commit cfe9285adf
16 changed files with 200 additions and 64 deletions

View file

@ -211,23 +211,33 @@ AC_CHECK_DECLS([res_init], [AC_CHECK_LIB(resolv, res_init)], [], [
AC_CACHE_SAVE AC_CACHE_SAVE
AC_ARG_ENABLE(legacy-protocol,
AS_HELP_STRING([--disable-legacy-protocol], [disable support for the legacy (tinc 1.0) protocol]),
[ AS_IF([test "x$enable_legacy_protocol" = "xno"],
[ AC_DEFINE(DISABLE_LEGACY, 1, [Disable support for the legacy (tinc 1.0) protocol]) ])
]
)
dnl These are defined in files in m4/ dnl These are defined in files in m4/
dnl AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcrypt instead of OpenSSL])], []) dnl AC_ARG_WITH(libgcrypt, AC_HELP_STRING([--with-libgcrypt], [enable use of libgcrypt instead of OpenSSL])], [])
dnl AC_ARG_WITH(openssl, AC_HELP_STRING([--without-openssl], [disable support for OpenSSL])], [])
tinc_CURSES tinc_CURSES
tinc_READLINE tinc_READLINE
tinc_ZLIB tinc_ZLIB
tinc_LZO tinc_LZO
if test -n "$with_libgcrypt"; then if test "x$enable_legacy_protocol" != "xno"; then
gcrypt=true if test -n "$with_libgcrypt"; then
tinc_LIBGCRYPT gcrypt=true
else tinc_LIBGCRYPT
openssl=true else
tinc_OPENSSL openssl=true
tinc_OPENSSL
fi
fi fi
AM_CONDITIONAL(OPENSSL, test -n "$openssl") AM_CONDITIONAL(OPENSSL, test -n "$openssl")
AM_CONDITIONAL(GCRYPT, test -n "$gcrypt") AM_CONDITIONAL(GCRYPT, test -n "$gcrypt")

View file

@ -92,6 +92,8 @@ tincd_SOURCES = \
utils.c utils.h \ utils.c utils.h \
xalloc.h \ xalloc.h \
version.c version.h \ version.c version.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
$(ed25519_SOURCES) \ $(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES) $(chacha_poly1305_SOURCES)
@ -111,6 +113,9 @@ tinc_SOURCES = \
top.c top.h \ top.c top.h \
utils.c utils.h \ utils.c utils.h \
version.c version.h \ version.c version.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
$(ed25519_SOURCES) \ $(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES) $(chacha_poly1305_SOURCES)
@ -119,12 +124,15 @@ sptps_test_SOURCES = \
sptps.c sptps.h \ sptps.c sptps.h \
sptps_test.c \ sptps_test.c \
utils.c utils.h \ utils.c utils.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
$(ed25519_SOURCES) \ $(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES) $(chacha_poly1305_SOURCES)
sptps_keypair_SOURCES = \ sptps_keypair_SOURCES = \
sptps_keypair.c \ sptps_keypair.c \
utils.c utils.h \ utils.c utils.h \
ed25519/ecdsagen.c \
$(ed25519_SOURCES) $(ed25519_SOURCES)
sptps_speed_SOURCES = \ sptps_speed_SOURCES = \
@ -132,6 +140,9 @@ sptps_speed_SOURCES = \
sptps.c sptps.h \ sptps.c sptps.h \
sptps_speed.c \ sptps_speed.c \
utils.c utils.h \ utils.c utils.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
$(ed25519_SOURCES) \ $(ed25519_SOURCES) \
$(chacha_poly1305_SOURCES) $(chacha_poly1305_SOURCES)
@ -173,54 +184,36 @@ tincd_SOURCES += \
openssl/cipher.c \ openssl/cipher.c \
openssl/crypto.c \ openssl/crypto.c \
openssl/digest.c openssl/digest.h \ openssl/digest.c openssl/digest.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
openssl/prf.c \ openssl/prf.c \
openssl/rsa.c openssl/rsa.c
tinc_SOURCES += \ tinc_SOURCES += \
openssl/cipher.c \ openssl/cipher.c \
openssl/crypto.c \ openssl/crypto.c \
openssl/digest.c openssl/digest.h \ openssl/digest.c openssl/digest.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
openssl/prf.c \ openssl/prf.c \
openssl/rsa.c \ openssl/rsa.c \
openssl/rsagen.c openssl/rsagen.c
sptps_test_SOURCES += \ sptps_test_SOURCES += \
openssl/crypto.c \ openssl/crypto.c \
openssl/digest.c openssl/digest.h \ openssl/digest.c openssl/digest.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
openssl/prf.c openssl/prf.c
sptps_keypair_SOURCES += \ sptps_keypair_SOURCES += \
openssl/crypto.c \ openssl/crypto.c
ed25519/ecdsagen.c
sptps_speed_SOURCES += \ sptps_speed_SOURCES += \
openssl/crypto.c \ openssl/crypto.c \
openssl/digest.c openssl/digest.h \ openssl/digest.c openssl/digest.h \
ed25519/ecdh.c \
ed25519/ecdsa.c \
ed25519/ecdsagen.c \
openssl/prf.c openssl/prf.c
endif elif GCRYPT
if GCRYPT
tincd_SOURCES += \ tincd_SOURCES += \
gcrypt/cipher.c \ gcrypt/cipher.c \
gcrypt/crypto.c \ gcrypt/crypto.c \
gcrypt/digest.c gcrypt/digest.h \ gcrypt/digest.c gcrypt/digest.h \
gcrypt/ecdh.c \
gcrypt/ecdsa.c \
gcrypt/prf.c \ gcrypt/prf.c \
gcrypt/rsa.c gcrypt/rsa.c
tinc_SOURCES += \ tinc_SOURCES += \
gcrypt/cipher.c \ gcrypt/cipher.c \
gcrypt/crypto.c \ gcrypt/crypto.c \
gcrypt/digest.c gcrypt/digest.h \ gcrypt/digest.c gcrypt/digest.h \
gcrypt/ecdh.c \
gcrypt/ecdsa.c \
gcrypt/ecdsagen.c \
gcrypt/prf.c \ gcrypt/prf.c \
gcrypt/rsa.c \ gcrypt/rsa.c \
gcrypt/rsagen.c gcrypt/rsagen.c
@ -228,9 +221,28 @@ sptps_test_SOURCES += \
gcrypt/cipher.c \ gcrypt/cipher.c \
gcrypt/crypto.c \ gcrypt/crypto.c \
gcrypt/digest.c gcrypt/digest.h \ gcrypt/digest.c gcrypt/digest.h \
gcrypt/ecdh.c \
gcrypt/ecdsa.c \
gcrypt/prf.c gcrypt/prf.c
sptps_keypair_SOURCES += \
openssl/crypto.c
sptps_speed_SOURCES += \
openssl/crypto.c \
openssl/digest.c openssl/digest.h \
openssl/prf.c
else
tincd_SOURCES += \
nolegacy/crypto.c \
nolegacy/prf.c
tinc_SOURCES += \
nolegacy/crypto.c \
nolegacy/prf.c
sptps_test_SOURCES += \
nolegacy/crypto.c \
nolegacy/prf.c
sptps_keypair_SOURCES += \
nolegacy/crypto.c
sptps_speed_SOURCES += \
nolegacy/crypto.c \
nolegacy/prf.c
endif endif
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS) tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)

View file

@ -24,6 +24,8 @@
#define CIPHER_MAX_IV_SIZE 16 #define CIPHER_MAX_IV_SIZE 16
#define CIPHER_MAX_KEY_SIZE 32 #define CIPHER_MAX_KEY_SIZE 32
#ifndef DISABLE_LEGACY
typedef struct cipher cipher_t; typedef struct cipher cipher_t;
extern cipher_t *cipher_open_by_name(const char *) __attribute__ ((__malloc__)); extern cipher_t *cipher_open_by_name(const char *) __attribute__ ((__malloc__));
@ -40,3 +42,5 @@ extern int cipher_get_nid(const cipher_t *);
extern bool cipher_active(const cipher_t *); extern bool cipher_active(const cipher_t *);
#endif #endif
#endif

View file

@ -55,14 +55,16 @@ void free_connection(connection_t *c) {
if(!c) if(!c)
return; return;
#ifndef DISABLE_LEGACY
cipher_close(c->incipher); cipher_close(c->incipher);
digest_close(c->indigest); digest_close(c->indigest);
cipher_close(c->outcipher); cipher_close(c->outcipher);
digest_close(c->outdigest); digest_close(c->outdigest);
rsa_free(c->rsa);
#endif
sptps_stop(&c->sptps); sptps_stop(&c->sptps);
ecdsa_free(c->ecdsa); ecdsa_free(c->ecdsa);
rsa_free(c->rsa);
free(c->hischallenge); free(c->hischallenge);

View file

@ -75,12 +75,15 @@ typedef struct connection_t {
struct node_t *node; /* node associated with the other end */ struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */ struct edge_t *edge; /* edge associated with this connection */
#ifndef DISABLE_LEGACY
rsa_t *rsa; /* his public RSA key */ rsa_t *rsa; /* his public RSA key */
ecdsa_t *ecdsa; /* his public ECDSA key */
cipher_t *incipher; /* Cipher he will use to send data to us */ cipher_t *incipher; /* Cipher he will use to send data to us */
cipher_t *outcipher; /* Cipher we will use to send data to him */ cipher_t *outcipher; /* Cipher we will use to send data to him */
digest_t *indigest; digest_t *indigest;
digest_t *outdigest; digest_t *outdigest;
#endif
ecdsa_t *ecdsa; /* his public ECDSA key */
sptps_t sptps; sptps_t sptps;
int inmaclength; int inmaclength;

View file

@ -22,6 +22,8 @@
#define DIGEST_MAX_SIZE 64 #define DIGEST_MAX_SIZE 64
#ifndef DISABLE_LEGACY
typedef struct digest digest_t; typedef struct digest digest_t;
extern digest_t *digest_open_by_name(const char *name, int maclength) __attribute__ ((__malloc__)); extern digest_t *digest_open_by_name(const char *name, int maclength) __attribute__ ((__malloc__));
@ -37,3 +39,5 @@ extern size_t digest_length(const digest_t *);
extern bool digest_active(const digest_t *); extern bool digest_active(const digest_t *);
#endif #endif
#endif

View file

@ -33,6 +33,8 @@
#include "utils.h" #include "utils.h"
#include "xalloc.h" #include "xalloc.h"
#include "ed25519/sha512.h"
int addressfamily = AF_UNSPEC; int addressfamily = AF_UNSPEC;
static void scan_for_hostname(const char *filename, char **hostname, char **port) { static void scan_for_hostname(const char *filename, char **hostname, char **port) {
@ -270,8 +272,6 @@ int cmd_invite(int argc, char *argv[]) {
} }
} }
char hash[25];
xasprintf(&filename, "%s" SLASH "invitations", confbase); xasprintf(&filename, "%s" SLASH "invitations", confbase);
if(mkdir(filename, 0700) && errno != EEXIST) { if(mkdir(filename, 0700) && errno != EEXIST) {
fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno)); fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
@ -365,11 +365,9 @@ int cmd_invite(int argc, char *argv[]) {
return 1; return 1;
// Create a hash of the key. // Create a hash of the key.
char hash[64];
char *fingerprint = ecdsa_get_base64_public_key(key); char *fingerprint = ecdsa_get_base64_public_key(key);
digest_t *digest = digest_open_by_name("sha256", 18); sha512(fingerprint, strlen(fingerprint), hash);
if(!digest)
abort();
digest_create(digest, fingerprint, strlen(fingerprint), hash);
b64encode_urlsafe(hash, hash, 18); b64encode_urlsafe(hash, hash, 18);
// Create a random cookie for this invitation. // Create a random cookie for this invitation.
@ -378,10 +376,10 @@ int cmd_invite(int argc, char *argv[]) {
// Create a filename that doesn't reveal the cookie itself // Create a filename that doesn't reveal the cookie itself
char buf[18 + strlen(fingerprint)]; char buf[18 + strlen(fingerprint)];
char cookiehash[25]; char cookiehash[64];
memcpy(buf, cookie, 18); memcpy(buf, cookie, 18);
memcpy(buf + 18, fingerprint, sizeof buf - 18); memcpy(buf + 18, fingerprint, sizeof buf - 18);
digest_create(digest, buf, sizeof buf, cookiehash); sha512(buf, sizeof buf, cookiehash);
b64encode_urlsafe(cookiehash, cookiehash, 18); b64encode_urlsafe(cookiehash, cookiehash, 18);
b64encode_urlsafe(cookie, cookie, 18); b64encode_urlsafe(cookie, cookie, 18);
@ -739,8 +737,9 @@ make_names:
sptps_send_record(&sptps, 1, b64key, strlen(b64key)); sptps_send_record(&sptps, 1, b64key, strlen(b64key));
free(b64key); free(b64key);
ecdsa_free(key);
#ifndef DISABLE_LEGACY
rsa_t *rsa = rsa_generate(2048, 0x1001); rsa_t *rsa = rsa_generate(2048, 0x1001);
xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase); xasprintf(&filename, "%s" SLASH "rsa_key.priv", confbase);
f = fopenmask(filename, "w", 0600); f = fopenmask(filename, "w", 0600);
@ -751,8 +750,8 @@ make_names:
rsa_write_pem_public_key(rsa, fh); rsa_write_pem_public_key(rsa, fh);
fclose(fh); fclose(fh);
ecdsa_free(key);
rsa_free(rsa); rsa_free(rsa);
#endif
check_port(name); check_port(name);
@ -958,11 +957,8 @@ int cmd_join(int argc, char *argv[]) {
// Check if the hash of the key he gave us matches the hash in the URL. // Check if the hash of the key he gave us matches the hash in the URL.
char *fingerprint = line + 2; char *fingerprint = line + 2;
digest_t *digest = digest_open_by_name("sha256", 18); char hishash[64];
if(!digest) if(sha512(fingerprint, strlen(fingerprint), hishash)) {
abort();
char hishash[18];
if(!digest_create(digest, fingerprint, strlen(fingerprint), hishash)) {
fprintf(stderr, "Could not create digest\n%s\n", line + 2); fprintf(stderr, "Could not create digest\n%s\n", line + 2);
return 1; return 1;
} }

View file

@ -58,6 +58,9 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
/* Add our data to buffer */ /* Add our data to buffer */
if(c->status.encryptout) { if(c->status.encryptout) {
#ifdef DISABLE_LEGACY
return false;
#else
size_t outlen = length; size_t outlen = length;
if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) { if(!cipher_encrypt(c->outcipher, buffer, length, buffer_prepare(&c->outbuf, length), &outlen, false) || outlen != length) {
@ -65,6 +68,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
c->name, c->hostname); c->name, c->hostname);
return false; return false;
} }
#endif
} else { } else {
buffer_add(&c->outbuf, buffer, length); buffer_add(&c->outbuf, buffer, length);
} }
@ -170,6 +174,9 @@ bool receive_meta(connection_t *c) {
inlen -= endp - bufp; inlen -= endp - bufp;
bufp = endp; bufp = endp;
} else { } else {
#ifdef DISABLE_LEGACY
return false;
#else
size_t outlen = inlen; size_t outlen = inlen;
if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) { if(!cipher_decrypt(c->incipher, bufp, inlen, buffer_prepare(&c->inbuf, inlen), &outlen, false) || inlen != outlen) {
@ -179,6 +186,7 @@ bool receive_meta(connection_t *c) {
} }
inlen = 0; inlen = 0;
#endif
} }
while(c->inbuf.len) { while(c->inbuf.len) {

View file

@ -351,10 +351,14 @@ static bool try_mac(node_t *n, const vpn_packet_t *inpkt) {
if(n->status.sptps) if(n->status.sptps)
return sptps_verify_datagram(&n->sptps, DATA(inpkt), inpkt->len); return sptps_verify_datagram(&n->sptps, DATA(inpkt), inpkt->len);
#ifdef DISABLE_LEGACY
return false;
#else
if(!digest_active(n->indigest) || inpkt->len < sizeof(seqno_t) + digest_length(n->indigest)) if(!digest_active(n->indigest) || inpkt->len < sizeof(seqno_t) + digest_length(n->indigest))
return false; return false;
return digest_verify(n->indigest, SEQNO(inpkt), inpkt->len - digest_length(n->indigest), DATA(inpkt) + inpkt->len - digest_length(n->indigest)); return digest_verify(n->indigest, SEQNO(inpkt), inpkt->len - digest_length(n->indigest), DATA(inpkt) + inpkt->len - digest_length(n->indigest));
#endif
} }
static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) { static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
@ -383,6 +387,9 @@ static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
return true; return true;
} }
#ifdef DISABLE_LEGACY
return false;
#else
if(!n->status.validkey) { if(!n->status.validkey) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname);
return false; return false;
@ -491,6 +498,7 @@ static bool receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
else else
receive_packet(n, inpkt); receive_packet(n, inpkt);
return true; return true;
#endif
} }
void receive_tcppacket(connection_t *c, const char *buffer, int len) { void receive_tcppacket(connection_t *c, const char *buffer, int len) {
@ -681,6 +689,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
if(n->status.sptps) if(n->status.sptps)
return send_sptps_packet(n, origpkt); return send_sptps_packet(n, origpkt);
#ifdef DISABLE_LEGACY
return;
#else
/* Make sure we have a valid key */ /* Make sure we have a valid key */
if(!n->status.validkey) { if(!n->status.validkey) {
@ -789,6 +800,7 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
end: end:
origpkt->len = origlen; origpkt->len = origlen;
#endif
} }
static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void *data, size_t len) { static bool send_sptps_data_priv(node_t *to, node_t *from, int type, const void *data, size_t len) {

View file

@ -145,6 +145,7 @@ bool read_ecdsa_public_key(connection_t *c) {
return c->ecdsa; return c->ecdsa;
} }
#ifndef DISABLE_LEGACY
bool read_rsa_public_key(connection_t *c) { bool read_rsa_public_key(connection_t *c) {
if(ecdsa_active(c->ecdsa)) if(ecdsa_active(c->ecdsa))
return true; return true;
@ -182,6 +183,7 @@ bool read_rsa_public_key(connection_t *c) {
free(fname); free(fname);
return c->rsa; return c->rsa;
} }
#endif
static bool read_ecdsa_private_key(void) { static bool read_ecdsa_private_key(void) {
FILE *fp; FILE *fp;
@ -248,6 +250,7 @@ static bool read_invitation_key(void) {
return invitation_key; return invitation_key;
} }
#ifndef DISABLE_LEGACY
static bool read_rsa_private_key(void) { static bool read_rsa_private_key(void) {
FILE *fp; FILE *fp;
char *fname; char *fname;
@ -304,6 +307,7 @@ static bool read_rsa_private_key(void) {
free(fname); free(fname);
return myself->connection->rsa; return myself->connection->rsa;
} }
#endif
static timeout_t keyexpire_timeout; static timeout_t keyexpire_timeout;
@ -773,6 +777,13 @@ static bool setup_myself(void) {
myself->options |= PROT_MINOR << 24; myself->options |= PROT_MINOR << 24;
#ifdef DISABLE_LEGACY
experimental = read_ecdsa_private_key();
if(!experimental) {
logger(DEBUG_ALWAYS, LOG_ERR, "No private key available, cannot start tinc!");
return false;
}
#else
if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) { if(!get_config_bool(lookup_config(config_tree, "ExperimentalProtocol"), &experimental)) {
experimental = read_ecdsa_private_key(); experimental = read_ecdsa_private_key();
if(!experimental) if(!experimental)
@ -790,6 +801,7 @@ static bool setup_myself(void) {
return false; return false;
} }
} }
#endif
/* Ensure myport is numeric */ /* Ensure myport is numeric */
@ -854,6 +866,7 @@ static bool setup_myself(void) {
sptps_replaywin = replaywin; sptps_replaywin = replaywin;
} }
#ifndef DISABLE_LEGACY
/* Generate packet encryption key */ /* Generate packet encryption key */
if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher)) if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher))
@ -891,6 +904,7 @@ static bool setup_myself(void) {
} }
free(digest); free(digest);
#endif
/* Compression */ /* Compression */

View file

@ -549,8 +549,10 @@ begin:
c->status.connecting = true; c->status.connecting = true;
c->name = xstrdup(outgoing->name); c->name = xstrdup(outgoing->name);
#ifndef DISABLE_LEGACY
c->outcipher = myself->connection->outcipher; c->outcipher = myself->connection->outcipher;
c->outdigest = myself->connection->outdigest; c->outdigest = myself->connection->outdigest;
#endif
c->outmaclength = myself->connection->outmaclength; c->outmaclength = myself->connection->outmaclength;
c->outcompression = myself->connection->outcompression; c->outcompression = myself->connection->outcompression;
c->last_ping_time = now.tv_sec; c->last_ping_time = now.tv_sec;
@ -696,8 +698,10 @@ void handle_new_meta_connection(void *data, int flags) {
c = new_connection(); c = new_connection();
c->name = xstrdup("<unknown>"); c->name = xstrdup("<unknown>");
#ifndef DISABLE_LEGACY
c->outcipher = myself->connection->outcipher; c->outcipher = myself->connection->outcipher;
c->outdigest = myself->connection->outdigest; c->outdigest = myself->connection->outdigest;
#endif
c->outmaclength = myself->connection->outmaclength; c->outmaclength = myself->connection->outmaclength;
c->outcompression = myself->connection->outcompression; c->outcompression = myself->connection->outcompression;

View file

@ -30,7 +30,7 @@
#include "utils.h" #include "utils.h"
#include "xalloc.h" #include "xalloc.h"
static digest_t *sha256; #include "ed25519/sha512.h"
splay_tree_t *node_tree; splay_tree_t *node_tree;
static splay_tree_t *node_id_tree; static splay_tree_t *node_id_tree;
@ -48,8 +48,6 @@ static int node_id_compare(const node_t *a, const node_t *b) {
} }
void init_nodes(void) { void init_nodes(void) {
sha256 = digest_open_by_name("sha256", sizeof(node_id_t));
node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node); node_tree = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL); node_id_tree = splay_alloc_tree((splay_compare_t) node_id_compare, NULL);
node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t)); node_udp_cache = hash_alloc(0x100, sizeof(sockaddr_t));
@ -61,8 +59,6 @@ void exit_nodes(void) {
hash_free(node_udp_cache); hash_free(node_udp_cache);
splay_delete_tree(node_id_tree); splay_delete_tree(node_id_tree);
splay_delete_tree(node_tree); splay_delete_tree(node_tree);
digest_close(sha256);
} }
node_t *new_node(void) { node_t *new_node(void) {
@ -86,10 +82,12 @@ void free_node(node_t *n) {
sockaddrfree(&n->address); sockaddrfree(&n->address);
#ifndef DISABLE_LEGACY
cipher_close(n->incipher); cipher_close(n->incipher);
digest_close(n->indigest); digest_close(n->indigest);
cipher_close(n->outcipher); cipher_close(n->outcipher);
digest_close(n->outdigest); digest_close(n->outdigest);
#endif
ecdsa_free(n->ecdsa); ecdsa_free(n->ecdsa);
sptps_stop(&n->sptps); sptps_stop(&n->sptps);
@ -109,7 +107,9 @@ void free_node(node_t *n) {
} }
void node_add(node_t *n) { void node_add(node_t *n) {
digest_create(sha256, n->name, strlen(n->name), &n->id); unsigned char buf[64];
sha512(n->name, strlen(n->name),buf);
memcpy(&n->id, buf, sizeof n->id);
splay_insert(node_tree, n); splay_insert(node_tree, n);
splay_insert(node_id_tree, n); splay_insert(node_id_tree, n);
@ -191,10 +191,15 @@ bool dump_nodes(connection_t *c) {
sprintf(id + 2 * c, "%02hhx", n->id.x[c]); sprintf(id + 2 * c, "%02hhx", n->id.x[c]);
id[sizeof id - 1] = 0; id[sizeof id - 1] = 0;
send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES, send_request(c, "%d %d %s %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
n->name, id, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher), n->name, id, n->hostname ?: "unknown port unknown",
digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), n->outcompression, #ifdef DISABLE_LEGACY
n->options, bitfield_to_int(&n->status, sizeof n->status), n->nexthop ? n->nexthop->name : "-", 0, 0, 0,
n->via ? n->via->name ?: "-" : "-", n->distance, n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change); #else
cipher_get_nid(n->outcipher), digest_get_nid(n->outdigest), (int)digest_length(n->outdigest),
#endif
n->outcompression, n->options, bitfield_to_int(&n->status, sizeof n->status),
n->nexthop ? n->nexthop->name : "-", n->via ? n->via->name ?: "-" : "-", n->distance,
n->mtu, n->minmtu, n->maxmtu, (long)n->last_state_change);
} }
return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES); return send_request(c, "%d %d", CONTROL, REQ_DUMP_NODES);

View file

@ -57,11 +57,13 @@ typedef struct node_t {
ecdsa_t *ecdsa; /* His public ECDSA key */ ecdsa_t *ecdsa; /* His public ECDSA key */
sptps_t sptps; sptps_t sptps;
#ifndef DISABLE_LEGACY
cipher_t *incipher; /* Cipher for UDP packets */ cipher_t *incipher; /* Cipher for UDP packets */
digest_t *indigest; /* Digest for UDP packets */ digest_t *indigest; /* Digest for UDP packets */
cipher_t *outcipher; /* Cipher for UDP packets */ cipher_t *outcipher; /* Cipher for UDP packets */
digest_t *outdigest; /* Digest for UDP packets */ digest_t *outdigest; /* Digest for UDP packets */
#endif
int incompression; /* Compressionlevel, 0 = no compression */ int incompression; /* Compressionlevel, 0 = no compression */
int outcompression; /* Compressionlevel, 0 = no compression */ int outcompression; /* Compressionlevel, 0 = no compression */

View file

@ -45,6 +45,8 @@
#include "utils.h" #include "utils.h"
#include "xalloc.h" #include "xalloc.h"
#include "ed25519/sha512.h"
ecdsa_t *invitation_key = NULL; ecdsa_t *invitation_key = NULL;
static bool send_proxyrequest(connection_t *c) { static bool send_proxyrequest(connection_t *c) {
@ -211,17 +213,13 @@ static bool receive_invitation_sptps(void *handle, uint8_t type, const void *dat
return false; return false;
// Recover the filename from the cookie and the key // Recover the filename from the cookie and the key
digest_t *digest = digest_open_by_name("sha256", 18);
if(!digest)
abort();
char *fingerprint = ecdsa_get_base64_public_key(invitation_key); char *fingerprint = ecdsa_get_base64_public_key(invitation_key);
char hashbuf[18 + strlen(fingerprint)]; char hashbuf[18 + strlen(fingerprint)];
char cookie[25]; char cookie[64];
memcpy(hashbuf, data, 18); memcpy(hashbuf, data, 18);
memcpy(hashbuf + 18, fingerprint, sizeof hashbuf - 18); memcpy(hashbuf + 18, fingerprint, sizeof hashbuf - 18);
digest_create(digest, hashbuf, sizeof hashbuf, cookie); sha512(hashbuf, sizeof hashbuf, cookie);
b64encode_urlsafe(cookie, cookie, 18); b64encode_urlsafe(cookie, cookie, 18);
digest_close(digest);
free(fingerprint); free(fingerprint);
char filename[PATH_MAX], usedname[PATH_MAX]; char filename[PATH_MAX], usedname[PATH_MAX];
@ -412,6 +410,9 @@ bool id_h(connection_t *c, const char *request) {
} }
bool send_metakey(connection_t *c) { bool send_metakey(connection_t *c) {
#ifdef DISABLE_LEGACY
return false;
#else
if(!myself->connection->rsa) { if(!myself->connection->rsa) {
logger(DEBUG_CONNECTIONS, LOG_ERR, "Peer %s (%s) uses legacy protocol which we don't support", c->name, c->hostname); logger(DEBUG_CONNECTIONS, LOG_ERR, "Peer %s (%s) uses legacy protocol which we don't support", c->name, c->hostname);
return false; return false;
@ -480,9 +481,13 @@ bool send_metakey(connection_t *c) {
c->status.encryptout = true; c->status.encryptout = true;
return result; return result;
#endif
} }
bool metakey_h(connection_t *c, const char *request) { bool metakey_h(connection_t *c, const char *request) {
#ifdef DISABLE_LEGACY
return false;
#else
if(!myself->connection->rsa) if(!myself->connection->rsa)
return false; return false;
@ -545,9 +550,13 @@ bool metakey_h(connection_t *c, const char *request) {
c->allow_request = CHALLENGE; c->allow_request = CHALLENGE;
return send_challenge(c); return send_challenge(c);
#endif
} }
bool send_challenge(connection_t *c) { bool send_challenge(connection_t *c) {
#ifdef DISABLE_LEGACY
return false;
#else
const size_t len = rsa_size(c->rsa); const size_t len = rsa_size(c->rsa);
char buffer[len * 2 + 1]; char buffer[len * 2 + 1];
@ -565,9 +574,13 @@ bool send_challenge(connection_t *c) {
/* Send the challenge */ /* Send the challenge */
return send_request(c, "%d %s", CHALLENGE, buffer); return send_request(c, "%d %s", CHALLENGE, buffer);
#endif
} }
bool challenge_h(connection_t *c, const char *request) { bool challenge_h(connection_t *c, const char *request) {
#ifdef DISABLE_LEGACY
return false;
#else
if(!myself->connection->rsa) if(!myself->connection->rsa)
return false; return false;
@ -606,9 +619,13 @@ bool challenge_h(connection_t *c, const char *request) {
c->allow_request = CHAL_REPLY; c->allow_request = CHAL_REPLY;
return send_request(c, "%d %s", CHAL_REPLY, buffer); return send_request(c, "%d %s", CHAL_REPLY, buffer);
#endif
} }
bool chal_reply_h(connection_t *c, const char *request) { bool chal_reply_h(connection_t *c, const char *request) {
#ifdef DISABLE_LEGACY
return false;
#else
char hishash[MAX_STRING_SIZE]; char hishash[MAX_STRING_SIZE];
if(sscanf(request, "%*d " MAX_STRING, hishash) != 1) { if(sscanf(request, "%*d " MAX_STRING, hishash) != 1) {
@ -645,9 +662,13 @@ bool chal_reply_h(connection_t *c, const char *request) {
c->allow_request = ACK; c->allow_request = ACK;
return send_ack(c); return send_ack(c);
#endif
} }
static bool send_upgrade(connection_t *c) { static bool send_upgrade(connection_t *c) {
#ifdef DISABLE_LEGACY
return false;
#else
/* Special case when protocol_minor is 1: the other end is Ed25519 capable, /* Special case when protocol_minor is 1: the other end is Ed25519 capable,
* but doesn't know our key yet. So send it now. */ * but doesn't know our key yet. So send it now. */
@ -659,6 +680,7 @@ static bool send_upgrade(connection_t *c) {
bool result = send_request(c, "%d %s", ACK, pubkey); bool result = send_request(c, "%d %s", ACK, pubkey);
free(pubkey); free(pubkey);
return result; return result;
#endif
} }
bool send_ack(connection_t *c) { bool send_ack(connection_t *c) {

View file

@ -266,6 +266,9 @@ bool send_ans_key(node_t *to) {
if(to->status.sptps) if(to->status.sptps)
abort(); abort();
#ifdef DISABLE_LEGACY
return false;
#else
size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1; size_t keylen = myself->incipher ? cipher_keylength(myself->incipher) : 1;
char key[keylen * 2 + 1]; char key[keylen * 2 + 1];
@ -306,6 +309,7 @@ bool send_ans_key(node_t *to) {
digest_get_nid(to->indigest), digest_get_nid(to->indigest),
(int)digest_length(to->indigest), (int)digest_length(to->indigest),
to->incompression); to->incompression);
#endif
} }
bool ans_key_h(connection_t *c, const char *request) { bool ans_key_h(connection_t *c, const char *request) {
@ -371,9 +375,11 @@ bool ans_key_h(connection_t *c, const char *request) {
return send_request(to->nexthop->connection, "%s", request); return send_request(to->nexthop->connection, "%s", request);
} }
#ifndef DISABLE_LEGACY
/* Don't use key material until every check has passed. */ /* Don't use key material until every check has passed. */
cipher_close(from->outcipher); cipher_close(from->outcipher);
digest_close(from->outdigest); digest_close(from->outdigest);
#endif
from->status.validkey = false; from->status.validkey = false;
if(compression < 0 || compression > 11) { if(compression < 0 || compression > 11) {
@ -408,6 +414,10 @@ bool ans_key_h(connection_t *c, const char *request) {
return true; return true;
} }
#ifdef DISABLE_LEGACY
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%) uses legacy protocol!", from->name, from->hostname);
return false;
#else
/* Check and lookup cipher and digest algorithms */ /* Check and lookup cipher and digest algorithms */
if(cipher) { if(cipher) {
@ -462,4 +472,5 @@ bool ans_key_h(connection_t *c, const char *request) {
send_mtu_probe(from); send_mtu_probe(from);
return true; return true;
#endif
} }

View file

@ -119,8 +119,12 @@ static void usage(bool status) {
" restart [tincd options] Restart tincd.\n" " restart [tincd options] Restart tincd.\n"
" reload Partially reload configuration of running tincd.\n" " reload Partially reload configuration of running tincd.\n"
" pid Show PID of currently running tincd.\n" " pid Show PID of currently running tincd.\n"
#ifdef DISABLE_LEGACY
" generate-keys Generate a new Ed25519 public/private keypair.\n"
#else
" generate-keys [bits] Generate new RSA and Ed25519 public/private keypairs.\n" " generate-keys [bits] Generate new RSA and Ed25519 public/private keypairs.\n"
" generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n" " generate-rsa-keys [bits] Generate a new RSA public/private keypair.\n"
#endif
" generate-ed25519-keys Generate a new Ed25519 public/private keypair.\n" " generate-ed25519-keys Generate a new Ed25519 public/private keypair.\n"
" dump Dump a list of one of the following things:\n" " dump Dump a list of one of the following things:\n"
" [reachable] nodes - all known nodes in the VPN\n" " [reachable] nodes - all known nodes in the VPN\n"
@ -415,6 +419,7 @@ static bool ed25519_keygen(bool ask) {
return true; return true;
} }
#ifndef DISABLE_LEGACY
/* /*
Generate a public/private RSA keypair, and ask for a file to store Generate a public/private RSA keypair, and ask for a file to store
them in. them in.
@ -480,6 +485,7 @@ static bool rsa_keygen(int bits, bool ask) {
return true; return true;
} }
#endif
char buffer[4096]; char buffer[4096];
size_t blen = 0; size_t blen = 0;
@ -1800,7 +1806,12 @@ static int cmd_init(int argc, char *argv[]) {
fprintf(f, "Name = %s\n", name); fprintf(f, "Name = %s\n", name);
fclose(f); fclose(f);
if(!rsa_keygen(2048, false) || !ed25519_keygen(false)) #ifndef DISABLE_LEGACY
if(!rsa_keygen(2048, false))
return 1;
#endif
if(!ed25519_keygen(false))
return 1; return 1;
check_port(name); check_port(name);
@ -1824,7 +1835,11 @@ static int cmd_init(int argc, char *argv[]) {
} }
static int cmd_generate_keys(int argc, char *argv[]) { static int cmd_generate_keys(int argc, char *argv[]) {
#ifdef DISABLE_LEGACY
if(argc > 1) {
#else
if(argc > 2) { if(argc > 2) {
#endif
fprintf(stderr, "Too many arguments!\n"); fprintf(stderr, "Too many arguments!\n");
return 1; return 1;
} }
@ -1832,9 +1847,18 @@ static int cmd_generate_keys(int argc, char *argv[]) {
if(!name) if(!name)
name = get_my_name(false); name = get_my_name(false);
return !(rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true) && ed25519_keygen(true)); #ifndef DISABLE_LEGACY
if(!rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true)
return 1;
#endif
if(!ed25519_keygen(true))
return 1;
return 0;
} }
#ifndef DISABLE_LEGACY
static int cmd_generate_rsa_keys(int argc, char *argv[]) { static int cmd_generate_rsa_keys(int argc, char *argv[]) {
if(argc > 2) { if(argc > 2) {
fprintf(stderr, "Too many arguments!\n"); fprintf(stderr, "Too many arguments!\n");
@ -1846,6 +1870,7 @@ static int cmd_generate_rsa_keys(int argc, char *argv[]) {
return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true); return !rsa_keygen(argc > 1 ? atoi(argv[1]) : 2048, true);
} }
#endif
static int cmd_generate_ed25519_keys(int argc, char *argv[]) { static int cmd_generate_ed25519_keys(int argc, char *argv[]) {
if(argc > 1) { if(argc > 1) {
@ -2196,7 +2221,9 @@ static const struct {
{"set", cmd_config}, {"set", cmd_config},
{"init", cmd_init}, {"init", cmd_init},
{"generate-keys", cmd_generate_keys}, {"generate-keys", cmd_generate_keys},
#ifndef DISABLE_LEGACY
{"generate-rsa-keys", cmd_generate_rsa_keys}, {"generate-rsa-keys", cmd_generate_rsa_keys},
#endif
{"generate-ed25519-keys", cmd_generate_ed25519_keys}, {"generate-ed25519-keys", cmd_generate_ed25519_keys},
{"help", cmd_help}, {"help", cmd_help},
{"version", cmd_version}, {"version", cmd_version},