diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 19 | ||||
-rw-r--r-- | src/config.c | 47 | ||||
-rw-r--r-- | src/config.l | 1 | ||||
-rw-r--r-- | src/config.y | 28 | ||||
-rw-r--r-- | src/fastd.c | 12 | ||||
-rw-r--r-- | src/fastd.h | 25 | ||||
-rw-r--r-- | src/handshake.c | 17 | ||||
-rw-r--r-- | src/handshake.h | 1 | ||||
-rw-r--r-- | src/method_null.c | 80 | ||||
-rw-r--r-- | src/method_xsalsa20_poly1305.c | 205 | ||||
-rw-r--r-- | src/protocol_ec25519_fhmqvc.c (renamed from src/protocol_ec25519_fhmqvc_xsalsa20_poly1305.c) | 222 | ||||
-rw-r--r-- | src/protocol_null.c | 158 | ||||
-rw-r--r-- | src/types.h | 4 |
13 files changed, 443 insertions, 376 deletions
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_ */ |