From 62d31032352f8d857f31d89872fd42b98501e1c3 Mon Sep 17 00:00:00 2001 From: Erwin Nindl Date: Sat, 8 Dec 2007 17:57:31 +0000 Subject: * added AuthTag class * bugfixes in keyderivation, aesicmcypher * removed authtag functins temorarly from anytun.cpp --- Makefile | 4 ++++ anytun.cpp | 36 ++++++++++++++++++++++-------------- authAlgo.cpp | 19 ++++++++++++++----- authAlgo.h | 8 ++++---- authTag.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ authTag.h | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ buffer.cpp | 37 +++++++------------------------------ buffer.h | 7 +++---- cypher.cpp | 51 +++++++++++++++++++++++++++++++++++---------------- keyDerivation.cpp | 30 ++++++++++++++++++++---------- keyDerivation.h | 3 ++- packet.cpp | 43 ++++++++++++++++++++++++++----------------- packet.h | 7 +++++-- 13 files changed, 240 insertions(+), 103 deletions(-) create mode 100644 authTag.cpp create mode 100644 authTag.h diff --git a/Makefile b/Makefile index ae4993f..4cc2469 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/anytun.cpp b/anytun.cpp index 9154dd8..3bf24f9 100644 --- a/anytun.cpp +++ b/anytun.cpp @@ -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(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(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(buf).getBuf(), buf.getLength() ); + gcry_md_final( ctx ); + hmac = Buffer(gcry_md_read( ctx, 0 ), 10); + gcry_md_close( ctx ); + return hmac; } diff --git a/authAlgo.h b/authAlgo.h index 7c7ca6d..e3de813 100644 --- a/authAlgo.h +++ b/authAlgo.h @@ -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 + * + * 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 +#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 + * + * 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 diff --git a/buffer.cpp b/buffer.cpp index a21ebb3..e85500d 100644 --- a/buffer.cpp +++ b/buffer.cpp @@ -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) diff --git a/buffer.h b/buffer.h index 85f539b..a9601fe 100644 --- a/buffer.h +++ b/buffer.h @@ -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_; diff --git a/cypher.cpp b/cypher.cpp index 857566c..ea511ef 100644 --- a/cypher.cpp +++ b/cypher.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #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 =