diff options
-rw-r--r-- | src/async.c | 2 | ||||
-rw-r--r-- | src/async.h | 2 | ||||
-rw-r--r-- | src/buffer.h | 2 | ||||
-rw-r--r-- | src/capabilities.c | 7 | ||||
-rw-r--r-- | src/compat.h | 2 | ||||
-rw-r--r-- | src/crypto.h | 23 | ||||
-rw-r--r-- | src/dlist.h | 6 | ||||
-rw-r--r-- | src/fastd.h | 2 | ||||
-rw-r--r-- | src/handshake.c | 25 | ||||
-rw-r--r-- | src/handshake.h | 2 | ||||
-rw-r--r-- | src/log.h | 2 | ||||
-rw-r--r-- | src/method.h | 2 | ||||
-rw-r--r-- | src/methods/common.c | 9 | ||||
-rw-r--r-- | src/methods/common.h | 53 | ||||
-rw-r--r-- | src/peer.c | 2 | ||||
-rw-r--r-- | src/peer.h | 2 | ||||
-rw-r--r-- | src/poll.c | 2 | ||||
-rw-r--r-- | src/poll.h | 2 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c | 12 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h | 60 | ||||
-rw-r--r-- | src/protocols/ec25519_fhmqvc/handshake.h | 36 | ||||
-rw-r--r-- | src/random.c | 6 | ||||
-rw-r--r-- | src/receive.c | 16 | ||||
-rw-r--r-- | src/resolve.c | 2 | ||||
-rw-r--r-- | src/send.c | 15 | ||||
-rw-r--r-- | src/sha256.c | 2 | ||||
-rw-r--r-- | src/sha256.h | 2 | ||||
-rw-r--r-- | src/shell.c | 2 | ||||
-rw-r--r-- | src/shell.h | 2 | ||||
-rw-r--r-- | src/tuntap.c | 6 | ||||
-rw-r--r-- | src/types.h | 2 | ||||
-rw-r--r-- | src/vector.c | 2 | ||||
-rw-r--r-- | src/vector.h | 6 |
33 files changed, 257 insertions, 61 deletions
diff --git a/src/async.c b/src/async.c index fb1af41..fa93cd0 100644 --- a/src/async.c +++ b/src/async.c @@ -24,7 +24,7 @@ */ /** - \file src/async.c + \file Asynchronous notifications */ diff --git a/src/async.h b/src/async.h index 4622c3c..e3298d4 100644 --- a/src/async.h +++ b/src/async.h @@ -24,7 +24,7 @@ */ /** - \file src/async.h + \file Asynchronous notifications */ diff --git a/src/buffer.h b/src/buffer.h index afd18d5..5b2e16a 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -24,7 +24,7 @@ */ /** - \file src/buffer.h + \file Buffer management */ diff --git a/src/capabilities.c b/src/capabilities.c index 8a7e823..9da3fd4 100644 --- a/src/capabilities.c +++ b/src/capabilities.c @@ -23,6 +23,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Handling of POSIX capabilities +*/ + #include "fastd.h" @@ -31,6 +37,7 @@ #include <sys/capability.h> +/** Tries to acquire a capability */ static void try_cap(cap_value_t cap) { char *name = cap_to_name(cap); if (!name) diff --git a/src/compat.h b/src/compat.h index 25e6be5..af7264d 100644 --- a/src/compat.h +++ b/src/compat.h @@ -24,7 +24,7 @@ */ /** - \file src/compat.h + \file Portablity definitions */ diff --git a/src/crypto.h b/src/crypto.h index fbb77ec..8f94fae 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -24,7 +24,7 @@ */ /** - \file src/crypto.h + \file Cyptographic algorithm API and utilities */ @@ -38,29 +38,41 @@ #include <string.h> +/** Contains information about a cipher algorithm */ struct fastd_cipher_info { - size_t key_length; - size_t iv_length; + size_t key_length; /**< The key length used by the cipher */ + size_t iv_length; /**< The initialization vector length used by the cipher */ }; +/** A stream cipher implementation */ struct fastd_cipher { + /**< Checks if the algorithm is available on the platform used. If NULL, the algorithm is always available. */ bool (*available)(void); + /** Initializes a cipher context with the given key */ fastd_cipher_state_t* (*init)(const uint8_t *key); + /** Encrypts or decrypts data */ bool (*crypt)(const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv); + /** Frees a cipher context */ void (*free)(fastd_cipher_state_t *state); }; +/** Contains information about a message authentication code algorithm */ struct fastd_mac_info { - size_t key_length; + size_t key_length; /**< The key length used by the MAC */ }; +/** A MAC implementation */ struct fastd_mac { + /**< Checks if the algorithm is available on the platform used. If NULL, the algorithm is always available. */ bool (*available)(void); + /** Initializes a MAC context with the given key */ fastd_mac_state_t* (*init)(const uint8_t *key); + /** Computes the MAC of data blocks */ bool (*hash)(const fastd_mac_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks); + /** Frees a MAC context */ void (*free)(fastd_mac_state_t *state); }; @@ -80,16 +92,19 @@ const fastd_mac_info_t* fastd_mac_info_get_by_name(const char *name); const fastd_mac_t* fastd_mac_get(const fastd_mac_info_t *info); +/** Sets a range of memory to zero, ensuring the operation can't be optimized out by the compiler */ static inline void secure_memzero(void *s, size_t n) { memset(s, 0, n); __asm__ volatile("" : : "m"(s)); } +/** XORs two blocks of data */ static inline void xor(fastd_block128_t *x, const fastd_block128_t *a, const fastd_block128_t *b) { x->qw[0] = a->qw[0] ^ b->qw[0]; x->qw[1] = a->qw[1] ^ b->qw[1]; } +/** XORs one block of data into another */ static inline void xor_a(fastd_block128_t *x, const fastd_block128_t *a) { xor(x, x, a); } diff --git a/src/dlist.h b/src/dlist.h index a8118f0..0ca6928 100644 --- a/src/dlist.h +++ b/src/dlist.h @@ -24,7 +24,7 @@ */ /** - \file src/dlist.h + \file Doubly-linked lists */ @@ -38,8 +38,8 @@ typedef struct fastd_dlist_head fastd_dlist_head_t; /** Doubly-linked list element */ struct fastd_dlist_head { - fastd_dlist_head_t *prev; - fastd_dlist_head_t *next; + fastd_dlist_head_t *prev; /**< The next element of the list or NULL */ + fastd_dlist_head_t *next; /**< The previous element of the list or NULL */ }; diff --git a/src/fastd.h b/src/fastd.h index 50f90a9..3dd5568 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -24,7 +24,7 @@ */ /** - \file src/fastd.h + \file \em fastd main header file defining most data structures */ diff --git a/src/handshake.c b/src/handshake.c index d0d6016..e8b2197 100644 --- a/src/handshake.c +++ b/src/handshake.c @@ -23,6 +23,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Functions and structures for composing and decomposing handshake packets +*/ + #include "handshake.h" #include "method.h" @@ -30,6 +36,7 @@ #include <fastd_version.h> +/** Human-readable names for the TLV record types */ static const char *const RECORD_TYPES[RECORD_MAX] = { "handshake type", "reply code", @@ -50,10 +57,14 @@ static const char *const RECORD_TYPES[RECORD_MAX] = { }; +/** Reads a TLV record as an 8bit integer */ #define AS_UINT8(ptr) (*(uint8_t*)(ptr).data) + +/** Reads a TLV record as a 16bit integer (big endian) */ #define AS_UINT16(ptr) ((*(uint8_t*)(ptr).data) + (*((uint8_t*)(ptr).data+1) << 8)) +/** Generates a zero-separated list of supported methods */ static uint8_t* create_method_list(size_t *len) { *len = 0; @@ -72,6 +83,7 @@ static uint8_t* create_method_list(size_t *len) { return ret; } +/** Checks if a string is equal to a buffer with a maximum length */ static inline bool string_equal(const char *str, const char *buf, size_t maxlen) { if (strlen(str) != strnlen(buf, maxlen)) return false; @@ -79,10 +91,12 @@ static inline bool string_equal(const char *str, const char *buf, size_t maxlen) return !strncmp(str, buf, maxlen); } +/** Checks if a string is equal to the value of a TLV record */ static inline bool record_equal(const char *str, const fastd_handshake_record_t *record) { return string_equal(str, (const char*)record->data, record->length); } +/** Parses a list of zero-separated strings */ static fastd_string_stack_t* parse_string_list(const uint8_t *data, size_t len) { const uint8_t *end = data+len; fastd_string_stack_t *ret = NULL; @@ -97,6 +111,7 @@ static fastd_string_stack_t* parse_string_list(const uint8_t *data, size_t len) return ret; } +/** Allocates and initializes a new handshake packet */ static fastd_buffer_t new_handshake(uint8_t type, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) { size_t version_len = strlen(FASTD_VERSION); size_t protocol_len = strlen(conf.protocol->name); @@ -139,16 +154,19 @@ static fastd_buffer_t new_handshake(uint8_t type, const fastd_method_info_t *met return buffer; } +/** Allocates and initializes a new initial handshake packet */ fastd_buffer_t fastd_handshake_new_init(size_t tail_space) { return new_handshake(1, NULL, !conf.secure_handshakes, tail_space); } +/** Allocates and initializes a new reply handshake packet */ fastd_buffer_t fastd_handshake_new_reply(uint8_t type, const fastd_method_info_t *method, bool with_method_list, size_t tail_space) { fastd_buffer_t buffer = new_handshake(type, method, with_method_list, tail_space); fastd_handshake_add_uint8(&buffer, RECORD_REPLY_CODE, 0); return buffer; } +/** Prints the error corresponding to the given reply code and error detail */ static void print_error(const char *prefix, const fastd_peer_address_t *remote_addr, uint8_t reply_code, uint8_t error_detail) { const char *error_field_str; @@ -174,6 +192,7 @@ static void print_error(const char *prefix, const fastd_peer_address_t *remote_a } } +/** Sends an error reply to a peer */ static void send_error(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake, uint8_t reply_code, uint8_t error_detail) { print_error("sending", remote_addr, reply_code, error_detail); @@ -190,6 +209,7 @@ static void send_error(fastd_socket_t *sock, const fastd_peer_address_t *local_a fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer); } +/** Parses the TLV records of a handshake */ static inline fastd_handshake_t parse_tlvs(const fastd_buffer_t *buffer) { fastd_handshake_t handshake = {}; @@ -232,6 +252,7 @@ static inline fastd_handshake_t parse_tlvs(const fastd_buffer_t *buffer) { return handshake; } +/** Prints the error found in a received handshake */ static inline void print_error_reply(const fastd_peer_address_t *remote_addr, const fastd_handshake_t *handshake) { uint8_t reply_code = AS_UINT8(handshake->records[RECORD_REPLY_CODE]); uint8_t error_detail = RECORD_MAX; @@ -242,6 +263,7 @@ static inline void print_error_reply(const fastd_peer_address_t *remote_addr, co print_error("received", remote_addr, reply_code, error_detail); } +/** Does some basic validity checks on a received handshake */ static inline bool check_records(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const fastd_handshake_t *handshake) { if (handshake->records[RECORD_PROTOCOL_NAME].data) { if (!record_equal(conf.protocol->name, &handshake->records[RECORD_PROTOCOL_NAME])) { @@ -281,6 +303,7 @@ static inline bool check_records(fastd_socket_t *sock, const fastd_peer_address_ return true; } +/** Returns the method info with a specified name and length */ static inline const fastd_method_info_t* get_method_by_name(const char *name, size_t n) { char name0[n+1]; memcpy(name0, name, n); @@ -289,6 +312,7 @@ static inline const fastd_method_info_t* get_method_by_name(const char *name, si return fastd_method_get_by_name(name0); } +/** Returns the most appropriate method to negotiate with a peer a handshake was received from */ static inline const fastd_method_info_t* get_method(const fastd_handshake_t *handshake) { if (handshake->records[RECORD_METHOD_LIST].data && handshake->records[RECORD_METHOD_LIST].length) { fastd_string_stack_t *method_list = parse_string_list(handshake->records[RECORD_METHOD_LIST].data, handshake->records[RECORD_METHOD_LIST].length); @@ -314,6 +338,7 @@ static inline const fastd_method_info_t* get_method(const fastd_handshake_t *han return get_method_by_name((const char*)handshake->records[RECORD_METHOD_NAME].data, handshake->records[RECORD_METHOD_NAME].length); } +/** Handles a handshake packet */ void fastd_handshake_handle(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer) { char *peer_version = NULL; const fastd_method_info_t *method = NULL; diff --git a/src/handshake.h b/src/handshake.h index 34597ed..2be71e5 100644 --- a/src/handshake.h +++ b/src/handshake.h @@ -24,7 +24,7 @@ */ /** - \file src/handshake.h + \file Functions and structures for composing and decomposing handshake packets */ @@ -24,7 +24,7 @@ */ /** - \file src/log.h + \file Logging functions and macros */ diff --git a/src/method.h b/src/method.h index da70a7b..4ae9e0a 100644 --- a/src/method.h +++ b/src/method.h @@ -24,7 +24,7 @@ */ /** - \file src/method.h + \file Management of encryption methods */ diff --git a/src/methods/common.c b/src/methods/common.c index 3fb8561..d26f009 100644 --- a/src/methods/common.c +++ b/src/methods/common.c @@ -23,10 +23,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Definitions for the common packet format used by most methods +*/ + #include "common.h" +/** Common initialization for a new session */ void fastd_method_common_init(fastd_method_common_t *session, bool initiator) { memset(session, 0, sizeof(*session)); @@ -42,6 +49,7 @@ void fastd_method_common_init(fastd_method_common_t *session, bool initiator) { } } +/** Checks if a received nonce is valid */ bool fastd_method_is_nonce_valid(const fastd_method_common_t *session, const uint8_t nonce[COMMON_NONCEBYTES], int64_t *age) { if ((nonce[0] & 1) != (session->receive_nonce[0] & 1)) return false; @@ -67,6 +75,7 @@ bool fastd_method_is_nonce_valid(const fastd_method_common_t *session, const uin return true; } +/** Checks if a possibly reordered packet should be accepted */ bool fastd_method_reorder_check(fastd_peer_t *peer, fastd_method_common_t *session, const uint8_t nonce[COMMON_NONCEBYTES], int64_t age) { if (age < 0) { size_t shift = age < (-64) ? 64 : ((size_t)-age); diff --git a/src/methods/common.h b/src/methods/common.h index 7b0a4ff..7a06f92 100644 --- a/src/methods/common.h +++ b/src/methods/common.h @@ -23,26 +23,37 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Definitions for the common packet format used by most methods +*/ + #pragma once #include "../fastd.h" +/** The length of the nonce in the common method packet header */ #define COMMON_NONCEBYTES 6 +/** The length of the flags in the common method packet header */ #define COMMON_FLAGBYTES 1 +/** The length of the common method packet header */ #define COMMON_HEADBYTES (COMMON_NONCEBYTES+COMMON_FLAGBYTES) + +/** Common method session state */ typedef struct fastd_method_common { - struct timespec valid_till; - struct timespec refresh_after; + struct timespec valid_till; /**< How long the session is valid */ + struct timespec refresh_after; /**< When to try refreshing the session */ - uint8_t send_nonce[COMMON_NONCEBYTES]; - uint8_t receive_nonce[COMMON_NONCEBYTES]; + uint8_t send_nonce[COMMON_NONCEBYTES]; /**< The next nonce to use */ + uint8_t receive_nonce[COMMON_NONCEBYTES]; /**< The hightest nonce received to far for this session */ - struct timespec reorder_timeout; - uint64_t receive_reorder_seen; + struct timespec reorder_timeout; /**< How long to packets with a lower sequence number (nonce) than the newest received */ + uint64_t receive_reorder_seen; /**< Bitmap specifying which of the 64 sequence numbers (nonces) before \a receive_nonce have bit seen */ } fastd_method_common_t; @@ -51,6 +62,11 @@ bool fastd_method_is_nonce_valid(const fastd_method_common_t *session, const uin bool fastd_method_reorder_check(fastd_peer_t *peer, fastd_method_common_t *session, const uint8_t nonce[COMMON_NONCEBYTES], int64_t age); +/** + The common \a session_is_valid implementation + + A session is valid when session->valid_till has not timeouted, unless almost all nonces have been used up (which \b should be impossible) +*/ static inline bool fastd_method_session_common_is_valid(const fastd_method_common_t *session) { if (session->send_nonce[0] == 0xff && session->send_nonce[1] == 0xff) return false; @@ -58,10 +74,20 @@ static inline bool fastd_method_session_common_is_valid(const fastd_method_commo return (!fastd_timed_out(&session->valid_till)); } +/** + The common \a session_is_initiator implementation + + The initiator of a session uses the odd nonces, the responder the even ones. +*/ static inline bool fastd_method_session_common_is_initiator(const fastd_method_common_t *session) { return (session->send_nonce[COMMON_NONCEBYTES-1] & 1); } +/** + The common \a session_want_refresh implementation + + A session wants to be refreshed when session->refresh_after has timeouted, or if lots of nonces have been used up +*/ static inline bool fastd_method_session_common_want_refresh(const fastd_method_common_t *session) { if (session->send_nonce[0] == 0xff) return true; @@ -72,6 +98,7 @@ static inline bool fastd_method_session_common_want_refresh(const fastd_method_c return false; } +/** The common \a session_superseded implementation */ static inline void fastd_method_session_common_superseded(fastd_method_common_t *session) { struct timespec valid_max = fastd_in_seconds(KEY_VALID_OLD); @@ -79,6 +106,12 @@ static inline void fastd_method_session_common_superseded(fastd_method_common_t session->valid_till = valid_max; } +/** + Increments the send nonce + + As one side of a connection uses the even nonces and the other side the odd ones, + the nonce is always incremented by 2. +*/ static inline void fastd_method_increment_nonce(fastd_method_common_t *session) { session->send_nonce[COMMON_NONCEBYTES-1] += 2; @@ -91,22 +124,30 @@ static inline void fastd_method_increment_nonce(fastd_method_common_t *session) } } +/** Adds the common header to a packet buffer */ static inline void fastd_method_put_common_header(fastd_buffer_t *buffer, const uint8_t nonce[COMMON_NONCEBYTES], uint8_t flags) { fastd_buffer_pull_head_from(buffer, nonce, COMMON_NONCEBYTES); fastd_buffer_pull_head_from(buffer, &flags, 1); } +/** Removes the common header from a packet buffer */ static inline void fastd_method_take_common_header(fastd_buffer_t *buffer, uint8_t nonce[COMMON_NONCEBYTES], uint8_t *flags) { fastd_buffer_push_head_to(buffer, flags, 1); fastd_buffer_push_head_to(buffer, nonce, COMMON_NONCEBYTES); } +/** Handles the common header of a packet */ static inline bool fastd_method_handle_common_header(const fastd_method_common_t *session, fastd_buffer_t *buffer, uint8_t nonce[COMMON_NONCEBYTES], uint8_t *flags, int64_t *age) { fastd_method_take_common_header(buffer, nonce, flags); return fastd_method_is_nonce_valid(session, nonce, age); } +/** + Expands a nonce from COMMON_NONCEBYTES to a buffer of arbitrary length + + The last byte of the buffer is set to 1 as many cryptographic algorithms are specified to have a counter starting with 1 concatenated to the nonce +*/ static inline void fastd_method_expand_nonce(uint8_t *buf, const uint8_t nonce[COMMON_NONCEBYTES], size_t len) { if (!len) return; @@ -24,7 +24,7 @@ */ /** - \file src/peer.c + \file Implementations of functions for peer management */ @@ -24,7 +24,7 @@ */ /** - \file src/peer.h + \file Structures and functions for peer management */ @@ -24,7 +24,7 @@ */ /** - \file src/poll.c + \file Portable polling API implementations */ @@ -24,7 +24,7 @@ */ /** - \file src/poll.h + \file Portable polling API */ diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c index 70944fe..b97bf4d 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c @@ -27,6 +27,7 @@ #include "ec25519_fhmqvc.h" +/** Converts a private or public key from a hexadecimal string representation to a uint8 array */ static inline bool read_key(uint8_t key[32], const char *hexkey) { if ((strlen(hexkey) != 64) || (strspn(hexkey, "0123456789abcdefABCDEF") != 64)) return false; @@ -38,6 +39,7 @@ static inline bool read_key(uint8_t key[32], const char *hexkey) { return true; } +/** Checks if the current session with a peers needs refreshing */ static inline void check_session_refresh(fastd_peer_t *peer) { protocol_session_t *session = &peer->protocol_state->session; @@ -49,6 +51,7 @@ static inline void check_session_refresh(fastd_peer_t *peer) { } } +/** Initializes the protocol-specific configuration */ static fastd_protocol_config_t* protocol_init(void) { fastd_protocol_config_t *protocol_config = malloc(sizeof(fastd_protocol_config_t)); @@ -65,6 +68,7 @@ static fastd_protocol_config_t* protocol_init(void) { return protocol_config; } +/** Checks if a peer configuration is valid */ static void protocol_peer_verify(fastd_peer_config_t *peer_conf) { if (!peer_conf->key) exit_error("no key configured for peer `%s'", peer_conf->name); @@ -74,6 +78,7 @@ static void protocol_peer_verify(fastd_peer_config_t *peer_conf) { exit_error("invalid key configured for peer `%s'", peer_conf->name); } +/** Initializes the protocol-specific peer configuration */ static void protocol_peer_configure(fastd_peer_config_t *peer_conf) { if (peer_conf->protocol_config) return; @@ -96,6 +101,7 @@ static void protocol_peer_configure(fastd_peer_config_t *peer_conf) { pr_debug("found own key as `%s', ignoring peer", peer_conf->name); } +/** Checks if the current session with a peer is valid and resets the connection if not */ static inline bool check_session(fastd_peer_t *peer) { if (is_session_valid(&peer->protocol_state->session)) return true; @@ -105,6 +111,7 @@ static inline bool check_session(fastd_peer_t *peer) { return false; } +/** Handles a payload packet received from a peer */ static void protocol_handle_recv(fastd_peer_t *peer, fastd_buffer_t buffer) { if (!peer->protocol_state || !check_session(peer)) goto fail; @@ -158,6 +165,7 @@ static void protocol_handle_recv(fastd_peer_t *peer, fastd_buffer_t buffer) { fastd_buffer_free(buffer); } +/** Encrypts and sends a packet to a peer using a specified session */ static void session_send(fastd_peer_t *peer, fastd_buffer_t buffer, protocol_session_t *session) { size_t stat_size = buffer.len; @@ -172,6 +180,7 @@ static void session_send(fastd_peer_t *peer, fastd_buffer_t buffer, protocol_ses peer->keepalive_timeout = fastd_in_seconds(KEEPALIVE_TIMEOUT); } +/** Encrypts and sends a packet to a peer */ static void protocol_send(fastd_peer_t *peer, fastd_buffer_t buffer) { if (!peer->protocol_state || !fastd_peer_is_established(peer) || !check_session(peer)) { fastd_buffer_free(buffer); @@ -189,10 +198,13 @@ static void protocol_send(fastd_peer_t *peer, fastd_buffer_t buffer) { } } +/** Sends an empty payload packet (i.e. keepalive) to a peer using a specified session */ void fastd_protocol_ec25519_fhmqvc_send_empty(fastd_peer_t *peer, protocol_session_t *session) { session_send(peer, fastd_buffer_alloc(0, alignto(session->method->provider->min_encrypt_head_space, 8), session->method->provider->min_encrypt_tail_space), session); } + +/** The \em ec25519-fhmqvc protocol definition */ const fastd_protocol_t fastd_protocol_ec25519_fhmqvc = { .name = "ec25519-fhmqvc", diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h index 6dcc149..fb07d19 100644 --- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h +++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.h @@ -23,6 +23,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + ec25519-fhmqvc protocol: general definitions +*/ + #pragma once @@ -34,49 +40,64 @@ #include <libuecc/ecc.h> +/** The length of a \em ec25519-fhmqvc public key */ #define PUBLICKEYBYTES 32 + +/** The length of a \em ec25519-fhmqvc private key */ #define SECRETKEYBYTES 32 +/** A \e libuecc int256, aligned to 32bit, so it can be used as input to the SHA256 functions */ typedef union aligned_int256 { - ecc_int256_t int256; - uint32_t u32[8]; - uint8_t u8[32]; + ecc_int256_t int256; /**< ecc_int256_t access */ + uint32_t u32[8]; /**< 32bit-wise access */ + uint8_t u8[32]; /**< byte-wise access */ } aligned_int256_t; +/** A keypair */ typedef struct keypair { - ecc_int256_t secret; - aligned_int256_t public; + ecc_int256_t secret; /**< The section key */ + aligned_int256_t public; /**< The public key */ } keypair_t; +/** The protocol-specific configuration */ struct fastd_protocol_config { - keypair_t key; + keypair_t key; /**< The own keypair */ }; +/** The protocol-specific peer configuration */ struct fastd_protocol_peer_config { - aligned_int256_t public_key; + aligned_int256_t public_key; /**< The peer's public key */ }; +/** Session state */ typedef struct protocol_session { + /** + Stores if remaining handshakes have been unqueued after session establishment. + + After a session has been established, further scheduled handshakes aren't unqueued + before it has been ensured the other side has established the session as well. + */ bool handshakes_cleaned; - bool refreshing; + bool refreshing; /**< true if a session refresh has been triggered by the local side */ - const fastd_method_info_t *method; - fastd_method_session_state_t *method_state; + const fastd_method_info_t *method; /**< The used crypto method */ + fastd_method_session_state_t *method_state; /**< The method-specific state */ } protocol_session_t; +/** Protocol-specific peer state */ struct fastd_protocol_peer_state { - protocol_session_t old_session; - protocol_session_t session; + protocol_session_t old_session; /**< An old, not yet invalidated session */ + protocol_session_t session; /**< The newest session */ - uint64_t last_serial; + uint64_t last_serial; /**< The serial number of the ephemeral keypair used for the last session establishment */ /* handshake cache */ - uint64_t last_handshake_serial; - aligned_int256_t peer_handshake_key; - aligned_int256_t sigma; - fastd_sha256_t shared_handshake_key; - fastd_sha256_t shared_handshake_key_compat; + uint64_t last_handshake_serial; /**< The serial number of the ephemeral keypair used in the last handshake */ + aligned_int256_t peer_handshake_key; /**< The peer's ephemeral public key used in the last handshake */ + aligned_int256_t sigma; /**< The value of sigma used in the last handshake */ + fastd_sha256_t shared_handshake_key; /**< The shared handshake key used in the last handshake */ + fastd_sha256_t shared_handshake_key_compat; /**< The shared handshake key used in the last handshake (pre-v11 compatiblity protocol) */ }; @@ -103,13 +124,14 @@ void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const f bool fastd_protocol_ec25519_fhmqvc_describe_peer(const fastd_peer_t *peer, char *buf, size_t len); +/** Converts a 32 byte value to a hexadecimal string representation */ static inline void hexdump(char out[65], const unsigned char d[32]) { size_t i; for (i = 0; i < 32; i++) snprintf(out+2*i, 3, "%02x", d[i]); } - +/** Checks if a session is currently valid */ static inline bool is_session_valid(const protocol_session_t *session) { return (session->method && session->method->provider->session_is_valid(session->method_state)); } diff --git a/src/protocols/ec25519_fhmqvc/handshake.h b/src/protocols/ec25519_fhmqvc/handshake.h index 1578913..a05e542 100644 --- a/src/protocols/ec25519_fhmqvc/handshake.h +++ b/src/protocols/ec25519_fhmqvc/handshake.h @@ -23,30 +23,56 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + ec25519-fhmqvc protocol: handshake handling +*/ + #pragma once #include "ec25519_fhmqvc.h" +/** + An ephemeral keypair used for the handshake protocol + + When a keypair's \e preferred_till has timed out, a new keypair + will be generated. +*/ typedef struct handshake_key { + /** + With each keypair, the serial number gets incremented. + By saving the serial number for established sessions, + it can be ensured that no two sessions with the same peer are established + with the same keypair + */ uint64_t serial; - struct timespec preferred_till; - struct timespec valid_till; - keypair_t key; + struct timespec preferred_till; /**< Specifies how long this keypair will be used for new handshakes */ + struct timespec valid_till; /**< Specifies how long handshakes using this keypair will be answered */ + + keypair_t key; /**< The actual keypair */ } handshake_key_t; +/** + The protocol-specific global state + + There are up to two keys valid at the same time. +*/ struct fastd_protocol_state { - handshake_key_t prev_handshake_key; - handshake_key_t handshake_key; + handshake_key_t prev_handshake_key; /**< The previously generated handshake keypair */ + handshake_key_t handshake_key; /**< The newest handshake keypair */ }; +/** Checks if a handshake keypair is currently valid */ static inline bool is_handshake_key_valid(const handshake_key_t *handshake_key) { return !fastd_timed_out(&handshake_key->valid_till); } +/** Checks if a handshake keypair is currently peferred */ static inline bool is_handshake_key_preferred(const handshake_key_t *handshake_key) { return !fastd_timed_out(&handshake_key->preferred_till); } diff --git a/src/random.c b/src/random.c index 71a3ad1..72a238b 100644 --- a/src/random.c +++ b/src/random.c @@ -23,6 +23,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Utilities for random data +*/ + #include "fastd.h" diff --git a/src/receive.c b/src/receive.c index 3813d7f..aae4f8f 100644 --- a/src/receive.c +++ b/src/receive.c @@ -23,6 +23,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Functions for receiving and handling packets +*/ + #include "fastd.h" #include "handshake.h" @@ -30,6 +36,7 @@ #include "peer_hashtable.h" +/** Handles the ancillary control messages of received packets */ static inline void handle_socket_control(struct msghdr *message, const fastd_socket_t *sock, fastd_peer_address_t *local_addr) { memset(local_addr, 0, sizeof(fastd_peer_address_t)); @@ -77,6 +84,11 @@ static inline void handle_socket_control(struct msghdr *message, const fastd_soc } } +/** + Checks if a handshake should be sent after an unexpected payload packet has been received + + backoff_unknown() tries to avoid flooding hosts with handshakes. +*/ static bool backoff_unknown(const fastd_peer_address_t *addr) { size_t i; for (i = 0; i < array_size(ctx.unknown_handshakes); i++) { @@ -104,6 +116,7 @@ static bool backoff_unknown(const fastd_peer_address_t *addr) { return false; } +/** Handles a packet received from a known peer address */ static inline void handle_socket_receive_known(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer) { if (!fastd_peer_may_connect(peer)) { fastd_buffer_free(buffer); @@ -131,10 +144,12 @@ static inline void handle_socket_receive_known(fastd_socket_t *sock, const fastd } } +/** Determines if packets from known addresses are accepted */ static inline bool allow_unknown_peers(void) { return conf.has_floating || fastd_allow_verify(); } +/** Handles a packet received from an unknown address */ static inline void handle_socket_receive_unknown(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) { const uint8_t *packet_type = buffer.data; fastd_buffer_push_head(&buffer, 1); @@ -152,6 +167,7 @@ static inline void handle_socket_receive_unknown(fastd_socket_t *sock, const fas } } +/** Handles a packet read from a socket */ static inline void handle_socket_receive(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_buffer_t buffer) { fastd_peer_t *peer = NULL; diff --git a/src/resolve.c b/src/resolve.c index 0635ddf..b37cef6 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -24,7 +24,7 @@ */ /** - \file src/resolve.c + \file DNS resolver functions */ @@ -23,11 +23,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Functions for sending packets +*/ + #include "fastd.h" #include "peer.h" +/** Adds packet info to ancillary control messages */ static inline void add_pktinfo(struct msghdr *msg, const fastd_peer_address_t *local_addr) { if (!local_addr) return; @@ -66,6 +73,7 @@ static inline void add_pktinfo(struct msghdr *msg, const fastd_peer_address_t *l } } +/** Adds statistics for a single packet of a given size */ static inline void count_stat(fastd_stats_t *stats, size_t stat_size) { if (stat_size) { stats->packets++; @@ -73,6 +81,7 @@ static inline void count_stat(fastd_stats_t *stats, size_t stat_size) { } } +/** Sends a packet of a given type */ static void send_type(const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, uint8_t packet_type, fastd_buffer_t buffer, size_t stat_size) { if (!sock) exit_bug("send: sock == NULL"); @@ -168,12 +177,12 @@ static void send_type(const fastd_socket_t *sock, const fastd_peer_address_t *lo fastd_buffer_free(buffer); } -/** Sends a payload packet to a peer */ +/** Sends a payload packet */ void fastd_send(const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer, size_t stat_size) { send_type(sock, local_addr, remote_addr, peer, PACKET_DATA, buffer, stat_size); } -/** Sends a handshake packet to a peer */ +/** Sends a handshake packet */ void fastd_send_handshake(const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, fastd_buffer_t buffer) { send_type(sock, local_addr, remote_addr, peer, PACKET_HANDSHAKE, buffer, 0); } @@ -205,6 +214,7 @@ static inline fastd_eth_addr_t get_dest_address(const fastd_buffer_t buffer) { return ret; } +/** Handles sending of a payload packet to a single peer in TAP mode */ static inline bool send_data_tap_single(fastd_buffer_t buffer, fastd_peer_t *source) { if (conf.mode != MODE_TAP) return false; @@ -233,6 +243,7 @@ static inline bool send_data_tap_single(fastd_buffer_t buffer, fastd_peer_t *sou return true; } +/** Sends a buffer of payload data to other peers */ void fastd_send_data(fastd_buffer_t buffer, fastd_peer_t *source) { if (send_data_tap_single(buffer, source)) return; diff --git a/src/sha256.c b/src/sha256.c index bed55fd..a9007da 100644 --- a/src/sha256.c +++ b/src/sha256.c @@ -24,7 +24,7 @@ */ /** - \file src/sha256.c + \file Small SHA256 and HMAC-SHA256 implementation */ diff --git a/src/sha256.h b/src/sha256.h index 2d45b2d..f553cad 100644 --- a/src/sha256.h +++ b/src/sha256.h @@ -24,7 +24,7 @@ */ /** - \file src/sha256.h + \file Small SHA256 and HMAC-SHA256 implementation */ diff --git a/src/shell.c b/src/shell.c index 524d38e..c573a85 100644 --- a/src/shell.c +++ b/src/shell.c @@ -25,7 +25,7 @@ /** - \file src/shell.c + \file Execution of shell commands and management of environment variables */ diff --git a/src/shell.h b/src/shell.h index 3a402f7..141126b 100644 --- a/src/shell.h +++ b/src/shell.h @@ -24,7 +24,7 @@ */ /** - \file src/shell.h + \file Execution of shell commands and management of environment variables */ diff --git a/src/tuntap.c b/src/tuntap.c index 7bd5f82..b5a5df9 100644 --- a/src/tuntap.c +++ b/src/tuntap.c @@ -23,6 +23,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + \file + + Management of the TUN/TAP interface +*/ #include "fastd.h" #include "poll.h" @@ -46,6 +51,7 @@ #endif +/** Defines if the platform uses an address family header on TUN interfaces */ #ifdef __linux__ static const bool multiaf_tun = false; #else diff --git a/src/types.h b/src/types.h index 6854a7c..d13828c 100644 --- a/src/types.h +++ b/src/types.h @@ -24,7 +24,7 @@ */ /** - \file src/types.h + \file Basic enums and typedefs for common types */ diff --git a/src/vector.c b/src/vector.c index 4b451b1..6e8c18d 100644 --- a/src/vector.c +++ b/src/vector.c @@ -24,7 +24,7 @@ */ /** - \file src/vector.c + \file Typesafe dynamically sized arrays */ diff --git a/src/vector.h b/src/vector.h index 526dfaf..0571d4d 100644 --- a/src/vector.h +++ b/src/vector.h @@ -24,7 +24,7 @@ */ /** - \file src/vector.h + \file Typesafe dynamically sized arrays */ @@ -37,8 +37,8 @@ /** A vector descriptor */ typedef struct fastd_vector_desc { - size_t allocated; - size_t length; + size_t allocated; /**< The number of elements currently allocated */ + size_t length; /**< The actual number of elements in the vector */ } fastd_vector_desc_t; |