summaryrefslogtreecommitdiff
path: root/src/keyDerivation.cpp
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2009-01-15 01:00:19 +0000
committerChristian Pointner <equinox@anytun.org>2009-01-15 01:00:19 +0000
commitbb9f6547ad858b11fb29c7f1e23eddb1573bff1c (patch)
tree39eb1d0f0bc4e20dadd03518b0af5a689a639031 /src/keyDerivation.cpp
parentported authAlgo from uanytun to anytun (diff)
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
Diffstat (limited to 'src/keyDerivation.cpp')
-rw-r--r--src/keyDerivation.cpp255
1 files changed, 177 insertions, 78 deletions
diff --git a/src/keyDerivation.cpp b/src/keyDerivation.cpp
index 0bf74a7..459d6c9 100644
--- a/src/keyDerivation.cpp
+++ b/src/keyDerivation.cpp
@@ -34,142 +34,241 @@
#include "keyDerivation.h"
#include "threadUtils.hpp"
#include "datatypes.h"
+#include "endian.h"
#include <stdexcept>
#include <iostream>
+#include <sstream>
#include <string>
-#ifndef NOCRYPT
-#include <gcrypt.h>
-#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 = <label> || r.
- // * Let x = key_id XOR master_salt, where key_id and master_salt are
- // aligned so that their least significant bits agree (right-
- // alignment).
- //
-
- Mpi r(48); // ld(kdr) <= 48
- if( ld_kdr_ == -1 ) // means key_derivation_rate = 0
- r = 0; // TODO: no new key should be generated if r == 0, except it is the first time
- else
- {
- Mpi seq(32);
- seq = seq_nr;
- Mpi rate(48);
- rate = 1;
- rate = rate.mul2exp(ld_kdr_);
- r = seq / rate;
- }
- // TODO: generate key only if index % r == 0, except it is the first time
+ return true;
+}
+
+bool AesIcmKeyDerivation::generate(kd_dir dir, satp_prf_label label, seq_nr_t seq_nr, Buffer& key)
+{
+// ReadersLock lock(mutex_);
+ WritersLock lock(mutex_);
- Mpi key_id(128); // TODO: hardcoded size
- Mpi l(128); // TODO: hardcoded size
- l = label;
- key_id = l.mul2exp(48) + r;
+ seq_nr_t r;
+ calcCtr(dir, &r, label, seq_nr);
+// TODO: return stored key
+// bool result = calcCtr(dir, &r, label, seq_nr);
+// if(!result) {
+// if(len > kd->key_store_[dir][label].key_.length_) {
+// log_printf(WARNING, "stored (old) key for label 0x%02X is too short, filling with zeros", label);
+// memset(key, 0, len);
+// len = kd->key_store_[dir][label].key_.length_;
+// }
+// memcpy(key, kd->key_store_[dir][label].key_.buf_, len);
+// return false;
+// }
- Mpi salt(master_salt_.getBuf(), master_salt_.getLength());
- Mpi x(128); // TODO: hardcoded size
- x = key_id ^ salt;
- size_t written;
- u_int8_t *ctr_buf = x.mul2exp(16).getNewBuf(&written); // TODO: hardcoded size
- err = gcry_cipher_setctr( cipher_ , ctr_buf, written );
- delete[] ctr_buf;
+#ifndef USE_SSL_CRYPTO
+ gcry_error_t err = gcry_cipher_reset(handle_);
+ if(err) {
+ 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);
+ }
- if( err ) {
+ err = gcry_cipher_setctr(handle_, ctr_.buf_, CTR_LENGTH);
+ if(err) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to set CTR: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
return false;
}
- for(u_int32_t i=0; i < key.getLength(); ++i) key[i] = 0;
- err = gcry_cipher_encrypt( cipher_, key, key.getLength(), NULL, 0);
- if( err ) {
+ std::memset(key.getBuf(), 0, key.getLength());
+ err = gcry_cipher_encrypt(handle_, key, key.getLength(), NULL, 0);
+ if(err) {
char buf[STERROR_TEXT_MAX];
buf[0] = 0;
cLog.msg(Log::PRIO_ERR) << "KeyDerivation::generate: Failed to generate cipher bitstream: " << gpg_strerror_r(err, buf, STERROR_TEXT_MAX);
}
return true;
+#else
+ if(CTR_LENGTH != AES_BLOCK_SIZE) {
+ char buf[STERROR_TEXT_MAX];
+ buf[0] = 0;
+ cLog.msg(Log::PRIO_ERR) << "AesIcmCipher: Failed to set cipher CTR: size don't fits";
+ return false;
+ }
+ u_int32_t num = 0;
+ std::memset(ecount_buf_, 0, AES_BLOCK_SIZE);
+ std::memset(key.getBuf(), 0, key.getLength());
+ AES_ctr128_encrypt(key.getBuf(), key.getBuf(), key.getLength(), &aes_key_, ctr_.buf_, ecount_buf_, &num);
+#endif
+
+// TODO: store key if key derivation rate is != 0
+// if(!ld_kdr_)
+// return true;
+
+// if(!kd->key_store_[dir][label].key_.buf_) {
+// kd->key_store_[dir][label].key_.length_ = 0;
+// kd->key_store_[dir][label].key_.buf_ = malloc(len);
+// if(!kd->key_store_[dir][label].key_.buf_)
+// return -2;
+
+// kd->key_store_[dir][label].key_.length_ = len;
+// }
+// else if(kd->key_store_[dir][label].key_.length_ < len) {
+// u_int8_t* tmp = realloc(kd->key_store_[dir][label].key_.buf_, len);
+// if(!tmp)
+// return -2;
+
+// kd->key_store_[dir][label].key_.buf_ = tmp;
+// kd->key_store_[dir][label].key_.length_ = len;
+// }
+
+// memcpy(kd->key_store_[dir][label].key_.buf_, key, len);
+// kd->key_store_[dir][label].r_ = r;
+
+ return true;
}
#endif