From 5329cef63bfb88ecf44c6a4dc360e33d70b84b41 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 2 Jan 2009 16:14:23 +0000 Subject: some cleanup at key derivation cipher supports now multiple key lengths and uses key derivation directly --- src/cipher.c | 104 ++++++++++++++++++++++++++------------------------- src/cipher.h | 13 +++---- src/key_derivation.c | 20 +++++----- src/uanytun.c | 7 ++-- 4 files changed, 73 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/cipher.c b/src/cipher.c index 8c086ee..0ca48b4 100644 --- a/src/cipher.c +++ b/src/cipher.c @@ -51,17 +51,28 @@ int cipher_init(cipher_t* c, const char* type) if(!c) return -1; + c->key_length_ = 0; + c->type_ = unknown; if(!strcmp(type, "null")) c->type_ = null; - else if(!strcmp(type, "aes-ctr")) + else if(!strncmp(type, "aes-ctr", 7)) { c->type_ = aes_ctr; + if(type[7] == 0) { + c->key_length_ = 128; + } + else if(type[7] != '-') + return -1; + else { + const char* tmp = &type[8]; + c->key_length_ = atoi(tmp); + } + } else { log_printf(ERR, "unknown cipher type"); return -1; } - c->key_length_ = 0; c->handle_ = 0; c->key_.buf_ = NULL; @@ -72,47 +83,11 @@ int cipher_init(cipher_t* c, const char* type) int ret = 0; if(c->type_ == aes_ctr) - ret = cipher_aesctr_init(c, 128); + ret = cipher_aesctr_init(c); return ret; } -void cipher_set_key(cipher_t* c, u_int8_t* key, u_int32_t len) -{ - if(!c || !key) - return; - if(c->type_ == null) - return; - - if(c->key_.buf_) - free(c->key_.buf_); - c->key_.buf_ = malloc(len); - if(!c->key_.buf_) { - c->key_.length_ = 0; - return; - } - memcpy(c->key_.buf_, key, len); - c->key_.length_ = len; -} - -void cipher_set_salt(cipher_t* c, u_int8_t* salt, u_int32_t len) -{ - if(!c || !salt) - return; - if(c->type_ == null) - return; - - if(c->salt_.buf_) - free(c->salt_.buf_); - c->salt_.buf_ = malloc(len); - if(!c->salt_.buf_) { - c->salt_.length_ = 0; - return; - } - memcpy(c->salt_.buf_, salt, len); - c->salt_.length_ = len; -} - void cipher_close(cipher_t* c) { if(!c) @@ -127,7 +102,8 @@ void cipher_close(cipher_t* c) free(c->salt_.buf_); } -void cipher_encrypt(cipher_t* c, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) + +void cipher_encrypt(cipher_t* c, key_derivation_t* kd, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { if(!c) return; @@ -137,7 +113,7 @@ void cipher_encrypt(cipher_t* c, plain_packet_t* in, encrypted_packet_t* out, se len = cipher_null_crypt(plain_packet_get_packet(in), plain_packet_get_length(in), encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out)); else if(c->type_ == aes_ctr) - len = cipher_aesctr_crypt(c, plain_packet_get_packet(in), plain_packet_get_length(in), + len = cipher_aesctr_crypt(c, kd, plain_packet_get_packet(in), plain_packet_get_length(in), encrypted_packet_get_payload(out), encrypted_packet_get_payload_length(out), seq_nr, sender_id, mux); else { @@ -152,7 +128,7 @@ void cipher_encrypt(cipher_t* c, plain_packet_t* in, encrypted_packet_t* out, se encrypted_packet_set_payload_length(out, len); } -void cipher_decrypt(cipher_t* c, encrypted_packet_t* in, plain_packet_t* out) +void cipher_decrypt(cipher_t* c, key_derivation_t* kd, encrypted_packet_t* in, plain_packet_t* out) { if(!c) return; @@ -162,7 +138,7 @@ void cipher_decrypt(cipher_t* c, encrypted_packet_t* in, plain_packet_t* out) len = cipher_null_crypt(encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in), plain_packet_get_packet(out), plain_packet_get_length(out)); else if(c->type_ == aes_ctr) - len = cipher_aesctr_crypt(c, encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in), + len = cipher_aesctr_crypt(c, kd, encrypted_packet_get_payload(in), encrypted_packet_get_payload_length(in), plain_packet_get_packet(out), plain_packet_get_length(out), encrypted_packet_get_seq_nr(in), encrypted_packet_get_sender_id(in), encrypted_packet_get_mux(in)); @@ -184,18 +160,18 @@ u_int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32 /* ---------------- AES-Ctr Cipher ---------------- */ -int cipher_aesctr_init(cipher_t* c, int key_length) +int cipher_aesctr_init(cipher_t* c) { if(!c) return -1; - c->key_length_ = key_length; - int algo; - switch(key_length) { + switch(c->key_length_) { case 128: algo = GCRY_CIPHER_AES128; break; + case 192: algo = GCRY_CIPHER_AES192; break; + case 256: algo = GCRY_CIPHER_AES256; break; default: { - log_printf(ERR, "key length of %d Bits is not supported", key_length); + log_printf(ERR, "cipher key length of %d Bits is not supported", c->key_length_); return -1; } } @@ -218,7 +194,7 @@ void cipher_aesctr_close(cipher_t* c) gcry_cipher_close(c->handle_); } -buffer_t cipher_aesctr_calc_ctr(cipher_t* c, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) +buffer_t cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux) { buffer_t result; result.buf_ = NULL; @@ -226,6 +202,16 @@ buffer_t cipher_aesctr_calc_ctr(cipher_t* c, seq_nr_t seq_nr, sender_id_t sender if(!c) return result; + + if(!c->salt_.buf_) { + c->salt_.length_ = 14; + c->salt_.buf_ = malloc(c->salt_.length_); + 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) + return result; mpz_t ctr, sid_mux, seq; mpz_init2(ctr, 128); @@ -263,20 +249,36 @@ buffer_t cipher_aesctr_calc_ctr(cipher_t* c, seq_nr_t seq_nr, sender_id_t sender return result; } -u_int32_t cipher_aesctr_crypt(cipher_t* c, 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_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"); return 0; } + if(!kd) { + log_printf(ERR, "no key derivation supplied"); + return 0; + } + + + if(!c->key_.buf_) { + c->key_.length_ = c->key_length_/8; + c->key_.buf_ = malloc(c->key_.length_); + if(c->key_.buf_) + return 0; + } + int ret = key_derivation_generate(kd, LABEL_SATP_ENCRYPTION, seq_nr, c->key_.buf_, c->key_.length_); + if(ret) + return 0; + gcry_error_t err = gcry_cipher_setkey(c->handle_, c->key_.buf_, c->key_.length_); if(err) { log_printf(ERR, "failed to set cipher key: %s/%s", gcry_strerror(err), gcry_strsource(err)); return 0; } - buffer_t ctr = cipher_aesctr_calc_ctr(c, seq_nr, sender_id, mux); + buffer_t ctr = cipher_aesctr_calc_ctr(c, kd, seq_nr, sender_id, mux); if(!ctr.buf_) { log_printf(ERR, "failed to calculate cipher CTR"); return 0; diff --git a/src/cipher.h b/src/cipher.h index 78aaba8..58e1290 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -36,6 +36,7 @@ #define _CIPHER_H_ #include +#include "key_derivation.h" enum cipher_type_enum { unknown, null, aes_ctr }; typedef enum cipher_type_enum cipher_type_t; @@ -50,18 +51,16 @@ struct cipher_struct { typedef struct cipher_struct cipher_t; int cipher_init(cipher_t* c, const char* type); -void cipher_set_key(cipher_t* c, u_int8_t* key, u_int32_t len); -void cipher_set_salt(cipher_t* c, u_int8_t* salt, u_int32_t len); void cipher_close(cipher_t* c); -void cipher_encrypt(cipher_t* c, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); -void cipher_decrypt(cipher_t* c, encrypted_packet_t* in, plain_packet_t* out); +void cipher_encrypt(cipher_t* c, key_derivation_t* kd, plain_packet_t* in, encrypted_packet_t* out, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); +void cipher_decrypt(cipher_t* c, key_derivation_t* kd, encrypted_packet_t* in, plain_packet_t* out); u_int32_t cipher_null_crypt(u_int8_t* in, u_int32_t ilen, u_int8_t* out, u_int32_t olen); -int cipher_aesctr_init(cipher_t* c, int key_length); +int cipher_aesctr_init(cipher_t* c); void cipher_aesctr_close(cipher_t* c); -buffer_t cipher_aesctr_calc_ctr(cipher_t* c, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); -u_int32_t cipher_aesctr_crypt(cipher_t* c, 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); +buffer_t cipher_aesctr_calc_ctr(cipher_t* c, key_derivation_t* kd, seq_nr_t seq_nr, sender_id_t sender_id, mux_t mux); +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); #endif diff --git a/src/key_derivation.c b/src/key_derivation.c index 28e9a1c..44ae667 100644 --- a/src/key_derivation.c +++ b/src/key_derivation.c @@ -171,7 +171,7 @@ int key_derivation_aesctr_init(key_derivation_t* kd, u_int16_t key_length) case 192: algo = GCRY_CIPHER_AES192; break; case 256: algo = GCRY_CIPHER_AES256; break; default: { - log_printf(ERR, "key length of %d Bits is not supported", key_length); + log_printf(ERR, "key derivation key length of %d Bits is not supported", key_length); return -1; } } @@ -225,7 +225,7 @@ int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, buffer_t* result, satp_ else mpz_fdiv_q_2exp(r, seq, kd->ld_kdr_); - if(kd->key_store_[label].buf_ && seq_nr) { + if(kd->key_store_[label].buf_) { if(!mpz_cmp_ui(r, 0)) { mpz_clear(seq); mpz_clear(ctr); @@ -235,7 +235,7 @@ int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, buffer_t* result, satp_ } mpz_t mod; - mpz_init2(mod, (sizeof(seq_nr) * 8)); + mpz_init2(mod, (sizeof(seq_nr_t) * 8)); mpz_fdiv_r(mod, seq, r); if(mpz_cmp_ui(mod, 0)) { mpz_clear(seq); @@ -249,7 +249,7 @@ int key_derivation_aesctr_calc_ctr(key_derivation_t* kd, buffer_t* result, satp_ } mpz_set_ui(key_id, label); - mpz_mul_2exp(key_id, key_id, 48); + 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_); @@ -280,12 +280,6 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, return -1; } - gcry_error_t err = gcry_cipher_reset(kd->handle_); - if(err) { - log_printf(ERR, "failed to reset key derivation cipher: %s/%s", gcry_strerror(err), gcry_strsource(err)); - return -1; - } - buffer_t ctr; ctr.buf_ = NULL; ctr.length_ = 0; @@ -304,6 +298,12 @@ int key_derivation_aesctr_generate(key_derivation_t* kd, satp_prf_label_t label, return 0; } + gcry_error_t err = gcry_cipher_reset(kd->handle_); + if(err) { + log_printf(ERR, "failed to reset key derivation cipher: %s/%s", gcry_strerror(err), gcry_strsource(err)); + return -1; + } + err = gcry_cipher_setctr(kd->handle_, ctr.buf_, ctr.length_); free(ctr.buf_); diff --git a/src/uanytun.c b/src/uanytun.c index b4ea9c0..8f677a4 100644 --- a/src/uanytun.c +++ b/src/uanytun.c @@ -110,7 +110,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) if(ret) { log_printf(ERR, "could not initialize key derivation of type %s", opt->kd_prf_); return_value = ret; - } + } seq_win_t seq_win; ret = seq_win_init(&seq_win, opt->seq_window_size_); @@ -158,7 +158,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, &plain_packet, &encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); + cipher_encrypt(&c, &kd, &plain_packet, &encrypted_packet, seq_nr, opt->sender_id_, opt->mux_); seq_nr++; // TODO: add auth-tag @@ -201,7 +201,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) free(addrstring); } - cipher_decrypt(&c, &encrypted_packet, &plain_packet); + cipher_decrypt(&c, &kd, &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,6 +210,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt) } cipher_close(&c); + key_derivation_close(&kd); seq_win_clear(&seq_win); return return_value; -- cgit v1.2.3