summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cipher.c104
-rw-r--r--src/cipher.h13
-rw-r--r--src/key_derivation.c20
-rw-r--r--src/uanytun.c7
4 files changed, 73 insertions, 71 deletions
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 <gcrypt.h>
+#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;