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/keyDerivation.cpp | 255 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 177 insertions(+), 78 deletions(-) (limited to 'src/keyDerivation.cpp') 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 =