diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | anytun.cpp | 36 | ||||
-rw-r--r-- | authAlgo.cpp | 19 | ||||
-rw-r--r-- | authAlgo.h | 8 | ||||
-rw-r--r-- | authTag.cpp | 49 | ||||
-rw-r--r-- | authTag.h | 49 | ||||
-rw-r--r-- | buffer.cpp | 37 | ||||
-rw-r--r-- | buffer.h | 7 | ||||
-rw-r--r-- | cypher.cpp | 51 | ||||
-rw-r--r-- | keyDerivation.cpp | 30 | ||||
-rw-r--r-- | keyDerivation.h | 3 | ||||
-rw-r--r-- | packet.cpp | 43 | ||||
-rw-r--r-- | packet.h | 7 |
13 files changed, 240 insertions, 103 deletions
@@ -51,6 +51,7 @@ OBJS = anytun.o \ packet.o \ cypher.o \ authAlgo.o \ + authTag.o \ keyDerivation.o \ connectionList.o \ connectionParam.o \ @@ -90,6 +91,9 @@ cypher.o: cypher.cpp cypher.h buffer.h authAlgo.o: authAlgo.cpp authAlgo.h buffer.h $(C++) $(CCFLAGS) $< -c +authTag.o: authTag.cpp authTag.h buffer.h + $(C++) $(CCFLAGS) $< -c + keyDerivation.o: keyDerivation.cpp keyDerivation.h $(C++) $(CCFLAGS) $< -c @@ -39,6 +39,7 @@ #include "cypher.h" #include "keyDerivation.h" #include "authAlgo.h" +//#include "authTag.h" #include "signalController.h" #include "packetSource.h" #include "tunDevice.h" @@ -76,7 +77,8 @@ void createConnection(const std::string & remote_host , u_int16_t remote_port, C KeyDerivation kd; kd.init(Buffer(key, sizeof(key)), Buffer(salt, sizeof(salt))); - ConnectionParam connparam ( kd, seq, remote_host, remote_port); + std::cout << "anytun.cpp: crateConnection called" << std::endl; + ConnectionParam connparam ( kd, seq, remote_host, remote_port); cl.addConnection(connparam,std::string("default")); } @@ -85,7 +87,8 @@ void* sender(void* p) Param* param = reinterpret_cast<Param*>(p); //TODO make Cypher selectable with command line option NullCypher c; - NullAuthAlgo a; +// AesIcmCypher c; +// NullAuthAlgo a; seq_nr_t seq = 0; while(1) @@ -123,10 +126,13 @@ void* sender(void* p) pack.addHeader(seq, param->opt.getSenderId()); seq++; - // calc auth_tag and add it to the packet - auth_tag_t at = a.calc(pack); - pack.addAuthTag(at); - +// // calc auth_tag and add it to the packet +// AuthTag at = a.calc(pack); +// if(at != AuthTag(0)) { +// //auth_tag_t at = a.calc(pack); +// pack.addAuthTag(at); +// } +// // send it out to remote host param->src.send(pack, param->opt.getRemoteAddr(), param->opt.getRemotePort()); } @@ -146,7 +152,8 @@ void* receiver(void* p) { Param* param = reinterpret_cast<Param*>(p); NullCypher c; - NullAuthAlgo a; +// AesIcmCypher c; +// NullAuthAlgo a; while(1) { @@ -158,13 +165,14 @@ 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); - - // check auth_tag and remove it - auth_tag_t at = pack.getAuthTag(); - pack.removeAuthTag(); - if(at != a.calc(pack)) - continue; +// pack.withPayloadType(true).withHeader(true).withAuthTag(true); + pack.withPayloadType(true).withHeader(true).withAuthTag(false); + +// // check auth_tag and remove it +// AuthTag at = pack.getAuthTag(); +// pack.removeAuthTag(); +// if(at != a.calc(pack)) +// continue; // autodetect peer // TODO fixme, IP might change!!! diff --git a/authAlgo.cpp b/authAlgo.cpp index d19cf2d..db4a16c 100644 --- a/authAlgo.cpp +++ b/authAlgo.cpp @@ -35,17 +35,26 @@ extern "C" { } -auth_tag_t NullAuthAlgo::calc(const Buffer& buf) +AuthTag NullAuthAlgo::calc(const Buffer& buf) { - return 0; + return AuthTag(0); } // HMAC_SHA1 -auth_tag_t HmacAuthAlgo::calc(const Buffer& buf) +AuthTag HmacAuthAlgo::calc(const Buffer& buf) { -// gcry_md_hash_buffer(GCRY_MD_SHA1, ht, buf.getBuf(), buf.getLength()); - return 0; + gcry_error_t err; + gcry_md_hd_t ctx; + Buffer hmac; //80bit + + err = gcry_md_open( &ctx, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC ); + //gcry_md_setkey( ctx, key, keylen ); + gcry_md_write( ctx, static_cast<Buffer>(buf).getBuf(), buf.getLength() ); + gcry_md_final( ctx ); + hmac = Buffer(gcry_md_read( ctx, 0 ), 10); + gcry_md_close( ctx ); + return hmac; } @@ -32,7 +32,7 @@ #define _AUTHALGO_H_ #include "datatypes.h" -#include "buffer.h" +#include "authTag.h" class AuthAlgo { @@ -40,13 +40,13 @@ public: AuthAlgo() {}; virtual ~AuthAlgo() {}; - virtual auth_tag_t calc(const Buffer& buf) = 0; + virtual AuthTag calc(const Buffer& buf) = 0; }; class NullAuthAlgo : public AuthAlgo { public: - auth_tag_t calc(const Buffer& buf); + AuthTag calc(const Buffer& buf); }; @@ -54,7 +54,7 @@ public: class HmacAuthAlgo : public AuthAlgo { public: - auth_tag_t calc(const Buffer& buf); + AuthTag calc(const Buffer& buf); }; #endif diff --git a/authTag.cpp b/authTag.cpp new file mode 100644 index 0000000..fe5dc6d --- /dev/null +++ b/authTag.cpp @@ -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 + */ + +#include <stdexcept> +#include "datatypes.h" +#include "authTag.h" + +AuthTag::AuthTag() +{ +} + +AuthTag::AuthTag(u_int32_t length) : Buffer(length) +{ +} + +AuthTag::AuthTag(const Buffer &src) : Buffer(src) +{ +} + +AuthTag::AuthTag(u_int8_t* data, u_int32_t length) : Buffer(data, length) +{ +} diff --git a/authTag.h b/authTag.h new file mode 100644 index 0000000..95f2805 --- /dev/null +++ b/authTag.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 _AUTHTAG_H_ +#define _AUTHTAG_H_ + +#include "datatypes.h" +#include "buffer.h" + +class AuthTag : public Buffer +{ +public: + AuthTag(); + AuthTag(u_int32_t length); + AuthTag(const Buffer &src); + AuthTag(u_int8_t* data, u_int32_t length); + +private: + +}; + +#endif @@ -88,43 +88,20 @@ void Buffer::operator=(const Buffer &src) length_ = 0; } -void Buffer::operator=(const seq_nr_t &src) -{ - if(buf_) - delete[] buf_; - - length_ = sizeof(src); - - buf_ = new u_int8_t[length_]; - if( buf_ ) - { - for( u_int32_t index = 0; index <= length_; index++ ) - buf_[index] = (src>>index) & 0xFF; - } - else - length_ = 0; -} - -void Buffer::operator=(const sender_id_t &src) +bool Buffer::operator==(const Buffer &cmp) const { - if(buf_) - delete[] buf_; + if(length_ != cmp.length_) + return false; - length_ = sizeof(src); - - buf_ = new u_int8_t[length_]; + if(!std::memcmp(buf_, cmp.buf_, length_)) + return true; - if( buf_ ) - { - for( u_int32_t index = 0; index <= length_; index++ ) - buf_[index] = (src>>index) & 0xFF; - } - else - length_ = 0; + return false; } + u_int32_t Buffer::resizeFront(u_int32_t new_length) { if(length_ == new_length) @@ -51,8 +51,7 @@ public: virtual ~Buffer(); Buffer(const Buffer &src); void operator=(const Buffer &src); - void operator=(const seq_nr_t &src); - void operator=(const sender_id_t &src); + bool operator==(const Buffer &cmp) const; // math operations to calculate IVs and keys virtual Buffer operator^(const Buffer &xor_by) const; @@ -71,8 +70,8 @@ public: protected: friend class TunDevice; friend class UDPPacketSource; -// friend class AesIcmCypher; -// friend class KeyDerivation; // + friend class AesIcmCypher; + friend class KeyDerivation; // u_int8_t *buf_; u_int32_t length_; @@ -31,6 +31,7 @@ #include <stdexcept> #include <iostream> #include <string> +#include <cstdio> #include "cypher.h" #include "keyDerivation.h" @@ -82,14 +83,17 @@ AesIcmCypher::AesIcmCypher() : salt_(Buffer(14)) 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 ) { - std::cerr << "Failed to allocate " << GCRYPT_SEC_MEM << "bytes of secure memory: "; - std::cerr << gpg_strerror( err ) << std::endl; - 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; +// } /* Tell Libgcrypt that initialization has completed. */ err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED); @@ -97,14 +101,14 @@ AesIcmCypher::AesIcmCypher() : salt_(Buffer(14)) std::cerr << "Failed to finish the initialization of libgcrypt"; std::cerr << gpg_strerror( err ) << std::endl; return; - } else { - std::cout << "AesIcmCypher::AesIcmCypher: libgcrypt init finished" << std::endl; +// } else { +// std::cout << "AesIcmCypher::AesIcmCypher: libgcrypt init finished" << std::endl; } } gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 ); - std::cout << "Keysize: " << gcry_cipher_get_algo_keylen( GCRY_CIPHER_AES128 ) << std::endl; +// std::cout << "Keysize: " << gcry_cipher_get_algo_keylen( GCRY_CIPHER_AES128 ) << std::endl; } @@ -124,6 +128,9 @@ void AesIcmCypher::setKey(Buffer key) void AesIcmCypher::setSalt(Buffer salt) { +// std::cout << "AesIcmCypher::setSalt" << std::endl; +// salt.printHexDump(); +// std::cout << std::endl; salt_ = salt; } @@ -140,14 +147,26 @@ Buffer AesIcmCypher::getBitStream(u_int32_t length, seq_nr_t seq_nr, sender_id_t // // IV = (k_s * 2^16) XOR (SSRC * 2^64) XOR (i * 2^16) // // sizeof(k_s) = 112 bit, random - Buffer iv(16), seq, sid; - sid = sender_id; - seq = seq_nr; + u_int8_t iv[16]; + std::memset(iv, 0, 16); //initalize iv + + // apply salt: + std::memcpy(&iv[2], salt_.getBuf(), 14); + +// std::cout << "salt:" << std::endl; +// salt_.printHexDump(); +// std::cout << std::endl; + + // apply sender id: + for(u_int8_t index = 0; index < sizeof(sender_id); index++) + iv[index+8] = iv[index+8] ^ ((sender_id>>index) & 0xFF); - iv = (salt_.leftByteShift(2) ^ sid.leftByteShift(8)) ^ sid.leftByteShift(2); + // apply seq nr: + for(u_int8_t index = 0; index < sizeof(seq_nr); index++) + iv[index+2] = iv[index+2] ^ ((seq_nr>>index) & 0xFF); - err = gcry_cipher_setiv( cipher_, iv.getBuf(), 0 ); + err = gcry_cipher_setiv( cipher_, iv, 16 ); if( err ) { std::cerr << "Failed to set cipher IV: " << gpg_strerror( err ) << std::endl; diff --git a/keyDerivation.cpp b/keyDerivation.cpp index 5b7b739..2c8a646 100644 --- a/keyDerivation.cpp +++ b/keyDerivation.cpp @@ -53,14 +53,17 @@ void KeyDerivation::init(Buffer key, Buffer salt) return; } - /* 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; - } + // 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; +// } /* Tell Libgcrypt that initialization has completed. */ err = gcry_control(GCRYCTL_INITIALIZATION_FINISHED); @@ -79,6 +82,8 @@ void KeyDerivation::init(Buffer key, Buffer salt) return; } + salt_ = salt; + initialized_ = true; } void KeyDerivation::setLogKDRate(const uint8_t log_rate) @@ -96,6 +101,11 @@ void KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, u_int8_t tmp_key_id[16]; + if(!initialized_) { + std::cout << "ERROR: keyderivation::generate: keyderivation not initialized yet!" << std::endl; + return; + } + // see at: http://tools.ietf.org/html/rfc3711#section-4.3 // * Let r = index DIV key_derivation_rate (with DIV as defined above). // * Let key_id = <label> || r. @@ -111,7 +121,6 @@ void KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, r = 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; @@ -129,7 +138,8 @@ void KeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key, std::cerr << "Failed to reset cipher: " << gpg_strerror( err ) << std::endl; } - err = gcry_cipher_encrypt( cipher_, key, key.getLength(), 0, 0 ); + err = gcry_cipher_encrypt( cipher_, key, length, 0, 0 ); + if( err ) { std::cerr << "Failed to generate cipher bitstream: " << gpg_strerror( err ) << std::endl; diff --git a/keyDerivation.h b/keyDerivation.h index 7f7fdc2..aae6c3e 100644 --- a/keyDerivation.h +++ b/keyDerivation.h @@ -56,7 +56,7 @@ namespace boost { class KeyDerivation { public: - KeyDerivation() : ld_kdr_(-1), cipher_(NULL) {}; + KeyDerivation() : ld_kdr_(-1), cipher_(NULL), initialized_(false) {}; virtual ~KeyDerivation() {}; void init(Buffer key, Buffer salt); @@ -73,6 +73,7 @@ protected: static const char* MIN_GCRYPT_VERSION; gcry_cipher_hd_t cipher_; + bool initialized_; }; @@ -30,11 +30,14 @@ #include <stdexcept> #include <arpa/inet.h> +#include <cstdio> // for std::memcpy #include "datatypes.h" +#include "authTag.h" #include "packet.h" + Packet::Packet() { has_header_ = false; @@ -165,7 +168,7 @@ payload_type_t Packet::getPayloadType() const return 0; if((!has_auth_tag_ && length_ < sizeof(payload_type_t)) || - (has_auth_tag_ && length_ < (sizeof(payload_type_t) + sizeof(auth_tag_t)))) + (has_auth_tag_ && length_ < (sizeof(payload_type_t) + AUTHTAG_SIZE))) return 0; payload_type_t* payload_type; @@ -173,7 +176,7 @@ payload_type_t Packet::getPayloadType() const if(!has_auth_tag_) payload_type = reinterpret_cast<payload_type_t*>(buf_ + length_ - sizeof(payload_type_t)); else - payload_type = reinterpret_cast<payload_type_t*>(buf_ + length_ - sizeof(payload_type_t) - sizeof(auth_tag_t)); + payload_type = reinterpret_cast<payload_type_t*>(buf_ + length_ - sizeof(payload_type_t) - AUTHTAG_SIZE); return PAYLOAD_TYPE_T_NTOH(*payload_type); } @@ -221,7 +224,7 @@ bool Packet::hasAuthTag() const Packet& Packet::withAuthTag(bool b) { - if(b && length_ >= sizeof(auth_tag_t)) + if(b && length_ >= AUTHTAG_SIZE) has_auth_tag_ = true; else has_auth_tag_ = false; @@ -229,32 +232,37 @@ Packet& Packet::withAuthTag(bool b) return *this; } -auth_tag_t Packet::getAuthTag() const +AuthTag Packet::getAuthTag() const { if(!has_auth_tag_) - return 0; + return AuthTag(0); - if(length_ < sizeof(auth_tag_t)) - return 0; + if(length_ < AUTHTAG_SIZE) + return AuthTag(0); - auth_tag_t* auth_tag; - auth_tag = reinterpret_cast<auth_tag_t*>(buf_ + length_ - sizeof(auth_tag_t)); - return AUTH_TAG_T_NTOH(*auth_tag); + //AuthTag* auth_tag; + //auth_tag = reinterpret_cast<AuthTag*>(buf_ + length_ - AUTHTAG_SIZE); + //return AUTH_TAG_T_NTOH(*auth_tag); + AuthTag auth_tag; + auth_tag = AuthTag(buf_ + length_ - AUTHTAG_SIZE, AUTHTAG_SIZE); + return auth_tag; } -Packet& Packet::addAuthTag(auth_tag_t auth_tag) +Packet& Packet::addAuthTag(AuthTag auth_tag) { if(!has_auth_tag_) { - u_int32_t new_length = length_ + sizeof(auth_tag_t); + u_int32_t new_length = length_ + auth_tag.getLength(); if(new_length > resizeBack(new_length)) return *this; has_auth_tag_ = true; } - auth_tag_t* auth_tag_ptr; - auth_tag_ptr = reinterpret_cast<auth_tag_t*>(buf_ + length_ - sizeof(auth_tag_t)); - *auth_tag_ptr = AUTH_TAG_T_HTON(auth_tag); + + AuthTag* auth_tag_ptr; + auth_tag_ptr = reinterpret_cast<AuthTag*>(buf_ + length_ - auth_tag.getLength()); + std::memcpy(auth_tag_ptr, auth_tag.getBuf(), auth_tag.getLength()); + return *this; } @@ -263,10 +271,11 @@ Packet& Packet::removeAuthTag() if(!has_auth_tag_) return *this; - if(length_ >= sizeof(auth_tag_t)) - resizeBack(length_ - sizeof(auth_tag_t)); + if(length_ >= AUTHTAG_SIZE) + resizeBack(length_ - AUTHTAG_SIZE); has_auth_tag_ = false; return *this; } + @@ -33,6 +33,7 @@ #include "datatypes.h" #include "buffer.h" +#include "authTag.h" class Packet : public Buffer { @@ -58,8 +59,8 @@ public: bool hasAuthTag() const; Packet& withAuthTag(bool b); - auth_tag_t getAuthTag() const; - Packet& addAuthTag(auth_tag_t auth_tag); + AuthTag getAuthTag() const; + Packet& addAuthTag(AuthTag auth_tag); Packet& removeAuthTag(); private: @@ -71,6 +72,8 @@ private: bool has_header_; bool has_payload_type_; bool has_auth_tag_; + // FIXXMEE: remove hardcoded authtag-size + static const u_int32_t AUTHTAG_SIZE = 10; }; #endif |