diff options
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | anytun.cpp | 55 | ||||
-rw-r--r-- | authAlgo.cpp | 10 | ||||
-rw-r--r-- | authAlgo.h | 4 | ||||
-rw-r--r-- | authAlgoFactory.cpp | 47 | ||||
-rw-r--r-- | authAlgoFactory.h | 49 | ||||
-rw-r--r-- | cypher.cpp | 19 | ||||
-rw-r--r-- | cypherFactory.h | 13 | ||||
-rw-r--r-- | encryptedPacket.cpp | 9 | ||||
-rw-r--r-- | encryptedPacket.h | 7 | ||||
-rw-r--r-- | keyDerivation.cpp | 16 | ||||
-rw-r--r-- | keyDerivation.h | 1 | ||||
-rw-r--r-- | options.cpp | 8 |
13 files changed, 186 insertions, 60 deletions
@@ -58,6 +58,8 @@ OBJS = anytun.o \ authTag.o \ keyDerivation.o \ mpi.o \ + cypherFactory.o \ + authAlgoFactory.o \ connectionList.o \ connectionParam.o \ networkAddress.o \ @@ -117,6 +119,12 @@ keyDerivation.o: keyDerivation.cpp keyDerivation.h mpi.o: mpi.cpp mpi.h $(C++) $(CCFLAGS) $< -c +cypherFactory.o: cypherFactory.cpp cypherFactory.h cypher.h + $(C++) $(CCFLAGS) $< -c + +authAlgoFactory.o: authAlgoFactory.cpp authAlgoFactory.h authAlgo.h + $(C++) $(CCFLAGS) $< -c + syncSocket.o: syncSocket.cpp syncSocket.h $(C++) $(CCFLAGS) $< -c @@ -44,6 +44,8 @@ #include "keyDerivation.h" #include "authAlgo.h" #include "authTag.h" +#include "cypherFactory.h" +#include "authAlgoFactory.h" #include "signalController.h" #include "packetSource.h" #include "tunDevice.h" @@ -94,17 +96,17 @@ void createConnection(const std::string & remote_host , u_int16_t remote_port, C } -void addPacketAuthTag(EncryptedPacket& pack, AuthAlgo& a, ConnectionParam& conn) +void addPacketAuthTag(EncryptedPacket& pack, AuthAlgo* a, ConnectionParam& conn) { - AuthTag at = a.calc(pack); + AuthTag at = a->calc(pack); pack.setAuthTag( at ); } -bool checkPacketAuthTag(EncryptedPacket& pack, AuthAlgo& a, ConnectionParam & conn) +bool checkPacketAuthTag(EncryptedPacket& pack, AuthAlgo* a, ConnectionParam & conn) { // check auth_tag and remove it AuthTag at = pack.getAuthTag(); - return (at == a.calc(pack)); + return (at == a->calc(pack)); } bool checkPacketSeqNr(EncryptedPacket& pack,ConnectionParam& conn) @@ -112,7 +114,8 @@ bool checkPacketSeqNr(EncryptedPacket& pack,ConnectionParam& conn) // compare sender_id and seq with window if(conn.seq_window_.hasSeqNr(pack.getSenderId(), pack.getSeqNr())) { - cLog.msg(Log::PRIO_NOTICE) << "Replay attack from " << conn.remote_host_<<":"<< conn.remote_port_<< " seq:"<<pack.getSeqNr() << " sid: "<<pack.getSenderId(); + cLog.msg(Log::PRIO_NOTICE) << "Replay attack from " << conn.remote_host_<<":"<< conn.remote_port_ + << " seq:"<<pack.getSeqNr() << " sid: "<<pack.getSenderId(); return false; } @@ -123,9 +126,11 @@ bool checkPacketSeqNr(EncryptedPacket& pack,ConnectionParam& conn) void* sender(void* p) { ThreadParam* param = reinterpret_cast<ThreadParam*>(p); - //TODO make Cypher selectable with command line option - AesIcmCypher c; - Sha1AuthAlgo a; + + CypherFactory c_factory; + AuthAlgoFactory a_factory; + std::auto_ptr<Cypher> c(c_factory.create(param->opt.getCypher())); + std::auto_ptr<AuthAlgo> a( a_factory.create(param->opt.getAuthAlgo()) ); PlainPacket plain_packet(1600); // TODO: fix me... mtu size EncryptedPacket packet(1600); @@ -163,15 +168,15 @@ void* sender(void* p) conn.kd_.generate(LABEL_SATP_SALT, conn.seq_nr_, session_salt, session_salt.getLength()); conn.kd_.generate(LABEL_SATP_MSG_AUTH, packet.getSeqNr(), session_auth_key, session_auth_key.getLength()); - c.setKey(session_key); - c.setSalt(session_salt); - c.cypher(packet, plain_packet, plain_packet.getLength(), conn.seq_nr_, param->opt.getSenderId()); + c->setKey(session_key); + c->setSalt(session_salt); + c->cypher(packet, plain_packet, plain_packet.getLength(), conn.seq_nr_, param->opt.getSenderId()); packet.setHeader(conn.seq_nr_, param->opt.getSenderId(), mux); conn.seq_nr_++; - a.setKey(session_auth_key); - addPacketAuthTag(packet, a, conn); +// a->setKey(session_auth_key); +// addPacketAuthTag(packet, a.get(), conn); param->src.send(packet, conn.remote_host_, conn.remote_port_); } pthread_exit(NULL); @@ -213,9 +218,12 @@ void* syncListener(void* p ) void* receiver(void* p) { - ThreadParam* param = reinterpret_cast<ThreadParam*>(p); - AesIcmCypher c; - Sha1AuthAlgo a; + ThreadParam* param = reinterpret_cast<ThreadParam*>(p); + + CypherFactory c_factory; + AuthAlgoFactory a_factory; + std::auto_ptr<Cypher> c( c_factory.create(param->opt.getCypher()) ); + std::auto_ptr<AuthAlgo> a( a_factory.create(param->opt.getAuthAlgo()) ); EncryptedPacket packet(1600); // TODO: dynamic mtu size PlainPacket plain_packet(1600); @@ -246,9 +254,9 @@ void* receiver(void* p) ConnectionParam & conn = param->cl.getConnection(0)->second; conn.kd_.generate(LABEL_SATP_MSG_AUTH, packet.getSeqNr(), session_auth_key, session_auth_key.getLength()); - a.setKey( session_auth_key ); - if(!checkPacketAuthTag(packet, a, conn)) - continue; +// a->setKey( session_auth_key ); +// if(!checkPacketAuthTag(packet, a.get(), conn)) +// continue; //Allow dynamic IP changes //TODO add command line option to turn this off @@ -268,9 +276,9 @@ void* receiver(void* p) // decrypt packet conn.kd_.generate(LABEL_SATP_ENCRYPTION, packet.getSeqNr(), session_key, session_key.getLength()); conn.kd_.generate(LABEL_SATP_SALT, packet.getSeqNr(), session_salt, session_salt.getLength()); - c.setKey(session_key); - c.setSalt(session_salt); - c.cypher(plain_packet, packet, packet.getLength(), packet.getSeqNr(), packet.getSenderId()); + c->setKey(session_key); + c->setSalt(session_salt); + c->cypher(plain_packet, packet, packet.getLength(), packet.getSeqNr(), packet.getSenderId()); // check payload_type and remove it if((param->dev.getType() == TunDevice::TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN) || @@ -284,7 +292,7 @@ void* receiver(void* p) } - +// make libgcrypt thread safe extern "C" { GCRY_THREAD_OPTION_PTHREAD_IMPL; } @@ -325,6 +333,7 @@ int main(int argc, char* argv[]) cLog.msg(Log::PRIO_NOTICE) << "dev opened - actual name is '" << p.dev.getActualName() << "'"; cLog.msg(Log::PRIO_NOTICE) << "dev type is '" << p.dev.getTypeString() << "'"; + // make libgcrypt thread safe gcry_control( GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread ); pthread_t senderThread; diff --git a/authAlgo.cpp b/authAlgo.cpp index d6f9565..4b5515e 100644 --- a/authAlgo.cpp +++ b/authAlgo.cpp @@ -44,7 +44,6 @@ AuthTag NullAuthAlgo::calc(const Buffer& buf) const char* Sha1AuthAlgo::MIN_GCRYPT_VERSION = "1.2.3"; - // HMAC_SHA1 Sha1AuthAlgo::Sha1AuthAlgo() : ctx_(NULL) { @@ -57,6 +56,15 @@ Sha1AuthAlgo::Sha1AuthAlgo() : ctx_(NULL) cLog.msg(Log::PRIO_ERR) << "Sha1AuthAlgo::Sha1AuthAlgo: Invalid Version of libgcrypt, should be >= " << MIN_GCRYPT_VERSION; return; } + + /* Allocate a pool of secure memory. + * This also drops priviliges on some systems. */ + err = gcry_control(GCRYCTL_INIT_SECMEM, GCRYPT_SEC_MEM, 0); + if( err ) { + cLog.msg(Log::PRIO_ERR) << "Failed to allocate " << GCRYPT_SEC_MEM << "bytes of secure memory: " << gpg_strerror( err ); + return; + } + /* Tell Libgcrypt that initialization has completed. */ err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED); if( err ) { @@ -45,12 +45,15 @@ public: virtual ~AuthAlgo() {}; virtual AuthTag calc(const Buffer& buf) { return AuthTag(0); }; + virtual void setKey(Buffer key) {}; }; class NullAuthAlgo : public AuthAlgo { public: + NullAuthAlgo() {}; AuthTag calc(const Buffer& buf); + void setKey(Buffer key) {}; }; @@ -78,6 +81,7 @@ public: AuthTag calc(const Buffer& buf); protected: static const char* MIN_GCRYPT_VERSION; + static const u_int32_t GCRYPT_SEC_MEM = 32768; // 32k secure memory gcry_md_hd_t ctx_; Mutex mutex_; }; diff --git a/authAlgoFactory.cpp b/authAlgoFactory.cpp new file mode 100644 index 0000000..262d7c3 --- /dev/null +++ b/authAlgoFactory.cpp @@ -0,0 +1,47 @@ +/* + * 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 <string> +#include <stdexcept> + +#include "authAlgoFactory.h" +#include "authAlgo.h" + + +AuthAlgo* AuthAlgoFactory::create(std::string const& type) +{ + if( type == "null" ) + return new NullAuthAlgo(); + else if( type == "sha1" ) + return new Sha1AuthAlgo(); + else + throw std::invalid_argument("auth algo not available"); +} + diff --git a/authAlgoFactory.h b/authAlgoFactory.h new file mode 100644 index 0000000..5949ca3 --- /dev/null +++ b/authAlgoFactory.h @@ -0,0 +1,49 @@ +/* + * 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 _AUTHALGO_FACTORY_H_ +#define _AUTHALGO_FACTORY_H_ + +#include <string> + +#include "datatypes.h" +#include "authAlgo.h" + +class AuthAlgoFactory +{ +public: + AuthAlgoFactory() {}; + ~AuthAlgoFactory() {}; + + AuthAlgo* create(std::string const& type); + +}; + +#endif @@ -64,16 +64,13 @@ AesIcmCypher::AesIcmCypher() : salt_(Buffer(14)) return; } - // do NOT allocate a pool of secure memory! - // this is NOT thread safe! - // /* Allocate a pool of secure memory. This also drops priviliges - // on some systems. */ - // err = gcry_control(GCRYCTL_INIT_SECMEM, GCRYPT_SEC_MEM, 0); - // if( err ) { - // std::cerr << "Failed to allocate " << GCRYPT_SEC_MEM << "bytes of secure memory: "; - // std::cerr << gpg_strerror( err ) << std::endl; - // return; - // } + /* Allocate a pool of secure memory. This also drops priviliges + on some systems. */ + err = gcry_control(GCRYCTL_INIT_SECMEM, GCRYPT_SEC_MEM, 0); + if( err ) { + cLog.msg(Log::PRIO_ERR) << "Failed to allocate " << GCRYPT_SEC_MEM << "bytes of secure memory: " << gpg_strerror( err ); + return; + } /* Tell Libgcrypt that initialization has completed. */ err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED); @@ -85,7 +82,7 @@ AesIcmCypher::AesIcmCypher() : salt_(Buffer(14)) } } - gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 ); + err = gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 ); if( err ) cLog.msg(Log::PRIO_CRIT) << "AesIcmCypher::AesIcmCypher: Failed to open cypher"; } diff --git a/cypherFactory.h b/cypherFactory.h index 3f44827..f245301 100644 --- a/cypherFactory.h +++ b/cypherFactory.h @@ -31,7 +31,6 @@ #ifndef _CYPHER_FACTORY_H_ #define _CYPHER_FACTORY_H_ -#include <stdexcept> #include <string> #include "datatypes.h" @@ -43,17 +42,7 @@ public: CypherFactory() {}; ~CypherFactory() {}; - Cypher* create(std::string const& type) - { - if( type == "null" ) - return new NullCypher(); - else if( type == "aes" ) - return new AesIcmCypher(); - else - throw std::invalid_argument("cypher not available"); - } - + Cypher* create(std::string const& type); }; - #endif diff --git a/encryptedPacket.cpp b/encryptedPacket.cpp index 0ac0ca9..35ccda0 100644 --- a/encryptedPacket.cpp +++ b/encryptedPacket.cpp @@ -50,6 +50,15 @@ EncryptedPacket::EncryptedPacket(u_int32_t max_payload_length) } +EncryptedPacket::~EncryptedPacket() +{ + buf_ = reinterpret_cast<u_int8_t*>(header_); + if( auth_tag_ == NULL ) + length_ = size_ + sizeof(struct HeaderStruct) + AUTHTAG_SIZE; + else + length_ = size_ + sizeof(struct HeaderStruct); +} + seq_nr_t EncryptedPacket::getSeqNr() const { return SEQ_NR_T_NTOH(header_->seq_nr); diff --git a/encryptedPacket.h b/encryptedPacket.h index ffe9246..7b70e17 100644 --- a/encryptedPacket.h +++ b/encryptedPacket.h @@ -44,7 +44,12 @@ public: * @param max_payload_length maximum length of encrypted payload */ EncryptedPacket(u_int32_t max_payload_length); - + + /** + * Packet destructor + */ + ~EncryptedPacket(); + /** * Get the sequence number * @return seqence number diff --git a/keyDerivation.cpp b/keyDerivation.cpp index dbef123..911ea87 100644 --- a/keyDerivation.cpp +++ b/keyDerivation.cpp @@ -59,14 +59,14 @@ void KeyDerivation::init(Buffer key, Buffer salt) // do NOT allocate a pool of secure memory! // this is NOT thread safe! - // /* Allocate a pool of 16k secure memory. This also drops priviliges - // * on some systems. */ - // err = gcry_control(GCRYCTL_INIT_SECMEM, 16384, 0); - // if( err ) - // { - // std::cerr << "Failed to allocate 16k secure memory: " << gpg_strerror( err ) << std::endl; - // return; - // } + /* Allocate a pool of 16k secure memory. This also drops priviliges + * on some systems. */ + err = gcry_control(GCRYCTL_INIT_SECMEM, GCRYPT_SEC_MEM, 0); + if( err ) + { + cLog.msg(Log::PRIO_ERR) << "Failed to allocate " << GCRYPT_SEC_MEM << " bytes of secure memory: " << gpg_strerror( err ); + return; + } /* Tell Libgcrypt that initialization has completed. */ err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED); diff --git a/keyDerivation.h b/keyDerivation.h index 531d441..214a1a4 100644 --- a/keyDerivation.h +++ b/keyDerivation.h @@ -75,6 +75,7 @@ protected: int8_t ld_kdr_; // ld(key_derivation_rate) SyncBuffer salt_; static const char* MIN_GCRYPT_VERSION; + static const u_int32_t GCRYPT_SEC_MEM = 32768; // 32k secure memory gcry_cipher_hd_t cipher_; Mutex mutex_; diff --git a/options.cpp b/options.cpp index 0bf39db..1158c98 100644 --- a/options.cpp +++ b/options.cpp @@ -103,8 +103,8 @@ Options::Options() ifconfig_param_local_ = "192.168.200.1"; ifconfig_param_remote_netmask_ = "255.255.255.0"; seq_window_size_ = 100; - cypher_ = "null"; - auth_algo_ = "null"; + cypher_ = "aes"; + auth_algo_ = "sha1"; } bool Options::parse(int argc, char* argv[]) @@ -171,8 +171,8 @@ void Options::printUsage() std::cout << " [-n|--ifconfig] <local> the local address for the tun/tap device" << std::endl << " <remote|netmask> the remote address(tun) or netmask(tap)" << std::endl; std::cout << " [-w|--window-size] <window size> seqence number window size" << std::endl; - std::cout << " [-c|--cypher] <cypher type> type of cypher" << std::endl; - std::cout << " [-a|--auth-algo] <algo type> authentication algoritm" << std::endl; + std::cout << " [-c|--cypher] <cypher type> payload encryption algorithm" << std::endl; + std::cout << " [-a|--auth-algo] <algo type> message authentication algorithm" << std::endl; } void Options::printOptions() |