summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2012-04-14 13:06:11 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2012-04-14 13:06:11 +0200
commit701fcc7c7e353def78d89d9ee0ca52d32fb894b9 (patch)
treee39e37e1bf8e8bd5d38885d059c61006ce90f172
parentac235fb7d28da6690f5ef7d7dc37d40bcebbd87a (diff)
downloadfastd-701fcc7c7e353def78d89d9ee0ca52d32fb894b9.tar
fastd-701fcc7c7e353def78d89d9ee0ca52d32fb894b9.zip
Separate handshake from encryption method
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt13
-rw-r--r--config.h.in2
-rw-r--r--src/CMakeLists.txt19
-rw-r--r--src/config.c47
-rw-r--r--src/config.l1
-rw-r--r--src/config.y28
-rw-r--r--src/fastd.c12
-rw-r--r--src/fastd.h25
-rw-r--r--src/handshake.c17
-rw-r--r--src/handshake.h1
-rw-r--r--src/method_null.c80
-rw-r--r--src/method_xsalsa20_poly1305.c205
-rw-r--r--src/protocol_ec25519_fhmqvc.c (renamed from src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c)222
-rw-r--r--src/protocol_null.c158
-rw-r--r--src/types.h4
16 files changed, 448 insertions, 387 deletions
diff --git a/.gitignore b/.gitignore
index bdc5af0..4f1b7ee 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
*~
build
+profile
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9e50c36..aa84c0f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,24 +6,17 @@ set(CMAKE_MODULE_PATH ${FASTD_SOURCE_DIR})
find_package(BISON 2.5 REQUIRED)
find_package(FLEX REQUIRED)
-find_package(UECC)
-find_package(NaCl)
+find_package(UECC REQUIRED)
+find_package(NaCl REQUIRED)
-if(UECC_FOUND AND NACL_FOUND)
- set(CRYPTO_FOUND TRUE)
-endif(UECC_FOUND AND NACL_FOUND)
-set(WITH_PROTOCOL_ECFXP ${CRYPTO_FOUND} CACHE BOOL "Include ec25519-fhmqvc-xsalsa20-poly1305 protocol")
+set(WITH_METHOD_XSALSA20_POLY1305 TRUE CACHE BOOL "Include xsalsa20-poly1305 method")
set(MAX_CONFIG_DEPTH 10 CACHE STRING "Maximum config include depth")
# Ensure the value is numeric
math(EXPR MAX_CONFIG_DEPTH_NUM ${MAX_CONFIG_DEPTH})
-if(WITH_PROTOCOL_ECFXP AND NOT CRYPTO_FOUND)
- MESSAGE(FATAL_ERROR "libuecc and NaCl are required for the ec25519-fhmqvc-xsalsa20-poly1305 protocol")
-endif(WITH_PROTOCOL_ECFXP AND NOT CRYPTO_FOUND)
-
configure_file(${FASTD_SOURCE_DIR}/config.h.in ${FASTD_BINARY_DIR}/config.h)
add_subdirectory(src)
diff --git a/config.h.in b/config.h.in
index 2a58ff1..c9db59c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -28,7 +28,7 @@
#ifndef _FASTD_CONFIG_H_
#define _FASTD_CONFIG_H_
-#cmakedefine WITH_PROTOCOL_ECFXP
+#cmakedefine WITH_METHOD_XSALSA20_POLY1305
#define MAX_CONFIG_DEPTH @MAX_CONFIG_DEPTH_NUM@
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 986568c..a700c4c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,14 +1,10 @@
-set(PROTOCOLS protocol_null.c)
-set(FASTD_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${FASTD_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR})
-set(FASTD_LIBS "")
+set(METHODS method_null.c)
-if(WITH_PROTOCOL_ECFXP)
- list(APPEND PROTOCOLS protocol_ec25519_fhmqvc_xsalsa20_poly1305.c)
- list(APPEND FASTD_INCLUDES ${UECC_INCLUDE_DIR} ${NACL_INCLUDE_DIR})
- list(APPEND FASTD_LIBS ${UECC_LIBRARY} ${NACL_LIBRARY})
-endif(WITH_PROTOCOL_ECFXP)
+if(WITH_METHOD_XSALSA20_POLY1305)
+ list(APPEND METHODS method_xsalsa20_poly1305.c)
+endif(WITH_METHOD_XSALSA20_POLY1305)
-include_directories(${FASTD_INCLUDES})
+include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${FASTD_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${UECC_INCLUDE_DIR} ${NACL_INCLUDE_DIR})
FLEX_TARGET(fastd_config_lex config.l ${CMAKE_CURRENT_BINARY_DIR}/config.ll.c)
BISON_TARGET(fastd_config_parse config.y ${CMAKE_CURRENT_BINARY_DIR}/config.yy.c)
@@ -22,10 +18,11 @@ add_executable(fastd
queue.c
random.c
task.c
+ protocol_ec25519_fhmqvc.c
${FLEX_fastd_config_lex_OUTPUTS}
${BISON_fastd_config_parse_OUTPUTS}
- ${PROTOCOLS}
+ ${METHODS}
)
-target_link_libraries(fastd rt ${FASTD_LIBS})
+target_link_libraries(fastd rt ${UECC_LIBRARY} ${NACL_LIBRARY})
install(TARGETS fastd RUNTIME DESTINATION sbin)
diff --git a/src/config.c b/src/config.c
index 8c63b4e..e7c8640 100644
--- a/src/config.c
+++ b/src/config.c
@@ -41,10 +41,12 @@
#include <sys/types.h>
-extern const fastd_protocol fastd_protocol_null;
+extern const fastd_protocol fastd_protocol_ec25519_fhmqvc;
-#ifdef WITH_PROTOCOL_ECFXP
-extern const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
+extern const fastd_method fastd_method_null;
+
+#ifdef WITH_METHOD_XSALSA20_POLY1305
+extern const fastd_method fastd_method_xsalsa20_poly1305;
#endif
@@ -66,7 +68,8 @@ static void default_config(fastd_config *conf) {
conf->peer_to_peer = false;
- conf->protocol = &fastd_protocol_null;
+ conf->protocol = &fastd_protocol_ec25519_fhmqvc;
+ conf->method = &fastd_method_null;
conf->secret = NULL;
conf->key_valid = 3600; /* 60 minutes */
conf->key_refresh = 3300; /* 55 minutes */
@@ -107,6 +110,28 @@ static bool config_match(const char *opt, ...) {
return match;
}
+bool fastd_config_protocol(fastd_context *ctx, fastd_config *conf, const char *name) {
+ if (!strcmp(name, "ec25519-fhmqvc"))
+ conf->protocol = &fastd_protocol_ec25519_fhmqvc;
+ else
+ return false;
+
+ return true;
+}
+
+bool fastd_config_method(fastd_context *ctx, fastd_config *conf, const char *name) {
+ if (!strcmp(name, "null"))
+ conf->method = &fastd_method_null;
+#ifdef WITH_METHOD_XSALSA20_POLY1305
+ else if (!strcmp(name, "xsalsa20-poly1305"))
+ conf->method = &fastd_method_xsalsa20_poly1305;
+#endif
+ else
+ return false;
+
+ return true;
+}
+
static void read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir) {
DIR *dirh = opendir(".");
@@ -436,17 +461,17 @@ void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *con
IF_OPTION_ARG("-P", "--protocol") {
- if (!strcmp(arg, "null"))
- conf->protocol = &fastd_protocol_null;
-#ifdef WITH_PROTOCOL_ECFXP
- else if (!strcmp(arg, "ecfxp"))
- conf->protocol = &fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
-#endif
- else
+ if (!fastd_config_protocol(ctx, conf, arg))
exit_error(ctx, "invalid protocol `%s'", arg);
continue;
}
+ IF_OPTION_ARG("--method") {
+ if (!fastd_config_method(ctx, conf, arg))
+ exit_error(ctx, "invalid method `%s'", arg);
+ continue;
+ }
+
IF_OPTION_ARG("-p", "--peer") {
peer = fastd_peer_config_new(ctx, conf);
diff --git a/src/config.l b/src/config.l
index c2f771a..f20116c 100644
--- a/src/config.l
+++ b/src/config.l
@@ -59,6 +59,7 @@ bind { UPDATE_LOCATION; return TOK_BIND; }
mtu { UPDATE_LOCATION; return TOK_MTU; }
mode { UPDATE_LOCATION; return TOK_MODE; }
protocol { UPDATE_LOCATION; return TOK_PROTOCOL; }
+method { UPDATE_LOCATION; return TOK_METHOD; }
peer { UPDATE_LOCATION; return TOK_PEER; }
address { UPDATE_LOCATION; return TOK_ADDRESS; }
secret { UPDATE_LOCATION; return TOK_SECRET; }
diff --git a/src/config.y b/src/config.y
index ac5f808..b1d68e0 100644
--- a/src/config.y
+++ b/src/config.y
@@ -61,6 +61,7 @@
%token TOK_MTU
%token TOK_MODE
%token TOK_PROTOCOL
+%token TOK_METHOD
%token TOK_PEER
%token TOK_ADDRESS
%token TOK_SECRET
@@ -99,12 +100,6 @@
#include <peer.h>
void fastd_config_error(YYLTYPE *loc, fastd_context *ctx, fastd_config *conf, const char *filename, int depth, char *s);
-
- extern const fastd_protocol fastd_protocol_null;
-
- #ifdef WITH_PROTOCOL_ECFXP
- extern const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
- #endif
}
@@ -130,6 +125,7 @@ statement: TOK_LOG log ';'
| TOK_MTU mtu ';'
| TOK_MODE mode ';'
| TOK_PROTOCOL protocol ';'
+ | TOK_METHOD method ';'
| TOK_SECRET secret ';'
| TOK_ON TOK_UP on_up ';'
| TOK_ON TOK_DOWN on_down ';'
@@ -180,19 +176,19 @@ mode: TOK_TAP { conf->mode = MODE_TAP; }
;
protocol: TOK_STRING {
- if (!strcmp($1->str, "null")) {
- conf->protocol = &fastd_protocol_null;
- }
-#ifdef WITH_PROTOCOL_ECFXP
- else if (!strcmp($1->str, "ecfxp")) {
- conf->protocol = &fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305;
- }
-#endif
- else {
+ if (!fastd_config_protocol(ctx, conf, $1->str)) {
fastd_config_error(&@$, ctx, conf, filename, depth, "invalid protocol");
YYERROR;
}
-}
+ }
+ ;
+
+method: TOK_STRING {
+ if (!fastd_config_method(ctx, conf, $1->str)) {
+ fastd_config_error(&@$, ctx, conf, filename, depth, "invalid method");
+ YYERROR;
+ }
+ }
;
secret: TOK_STRING { free(conf->secret); conf->secret = strdup($1->str); }
diff --git a/src/fastd.c b/src/fastd.c
index ba8c6e8..711d903 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -340,7 +340,7 @@ static void handle_tasks(fastd_context *ctx) {
fastd_peer *dest_peer;
for (dest_peer = ctx->peers; dest_peer; dest_peer = dest_peer->next) {
if (dest_peer != task->peer && dest_peer->state == STATE_ESTABLISHED) {
- fastd_buffer send_buffer = fastd_buffer_alloc(task->handle_recv.buffer.len, ctx->conf->protocol->min_encrypt_head_space(ctx), 0);
+ fastd_buffer send_buffer = fastd_buffer_alloc(task->handle_recv.buffer.len, ctx->conf->method->min_encrypt_head_space(ctx), 0);
memcpy(send_buffer.data, task->handle_recv.buffer.data, task->handle_recv.buffer.len);
ctx->conf->protocol->send(ctx, dest_peer, send_buffer);
}
@@ -366,7 +366,7 @@ static void handle_tasks(fastd_context *ctx) {
case TASK_KEEPALIVE:
pr_debug(ctx, "sending keepalive to %P", task->peer);
- ctx->conf->protocol->send(ctx, task->peer, fastd_buffer_alloc(0, ctx->conf->protocol->min_encrypt_head_space(ctx), 0));
+ ctx->conf->protocol->send(ctx, task->peer, fastd_buffer_alloc(0, ctx->conf->method->min_encrypt_head_space(ctx), 0));
break;
default:
@@ -379,7 +379,7 @@ static void handle_tasks(fastd_context *ctx) {
static void handle_tun(fastd_context *ctx) {
size_t max_len = fastd_max_packet_size(ctx);
- fastd_buffer buffer = fastd_buffer_alloc(max_len, ctx->conf->protocol->min_encrypt_head_space(ctx), 0);
+ fastd_buffer buffer = fastd_buffer_alloc(max_len, ctx->conf->method->min_encrypt_head_space(ctx), 0);
ssize_t len = read(ctx->tunfd, buffer.data, max_len);
if (len < 0) {
@@ -416,7 +416,7 @@ static void handle_tun(fastd_context *ctx) {
if (peer == NULL) {
for (peer = ctx->peers; peer; peer = peer->next) {
if (peer->state == STATE_ESTABLISHED) {
- fastd_buffer send_buffer = fastd_buffer_alloc(len, ctx->conf->protocol->min_encrypt_head_space(ctx), 0);
+ fastd_buffer send_buffer = fastd_buffer_alloc(len, ctx->conf->method->min_encrypt_head_space(ctx), 0);
memcpy(send_buffer.data, buffer.data, len);
ctx->conf->protocol->send(ctx, peer, send_buffer);
}
@@ -427,8 +427,8 @@ static void handle_tun(fastd_context *ctx) {
}
static void handle_socket(fastd_context *ctx, int sockfd) {
- size_t max_len = ctx->conf->protocol->max_packet_size(ctx);
- fastd_buffer buffer = fastd_buffer_alloc(max_len, ctx->conf->protocol->min_decrypt_head_space(ctx), 0);
+ size_t max_len = ctx->conf->method->max_packet_size(ctx);
+ fastd_buffer buffer = fastd_buffer_alloc(max_len, ctx->conf->method->min_decrypt_head_space(ctx), 0);
uint8_t packet_type;
struct iovec iov[2] = {
diff --git a/src/fastd.h b/src/fastd.h
index e3d3b02..2113ccd 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -63,10 +63,6 @@ struct _fastd_protocol {
void (*peer_configure)(fastd_context *ctx, fastd_peer_config *peer_conf);
void (*peer_config_purged)(fastd_context *ctx, fastd_peer_config *peer_conf);
- size_t (*max_packet_size)(fastd_context *ctx);
- size_t (*min_encrypt_head_space)(fastd_context *ctx);
- size_t (*min_decrypt_head_space)(fastd_context *ctx);
-
void (*handshake_init)(fastd_context *ctx, fastd_peer *peer);
void (*handshake_handle)(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake);
@@ -78,6 +74,23 @@ struct _fastd_protocol {
void (*generate_key)(fastd_context *ctx);
};
+struct _fastd_method {
+ const char *name;
+
+ size_t (*max_packet_size)(fastd_context *ctx);
+ size_t (*min_encrypt_head_space)(fastd_context *ctx);
+ size_t (*min_decrypt_head_space)(fastd_context *ctx);
+
+ fastd_method_session_state* (*session_init)(fastd_context *ctx, uint8_t *secret, size_t length, bool initiator);
+ bool (*session_is_valid)(fastd_context *ctx, fastd_method_session_state *session);
+ bool (*session_is_initiator)(fastd_context *ctx, fastd_method_session_state *session);
+ bool (*session_want_refresh)(fastd_context *ctx, fastd_method_session_state *session);
+ void (*session_free)(fastd_context *ctx, fastd_method_session_state *session);
+
+ bool (*encrypt)(fastd_context *ctx, fastd_method_session_state *session, fastd_buffer *out, fastd_buffer in);
+ bool (*decrypt)(fastd_context *ctx, fastd_method_session_state *session, fastd_buffer *out, fastd_buffer in);
+};
+
struct _fastd_config {
fastd_loglevel loglevel;
@@ -97,6 +110,7 @@ struct _fastd_config {
bool peer_to_peer;
const fastd_protocol *protocol;
+ const fastd_method *method;
char *secret;
unsigned key_valid;
unsigned key_refresh;
@@ -153,6 +167,9 @@ void fastd_printf(const fastd_context *ctx, const char *format, ...);
void fastd_read_peer_dir(fastd_context *ctx, fastd_config *conf, const char *dir);
bool fastd_read_config(fastd_context *ctx, fastd_config *conf, const char *filename, bool peer_config, int depth);
+
+bool fastd_config_protocol(fastd_context *ctx, fastd_config *conf, const char *name);
+bool fastd_config_method(fastd_context *ctx, fastd_config *conf, const char *name);
void fastd_configure(fastd_context *ctx, fastd_config *conf, int argc, char *const argv[]);
void fastd_reconfigure(fastd_context *ctx, fastd_config *conf);
void fastd_config_release(fastd_context *ctx, fastd_config *conf);
diff --git a/src/handshake.c b/src/handshake.c
index 06adef8..2015208 100644
--- a/src/handshake.c
+++ b/src/handshake.c
@@ -45,6 +45,7 @@ static const char const *RECORD_TYPES[RECORD_MAX] = {
"(protocol specific 4)",
"(protocol specific 5)",
"MTU",
+ "method name",
};
static const char const *REPLY_TYPES[REPLY_MAX] = {
@@ -59,10 +60,12 @@ static const char const *REPLY_TYPES[REPLY_MAX] = {
fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size_t tail_space) {
size_t protocol_len = strlen(ctx->conf->protocol->name);
+ size_t method_len = strlen(ctx->conf->method->name);
fastd_buffer buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0,
2*5 + /* handshake type, mode */
6 + /* MTU */
4+protocol_len + /* protocol name */
+ 4+method_len + /* method name */
tail_space
);
fastd_packet *request = buffer.data;
@@ -75,6 +78,7 @@ fastd_buffer fastd_handshake_new_init(fastd_context *ctx, fastd_peer *peer, size
fastd_handshake_add_uint16(ctx, &buffer, RECORD_MTU, ctx->conf->mtu);
fastd_handshake_add(ctx, &buffer, RECORD_PROTOCOL_NAME, protocol_len, ctx->conf->protocol->name);
+ fastd_handshake_add(ctx, &buffer, RECORD_METHOD_NAME, method_len, ctx->conf->method->name);
return buffer;
}
@@ -181,6 +185,19 @@ void fastd_handshake_handle(fastd_context *ctx, fastd_peer *peer, fastd_buffer b
goto send_reply;
}
+ if (!handshake.records[RECORD_METHOD_NAME].data) {
+ reply_code = REPLY_MANDATORY_MISSING;
+ error_detail = RECORD_METHOD_NAME;
+ goto send_reply;
+ }
+
+ if (handshake.records[RECORD_METHOD_NAME].length != strlen(ctx->conf->method->name)
+ || strncmp((char*)handshake.records[RECORD_METHOD_NAME].data, ctx->conf->method->name, handshake.records[RECORD_METHOD_NAME].length)) {
+ reply_code = REPLY_UNACCEPTABLE_VALUE;
+ error_detail = RECORD_METHOD_NAME;
+ goto send_reply;
+ }
+
send_reply:
if (reply_code) {
fastd_buffer reply_buffer = fastd_buffer_alloc(sizeof(fastd_packet), 0, 3*5 /* enough space for handshake type, reply code and error detail */);
diff --git a/src/handshake.h b/src/handshake.h
index a5b861e..9bb1a56 100644
--- a/src/handshake.h
+++ b/src/handshake.h
@@ -43,6 +43,7 @@ typedef enum _fastd_handshake_record_type {
RECORD_PROTOCOL4,
RECORD_PROTOCOL5,
RECORD_MTU,
+ RECORD_METHOD_NAME,
RECORD_MAX,
} fastd_handshake_record_type;
diff --git a/src/method_null.c b/src/method_null.c
new file mode 100644
index 0000000..fbdf1f5
--- /dev/null
+++ b/src/method_null.c
@@ -0,0 +1,80 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "fastd.h"
+
+
+static size_t method_max_packet_size(fastd_context *ctx) {
+ return fastd_max_packet_size(ctx);
+}
+
+static size_t method_min_head_space(fastd_context *ctx) {
+ return 0;
+}
+
+static fastd_method_session_state* method_session_init(fastd_context *ctx, uint8_t *secret, size_t length, bool initiator) {
+ if (initiator)
+ return (fastd_method_session_state*)1;
+ else
+ return (fastd_method_session_state*)2;
+}
+
+static bool method_session_is_valid(fastd_context *ctx, fastd_method_session_state *session) {
+ return session;
+}
+
+static bool method_session_is_initiator(fastd_context *ctx, fastd_method_session_state *session) {
+ return (session == (fastd_method_session_state*)1);
+}
+
+static bool method_session_want_refresh(fastd_context *ctx, fastd_method_session_state *session) {
+ return false;
+}
+
+static void method_session_free(fastd_context *ctx, fastd_method_session_state *session) {
+}
+
+static bool method_passthrough(fastd_context *ctx, fastd_method_session_state *session, fastd_buffer *out, fastd_buffer in) {
+ *out = in;
+ return true;
+}
+
+const fastd_method fastd_method_null = {
+ .name = "null",
+
+ .max_packet_size = method_max_packet_size,
+ .min_encrypt_head_space = method_min_head_space,
+ .min_decrypt_head_space = method_min_head_space,
+
+ .session_init = method_session_init,
+ .session_is_valid = method_session_is_valid,
+ .session_is_initiator = method_session_is_initiator,
+ .session_want_refresh = method_session_want_refresh,
+ .session_free = method_session_free,
+
+ .encrypt = method_passthrough,
+ .decrypt = method_passthrough,
+};
diff --git a/src/method_xsalsa20_poly1305.c b/src/method_xsalsa20_poly1305.c
new file mode 100644
index 0000000..5194a4d
--- /dev/null
+++ b/src/method_xsalsa20_poly1305.c
@@ -0,0 +1,205 @@
+/*
+ Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include "fastd.h"
+#include <crypto_secretbox_xsalsa20poly1305.h>
+
+
+#define NONCEBYTES 7
+
+
+struct _fastd_method_session_state {
+ struct timespec valid_till;
+ struct timespec refresh_after;
+
+ uint8_t key[crypto_secretbox_xsalsa20poly1305_KEYBYTES];
+
+ uint8_t send_nonce[NONCEBYTES];
+ uint8_t receive_nonce[NONCEBYTES];
+};
+
+
+static inline void increment_nonce(uint8_t nonce[NONCEBYTES]) {
+ nonce[0] += 2;
+
+ if (nonce[0] == 0 || nonce[0] == 1) {
+ int i;
+ for (i = 1; i < NONCEBYTES; i++) {
+ nonce[i]++;
+ if (nonce[i] != 0)
+ break;
+ }
+ }
+}
+
+static inline bool is_nonce_valid(const uint8_t nonce[NONCEBYTES], const uint8_t old_nonce[NONCEBYTES]) {
+ if ((nonce[0] & 1) != (old_nonce[0] & 1))
+ return false;
+
+ int i;
+ for (i = NONCEBYTES-1; i >= 0; i--) {
+ if (nonce[i] > old_nonce[i])
+ return true;
+ if (nonce[i] < old_nonce[i])
+ return false;
+ }
+
+ return false;
+}
+
+static size_t method_max_packet_size(fastd_context *ctx) {
+ return (fastd_max_packet_size(ctx) + NONCEBYTES + crypto_secretbox_xsalsa20poly1305_ZEROBYTES - crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
+}
+
+static size_t method_min_encrypt_head_space(fastd_context *ctx) {
+ return crypto_secretbox_xsalsa20poly1305_ZEROBYTES;
+}
+
+static size_t method_min_decrypt_head_space(fastd_context *ctx) {
+ return (crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES - NONCEBYTES);
+}
+
+static fastd_method_session_state* method_session_init(fastd_context *ctx, uint8_t *secret, size_t length, bool initiator) {
+ int i;
+
+ if (length < crypto_secretbox_xsalsa20poly1305_KEYBYTES)
+ exit_bug(ctx, "xsalsa20-poly1305: tried to init with short secret");
+
+ fastd_method_session_state *session = malloc(sizeof(fastd_method_session_state));
+
+ session->valid_till = ctx->now;
+ session->valid_till.tv_sec += ctx->conf->key_valid;
+
+ session->refresh_after = ctx->now;
+ session->refresh_after.tv_sec += ctx->conf->key_refresh;
+
+ memcpy(session->key, secret, crypto_secretbox_xsalsa20poly1305_KEYBYTES);
+
+ session->send_nonce[0] = initiator ? 3 : 2;
+ session->receive_nonce[0] = initiator ? 0 : 1;
+
+ for (i = 1; i < NONCEBYTES; i++) {
+ session->send_nonce[i] = 0;
+ session->receive_nonce[i] = 0;
+ }
+
+ return session;
+}
+
+static bool method_session_is_valid(fastd_context *ctx, fastd_method_session_state *session) {
+ return (session && timespec_after(&session->valid_till, &ctx->now));
+}
+
+static bool method_session_is_initiator(fastd_context *ctx, fastd_method_session_state *session) {
+ return (session->send_nonce[0] & 1);
+}
+
+static bool method_session_want_refresh(fastd_context *ctx, fastd_method_session_state *session) {
+ return (method_session_is_initiator(ctx, session) && timespec_after(&ctx->now, &session->refresh_after));
+}
+
+static void method_session_free(fastd_context *ctx, fastd_method_session_state *session) {
+ if(session) {
+ memset(session, 0, sizeof(fastd_method_session_state));
+ free(session);
+ }
+}
+
+static bool method_encrypt(fastd_context *ctx, fastd_method_session_state *session, fastd_buffer *out, fastd_buffer in) {
+ fastd_buffer_pull_head(&in, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
+ memset(in.data, 0, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
+
+ *out = fastd_buffer_alloc(in.len, 0, 0);
+
+ uint8_t nonce[crypto_secretbox_xsalsa20poly1305_NONCEBYTES];
+ memcpy(nonce, session->send_nonce, NONCEBYTES);
+ memset(nonce+NONCEBYTES, 0, crypto_secretbox_xsalsa20poly1305_NONCEBYTES-NONCEBYTES);
+
+ crypto_secretbox_xsalsa20poly1305(out->data, in.data, in.len, nonce, session->key);
+
+ fastd_buffer_free(in);
+
+ fastd_buffer_push_head(out, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES-NONCEBYTES);
+ memcpy(out->data, session->send_nonce, NONCEBYTES);
+
+ increment_nonce(session->send_nonce);
+
+ return true;
+}
+
+static bool method_decrypt(fastd_context *ctx, fastd_method_session_state *session, fastd_buffer *out, fastd_buffer in) {
+ if (in.len < NONCEBYTES)
+ return false;
+
+ if (!method_session_is_valid(ctx, session))
+ return false;
+
+ uint8_t nonce[crypto_secretbox_xsalsa20poly1305_NONCEBYTES];
+ memcpy(nonce, in.data, NONCEBYTES);
+ memset(nonce+NONCEBYTES, 0, crypto_secretbox_xsalsa20poly1305_NONCEBYTES-NONCEBYTES);
+
+ if (!is_nonce_valid(nonce, session->receive_nonce))
+ return false;
+
+ fastd_buffer_pull_head(&in, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES-NONCEBYTES);
+ memset(in.data, 0, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
+
+ *out = fastd_buffer_alloc(in.len, 0, 0);
+
+ if (crypto_secretbox_xsalsa20poly1305_open(out->data, in.data, in.len, nonce, session->key) != 0) {
+ fastd_buffer_free(*out);
+
+ /* restore input buffer */
+ fastd_buffer_push_head(&in, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES-NONCEBYTES);
+ memcpy(in.data, nonce, NONCEBYTES);
+ return false;
+ }
+
+ fastd_buffer_free(in);
+
+ fastd_buffer_push_head(out, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
+
+ memcpy(session->receive_nonce, nonce, NONCEBYTES);
+
+ return true;
+}
+
+const fastd_method fastd_method_xsalsa20_poly1305 = {
+ .name = "xsalsa20-poly1305",
+
+ .max_packet_size = method_max_packet_size,
+ .min_encrypt_head_space = method_min_encrypt_head_space,
+ .min_decrypt_head_space = method_min_decrypt_head_space,
+
+ .session_init = method_session_init,
+ .session_is_valid = method_session_is_valid,
+ .session_is_initiator = method_session_is_initiator,
+ .session_want_refresh = method_session_want_refresh,
+ .session_free = method_session_free,
+
+ .encrypt = method_encrypt,
+ .decrypt = method_decrypt,
+};
diff --git a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c b/src/protocol_ec25519_fhmqvc.c
index 8dbf10e..3168d03 100644
--- a/src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c
+++ b/src/protocol_ec25519_fhmqvc.c
@@ -36,10 +36,8 @@
#include <libuecc/ecc.h>
#include <crypto_auth_hmacsha256.h>
#include <crypto_hash_sha256.h>
-#include <crypto_secretbox_xsalsa20poly1305.h>
-#define NONCEBYTES 7
#define PUBLICKEYBYTES 32
#define SECRETKEYBYTES 32
#define HMACBYTES crypto_auth_hmacsha256_BYTES
@@ -50,18 +48,10 @@
#error bug: HASHBYTES != crypto_auth_hmacsha256_KEYBYTES
#endif
-#if HASHBYTES != crypto_secretbox_xsalsa20poly1305_KEYBYTES
-#error bug: HASHBYTES != crypto_secretbox_xsalsa20poly1305_KEYBYTES
-#endif
-
#if HASHBYTES != SECRETKEYBYTES
#error bug: HASHBYTES != SECRETKEYBYTES
#endif
-#if crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES < NONCEBYTES
-#error bug: crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES < NONCEBYTES
-#endif
-
struct _fastd_protocol_config {
ecc_secret_key_256 secret_key;
@@ -91,14 +81,9 @@ typedef struct _protocol_handshake {
typedef struct _protocol_session {
bool handshakes_cleaned;
-
- struct timespec valid_till;
- struct timespec refresh_after;
bool refreshing;
- uint8_t key[HASHBYTES];
- uint8_t send_nonce[NONCEBYTES];
- uint8_t receive_nonce[NONCEBYTES];
+ fastd_method_session_state *method_state;
} protocol_session;
struct _fastd_protocol_peer_state {
@@ -131,66 +116,20 @@ static inline bool read_key(uint8_t key[32], const char *hexkey) {
return true;
}
-static inline bool is_nonce_zero(const uint8_t nonce[NONCEBYTES]) {
- int i;
- for (i = 0; i < NONCEBYTES; i++) {
- if (nonce[i] != 0)
- return false;
- }
-
- return true;
-}
-
-static inline void increment_nonce(uint8_t nonce[NONCEBYTES]) {
- nonce[0] += 2;
-
- if (nonce[0] == 0 || nonce[0] == 1) {
- int i;
- for (i = 1; i < NONCEBYTES; i++) {
- nonce[i]++;
- if (nonce[i] != 0)
- break;
- }
- }
-}
-
static inline bool is_session_valid(fastd_context *ctx, const protocol_session *session) {
- return timespec_after(&session->valid_till, &ctx->now);
-}
-
-static inline bool is_session_zero(fastd_context *ctx, const protocol_session *session) {
- return (session->valid_till.tv_sec == 0);
-}
-
-static inline bool is_session_initiator(const protocol_session *session) {
- return (session->send_nonce[0] & 1);
+ return ctx->conf->method->session_is_valid(ctx, session->method_state);
}
static inline void check_session_refresh(fastd_context *ctx, fastd_peer *peer) {
protocol_session *session = &peer->protocol_state->session;
- if (is_session_initiator(session) && !session->refreshing && timespec_after(&ctx->now, &session->refresh_after)) {
+ if (!session->refreshing && ctx->conf->method->session_want_refresh(ctx, session->method_state)) {
pr_debug(ctx, "refreshing session with %P", peer);
session->refreshing = true;
fastd_task_schedule_handshake(ctx, peer, 0);
}
}
-static inline bool is_nonce_valid(const uint8_t nonce[NONCEBYTES], const uint8_t old_nonce[NONCEBYTES]) {
- if ((nonce[0] & 1) != (old_nonce[0] & 1))
- return false;
-
- int i;
- for (i = NONCEBYTES-1; i >= 0; i--) {
- if (nonce[i] > old_nonce[i])
- return true;
- if (nonce[i] < old_nonce[i])
- return false;
- }
-
- return false;
-}
-
static fastd_protocol_config* protocol_init(fastd_context *ctx) {
fastd_protocol_config *protocol_config = malloc(sizeof(fastd_protocol_config));
@@ -261,18 +200,6 @@ static void protocol_peer_config_purged(fastd_context *ctx, fastd_peer_config *p
}
}
-static size_t protocol_max_packet_size(fastd_context *ctx) {
- return (fastd_max_packet_size(ctx) + NONCEBYTES + crypto_secretbox_xsalsa20poly1305_ZEROBYTES - crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
-}
-
-static size_t protocol_min_encrypt_head_space(fastd_context *ctx) {
- return crypto_secretbox_xsalsa20poly1305_ZEROBYTES;
-}
-
-static size_t protocol_min_decrypt_head_space(fastd_context *ctx) {
- return (crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES - NONCEBYTES);
-}
-
static protocol_handshake* new_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiate) {
protocol_handshake **handshake;
@@ -384,36 +311,29 @@ static void respond_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_
static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_config *peer_config, bool initiator,
const ecc_public_key_256 *A, const ecc_public_key_256 *B, const ecc_public_key_256 *X,
const ecc_public_key_256 *Y, const ecc_public_key_256 *sigma) {
- int i;
uint8_t hashinput[5*PUBLICKEYBYTES];
+ uint8_t hash[HASHBYTES];
pr_verbose(ctx, "New session with %P established.", peer);
- if (is_session_valid(ctx, &peer->protocol_state->session) && !is_session_valid(ctx, &peer->protocol_state->old_session))
+ if (is_session_valid(ctx, &peer->protocol_state->session) && !is_session_valid(ctx, &peer->protocol_state->old_session)) {
+ ctx->conf->method->session_free(ctx, peer->protocol_state->old_session.method_state);
peer->protocol_state->old_session = peer->protocol_state->session;
+ }
+ else {
+ ctx->conf->method->session_free(ctx, peer->protocol_state->session.method_state);
+ }
memcpy(hashinput, X->p, PUBLICKEYBYTES);
memcpy(hashinput+PUBLICKEYBYTES, Y->p, PUBLICKEYBYTES);
memcpy(hashinput+2*PUBLICKEYBYTES, A->p, PUBLICKEYBYTES);
memcpy(hashinput+3*PUBLICKEYBYTES, B->p, PUBLICKEYBYTES);
memcpy(hashinput+4*PUBLICKEYBYTES, sigma->p, PUBLICKEYBYTES);
- crypto_hash_sha256(peer->protocol_state->session.key, hashinput, 5*PUBLICKEYBYTES);
+ crypto_hash_sha256(hash, hashinput, 5*PUBLICKEYBYTES);
peer->protocol_state->session.handshakes_cleaned = false;
-
- peer->protocol_state->session.valid_till = ctx->now;
- peer->protocol_state->session.valid_till.tv_sec += ctx->conf->key_valid;
-
- peer->protocol_state->session.refresh_after = ctx->now;
- peer->protocol_state->session.refresh_after.tv_sec += ctx->conf->key_refresh;
peer->protocol_state->session.refreshing = false;
-
- peer->protocol_state->session.send_nonce[0] = initiator ? 3 : 2;
- peer->protocol_state->session.receive_nonce[0] = initiator ? 0 : 1;
- for (i = 1; i < NONCEBYTES; i++) {
- peer->protocol_state->session.send_nonce[i] = 0;
- peer->protocol_state->session.receive_nonce[i] = 0;
- }
+ peer->protocol_state->session.method_state = ctx->conf->method->session_init(ctx, hash, HASHBYTES, initiator);
free_handshake(peer->protocol_state->initiating_handshake);
peer->protocol_state->initiating_handshake = NULL;
@@ -439,7 +359,7 @@ static void establish(fastd_context *ctx, fastd_peer *peer, const fastd_peer_con
fastd_task_schedule_keepalive(ctx, peer, ctx->conf->keepalive_interval*1000);
if (!initiator)
- protocol_send(ctx, peer, fastd_buffer_alloc(0, protocol_min_encrypt_head_space(ctx), 0));
+ protocol_send(ctx, peer, fastd_buffer_alloc(0, ctx->conf->method->min_encrypt_head_space(ctx), 0));
}
static void finish_handshake(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
@@ -685,94 +605,69 @@ static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buf
fastd_task_schedule_handshake(ctx, peer, 0);
}
- goto end;
- }
-
- if (buffer.len < NONCEBYTES)
- goto end;
-
- if (!peer->protocol_state || !is_session_valid(ctx, &peer->protocol_state->session)) {
- goto end;
+ goto fail;
}
- uint8_t nonce[crypto_secretbox_xsalsa20poly1305_NONCEBYTES];
- memcpy(nonce, buffer.data, NONCEBYTES);
- memset(nonce+NONCEBYTES, 0, crypto_secretbox_xsalsa20poly1305_NONCEBYTES-NONCEBYTES);
-
- fastd_buffer_pull_head(&buffer, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES-NONCEBYTES);
- memset(buffer.data, 0, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES);
-
- fastd_buffer recv_buffer = fastd_buffer_alloc(buffer.len, 0, 0);
+ if (!peer->protocol_state || !is_session_valid(ctx, &peer->protocol_state->session))
+ goto fail;
- protocol_session *session = NULL;
+ fastd_buffer recv_buffer;
+ bool ok = false;
if (is_session_valid(ctx, &peer->protocol_state->old_session)) {
- if (is_nonce_valid(nonce, peer->protocol_state->old_session.receive_nonce)) {
- if (crypto_secretbox_xsalsa20poly1305_open(recv_buffer.data, buffer.data, buffer.len, nonce, peer->protocol_state->old_session.key) == 0) {
- pr_debug(ctx, "received packet for old session from %P", peer);
- session = &peer->protocol_state->old_session;
- }
- }
+ if (ctx->conf->method->decrypt(ctx, peer->protocol_state->old_session.method_state, &recv_buffer, buffer))
+ ok = true;
}
- if (!session) {
- session = &peer->protocol_state->session;
-
- if (!is_nonce_valid(nonce, session->receive_nonce)) {
- pr_debug(ctx, "received packet with invalid nonce from %P", peer);
- fastd_buffer_free(recv_buffer);
- goto end;
- }
+ if (!ok) {
+ if (ctx->conf->method->decrypt(ctx, peer->protocol_state->session.method_state, &recv_buffer, buffer)) {
+ ok = true;
- if (crypto_secretbox_xsalsa20poly1305_open(recv_buffer.data, buffer.data, buffer.len, nonce, session->key) == 0) {
- if (!session->handshakes_cleaned) {
+ if (!peer->protocol_state->session.handshakes_cleaned) {
pr_debug(ctx, "cleaning left handshakes with %P", peer);
fastd_task_delete_peer_handshakes(ctx, peer);
- session->handshakes_cleaned = true;
+ peer->protocol_state->session.handshakes_cleaned = true;
- if (is_session_initiator(session))
- protocol_send(ctx, peer, fastd_buffer_alloc(0, protocol_min_encrypt_head_space(ctx), 0));
+ if (ctx->conf->method->session_is_initiator(ctx, peer->protocol_state->session.method_state))
+ protocol_send(ctx, peer, fastd_buffer_alloc(0, ctx->conf->method->min_encrypt_head_space(ctx), 0));
}
- if (!is_session_zero(ctx, &peer->protocol_state->old_session)) {
+ if (peer->protocol_state->old_session.method_state) {
pr_debug(ctx, "invalidating old session with %P", peer);
- memset(&peer->protocol_state->old_session, 0, sizeof(protocol_session));
+ ctx->conf->method->session_free(ctx, peer->protocol_state->old_session.method_state);
+ peer->protocol_state->old_session.method_state = NULL;
}
check_session_refresh(ctx, peer);
}
- else {
- pr_debug(ctx, "verification failed for packet received from %P", peer);
- fastd_buffer_free(recv_buffer);
- goto end;
- }
}
- fastd_peer_seen(ctx, peer);
+ if (!ok) {
+ pr_debug(ctx, "verification failed for packet received from %P", peer);
+ goto fail;
+ }
- fastd_buffer_push_head(&recv_buffer, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
+ fastd_peer_seen(ctx, peer);
if (recv_buffer.len)
fastd_task_put_handle_recv(ctx, peer, recv_buffer);
else
fastd_buffer_free(recv_buffer);
- memcpy(session->receive_nonce, nonce, NONCEBYTES);
+ return;
- end:
+ fail:
fastd_buffer_free(buffer);
}
static void protocol_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) {
- if (!peer->protocol_state || !is_session_valid(ctx, &peer->protocol_state->session)) {
- fastd_buffer_free(buffer);
- return;
- }
+ if (!peer->protocol_state || !is_session_valid(ctx, &peer->protocol_state->session))
+ goto fail;
check_session_refresh(ctx, peer);
protocol_session *session;
- if (is_session_initiator(&peer->protocol_state->session) && is_session_valid(ctx, &peer->protocol_state->old_session)) {
+ if (ctx->conf->method->session_is_initiator(ctx, peer->protocol_state->session.method_state) && is_session_valid(ctx, &peer->protocol_state->old_session)) {
pr_debug(ctx, "sending packet for old session to %P", peer);
session = &peer->protocol_state->old_session;
}
@@ -780,28 +675,18 @@ static void protocol_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buf
session = &peer->protocol_state->session;
}
- fastd_buffer_pull_head(&buffer, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
- memset(buffer.data, 0, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
-
- fastd_buffer send_buffer = fastd_buffer_alloc(buffer.len, 0, 0);
-
- uint8_t nonce[crypto_secretbox_xsalsa20poly1305_NONCEBYTES];
- memcpy(nonce, session->send_nonce, NONCEBYTES);
- memset(nonce+NONCEBYTES, 0, crypto_secretbox_xsalsa20poly1305_NONCEBYTES-NONCEBYTES);
-
- crypto_secretbox_xsalsa20poly1305(send_buffer.data, buffer.data, buffer.len, nonce, session->key);
-
- fastd_buffer_free(buffer);
-
- fastd_buffer_push_head(&send_buffer, crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES-NONCEBYTES);
- memcpy(send_buffer.data, session->send_nonce, NONCEBYTES);
-
+ fastd_buffer send_buffer;
+ if (!ctx->conf->method->encrypt(ctx, session->method_state, &send_buffer, buffer))
+ goto fail;
+
fastd_task_put_send(ctx, peer, send_buffer);
- increment_nonce(session->send_nonce);
-
fastd_task_delete_peer_keepalives(ctx, peer);
fastd_task_schedule_keepalive(ctx, peer, ctx->conf->keepalive_interval*1000);
+ return;
+
+ fail:
+ fastd_buffer_free(buffer);
}
static void protocol_free_peer_state(fastd_context *ctx, fastd_peer *peer) {
@@ -809,6 +694,9 @@ static void protocol_free_peer_state(fastd_context *ctx, fastd_peer *peer) {
free_handshake(peer->protocol_state->initiating_handshake);
free_handshake(peer->protocol_state->accepting_handshake);
+ ctx->conf->method->session_free(ctx, peer->protocol_state->old_session.method_state);
+ ctx->conf->method->session_free(ctx, peer->protocol_state->session.method_state);
+
free(peer->protocol_state);
}
}
@@ -842,17 +730,13 @@ static void protocol_generate_key(fastd_context *ctx) {
}
-const fastd_protocol fastd_protocol_ec25519_fhmqvc_xsalsa20_poly1305 = {
- .name = "ec25519-fhmqvc-xsalsa20-poly1305",
+const fastd_protocol fastd_protocol_ec25519_fhmqvc = {
+ .name = "ec25519-fhmqvc",
.init = protocol_init,
.peer_configure = protocol_peer_configure,
.peer_config_purged = protocol_peer_config_purged,
- .max_packet_size = protocol_max_packet_size,
- .min_encrypt_head_space = protocol_min_encrypt_head_space,
- .min_decrypt_head_space = protocol_min_decrypt_head_space,
-
.handshake_init = protocol_handshake_init,
.handshake_handle = protocol_handshake_handle,
diff --git a/src/protocol_null.c b/src/protocol_null.c
deleted file mode 100644
index b3c0b17..0000000
--- a/src/protocol_null.c
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- Copyright (c) 2012, Matthias Schiffer <mschiffer@universe-factory.net>
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-
-#define _GNU_SOURCE
-
-#include "fastd.h"
-#include "task.h"
-#include "peer.h"
-#include "handshake.h"
-
-#include <arpa/inet.h>
-
-
-static fastd_protocol_config* protocol_init(fastd_context *ctx) {
- if (ctx->conf->n_floating > 1)
- exit_error(ctx, "with protocol `null' use can't define more than one floating peer");
-
- return NULL;
-}
-
-static void protocol_peer_configure(fastd_context *ctx, fastd_peer_config *peer_conf) {
-}
-
-static void protocol_peer_config_purged(fastd_context *ctx, fastd_peer_config *peer_conf) {
-}
-
-static size_t protocol_max_packet_size(fastd_context *ctx) {
- return fastd_max_packet_size(ctx);
-}
-
-static size_t protocol_min_head_space(fastd_context *ctx) {
- return 0;
-}
-
-static void protocol_handshake_init(fastd_context *ctx, fastd_peer *peer) {
- fastd_buffer buffer = fastd_handshake_new_init(ctx, peer, 0);
- fastd_task_put_send_handshake(ctx, peer, buffer);
-}
-
-static void establish(fastd_context *ctx, fastd_peer *peer) {
- fastd_peer_seen(ctx, peer);
-
- if (fastd_peer_is_temporary(peer)) {
- fastd_peer *perm_peer;
- for (perm_peer = ctx->peers; perm_peer; perm_peer = perm_peer->next) {
- if (fastd_peer_is_floating(perm_peer))
- break;
- }
-
- if (!perm_peer) {
- return;
- }
-
- fastd_peer_set_established_merge(ctx, perm_peer, peer);
- }
- else {
- fastd_peer_set_established(ctx, peer);
- }
-
- fastd_task_schedule_keepalive(ctx, peer, ctx->conf->keepalive_interval*1000);
-}
-
-static void protocol_handshake_handle(fastd_context *ctx, fastd_peer *peer, const fastd_handshake *handshake) {
- fastd_buffer buffer;
-
- switch(handshake->type) {
- case 1:
- buffer = fastd_handshake_new_reply(ctx, peer, handshake, 0);
- fastd_task_put_send_handshake(ctx, peer, buffer);
- break;
-
- case 2:
- establish(ctx, peer);
- buffer = fastd_handshake_new_reply(ctx, peer, handshake, 0);
- fastd_task_put_send_handshake(ctx, peer, buffer);
- break;
-
- case 3:
- establish(ctx, peer);
- break;
-
- default:
- pr_debug(ctx, "received handshake reply with unknown type %u", handshake->type);
- }
-
-}
-
-static void protocol_handle_recv(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) {
- if (fastd_peer_is_established(peer) && buffer.len) {
- /* this could be optimized a bit */
- fastd_task_delete_peer_handshakes(ctx, peer);
-
- fastd_peer_seen(ctx, peer);
- fastd_task_put_handle_recv(ctx, peer, buffer);
-
- fastd_task_delete_peer_keepalives(ctx, peer);
- fastd_task_schedule_keepalive(ctx, peer, ctx->conf->keepalive_interval*1000);
- }
- else {
- fastd_buffer_free(buffer);
- }
-}
-
-static void protocol_send(fastd_context *ctx, fastd_peer *peer, fastd_buffer buffer) {
- fastd_task_put_send(ctx, peer, buffer);
-}
-
-static void protocol_free_peer_state(fastd_context *ctx, fastd_peer *peer) {
-}
-
-static void protocol_generate_key(fastd_context *ctx) {
- exit_error(ctx, "trying to generate key for `null' protocol");
-}
-
-const fastd_protocol fastd_protocol_null = {
- .name = "null",
-
- .init = protocol_init,
- .peer_configure = protocol_peer_configure,
- .peer_config_purged = protocol_peer_config_purged,
-
- .max_packet_size = protocol_max_packet_size,
- .min_encrypt_head_space = protocol_min_head_space,
- .min_decrypt_head_space = protocol_min_head_space,
-
- .handshake_init = protocol_handshake_init,
- .handshake_handle = protocol_handshake_handle,
-
- .handle_recv = protocol_handle_recv,
- .send = protocol_send,
-
- .free_peer_state = protocol_free_peer_state,
-
- .generate_key = protocol_generate_key,
-};
diff --git a/src/types.h b/src/types.h
index 504b6dd..3808b32 100644
--- a/src/types.h
+++ b/src/types.h
@@ -66,14 +66,16 @@ typedef struct _fastd_config fastd_config;
typedef struct _fastd_context fastd_context;
typedef struct _fastd_protocol fastd_protocol;
+typedef struct _fastd_method fastd_method;
typedef struct _fastd_handshake fastd_handshake;
typedef struct _fastd_string_stack fastd_string_stack;
-/* May be defined by the protocol however it likes */
+/* May be defined by the protocol/method however it likes */
typedef struct _fastd_protocol_config fastd_protocol_config;
typedef struct _fastd_protocol_peer_config fastd_protocol_peer_config;
typedef struct _fastd_protocol_peer_state fastd_protocol_peer_state;
+typedef struct _fastd_method_session_state fastd_method_session_state;
#endif /* _FASTD_TYPES_H_ */