ACLOCAL_AMFLAGS = -I m4
-EXTRA_DIST = have.h system.h COPYING.README README.android
+EXTRA_DIST = COPYING.README README.android
ChangeLog:
git log > ChangeLog
tinc_LZO
if test "$with_libgcrypt" = yes; then
+ gcrypt=true
AM_PATH_LIBGCRYPT([1.4.0], [], [])
- ln -sf gcrypt/cipher.c gcrypt/cipher.h gcrypt/crypto.c gcrypt/crypto.h gcrypt/digest.c gcrypt/digest.h gcrypt/ecdh.c gcrypt/ecdh.h gcrypt/ecdsa.c gcrypt/ecdsa.h gcrypt/ecdsagen.c gcrypt/ecdsagen.h gcrypt/prf.c gcrypt/prf.h gcrypt/rsa.c gcrypt/rsa.h gcrypt/rsagen.c gcrypt/rsagen.h src/
else
+ openssl=true
tinc_OPENSSL
- ln -sf openssl/cipher.c openssl/cipher.h openssl/crypto.c openssl/crypto.h openssl/digest.c openssl/digest.h openssl/ecdh.c openssl/ecdh.h openssl/ecdsa.c openssl/ecdsa.h openssl/ecdsagen.c openssl/ecdsagen.h openssl/prf.c openssl/prf.h openssl/rsa.c openssl/rsa.h openssl/rsagen.c openssl/rsagen.h src/
fi
+AM_CONDITIONAL(OPENSSL, test "$openssl" = true)
+AM_CONDITIONAL(GCRYPT, test "$grypt" = true)
dnl Check if support for jumbograms is requested
AC_ARG_ENABLE(jumbograms,
protocol_key.c protocol_subnet.c route.c sptps.c subnet.c subnet_parse.c event.c tincd.c \
dummy_device.c raw_socket_device.c multicast_device.c names.c
+tinc_SOURCES = \
+ utils.c getopt.c getopt1.c dropin.c \
+ info.c list.c subnet_parse.c tincctl.c top.c names.c
+
+sptps_test_SOURCES = \
+ logger.c sptps.c sptps_test.c utils.c
+
## Conditionally compile device drivers
if LINUX
if BSD
tincd_SOURCES += bsd/device.c
+if TUNEMU
+tincd_SOURCES += bsd/tunemu.c
+endif
endif
if SOLARIS
tincd_SOURCES += vde_device.c
endif
-nodist_tincd_SOURCES = \
- cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c rsa.c
-
-tinc_SOURCES = \
- utils.c getopt.c getopt1.c dropin.c \
- info.c list.c subnet_parse.c tincctl.c top.c names.c
-
-nodist_tinc_SOURCES = \
- ecdsagen.c rsagen.c
-
-sptps_test_SOURCES = \
- logger.c cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c \
- sptps.c sptps_test.c utils.c
+if OPENSSL
+tincd_SOURCES += \
+ openssl/cipher.c \
+ openssl/crypto.c \
+ openssl/ecdh.c \
+ openssl/ecdsa.c \
+ openssl/digest.c \
+ openssl/prf.c \
+ openssl/rsa.c
+tinc_SOURCES += \
+ openssl/ecdsa.c \
+ openssl/ecdsagen.c \
+ openssl/rsa.c \
+ openssl/rsagen.c
+sptps_test_SOURCES += \
+ openssl/cipher.c \
+ openssl/crypto.c \
+ openssl/ecdh.c \
+ openssl/ecdsa.c \
+ openssl/digest.c \
+ openssl/prf.c
+endif
-if TUNEMU
-tincd_SOURCES += bsd/tunemu.c
+if GCRYPT
+tincd_SOURCES += \
+ gcrypt/cipher.c \
+ gcrypt/crypto.c \
+ gcrypt/ecdh.c \
+ gcrypt/ecdsa.c \
+ gcrypt/digest.c \
+ gcrypt/prf.c \
+ gcrypt/rsa.c
+tinc_SOURCES += \
+ gcrypt/ecdsa.c \
+ gcrypt/ecdsagen.c \
+ gcrypt/rsa.c \
+ gcrypt/rsagen.c
+sptps_test_SOURCES += \
+ gcrypt/cipher.c \
+ gcrypt/crypto.c \
+ gcrypt/ecdh.c \
+ gcrypt/ecdsa.c \
+ gcrypt/digest.c \
+ gcrypt/prf.c
endif
tinc_LDADD = $(READLINE_LIBS) $(CURSES_LIBS)
noinst_HEADERS = \
xalloc.h utils.h getopt.h list.h splay_tree.h dropin.h fake-getaddrinfo.h fake-getnameinfo.h fake-gai-errnos.h ipv6.h ipv4.h ethernet.h \
buffer.h conf.h connection.h control.h control_common.h device.h edge.h graph.h info.h logger.h meta.h net.h netutl.h node.h process.h \
- protocol.h route.h subnet.h sptps.h tincctl.h top.h bsd/tunemu.h hash.h event.h names.h
-
-nodist_noinst_HEADERS = \
- cipher.h crypto.h ecdh.h ecdsa.h digest.h prf.h rsa.h ecdsagen.h rsagen.h
+ protocol.h route.h subnet.h sptps.h tincctl.h top.h hash.h event.h names.h have.h system.h
LIBS = @LIBS@ @LIBGCRYPT_LIBS@
/*
connection.c -- connection list management
- Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
2008 Max Rijevski <maksuf@gmail.com>
#include "control_common.h"
#include "list.h"
#include "logger.h"
+#include "rsa.h"
#include "subnet.h"
#include "utils.h"
#include "xalloc.h"
if(!c)
return;
- cipher_close(&c->incipher);
- digest_close(&c->indigest);
- cipher_close(&c->outcipher);
- digest_close(&c->outdigest);
+ cipher_close(c->incipher);
+ digest_close(c->indigest);
+ cipher_close(c->outcipher);
+ digest_close(c->outdigest);
sptps_stop(&c->sptps);
- ecdsa_free(&c->ecdsa);
- rsa_free(&c->rsa);
+ ecdsa_free(c->ecdsa);
+ rsa_free(c->rsa);
free(c->hischallenge);
/*
connection.h -- header for connection.c
- Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
struct node_t *node; /* node associated with the other end */
struct edge_t *edge; /* edge associated with this connection */
- 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 outcipher; /* Cipher we will use to send data to him */
- digest_t indigest;
- digest_t outdigest;
+ 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 *outcipher; /* Cipher we will use to send data to him */
+ digest_t *indigest;
+ digest_t *outdigest;
sptps_t sptps;
int inmaclength;
--- /dev/null
+/*
+ ecdh.c -- Diffie-Hellman key exchange handling
+ Copyright (C) 2011-2013 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "../system.h"
+
+#include "../ecdh.h"
+#include "../logger.h"
+#include "../utils.h"
+#include "../xalloc.h"
+
+ecdh_t *ecdh_generate_public(void *pubkey) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
+ return NULL;
+}
+
+bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
+ return false
+}
+
+void ecdh_free(ecdh_t *ecdh) {
+}
--- /dev/null
+/*
+ ecdsa.c -- ECDSA key handling
+ Copyright (C) 2011-2013 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "../system.h"
+
+#include "../logger.h"
+#include "../ecdsa.h"
+#include "../utils.h"
+#include "../xalloc.h"
+
+// Get and set ECDSA keys
+//
+ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
+ return NULL;
+}
+
+char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
+ return NULL;
+}
+
+// Read PEM ECDSA keys
+
+ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
+ return NULL;
+}
+
+ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
+ return NULL;
+}
+
+size_t ecdsa_size(ecdsa_t *ecdsa) {
+ return 0;
+}
+
+bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
+ return false;
+}
+
+bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
+ return false;
+}
+
+bool ecdsa_active(ecdsa_t *ecdsa) {
+ return false;
+}
+
+void ecdsa_free(ecdsa_t *ecdsa) {
+}
--- /dev/null
+/*
+ ecdsagen.c -- ECDSA key generation and export
+ Copyright (C) 2011-2013 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "../system.h"
+
+#include "../ecdsagen.h"
+#include "../utils.h"
+#include "../xalloc.h"
+
+// Generate ECDSA key
+
+ecdsa_t *ecdsa_generate(void) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
+ return NULL;
+}
+
+// Write PEM ECDSA keys
+
+bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
+ return false;
+}
+
+bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
+ return false;
+}
--- /dev/null
+/*
+ prf.c -- Pseudo-Random Function for key material generation
+ Copyright (C) 2011-2013 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
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "../system.h"
+
+#include "digest.h"
+#include "../digest.h"
+#include "../prf.h"
+
+bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "PRF support using libgcrypt not implemented");
+ return false;
+}
/*
meta.c -- handle the meta communication
- Copyright (C) 2000-2012 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2000-2013 Guus Sliepen <guus@tinc-vpn.org>,
2000-2005 Ivo Timmermans
2006 Scott Lamb <slamb@slamb.org>
if(c->status.encryptout) {
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) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while encrypting metadata to %s (%s)",
c->name, c->hostname);
return false;
} else {
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) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error while decrypting metadata from %s (%s)",
c->name, c->hostname);
return false;
if(n->status.sptps)
return sptps_verify_datagram(&n->sptps, (char *)&inpkt->seqno, inpkt->len);
- if(!digest_active(&n->indigest) || inpkt->len < sizeof inpkt->seqno + digest_length(&n->indigest))
+ if(!digest_active(n->indigest) || inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest))
return false;
- return digest_verify(&n->indigest, &inpkt->seqno, inpkt->len - n->indigest.maclength, (const char *)&inpkt->seqno + inpkt->len - n->indigest.maclength);
+ return digest_verify(n->indigest, &inpkt->seqno, inpkt->len - digest_length(n->indigest), (const char *)&inpkt->seqno + inpkt->len - digest_length(n->indigest));
}
static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
return;
}
- if(!cipher_active(&n->incipher)) {
+ if(!cipher_active(n->incipher)) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet",
n->name, n->hostname);
return;
/* Check packet length */
- if(inpkt->len < sizeof inpkt->seqno + digest_length(&n->indigest)) {
+ if(inpkt->len < sizeof inpkt->seqno + digest_length(n->indigest)) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got too short packet from %s (%s)",
n->name, n->hostname);
return;
/* Check the message authentication code */
- if(digest_active(&n->indigest)) {
- inpkt->len -= n->indigest.maclength;
- if(!digest_verify(&n->indigest, &inpkt->seqno, inpkt->len, (const char *)&inpkt->seqno + inpkt->len)) {
+ if(digest_active(n->indigest)) {
+ inpkt->len -= digest_length(n->indigest);
+ if(!digest_verify(n->indigest, &inpkt->seqno, inpkt->len, (const char *)&inpkt->seqno + inpkt->len)) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Got unauthenticated packet from %s (%s)", n->name, n->hostname);
return;
}
}
/* Decrypt the packet */
- if(cipher_active(&n->incipher)) {
+ if(cipher_active(n->incipher)) {
outpkt = pkt[nextpkt++];
outlen = MAXSIZE;
- if(!cipher_decrypt(&n->incipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
+ if(!cipher_decrypt(n->incipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
logger(DEBUG_TRAFFIC, LOG_DEBUG, "Error decrypting packet from %s (%s)", n->name, n->hostname);
return;
}
/* Encrypt the packet */
- if(cipher_active(&n->outcipher)) {
+ if(cipher_active(n->outcipher)) {
outpkt = pkt[nextpkt++];
outlen = MAXSIZE;
- if(!cipher_encrypt(&n->outcipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
+ if(!cipher_encrypt(n->outcipher, &inpkt->seqno, inpkt->len, &outpkt->seqno, &outlen, true)) {
logger(DEBUG_TRAFFIC, LOG_ERR, "Error while encrypting packet to %s (%s)", n->name, n->hostname);
goto end;
}
/* Add the message authentication code */
- if(digest_active(&n->outdigest)) {
- digest_create(&n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len);
- inpkt->len += digest_length(&n->outdigest);
+ if(digest_active(n->outdigest)) {
+ digest_create(n->outdigest, &inpkt->seqno, inpkt->len, (char *)&inpkt->seqno + inpkt->len);
+ inpkt->len += digest_length(n->outdigest);
}
/* Send the packet */
char *scriptextension;
bool node_read_ecdsa_public_key(node_t *n) {
- if(ecdsa_active(&n->ecdsa))
+ if(ecdsa_active(n->ecdsa))
return true;
splay_tree_t *config_tree;
FILE *fp;
char *pubname = NULL, *hcfname = NULL;
char *p;
- bool result = false;
xasprintf(&hcfname, "%s" SLASH "hosts" SLASH "%s", confbase, n->name);
/* First, check for simple ECDSAPublicKey statement */
if(get_config_string(lookup_config(config_tree, "ECDSAPublicKey"), &p)) {
- result = ecdsa_set_base64_public_key(&n->ecdsa, p);
+ n->ecdsa = ecdsa_set_base64_public_key(p);
free(p);
goto exit;
}
goto exit;
}
- result = ecdsa_read_pem_public_key(&n->ecdsa, fp);
+ n->ecdsa = ecdsa_read_pem_public_key(fp);
fclose(fp);
exit:
exit_configuration(&config_tree);
free(hcfname);
free(pubname);
- return result;
+ return n->ecdsa;
}
bool read_ecdsa_public_key(connection_t *c) {
+ if(ecdsa_active(c->ecdsa))
+ return true;
+
FILE *fp;
char *fname;
char *p;
- bool result;
/* First, check for simple ECDSAPublicKey statement */
if(get_config_string(lookup_config(c->config_tree, "ECDSAPublicKey"), &p)) {
- result = ecdsa_set_base64_public_key(&c->ecdsa, p);
+ c->ecdsa = ecdsa_set_base64_public_key(p);
free(p);
- return result;
+ return c->ecdsa;
}
/* Else, check for ECDSAPublicKeyFile statement and read it */
return false;
}
- result = ecdsa_read_pem_public_key(&c->ecdsa, fp);
+ c->ecdsa = ecdsa_read_pem_public_key(fp);
fclose(fp);
- if(!result)
+ if(!c->ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Parsing ECDSA public key file `%s' failed.", fname);
free(fname);
- return result;
+ return c->ecdsa;
}
bool read_rsa_public_key(connection_t *c) {
+ if(ecdsa_active(c->ecdsa))
+ return true;
+
FILE *fp;
char *fname;
char *n;
- bool result;
/* First, check for simple PublicKey statement */
if(get_config_string(lookup_config(c->config_tree, "PublicKey"), &n)) {
- result = rsa_set_hex_public_key(&c->rsa, n, "FFFF");
+ c->rsa = rsa_set_hex_public_key(n, "FFFF");
free(n);
- return result;
+ return c->rsa;
}
/* Else, check for PublicKeyFile statement and read it */
return false;
}
- result = rsa_read_pem_public_key(&c->rsa, fp);
+ c->rsa = rsa_read_pem_public_key(fp);
fclose(fp);
- if(!result)
+ if(!c->rsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA public key file `%s' failed: %s", fname, strerror(errno));
free(fname);
- return result;
+ return c->rsa;
}
static bool read_ecdsa_private_key(void) {
FILE *fp;
char *fname;
- bool result;
/* Check for PrivateKeyFile statement and read it */
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for ECDSA private key file `%s'!", fname);
#endif
- result = ecdsa_read_pem_private_key(&myself->connection->ecdsa, fp);
+ myself->connection->ecdsa = ecdsa_read_pem_private_key(fp);
fclose(fp);
- if(!result)
+ if(!myself->connection->ecdsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Reading ECDSA private key file `%s' failed: %s", fname, strerror(errno));
free(fname);
- return result;
+ return myself->connection->ecdsa;
}
static bool read_rsa_private_key(void) {
FILE *fp;
char *fname;
char *n, *d;
- bool result;
/* First, check for simple PrivateKey statement */
free(d);
return false;
}
- result = rsa_set_hex_private_key(&myself->connection->rsa, n, "FFFF", d);
+ myself->connection->rsa = rsa_set_hex_private_key(n, "FFFF", d);
free(n);
free(d);
- return result;
+ return myself->connection->rsa;
}
/* Else, check for PrivateKeyFile statement and read it */
logger(DEBUG_ALWAYS, LOG_WARNING, "Warning: insecure file permissions for RSA private key file `%s'!", fname);
#endif
- result = rsa_read_pem_private_key(&myself->connection->rsa, fp);
+ myself->connection->rsa = rsa_read_pem_private_key(fp);
fclose(fp);
- if(!result)
+ if(!myself->connection->rsa)
logger(DEBUG_ALWAYS, LOG_ERR, "Reading RSA private key file `%s' failed: %s", fname, strerror(errno));
free(fname);
- return result;
+ return myself->connection->rsa;
}
static timeout_t keyexpire_timeout;
if(!get_config_string(lookup_config(config_tree, "Cipher"), &cipher))
cipher = xstrdup("blowfish");
- if(!cipher_open_by_name(&myself->incipher, cipher)) {
+ if(!(myself->incipher = cipher_open_by_name(cipher))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized cipher type!");
return false;
}
if(!get_config_string(lookup_config(config_tree, "Digest"), &digest))
digest = xstrdup("sha1");
- if(!digest_open_by_name(&myself->indigest, digest, maclength)) {
+ if(!(myself->indigest = digest_open_by_name(digest, maclength))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Unrecognized digest type!");
return false;
}
/*
node.c -- node tree management
- Copyright (C) 2001-2012 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
2001-2005 Ivo Timmermans
This program is free software; you can redistribute it and/or modify
sockaddrfree(&n->address);
- cipher_close(&n->incipher);
- digest_close(&n->indigest);
- cipher_close(&n->outcipher);
- digest_close(&n->outdigest);
+ cipher_close(n->incipher);
+ digest_close(n->indigest);
+ cipher_close(n->outcipher);
+ digest_close(n->outdigest);
- ecdsa_free(&n->ecdsa);
+ ecdsa_free(n->ecdsa);
sptps_stop(&n->sptps);
timeout_del(&n->mtutimeout);
bool dump_nodes(connection_t *c) {
for splay_each(node_t, n, node_tree)
send_request(c, "%d %d %s %s %d %d %d %d %x %x %s %s %d %hd %hd %hd %ld", CONTROL, REQ_DUMP_NODES,
- n->name, n->hostname ?: "unknown port unknown", cipher_get_nid(&n->outcipher),
- digest_get_nid(&n->outdigest), (int)digest_length(&n->outdigest), n->outcompression,
+ n->name, n->hostname ?: "unknown port unknown", cipher_get_nid(n->outcipher),
+ digest_get_nid(n->outdigest), (int)digest_length(n->outdigest), 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);
time_t last_state_change;
time_t last_req_key;
- ecdsa_t ecdsa; /* His public ECDSA key */
+ ecdsa_t *ecdsa; /* His public ECDSA key */
sptps_t sptps;
- cipher_t incipher; /* Cipher for UDP packets */
- digest_t indigest; /* Digest for UDP packets */
+ cipher_t *incipher; /* Cipher for UDP packets */
+ digest_t *indigest; /* Digest for UDP packets */
- cipher_t outcipher; /* Cipher for UDP packets */
- digest_t outdigest; /* Digest for UDP packets */
+ cipher_t *outcipher; /* Cipher for UDP packets */
+ digest_t *outdigest; /* Digest for UDP packets */
int incompression; /* Compressionlevel, 0 = no compression */
int outcompression; /* Compressionlevel, 0 = no compression */
/*
cipher.c -- Symmetric block cipher handling
- Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2007-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <openssl/rand.h>
#include <openssl/err.h>
+#include <openssl/evp.h>
-#include "cipher.h"
-#include "logger.h"
-#include "xalloc.h"
+#include "../cipher.h"
+#include "../logger.h"
+#include "../xalloc.h"
+
+struct cipher {
+ EVP_CIPHER_CTX ctx;
+ const EVP_CIPHER *cipher;
+ struct cipher_counter *counter;
+};
typedef struct cipher_counter {
- unsigned char counter[EVP_MAX_IV_LENGTH];
- unsigned char block[EVP_MAX_IV_LENGTH];
+ unsigned char counter[CIPHER_MAX_IV_SIZE];
+ unsigned char block[CIPHER_MAX_IV_SIZE];
int n;
} cipher_counter_t;
-static bool cipher_open(cipher_t *cipher) {
+static cipher_t *cipher_open(const EVP_CIPHER *evp_cipher) {
+ cipher_t *cipher = xmalloc_and_zero(sizeof *cipher);
+ cipher->cipher = evp_cipher;
EVP_CIPHER_CTX_init(&cipher->ctx);
- return true;
+ return cipher;
}
-bool cipher_open_by_name(cipher_t *cipher, const char *name) {
- cipher->cipher = EVP_get_cipherbyname(name);
-
- if(cipher->cipher)
- return cipher_open(cipher);
+cipher_t *cipher_open_by_name(const char *name) {
+ const EVP_CIPHER *evp_cipher = EVP_get_cipherbyname(name);
+ if(!evp_cipher) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher name '%s'!", name);
+ return NULL;
+ }
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher name '%s'!", name);
- return false;
+ return cipher_open(evp_cipher);
}
-bool cipher_open_by_nid(cipher_t *cipher, int nid) {
- cipher->cipher = EVP_get_cipherbynid(nid);
-
- if(cipher->cipher)
- return cipher_open(cipher);
+cipher_t *cipher_open_by_nid(int nid) {
+ const EVP_CIPHER *evp_cipher = EVP_get_cipherbynid(nid);
+ if(!evp_cipher) {
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher nid %d!", nid);
+ return NULL;
+ }
- logger(DEBUG_ALWAYS, LOG_ERR, "Unknown cipher nid %d!", nid);
- return false;
+ return cipher_open(evp_cipher);
}
-bool cipher_open_blowfish_ofb(cipher_t *cipher) {
- cipher->cipher = EVP_bf_ofb();
- return cipher_open(cipher);
+cipher_t *cipher_open_blowfish_ofb(void) {
+ return cipher_open(EVP_bf_ofb());
}
void cipher_close(cipher_t *cipher) {
+ if(!cipher)
+ return;
+
EVP_CIPHER_CTX_cleanup(&cipher->ctx);
free(cipher->counter);
- cipher->counter = NULL;
+ free(cipher);
}
size_t cipher_keylength(const cipher_t *cipher) {
}
bool cipher_active(const cipher_t *cipher) {
- return cipher->cipher && cipher->cipher->nid != 0;
+ return cipher && cipher->cipher && cipher->cipher->nid != 0;
}
+++ /dev/null
-/*
- cipher.h -- header file cipher.c
- Copyright (C) 2007-2012 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_CIPHER_H__
-#define __TINC_CIPHER_H__
-
-#include <openssl/evp.h>
-
-#define CIPHER_MAX_BLOCK_SIZE EVP_MAX_BLOCK_LENGTH
-#define CIPHER_MAX_KEY_SIZE EVP_MAX_KEY_LENGTH
-#define CIPHER_MAX_IV_SIZE EVP_MAX_IV_LENGTH
-
-typedef struct cipher {
- EVP_CIPHER_CTX ctx;
- const EVP_CIPHER *cipher;
- struct cipher_counter *counter;
-} cipher_t;
-
-extern bool cipher_open_by_name(cipher_t *, const char *);
-extern bool cipher_open_by_nid(cipher_t *, int);
-extern bool cipher_open_blowfish_ofb(cipher_t *);
-extern void cipher_close(cipher_t *);
-extern size_t cipher_keylength(const cipher_t *);
-extern bool cipher_set_key(cipher_t *, void *, bool);
-extern bool cipher_set_key_from_rsa(cipher_t *, void *, size_t, bool);
-extern bool cipher_set_counter(cipher_t *, const void *, size_t);
-extern bool cipher_set_counter_key(cipher_t *, void *);
-extern bool cipher_encrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool);
-extern bool cipher_decrypt(cipher_t *, const void *indata, size_t inlen, void *outdata, size_t *outlen, bool);
-extern bool cipher_counter_xor(cipher_t *, const void *indata, size_t inlen, void *outdata);
-extern int cipher_get_nid(const cipher_t *);
-extern bool cipher_active(const cipher_t *);
-
-#endif
/*
crypto.c -- Cryptographic miscellaneous functions and initialisation
- Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2007-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
-#include "crypto.h"
+#include "../crypto.h"
void crypto_init(void) {
RAND_load_file("/dev/urandom", 1024);
+++ /dev/null
-/*
- crypto.h -- header for crypto.c
- Copyright (C) 2007 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_CRYPTO_H__
-#define __TINC_CRYPTO_H__
-
-extern void crypto_init();
-extern void crypto_exit();
-extern void randomize(void *, size_t);
-
-#endif
/*
digest.c -- Digest handling
- Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2007-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
-#include "utils.h"
-#include "xalloc.h"
+#include "../system.h"
+#include "../utils.h"
+#include "../xalloc.h"
#include <openssl/err.h>
#include <openssl/hmac.h>
#include "digest.h"
-#include "logger.h"
+#include "../digest.h"
+#include "../logger.h"
+
+static digest_t *digest_open(const EVP_MD *evp_md, int maclength) {
+ digest_t *digest = xmalloc_and_zero(sizeof *digest);
+ digest->digest = evp_md;
-static void set_maclength(digest_t *digest, int maclength) {
int digestlen = EVP_MD_size(digest->digest);
if(maclength > digestlen || maclength < 0)
digest->maclength = digestlen;
else
digest->maclength = maclength;
+
+ return digest;
}
-bool digest_open_by_name(digest_t *digest, const char *name, int maclength) {
- digest->digest = EVP_get_digestbyname(name);
- digest->key = NULL;
+digest_t *digest_open_by_name(const char *name, int maclength) {
+ const EVP_MD *evp_md = EVP_get_digestbyname(name);
- if(!digest->digest) {
+ if(!evp_md) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest name '%s'!", name);
return false;
}
- set_maclength(digest, maclength);
- return true;
+ return digest_open(evp_md, maclength);
}
-bool digest_open_by_nid(digest_t *digest, int nid, int maclength) {
- digest->digest = EVP_get_digestbynid(nid);
- digest->key = NULL;
+digest_t *digest_open_by_nid(int nid, int maclength) {
+ const EVP_MD *evp_md = EVP_get_digestbynid(nid);
- if(!digest->digest) {
+ if(!evp_md) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "Unknown digest nid %d!", nid);
return false;
}
- set_maclength(digest, maclength);
- return true;
+ return digest_open(evp_md, maclength);
}
-bool digest_open_sha1(digest_t *digest, int maclength) {
- digest->digest = EVP_sha1();
- digest->key = NULL;
-
- set_maclength(digest, maclength);
- return true;
+digest_t *digest_open_sha1(int maclength) {
+ return digest_open(EVP_sha1(), maclength);
}
bool digest_set_key(digest_t *digest, const void *key, size_t len) {
}
void digest_close(digest_t *digest) {
+ if(!digest)
+ return;
+
free(digest->key);
- digest->key = NULL;
+ free(digest);
}
bool digest_create(digest_t *digest, const void *indata, size_t inlen, void *outdata) {
}
bool digest_active(const digest_t *digest) {
- return digest->digest && digest->digest->type != 0;
+ return digest && digest->digest && digest->digest->type != 0;
}
/*
digest.h -- header file digest.c
- Copyright (C) 2007-2011 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef __TINC_DIGEST_H__
-#define __TINC_DIGEST_H__
+#ifndef __TINC_OPENSSL_DIGEST_H__
+#define __TINC_OPENSSL_DIGEST_H__
#include <openssl/evp.h>
-#define DIGEST_MAX_SIZE EVP_MAX_MD_SIZE
-
typedef struct digest {
const EVP_MD *digest;
int maclength;
char *key;
} digest_t;
-extern bool digest_open_by_name(struct digest *, const char *name, int maclength);
-extern bool digest_open_by_nid(struct digest *, int nid, int maclength);
-extern bool digest_open_sha1(struct digest *, int maclength);
-extern void digest_close(struct digest *);
-extern bool digest_create(struct digest *, const void *indata, size_t inlen, void *outdata);
-extern bool digest_verify(struct digest *, const void *indata, size_t inlen, const void *digestdata);
-extern bool digest_set_key(struct digest *, const void *key, size_t len);
-extern int digest_get_nid(const struct digest *);
-extern size_t digest_keylength(const struct digest *);
-extern size_t digest_length(const struct digest *);
-extern bool digest_active(const struct digest *);
-
#endif
/*
ecdh.c -- Diffie-Hellman key exchange handling
- Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2011-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
-#include "utils.h"
-#include "xalloc.h"
+#include "../system.h"
#include <openssl/err.h>
#include <openssl/ec.h>
+#include <openssl/ecdh.h>
#include <openssl/obj_mac.h>
-#include "ecdh.h"
-#include "logger.h"
+#define __TINC_ECDH_INTERNAL__
+typedef EC_KEY ecdh_t;
-bool ecdh_generate_public(ecdh_t *ecdh, void *pubkey) {
- *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
- if(!*ecdh) {
+#include "../ecdh.h"
+#include "../logger.h"
+#include "../utils.h"
+#include "../xalloc.h"
+
+ecdh_t *ecdh_generate_public(void *pubkey) {
+ ecdh_t *ecdh = EC_KEY_new_by_curve_name(NID_secp521r1);
+ if(!ecdh) {
logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
- if(!EC_KEY_generate_key(*ecdh)) {
- EC_KEY_free(*ecdh);
- *ecdh = NULL;
+ if(!EC_KEY_generate_key(ecdh)) {
+ EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return NULL;
}
- const EC_POINT *point = EC_KEY_get0_public_key(*ecdh);
+ const EC_POINT *point = EC_KEY_get0_public_key(ecdh);
if(!point) {
- EC_KEY_free(*ecdh);
- *ecdh = NULL;
+ EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Getting public key failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return NULL;
}
- size_t result = EC_POINT_point2oct(EC_KEY_get0_group(*ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL);
+ size_t result = EC_POINT_point2oct(EC_KEY_get0_group(ecdh), point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL);
if(!result) {
- EC_KEY_free(*ecdh);
- *ecdh = NULL;
+ EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Converting EC_POINT to binary failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return NULL;
}
- return true;
+ return ecdh;
}
bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
- EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(*ecdh));
+ EC_POINT *point = EC_POINT_new(EC_KEY_get0_group(ecdh));
if(!point) {
logger(DEBUG_ALWAYS, LOG_ERR, "EC_POINT_new() failed: %s", ERR_error_string(ERR_get_error(), NULL));
+ EC_KEY_free(ecdh);
return false;
}
- int result = EC_POINT_oct2point(EC_KEY_get0_group(*ecdh), point, pubkey, ECDH_SIZE, NULL);
+ int result = EC_POINT_oct2point(EC_KEY_get0_group(ecdh), point, pubkey, ECDH_SIZE, NULL);
if(!result) {
EC_POINT_free(point);
+ EC_KEY_free(ecdh);
logger(DEBUG_ALWAYS, LOG_ERR, "Converting binary to EC_POINT failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
- result = ECDH_compute_key(shared, ECDH_SIZE, point, *ecdh, NULL);
+ result = ECDH_compute_key(shared, ECDH_SIZE, point, ecdh, NULL);
EC_POINT_free(point);
- EC_KEY_free(*ecdh);
- *ecdh = NULL;
+ EC_KEY_free(ecdh);
if(!result) {
logger(DEBUG_ALWAYS, LOG_ERR, "Computing Elliptic Curve Diffie-Hellman shared key failed: %s", ERR_error_string(ERR_get_error(), NULL));
}
void ecdh_free(ecdh_t *ecdh) {
- if(*ecdh) {
- EC_KEY_free(*ecdh);
- *ecdh = NULL;
- }
+ if(ecdh)
+ EC_KEY_free(ecdh);
}
+++ /dev/null
-/*
- ecdh.h -- header file for ecdh.c
- Copyright (C) 2011 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_ECDH_H__
-#define __TINC_ECDH_H__
-
-#include <openssl/ecdh.h>
-
-#define ECDH_SIZE 67
-#define ECDH_SHARED_SIZE 66
-
-typedef EC_KEY *ecdh_t;
-
-extern bool ecdh_generate_public(ecdh_t *ecdh, void *pubkey);
-extern bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared);
-extern void ecdh_free(ecdh_t *ecdh);
-
-#endif
/*
ecdsa.c -- ECDSA key handling
- Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2011-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
-#include "logger.h"
-#include "ecdsa.h"
-#include "utils.h"
+#define __TINC_ECDSA_INTERNAL__
+typedef EC_KEY ecdsa_t;
+
+#include "../logger.h"
+#include "../ecdsa.h"
+#include "../utils.h"
+#include "../xalloc.h"
// Get and set ECDSA keys
//
-bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *p) {
- *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
- if(!*ecdsa) {
+ecdsa_t *ecdsa_set_base64_public_key(const char *p) {
+ ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
+ if(!ecdsa) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "EC_KEY_new_by_curve_name failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return NULL;
}
int len = strlen(p);
const unsigned char *ppubkey = pubkey;
len = b64decode(p, (char *)pubkey, len);
- if(!o2i_ECPublicKey(ecdsa, &ppubkey, len)) {
+ if(!o2i_ECPublicKey(&ecdsa, &ppubkey, len)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "o2i_ECPublicKey failed: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ EC_KEY_free(ecdsa);
+ return NULL;
}
- return true;
+ return ecdsa;
}
char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
unsigned char *pubkey = NULL;
- int len = i2o_ECPublicKey(*ecdsa, &pubkey);
+ int len = i2o_ECPublicKey(ecdsa, &pubkey);
- char *base64 = malloc(len * 4 / 3 + 5);
+ char *base64 = xmalloc(len * 4 / 3 + 5);
b64encode((char *)pubkey, base64, len);
free(pubkey);
// Read PEM ECDSA keys
-bool ecdsa_read_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
- *ecdsa = PEM_read_EC_PUBKEY(fp, ecdsa, NULL, NULL);
+ecdsa_t *ecdsa_read_pem_public_key(FILE *fp) {
+ ecdsa_t *ecdsa = PEM_read_EC_PUBKEY(fp, NULL, NULL, NULL);
- if(*ecdsa)
- return true;
+ if(!ecdsa)
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return ecdsa;
}
-bool ecdsa_read_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
- *ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
+ecdsa_t *ecdsa_read_pem_private_key(FILE *fp) {
+ ecdsa_t *ecdsa = PEM_read_ECPrivateKey(fp, NULL, NULL, NULL);
- if(*ecdsa)
- return true;
+ if(!ecdsa)
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read ECDSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return ecdsa;
}
size_t ecdsa_size(ecdsa_t *ecdsa) {
- return ECDSA_size(*ecdsa);
+ return ECDSA_size(ecdsa);
}
// TODO: standardise output format?
bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
- unsigned int siglen = ECDSA_size(*ecdsa);
+ unsigned int siglen = ECDSA_size(ecdsa);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512(in, len, hash);
memset(sig, 0, siglen);
- if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, *ecdsa)) {
+ if(!ECDSA_sign(0, hash, sizeof hash, sig, &siglen, ecdsa)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_sign() failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
}
bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
- unsigned int siglen = ECDSA_size(*ecdsa);
+ unsigned int siglen = ECDSA_size(ecdsa);
unsigned char hash[SHA512_DIGEST_LENGTH];
SHA512(in, len, hash);
- if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, *ecdsa)) {
+ if(!ECDSA_verify(0, hash, sizeof hash, sig, siglen, ecdsa)) {
logger(DEBUG_ALWAYS, LOG_DEBUG, "ECDSA_verify() failed: %s", ERR_error_string(ERR_get_error(), NULL));
return false;
}
}
bool ecdsa_active(ecdsa_t *ecdsa) {
- return *ecdsa;
+ return ecdsa;
}
void ecdsa_free(ecdsa_t *ecdsa) {
- if(*ecdsa) {
- EC_KEY_free(*ecdsa);
- *ecdsa = NULL;
- }
+ if(ecdsa)
+ EC_KEY_free(ecdsa);
}
+++ /dev/null
-/*
- ecdsa.h -- ECDSA key handling
- Copyright (C) 2011 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_ECDSA_H__
-#define __TINC_ECDSA_H__
-
-#include <openssl/ec.h>
-
-typedef EC_KEY *ecdsa_t;
-
-extern bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *p);
-extern char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa);
-extern bool ecdsa_read_pem_public_key(ecdsa_t *ecdsa, FILE *fp);
-extern bool ecdsa_read_pem_private_key(ecdsa_t *ecdsa, FILE *fp);
-extern size_t ecdsa_size(ecdsa_t *ecdsa);
-extern bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t inlen, void *out);
-extern bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t inlen, const void *out);
-extern bool ecdsa_active(ecdsa_t *ecdsa);
-extern void ecdsa_free(ecdsa_t *ecdsa);
-
-#endif
/*
ecdsagen.c -- ECDSA key generation and export
- Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2011-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/obj_mac.h>
-#include "ecdsagen.h"
-#include "utils.h"
+#define __TINC_ECDSA_INTERNAL__
+typedef EC_KEY ecdsa_t;
+
+#include "../ecdsagen.h"
+#include "../utils.h"
+#include "../xalloc.h"
// Generate ECDSA key
-bool ecdsa_generate(ecdsa_t *ecdsa) {
- *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
+ecdsa_t *ecdsa_generate(void) {
+ ecdsa_t *ecdsa = EC_KEY_new_by_curve_name(NID_secp521r1);
- if(!EC_KEY_generate_key(*ecdsa)) {
+ if(!ecdsa || !EC_KEY_generate_key(ecdsa)) {
fprintf(stderr, "Generating EC key failed: %s", ERR_error_string(ERR_get_error(), NULL));
+ ecdsa_free(ecdsa);
return false;
}
- EC_KEY_set_asn1_flag(*ecdsa, OPENSSL_EC_NAMED_CURVE);
- EC_KEY_set_conv_form(*ecdsa, POINT_CONVERSION_COMPRESSED);
+ EC_KEY_set_asn1_flag(ecdsa, OPENSSL_EC_NAMED_CURVE);
+ EC_KEY_set_conv_form(ecdsa, POINT_CONVERSION_COMPRESSED);
- return true;
+ return ecdsa;
}
// Write PEM ECDSA keys
bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp) {
BIO *out = BIO_new(BIO_s_file());
- BIO_set_fp(out,fp,BIO_NOCLOSE);
- PEM_write_bio_EC_PUBKEY(out, *ecdsa);
+ BIO_set_fp(out, fp, BIO_NOCLOSE);
+ PEM_write_bio_EC_PUBKEY(out, ecdsa);
BIO_free(out);
return true;
}
bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp) {
BIO *out = BIO_new(BIO_s_file());
- BIO_set_fp(out,fp,BIO_NOCLOSE);
- PEM_write_bio_ECPrivateKey(out, *ecdsa, NULL, NULL, 0, NULL, NULL);
+ BIO_set_fp(out, fp, BIO_NOCLOSE);
+ PEM_write_bio_ECPrivateKey(out, ecdsa, NULL, NULL, 0, NULL, NULL);
BIO_free(out);
return true;
}
-
-// Convert ECDSA public key to base64 format
-
-char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
- unsigned char *pubkey = NULL;
- int len = i2o_ECPublicKey(*ecdsa, &pubkey);
-
- char *base64 = malloc(len * 4 / 3 + 5);
- b64encode((char *)pubkey, base64, len);
-
- free(pubkey);
-
- return base64;
-}
+++ /dev/null
-/*
- ecdsagen.h -- ECDSA key generation and export
- Copyright (C) 2011 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_ECDSAGEN_H__
-#define __TINC_ECDSAGEN_H__
-
-#include "ecdsa.h"
-
-extern bool ecdsa_generate(ecdsa_t *ecdsa);
-extern bool ecdsa_write_pem_public_key(ecdsa_t *ecdsa, FILE *fp);
-extern bool ecdsa_write_pem_private_key(ecdsa_t *ecdsa, FILE *fp);
-extern char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa);
-
-#endif
/*
prf.c -- Pseudo-Random Function for key material generation
- Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2011-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <openssl/obj_mac.h>
#include "digest.h"
-#include "prf.h"
+#include "../digest.h"
+#include "../prf.h"
/* Generate key material from a master secret and a seed, based on RFC 4346 section 5.
We use SHA512 instead of MD5 and SHA1.
*/
static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, ssize_t outlen) {
- digest_t digest;
+ digest_t *digest = digest_open_by_nid(nid, -1);
- if(!digest_open_by_nid(&digest, nid, -1))
+ if(!digest)
return false;
- if(!digest_set_key(&digest, secret, secretlen))
+ if(!digest_set_key(digest, secret, secretlen)) {
+ digest_close(digest);
return false;
+ }
- size_t len = digest_length(&digest);
+ size_t len = digest_length(digest);
/* Data is what the "inner" HMAC function processes.
It consists of the previous HMAC result plus the seed.
while(outlen > 0) {
/* Inner HMAC */
- digest_create(&digest, data, len + seedlen, data);
+ digest_create(digest, data, len + seedlen, data);
/* Outer HMAC */
- digest_create(&digest, data, len + seedlen, hash);
+ digest_create(digest, data, len + seedlen, hash);
/* XOR the results of the outer HMAC into the out buffer */
for(int i = 0; i < len && i < outlen; i++)
outlen -= len;
}
- digest_close(&digest);
+ digest_close(digest);
return true;
}
+++ /dev/null
-/*
- prf.h -- header file for prf.c
- Copyright (C) 2011 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_PRF_H__
-#define __TINC_PRF_H__
-
-extern bool prf(const char *secret, size_t secretlen, char *seed, size_t seedlen, char *out, size_t outlen);
-
-#endif
/*
rsa.c -- RSA key handling
- Copyright (C) 2007-2012 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2007-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
-#include "logger.h"
-#include "rsa.h"
+#define __TINC_RSA_INTERNAL__
+typedef RSA rsa_t;
+
+#include "../logger.h"
+#include "../rsa.h"
// Set RSA keys
-bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e) {
- *rsa = RSA_new();
- if(BN_hex2bn(&(*rsa)->n, n) != strlen(n))
- return false;
- if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
+rsa_t *rsa_set_hex_public_key(char *n, char *e) {
+ rsa_t *rsa = RSA_new();
+ if(!rsa)
+ return NULL;
+
+ if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e)) {
+ RSA_free(rsa);
return false;
- return true;
+ }
+
+ return rsa;
}
-bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d) {
- *rsa = RSA_new();
- if(BN_hex2bn(&(*rsa)->n, n) != strlen(n))
- return false;
- if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
- return false;
- if(BN_hex2bn(&(*rsa)->d, d) != strlen(d))
+rsa_t *rsa_set_hex_private_key(char *n, char *e, char *d) {
+ rsa_t *rsa = RSA_new();
+ if(!rsa)
+ return NULL;
+
+ if(BN_hex2bn(&rsa->n, n) != strlen(n) || BN_hex2bn(&rsa->e, e) != strlen(e) || BN_hex2bn(&rsa->d, d) != strlen(d)) {
+ RSA_free(rsa);
return false;
- return true;
+ }
+
+ return rsa;
}
// Read PEM RSA keys
-bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp) {
- *rsa = PEM_read_RSAPublicKey(fp, rsa, NULL, NULL);
-
- if(*rsa)
- return true;
+rsa_t *rsa_read_pem_public_key(FILE *fp) {
+ rsa_t *rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
- *rsa = PEM_read_RSA_PUBKEY(fp, rsa, NULL, NULL);
+ if(!rsa)
+ rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
- if(*rsa)
- return true;
+ if(!rsa)
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return rsa;
}
-bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp) {
- *rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
+rsa_t *rsa_read_pem_private_key(FILE *fp) {
+ rsa_t *rsa = PEM_read_RSAPrivateKey(fp, NULL, NULL, NULL);
- if(*rsa)
- return true;
+ if(!rsa)
+ logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
- logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA private key: %s", ERR_error_string(ERR_get_error(), NULL));
- return false;
+ return rsa;
}
size_t rsa_size(rsa_t *rsa) {
- return RSA_size(*rsa);
+ return RSA_size(rsa);
}
bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) {
- if(RSA_public_encrypt(len, in, out, *rsa, RSA_NO_PADDING) == len)
+ if(RSA_public_encrypt(len, in, out, rsa, RSA_NO_PADDING) == len)
return true;
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA encryption: %s", ERR_error_string(ERR_get_error(), NULL));
}
bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) {
- if(RSA_private_decrypt(len, in, out, *rsa, RSA_NO_PADDING) == len)
+ if(RSA_private_decrypt(len, in, out, rsa, RSA_NO_PADDING) == len)
return true;
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to perform RSA decryption: %s", ERR_error_string(ERR_get_error(), NULL));
}
bool rsa_active(rsa_t *rsa) {
- return *rsa;
+ return rsa;
}
void rsa_free(rsa_t *rsa) {
- if(*rsa) {
- RSA_free(*rsa);
- *rsa = NULL;
- }
+ if(rsa)
+ RSA_free(rsa);
}
+++ /dev/null
-/*
- rsa.h -- RSA key handling
- Copyright (C) 2007-2011 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_RSA_H__
-#define __TINC_RSA_H__
-
-#include <openssl/rsa.h>
-
-typedef RSA *rsa_t;
-
-extern bool rsa_set_hex_public_key(rsa_t *rsa, char *n, char *e);
-extern bool rsa_set_hex_private_key(rsa_t *rsa, char *n, char *e, char *d);
-extern bool rsa_read_pem_public_key(rsa_t *rsa, FILE *fp);
-extern bool rsa_read_pem_private_key(rsa_t *rsa, FILE *fp);
-extern size_t rsa_size(rsa_t *rsa);
-extern bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t inlen, void *out);
-extern bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t inlen, void *out);
-extern bool rsa_active(rsa_t *rsa);
-extern void rsa_free(rsa_t *rsa);
-
-
-#endif
/*
rsagen.c -- RSA key generation and export
- Copyright (C) 2008 Guus Sliepen <guus@tinc-vpn.org>
+ Copyright (C) 2008-2013 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
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#include "system.h"
+#include "../system.h"
#include <openssl/pem.h>
#include <openssl/err.h>
-#include "logger.h"
-#include "rsagen.h"
+#define __TINC_RSA_INTERNAL__
+typedef RSA rsa_t;
+
+#include "../logger.h"
+#include "../rsagen.h"
/* This function prettyprints the key generation process */
// Generate RSA key
-bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent) {
- *rsa = RSA_generate_key(bits, exponent, indicator, NULL);
-
- return *rsa;
+rsa_t *rsa_generate(size_t bits, unsigned long exponent) {
+ return RSA_generate_key(bits, exponent, indicator, NULL);
}
// Write PEM RSA keys
bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp) {
- PEM_write_RSAPublicKey(fp, *rsa);
-
- return true;
+ return PEM_write_RSAPublicKey(fp, rsa);
}
bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp) {
- PEM_write_RSAPrivateKey(fp, *rsa, NULL, NULL, 0, NULL, NULL);
- return true;
+ return PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL);
}
+++ /dev/null
-/*
- rsagen.h -- RSA key generation and export
- Copyright (C) 2008 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
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-
-#ifndef __TINC_RSAGEN_H__
-#define __TINC_RSAGEN_H__
-
-#include "rsa.h"
-
-extern bool rsa_generate(rsa_t *rsa, size_t bits, unsigned long exponent);
-extern bool rsa_write_pem_public_key(rsa_t *rsa, FILE *fp);
-extern bool rsa_write_pem_private_key(rsa_t *rsa, FILE *fp);
-
-#endif
/*
protocol_auth.c -- handle the meta-protocol, authentication
Copyright (C) 1999-2005 Ivo Timmermans,
- 2000-2012 Guus Sliepen <guus@tinc-vpn.org>
+ 2000-2013 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
return false;
}
} else {
- if(c->protocol_minor && !ecdsa_active(&c->ecdsa))
+ if(c->protocol_minor && !ecdsa_active(c->ecdsa))
c->protocol_minor = 1;
}
if(!read_rsa_public_key(c))
return false;
- if(!cipher_open_blowfish_ofb(&c->outcipher))
+ if(!(c->outcipher = cipher_open_blowfish_ofb()))
return false;
- if(!digest_open_sha1(&c->outdigest, -1))
+ if(!(c->outdigest = digest_open_sha1(-1)))
return false;
- size_t len = rsa_size(&c->rsa);
+ size_t len = rsa_size(c->rsa);
char key[len];
char enckey[len];
char hexkey[2 * len + 1];
key[0] &= 0x7F;
- cipher_set_key_from_rsa(&c->outcipher, key, len, true);
+ cipher_set_key_from_rsa(c->outcipher, key, len, true);
if(debug_level >= DEBUG_SCARY_THINGS) {
bin2hex(key, hexkey, len);
with a length equal to that of the modulus of the RSA key.
*/
- if(!rsa_public_encrypt(&c->rsa, key, len, enckey)) {
+ if(!rsa_public_encrypt(c->rsa, key, len, enckey)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error during encryption of meta key for %s (%s)", c->name, c->hostname);
return false;
}
/* Send the meta key */
bool result = send_request(c, "%d %d %d %d %d %s", METAKEY,
- cipher_get_nid(&c->outcipher),
- digest_get_nid(&c->outdigest), c->outmaclength,
+ cipher_get_nid(c->outcipher),
+ digest_get_nid(c->outdigest), c->outmaclength,
c->outcompression, hexkey);
c->status.encryptout = true;
bool metakey_h(connection_t *c, const char *request) {
char hexkey[MAX_STRING_SIZE];
int cipher, digest, maclength, compression;
- size_t len = rsa_size(&myself->connection->rsa);
+ size_t len = rsa_size(myself->connection->rsa);
char enckey[len];
char key[len];
/* Decrypt the meta key */
- if(!rsa_private_decrypt(&myself->connection->rsa, enckey, len, key)) {
+ if(!rsa_private_decrypt(myself->connection->rsa, enckey, len, key)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error during decryption of meta key for %s (%s)", c->name, c->hostname);
return false;
}
/* Check and lookup cipher and digest algorithms */
- if(!cipher_open_by_nid(&c->incipher, cipher) || !cipher_set_key_from_rsa(&c->incipher, key, len, false)) {
+ if(!(c->incipher = cipher_open_by_nid(cipher)) || !cipher_set_key_from_rsa(c->incipher, key, len, false)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of cipher from %s (%s)", c->name, c->hostname);
return false;
}
- if(!digest_open_by_nid(&c->indigest, digest, -1)) {
+ if(!(c->indigest = digest_open_by_nid(digest, -1))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Error during initialisation of digest from %s (%s)", c->name, c->hostname);
return false;
}
}
bool send_challenge(connection_t *c) {
- size_t len = rsa_size(&c->rsa);
+ size_t len = rsa_size(c->rsa);
char buffer[len * 2 + 1];
if(!c->hischallenge)
bool challenge_h(connection_t *c, const char *request) {
char buffer[MAX_STRING_SIZE];
- size_t len = rsa_size(&myself->connection->rsa);
- size_t digestlen = digest_length(&c->indigest);
+ size_t len = rsa_size(myself->connection->rsa);
+ size_t digestlen = digest_length(c->indigest);
char digest[digestlen];
if(sscanf(request, "%*d " MAX_STRING, buffer) != 1) {
/* Calculate the hash from the challenge we received */
- digest_create(&c->indigest, buffer, len, digest);
+ digest_create(c->indigest, buffer, len, digest);
/* Convert the hash to a hexadecimal formatted string */
/* Check if the length of the hash is all right */
- if(inlen != digest_length(&c->outdigest)) {
+ if(inlen != digest_length(c->outdigest)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply length");
return false;
}
/* Verify the hash */
- if(!digest_verify(&c->outdigest, c->hischallenge, rsa_size(&c->rsa), hishash)) {
+ if(!digest_verify(c->outdigest, c->hischallenge, rsa_size(c->rsa), hishash)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Possible intruder %s (%s): %s", c->name, c->hostname, "wrong challenge reply");
return false;
}
/* Special case when protocol_minor is 1: the other end is ECDSA capable,
* but doesn't know our key yet. So send it now. */
- char *pubkey = ecdsa_get_base64_public_key(&myself->connection->ecdsa);
+ char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
if(!pubkey)
return false;
return false;
}
- if(ecdsa_active(&c->ecdsa) || read_ecdsa_public_key(c)) {
+ if(ecdsa_active(c->ecdsa) || read_ecdsa_public_key(c)) {
logger(DEBUG_ALWAYS, LOG_INFO, "Already have ECDSA public key from %s (%s), not upgrading.", c->name, c->hostname);
return false;
}
static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, int reqno) {
switch(reqno) {
case REQ_PUBKEY: {
- char *pubkey = ecdsa_get_base64_public_key(&myself->connection->ecdsa);
+ char *pubkey = ecdsa_get_base64_public_key(myself->connection->ecdsa);
send_request(from->nexthop->connection, "%d %s %s %d %s", REQ_KEY, myself->name, from->name, ANS_PUBKEY, pubkey);
free(pubkey);
return true;
}
char pubkey[MAX_STRING_SIZE];
- if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !ecdsa_set_base64_public_key(&from->ecdsa, pubkey)) {
+ if(sscanf(request, "%*d %*s %*s %*d " MAX_STRING, pubkey) != 1 || !(from->ecdsa = ecdsa_set_base64_public_key(pubkey))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Got bad %s from %s (%s): %s", "ANS_PUBKEY", from->name, from->hostname, "invalid pubkey");
return true;
}
if(to->status.sptps)
abort();
- size_t keylen = cipher_keylength(&myself->incipher);
+ size_t keylen = cipher_keylength(myself->incipher);
char key[keylen * 2 + 1];
- cipher_close(&to->incipher);
- digest_close(&to->indigest);
+ cipher_close(to->incipher);
+ digest_close(to->indigest);
- cipher_open_by_nid(&to->incipher, cipher_get_nid(&myself->incipher));
- digest_open_by_nid(&to->indigest, digest_get_nid(&myself->indigest), digest_length(&myself->indigest));
+ to->incipher = cipher_open_by_nid(cipher_get_nid(myself->incipher));
+ to->indigest = digest_open_by_nid(digest_get_nid(myself->indigest), digest_length(myself->indigest));
to->incompression = myself->incompression;
+ if(!to->incipher || !to->indigest)
+ abort();
+
randomize(key, keylen);
- cipher_set_key(&to->incipher, key, false);
- digest_set_key(&to->indigest, key, keylen);
+ cipher_set_key(to->incipher, key, false);
+ digest_set_key(to->indigest, key, keylen);
bin2hex(key, key, keylen);
return send_request(to->nexthop->connection, "%d %s %s %s %d %d %d %d", ANS_KEY,
myself->name, to->name, key,
- cipher_get_nid(&to->incipher),
- digest_get_nid(&to->indigest),
- (int)digest_length(&to->indigest),
+ cipher_get_nid(to->incipher),
+ digest_get_nid(to->indigest),
+ (int)digest_length(to->indigest),
to->incompression);
}
}
/* Don't use key material until every check has passed. */
- cipher_close(&from->outcipher);
- digest_close(&from->outdigest);
+ cipher_close(from->outcipher);
+ digest_close(from->outdigest);
from->status.validkey = false;
if(compression < 0 || compression > 11) {
/* Check and lookup cipher and digest algorithms */
- if(!cipher_open_by_nid(&from->outcipher, cipher)) {
+ if(!(from->outcipher = cipher_open_by_nid(cipher))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown cipher!", from->name, from->hostname);
return false;
}
- if(!digest_open_by_nid(&from->outdigest, digest, maclength)) {
+ if(!(from->outdigest = digest_open_by_nid(digest, maclength))) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses unknown digest!", from->name, from->hostname);
return false;
}
- if(maclength != digest_length(&from->outdigest)) {
+ if(maclength != digest_length(from->outdigest)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses bogus MAC length!", from->name, from->hostname);
return false;
}
keylen = hex2bin(key, key, sizeof key);
- if(keylen != cipher_keylength(&from->outcipher)) {
+ if(keylen != cipher_keylength(from->outcipher)) {
logger(DEBUG_ALWAYS, LOG_ERR, "Node %s (%s) uses wrong keylength!", from->name, from->hostname);
return true;
}
/* Update our copy of the origin's packet key */
- cipher_set_key(&from->outcipher, key, true);
- digest_set_key(&from->outdigest, key, keylen);
+ cipher_set_key(from->outcipher, key, true);
+ digest_set_key(from->outdigest, key, keylen);
from->status.validkey = true;
from->sent_seqno = 0;
if(s->outstate) {
// If first handshake has finished, encrypt and HMAC
- cipher_set_counter(&s->outcipher, &seqno, sizeof seqno);
- if(!cipher_counter_xor(&s->outcipher, buffer + 6, len + 1UL, buffer + 6))
+ cipher_set_counter(s->outcipher, &seqno, sizeof seqno);
+ if(!cipher_counter_xor(s->outcipher, buffer + 6, len + 1UL, buffer + 6))
return false;
- if(!digest_create(&s->outdigest, buffer, len + 7UL, buffer + 7UL + len))
+ if(!digest_create(s->outdigest, buffer, len + 7UL, buffer + 7UL + len))
return false;
return s->send_data(s->handle, type, buffer + 2, len + 21UL);
if(s->outstate) {
// If first handshake has finished, encrypt and HMAC
- if(!cipher_counter_xor(&s->outcipher, buffer + 4, len + 3UL, buffer + 4))
+ if(!cipher_counter_xor(s->outcipher, buffer + 4, len + 3UL, buffer + 4))
return false;
- if(!digest_create(&s->outdigest, buffer, len + 7UL, buffer + 7UL + len))
+ if(!digest_create(s->outdigest, buffer, len + 7UL, buffer + 7UL + len))
return false;
return s->send_data(s->handle, type, buffer + 4, len + 19UL);
randomize(s->mykex + 1, 32);
// Create a new ECDH public key.
- if(!ecdh_generate_public(&s->ecdh, s->mykex + 1 + 32))
+ if(!(s->ecdh = ecdh_generate_public(s->mykex + 1 + 32)))
return false;
return send_record_priv(s, SPTPS_HANDSHAKE, s->mykex, 1 + 32 + keylen);
// Send a SIGnature record, containing an ECDSA signature over both KEX records.
static bool send_sig(sptps_t *s) {
size_t keylen = ECDH_SIZE;
- size_t siglen = ecdsa_size(&s->mykey);
+ size_t siglen = ecdsa_size(s->mykey);
// Concatenate both KEX messages, plus tag indicating if it is from the connection originator, plus label
char msg[(1 + 32 + keylen) * 2 + 1 + s->labellen];
memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
// Sign the result.
- if(!ecdsa_sign(&s->mykey, msg, sizeof msg, sig))
+ if(!ecdsa_sign(s->mykey, msg, sizeof msg, sig))
return false;
// Send the SIG exchange record.
static bool generate_key_material(sptps_t *s, const char *shared, size_t len) {
// Initialise cipher and digest structures if necessary
if(!s->outstate) {
- bool result
- = cipher_open_by_name(&s->incipher, "aes-256-ecb")
- && cipher_open_by_name(&s->outcipher, "aes-256-ecb")
- && digest_open_by_name(&s->indigest, "sha256", 16)
- && digest_open_by_name(&s->outdigest, "sha256", 16);
- if(!result)
+ s->incipher = cipher_open_by_name("aes-256-ecb");
+ s->outcipher = cipher_open_by_name("aes-256-ecb");
+ s->indigest = digest_open_by_name("sha256", 16);
+ s->outdigest = digest_open_by_name("sha256", 16);
+ if(!s->incipher || !s->outcipher || !s->indigest || !s->outdigest)
return false;
}
// Allocate memory for key material
- size_t keylen = digest_keylength(&s->indigest) + digest_keylength(&s->outdigest) + cipher_keylength(&s->incipher) + cipher_keylength(&s->outcipher);
+ size_t keylen = digest_keylength(s->indigest) + digest_keylength(s->outdigest) + cipher_keylength(s->incipher) + cipher_keylength(s->outcipher);
s->key = realloc(s->key, keylen);
if(!s->key)
if(s->initiator) {
bool result
- = cipher_set_counter_key(&s->incipher, s->key)
- && digest_set_key(&s->indigest, s->key + cipher_keylength(&s->incipher), digest_keylength(&s->indigest));
+ = cipher_set_counter_key(s->incipher, s->key)
+ && digest_set_key(s->indigest, s->key + cipher_keylength(s->incipher), digest_keylength(s->indigest));
if(!result)
return false;
} else {
bool result
- = cipher_set_counter_key(&s->incipher, s->key + cipher_keylength(&s->outcipher) + digest_keylength(&s->outdigest))
- && digest_set_key(&s->indigest, s->key + cipher_keylength(&s->outcipher) + digest_keylength(&s->outdigest) + cipher_keylength(&s->incipher), digest_keylength(&s->indigest));
+ = cipher_set_counter_key(s->incipher, s->key + cipher_keylength(s->outcipher) + digest_keylength(s->outdigest))
+ && digest_set_key(s->indigest, s->key + cipher_keylength(s->outcipher) + digest_keylength(s->outdigest) + cipher_keylength(s->incipher), digest_keylength(s->indigest));
if(!result)
return false;
}
// Receive a SIGnature record, verify it, if it passed, compute the shared secret and calculate the session keys.
static bool receive_sig(sptps_t *s, const char *data, uint16_t len) {
size_t keylen = ECDH_SIZE;
- size_t siglen = ecdsa_size(&s->hiskey);
+ size_t siglen = ecdsa_size(s->hiskey);
// Verify length of KEX record.
if(len != siglen)
memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen);
// Verify signature.
- if(!ecdsa_verify(&s->hiskey, msg, sizeof msg, data))
+ if(!ecdsa_verify(s->hiskey, msg, sizeof msg, data))
return false;
// Compute shared secret.
char shared[ECDH_SHARED_SIZE];
- if(!ecdh_compute_shared(&s->ecdh, s->hiskex + 1 + 32, shared))
+ if(!ecdh_compute_shared(s->ecdh, s->hiskex + 1 + 32, shared))
return false;
// Generate key material from shared secret.
// TODO: only set new keys after ACK has been set/received
if(s->initiator) {
bool result
- = cipher_set_counter_key(&s->outcipher, s->key + cipher_keylength(&s->incipher) + digest_keylength(&s->indigest))
- && digest_set_key(&s->outdigest, s->key + cipher_keylength(&s->incipher) + digest_keylength(&s->indigest) + cipher_keylength(&s->outcipher), digest_keylength(&s->outdigest));
+ = cipher_set_counter_key(s->outcipher, s->key + cipher_keylength(s->incipher) + digest_keylength(s->indigest))
+ && digest_set_key(s->outdigest, s->key + cipher_keylength(s->incipher) + digest_keylength(s->indigest) + cipher_keylength(s->outcipher), digest_keylength(s->outdigest));
if(!result)
return false;
} else {
bool result
- = cipher_set_counter_key(&s->outcipher, s->key)
- && digest_set_key(&s->outdigest, s->key + cipher_keylength(&s->outcipher), digest_keylength(&s->outdigest));
+ = cipher_set_counter_key(s->outcipher, s->key)
+ && digest_set_key(s->outdigest, s->key + cipher_keylength(s->outcipher), digest_keylength(s->outdigest));
if(!result)
return false;
}
memcpy(buffer, &netlen, 2);
memcpy(buffer + 2, data, len);
- return digest_verify(&s->indigest, buffer, len - 14, buffer + len - 14);
+ return digest_verify(s->indigest, buffer, len - 14, buffer + len - 14);
}
// Receive incoming data, datagram version.
memcpy(buffer, &netlen, 2);
memcpy(buffer + 2, data, len);
- if(!digest_verify(&s->indigest, buffer, len - 14, buffer + len - 14))
+ if(!digest_verify(s->indigest, buffer, len - 14, buffer + len - 14))
return error(s, EIO, "Invalid HMAC");
// Replay protection using a sliding window of configurable size.
// Decrypt.
memcpy(&seqno, buffer + 2, 4);
- cipher_set_counter(&s->incipher, &seqno, sizeof seqno);
- if(!cipher_counter_xor(&s->incipher, buffer + 6, len - 4, buffer + 6))
+ cipher_set_counter(s->incipher, &seqno, sizeof seqno);
+ if(!cipher_counter_xor(s->incipher, buffer + 6, len - 4, buffer + 6))
return false;
// Append a NULL byte for safety.
// Decrypt the length bytes
if(s->instate) {
- if(!cipher_counter_xor(&s->incipher, s->inbuf + 4, 2, &s->reclen))
+ if(!cipher_counter_xor(s->incipher, s->inbuf + 4, 2, &s->reclen))
return false;
} else {
memcpy(&s->reclen, s->inbuf + 4, 2);
// Check HMAC and decrypt.
if(s->instate) {
- if(!digest_verify(&s->indigest, s->inbuf, s->reclen + 7UL, s->inbuf + s->reclen + 7UL))
+ if(!digest_verify(s->indigest, s->inbuf, s->reclen + 7UL, s->inbuf + s->reclen + 7UL))
return error(s, EIO, "Invalid HMAC");
- if(!cipher_counter_xor(&s->incipher, s->inbuf + 6UL, s->reclen + 1UL, s->inbuf + 6UL))
+ if(!cipher_counter_xor(s->incipher, s->inbuf + 6UL, s->reclen + 1UL, s->inbuf + 6UL))
return false;
}
}
// Start a SPTPS session.
-bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t mykey, ecdsa_t hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) {
+bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record) {
// Initialise struct sptps
memset(s, 0, sizeof *s);
// Stop a SPTPS session.
bool sptps_stop(sptps_t *s) {
// Clean up any resources.
- cipher_close(&s->incipher);
- cipher_close(&s->outcipher);
- digest_close(&s->indigest);
- digest_close(&s->outdigest);
- ecdh_free(&s->ecdh);
+ cipher_close(s->incipher);
+ cipher_close(s->outcipher);
+ digest_close(s->indigest);
+ digest_close(s->outdigest);
+ ecdh_free(s->ecdh);
free(s->inbuf);
free(s->mykex);
free(s->hiskex);
uint16_t reclen;
bool instate;
- cipher_t incipher;
- digest_t indigest;
+ cipher_t *incipher;
+ digest_t *indigest;
uint32_t inseqno;
uint32_t received;
unsigned int replaywin;
char *late;
bool outstate;
- cipher_t outcipher;
- digest_t outdigest;
+ cipher_t *outcipher;
+ digest_t *outdigest;
uint32_t outseqno;
- ecdsa_t mykey;
- ecdsa_t hiskey;
- ecdh_t ecdh;
+ ecdsa_t *mykey;
+ ecdsa_t *hiskey;
+ ecdh_t *ecdh;
char *mykex;
char *hiskex;
extern void sptps_log_quiet(sptps_t *s, int s_errno, const char *format, va_list ap);
extern void sptps_log_stderr(sptps_t *s, int s_errno, const char *format, va_list ap);
extern void (*sptps_log)(sptps_t *s, int s_errno, const char *format, va_list ap);
-extern bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t mykey, ecdsa_t hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record);
+extern bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_t *mykey, ecdsa_t *hiskey, const char *label, size_t labellen, send_data_t send_data, receive_record_t receive_record);
extern bool sptps_stop(sptps_t *s);
extern bool sptps_send_record(sptps_t *s, uint8_t type, const char *data, uint16_t len);
extern bool sptps_receive_data(sptps_t *s, const char *data, size_t len);
/*
sptps_test.c -- Simple Peer-to-Peer Security test program
- Copyright (C) 2011-2012 Guus Sliepen <guus@tinc-vpn.org>,
+ Copyright (C) 2011-2013 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
char *logfilename = NULL;
struct timeval now;
-ecdsa_t mykey, hiskey;
+ecdsa_t *mykey, *hiskey;
static bool send_data(void *handle, uint8_t type, const char *data, size_t len) {
char hex[len * 2 + 1];
crypto_init();
FILE *fp = fopen(argv[1], "r");
- if(!ecdsa_read_pem_private_key(&mykey, fp))
+ if(!(mykey = ecdsa_read_pem_private_key(fp)))
return 1;
fclose(fp);
fp = fopen(argv[2], "r");
- if(!ecdsa_read_pem_public_key(&hiskey, fp))
+ if(!(hiskey = ecdsa_read_pem_public_key(fp)))
return 1;
fclose(fp);
them in.
*/
static bool ecdsa_keygen(bool ask) {
- ecdsa_t key;
+ ecdsa_t *key;
FILE *f;
char *pubname, *privname;
fprintf(stderr, "Generating ECDSA keypair:\n");
- if(!ecdsa_generate(&key)) {
+ if(!(key = ecdsa_generate())) {
fprintf(stderr, "Error during key generation!\n");
return false;
} else
fchmod(fileno(f), 0600);
#endif
- ecdsa_write_pem_private_key(&key, f);
+ if(!ecdsa_write_pem_private_key(key, f)) {
+ fprintf(stderr, "Error writing private key!\n");
+ ecdsa_free(key);
+ fclose(f);
+ return false;
+ }
fclose(f);
if(!f)
return false;
- char *pubkey = ecdsa_get_base64_public_key(&key);
+ char *pubkey = ecdsa_get_base64_public_key(key);
fprintf(f, "ECDSAPublicKey = %s\n", pubkey);
free(pubkey);
fclose(f);
+ ecdsa_free(key);
return true;
}
them in.
*/
static bool rsa_keygen(int bits, bool ask) {
- rsa_t key;
+ rsa_t *key;
FILE *f;
char *pubname, *privname;
fprintf(stderr, "Generating %d bits keys:\n", bits);
- if(!rsa_generate(&key, bits, 0x10001)) {
+ if(!(key = rsa_generate(bits, 0x10001))) {
fprintf(stderr, "Error during key generation!\n");
return false;
} else
fchmod(fileno(f), 0600);
#endif
- rsa_write_pem_private_key(&key, f);
+ if(!rsa_write_pem_private_key(key, f)) {
+ fprintf(stderr, "Error writing private key!\n");
+ fclose(f);
+ rsa_free(key);
+ return false;
+ }
fclose(f);
if(!f)
return false;
- rsa_write_pem_public_key(&key, f);
+ if(!rsa_write_pem_public_key(key, f)) {
+ fprintf(stderr, "Error writing public key!\n");
+ fclose(f);
+ rsa_free(key);
+ return false;
+ }
fclose(f);
+ rsa_free(key);
return true;
}