summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Pointner <equinox@anytun.org>2009-01-02 19:49:51 +0000
committerChristian Pointner <equinox@anytun.org>2009-01-02 19:49:51 +0000
commitc0cfc1ff73049c4f420fdc70002f6f2c068d34dd (patch)
tree1bb22c9f3fdcb6706941e492f334ad1c16bd858a
parentsome cleanup at key derivation (diff)
some improvements in key derivation
note this is no longer compatible to anytun and currently not compliant to the rfc (but probably will)
-rw-r--r--src/cipher.c26
-rw-r--r--src/key_derivation.c122
-rw-r--r--src/key_derivation.h10
-rw-r--r--src/uanytun.c20
4 files changed, 88 insertions, 90 deletions
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; i<KD_LABEL_COUNT; ++i) {
- kd->key_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; i<KD_LABEL_COUNT; ++i) {
- if(kd->key_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;