From bb9f6547ad858b11fb29c7f1e23eddb1573bff1c Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Thu, 15 Jan 2009 01:00:19 +0000 Subject: ported uanytun key derivation to anytun no key store until now (ld_kdr gets ignored) no multi kd until now (WritersLock instead of ReadersLock @ generate) finally removed creepy mpi class --- src/Makefile | 2 - src/anytun.cpp | 10 +- src/authAlgo.cpp | 12 +-- src/authAlgo.h | 12 +-- src/cipher.cpp | 71 ++++++-------- src/cipher.h | 20 ++-- src/cryptinit.hpp | 37 +++++++- src/keyDerivation.cpp | 255 +++++++++++++++++++++++++++++++++++--------------- src/keyDerivation.h | 71 +++++++++++--- src/mpi.cpp | 203 ---------------------------------------- src/mpi.h | 84 ----------------- src/threadUtils.hpp | 5 + 12 files changed, 334 insertions(+), 448 deletions(-) delete mode 100644 src/mpi.cpp delete mode 100644 src/mpi.h diff --git a/src/Makefile b/src/Makefile index 5dae026..64dd5b8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -55,7 +55,6 @@ OBJS = tunDevice.o \ cipher.o \ authAlgo.o \ keyDerivation.o \ - mpi.o \ cipherFactory.o \ authAlgoFactory.o \ keyDerivationFactory.o \ @@ -87,7 +86,6 @@ ANYCTROBJS = signalController.o \ ANYCONFOBJS = log.o \ buffer.o \ keyDerivation.o \ - mpi.o \ keyDerivationFactory.o \ networkAddress.o \ networkPrefix.o \ diff --git a/src/anytun.cpp b/src/anytun.cpp index e46731a..c0cb03b 100644 --- a/src/anytun.cpp +++ b/src/anytun.cpp @@ -169,13 +169,13 @@ void sender(void* p) } // encrypt packet - c->encrypt(conn.kd_, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux); + c->encrypt(conn.kd_, KD_OUTBOUND, plain_packet, encrypted_packet, conn.seq_nr_, gOpt.getSenderId(), mux); encrypted_packet.setHeader(conn.seq_nr_, gOpt.getSenderId(), mux); conn.seq_nr_++; // add authentication tag - a->generate(conn.kd_, encrypted_packet); + a->generate(conn.kd_, KD_OUTBOUND, encrypted_packet); try { @@ -276,7 +276,7 @@ void receiver(void* p) ConnectionParam & conn = cit->second; // check whether auth tag is ok or not - if(!a->checkTag(conn.kd_, encrypted_packet)) { + if(!a->checkTag(conn.kd_, KD_INBOUND, encrypted_packet)) { cLog.msg(Log::PRIO_NOTICE) << "wrong Authentication Tag!" << std::endl; continue; } @@ -302,7 +302,7 @@ void receiver(void* p) } // decrypt packet - c->decrypt(conn.kd_, encrypted_packet, plain_packet); + c->decrypt(conn.kd_, KD_INBOUND, encrypted_packet, plain_packet); // check payload_type if((param->dev.getType() == TYPE_TUN && plain_packet.getPayloadType() != PAYLOAD_TYPE_TUN4 && @@ -418,9 +418,11 @@ int main(int argc, char* argv[]) ThreadParam p(dev, *src, *(new OptionConnectTo())); #ifndef NOCRYPT +#ifndef USE_SSL_CRYPTO // this must be called before any other libgcrypt call if(!initLibGCrypt()) return -1; +#endif #endif boost::thread senderThread(boost::bind(sender,&p)); diff --git a/src/authAlgo.cpp b/src/authAlgo.cpp index 669308b..a0b9193 100644 --- a/src/authAlgo.cpp +++ b/src/authAlgo.cpp @@ -38,11 +38,11 @@ #include //****** NullAuthAlgo ****** -void NullAuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet) +void NullAuthAlgo::generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) { } -bool NullAuthAlgo::checkTag(KeyDerivation& kd, EncryptedPacket& packet) +bool NullAuthAlgo::checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) { return true; } @@ -74,13 +74,13 @@ Sha1AuthAlgo::~Sha1AuthAlgo() #endif } -void Sha1AuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet) +void Sha1AuthAlgo::generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) { packet.addAuthTag(); if(!packet.getAuthTagLength()) return; - bool result = kd.generate(LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_); + bool result = kd.generate(dir, LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_); if(result) { // a new key got generated #ifndef USE_SSL_CRYPTO gcry_error_t err = gcry_md_setkey(handle_, key_.getBuf(), key_.getLength()); @@ -118,13 +118,13 @@ void Sha1AuthAlgo::generate(KeyDerivation& kd, EncryptedPacket& packet) std::memcpy(&tag[packet.getAuthTagLength() - length], &hmac[DIGEST_LENGTH - length], length); } -bool Sha1AuthAlgo::checkTag(KeyDerivation& kd, EncryptedPacket& packet) +bool Sha1AuthAlgo::checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) { packet.withAuthTag(true); if(!packet.getAuthTagLength()) return true; - bool result = kd.generate(LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_); + bool result = kd.generate(dir, LABEL_SATP_MSG_AUTH, packet.getSeqNr(), key_); if(result) { // a new key got generated #ifndef USE_SSL_CRYPTO gcry_error_t err = gcry_md_setkey(handle_, key_.getBuf(), key_.getLength()); diff --git a/src/authAlgo.h b/src/authAlgo.h index be8d158..5728426 100644 --- a/src/authAlgo.h +++ b/src/authAlgo.h @@ -55,13 +55,13 @@ public: * generate the mac * @param packet the packet to be authenticated */ - virtual void generate(KeyDerivation& kd, EncryptedPacket& packet) = 0; + virtual void generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) = 0; /** * check the mac * @param packet the packet to be authenticated */ - virtual bool checkTag(KeyDerivation& kd, EncryptedPacket& packet) = 0; + virtual bool checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet) = 0; }; //****** NullAuthAlgo ****** @@ -69,8 +69,8 @@ public: class NullAuthAlgo : public AuthAlgo { public: - void generate(KeyDerivation& kd, EncryptedPacket& packet); - bool checkTag(KeyDerivation& kd, EncryptedPacket& packet); + void generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet); + bool checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet); }; #ifndef NOCRYPT @@ -83,8 +83,8 @@ public: Sha1AuthAlgo(); ~Sha1AuthAlgo(); - void generate(KeyDerivation& kd, EncryptedPacket& packet); - bool checkTag(KeyDerivation& kd, EncryptedPacket& packet); + void generate(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet); + bool checkTag(KeyDerivation& kd, kd_dir dir, EncryptedPacket& packet); static const u_int32_t DIGEST_LENGTH = 20; diff --git a/src/cipher.cpp b/src/cipher.cpp index 8db6256..3d86fc5 100644 --- a/src/cipher.cpp +++ b/src/cipher.cpp @@ -40,31 +40,31 @@ #include "cipher.h" #include "log.h" -void Cipher::encrypt(KeyDerivation& kd, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +void Cipher::encrypt(KeyDerivation& kd, kd_dir dir, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { - u_int32_t len = cipher(kd, in, in.getLength(), out.getPayload(), out.getPayloadLength(), seq_nr, sender_id, mux); + u_int32_t len = cipher(kd, dir, in, in.getLength(), out.getPayload(), out.getPayloadLength(), seq_nr, sender_id, mux); out.setSenderId(sender_id); out.setSeqNr(seq_nr); out.setMux(mux); out.setPayloadLength(len); } -void Cipher::decrypt(KeyDerivation& kd, EncryptedPacket & in, PlainPacket & out) +void Cipher::decrypt(KeyDerivation& kd, kd_dir dir, EncryptedPacket & in, PlainPacket & out) { - u_int32_t len = decipher(kd, in.getPayload() , in.getPayloadLength(), out, out.getLength(), in.getSeqNr(), in.getSenderId(), in.getMux()); + u_int32_t len = decipher(kd, dir, in.getPayload() , in.getPayloadLength(), out, out.getLength(), in.getSeqNr(), in.getSenderId(), in.getMux()); out.setLength(len); } //******* NullCipher ******* -u_int32_t NullCipher::cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +u_int32_t NullCipher::cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { std::memcpy(out, in, (ilen < olen) ? ilen : olen); return (ilen < olen) ? ilen : olen; } -u_int32_t NullCipher::decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +u_int32_t NullCipher::decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { std::memcpy(out, in, (ilen < olen) ? ilen : olen); return (ilen < olen) ? ilen : olen; @@ -118,21 +118,21 @@ AesIcmCipher::~AesIcmCipher() #endif } -u_int32_t AesIcmCipher::cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +u_int32_t AesIcmCipher::cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { - calc(kd, in, ilen, out, olen, seq_nr, sender_id, mux); + calc(kd, dir, in, ilen, out, olen, seq_nr, sender_id, mux); return (ilen < olen) ? ilen : olen; } -u_int32_t AesIcmCipher::decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +u_int32_t AesIcmCipher::decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { - calc(kd, in, ilen, out, olen, seq_nr, sender_id, mux); + calc(kd, dir, in, ilen, out, olen, seq_nr, sender_id, mux); return (ilen < olen) ? ilen : olen; } -void AesIcmCipher::calc_ctr(KeyDerivation& kd, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +void AesIcmCipher::calcCtr(KeyDerivation& kd, kd_dir dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { - kd.generate(LABEL_SATP_SALT, seq_nr, salt_); + kd.generate(dir, LABEL_SATP_SALT, seq_nr, salt_); #ifdef ANYTUN_02_COMPAT if(!salt_[int32_t(0)]) @@ -148,47 +148,36 @@ void AesIcmCipher::calc_ctr(KeyDerivation& kd, seq_nr_t seq_nr, sender_id_t send return; } -void AesIcmCipher::calc(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +void AesIcmCipher::calc(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { #ifndef USE_SSL_CRYPTO if(!handle_) return; #endif - bool result = kd.generate(LABEL_SATP_ENCRYPTION, seq_nr, key_); - if(result) { // a new key got generated + kd.generate(dir, LABEL_SATP_ENCRYPTION, seq_nr, key_); #ifdef USE_SSL_CRYPTO - int ret = AES_set_encrypt_key(key_.getBuf(), key_.getLength()*8, &aes_key_); - if(ret) { - char buf[STERROR_TEXT_MAX]; - buf[0] = 0; - cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher ssl key (code: " << ret << ")"; - return; - } + int ret = AES_set_encrypt_key(key_.getBuf(), key_.getLength()*8, &aes_key_); + if(ret) { + char buf[STERROR_TEXT_MAX]; + buf[0] = 0; + cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher ssl key (code: " << ret << ")"; + return; + } #else - gcry_error_t err = gcry_cipher_setkey(handle_, key_.getBuf(), key_.getLength()); - if(err) { - char buf[STERROR_TEXT_MAX]; - buf[0] = 0; - cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); - return; - } - } // no new key got generated - else { - gcry_error_t err = gcry_cipher_reset(handle_); - if(err) { - char buf[STERROR_TEXT_MAX]; - buf[0] = 0; - cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to reset cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); - return; - } -#endif + gcry_error_t err = gcry_cipher_setkey(handle_, key_.getBuf(), key_.getLength()); + if(err) { + char buf[STERROR_TEXT_MAX]; + buf[0] = 0; + cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); + return; } +#endif - calc_ctr(kd, seq_nr, sender_id, mux); + calcCtr(kd, dir, seq_nr, sender_id, mux); #ifndef USE_SSL_CRYPTO - gcry_error_t err = gcry_cipher_setctr(handle_, ctr_.buf_, CTR_LENGTH); + err = gcry_cipher_setctr(handle_, ctr_.buf_, CTR_LENGTH); if(err) { char buf[STERROR_TEXT_MAX]; buf[0] = 0; diff --git a/src/cipher.h b/src/cipher.h index f930bc4..30bbeed 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -51,12 +51,12 @@ class Cipher public: virtual ~Cipher() {}; - void encrypt(KeyDerivation& kd, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); - void decrypt(KeyDerivation& kd, EncryptedPacket & in, PlainPacket & out); + void encrypt(KeyDerivation& kd, kd_dir dir, PlainPacket & in, EncryptedPacket & out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); + void decrypt(KeyDerivation& kd, kd_dir dir, EncryptedPacket & in, PlainPacket & out); protected: - virtual u_int32_t cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0; - virtual u_int32_t decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0; + virtual u_int32_t cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0; + virtual u_int32_t decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) = 0; }; //****** NullCipher ****** @@ -64,8 +64,8 @@ protected: class NullCipher : public Cipher { protected: - u_int32_t cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); - u_int32_t decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); + u_int32_t cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); + u_int32_t decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); }; #ifndef NOCRYPT @@ -83,14 +83,14 @@ public: static const u_int16_t SALT_LENGTH = 14; protected: - u_int32_t cipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); - u_int32_t decipher(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); + u_int32_t cipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); + u_int32_t decipher(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); private: void init(u_int16_t key_length = DEFAULT_KEY_LENGTH); - void calc_ctr(KeyDerivation& kd, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); - void calc(KeyDerivation& kd, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); + void calcCtr(KeyDerivation& kd, kd_dir dir, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); + void calc(KeyDerivation& kd, kd_dir dir, u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); #ifndef USE_SSL_CRYPTO gcry_cipher_hd_t handle_; diff --git a/src/cryptinit.hpp b/src/cryptinit.hpp index 567a374..dd878cd 100644 --- a/src/cryptinit.hpp +++ b/src/cryptinit.hpp @@ -1,7 +1,39 @@ +/* + * 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-2008 Othmar Gsenger, Erwin Nindl, + * Christian Pointner + * + * This file is part of Anytun. + * + * Anytun is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 3 as + * published by the Free Software Foundation. + * + * Anytun 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 anytun. If not, see . + */ + #ifndef _CRYPTINIT_HPP #define _CRYPTINIT_HPP -#ifndef NOCRYPT +#ifndef NOCRYPT +#ifndef USE_SSL_CRYPTO // boost thread callbacks for libgcrypt #if defined(BOOST_HAS_PTHREADS) @@ -76,7 +108,8 @@ bool initLibGCrypt() cLog.msg(Log::PRIO_NOTICE) << "initLibGCrypt: libgcrypt init finished"; return true; } - #endif #endif +#endif + diff --git a/src/keyDerivation.cpp b/src/keyDerivation.cpp index 0bf74a7..459d6c9 100644 --- a/src/keyDerivation.cpp +++ b/src/keyDerivation.cpp @@ -34,141 +34,240 @@ #include "keyDerivation.h" #include "threadUtils.hpp" #include "datatypes.h" +#include "endian.h" #include #include +#include #include -#ifndef NOCRYPT -#include -#include "mpi.h" -#endif - -void KeyDerivation::setLogKDRate(const u_int8_t log_rate) +void KeyDerivation::setLogKDRate(const int8_t log_rate) { - Lock lock(mutex_); - if( log_rate < 49 ) - ld_kdr_ = log_rate; + WritersLock lock(mutex_); + ld_kdr_ = log_rate; + if(ld_kdr_ > (int8_t)(sizeof(seq_nr_t) * 8)) + ld_kdr_ = sizeof(seq_nr_t) * 8; } //****** NullKeyDerivation ****** -bool NullKeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key) +bool NullKeyDerivation::generate(kd_dir dir, satp_prf_label label, seq_nr_t seq_nr, Buffer& key) { - for(u_int32_t i=0; i < key.getLength(); ++i) key[i] = 0; + std::memset(key.getBuf(), 0, key.getLength()); return true; } #ifndef NOCRYPT //****** AesIcmKeyDerivation ****** +AesIcmKeyDerivation::AesIcmKeyDerivation() : KeyDerivation(DEFAULT_KEY_LENGTH) +{ +#ifndef USE_SSL_CRYPTO + handle_ = NULL; +#endif +} + +AesIcmKeyDerivation::AesIcmKeyDerivation(u_int16_t key_length) : KeyDerivation(key_length) +{ +#ifndef USE_SSL_CRYPTO + handle_ = NULL; +#endif +} + AesIcmKeyDerivation::~AesIcmKeyDerivation() { - Lock lock(mutex_); - if(cipher_) - gcry_cipher_close( cipher_ ); + WritersLock lock(mutex_); +#ifndef USE_SSL_CRYPTO + if(handle_) + gcry_cipher_close(handle_); +#endif +} + +void AesIcmKeyDerivation::init(Buffer key, Buffer salt) +{ + WritersLock lock(mutex_); + + master_salt_ = SyncBuffer(salt); + master_key_ = SyncBuffer(key); + + updateMasterKey(); } void AesIcmKeyDerivation::updateMasterKey() { - if(!cipher_) + if(master_key_.getLength()*8 != key_length_) { + char buf[STERROR_TEXT_MAX]; + buf[0] = 0; + cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::updateMasterKey: key lengths don't match"; return; + } - gcry_error_t err = gcry_cipher_setkey( cipher_, master_key_.getBuf(), master_key_.getLength() ); - if( err ) { + if(master_salt_.getLength() != SALT_LENGTH) { char buf[STERROR_TEXT_MAX]; buf[0] = 0; - cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); + cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::updateMasterKey: salt lengths don't match"; + return; } -} -void AesIcmKeyDerivation::init(Buffer key, Buffer salt) -{ - Lock lock(mutex_); - if(cipher_) - gcry_cipher_close( cipher_ ); +#ifndef USE_SSL_CRYPTO + int algo; + switch(key_length_) { + case 128: algo = GCRY_CIPHER_AES128; break; + case 192: algo = GCRY_CIPHER_AES192; break; + case 256: algo = GCRY_CIPHER_AES256; break; + default: { + char buf[STERROR_TEXT_MAX]; + buf[0] = 0; + cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::updateMasterKey: cipher key length of " << key_length_ << " Bits is not supported"; + return; + } + } + + if(handle_) + gcry_cipher_close(handle_); + + gcry_error_t err = gcry_cipher_open(&handle_, algo, GCRY_CIPHER_MODE_CTR, 0); + if(err) { + char buf[STERROR_TEXT_MAX]; + buf[0] = 0; + cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to open cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); + return; + } - // TODO: hardcoded size - gcry_error_t err = gcry_cipher_open( &cipher_, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0 ); - if( err ) { + err = gcry_cipher_setkey(handle_, master_key_.getBuf(), master_key_.getLength()); + if(err) { char buf[STERROR_TEXT_MAX]; buf[0] = 0; - cLog.msg(Log::PRIO_ERR) << "KeyDerivation::init: Failed to open cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); + cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to set cipher key: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); return; } - - master_salt_ = SyncBuffer(salt); - master_key_ = SyncBuffer(key); +#else + int ret = AES_set_encrypt_key(master_key_.getBuf(), master_key_.getLength()*8, &aes_key_); + if(ret) { + char buf[STERROR_TEXT_MAX]; + buf[0] = 0; + cLog.msg(Log::PRIO_ERR) << "KeyDerivation::updateMasterKey: Failed to set ssl key (code: " << ret << ")"; + return; + } +#endif +} - updateMasterKey(); +std::string AesIcmKeyDerivation::printType() +{ + ReadersLock lock(mutex_); + + std::stringstream sstr; + sstr << "AesIcm" << key_length_ << "KeyDerivation"; + return sstr.str(); } -bool AesIcmKeyDerivation::generate(satp_prf_label label, seq_nr_t seq_nr, Buffer& key) +bool AesIcmKeyDerivation::calcCtr(kd_dir dir, seq_nr_t* r, satp_prf_label label, seq_nr_t seq_nr) { - Lock lock(mutex_); - if(!cipher_) - { - cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: cipher not opened"; - return false; - } + *r = 0; + if(ld_kdr_ >= 0) + *r = seq_nr >> ld_kdr_; - gcry_error_t err = gcry_cipher_reset( cipher_ ); - if( err ) { +// TODO: determine whether to generate a key or not +// if(key_store_[dir][label].key_.getBuf() && key_store_[dir][label].r_ == *r) { +// if(!(*r) || (seq_nr % (*r))) +// return false; +// } + + if(master_salt_.getLength() != SALT_LENGTH) { char buf[STERROR_TEXT_MAX]; buf[0] = 0; - cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to reset cipher: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX); + cLog.msg(Log::PRIO_CRIT) << "KeyDerivation::calcCtr: salt lengths don't match"; + return false; } + memcpy(ctr_.salt_.buf_, master_salt_.getBuf(), SALT_LENGTH); + ctr_.salt_.zero_ = 0; + ctr_.params_.label_ ^= label; + ctr_.params_.r_ ^= SEQ_NR_T_HTON(*r); - // 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 =