summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile10
-rw-r--r--src/auth_algo.c245
-rw-r--r--src/auth_algo.h63
-rw-r--r--src/cipher.c29
-rw-r--r--src/cipher.h2
-rw-r--r--src/encrypted_packet.c72
-rw-r--r--src/encrypted_packet.h11
-rw-r--r--src/options.c6
-rw-r--r--src/plain_packet.c2
-rw-r--r--src/uanytun.c19
10 files changed, 435 insertions, 24 deletions
diff --git a/src/Makefile b/src/Makefile
index 3c0edba..1431568 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -34,7 +34,7 @@
TARGET=$(shell uname -s)
CC = gcc
-CCFLAGS = -g -O2 # -DANYTUN_02_COMPAT
+CCFLAGS = -g -O2 #-DANYTUN_02_COMPAT
LD = gcc
LDFLAGS = -g -Wall -O2 -lgcrypt -lgpg-error -lgmp
@@ -54,8 +54,9 @@ OBJS = log.o \
plain_packet.o \
encrypted_packet.o \
seq_window.o \
- cipher.o \
key_derivation.o \
+ cipher.o \
+ auth_algo.o \
uanytun.o
EXECUTABLE = uanytun
@@ -92,10 +93,13 @@ encrypted_packet.o: encrypted_packet.c encrypted_packet.h
seq_window.o: seq_window.c seq_window.h
$(CC) $(CCFLAGS) $< -c
+key_derivation.o: key_derivation.c key_derivation.h
+ $(CC) $(CCFLAGS) $< -c
+
cipher.o: cipher.c cipher.h
$(CC) $(CCFLAGS) $< -c
-key_derivation.o: key_derivation.c key_derivation.h
+auth_algo.o: auth_algo.c auth_algo.h
$(CC) $(CCFLAGS) $< -c
distclean: clean
diff --git a/src/auth_algo.c b/src/auth_algo.c
new file mode 100644
index 0000000..4f91338
--- /dev/null
+++ b/src/auth_algo.c
@@ -0,0 +1,245 @@
+/*
+ * ľAnytun
+ *
+ * ľAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ * featured implementation ľAnytun has no support for multiple connections
+ * or synchronisation. It is a small single threaded implementation intended
+ * to act as a client on small platforms.
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methodes used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ * This file is part of ľAnytun.
+ *
+ * ľAnytun is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * ľAnytun is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ľAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "datatypes.h"
+
+#include "encrypted_packet.h"
+
+#include "auth_algo.h"
+
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+int auth_algo_init(auth_algo_t* aa, const char* type)
+{
+ if(!aa)
+ return -1;
+
+ aa->type_ = aa_unknown;
+ if(!strcmp(type, "null"))
+ aa->type_ = aa_null;
+ else if(!strcmp(type, "sha1"))
+ aa->type_ = aa_sha1;
+ else {
+ log_printf(ERR, "unknown auth algo type");
+ return -1;
+ }
+
+ aa->handle_ = 0;
+
+ aa->key_.buf_ = NULL;
+ aa->key_.length_ = 0;
+
+ int ret = 0;
+ if(aa->type_ == aa_sha1)
+ ret = auth_algo_sha1_init(aa);
+
+ if(ret)
+ auth_algo_close(aa);
+
+ return ret;
+}
+
+void auth_algo_close(auth_algo_t* aa)
+{
+ if(!aa)
+ return;
+
+ if(aa->type_ == aa_sha1)
+ auth_algo_sha1_close(aa);
+
+ if(aa->key_.buf_)
+ free(aa->key_.buf_);
+}
+
+void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet)
+{
+ if(!aa)
+ return;
+
+ u_int32_t len;
+ if(aa->type_ == aa_null)
+ return;
+ else if(aa->type_ == aa_sha1)
+ auth_algo_sha1_generate(aa, kd, packet);
+ else {
+ log_printf(ERR, "unknown auth algo type");
+ return;
+ }
+}
+
+int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet)
+{
+ if(!aa)
+ return;
+
+ u_int32_t len;
+ if(aa->type_ == aa_null)
+ return 1;
+ else if(aa->type_ == aa_sha1)
+ return auth_algo_sha1_check_tag(aa, kd, packet);
+ else {
+ log_printf(ERR, "unknown auth algo type");
+ return;
+ }
+}
+
+/* ---------------- HMAC Sha1 Auth Algo ---------------- */
+
+int auth_algo_sha1_init(auth_algo_t* aa)
+{
+ if(!aa)
+ return -1;
+
+ gcry_error_t err = gcry_md_open(&aa->handle_, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+ if(err) {
+ log_printf(ERR, "failed to open message digest algo: %s/%s", gcry_strerror(err), gcry_strsource(err));
+ return -1;
+ }
+
+ return 0;
+}
+
+void auth_algo_sha1_close(auth_algo_t* aa)
+{
+ if(!aa)
+ return;
+
+ if(aa->handle_)
+ gcry_md_close(aa->handle_);
+}
+
+
+void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet)
+{
+ if(!aa) {
+ log_printf(ERR, "auth algo not initialized");
+ return;
+ }
+ if(!kd) {
+ log_printf(ERR, "no key derivation supplied");
+ return;
+ }
+
+
+ if(!aa->key_.buf_) {
+ aa->key_.length_ = SHA1_LENGTH;
+ aa->key_.buf_ = malloc(aa->key_.length_);
+ if(!aa->key_.buf_) {
+ log_printf(ERR, "memory error at auth algo generate");
+ return;
+ }
+ }
+
+ int ret = key_derivation_generate(kd, LABEL_SATP_MSG_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
+ if(ret < 0)
+ return;
+ gcry_error_t err = gcry_md_setkey(aa->handle_, aa->key_.buf_, aa->key_.length_);
+ if(err) {
+ log_printf(ERR, "failed to set hmac key: %s/%s", gcry_strerror(err), gcry_strsource(err));
+ return;
+ }
+
+ encrypted_packet_add_auth_tag(packet);
+
+ gcry_md_reset(aa->handle_);
+
+ gcry_md_write(aa->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
+ gcry_md_final(aa->handle_);
+
+ u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
+ u_int8_t* hmac = gcry_md_read(aa->handle_, 0);
+ u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
+
+ if(length > SHA1_LENGTH)
+ memset(tag, 0, encrypted_packet_get_auth_tag_length(packet));
+
+ memcpy(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
+}
+
+
+int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet)
+{
+ if(!aa) {
+ log_printf(ERR, "auth algo not initialized");
+ return 0;
+ }
+ if(!kd) {
+ log_printf(ERR, "no key derivation supplied");
+ return 0;
+ }
+
+ if(!aa->key_.buf_) {
+ aa->key_.length_ = SHA1_LENGTH;
+ aa->key_.buf_ = malloc(aa->key_.length_);
+ if(!aa->key_.buf_) {
+ log_printf(ERR, "memory error at auth algo check tag");
+ return;
+ }
+ }
+
+ int ret = key_derivation_generate(kd, LABEL_SATP_MSG_AUTH, encrypted_packet_get_seq_nr(packet), aa->key_.buf_, aa->key_.length_);
+ if(ret < 0)
+ return 0;
+ gcry_error_t err = gcry_md_setkey(aa->handle_, aa->key_.buf_, aa->key_.length_);
+ if(err) {
+ log_printf(ERR, "failed to set hmac key: %s/%s", gcry_strerror(err), gcry_strsource(err));
+ return;
+ }
+
+ gcry_md_reset(aa->handle_);
+
+ gcry_md_write(aa->handle_, encrypted_packet_get_auth_portion(packet), encrypted_packet_get_auth_portion_length(packet));
+ gcry_md_final(aa->handle_);
+
+ u_int8_t* tag = encrypted_packet_get_auth_tag(packet);
+ u_int8_t* hmac = gcry_md_read(aa->handle_, 0);
+ u_int32_t length = (encrypted_packet_get_auth_tag_length(packet) < SHA1_LENGTH) ? encrypted_packet_get_auth_tag_length(packet) : SHA1_LENGTH;
+
+ if(length > SHA1_LENGTH) {
+ u_int32_t i;
+ for(i=0; i < (encrypted_packet_get_auth_tag_length(packet) - SHA1_LENGTH); ++i)
+ if(tag[i]) return 0;
+ }
+
+ int result = memcmp(&tag[encrypted_packet_get_auth_tag_length(packet) - length], &hmac[SHA1_LENGTH - length], length);
+ encrypted_packet_remove_auth_tag(packet);
+
+ if(result)
+ return 0;
+
+ return 1;
+}
diff --git a/src/auth_algo.h b/src/auth_algo.h
new file mode 100644
index 0000000..b22ea46
--- /dev/null
+++ b/src/auth_algo.h
@@ -0,0 +1,63 @@
+/*
+ * ľAnytun
+ *
+ * ľAnytun is a tiny implementation of SATP. Unlike Anytun which is a full
+ * featured implementation ľAnytun has no support for multiple connections
+ * or synchronisation. It is a small single threaded implementation intended
+ * to act as a client on small platforms.
+ * The secure anycast tunneling protocol (satp) defines a protocol used
+ * for communication between any combination of unicast and anycast
+ * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
+ * mode and allows tunneling of every ETHER TYPE protocol (e.g.
+ * ethernet, ip, arp ...). satp directly includes cryptography and
+ * message authentication based on the methodes used by SRTP. It is
+ * intended to deliver a generic, scaleable and secure solution for
+ * tunneling and relaying of packets of any protocol.
+ *
+ *
+ * Copyright (C) 2007-2008 Christian Pointner <equinox@anytun.org>
+ *
+ * This file is part of ľAnytun.
+ *
+ * ľAnytun is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * ľAnytun is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with ľAnytun. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _AUTH_ALGO_H_
+#define _AUTH_ALGO_H_
+
+#include <gcrypt.h>
+#include "key_derivation.h"
+
+enum auth_algo_type_enum { aa_unknown, aa_null, aa_sha1 };
+typedef enum auth_algo_type_enum auth_algo_type_t;
+
+struct auth_algo_struct {
+ auth_algo_type_t type_;
+ buffer_t key_;
+ gcry_md_hd_t handle_;
+};
+typedef struct auth_algo_struct auth_algo_t;
+
+int auth_algo_init(auth_algo_t* aa, const char* type);
+void auth_algo_close(auth_algo_t* aa);
+
+void auth_algo_generate(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet);
+int auth_algo_check_tag(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet);
+
+#define SHA1_LENGTH 20
+int auth_algo_sha1_init(auth_algo_t* aa);
+void auth_algo_sha1_close(auth_algo_t* aa);
+void auth_algo_sha1_generate(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet);
+int auth_algo_sha1_check_tag(auth_algo_t* aa, key_derivation_t* kd, encrypted_packet_t* packet);
+
+#endif
diff --git a/src/cipher.c b/src/cipher.c
index b61dd22..f640d6d 100644
--- a/src/cipher.c
+++ b/src/cipher.c
@@ -53,11 +53,11 @@ int cipher_init(cipher_t* c, const char* type)
c->key_length_ = 0;
- c->type_ = unknown;
+ c->type_ = c_unknown;
if(!strcmp(type, "null"))
- c->type_ = null;
+ c->type_ = c_null;
else if(!strncmp(type, "aes-ctr", 7)) {
- c->type_ = aes_ctr;
+ c->type_ = c_aes_ctr;
if(type[7] == 0) {
c->key_length_ = 128;
}
@@ -82,9 +82,12 @@ int cipher_init(cipher_t* c, const char* type)
c->salt_.length_ = 0;
int ret = 0;
- if(c->type_ == aes_ctr)
+ if(c->type_ == c_aes_ctr)
ret = cipher_aesctr_init(c);
+ if(ret)
+ cipher_close(c);
+
return ret;
}
@@ -93,7 +96,7 @@ void cipher_close(cipher_t* c)
if(!c)
return;
- if(c->type_ == aes_ctr)
+ if(c->type_ == c_aes_ctr)
cipher_aesctr_close(c);
if(c->key_.buf_)
@@ -109,10 +112,10 @@ void cipher_encrypt(cipher_t* c, key_derivation_t* kd, plain_packet_t* in, encry
return;
u_int32_t len;
- if(c->type_ == null)
+ if(c->type_ == c_null)
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)
+ else if(c->type_ == c_aes_ctr)
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);
@@ -134,10 +137,10 @@ void cipher_decrypt(cipher_t* c, key_derivation_t* kd, encrypted_packet_t* in, p
return;
u_int32_t len;
- if(c->type_ == null)
+ if(c->type_ == c_null)
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)
+ else if(c->type_ == c_aes_ctr)
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),
@@ -206,8 +209,10 @@ 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_) {
+ log_printf(ERR, "memory error aes-ctr calc ctr");
return result;
+ }
}
int ret = key_derivation_generate(kd, LABEL_SATP_SALT, seq_nr, c->salt_.buf_, c->salt_.length_);
if(ret < 0)
@@ -269,8 +274,10 @@ u_int32_t cipher_aesctr_crypt(cipher_t* c, key_derivation_t* kd, u_int8_t* in, u
if(!c->key_.buf_) {
c->key_.length_ = c->key_length_/8;
c->key_.buf_ = malloc(c->key_.length_);
- if(c->key_.buf_)
+ if(!c->key_.buf_) {
+ log_printf(ERR, "memory error aes-ctr crypt");
return 0;
+ }
}
int ret = key_derivation_generate(kd, LABEL_SATP_ENCRYPTION, seq_nr, c->key_.buf_, c->key_.length_);
diff --git a/src/cipher.h b/src/cipher.h
index 58e1290..9406761 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -38,7 +38,7 @@
#include <gcrypt.h>
#include "key_derivation.h"
-enum cipher_type_enum { unknown, null, aes_ctr };
+enum cipher_type_enum { c_unknown, c_null, c_aes_ctr };
typedef enum cipher_type_enum cipher_type_t;
struct cipher_struct {
diff --git a/src/encrypted_packet.c b/src/encrypted_packet.c
index 176241b..eb21828 100644
--- a/src/encrypted_packet.c
+++ b/src/encrypted_packet.c
@@ -76,11 +76,18 @@ void encrypted_packet_set_length(encrypted_packet_t* packet, u_int32_t len)
len -= sizeof(encrypted_packet_header_t);
packet->payload_length_ = len;
+
+ if(len >= ENCRYPTED_PACKET_AUTHTAG_SIZE) {
+ packet->auth_tag_ = packet->data_.buf_ + sizeof(encrypted_packet_header_t);
+ packet->auth_tag_ += packet->payload_length_ - ENCRYPTED_PACKET_AUTHTAG_SIZE;
+ }
+ else
+ packet->auth_tag_ = NULL;
}
u_int8_t* encrypted_packet_get_payload(encrypted_packet_t* packet)
{
- if(!packet)
+ if(!packet || !packet->payload_length_)
return NULL;
return (packet->data_.buf_ + sizeof(encrypted_packet_header_t));
@@ -103,8 +110,71 @@ void encrypted_packet_set_payload_length(encrypted_packet_t* packet, u_int32_t l
len = ENCRYPTED_PACKET_SIZE_MAX - sizeof(encrypted_packet_header_t);
packet->payload_length_ = len;
+
+ if(len >= ENCRYPTED_PACKET_AUTHTAG_SIZE) {
+ packet->auth_tag_ = packet->data_.buf_ + sizeof(encrypted_packet_header_t);
+ packet->auth_tag_ += packet->payload_length_ - ENCRYPTED_PACKET_AUTHTAG_SIZE;
+ }
+ else
+ packet->auth_tag_ = NULL;
+}
+
+u_int8_t* encrypted_packet_get_auth_portion(encrypted_packet_t* packet)
+{
+ if(!packet)
+ return NULL;
+
+ return packet->data_.buf_;
+}
+
+u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet)
+{
+ if(!packet)
+ return 0;
+
+ u_int32_t len = packet->payload_length_ + sizeof(encrypted_packet_header_t);
+
+ if(!packet->auth_tag_)
+ return len;
+
+ return (len > ENCRYPTED_PACKET_AUTHTAG_SIZE) ? (len - ENCRYPTED_PACKET_AUTHTAG_SIZE) : 0;
+}
+
+
+u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet)
+{
+ if(!packet)
+ return NULL;
+
+ return packet->auth_tag_;
+}
+
+u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet)
+{
+ if(!packet || !packet->auth_tag_)
+ return 0;
+
+ return ENCRYPTED_PACKET_AUTHTAG_SIZE;
+}
+
+void encrypted_packet_add_auth_tag(encrypted_packet_t* packet)
+{
+ if(!packet)
+ return;
+
+ encrypted_packet_set_payload_length(packet, packet->payload_length_ + ENCRYPTED_PACKET_AUTHTAG_SIZE);
}
+void encrypted_packet_remove_auth_tag(encrypted_packet_t* packet)
+{
+ if(!packet || !packet->auth_tag_)
+ return;
+
+ packet->auth_tag_ = NULL;
+ packet->payload_length_ = (packet->payload_length_ > ENCRYPTED_PACKET_AUTHTAG_SIZE) ? packet->payload_length_ - ENCRYPTED_PACKET_AUTHTAG_SIZE: 0;
+}
+
+
seq_nr_t encrypted_packet_get_seq_nr(encrypted_packet_t* packet)
{
if(!packet)
diff --git a/src/encrypted_packet.h b/src/encrypted_packet.h
index a77e663..e35ca25 100644
--- a/src/encrypted_packet.h
+++ b/src/encrypted_packet.h
@@ -36,6 +36,7 @@
#define _ENCRYPTED_PACKET_H_
#define ENCRYPTED_PACKET_SIZE_MAX 1600
+#define ENCRYPTED_PACKET_AUTHTAG_SIZE 10
#define PAYLOAD_TYPE_TAP 0x6558
#define PAYLOAD_TYPE_TUN 0x0000
@@ -51,6 +52,7 @@ typedef struct encrypted_packet_header_struct encrypted_packet_header_t;
struct encrypted_packet_struct {
u_int32_t payload_length_;
+ u_int8_t* auth_tag_;
union __attribute__ ((__packed__)) {
u_int8_t buf_[ENCRYPTED_PACKET_SIZE_MAX];
encrypted_packet_header_t header_;
@@ -68,6 +70,15 @@ u_int8_t* encrypted_packet_get_payload(encrypted_packet_t* packet);
u_int32_t encrypted_packet_get_payload_length(encrypted_packet_t* packet);
void encrypted_packet_set_payload_length(encrypted_packet_t* packet, u_int32_t len);
+u_int8_t* encrypted_packet_get_auth_portion(encrypted_packet_t* packet);
+u_int32_t encrypted_packet_get_auth_portion_length(encrypted_packet_t* packet);
+
+u_int8_t* encrypted_packet_get_auth_tag(encrypted_packet_t* packet);
+u_int32_t encrypted_packet_get_auth_tag_length(encrypted_packet_t* packet);
+
+void encrypted_packet_add_auth_tag(encrypted_packet_t* packet);
+void encrypted_packet_remove_auth_tag(encrypted_packet_t* packet);
+
seq_nr_t encrypted_packet_get_seq_nr(encrypted_packet_t* packet);
void encrypted_packet_set_seq_nr(encrypted_packet_t* packet, seq_nr_t seq_nr);
diff --git a/src/options.c b/src/options.c
index b74092b..b430eba 100644
--- a/src/options.c
+++ b/src/options.c
@@ -222,10 +222,10 @@ void options_default(options_t* opt)
opt->ifconfig_param_remote_netmask_ = NULL;
opt->post_up_script_ = NULL;
opt->seq_window_size_ = 100;
- opt->cipher_ = strdup("null");
- opt->kd_prf_ = strdup("null");
+ opt->cipher_ = strdup("aes-ctr");
+ opt->kd_prf_ = strdup("aes-ctr");
opt->ld_kdr_ = 0;
- opt->auth_algo_ = strdup("null");
+ opt->auth_algo_ = strdup("sha1");
opt->mux_ = 0;
opt->key_.buf_ = NULL;
opt->key_.length_ = 0;
diff --git a/src/plain_packet.c b/src/plain_packet.c
index 6eca0af..8b63e4a 100644
--- a/src/plain_packet.c
+++ b/src/plain_packet.c
@@ -83,7 +83,7 @@ void plain_packet_set_length(plain_packet_t* packet, u_int32_t len)
u_int8_t* plain_packet_get_payload(plain_packet_t* packet)
{
- if(!packet)
+ if(!packet || !packet->payload_length_)
return NULL;
return (packet->data_.buf_ + sizeof(payload_type_t));
diff --git a/src/uanytun.c b/src/uanytun.c
index 8ad6ed7..55a73a2 100644
--- a/src/uanytun.c
+++ b/src/uanytun.c
@@ -50,15 +50,15 @@
#include "encrypted_packet.h"
#include "seq_window.h"
-#include "cipher.h"
#include "key_derivation.h"
+#include "cipher.h"
+#include "auth_algo.h"
#include "daemon.h"
#include "sysexec.h"
#include <gcrypt.h>
-
#define MIN_GCRYPT_VERSION "1.2.0"
int init_libgcrypt()
@@ -104,6 +104,13 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
log_printf(ERR, "could not initialize cipher of type %s", opt->cipher_);
return_value = ret;
}
+
+ auth_algo_t aa;
+ ret = auth_algo_init(&aa, opt->auth_algo_);
+ if(ret) {
+ log_printf(ERR, "could not initialize auth algo of type %s", opt->auth_algo_);
+ return_value = ret;
+ }
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_);
@@ -168,7 +175,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
cipher_encrypt(&c, &kd_out, &plain_packet, &encrypted_packet, seq_nr, opt->sender_id_, opt->mux_);
seq_nr++;
- // TODO: add auth-tag
+ auth_algo_generate(&aa, &kd_out, &encrypted_packet);
len = udp_write(sock, encrypted_packet_get_packet(&encrypted_packet), encrypted_packet_get_length(&encrypted_packet));
if(len == -1)
@@ -184,7 +191,10 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
encrypted_packet_set_length(&encrypted_packet, len);
- // TODO: check auth-tag
+ if(!auth_algo_check_tag(&aa, &kd_out, &encrypted_packet)) {
+ log_printf(WARNING, "wrong authentication tag, discarding packet");
+ continue;
+ }
if(encrypted_packet_get_mux(&encrypted_packet) != opt->mux_)
continue;
@@ -217,6 +227,7 @@ int main_loop(tun_device_t* dev, udp_socket_t* sock, options_t* opt)
}
cipher_close(&c);
+ auth_algo_close(&aa);
key_derivation_close(&kd_out);
key_derivation_close(&kd_in);
seq_win_clear(&seq_win);