From c0cfc1ff73049c4f420fdc70002f6f2c068d34dd Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 2 Jan 2009 19:49:51 +0000 Subject: some improvements in key derivation note this is no longer compatible to anytun and currently not compliant to the rfc (but probably will) --- src/cipher.c | 26 ++++++----- src/key_derivation.c | 122 ++++++++++++++++++++++----------------------------- src/key_derivation.h | 10 ++++- src/uanytun.c | 20 ++++++--- 4 files changed, 88 insertions(+), 90 deletions(-) (limited to 'src') diff --git a/src/cipher.c b/src/cipher.c index 0ca48b4..22fba9a 100644 --- a/src/cipher.c +++ b/src/cipher.c @@ -206,36 +206,38 @@ buffer_t cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, seq_nr_t seq_ if(!c->salt_.buf_) { c->salt_.length_ = 14; c->salt_.buf_ = malloc(c->salt_.length_); - if(c->salt_.buf_) + if(!c->salt_.buf_) return result; } int ret = key_derivation_generate(kd, LABEL_SATP_SALT, seq_nr, c->salt_.buf_, c->salt_.length_); - if(ret) + if(ret < 0) return result; mpz_t ctr, sid_mux, seq; mpz_init2(ctr, 128); - mpz_init2(sid_mux, 96); - mpz_init2(seq, 48); + mpz_init2(sid_mux, 128); + mpz_init2(seq, 128); int faked_msb = 0; - if(!c->salt_.buf_[0]) + if(!c->salt_.buf_[0]) { c->salt_.buf_[0] = 1; + faked_msb = 1; + } mpz_import(ctr, c->salt_.length_, 1, 1, 0, 0, c->salt_.buf_); - mpz_mul_2exp(ctr, ctr, 16); mpz_set_ui(sid_mux, mux); - mpz_mul_2exp(sid_mux, sid_mux, 16); + mpz_mul_2exp(sid_mux, sid_mux, (sizeof(sender_id) * 8)); mpz_add_ui(sid_mux, sid_mux, sender_id); - mpz_mul_2exp(sid_mux, sid_mux, 64); + mpz_mul_2exp(sid_mux, sid_mux, 48); mpz_set_ui(seq, seq_nr); - mpz_mul_2exp(seq, seq, 16); mpz_xor(ctr, ctr, sid_mux); mpz_xor(ctr, ctr, seq); + mpz_mul_2exp(ctr, ctr, 16); + result.buf_ = mpz_export(NULL, (size_t*)&result.length_, 1, 1, 0, 0, ctr); if(faked_msb) { c->salt_.buf_[0] = 0; @@ -251,8 +253,8 @@ buffer_t cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, seq_nr_t seq_ u_int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* 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) { - if(!c || !c->key_.buf_ || !c->salt_.buf_) { - log_printf(ERR, "cipher not initialized or no key or salt set"); + if(!c) { + log_printf(ERR, "cipher not initialized"); return 0; } if(!kd) { @@ -269,7 +271,7 @@ u_int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* kd, u_int8_t* in, u } int ret = key_derivation_generate(kd, LABEL_SATP_ENCRYPTION, seq_nr, c->key_.buf_, c->key_.length_); - if(ret) + if(ret < 0) return 0; gcry_error_t err = gcry_cipher_setkey(c->handle_, c->key_.buf_, c->key_.length_); diff --git a/src/key_derivation.c b/src/key_derivation.c index 44ae667..3977993 100644 --- a/src/key_derivation.c +++ b/src/key_derivation.c @@ -60,15 +60,17 @@ int key_derivation_init(key_derivation_t* kd, const char* type, int8_t ld_kdr, u } kd->ld_kdr_ = ld_kdr; - if(ld_kdr > (sizeof(seq_nr_t) * 8)) + if(ld_kdr > (int8_t)(sizeof(seq_nr_t) * 8)) kd->ld_kdr_ = sizeof(seq_nr_t) * 8; + kd->key_length_ = key_len * sizeof(key[0]) * 8; kd->handle_ = 0; int i; for(i = 0; ikey_store_[i].buf_ = NULL; - kd->key_store_[i].length_ = 0; + kd->key_store_[i].key_.buf_ = NULL; + kd->key_store_[i].key_.length_ = 0; + kd->key_store_[i].r_ = 0; } if(!key) { @@ -123,8 +125,8 @@ void key_derivation_close(key_derivation_t* kd) int i; for(i = 0; ikey_store_[i].buf_) - free(kd->key_store_[i].buf_); + if(kd->key_store_[i].key_.buf_) + free(kd->key_store_[i].key_.buf_); } } @@ -200,75 +202,50 @@ void key_derivation_aesctr_close(key_derivation_t* kd) gcry_cipher_close(kd->handle_); } -int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, buffer_t* result, satp_prf_label_t label, seq_nr_t seq_nr) +int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_store_t* result, satp_prf_label_t label, seq_nr_t seq_nr) { if(!kd || !result) return -1; - result->buf_ = NULL; - result->length_ = 0; + seq_nr_t r = 0; + if(kd->ld_kdr_ >= 0) + r = seq_nr >> kd->ld_kdr_; - mpz_t ctr, key_id, r, seq; + if(kd->key_store_[label].key_.buf_ && kd->key_store_[label].r_ == r) { + if(!r || (seq_nr % r)) + return 0; + } + result->r_ = r; + + mpz_t ctr, key_id; mpz_init2(ctr, 128); mpz_init2(key_id, 128); - mpz_init2(r, 128); - mpz_init2(seq, (sizeof(seq_nr_t) * 8)); - - mpz_set_ui(seq, seq_nr); int faked_msb = 0; - if(!kd->master_salt_.buf_[0]) + if(!kd->master_salt_.buf_[0]) { kd->master_salt_.buf_[0] = 1; - - if(kd->ld_kdr_ == -1) - mpz_set_ui(r, 0); - else - mpz_fdiv_q_2exp(r, seq, kd->ld_kdr_); - - if(kd->key_store_[label].buf_) { - if(!mpz_cmp_ui(r, 0)) { - mpz_clear(seq); - mpz_clear(ctr); - mpz_clear(key_id); - mpz_clear(r); - return 0; - } - - mpz_t mod; - mpz_init2(mod, (sizeof(seq_nr_t) * 8)); - mpz_fdiv_r(mod, seq, r); - if(mpz_cmp_ui(mod, 0)) { - mpz_clear(seq); - mpz_clear(mod); - mpz_clear(ctr); - mpz_clear(key_id); - mpz_clear(r); - return 0; - } - mpz_clear(mod); + faked_msb = 1; } + mpz_import(ctr, kd->master_salt_.length_, 1, 1, 0, 0, kd->master_salt_.buf_); mpz_set_ui(key_id, label); - mpz_mul_2exp(key_id, key_id, (sizeof(seq_nr_t) * 8)); - mpz_add(key_id, key_id, r); - - mpz_import(ctr, kd->master_salt_.length_, 1, 1, 0, 0, kd->master_salt_.buf_); + mpz_mul_2exp(key_id, key_id, (sizeof(r) * 8)); + mpz_add_ui(key_id, key_id, r); mpz_xor(ctr, ctr, key_id); mpz_mul_2exp(ctr, ctr, 16); - if(result->buf_) - free(result->buf_); - result->buf_ = mpz_export(NULL, (size_t*)&(result->length_), 1, 1, 0, 0, ctr); + if(result->key_.buf_) + free(result->key_.buf_); + result->key_.buf_ = mpz_export(NULL, (size_t*)&(result->key_.length_), 1, 1, 0, 0, ctr); + if(faked_msb) { kd->master_salt_.buf_[0] = 0; - result->buf_[0] = 0; + result->key_.buf_[0] = 0; } - mpz_clear(seq); mpz_clear(ctr); mpz_clear(key_id); - mpz_clear(r); return 1; } @@ -280,21 +257,22 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, return -1; } - buffer_t ctr; - ctr.buf_ = NULL; - ctr.length_ = 0; + key_store_t ctr; + ctr.key_.buf_ = NULL; + ctr.key_.length_ = 0; + ctr.r_ = 0; int ret = key_derivation_aesctr_calc_ctr(kd, &ctr, label, seq_nr); if(ret < 0) { log_printf(ERR, "failed to calculate key derivation CTR"); return -1; } else if(!ret) { - if(len > kd->key_store_[label].length_) { + if(len > kd->key_store_[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_[label].length_; + len = kd->key_store_[label].key_.length_; } - memcpy(key, kd->key_store_[label].buf_, len); + memcpy(key, kd->key_store_[label].key_.buf_, len); return 0; } @@ -304,8 +282,8 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, return -1; } - err = gcry_cipher_setctr(kd->handle_, ctr.buf_, ctr.length_); - free(ctr.buf_); + err = gcry_cipher_setctr(kd->handle_, ctr.key_.buf_, ctr.key_.length_); + free(ctr.key_.buf_); if(err) { log_printf(ERR, "failed to set key derivation CTR: %s/%s", gcry_strerror(err), gcry_strsource(err)); @@ -319,26 +297,30 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, return -1; } - if(!kd->key_store_[label].buf_) { - kd->key_store_[label].length_ = 0; - kd->key_store_[label].buf_ = malloc(len); - if(!kd->key_store_[label].buf_) { + if(!kd->ld_kdr_) + return 1; + + if(!kd->key_store_[label].key_.buf_) { + kd->key_store_[label].key_.length_ = 0; + kd->key_store_[label].key_.buf_ = malloc(len); + if(!kd->key_store_[label].key_.buf_) { log_printf(ERR, "memory error at key derivation"); return -2; } - kd->key_store_[label].length_ = len; + kd->key_store_[label].key_.length_ = len; } - else if(kd->key_store_[label].length_ < len) { - u_int8_t* tmp = realloc(kd->key_store_[label].buf_, len); + else if(kd->key_store_[label].key_.length_ < len) { + u_int8_t* tmp = realloc(kd->key_store_[label].key_.buf_, len); if(!tmp) { log_printf(ERR, "memory error at key derivation"); return -2; } - kd->key_store_[label].buf_ = tmp; - kd->key_store_[label].length_ = len; + kd->key_store_[label].key_.buf_ = tmp; + kd->key_store_[label].key_.length_ = len; } - memcpy(kd->key_store_[label].buf_, key, len); + memcpy(kd->key_store_[label].key_.buf_, key, len); + kd->key_store_[label].r_ = ctr.r_; - return 0; + return 1; } diff --git a/src/key_derivation.h b/src/key_derivation.h index 21f069d..d8f49c6 100644 --- a/src/key_derivation.h +++ b/src/key_derivation.h @@ -48,6 +48,12 @@ typedef enum satp_prf_label_enum satp_prf_label_t; enum key_derivation_type_enum { kd_unknown, kd_null, kd_aes_ctr }; typedef enum key_derivation_type_enum key_derivation_type_t; +struct key_store_struct { + buffer_t key_; + seq_nr_t r_; +}; +typedef struct key_store_struct key_store_t; + struct key_derivation_struct { key_derivation_type_t type_; int8_t ld_kdr_; @@ -55,7 +61,7 @@ struct key_derivation_struct { buffer_t master_key_; buffer_t master_salt_; gcry_cipher_hd_t handle_; - buffer_t key_store_[KD_LABEL_COUNT]; + key_store_t key_store_[KD_LABEL_COUNT]; }; typedef struct key_derivation_struct key_derivation_t; @@ -67,7 +73,7 @@ int key_derivation_null_generate(u_int8_t* key, u_int32_t len); int key_derivation_aesctr_init(key_derivation_t* kd, u_int16_t key_length); void key_derivation_aesctr_close(key_derivation_t* kd); -int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, buffer_t* result, satp_prf_label_t label, seq_nr_t seq_nr); +int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, key_store_t* result, satp_prf_label_t label, seq_nr_t seq_nr); int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, seq_nr_t seq_nr, u_int8_t* key, u_int32_t len); #endif diff --git a/src/uanytun.c b/src/uanytun.c index 8f677a4..8ad6ed7 100644 --- a/src/uanytun.c +++ b/src/uanytun.c @@ -105,10 +105,17 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) return_value = ret; } - key_derivation_t kd; - ret = key_derivation_init(&kd, opt->kd_prf_, opt->ld_kdr_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_); + key_derivation_t kd_in; + ret = key_derivation_init(&kd_in, opt->kd_prf_, opt->ld_kdr_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_); if(ret) { - log_printf(ERR, "could not initialize key derivation of type %s", opt->kd_prf_); + log_printf(ERR, "could not initialize inbound key derivation of type %s", opt->kd_prf_); + return_value = ret; + } + + key_derivation_t kd_out; + ret = key_derivation_init(&kd_out, opt->kd_prf_, opt->ld_kdr_, opt->key_.buf_, opt->key_.length_, opt->salt_.buf_, opt->salt_.length_); + if(ret) { + log_printf(ERR, "could not initialize outbound key derivation of type %s", opt->kd_prf_); return_value = ret; } @@ -158,7 +165,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) else plain_packet_set_type(&plain_packet, PAYLOAD_TYPE_UNKNOWN); - cipher_encrypt(&c, &kd, &plain_packet, &encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); + cipher_encrypt(&c, &kd_out, &plain_packet, &encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); seq_nr++; // TODO: add auth-tag @@ -201,7 +208,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) free(addrstring); } - cipher_decrypt(&c, &kd, &encrypted_packet, &plain_packet); + cipher_decrypt(&c, &kd_in, &encrypted_packet, &plain_packet); len = tun_write(dev, plain_packet_get_payload(&plain_packet), plain_packet_get_payload_length(&plain_packet)); if(len == -1) @@ -210,7 +217,8 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) } cipher_close(&c); - key_derivation_close(&kd); + key_derivation_close(&kd_out); + key_derivation_close(&kd_in); seq_win_clear(&seq_win); return return_value; -- cgit v1.2.3