diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | anytun.cpp | 99 | ||||
-rw-r--r-- | buffer.h | 3 | ||||
-rw-r--r-- | connectionParam.h | 3 | ||||
-rw-r--r-- | keyDerivation.cpp | 66 | ||||
-rw-r--r-- | keyDerivation.h | 11 | ||||
-rw-r--r-- | mpi.cpp | 118 | ||||
-rw-r--r-- | mpi.h | 63 |
8 files changed, 276 insertions, 91 deletions
@@ -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 @@ -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; @@ -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_; }; @@ -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_ ); +} + @@ -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 |