Use conditional compilation for cryptographic functions.
This gets rid of the rest of the symbolic links. However, as a consequence, the crypto header files have now moved to src/, and can no longer contain library-specific declarations. Therefore, cipher_t, digest_t, ecdh_t, ecdsa_t and rsa_t are now all opaque types, and only pointers to those types can be used.
This commit is contained in:
parent
e70b5b5bd7
commit
9b9230a0a7
35 changed files with 595 additions and 639 deletions
|
@ -6,7 +6,7 @@ SUBDIRS = m4 src doc gui
|
|||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
|
||||
EXTRA_DIST = have.h system.h COPYING.README README.android
|
||||
EXTRA_DIST = COPYING.README README.android
|
||||
|
||||
ChangeLog:
|
||||
git log > ChangeLog
|
||||
|
|
|
@ -192,13 +192,15 @@ tinc_ZLIB
|
|||
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,
|
||||
|
|
|
@ -11,6 +11,13 @@ tincd_SOURCES = \
|
|||
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
|
||||
|
@ -19,6 +26,9 @@ endif
|
|||
|
||||
if BSD
|
||||
tincd_SOURCES += bsd/device.c
|
||||
if TUNEMU
|
||||
tincd_SOURCES += bsd/tunemu.c
|
||||
endif
|
||||
endif
|
||||
|
||||
if SOLARIS
|
||||
|
@ -41,22 +51,50 @@ if VDE
|
|||
tincd_SOURCES += vde_device.c
|
||||
endif
|
||||
|
||||
nodist_tincd_SOURCES = \
|
||||
cipher.c crypto.c ecdh.c ecdsa.c digest.c prf.c rsa.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
|
||||
|
||||
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 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)
|
||||
|
@ -68,10 +106,7 @@ INCLUDES = @INCLUDES@
|
|||
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@
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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>
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
|||
#include "control_common.h"
|
||||
#include "list.h"
|
||||
#include "logger.h"
|
||||
#include "rsa.h"
|
||||
#include "subnet.h"
|
||||
#include "utils.h"
|
||||
#include "xalloc.h"
|
||||
|
@ -54,14 +55,14 @@ void free_connection(connection_t *c) {
|
|||
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);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -73,12 +73,12 @@ typedef struct connection_t {
|
|||
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;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
ecdh.h -- header file for ecdh.c
|
||||
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
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
|
||||
|
@ -17,18 +17,21 @@
|
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TINC_ECDH_H__
|
||||
#define __TINC_ECDH_H__
|
||||
#include "../system.h"
|
||||
|
||||
#include <openssl/ecdh.h>
|
||||
#include "../ecdh.h"
|
||||
#include "../logger.h"
|
||||
#include "../utils.h"
|
||||
#include "../xalloc.h"
|
||||
|
||||
#define ECDH_SIZE 67
|
||||
#define ECDH_SHARED_SIZE 66
|
||||
ecdh_t *ecdh_generate_public(void *pubkey) {
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "EC support using libgcrypt not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef EC_KEY *ecdh_t;
|
||||
bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
|
||||
return false
|
||||
}
|
||||
|
||||
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
|
||||
void ecdh_free(ecdh_t *ecdh) {
|
||||
}
|
67
src/gcrypt/ecdsa.c
Normal file
67
src/gcrypt/ecdsa.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
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) {
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
ecdsagen.h -- ECDSA key generation and export
|
||||
Copyright (C) 2011 Guus Sliepen <guus@tinc-vpn.org>
|
||||
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
|
||||
|
@ -17,14 +17,25 @@
|
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TINC_ECDSAGEN_H__
|
||||
#define __TINC_ECDSAGEN_H__
|
||||
#include "../system.h"
|
||||
|
||||
#include "ecdsa.h"
|
||||
#include "../ecdsagen.h"
|
||||
#include "../utils.h"
|
||||
#include "../xalloc.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);
|
||||
// Generate ECDSA key
|
||||
|
||||
#endif
|
||||
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;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
crypto.h -- header for crypto.c
|
||||
Copyright (C) 2007 Guus Sliepen <guus@tinc-vpn.org>
|
||||
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
|
||||
|
@ -17,11 +17,13 @@
|
|||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef __TINC_CRYPTO_H__
|
||||
#define __TINC_CRYPTO_H__
|
||||
#include "../system.h"
|
||||
|
||||
extern void crypto_init();
|
||||
extern void crypto_exit();
|
||||
extern void randomize(void *, size_t);
|
||||
#include "digest.h"
|
||||
#include "../digest.h"
|
||||
#include "../prf.h"
|
||||
|
||||
#endif
|
||||
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;
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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>
|
||||
|
||||
|
@ -60,7 +60,7 @@ bool send_meta(connection_t *c, const char *buffer, int length) {
|
|||
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;
|
||||
|
@ -171,7 +171,7 @@ bool receive_meta(connection_t *c) {
|
|||
} 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;
|
||||
|
|
|
@ -318,10 +318,10 @@ static bool try_mac(node_t *n, const vpn_packet_t *inpkt) {
|
|||
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) {
|
||||
|
@ -336,7 +336,7 @@ 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;
|
||||
|
@ -344,7 +344,7 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
|||
|
||||
/* 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;
|
||||
|
@ -352,20 +352,20 @@ static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) {
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -653,11 +653,11 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -668,9 +668,9 @@ static void send_udppacket(node_t *n, vpn_packet_t *origpkt) {
|
|||
|
||||
/* 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 */
|
||||
|
|
|
@ -58,14 +58,13 @@ char *scriptinterpreter;
|
|||
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);
|
||||
|
||||
|
@ -76,7 +75,7 @@ bool node_read_ecdsa_public_key(node_t *n) {
|
|||
/* 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;
|
||||
}
|
||||
|
@ -93,28 +92,30 @@ bool node_read_ecdsa_public_key(node_t *n) {
|
|||
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 */
|
||||
|
@ -131,27 +132,29 @@ bool read_ecdsa_public_key(connection_t *c) {
|
|||
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 */
|
||||
|
@ -167,19 +170,18 @@ bool read_rsa_public_key(connection_t *c) {
|
|||
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 */
|
||||
|
||||
|
@ -207,20 +209,19 @@ static bool read_ecdsa_private_key(void) {
|
|||
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 */
|
||||
|
||||
|
@ -230,10 +231,10 @@ static bool read_rsa_private_key(void) {
|
|||
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 */
|
||||
|
@ -263,13 +264,13 @@ static bool read_rsa_private_key(void) {
|
|||
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;
|
||||
|
@ -707,7 +708,7 @@ static bool setup_myself(void) {
|
|||
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;
|
||||
}
|
||||
|
@ -730,7 +731,7 @@ static bool setup_myself(void) {
|
|||
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;
|
||||
}
|
||||
|
|
16
src/node.c
16
src/node.c
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -70,12 +70,12 @@ void free_node(node_t *n) {
|
|||
|
||||
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);
|
||||
|
@ -145,8 +145,8 @@ void update_node_udp(node_t *n, const sockaddr_t *sa) {
|
|||
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);
|
||||
|
||||
|
|
10
src/node.h
10
src/node.h
|
@ -52,14 +52,14 @@ typedef struct node_t {
|
|||
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 */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,56 +17,67 @@
|
|||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
if(cipher->cipher)
|
||||
return cipher_open(cipher);
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
if(cipher->cipher)
|
||||
return cipher_open(cipher);
|
||||
|
||||
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) {
|
||||
|
@ -214,5 +225,5 @@ int cipher_get_nid(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;
|
||||
}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,13 +17,13 @@
|
|||
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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,57 +17,55 @@
|
|||
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) {
|
||||
|
@ -78,8 +76,11 @@ 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) {
|
||||
|
@ -123,5 +124,5 @@ size_t digest_length(const digest_t *digest) {
|
|||
}
|
||||
|
||||
bool digest_active(const digest_t *digest) {
|
||||
return digest->digest && digest->digest->type != 0;
|
||||
return digest && digest->digest && digest->digest->type != 0;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,13 +17,11 @@
|
|||
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;
|
||||
|
@ -31,16 +29,4 @@ typedef struct digest {
|
|||
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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,68 +17,70 @@
|
|||
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));
|
||||
|
@ -89,8 +91,6 @@ bool ecdh_compute_shared(ecdh_t *ecdh, const void *pubkey, void *shared) {
|
|||
}
|
||||
|
||||
void ecdh_free(ecdh_t *ecdh) {
|
||||
if(*ecdh) {
|
||||
EC_KEY_free(*ecdh);
|
||||
*ecdh = NULL;
|
||||
}
|
||||
if(ecdh)
|
||||
EC_KEY_free(ecdh);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,22 +17,26 @@
|
|||
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);
|
||||
|
@ -40,19 +44,20 @@ bool ecdsa_set_base64_public_key(ecdsa_t *ecdsa, const char *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);
|
||||
|
@ -62,41 +67,39 @@ char *ecdsa_get_base64_public_key(ecdsa_t *ecdsa) {
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
@ -105,12 +108,12 @@ bool ecdsa_sign(ecdsa_t *ecdsa, const void *in, size_t len, void *sig) {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -119,12 +122,10 @@ bool ecdsa_verify(ecdsa_t *ecdsa, const void *in, size_t len, const void *sig) {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,59 +17,50 @@
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,27 +17,30 @@
|
|||
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.
|
||||
|
@ -51,10 +54,10 @@ static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, s
|
|||
|
||||
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++)
|
||||
|
@ -63,7 +66,7 @@ static bool prf_xor(int nid, const char *secret, size_t secretlen, char *seed, s
|
|||
outlen -= len;
|
||||
}
|
||||
|
||||
digest_close(&digest);
|
||||
digest_close(digest);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,69 +17,74 @@
|
|||
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))
|
||||
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;
|
||||
if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
|
||||
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))
|
||||
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;
|
||||
if(BN_hex2bn(&(*rsa)->e, e) != strlen(e))
|
||||
return false;
|
||||
if(BN_hex2bn(&(*rsa)->d, d) != strlen(d))
|
||||
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);
|
||||
rsa_t *rsa_read_pem_public_key(FILE *fp) {
|
||||
rsa_t *rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL);
|
||||
|
||||
if(*rsa)
|
||||
return true;
|
||||
if(!rsa)
|
||||
rsa = PEM_read_RSA_PUBKEY(fp, NULL, NULL, NULL);
|
||||
|
||||
*rsa = PEM_read_RSA_PUBKEY(fp, rsa, NULL, NULL);
|
||||
if(!rsa)
|
||||
logger(DEBUG_ALWAYS, LOG_ERR, "Unable to read RSA public key: %s", ERR_error_string(ERR_get_error(), NULL));
|
||||
|
||||
if(*rsa)
|
||||
return true;
|
||||
|
||||
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));
|
||||
|
@ -87,7 +92,7 @@ bool rsa_public_encrypt(rsa_t *rsa, void *in, size_t len, void *out) {
|
|||
}
|
||||
|
||||
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));
|
||||
|
@ -95,12 +100,10 @@ bool rsa_private_decrypt(rsa_t *rsa, void *in, size_t len, void *out) {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -17,13 +17,16 @@
|
|||
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 */
|
||||
|
||||
|
@ -63,21 +66,16 @@ static void indicator(int a, int b, void *p) {
|
|||
|
||||
// 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);
|
||||
}
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
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
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
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
|
||||
|
@ -221,7 +221,7 @@ bool id_h(connection_t *c, const char *request) {
|
|||
return false;
|
||||
}
|
||||
} else {
|
||||
if(c->protocol_minor && !ecdsa_active(&c->ecdsa))
|
||||
if(c->protocol_minor && !ecdsa_active(c->ecdsa))
|
||||
c->protocol_minor = 1;
|
||||
}
|
||||
|
||||
|
@ -246,13 +246,13 @@ bool send_metakey(connection_t *c) {
|
|||
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];
|
||||
|
@ -273,7 +273,7 @@ bool send_metakey(connection_t *c) {
|
|||
|
||||
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);
|
||||
|
@ -287,7 +287,7 @@ bool send_metakey(connection_t *c) {
|
|||
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;
|
||||
}
|
||||
|
@ -299,8 +299,8 @@ bool send_metakey(connection_t *c) {
|
|||
/* 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;
|
||||
|
@ -310,7 +310,7 @@ bool send_metakey(connection_t *c) {
|
|||
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];
|
||||
|
||||
|
@ -332,7 +332,7 @@ bool metakey_h(connection_t *c, const char *request) {
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -344,12 +344,12 @@ bool metakey_h(connection_t *c, const char *request) {
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -362,7 +362,7 @@ bool metakey_h(connection_t *c, const char *request) {
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -383,8 +383,8 @@ bool send_challenge(connection_t *c) {
|
|||
|
||||
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) {
|
||||
|
@ -407,7 +407,7 @@ bool challenge_h(connection_t *c, const char *request) {
|
|||
|
||||
/* 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 */
|
||||
|
||||
|
@ -433,7 +433,7 @@ bool chal_reply_h(connection_t *c, const char *request) {
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ bool chal_reply_h(connection_t *c, const char *request) {
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -461,7 +461,7 @@ static bool send_upgrade(connection_t *c) {
|
|||
/* 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;
|
||||
|
@ -545,7 +545,7 @@ static bool upgrade_h(connection_t *c, const char *request) {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ bool send_req_key(node_t *to) {
|
|||
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;
|
||||
|
@ -137,7 +137,7 @@ static bool req_key_ext_h(connection_t *c, const char *request, node_t *from, in
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -259,19 +259,22 @@ bool send_ans_key(node_t *to) {
|
|||
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);
|
||||
|
||||
|
@ -283,9 +286,9 @@ bool send_ans_key(node_t *to) {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -353,8 +356,8 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
}
|
||||
|
||||
/* 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) {
|
||||
|
@ -389,17 +392,17 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -408,15 +411,15 @@ bool ans_key_h(connection_t *c, const char *request) {
|
|||
|
||||
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;
|
||||
|
|
77
src/sptps.c
77
src/sptps.c
|
@ -98,11 +98,11 @@ static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const char *data
|
|||
|
||||
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);
|
||||
|
@ -131,10 +131,10 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const char *data, uint16_
|
|||
|
||||
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);
|
||||
|
@ -175,7 +175,7 @@ static bool send_kex(sptps_t *s) {
|
|||
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);
|
||||
|
@ -184,7 +184,7 @@ static bool send_kex(sptps_t *s) {
|
|||
// 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];
|
||||
|
@ -196,7 +196,7 @@ static bool send_sig(sptps_t *s) {
|
|||
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.
|
||||
|
@ -207,17 +207,16 @@ static bool send_sig(sptps_t *s) {
|
|||
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)
|
||||
|
@ -254,14 +253,14 @@ static bool receive_ack(sptps_t *s, const char *data, uint16_t len) {
|
|||
|
||||
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;
|
||||
}
|
||||
|
@ -296,7 +295,7 @@ static bool receive_kex(sptps_t *s, const char *data, uint16_t len) {
|
|||
// 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)
|
||||
|
@ -311,12 +310,12 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) {
|
|||
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.
|
||||
|
@ -336,14 +335,14 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) {
|
|||
// 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;
|
||||
}
|
||||
|
@ -413,7 +412,7 @@ bool sptps_verify_datagram(sptps_t *s, const char *data, size_t len) {
|
|||
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.
|
||||
|
@ -447,7 +446,7 @@ static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len
|
|||
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.
|
||||
|
@ -491,8 +490,8 @@ static bool sptps_receive_data_datagram(sptps_t *s, const char *data, size_t len
|
|||
|
||||
// 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.
|
||||
|
@ -540,7 +539,7 @@ bool sptps_receive_data(sptps_t *s, const char *data, size_t len) {
|
|||
// 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);
|
||||
|
@ -578,10 +577,10 @@ bool sptps_receive_data(sptps_t *s, const char *data, size_t len) {
|
|||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
@ -609,7 +608,7 @@ bool sptps_receive_data(sptps_t *s, const char *data, size_t len) {
|
|||
}
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -651,11 +650,11 @@ bool sptps_start(sptps_t *s, void *handle, bool initiator, bool datagram, ecdsa_
|
|||
// 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);
|
||||
|
|
16
src/sptps.h
16
src/sptps.h
|
@ -53,8 +53,8 @@ typedef struct sptps {
|
|||
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;
|
||||
|
@ -62,13 +62,13 @@ typedef struct sptps {
|
|||
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;
|
||||
|
@ -85,7 +85,7 @@ extern unsigned int sptps_replaywin;
|
|||
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);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
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
|
||||
|
@ -31,7 +31,7 @@ bool send_meta(void *c, const char *msg , int len) { return false; }
|
|||
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];
|
||||
|
@ -143,12 +143,12 @@ int main(int argc, char *argv[]) {
|
|||
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);
|
||||
|
||||
|
|
|
@ -346,13 +346,13 @@ static FILE *ask_and_open(const char *filename, const char *what, const char *mo
|
|||
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
|
||||
|
@ -370,7 +370,12 @@ static bool ecdsa_keygen(bool ask) {
|
|||
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);
|
||||
|
||||
|
@ -385,11 +390,12 @@ static bool ecdsa_keygen(bool ask) {
|
|||
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;
|
||||
}
|
||||
|
@ -399,13 +405,13 @@ static bool ecdsa_keygen(bool ask) {
|
|||
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
|
||||
|
@ -423,7 +429,12 @@ static bool rsa_keygen(int bits, bool ask) {
|
|||
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);
|
||||
|
||||
|
@ -438,9 +449,15 @@ static bool rsa_keygen(int bits, bool ask) {
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue