From 7d04626ef28ca5d27bc8515660c58bb135aa8c93 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Tue, 17 Mar 2009 15:53:22 +0000 Subject: added support for configurabel auth tag length --- cmd-option-letters | 4 ++-- src/anytun.cpp | 4 ++-- src/authAlgo.h | 2 ++ src/authAlgoFactory.cpp | 16 ++++++++++++++-- src/authAlgoFactory.h | 1 + src/encryptedPacket.cpp | 22 +++++++++++----------- src/encryptedPacket.h | 4 ++-- src/man/anytun.8.txt | 11 +++++++++-- src/options.cpp | 34 +++++++++++++++++++++++++++++++++- src/options.h | 3 +++ 10 files changed, 79 insertions(+), 22 deletions(-) diff --git a/cmd-option-letters b/cmd-option-letters index 5533d21..340ed83 100644 --- a/cmd-option-letters +++ b/cmd-option-letters @@ -2,7 +2,7 @@ 6: resolv ipv6 only (payload socket) a: auth algo -b: auth tag length (not yet) +b: auth tag length c: cipher d: device name e: role @@ -42,7 +42,7 @@ K: master key L: logging M: remote sync hosts N: -O: anytun 0.2 compat mode +O: anytun 0.2 compat mode // deprecated P: write pid file Q: R: route diff --git a/src/anytun.cpp b/src/anytun.cpp index c19ceb5..99f1560 100644 --- a/src/anytun.cpp +++ b/src/anytun.cpp @@ -149,7 +149,7 @@ void sender(TunDevice* dev, PacketSource* src) std::auto_ptr a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_OUTBOUND) ); PlainPacket plain_packet(MAX_PACKET_LENGTH); - EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH); + EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, gOpt.getAuthTagLength()); u_int16_t mux = gOpt.getMux(); PacketSourceEndpoint emptyEndpoint; @@ -237,7 +237,7 @@ void receiver(TunDevice* dev, PacketSource* src) std::auto_ptr c(CipherFactory::create(gOpt.getCipher(), KD_INBOUND, gOpt.getAnytun02Compat())); std::auto_ptr a(AuthAlgoFactory::create(gOpt.getAuthAlgo(), KD_INBOUND)); - EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH); + EncryptedPacket encrypted_packet(MAX_PACKET_LENGTH, gOpt.getAuthTagLength()); PlainPacket plain_packet(MAX_PACKET_LENGTH); while(1) { diff --git a/src/authAlgo.h b/src/authAlgo.h index cca706d..c446853 100644 --- a/src/authAlgo.h +++ b/src/authAlgo.h @@ -75,6 +75,8 @@ class NullAuthAlgo : public AuthAlgo public: void generate(KeyDerivation& kd, EncryptedPacket& packet); bool checkTag(KeyDerivation& kd, EncryptedPacket& packet); + + static const u_int32_t DIGEST_LENGTH = 0; }; #ifndef NO_CRYPT diff --git a/src/authAlgoFactory.cpp b/src/authAlgoFactory.cpp index 8fa16fc..c284f34 100644 --- a/src/authAlgoFactory.cpp +++ b/src/authAlgoFactory.cpp @@ -38,13 +38,25 @@ AuthAlgo* AuthAlgoFactory::create(std::string const& type, kd_dir_t dir) { - if( type == "null" ) + if(type == "null") return new NullAuthAlgo(); #ifndef NO_CRYPT - else if( type == "sha1" ) + else if(type == "sha1") return new Sha1AuthAlgo(dir); #endif else throw std::invalid_argument("auth algo not available"); } +u_int32_t AuthAlgoFactory::getDigestLength(std::string const& type) +{ + if(type == "null") + return NullAuthAlgo::DIGEST_LENGTH; +#ifndef NO_CRYPT + else if(type == "sha1") + return Sha1AuthAlgo::DIGEST_LENGTH; +#endif + else + throw std::invalid_argument("auth algo not available"); +} + diff --git a/src/authAlgoFactory.h b/src/authAlgoFactory.h index ee38248..2dca567 100644 --- a/src/authAlgoFactory.h +++ b/src/authAlgoFactory.h @@ -41,6 +41,7 @@ class AuthAlgoFactory { public: static AuthAlgo* create(std::string const& type, kd_dir_t dir); + static u_int32_t getDigestLength(std::string const& type); private: AuthAlgoFactory(); diff --git a/src/encryptedPacket.cpp b/src/encryptedPacket.cpp index c18551c..a5aec86 100644 --- a/src/encryptedPacket.cpp +++ b/src/encryptedPacket.cpp @@ -39,8 +39,8 @@ #include "log.h" #include "anytunError.h" -EncryptedPacket::EncryptedPacket(u_int32_t payload_length, bool allow_realloc) - : Buffer(payload_length + sizeof(struct HeaderStruct), allow_realloc) +EncryptedPacket::EncryptedPacket(u_int32_t payload_length, u_int32_t auth_tag_length, bool allow_realloc) + : Buffer(payload_length + sizeof(struct HeaderStruct), allow_realloc), auth_tag_length_(auth_tag_length) { header_ = reinterpret_cast(buf_); payload_ = buf_ + sizeof(struct HeaderStruct); @@ -118,7 +118,7 @@ u_int32_t EncryptedPacket::getPayloadLength() const if(!auth_tag_) return (length_ > sizeof(struct HeaderStruct)) ? (length_ - sizeof(struct HeaderStruct)) : 0; - return (length_ > (sizeof(struct HeaderStruct) + AUTHTAG_SIZE)) ? (length_ - sizeof(struct HeaderStruct) - AUTHTAG_SIZE) : 0; + return (length_ > (sizeof(struct HeaderStruct) + auth_tag_length_)) ? (length_ - sizeof(struct HeaderStruct) - auth_tag_length_) : 0; } void EncryptedPacket::setPayloadLength(u_int32_t payload_length) @@ -143,11 +143,11 @@ void EncryptedPacket::reinit() if(auth_tag_) { - if(length_ < (sizeof(struct HeaderStruct) + AUTHTAG_SIZE)) { + if(length_ < (sizeof(struct HeaderStruct) + auth_tag_length_)) { auth_tag_ = NULL; AnytunError::throwErr() << "auth-tag can't be enabled, buffer is too small"; } - auth_tag_ = buf_ + length_ - AUTHTAG_SIZE; + auth_tag_ = buf_ + length_ - auth_tag_length_; } } @@ -169,7 +169,7 @@ u_int32_t EncryptedPacket::getAuthenticatedPortionLength() if(!auth_tag_) return length_; - return (length_ > AUTHTAG_SIZE) ? (length_ - AUTHTAG_SIZE) : 0; + return (length_ > auth_tag_length_) ? (length_ - auth_tag_length_) : 0; } void EncryptedPacket::withAuthTag(bool b) @@ -179,10 +179,10 @@ void EncryptedPacket::withAuthTag(bool b) if(b) { - if(length_ < (sizeof(struct HeaderStruct) + AUTHTAG_SIZE)) + if(length_ < (sizeof(struct HeaderStruct) + auth_tag_length_)) AnytunError::throwErr() << "auth-tag can't be enabled, buffer is too small"; - auth_tag_ = buf_ + length_ - AUTHTAG_SIZE; + auth_tag_ = buf_ + length_ - auth_tag_length_; } else auth_tag_ = NULL; @@ -194,7 +194,7 @@ void EncryptedPacket::addAuthTag() return; auth_tag_ = buf_; // will be set to the correct value @ reinit - setLength(length_ + AUTHTAG_SIZE); + setLength(length_ + auth_tag_length_); if(auth_tag_ == buf_) // reinit was not called by setLength reinit(); } @@ -205,7 +205,7 @@ void EncryptedPacket::removeAuthTag() return; auth_tag_ = NULL; - setLength(length_ - AUTHTAG_SIZE); + setLength(length_ - auth_tag_length_); } u_int8_t* EncryptedPacket::getAuthTag() @@ -216,7 +216,7 @@ u_int8_t* EncryptedPacket::getAuthTag() u_int32_t EncryptedPacket::getAuthTagLength() { if(auth_tag_) - return AUTHTAG_SIZE; + return auth_tag_length_; return 0; } diff --git a/src/encryptedPacket.h b/src/encryptedPacket.h index 4f64022..618fa44 100644 --- a/src/encryptedPacket.h +++ b/src/encryptedPacket.h @@ -45,7 +45,7 @@ public: * @param the length of the payload * @param allow reallocation of buffer */ - EncryptedPacket(u_int32_t payload_length, bool allow_realloc = false); + EncryptedPacket(u_int32_t payload_length, u_int32_t auth_tag_length, bool allow_realloc = false); /** * Packet destructor @@ -152,7 +152,7 @@ private: struct HeaderStruct* header_; u_int8_t * payload_; u_int8_t * auth_tag_; - static const u_int32_t AUTHTAG_SIZE = 10; // TODO: hardcoded size + u_int32_t auth_tag_length_; }; #endif diff --git a/src/man/anytun.8.txt b/src/man/anytun.8.txt index 05a650c..fa30441 100644 --- a/src/man/anytun.8.txt +++ b/src/man/anytun.8.txt @@ -41,6 +41,7 @@ SYNOPSIS [ *-A|--salt* ] [ *-c|--cipher* ] [ *-a|--auth-algo* ] +[ *-b|--auth-tag-length* ] DESCRIPTION ----------- @@ -362,8 +363,14 @@ Possible values: * *null* - no message authentication * *sha1* - HMAC-SHA1, default value -If HMAC-SHA1 is used, the packet length is increased by -10 bytes. These 10 bytes contain the authentication data. +If HMAC-SHA1 is used, the packet length is increased. The additional bytes +contain the authentication data. see *-b|--auth-tag-length* for more info. + +-b|--auth-tag-length +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The number of bytes to use for the auth tag. This value defaults to 10 bytes +unless the *null* auth algo is used in which case it defaults to 0. EXAMPLES diff --git a/src/options.cpp b/src/options.cpp index e58278a..94e3c44 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -38,6 +38,7 @@ #include "datatypes.h" #include "options.h" #include "log.h" +#include "authAlgoFactory.h" std::ostream& operator<<(std::ostream& stream, syntax_error const& error) { @@ -181,10 +182,12 @@ Options::Options() : key_(u_int32_t(0)), salt_(u_int32_t(0)) #ifndef NO_CRYPT cipher_ = "aes-ctr"; auth_algo_ = "sha1"; + auth_tag_length_ = 10; kd_prf_ = "aes-ctr"; #else cipher_ = "null"; auth_algo_ = "null"; + auth_tag_length_ = 0; kd_prf_ = "null"; #endif role_ = ROLE_LEFT; @@ -412,6 +415,7 @@ bool Options::parse(int argc, char* argv[]) #ifndef NO_CRYPT PARSE_SCALAR_PARAM("-c","--cipher", cipher_) PARSE_SCALAR_PARAM("-a","--auth-algo", auth_algo_) + PARSE_SCALAR_PARAM("-b","--auth-tag-length", auth_tag_length_) #endif #endif @@ -443,6 +447,19 @@ void Options::parse_post() kd_prf_ = "null"; if((cipher_ != "null" || auth_algo_ != "null") && kd_prf_ == "null") cLog.msg(Log::PRIO_WARNING) << "using NULL key derivation with encryption and or authentication enabled!"; + + +#if defined(ANYTUN_OPTIONS) + u_int32_t tag_len_max = AuthAlgoFactory::getDigestLength(auth_algo_); + if(!tag_len_max) auth_tag_length_ = 0; + else if(tag_len_max < auth_tag_length_) { + cLog.msg(Log::PRIO_WARNING) << auth_algo_ << " auth algo can't generate tags of length " << auth_tag_length_ << ", using maximum tag length(" << tag_len_max << ")"; + auth_tag_length_ = tag_len_max; + } +#endif + + if(anytun02_compat_) + cLog.msg(Log::PRIO_WARNING) << "--anytun02-compat is deprecated and very likly to be removed by the next release"; if(dev_name_ == "" && dev_type_ == "") dev_type_ = "tun"; @@ -528,7 +545,6 @@ void Options::printUsage() #ifndef NO_CRYPT std::cout << " [-k|--kd-prf] key derivation pseudo random function" << std::endl; std::cout << " [-e|--role] left (alice) or right (bob)" << std::endl; - std::cout << " [-O|--anytun02-compat] enable compatiblity mode for anytun 0.2.x and prior" << std::endl; #ifndef NO_PASSPHRASE std::cout << " [-E|--passphrase] a passprhase to generate master key and salt from" << std::endl; #endif @@ -542,6 +558,7 @@ void Options::printUsage() #ifndef NO_CRYPT std::cout << " [-c|--cipher] payload encryption algorithm" << std::endl; std::cout << " [-a|--auth-algo] message authentication algorithm" << std::endl; + std::cout << " [-b|--auth-tag-length] length of the auth tag" << std::endl; #endif #endif @@ -602,6 +619,7 @@ void Options::printOptions() std::cout << std::endl; std::cout << "cipher = '" << cipher_ << "'" << std::endl; std::cout << "auth_algo = '" << auth_algo_ << "'" << std::endl; + std::cout << "auth_tag_length = " << auth_tag_length_ << std::endl; std::cout << "kd_prf = '" << kd_prf_ << "'" << std::endl; std::cout << "role = "; switch(role_) { @@ -971,6 +989,20 @@ Options& Options::setAuthAlgo(std::string a) return *this; } +u_int32_t Options::getAuthTagLength() +{ + ReadersLock lock(mutex); + return auth_tag_length_; +} + +Options& Options::setAuthTagLength(u_int32_t a) +{ + WritersLock lock(mutex); + auth_tag_length_ = a; + return *this; +} + + std::string Options::getKdPrf() { ReadersLock lock(mutex); diff --git a/src/options.h b/src/options.h index 480d1c7..71229cc 100644 --- a/src/options.h +++ b/src/options.h @@ -149,6 +149,8 @@ public: Options& setCipher(std::string c); std::string getAuthAlgo(); Options& setAuthAlgo(std::string a); + u_int32_t getAuthTagLength(); + Options& setAuthTagLength(u_int32_t a); std::string getKdPrf(); Options& setKdPrf(std::string k); role_t getRole(); @@ -212,6 +214,7 @@ private: std::string cipher_; std::string auth_algo_; + u_int32_t auth_tag_length_; std::string kd_prf_; role_t role_; bool anytun02_compat_; -- cgit v1.2.3