summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--anytun.cpp99
-rw-r--r--buffer.h3
-rw-r--r--connectionParam.h3
-rw-r--r--keyDerivation.cpp66
-rw-r--r--keyDerivation.h11
-rw-r--r--mpi.cpp118
-rw-r--r--mpi.h63
8 files changed, 276 insertions, 91 deletions
diff --git a/Makefile b/Makefile
index 336c2d6..16bc512 100644
--- a/Makefile
+++ b/Makefile
@@ -54,6 +54,7 @@ OBJS = anytun.o \
authAlgo.o \
authTag.o \
keyDerivation.o \
+ mpi.o \
connectionList.o \
connectionParam.o \
networkAddress.o \
@@ -101,6 +102,9 @@ authTag.o: authTag.cpp authTag.h buffer.h
keyDerivation.o: keyDerivation.cpp keyDerivation.h
$(C++) $(CCFLAGS) $< -c
+mpi.o: mpi.cpp mpi.h
+ $(C++) $(CCFLAGS) $< -c
+
syncSocket.o: syncSocket.cpp syncSocket.h
$(C++) $(CCFLAGS) $< -c
diff --git a/anytun.cpp b/anytun.cpp
index 91daf86..b3ed30e 100644
--- a/anytun.cpp
+++ b/anytun.cpp
@@ -30,6 +30,8 @@
#include <iostream>
#include <poll.h>
+#include <gcrypt.h>
+#include <errno.h>
#include "datatypes.h"
@@ -55,6 +57,7 @@
#define PAYLOAD_TYPE_TAP 0x6558
#define PAYLOAD_TYPE_TUN 0x0800
+
struct Param
{
Options& opt;
@@ -68,64 +71,62 @@ void createConnection(const std::string & remote_host , u_int16_t remote_port, C
SeqWindow seq(seqSize);
-// uint8_t key[] = {
-// 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
-// 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
-// 'q', 'r', 's', 't'
-// };
+ uint8_t key[] = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 'q', 'r', 's', 't'
+ };
-// uint8_t salt[] = {
-// 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
-// 'i', 'j', 'k', 'l', 'm', 'n'
-// };
+ uint8_t salt[] = {
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+ 'i', 'j', 'k', 'l', 'm', 'n'
+ };
seq_nr_t seq_nr_=0;
KeyDerivation kd;
- //kd.init(Buffer(key, sizeof(key)), Buffer(salt, sizeof(salt)));
+ kd.init(Buffer(key, sizeof(key)), Buffer(salt, sizeof(salt)));
cLog.msg(Log::PRIO_NOTICE) << "added connection remote host " << remote_host << ":" << remote_port;
ConnectionParam connparam ( kd, seq, seq_nr_, remote_host, remote_port);
cl.addConnection(connparam,std::string("default"));
}
-void encryptPacket(Packet & pack, Cypher & c, ConnectionParam & conn)
+void encryptPacket(Packet & pack, Cypher & c, ConnectionParam & conn, void* p)
{
- // cypher the packet
-/* Buffer tmp_key(16), tmp_salt(14);
- //TODO fix key derivation!
- //conn.kd_.generate(label_satp_encryption, seq, tmp_key, tmp_key.getLength());
- //conn.kd_.generate(label_satp_salt, seq, tmp_salt, tmp_salt.getLength());
- c.setKey(tmp_key);
- c.setSalt(tmp_salt);
-
- //cLog.msg(Log::PRIO_NOTICE) << "Send Package: seq: " << seq;
- //cLog.msg(Log::PRIO_NOTICE) << "sID: " << param->opt.getSenderId();
- //cLog.msg(Log::PRIO_NOTICE) << "Package dump: " << pack.getBuf();
-
- c.cypher(pack, seq, param->opt.getSenderId());
-
-*/ // add header to packet
-
+ Param* param = reinterpret_cast<Param*>(p);
+ // cypher the packet
+ Buffer tmp_key(16), tmp_salt(14);
+ //TODO fix key derivation!
+ conn.kd_.generate(label_satp_encryption, conn.seq_nr_, tmp_key, tmp_key.getLength());
+ conn.kd_.generate(label_satp_salt, conn.seq_nr_, tmp_salt, tmp_salt.getLength());
+ c.setKey(tmp_key);
+ c.setSalt(tmp_salt);
+
+ cLog.msg(Log::PRIO_NOTICE) << "Send Package: seq: " << conn.seq_nr_;
+ cLog.msg(Log::PRIO_NOTICE) << "sID: " << param->opt.getSenderId();
+ cLog.msg(Log::PRIO_NOTICE) << "Package dump: " << pack.getBuf();
+
+ c.cypher(pack, conn.seq_nr_, param->opt.getSenderId());
}
bool decryptPacket(Packet & pack, Cypher & c, ConnectionParam & conn)
{
-// u_int16_t sid = pack.getSenderId();
-// u_int16_t seq = pack.getSeqNr();
-/*
- // decypher the packet
- Buffer tmp_key(16), tmp_salt(14);
- //conn.kd_.generate(label_satp_encryption, seq, tmp_key, tmp_key.getLength());
- //conn.kd_.generate(label_satp_salt, seq, tmp_salt, tmp_salt.getLength());
- c.setKey(tmp_key);
- c.setSalt(tmp_salt);
- c.cypher(pack, seq, sid);
-
- //cLog.msg(Log::PRIO_NOTICE) << "Received Package: seq: " << seq;
- //cLog.msg(Log::PRIO_NOTICE) << "sID: " << sid;
- //cLog.msg(Log::PRIO_NOTICE) << "Package dump: " << pack.getBuf();
-*/
- return true;
+ u_int16_t sid = pack.getSenderId();
+ u_int16_t seq = pack.getSeqNr();
+
+ // decypher the packet
+ Buffer tmp_key(16), tmp_salt(14);
+ conn.kd_.generate(label_satp_encryption, seq, tmp_key, tmp_key.getLength());
+ conn.kd_.generate(label_satp_salt, seq, tmp_salt, tmp_salt.getLength());
+ c.setKey(tmp_key);
+ c.setSalt(tmp_salt);
+ c.cypher(pack, seq, sid);
+
+ cLog.msg(Log::PRIO_NOTICE) << "Received Package: seq: " << seq;
+ cLog.msg(Log::PRIO_NOTICE) << "sID: " << sid;
+ cLog.msg(Log::PRIO_NOTICE) << "Package dump: " << pack.getBuf();
+
+ return true;
}
void addPacketAuthTag(Packet & pack, Cypher & c, ConnectionParam & conn)
@@ -194,7 +195,7 @@ void* sender(void* p)
else
pack.addPayloadType(0);
- encryptPacket(pack, c, conn);
+ encryptPacket(pack, c, conn, param);
pack.addHeader(conn.seq_nr_, param->opt.getSenderId());
conn.seq_nr_++;
@@ -242,7 +243,6 @@ void* receiver(void* p)
// read packet from socket
u_int32_t len = param->src.recv(pack, remote_host, remote_port);
pack.resizeBack(len);
-// pack.withPayloadType(true).withHeader(true).withAuthTag(true);
pack.withPayloadType(true).withHeader(true).withAuthTag(false);
@@ -289,6 +289,10 @@ void* receiver(void* p)
pthread_exit(NULL);
}
+extern "C" {
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+}
+
int main(int argc, char* argv[])
{
std::cout << "anytun - secure anycast tunneling protocol" << std::endl;
@@ -315,13 +319,16 @@ int main(int argc, char* argv[])
if(opt.getRemoteAddr() != "")
createConnection(opt.getRemoteAddr(),opt.getRemotePort(),cl,opt.getSeqWindowSize());
+
struct Param p = {opt, dev, *src, cl};
cLog.msg(Log::PRIO_NOTICE) << "dev created (opened)";
cLog.msg(Log::PRIO_NOTICE) << "dev opened - actual name is '" << p.dev.getActualName() << "'";
cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << p.dev.getTypeString() << "'";
-
+
+ gcry_control( GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread );
+
pthread_t senderThread;
pthread_create(&senderThread, NULL, sender, &p);
pthread_t receiverThread;
diff --git a/buffer.h b/buffer.h
index 17e1154..e8c33e6 100644
--- a/buffer.h
+++ b/buffer.h
@@ -65,7 +65,8 @@ protected:
friend class TunDevice;
friend class UDPPacketSource;
friend class AesIcmCypher;
- friend class KeyDerivation; //
+ friend class KeyDerivation; //
+ friend class Mpi;
u_int8_t *buf_;
u_int32_t length_;
diff --git a/connectionParam.h b/connectionParam.h
index 98eab34..4bd58ab 100644
--- a/connectionParam.h
+++ b/connectionParam.h
@@ -43,10 +43,11 @@
class ConnectionParam
{
public:
- ConnectionParam( KeyDerivation& kd, SeqWindow& seq_window,seq_nr_t seq_nr_, std::string remote_host, u_int16_t remote_port);
+ ConnectionParam( KeyDerivation& kd, SeqWindow& seq_window, seq_nr_t seq_nr_, std::string remote_host, u_int16_t remote_port);
KeyDerivation& kd_;
SeqWindow& seq_window_;
seq_nr_t seq_nr_;
+ sender_id_t sennder_id_;
std::string remote_host_;
u_int16_t remote_port_;
private:
diff --git a/keyDerivation.cpp b/keyDerivation.cpp
index b74f459..d3498b8 100644
--- a/keyDerivation.cpp
+++ b/keyDerivation.cpp
@@ -29,27 +29,30 @@
*/
+#include "log.h"
#include "keyDerivation.h"
+#include "mpi.h"
+#include "threadUtils.hpp"
#include <stdexcept>
#include <iostream>
#include <string>
-extern "C" {
#include <gcrypt.h>
-}
+
const char* KeyDerivation::MIN_GCRYPT_VERSION = "1.2.3";
void KeyDerivation::init(Buffer key, Buffer salt)
{
+ Lock lock(mutex_);
gcry_error_t err;
// No other library has already initialized libgcrypt.
if( !gcry_control(GCRYCTL_ANY_INITIALIZATION_P) )
{
if( !gcry_check_version( MIN_GCRYPT_VERSION ) ) {
- std::cerr << "Invalid Version of libgcrypt, should be >= " << MIN_GCRYPT_VERSION << std::endl;
+ cLog.msg(Log::PRIO_ERR) << "Invalid Version of libgcrypt, should be >= " << MIN_GCRYPT_VERSION;
return;
}
@@ -68,43 +71,38 @@ void KeyDerivation::init(Buffer key, Buffer salt)
/* Tell Libgcrypt that initialization has completed. */
err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
if( err ) {
- std::cerr << "Failed to finish the initialization of libgcrypt" << gpg_strerror( err ) << std::endl;
+ cLog.msg(Log::PRIO_ERR) << "Failed to finish the initialization of libgcrypt: " << gpg_strerror( err );
return;
} else {
- std::cout << "KeyDerivation::init: libgcrypt init finished" << std::endl;
+ cLog.msg(Log::PRIO_NOTICE) << "KeyDerivation::init: libgcrypt init finished";
}
}
err = gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 );
- if( err )
- {
- std::cerr << "Failed to open cipher: " << gpg_strerror( err ) << std::endl;
+ if( err ) {
+ cLog.msg(Log::PRIO_ERR) << "Failed to open cipher: " << gpg_strerror( err );
return;
}
salt_ = SyncBuffer(salt);
- initialized_ = true;
}
void KeyDerivation::setLogKDRate(const uint8_t log_rate)
{
+ Lock lock(mutex_);
if( log_rate < 49 )
ld_kdr_ = log_rate;
}
-void KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, u_int32_t length)
+void KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, u_int32_t length)
{
+ Lock lock(mutex_);
gcry_error_t err;
- u_int8_t r = 0;
- Buffer iv(16);
- u_int8_t tmp_key_id[16];
-
- if(!initialized_) {
- std::cout << "ERROR: keyderivation::generate: keyderivation not initialized yet!" << std::endl;
- return;
- }
+ Mpi r;
+ Mpi key_id;
+ Mpi iv(128);
// see at: http://tools.ietf.org/html/rfc3711#section-4.3
// * Let r = index DIV key_derivation_rate (with DIV as defined above).
@@ -118,37 +116,33 @@ void KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key,
r = 0;
else
// FIXXME: kdr can be greater than 2^32 (= 2^48)
- r = seq_nr / ( 0x01 << ld_kdr_ );
-
+ r = static_cast<long unsigned int>(seq_nr / ( 0x01 << ld_kdr_ ));
- // FIXXME: why i cant access key_id via operator []?
- for(u_int8_t i=0; i<sizeof(tmp_key_id); i++)
- tmp_key_id[i] = 0x00;
+ r.rShift(8);
+ key_id = r + Mpi(static_cast<long unsigned int>(label));
- tmp_key_id[0] = r;
- tmp_key_id[1] = label;
-
- Buffer key_id(tmp_key_id, 16);
-
- iv = key_id ^ salt_;
+ Mpi salt = Mpi(salt_.getBuf(), salt_.getLength());
+ iv = key_id ^ salt;
err = gcry_cipher_reset( cipher_ );
+ if( err )
+ cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to reset cipher: " << gpg_strerror( err );
+
+
+ err = gcry_cipher_setiv( cipher_ , iv.getBuf().getBuf(), iv.getBuf().getLength());
if( err )
- {
- std::cerr << "Failed to reset cipher: " << gpg_strerror( err ) << std::endl;
- }
+ cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to set IV: " << gpg_strerror( err );
err = gcry_cipher_encrypt( cipher_, key, length, 0, 0 );
- if( err )
- {
- std::cerr << "Failed to generate cipher bitstream: " << gpg_strerror( err ) << std::endl;
- }
+ if( err )
+ cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to generate cipher bitstream: " << gpg_strerror( err );
}
void KeyDerivation::clear()
{
+ Lock lock(mutex_);
gcry_cipher_close( cipher_ );
}
diff --git a/keyDerivation.h b/keyDerivation.h
index d155934..f7a4068 100644
--- a/keyDerivation.h
+++ b/keyDerivation.h
@@ -33,17 +33,14 @@
#include "datatypes.h"
#include "buffer.h"
+#include "threadUtils.hpp"
#include "syncBuffer.h"
+#include <gcrypt.h>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
-extern "C" {
- #include <gcrypt.h>
-}
-
-
typedef enum {
label_satp_encryption = 0x00,
label_satp_msg_auth = 0x01,
@@ -54,7 +51,7 @@ typedef enum {
class KeyDerivation
{
public:
- KeyDerivation() : ld_kdr_(-1), cipher_(NULL), initialized_(false) {};
+ KeyDerivation() : ld_kdr_(-1), cipher_(NULL) {};
virtual ~KeyDerivation() {};
void init(Buffer key, Buffer salt);
@@ -71,7 +68,7 @@ protected:
static const char* MIN_GCRYPT_VERSION;
gcry_cipher_hd_t cipher_;
- bool initialized_;
+ Mutex mutex_;
};
diff --git a/mpi.cpp b/mpi.cpp
new file mode 100644
index 0000000..510a17f
--- /dev/null
+++ b/mpi.cpp
@@ -0,0 +1,118 @@
+/*
+ * anytun
+ *
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methodes used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007 anytun.org <satp@wirdorange.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mpi.h"
+
+#include "datatypes.h"
+#include "cypher.h"
+
+#include <stdexcept>
+#include <gcrypt.h>
+
+
+Mpi::Mpi() : val_(NULL)
+{
+}
+
+Mpi::Mpi(u_int8_t length)
+{
+ val_ = gcry_mpi_new(length);
+}
+
+Mpi::Mpi(const Mpi &src)
+{
+ val_ = gcry_mpi_copy(src.val_);
+}
+
+Mpi::Mpi(const u_int8_t * src, u_int32_t len)
+{
+ gcry_mpi_scan( &val_, GCRYMPI_FMT_STD, src, len, NULL );
+}
+void Mpi::operator=(const Mpi &src)
+{
+ val_ = gcry_mpi_copy(src.val_);
+}
+
+void Mpi::operator=(const long unsigned int src)
+{
+ gcry_mpi_set_ui(val_, src);
+}
+
+Mpi Mpi::operator+(const Mpi &b) const
+{
+ Mpi res;
+ gcry_mpi_add(res.val_, val_, b.val_);
+ return res;
+}
+
+Mpi Mpi::operator^(const Mpi &b) const
+{
+ u_int32_t len = 0;
+
+ Mpi res(gcry_mpi_get_nbits(val_));
+
+ if(gcry_mpi_get_nbits(val_) != gcry_mpi_get_nbits(b.val_))
+ throw std::length_error("mpi::operator^ const");
+
+ len = gcry_mpi_get_nbits(val_);
+
+ for(u_int32_t i=0; i<len; i++) {
+ if(gcry_mpi_test_bit(val_, i) ^ gcry_mpi_test_bit(b.val_, i))
+ gcry_mpi_set_bit(res.val_, i);
+ }
+ return res;
+}
+
+void Mpi::rShift(u_int8_t n)
+{
+ gcry_mpi_rshift(val_, val_, n);
+}
+
+Buffer Mpi::getBuf() const
+{
+ u_int32_t len = 0, written = 0;
+ len = gcry_mpi_get_nbits( val_ );
+
+ Buffer res(static_cast<u_int32_t>(len/8)+1);
+
+ gcry_mpi_print( GCRYMPI_FMT_STD, res, len, &written, val_ );
+ return res;
+}
+
+u_int32_t Mpi::getLen() const
+{
+ return gcry_mpi_get_nbits( val_ );
+}
+
+Mpi::~Mpi()
+{
+ gcry_mpi_release( val_ );
+}
+
diff --git a/mpi.h b/mpi.h
new file mode 100644
index 0000000..c8a9907
--- /dev/null
+++ b/mpi.h
@@ -0,0 +1,63 @@
+/*
+ * anytun
+ *
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methodes used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007 anytun.org <satp@wirdorange.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MPI_H_
+#define _MPI_H_
+
+#include "datatypes.h"
+#include "buffer.h"
+
+#include <gcrypt.h>
+
+
+class Mpi
+{
+public:
+ Mpi();
+ virtual ~Mpi();
+ Mpi(u_int8_t length);
+ Mpi(const Mpi &src);
+ Mpi(const u_int8_t * src, u_int32_t len);
+ void operator=(const Mpi &src);
+ void operator=(long unsigned int);
+ Mpi operator+(const Mpi &b) const;
+ Mpi operator^(const Mpi &b) const;
+
+ void rShift(u_int8_t n);
+ Buffer getBuf() const;
+ u_int32_t getLen() const;
+
+protected:
+ gcry_mpi_t val_;
+};
+
+
+
+#endif