summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/async.c4
-rw-r--r--src/config.c36
-rw-r--r--src/config.h6
-rw-r--r--src/cpuid.h13
-rw-r--r--src/crypto/cipher/aes128_ctr/aes128_ctr.c7
-rw-r--r--src/crypto/cipher/aes128_ctr/nacl/cipher_aes128_ctr_nacl.c14
-rw-r--r--src/crypto/cipher/aes128_ctr/openssl/aes128_ctr_openssl.c14
-rw-r--r--src/crypto/cipher/ciphers.c.in25
-rw-r--r--src/crypto/cipher/null/memcpy/null_memcpy.c10
-rw-r--r--src/crypto/cipher/null/null.c7
-rw-r--r--src/crypto/cipher/salsa20/nacl/salsa20_nacl.c14
-rw-r--r--src/crypto/cipher/salsa20/salsa20.c7
-rw-r--r--src/crypto/cipher/salsa20/xmm/salsa20_xmm.c22
-rw-r--r--src/crypto/cipher/salsa2012/nacl/salsa2012_nacl.c14
-rw-r--r--src/crypto/cipher/salsa2012/salsa2012.c7
-rw-r--r--src/crypto/cipher/salsa2012/xmm/salsa2012_xmm.c22
-rw-r--r--src/crypto/mac/ghash/builtin/ghash_builtin.c16
-rw-r--r--src/crypto/mac/ghash/ghash.c8
-rw-r--r--src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c8
-rw-r--r--src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h6
-rw-r--r--src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c22
-rw-r--r--src/crypto/mac/macs.c.in25
-rw-r--r--src/fastd.c47
-rw-r--r--src/fastd.h12
-rw-r--r--src/fastd_config.h.in68
-rw-r--r--src/hash.h10
-rw-r--r--src/hkdf_sha256.c7
-rw-r--r--src/hkdf_sha256.h7
-rw-r--r--src/lex.c51
-rw-r--r--src/lex.h6
-rw-r--r--src/log.c13
-rw-r--r--src/methods/cipher_test/cipher_test.c35
-rw-r--r--src/methods/composed_gmac/composed_gmac.c50
-rw-r--r--src/methods/generic_gmac/generic_gmac.c41
-rw-r--r--src/methods/generic_poly1305/generic_poly1305.c38
-rw-r--r--src/methods/methods.c.in8
-rw-r--r--src/methods/null/null.c28
-rw-r--r--src/methods/xsalsa20_poly1305/xsalsa20_poly1305.c39
-rw-r--r--src/options.c59
-rw-r--r--src/peer_hashtable.c21
-rw-r--r--src/peer_hashtable.h6
-rw-r--r--src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c6
-rw-r--r--src/protocols/ec25519_fhmqvc/handshake.c87
-rw-r--r--src/protocols/ec25519_fhmqvc/state.c18
-rw-r--r--src/protocols/ec25519_fhmqvc/util.c17
-rw-r--r--src/shell.c6
-rw-r--r--src/socket.c11
-rw-r--r--src/verify.c26
-rw-r--r--src/verify.h6
49 files changed, 919 insertions, 111 deletions
diff --git a/src/async.c b/src/async.c
index fa93cd0..a443cfe 100644
--- a/src/async.c
+++ b/src/async.c
@@ -36,8 +36,8 @@
/** The packet header used on the async notification sockets */
typedef struct fastd_async_hdr {
- fastd_async_type_t type;
- size_t len;
+ fastd_async_type_t type; /**< The type of the notification */
+ size_t len; /**< The length of the notification payload */
} fastd_async_hdr_t;
diff --git a/src/config.c b/src/config.c
index 8be44bb..6119669 100644
--- a/src/config.c
+++ b/src/config.c
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Configuration management
+*/
+
#include "fastd.h"
#include "config.h"
@@ -43,12 +49,14 @@
#include <sys/types.h>
+/** The global configuration */
fastd_config_t conf = {};
extern const fastd_protocol_t fastd_protocol_ec25519_fhmqvc;
+/** Initializes the global configuration with default values */
static void default_config(void) {
memset(&conf, 0, sizeof(fastd_config_t));
@@ -67,6 +75,7 @@ static void default_config(void) {
conf.peer_group->max_connections = -1;
}
+/** Handles the configuration of a handshake protocol */
void fastd_config_protocol(const char *name) {
if (!strcmp(name, "ec25519-fhmqvc"))
conf.protocol = &fastd_protocol_ec25519_fhmqvc;
@@ -74,6 +83,7 @@ void fastd_config_protocol(const char *name) {
exit_error("config error: protocol `%s' not supported", name);
}
+/** Handles the configuration of a crypto method */
void fastd_config_method(const char *name) {
fastd_string_stack_t **method;
@@ -87,16 +97,19 @@ void fastd_config_method(const char *name) {
*method = fastd_string_stack_dup(name);
}
+/** Handles the configuration of a cipher implementation */
void fastd_config_cipher(const char *name, const char *impl) {
if (!fastd_cipher_config(name, impl))
exit_error("config error: implementation `%s' is not supported for cipher `%s' (or cipher `%s' is not supported)", impl, name, name);
}
+/** Handles the configuration of a MAC implementation */
void fastd_config_mac(const char *name, const char *impl) {
if (!fastd_mac_config(name, impl))
exit_error("config error: implementation `%s' is not supported for MAC `%s' (or MAC `%s' is not supported)", impl, name, name);
}
+/** Handles the configuration of a bind address */
void fastd_config_bind_address(const fastd_peer_address_t *address, const char *bindtodev, bool default_v4, bool default_v6) {
#ifndef USE_BINDTODEVICE
if (bindtodev && !fastd_peer_address_is_v6_ll(address))
@@ -131,6 +144,7 @@ void fastd_config_bind_address(const fastd_peer_address_t *address, const char *
conf.bind_addr_default_v6 = addr;
}
+/** Handles the start of a peer group configuration */
void fastd_config_peer_group_push(const char *name) {
fastd_peer_group_t *group = calloc(1, sizeof(fastd_peer_group_t));
group->name = strdup(name);
@@ -144,10 +158,12 @@ void fastd_config_peer_group_push(const char *name) {
conf.peer_group = group;
}
+/** Handles the end of a peer group configuration */
void fastd_config_peer_group_pop(void) {
conf.peer_group = conf.peer_group->parent;
}
+/** Frees a peer group and its children */
static void free_peer_group(fastd_peer_group_t *group) {
while (group->children) {
fastd_peer_group_t *next = group->children->next;
@@ -160,6 +176,7 @@ static void free_peer_group(fastd_peer_group_t *group) {
free(group);
}
+/** Checks if a peer group has configured any peer dirs */
static bool has_peer_group_peer_dirs(const fastd_peer_group_t *group) {
if (group->peer_dirs)
return true;
@@ -173,6 +190,7 @@ static bool has_peer_group_peer_dirs(const fastd_peer_group_t *group) {
return false;
}
+/** Reads and processes all peer definitions in the current directory (which must also be supplied as the argument) */
static void read_peer_dir(const char *dir) {
DIR *dirh = opendir(".");
@@ -224,6 +242,7 @@ static void read_peer_dir(const char *dir) {
}
}
+/** Reads all peer configured directories */
static void read_peer_dirs(void) {
char *oldcwd = get_current_dir_name();
@@ -241,6 +260,7 @@ static void read_peer_dirs(void) {
free(oldcwd);
}
+/** Adds a peer directory to the configuration */
void fastd_add_peer_dir(const char *dir) {
char *oldcwd = get_current_dir_name();
@@ -259,6 +279,7 @@ void fastd_add_peer_dir(const char *dir) {
free(oldcwd);
}
+/** Reads and processes a configuration file */
bool fastd_read_config(const char *filename, bool peer_config, int depth) {
if (depth >= MAX_CONFIG_DEPTH)
exit_error("maximum config include depth exceeded");
@@ -348,6 +369,7 @@ bool fastd_read_config(const char *filename, bool peer_config, int depth) {
return ret;
}
+/** Gathers some information about the configured peers */
static void assess_peers(void) {
conf.has_floating = false;
@@ -358,7 +380,7 @@ static void assess_peers(void) {
}
}
-
+/** Loads information about the configured user and group */
static void configure_user(void) {
conf.uid = getuid();
conf.gid = getgid();
@@ -418,6 +440,7 @@ static void configure_user(void) {
}
}
+/** Initializes global configuration that depends on the configured methods */
static void configure_method_parameters(void) {
conf.max_overhead = 0;
conf.min_encrypt_head_space = 0;
@@ -442,6 +465,7 @@ static void configure_method_parameters(void) {
conf.min_decrypt_head_space = alignto(conf.min_decrypt_head_space, 16) + 8;
}
+/** Handles the initialization of the configured methods */
static void configure_methods(void) {
size_t n_methods = 0, i;
fastd_string_stack_t *method_name;
@@ -459,6 +483,7 @@ static void configure_methods(void) {
configure_method_parameters();
}
+/** Frees the resources used by the configured methods */
static void destroy_methods(void) {
size_t i;
for (i = 0; conf.methods[i].name; i++) {
@@ -468,6 +493,7 @@ static void destroy_methods(void) {
free(conf.methods);
}
+/** Loads the configuration */
void fastd_configure(int argc, char *const argv[]) {
default_config();
@@ -477,6 +503,7 @@ void fastd_configure(int argc, char *const argv[]) {
conf.log_stderr_level = LL_DEFAULT;
}
+/** Performs some basic checks on the configuration */
static void config_check_base(void) {
if (conf.ifname) {
if (strchr(conf.ifname, '/'))
@@ -503,6 +530,7 @@ static void config_check_base(void) {
#endif
}
+/** Performs more checks on the configuration */
void fastd_config_check(void) {
config_check_base();
@@ -523,6 +551,7 @@ void fastd_config_check(void) {
configure_methods();
}
+/** Performs the verify-config checks */
void fastd_config_verify(void) {
config_check_base();
configure_methods();
@@ -532,6 +561,7 @@ void fastd_config_verify(void) {
conf.protocol->peer_verify(peer);
}
+/** Reads the peer dirs of the current peer group and its children */
static void peer_dirs_read_peer_group(void) {
read_peer_dirs();
@@ -544,6 +574,7 @@ static void peer_dirs_read_peer_group(void) {
conf.peer_group = base;
}
+/** Deletes peer configs that have disappeared from a peer dir on reconfiguration */
static void peer_dirs_handle_old_peers(fastd_peer_config_t **old_peers, fastd_peer_config_t **new_peers) {
fastd_peer_config_t **peer, **next, **new_peer, **new_next;
for (peer = old_peers; *peer; peer = next) {
@@ -588,6 +619,7 @@ static void peer_dirs_handle_old_peers(fastd_peer_config_t **old_peers, fastd_pe
}
}
+/** Adds new peer configs on reconfiguration */
static void peer_dirs_handle_new_peers(fastd_peer_config_t **peers, fastd_peer_config_t *new_peers) {
fastd_peer_config_t *peer;
for (peer = new_peers; peer; peer = peer->next) {
@@ -600,6 +632,7 @@ static void peer_dirs_handle_new_peers(fastd_peer_config_t **peers, fastd_peer_c
}
}
+/** Refreshes the peer configurations from the configured peer dirs */
void fastd_config_load_peer_dirs(void) {
fastd_peer_config_t *old_peers = conf.peers;
conf.peers = NULL;
@@ -615,6 +648,7 @@ void fastd_config_load_peer_dirs(void) {
assess_peers();
}
+/** Frees all resources used by the global configuration */
void fastd_config_release(void) {
while (conf.peers)
fastd_peer_config_delete();
diff --git a/src/config.h b/src/config.h
index d4cbf93..3231f6d 100644
--- a/src/config.h
+++ b/src/config.h
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Configuration management
+*/
+
#pragma once
diff --git a/src/cpuid.h b/src/cpuid.h
index 546c258..9382156 100644
--- a/src/cpuid.h
+++ b/src/cpuid.h
@@ -23,17 +23,30 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ CPUID function for x86-based platforms
+*/
#pragma once
#include <stdint.h>
+/** The FXSR bit in the CPUID return value */
#define CPUID_FXSR ((uint64_t)1 << 24)
+
+/** The SSE2 bit in the CPUID return value */
#define CPUID_SSE2 ((uint64_t)1 << 26)
+
+/** The PCLMULQDQ bit in the CPUID return value */
#define CPUID_PCLMULQDQ ((uint64_t)1 << 33)
+
+/** The SSSE3 bit in the CPUID return value */
#define CPUID_SSSE3 ((uint64_t)1 << 41)
+/** Returns the ECX and EDX return values of CPUID function 1 as a single uint64 */
static inline uint64_t fastd_cpuid(void) {
unsigned eax, ebx, ecx, edx;
diff --git a/src/crypto/cipher/aes128_ctr/aes128_ctr.c b/src/crypto/cipher/aes128_ctr/aes128_ctr.c
index 52122d9..4448dd0 100644
--- a/src/crypto/cipher/aes128_ctr/aes128_ctr.c
+++ b/src/crypto/cipher/aes128_ctr/aes128_ctr.c
@@ -23,10 +23,17 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The aes128-ctr stream cipher
+*/
+
#include "../../../crypto.h"
+/** cipher info about aes128-ctr */
const fastd_cipher_info_t fastd_cipher_info_aes128_ctr = {
.key_length = 16,
.iv_length = 16,
diff --git a/src/crypto/cipher/aes128_ctr/nacl/cipher_aes128_ctr_nacl.c b/src/crypto/cipher/aes128_ctr/nacl/cipher_aes128_ctr_nacl.c
index 793b724..797572c 100644
--- a/src/crypto/cipher/aes128_ctr/nacl/cipher_aes128_ctr_nacl.c
+++ b/src/crypto/cipher/aes128_ctr/nacl/cipher_aes128_ctr_nacl.c
@@ -23,17 +23,25 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The aes128-ctr implementation from NaCl
+*/
+
#include "../../../../crypto.h"
#include <crypto_stream_aes128ctr.h>
+/** The cipher state */
struct __attribute__((aligned(16))) fastd_cipher_state {
- uint8_t d[crypto_stream_aes128ctr_BEFORENMBYTES] __attribute__((aligned(16)));
+ uint8_t d[crypto_stream_aes128ctr_BEFORENMBYTES] __attribute__((aligned(16))); /**< The unpacked AES key */
};
+/** Initializes the cipher state */
static fastd_cipher_state_t* aes128_ctr_init(const uint8_t *key) {
fastd_block128_t k;
memcpy(k.b, key, sizeof(fastd_block128_t));
@@ -47,11 +55,13 @@ static fastd_cipher_state_t* aes128_ctr_init(const uint8_t *key) {
return state;
}
+/** XORs data with the aes128-ctr cipher stream */
static bool aes128_ctr_crypt(const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv) {
crypto_stream_aes128ctr_xor_afternm(out->b, in->b, len, iv, state->d);
return true;
}
+/** Frees the cipher state */
static void aes128_ctr_free(fastd_cipher_state_t *state) {
if (state) {
secure_memzero(state, sizeof(*state));
@@ -59,6 +69,8 @@ static void aes128_ctr_free(fastd_cipher_state_t *state) {
}
}
+
+/** The nacl aes128-ctr implementation */
const fastd_cipher_t fastd_cipher_aes128_ctr_nacl = {
.init = aes128_ctr_init,
.crypt = aes128_ctr_crypt,
diff --git a/src/crypto/cipher/aes128_ctr/openssl/aes128_ctr_openssl.c b/src/crypto/cipher/aes128_ctr/openssl/aes128_ctr_openssl.c
index b47be57..2e06763 100644
--- a/src/crypto/cipher/aes128_ctr/openssl/aes128_ctr_openssl.c
+++ b/src/crypto/cipher/aes128_ctr/openssl/aes128_ctr_openssl.c
@@ -23,17 +23,25 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The aes128-ctr implementation from OpenSSL
+*/
+
#include "../../../../crypto.h"
#include <openssl/evp.h>
+/** The cipher state containing the OpenSSL cipher context */
struct fastd_cipher_state {
- EVP_CIPHER_CTX *aes;
+ EVP_CIPHER_CTX *aes; /**< The OpenSSL cipher context */
};
+/** Initializes the cipher state */
static fastd_cipher_state_t* aes128_ctr_init(const uint8_t *key) {
fastd_cipher_state_t *state = malloc(sizeof(fastd_cipher_state_t));
@@ -43,6 +51,7 @@ static fastd_cipher_state_t* aes128_ctr_init(const uint8_t *key) {
return state;
}
+/** XORs data with the aes128-ctr cipher stream */
static bool aes128_ctr_crypt(const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv) {
int clen, clen2;
@@ -61,6 +70,7 @@ static bool aes128_ctr_crypt(const fastd_cipher_state_t *state, fastd_block128_t
return true;
}
+/** Frees the cipher state */
static void aes128_ctr_free(fastd_cipher_state_t *state) {
if (state) {
EVP_CIPHER_CTX_free(state->aes);
@@ -68,6 +78,8 @@ static void aes128_ctr_free(fastd_cipher_state_t *state) {
}
}
+
+/** The openssl aes128-ctr implementation */
const fastd_cipher_t fastd_cipher_aes128_ctr_openssl = {
.available = fastd_true,
diff --git a/src/crypto/cipher/ciphers.c.in b/src/crypto/cipher/ciphers.c.in
index 01b5a35..7816bca 100644
--- a/src/crypto/cipher/ciphers.c.in
+++ b/src/crypto/cipher/ciphers.c.in
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Generated lists of ciphers and their implementations
+*/
+
#include <src/crypto.h>
#include <src/fastd.h>
@@ -30,30 +36,35 @@
@CIPHER_DEFINITIONS@
+/** A cipher implementation */
typedef struct fastd_cipher_impl {
- const char *name;
- const fastd_cipher_t *impl;
+ const char *name; /**< The name of the cipher implementation */
+ const fastd_cipher_t *impl; /**< The cipher implementation */
} fastd_cipher_impl_t;
+/** A cipher */
typedef struct cipher_entry {
- const char *name;
- const fastd_cipher_info_t *info;
- const fastd_cipher_impl_t *impls;
+ const char *name; /**< The name of the cipher */
+ const fastd_cipher_info_t *info; /**< The associated cipher information */
+ const fastd_cipher_impl_t *impls; /**< NULL-terminated array of cipher implementations */
} cipher_entry_t;
@CIPHER_IMPLS@
+/** The list of supported ciphers */
static const cipher_entry_t ciphers[] = { @CIPHER_LIST@
};
+/** The list of chosen cipher implementations */
static const fastd_cipher_t *cipher_conf[array_size(ciphers)] = {};
+/** Checks if a cipher implementation is available on the runtime platform */
static inline bool cipher_available(const fastd_cipher_t *cipher) {
return (!cipher->available) || cipher->available();
}
-/** Initializes the list of ciphers */
+/** Initializes the list of cipher implementations */
void fastd_cipher_init(void) {
size_t i, j;
for (i = 0; i < array_size(ciphers); i++) {
@@ -89,6 +100,7 @@ bool fastd_cipher_config(const char *name, const char *impl) {
return false;
}
+/** Returns information about the cipher with the specified name if there is an implementation available */
const fastd_cipher_info_t* fastd_cipher_info_get_by_name(const char *name) {
size_t i;
for (i = 0; i < array_size(ciphers); i++) {
@@ -104,6 +116,7 @@ const fastd_cipher_info_t* fastd_cipher_info_get_by_name(const char *name) {
return NULL;
}
+/** Returns the chosen cipher implementation for a given cipher */
const fastd_cipher_t* fastd_cipher_get(const fastd_cipher_info_t *info) {
size_t i;
for (i = 0; i < array_size(ciphers); i++) {
diff --git a/src/crypto/cipher/null/memcpy/null_memcpy.c b/src/crypto/cipher/null/memcpy/null_memcpy.c
index a2c0df9..089817f 100644
--- a/src/crypto/cipher/null/memcpy/null_memcpy.c
+++ b/src/crypto/cipher/null/memcpy/null_memcpy.c
@@ -23,22 +23,32 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The memcpy null implementation
+*/
+
#include "../../../../crypto.h"
+/** Doesn't do anything as the null cipher doesn't use any state */
static fastd_cipher_state_t* null_init(const uint8_t *key UNUSED) {
return NULL;
}
+/** Just copies the input data to the output */
static bool null_memcpy(const fastd_cipher_state_t *state UNUSED, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv UNUSED) {
memcpy(out, in, len);
return true;
}
+/** Doesn't do anything as the null cipher doesn't use any state */
static void null_free(fastd_cipher_state_t *state UNUSED) {
}
+/** The memcpy null implementation */
const fastd_cipher_t fastd_cipher_null_memcpy = {
.init = null_init,
.crypt = null_memcpy,
diff --git a/src/crypto/cipher/null/null.c b/src/crypto/cipher/null/null.c
index d6e4cab..353090a 100644
--- a/src/crypto/cipher/null/null.c
+++ b/src/crypto/cipher/null/null.c
@@ -23,10 +23,17 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The null cipher not performing any encryption
+*/
+
#include "../../../crypto.h"
+/** cipher info about the null cipher */
const fastd_cipher_info_t fastd_cipher_info_null = {
.key_length = 0,
.iv_length = 0,
diff --git a/src/crypto/cipher/salsa20/nacl/salsa20_nacl.c b/src/crypto/cipher/salsa20/nacl/salsa20_nacl.c
index 03ab1d9..6179bc2 100644
--- a/src/crypto/cipher/salsa20/nacl/salsa20_nacl.c
+++ b/src/crypto/cipher/salsa20/nacl/salsa20_nacl.c
@@ -23,17 +23,25 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The Salsa20 implementation from NaCl
+*/
+
#include "../../../../crypto.h"
#include <crypto_stream_salsa20.h>
+/** The cipher state */
struct fastd_cipher_state {
- uint8_t key[crypto_stream_salsa20_KEYBYTES];
+ uint8_t key[crypto_stream_salsa20_KEYBYTES]; /**< The encryption key */
};
+/** Initializes the cipher state */
static fastd_cipher_state_t* salsa20_init(const uint8_t *key) {
fastd_cipher_state_t *state = malloc(sizeof(fastd_cipher_state_t));
memcpy(state->key, key, crypto_stream_salsa20_KEYBYTES);
@@ -41,11 +49,13 @@ static fastd_cipher_state_t* salsa20_init(const uint8_t *key) {
return state;
}
+/** XORs data with the Salsa20 cipher stream */
static bool salsa20_crypt(const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv) {
crypto_stream_salsa20_xor(out->b, in->b, len, iv, state->key);
return true;
}
+/** Frees the cipher state */
static void salsa20_free(fastd_cipher_state_t *state) {
if (state) {
secure_memzero(state, sizeof(*state));
@@ -53,6 +63,8 @@ static void salsa20_free(fastd_cipher_state_t *state) {
}
}
+
+/** The nacl salsa20 implementation */
const fastd_cipher_t fastd_cipher_salsa20_nacl = {
.init = salsa20_init,
.crypt = salsa20_crypt,
diff --git a/src/crypto/cipher/salsa20/salsa20.c b/src/crypto/cipher/salsa20/salsa20.c
index f4f713f..dad6a6c 100644
--- a/src/crypto/cipher/salsa20/salsa20.c
+++ b/src/crypto/cipher/salsa20/salsa20.c
@@ -23,10 +23,17 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The Salsa20 stream cipher
+*/
+
#include "../../../crypto.h"
+/** Cipher info about Salsa20 */
const fastd_cipher_info_t fastd_cipher_info_salsa20 = {
.key_length = 32,
.iv_length = 8,
diff --git a/src/crypto/cipher/salsa20/xmm/salsa20_xmm.c b/src/crypto/cipher/salsa20/xmm/salsa20_xmm.c
index 52c4b6d..a85ed72 100644
--- a/src/crypto/cipher/salsa20/xmm/salsa20_xmm.c
+++ b/src/crypto/cipher/salsa20/xmm/salsa20_xmm.c
@@ -23,15 +23,21 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- The assembly implementations were written by D. J. Bernstein and are
- Public Domain. For more information see http://cr.yp.to/snuffle.html
+/**
+ \file
+
+ The XMM Salsa20 implementation for SSE2-capable x86 systems
+
+ The assembly implementations were written by D. J. Bernstein and are
+ Public Domain. For more information see http://cr.yp.to/snuffle.html
*/
+
#include "../../../../crypto.h"
#include "../../../../cpuid.h"
+/** The length of the key used by Salsa20 */
#define KEYBYTES 32
@@ -44,18 +50,22 @@
#endif
+/** The actual Salsa20 assembly implementation */
int crypto_stream_salsa20_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k);
+/** The cipher state */
struct fastd_cipher_state {
- uint8_t key[KEYBYTES];
+ uint8_t key[KEYBYTES]; /**< The encryption key */
};
+/** Checks if the runtime platform supports SSE2 */
static bool salsa20_available(void) {
return fastd_cpuid() & CPUID_SSE2;
}
+/** Initializes the cipher state */
static fastd_cipher_state_t* salsa20_init(const uint8_t *key) {
fastd_cipher_state_t *state = malloc(sizeof(fastd_cipher_state_t));
memcpy(state->key, key, KEYBYTES);
@@ -63,11 +73,13 @@ static fastd_cipher_state_t* salsa20_init(const uint8_t *key) {
return state;
}
+/** XORs data with the Salsa20 cipher stream */
static bool salsa20_crypt(const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv) {
crypto_stream_salsa20_xor(out->b, in->b, len, iv, state->key);
return true;
}
+/** Frees the cipher state */
static void salsa20_free(fastd_cipher_state_t *state) {
if (state) {
secure_memzero(state, sizeof(*state));
@@ -75,6 +87,8 @@ static void salsa20_free(fastd_cipher_state_t *state) {
}
}
+
+/** The xmm salsa20 implementation */
const fastd_cipher_t fastd_cipher_salsa20_xmm = {
.available = salsa20_available,
diff --git a/src/crypto/cipher/salsa2012/nacl/salsa2012_nacl.c b/src/crypto/cipher/salsa2012/nacl/salsa2012_nacl.c
index efe7089..18ec502 100644
--- a/src/crypto/cipher/salsa2012/nacl/salsa2012_nacl.c
+++ b/src/crypto/cipher/salsa2012/nacl/salsa2012_nacl.c
@@ -23,17 +23,25 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The Salsa20/12 implementation from NaCl
+*/
+
#include "../../../../crypto.h"
#include <crypto_stream_salsa2012.h>
+/** The cipher state */
struct fastd_cipher_state {
- uint8_t key[crypto_stream_salsa2012_KEYBYTES];
+ uint8_t key[crypto_stream_salsa2012_KEYBYTES]; /**< The encryption key */
};
+/** Initializes the cipher state */
static fastd_cipher_state_t* salsa2012_init(const uint8_t *key) {
fastd_cipher_state_t *state = malloc(sizeof(fastd_cipher_state_t));
memcpy(state->key, key, crypto_stream_salsa2012_KEYBYTES);
@@ -41,11 +49,13 @@ static fastd_cipher_state_t* salsa2012_init(const uint8_t *key) {
return state;
}
+/** XORs data with the Salsa20/12 cipher stream */
static bool salsa2012_crypt(const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv) {
crypto_stream_salsa2012_xor(out->b, in->b, len, iv, state->key);
return true;
}
+/** Frees the cipher state */
static void salsa2012_free(fastd_cipher_state_t *state) {
if (state) {
secure_memzero(state, sizeof(*state));
@@ -53,6 +63,8 @@ static void salsa2012_free(fastd_cipher_state_t *state) {
}
}
+
+/** The nacl salsa2012 implementation */
const fastd_cipher_t fastd_cipher_salsa2012_nacl = {
.init = salsa2012_init,
.crypt = salsa2012_crypt,
diff --git a/src/crypto/cipher/salsa2012/salsa2012.c b/src/crypto/cipher/salsa2012/salsa2012.c
index 8dcfc33..d10c4fb 100644
--- a/src/crypto/cipher/salsa2012/salsa2012.c
+++ b/src/crypto/cipher/salsa2012/salsa2012.c
@@ -23,10 +23,17 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The Salsa20/12 stream cipher, a reduced-round version of Salsa20
+*/
+
#include "../../../crypto.h"
+/** Cipher info about Salsa20/12 */
const fastd_cipher_info_t fastd_cipher_info_salsa2012 = {
.key_length = 32,
.iv_length = 8,
diff --git a/src/crypto/cipher/salsa2012/xmm/salsa2012_xmm.c b/src/crypto/cipher/salsa2012/xmm/salsa2012_xmm.c
index 5e5862f..7e6fe80 100644
--- a/src/crypto/cipher/salsa2012/xmm/salsa2012_xmm.c
+++ b/src/crypto/cipher/salsa2012/xmm/salsa2012_xmm.c
@@ -23,15 +23,21 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- The assembly implementations were written by D. J. Bernstein and are
- Public Domain. For more information see http://cr.yp.to/snuffle.html
+/**
+ \file
+
+ The XMM Salsa20/12 implementation for SSE2-capable x86 systems
+
+ The assembly implementations were written by D. J. Bernstein and are
+ Public Domain. For more information see http://cr.yp.to/snuffle.html
*/
+
#include "../../../../crypto.h"
#include "../../../../cpuid.h"
+/** The length of the key used by Salsa20/12 */
#define KEYBYTES 32
@@ -44,18 +50,22 @@
#endif
+/** The actual Salsa20/12 assembly implementation */
int crypto_stream_salsa2012_xor(unsigned char *c, const unsigned char *m, unsigned long long mlen, const unsigned char *n, const unsigned char *k);
+/** The cipher state */
struct fastd_cipher_state {
- uint8_t key[KEYBYTES];
+ uint8_t key[KEYBYTES]; /**< The encryption key */
};
+/** Checks if the runtime platform supports SSE2 */
static bool salsa2012_available(void) {
return fastd_cpuid() & CPUID_SSE2;
}
+/** Initializes the cipher state */
static fastd_cipher_state_t* salsa2012_init(const uint8_t *key) {
fastd_cipher_state_t *state = malloc(sizeof(fastd_cipher_state_t));
memcpy(state->key, key, KEYBYTES);
@@ -63,11 +73,13 @@ static fastd_cipher_state_t* salsa2012_init(const uint8_t *key) {
return state;
}
+/** XORs data with the Salsa20/12 cipher stream */
static bool salsa2012_crypt(const fastd_cipher_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t len, const uint8_t *iv) {
crypto_stream_salsa2012_xor(out->b, in->b, len, iv, state->key);
return true;
}
+/** Frees the cipher state */
static void salsa2012_free(fastd_cipher_state_t *state) {
if (state) {
secure_memzero(state, sizeof(*state));
@@ -75,6 +87,8 @@ static void salsa2012_free(fastd_cipher_state_t *state) {
}
}
+
+/** The xmm salsa2012 implementation */
const fastd_cipher_t fastd_cipher_salsa2012_xmm = {
.available = salsa2012_available,
diff --git a/src/crypto/mac/ghash/builtin/ghash_builtin.c b/src/crypto/mac/ghash/builtin/ghash_builtin.c
index 28e9292..0b957a4 100644
--- a/src/crypto/mac/ghash/builtin/ghash_builtin.c
+++ b/src/crypto/mac/ghash/builtin/ghash_builtin.c
@@ -23,18 +23,27 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Portable, table-based GHASH implementation
+*/
+
#include "../../../../crypto.h"
+/** MAC state used by this GHASH implmentation */
struct fastd_mac_state {
- fastd_block128_t H[32][16];
+ fastd_block128_t H[32][16]; /**< Lookup table unpacked from the hash key */
};
+/** Lower 128 bit of the modulus \f$ x^{128} + x^7 + x^2 + x + 1 \f$ */
static const fastd_block128_t r = { .b = {0xe1} };
+/** Right shift of a 128bit integer by up to 8 bytes */
static inline uint8_t shr(fastd_block128_t *out, const fastd_block128_t *in, int n) {
size_t i;
uint8_t c = 0;
@@ -48,6 +57,7 @@ static inline uint8_t shr(fastd_block128_t *out, const fastd_block128_t *in, int
return (c >> (8-n));
}
+/** Galois field multiplication of a 128bit integer with H */
static inline void mulH_a(fastd_block128_t *x, const fastd_mac_state_t *cstate) {
fastd_block128_t out = {};
@@ -61,6 +71,7 @@ static inline void mulH_a(fastd_block128_t *x, const fastd_mac_state_t *cstate)
}
+/** Initializes the MAC state with the unpacked key data */
static fastd_mac_state_t* ghash_init(const uint8_t *key) {
fastd_mac_state_t *state;
if (posix_memalign((void**)&state, 16, sizeof(fastd_mac_state_t)))
@@ -107,6 +118,7 @@ static fastd_mac_state_t* ghash_init(const uint8_t *key) {
return state;
}
+/** Calculates the GHASH of the supplied blocks */
static bool ghash_hash(const fastd_mac_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks) {
memset(out, 0, sizeof(fastd_block128_t));
@@ -119,6 +131,7 @@ static bool ghash_hash(const fastd_mac_state_t *state, fastd_block128_t *out, co
return true;
}
+/** Frees the MAC state */
static void ghash_free(fastd_mac_state_t *state) {
if (state) {
secure_memzero(state, sizeof(*state));
@@ -126,6 +139,7 @@ static void ghash_free(fastd_mac_state_t *state) {
}
}
+/** The builtin GHASH implementation */
const fastd_mac_t fastd_mac_ghash_builtin = {
.init = ghash_init,
.hash = ghash_hash,
diff --git a/src/crypto/mac/ghash/ghash.c b/src/crypto/mac/ghash/ghash.c
index 5976131..0ba6440 100644
--- a/src/crypto/mac/ghash/ghash.c
+++ b/src/crypto/mac/ghash/ghash.c
@@ -23,10 +23,18 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ General information about the GHASH algorithm
+
+ \sa http://en.wikipedia.org/wiki/Galois/Counter_Mode
+*/
#include "../../../crypto.h"
+/** MAC info about the GHASH algorithm */
const fastd_mac_info_t fastd_mac_info_ghash = {
.key_length = 16,
};
diff --git a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c
index e335a82..5d5977a 100644
--- a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c
+++ b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.c
@@ -23,17 +23,25 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ PCLMULQDQ-based GHASH implementation for newer x86 systems
+*/
+
#include "ghash_pclmulqdq.h"
#include "../../../../cpuid.h"
+/** Checks if the runtime platform can support the PCLMULQDQ implementation */
static bool ghash_available(void) {
static const uint64_t REQ = CPUID_FXSR|CPUID_SSSE3|CPUID_PCLMULQDQ;
return ((fastd_cpuid()&REQ) == REQ);
}
+/** The pclmulqdq ghash implementation */
const fastd_mac_t fastd_mac_ghash_pclmulqdq = {
.available = ghash_available,
diff --git a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h
index c2cf4e3..51ef5da 100644
--- a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h
+++ b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq.h
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ PCLMULQDQ-based GHASH implementation for newer x86 systems
+*/
+
#pragma once
diff --git a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c
index 9dc0a32..49c036a 100644
--- a/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c
+++ b/src/crypto/mac/ghash/pclmulqdq/ghash_pclmulqdq_impl.c
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ PCLMULQDQ-based GHASH implementation for newer x86 systems: implementation
+*/
+
#include "ghash_pclmulqdq.h"
#include <wmmintrin.h>
@@ -30,16 +36,19 @@
#include <tmmintrin.h>
+/** An union allowing easy access to a block as a SIMD vector and a fastd_block128_t */
typedef union vecblock {
- __m128i v;
- fastd_block128_t b;
+ __m128i v; /**< __m128i access */
+ fastd_block128_t b; /**< fastd_block128_t access */
} vecblock_t;
+/** The MAC state used by this GHASH implementation */
struct fastd_mac_state {
- vecblock_t H;
+ vecblock_t H; /**< The hash key used by GHASH */
};
+/** Left shift on a 128bit integer */
static inline __m128i shl(__m128i v, int a) {
__m128i tmpl = _mm_slli_epi64(v, a);
__m128i tmpr = _mm_srli_epi64(v, 64-a);
@@ -48,6 +57,7 @@ static inline __m128i shl(__m128i v, int a) {
return _mm_xor_si128(tmpl, tmpr);
}
+/** Right shift on a 128bit integer */
static inline __m128i shr(__m128i v, int a) {
__m128i tmpr = _mm_srli_epi64(v, a);
__m128i tmpl = _mm_slli_epi64(v, 64-a);
@@ -56,13 +66,16 @@ static inline __m128i shr(__m128i v, int a) {
return _mm_xor_si128(tmpr, tmpl);
}
+/** _mm_shuffle_epi8 parameter to reverse the bytes of a __m128i */
static const __v16qi BYTESWAP_SHUFFLE = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
+/** Reverses the order of the bytes of a __m128i */
static inline __m128i byteswap(__m128i v) {
return _mm_shuffle_epi8(v, (__m128i)BYTESWAP_SHUFFLE);
}
+/** Initializes the state used by this GHASH implementation */
fastd_mac_state_t* fastd_ghash_pclmulqdq_init(const uint8_t *key) {
fastd_mac_state_t *state;
if (posix_memalign((void**)&state, 16, sizeof(fastd_mac_state_t)))
@@ -74,6 +87,7 @@ fastd_mac_state_t* fastd_ghash_pclmulqdq_init(const uint8_t *key) {
return state;
}
+/** Frees the state used by this GHASH implementation */
void fastd_ghash_pclmulqdq_free(fastd_mac_state_t *state) {
if (state) {
secure_memzero(state, sizeof(*state));
@@ -81,6 +95,7 @@ void fastd_ghash_pclmulqdq_free(fastd_mac_state_t *state) {
}
}
+/** Performs a carryless multiplication of two 128bit integers modulo \f$ x^{128} + x^7 + x^2 + x + 1 \f$ */
static __m128i gmul(__m128i v, __m128i h) {
/* multiply */
__m128i z0, z1, z2, tmp;
@@ -134,6 +149,7 @@ static __m128i gmul(__m128i v, __m128i h) {
}
+/** Calculates the GHASH of the supplied input blocks */
bool fastd_ghash_pclmulqdq_hash(const fastd_mac_state_t *state, fastd_block128_t *out, const fastd_block128_t *in, size_t n_blocks) {
vecblock_t v = {.v = _mm_setzero_si128()};
diff --git a/src/crypto/mac/macs.c.in b/src/crypto/mac/macs.c.in
index 0db26d9..5f9a353 100644
--- a/src/crypto/mac/macs.c.in
+++ b/src/crypto/mac/macs.c.in
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Generated lists of MACs and their implementations
+*/
+
#include <src/crypto.h>
#include <src/fastd.h>
@@ -30,29 +36,35 @@
@MAC_DEFINITIONS@
+/** A MAC implementation */
typedef struct fastd_mac_impl {
- const char *name;
- const fastd_mac_t *impl;
+ const char *name; /**< The name of the MAC implementation */
+ const fastd_mac_t *impl; /**< The MAC implementation */
} fastd_mac_impl_t;
+/** A MAC */
typedef struct mac_entry {
- const char *name;
- const fastd_mac_info_t *info;
- const fastd_mac_impl_t *impls;
+ const char *name; /**< The name of the MAC */
+ const fastd_mac_info_t *info; /**< The associated MAC information */
+ const fastd_mac_impl_t *impls; /**< NULL-terminated array of MAC implementations */
} mac_entry_t;
@MAC_IMPLS@
+/** The list of supported MACs */
static const mac_entry_t macs[] = { @MAC_LIST@
};
+/** The list of chosen MAC implementations */
static const fastd_mac_t *mac_conf[array_size(macs)] = {};
+/** Checks if a MAC implementation is available on the runtime platform */
static inline bool mac_available(const fastd_mac_t *mac) {
return (!mac->available) || mac->available();
}
+/** Initializes the list of MAC implementations */
void fastd_mac_init(void) {
size_t i, j;
for (i = 0; i < array_size(macs); i++) {
@@ -65,6 +77,7 @@ void fastd_mac_init(void) {
}
}
+/** Configures a MAC to use a specific implementation */
bool fastd_mac_config(const char *name, const char *impl) {
size_t i;
for (i = 0; i < array_size(macs); i++) {
@@ -87,6 +100,7 @@ bool fastd_mac_config(const char *name, const char *impl) {
return false;
}
+/** Returns information about the MAC with the specified name if there is an implementation available */
const fastd_mac_info_t* fastd_mac_info_get_by_name(const char *name) {
size_t i, j;
for (i = 0; i < array_size(macs); i++) {
@@ -102,6 +116,7 @@ const fastd_mac_info_t* fastd_mac_info_get_by_name(const char *name) {
return NULL;
}
+/** Returns the chosen MAC implementation for a given cipher */
const fastd_mac_t* fastd_mac_get(const fastd_mac_info_t *info) {
size_t i;
for (i = 0; i < array_size(macs); i++) {
diff --git a/src/fastd.c b/src/fastd.c
index a33ba66..3bc3929 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -23,6 +23,13 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Initialization, main loop and cleanup
+*/
+
+
#include "fastd.h"
#include "async.h"
@@ -55,26 +62,35 @@
#endif
+/** The global context */
fastd_context_t ctx;
-static volatile bool sighup = false;
-static volatile bool terminate = false;
-static volatile bool dump = false;
+static volatile bool sighup = false; /**< Is set to true when a SIGHUP is received */
+static volatile bool terminate = false; /**< Is set to true when a SIGTERM, SIGQUIT or SIGINT is received */
+static volatile bool dump = false; /**< Is set to true when a SIGUSR1 is received */
+/** SIGHUP handler */
static void on_sighup(int signo UNUSED) {
sighup = true;
}
+/** SIGTERM, SIGQUIT and SIGINT handler */
static void on_terminate(int signo UNUSED) {
terminate = true;
}
+/** SIGUSR1 handler */
static void on_sigusr1(int signo UNUSED) {
dump = true;
}
+/**
+ SIGCHLD handler
+
+ Reaps zombies of asynchronous shell commands.
+*/
static void on_sigchld(int signo UNUSED) {
size_t i;
for (i = 0; i < VECTOR_LEN(ctx.async_pids);) {
@@ -96,6 +112,7 @@ static void on_sigchld(int signo UNUSED) {
}
}
+/** Installs signal handlers */
static void init_signals(void) {
struct sigaction action;
@@ -135,6 +152,7 @@ static void init_signals(void) {
}
+/** Initializes log destinations */
static inline void init_log(void) {
if (conf.log_syslog_level > LL_UNSPEC)
openlog(conf.log_syslog_ident, LOG_PID, LOG_DAEMON);
@@ -142,11 +160,13 @@ static inline void init_log(void) {
ctx.log_initialized = true;
}
+/** Cleans up log destinations */
static inline void close_log(void) {
closelog();
}
+/** Initializes the configured sockets */
static void init_sockets(void) {
ctx.socks = malloc(conf.n_bind_addrs * sizeof(fastd_socket_t));
@@ -167,6 +187,7 @@ static void init_sockets(void) {
ctx.n_socks = conf.n_bind_addrs;
}
+/** Closes fastd's sockets */
static void close_sockets(void) {
size_t i;
for (i = 0; i < ctx.n_socks; i++)
@@ -175,22 +196,31 @@ static void close_sockets(void) {
free(ctx.socks);
}
+/** Calls the on-pre-up command */
static inline void on_pre_up(void) {
fastd_shell_command_exec(&conf.on_pre_up, NULL);
}
+/** Calls the on-up command */
static inline void on_up(void) {
fastd_shell_command_exec(&conf.on_up, NULL);
}
+/** Calls the on-down command */
static inline void on_down(void) {
fastd_shell_command_exec(&conf.on_down, NULL);
}
+/** Calls the on-post-down command */
static inline void on_post_down(void) {
fastd_shell_command_exec(&conf.on_post_down, NULL);
}
+/**
+ Initializes the peers
+
+ Is called after each reconfiguration to remove old peers and add new ones.
+*/
static void init_peers(void) {
fastd_peer_config_t *peer_conf;
for (peer_conf = conf.peers; peer_conf; peer_conf = peer_conf->next)
@@ -227,11 +257,13 @@ static void init_peers(void) {
}
}
+/** Removes all peers */
static void delete_peers(void) {
while (VECTOR_LEN(ctx.peers))
fastd_peer_delete(VECTOR_INDEX(ctx.peers, VECTOR_LEN(ctx.peers)-1));
}
+/** Dumps statistics and the list of known peers to the logs */
static void dump_state(void) {
pr_info("TX stats: %U packet(s), %U byte(s); dropped: %U packet(s), %U byte(s); error: %U packet(s), %U byte(s)",
ctx.tx.packets, ctx.tx.bytes, ctx.tx_dropped.packets, ctx.tx_dropped.bytes, ctx.tx_error.packets, ctx.tx_error.bytes);
@@ -265,6 +297,7 @@ static void dump_state(void) {
pr_info("dump finished.");
}
+/** Performs periodic maintenance tasks */
static inline void maintenance(void) {
if (!fastd_timed_out(&ctx.next_maintenance))
return;
@@ -299,6 +332,7 @@ void fastd_close_all_fds(void) {
}
}
+/** Writes the PID file */
static void write_pid(pid_t pid) {
if (!conf.pid_file)
return;
@@ -332,6 +366,7 @@ static void write_pid(pid_t pid) {
pr_debug_errno("setegid");
}
+/** Switches to the configured user */
static void set_user(void) {
if (conf.user || conf.group) {
if (setgid(conf.gid) < 0)
@@ -344,6 +379,7 @@ static void set_user(void) {
}
}
+/** Sets the configured user's supplementary groups */
static void set_groups(void) {
if (conf.groups) {
if (setgroups(conf.n_groups, conf.groups) < 0) {
@@ -359,12 +395,13 @@ static void set_groups(void) {
}
}
+/** Switches the user and drops all capabilities */
static void drop_caps(void) {
set_user();
fastd_cap_drop();
}
-/* will double fork and wait for a status notification from the child */
+/** Will double fork and wait for a status notification from the child before exiting in the original parent */
static int daemonize(void) {
uint8_t status = 1;
int pipefd[2];
@@ -415,6 +452,7 @@ static int daemonize(void) {
}
#ifdef ENABLE_SYSTEMD
+/** Sends a readiness notification on a notify socket */
static void notify_systemd(const char *notify_socket) {
int fd;
struct sockaddr_un sa = {};
@@ -445,6 +483,7 @@ static void notify_systemd(const char *notify_socket) {
}
#endif
+/** Main function */
int main(int argc, char *argv[]) {
memset(&ctx, 0, sizeof(ctx));
int status_fd = -1;
diff --git a/src/fastd.h b/src/fastd.h
index 0b326b0..f69f2f8 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -124,9 +124,9 @@ struct fastd_protocol {
/** An union storing an IPv4 or IPv6 address */
union fastd_peer_address {
- struct sockaddr sa; /**< A generic sockaddr union field of the address (for access to sa_family) */
- struct sockaddr_in in; /**< An IPv4 address */
- struct sockaddr_in6 in6; /**< An IPv6 address */
+ struct sockaddr sa; /**< A sockaddr field (for access to sa_family) */
+ struct sockaddr_in in; /**< An IPv4 address */
+ struct sockaddr_in6 in6; /**< An IPv6 address */
};
/** A linked list of addresses to bind to */
@@ -201,7 +201,7 @@ struct fastd_config {
char *secret; /**< The configured secret key */
- fastd_peer_group_t *peer_group; /**< The root peer group configuration */
+ fastd_peer_group_t *peer_group; /**< The root peer group configuration */
fastd_peer_config_t *peers; /**< The configured peers */
bool has_floating; /**< Specifies if any of the configured peers have floating remotes */
@@ -289,8 +289,8 @@ struct fastd_string_stack {
};
-extern fastd_context_t ctx; /**< The global context */
-extern fastd_config_t conf; /**< The global configuration */
+extern fastd_context_t ctx;
+extern fastd_config_t conf;
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);
diff --git a/src/fastd_config.h.in b/src/fastd_config.h.in
index 196ed34..429e42e 100644
--- a/src/fastd_config.h.in
+++ b/src/fastd_config.h.in
@@ -23,52 +23,118 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Generated configuration
+*/
+
#pragma once
+/** Defined if the platform supports the AI_ADDRCONFIG flag to getaddrinfo() */
#cmakedefine HAVE_AI_ADDRCONFIG
+
+/** Defined if the platform defines the \e ethhdr struct */
#cmakedefine HAVE_ETHHDR
+
+/** Defined if the platform defines get_current_dir_name() */
#cmakedefine HAVE_GET_CURRENT_DIR_NAME
+/** Defined if the platform supports SO_BINDTODEVICE */
#cmakedefine USE_BINDTODEVICE
+
+/** Defined if the platform supports epoll */
#cmakedefine USE_EPOLL
+
+/** Defined if the platform supports SO_FREEBIND */
#cmakedefine USE_FREEBIND
+
+/** Defined if the platform supports IP_MTU_DISCOVER */
#cmakedefine USE_PMTU
+
+/** Defined if the platform supports IP_PKTINFO */
#cmakedefine USE_PKTINFO
+
+/** Defined if the platform supports SO_MARK */
#cmakedefine USE_PACKET_MARK
+
+/** Defined if the platform supports binding on IPv4 and IPv6 with a single socket */
#cmakedefine USE_MULTIAF_BIND
+/** Defined if POSIX capability support is enabled */
#cmakedefine WITH_CAPABILITIES
+
+/** Defined if support for setting user/group related options on the command line is enabled */
#cmakedefine WITH_CMDLINE_USER
+
+/** Defined if support for setting logging related options on the command line is enabled */
#cmakedefine WITH_CMDLINE_LOGGING
+
+/** Defined if support for setting related to the VPN operation (like mode, interface, encryption method) on the command line is enabled */
#cmakedefine WITH_CMDLINE_OPERATION
+
+/** Defined if support for setting handler scripts (e.g. --on-up) on the command line is enabled */
#cmakedefine WITH_CMDLINE_COMMANDS
+/** Defined if on-verify support is enabled */
#cmakedefine WITH_VERIFY
+/** Defined if systemd support is enabled */
+#cmakedefine ENABLE_SYSTEMD
+
+
+/** Defined if libsodium is used */
#cmakedefine HAVE_LIBSODIUM
+
+/** Defined if OpenSSL is used */
#cmakedefine ENABLE_OPENSSL
-#cmakedefine ENABLE_SYSTEMD
+
+/** The maximum depth of nested includes in config files */
#define MAX_CONFIG_DEPTH @MAX_CONFIG_DEPTH_NUM@
+/** The interval of periodic maintenance tasks */
#define MAINTENANCE_INTERVAL 10
+
+/** The time after which a keepalive should be sent */
#define KEEPALIVE_TIMEOUT 15
+
+/** The time after with a peer is reset if no traffic is received from it */
#define PEER_STALE_TIME 90
+
+/** The time after which a peer's ethernet address is forgotten if it is not seen */
#define ETH_ADDR_STALE_TIME 300
+
+/** The time after a packet is received and no packets with lower sequence numbers are accepted anymore */
#define REORDER_TIME 10
+
+/** The minimum time that must pass between two on-verify calls on the same peer */
#define MIN_VERIFY_INTERVAL 10
+
+/** How long a peer stays valid after a successful on-verify run */
#define VERIFY_VALID_TIME 60 /* 1 minute */
+/** The minimum interval between two handshakes with a peer */
#define MIN_HANDSHAKE_INTERVAL 15
+
+/** The minimum interval between two resolves of the same remote */
#define MIN_RESOLVE_INTERVAL 15
+
+/** How long a session stays valid after a key is negotiated */
#define KEY_VALID 3600 /* 60 minutes */
+
+/** How long an old session stays valid after a new session has been established */
#define KEY_VALID_OLD 60 /* 1 minute */
+
+/** How many seconds after the establishment of a session we want to refresh the session */
#define KEY_REFRESH 3300 /* 55 minutes */
+
+/** A random time up to KEY_REFRESH_SPLAY is subtracted from KEY_REFRESH */
#define KEY_REFRESH_SPLAY 300 /* 5 minutes */
diff --git a/src/hash.h b/src/hash.h
index 7a47388..7a8c79b 100644
--- a/src/hash.h
+++ b/src/hash.h
@@ -23,6 +23,14 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ An implementation of the Jenkins hash function
+
+ \sa https://en.wikipedia.org/wiki/Jenkins_hash_function
+*/
+
#pragma once
@@ -31,6 +39,7 @@
#include <stdint.h>
+/** Adds data bytes to the 32bit hash value */
static inline void fastd_hash(uint32_t *hash, const void *data, size_t len) {
size_t i;
for (i = 0; i < len; ++i) {
@@ -40,6 +49,7 @@ static inline void fastd_hash(uint32_t *hash, const void *data, size_t len) {
}
}
+/** Finalizes a hash value */
static inline void fastd_hash_final(uint32_t *hash) {
*hash += (*hash << 3);
*hash ^= (*hash >> 11);
diff --git a/src/hkdf_sha256.c b/src/hkdf_sha256.c
index 7cf3af8..f521f41 100644
--- a/src/hkdf_sha256.c
+++ b/src/hkdf_sha256.c
@@ -23,12 +23,19 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ An implementation of the HMAC-based Key Derivation Function (RFC 5869) using HMAC-SHA256
+*/
+
#include "hkdf_sha256.h"
#include <string.h>
+/** The HKDF-SHA256 expansion function */
void fastd_hkdf_sha256_expand(fastd_sha256_t *out, size_t blocks, const fastd_sha256_t *prk, const uint8_t *info, size_t infolen) {
if (!blocks)
return;
diff --git a/src/hkdf_sha256.h b/src/hkdf_sha256.h
index 94b726e..5de543c 100644
--- a/src/hkdf_sha256.h
+++ b/src/hkdf_sha256.h
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ An implementation of the HMAC-based Key Derivation Function (RFC 5869) using HMAC-SHA256
+*/
+
#pragma once
@@ -30,6 +36,7 @@
#include "types.h"
+/** The HKDF-SHA256 extraction function (which is just HMAC-SHA256) */
static inline void fastd_hkdf_sha256_extract(fastd_sha256_t *out, const uint32_t salt[FASTD_HMACSHA256_KEY_WORDS], const uint32_t *in, size_t len) {
fastd_hmacsha256(out, salt, in, len);
}
diff --git a/src/lex.c b/src/lex.c
index 92a3866..47f6847 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -23,30 +23,42 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Config scanner for the fastd configuration file format
+*/
+
#include "lex.h"
#include <stdlib.h>
+/** The scanner context */
struct fastd_lex {
- FILE *file;
+ FILE *file; /**< The input file */
- bool needspace;
+ bool needspace; /**< Specifies if some kind of whitespace (or similar separator like a semicolon) is needed before the next token is parsed */
- size_t start;
- size_t end;
- size_t tok_len;
- char buffer[1024];
+ size_t start; /**< The start of the current token in the input buffer */
+ size_t end; /**< The end of the input read into the input buffer so far */
+ size_t tok_len; /**< The number of characters in the current token */
+ char buffer[1024]; /**< The input buffer */
};
-
+/** A keyword with the corresponding token ID */
typedef struct keyword {
- const char *keyword;
- int token;
+ const char *keyword; /**< The keyword */
+ int token; /**< The numerical token ID as generated by the parser */
} keyword_t;
-/* the keyword list must be sorted */
+
+/**
+ The list of known keywords
+
+ The keyword list must be sorted so binary search can work.
+*/
static const keyword_t keywords[] = {
{ "addresses", TOK_ADDRESSES },
{ "any", TOK_ANY },
@@ -116,12 +128,14 @@ static const keyword_t keywords[] = {
{ "yes", TOK_YES },
};
+/** Compares two keyword_t instances by their keyword */
static int compare_keywords(const void *v1, const void *v2) {
const keyword_t *k1 = v1, *k2 = v2;
return strcmp(k1->keyword, k2->keyword);
}
+/** Reads the next part of the input file into the input buffer */
static bool advance(fastd_lex_t *lex) {
if (lex->start > 0) {
memmove(lex->buffer, lex->buffer+lex->start, lex->end - lex->start);
@@ -138,14 +152,17 @@ static bool advance(fastd_lex_t *lex) {
return l;
}
+/** Returns the current character (not yet added to the current token) */
static inline char current(fastd_lex_t *lex) {
return lex->buffer[lex->start + lex->tok_len];
}
+/** Returns the current token as a newly allocated string */
static char* get_token(fastd_lex_t *lex) {
return strndup(lex->buffer+lex->start, lex->tok_len);
}
+/** Tries to add the next character to the current token */
static bool next(YYLTYPE *yylloc, fastd_lex_t *lex, bool move) {
if (lex->start + lex->tok_len >= lex->end)
return false;
@@ -170,6 +187,7 @@ static bool next(YYLTYPE *yylloc, fastd_lex_t *lex, bool move) {
return true;
}
+/** Removes the current token from the input buffer */
static void consume(fastd_lex_t *lex, bool needspace) {
lex->start += lex->tok_len;
lex->tok_len = 0;
@@ -177,11 +195,13 @@ static void consume(fastd_lex_t *lex, bool needspace) {
lex->needspace = needspace;
}
+/** Signals an error caused by an I/O error */
static int io_error(YYSTYPE *yylval, fastd_lex_t *lex UNUSED) {
yylval->error = "I/O error";
return -1;
}
+/** Signals an error caused by a syntax error */
static int syntax_error(YYSTYPE *yylval, fastd_lex_t *lex) {
if (ferror(lex->file))
return io_error(yylval, lex);
@@ -190,6 +210,7 @@ static int syntax_error(YYSTYPE *yylval, fastd_lex_t *lex) {
return -1;
}
+/** Skips a block comment */
static int consume_comment(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
char prev = 0;
@@ -210,6 +231,7 @@ static int consume_comment(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
return -1;
}
+/** Signals an error caused by an unterminated string */
static int unterminated_string(YYSTYPE *yylval, fastd_lex_t *lex) {
if (ferror(lex->file))
return io_error(yylval, lex);
@@ -218,6 +240,7 @@ static int unterminated_string(YYSTYPE *yylval, fastd_lex_t *lex) {
return -1;
}
+/** Tries to process the current input as a string */
static int parse_string(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
char *buf = NULL;
size_t len = 1024;
@@ -268,6 +291,7 @@ static int parse_string(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
return TOK_STRING;
}
+/** Tries to process the current input as an IPv6 address */
static int parse_ipv6_address(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
if (lex->needspace)
return syntax_error(yylval, lex);
@@ -332,6 +356,7 @@ static int parse_ipv6_address(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex
return ifname ? TOK_ADDR6_SCOPED : TOK_ADDR6;
}
+/** Tries to process the current input as an IPv4 address */
static int parse_ipv4_address(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
if (lex->needspace)
return syntax_error(yylval, lex);
@@ -356,6 +381,7 @@ static int parse_ipv4_address(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex
return TOK_ADDR4;
}
+/** Tries to process the current input as a number */
static int parse_number(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
bool digitonly = true;
@@ -390,6 +416,7 @@ static int parse_number(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
return TOK_UINT;
}
+/** Tries to process the current input as a keyword */
static int parse_keyword(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
if (lex->needspace)
return syntax_error(yylval, lex);
@@ -414,6 +441,8 @@ static int parse_keyword(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
return ret->token;
}
+
+/** Initializes a new scanner for the given file */
fastd_lex_t* fastd_lex_init(FILE *file) {
fastd_lex_t *lex = calloc(1, sizeof(fastd_lex_t));
lex->file = file;
@@ -423,10 +452,12 @@ fastd_lex_t* fastd_lex_init(FILE *file) {
return lex;
}
+/** Destroys the scanner */
void fastd_lex_destroy(fastd_lex_t *lex) {
free(lex);
}
+/** Returns a single lexeme of the scanned file */
int fastd_lex(YYSTYPE *yylval, YYLTYPE *yylloc, fastd_lex_t *lex) {
int token;
diff --git a/src/lex.h b/src/lex.h
index 1b9ec68..53ecce2 100644
--- a/src/lex.h
+++ b/src/lex.h
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Config scanner for the fastd configuration file format
+*/
+
#pragma once
diff --git a/src/log.c b/src/log.c
index b274dbd..8809387 100644
--- a/src/log.c
+++ b/src/log.c
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Logging function implementations
+*/
+
#include "fastd.h"
#include "peer.h"
@@ -32,6 +38,7 @@
#include <net/if.h>
+/** snprintf wrapper always returning the number of bytes written */
static inline size_t snprintf_safe(char *buffer, size_t size, const char *format, ...) {
va_list ap;
va_start(ap, format);
@@ -44,6 +51,7 @@ static inline size_t snprintf_safe(char *buffer, size_t size, const char *format
return min_size_t(ret, size);
}
+/** Creates a string representation of a peer address */
static size_t snprint_peer_address(char *buffer, size_t size, const fastd_peer_address_t *address, const char *iface, bool bind_address) {
char addr_buf[INET6_ADDRSTRLEN] = "";
@@ -83,6 +91,7 @@ static size_t snprint_peer_address(char *buffer, size_t size, const fastd_peer_a
}
}
+/** Creates a string representation of a peer */
static size_t snprint_peer_str(char *buffer, size_t size, const fastd_peer_t *peer) {
if (peer->config && peer->config->name) {
return snprintf_safe(buffer, size, "<%s>", peer->config->name);
@@ -96,6 +105,7 @@ static size_t snprint_peer_str(char *buffer, size_t size, const fastd_peer_t *pe
}
}
+/** vsnprintf-like function using different conversion specifiers */
static int fastd_vsnprintf(char *buffer, size_t size, const char *format, va_list ap) {
char *buffer_start = buffer;
char *buffer_end = buffer+size;
@@ -190,6 +200,7 @@ static int fastd_vsnprintf(char *buffer, size_t size, const char *format, va_lis
return buffer-buffer_start;
}
+/** Returns a prefix string to use for log messages of a specified level */
static inline const char* get_log_prefix(fastd_loglevel_t log_level) {
switch(log_level) {
case LL_FATAL:
@@ -211,6 +222,7 @@ static inline const char* get_log_prefix(fastd_loglevel_t log_level) {
}
}
+/** Converts fastd log levels to syslog levels */
static inline int get_syslog_level(fastd_loglevel_t log_level) {
switch(log_level) {
case LL_FATAL:
@@ -228,6 +240,7 @@ static inline int get_syslog_level(fastd_loglevel_t log_level) {
}
}
+/** printf-like function handling different conversion specifiers and using the configured log destinations */
void fastd_logf(fastd_loglevel_t level, const char *format, ...) {
char buffer[1024];
char timestr[100] = "";
diff --git a/src/methods/cipher_test/cipher_test.c b/src/methods/cipher_test/cipher_test.c
index 52bca0f..7e064ba 100644
--- a/src/methods/cipher_test/cipher_test.c
+++ b/src/methods/cipher_test/cipher_test.c
@@ -23,25 +23,37 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ cipher-test method provider (testing and benchmarking only)
+
+ The cipher-test method provider performs encryption only and can be used to test
+ and benchmark cipher implementations.
+*/
+
#include "../../crypto.h"
#include "../../method.h"
#include "../common.h"
+/** A specific method provided by this provider */
struct fastd_method {
- const fastd_cipher_info_t *cipher_info;
+ const fastd_cipher_info_t *cipher_info; /**< The cipher used */
};
+/** The method-specific session state */
struct fastd_method_session_state {
- fastd_method_common_t common;
+ fastd_method_common_t common; /**< The common method state */
- const fastd_method_t *method;
- const fastd_cipher_t *cipher;
- fastd_cipher_state_t *cipher_state;
+ const fastd_method_t *method; /**< The specific method used */
+ const fastd_cipher_t *cipher; /**< The cipher implementation used */
+ fastd_cipher_state_t *cipher_state; /**< The cipher state */
};
+/** Instanciates a method using a name of the pattern "<cipher>+cipher-test" */
static bool method_create_by_name(const char *name, fastd_method_t **method) {
fastd_method_t m;
@@ -66,14 +78,17 @@ static bool method_create_by_name(const char *name, fastd_method_t **method) {
return true;
}
+/** Frees a method */
static void method_destroy(fastd_method_t *method) {
free(method);
}
+/** Returns the key length used by a method */
static size_t method_key_length(const fastd_method_t *method) {
return method->cipher_info->key_length;
}
+/** Initializes a session */
static fastd_method_session_state_t* method_session_init(const fastd_method_t *method, const uint8_t *secret, bool initiator) {
fastd_method_session_state_t *session = malloc(sizeof(fastd_method_session_state_t));
@@ -87,22 +102,27 @@ static fastd_method_session_state_t* method_session_init(const fastd_method_t *m
return session;
}
+/** Checks if the session is currently valid */
static bool method_session_is_valid(fastd_method_session_state_t *session) {
return (session && fastd_method_session_common_is_valid(&session->common));
}
+/** Checks if this side is the initator of the session */
static bool method_session_is_initiator(fastd_method_session_state_t *session) {
return fastd_method_session_common_is_initiator(&session->common);
}
+/** Checks if the session should be refreshed */
static bool method_session_want_refresh(fastd_method_session_state_t *session) {
return fastd_method_session_common_want_refresh(&session->common);
}
+/** Marks the session as superseded */
static void method_session_superseded(fastd_method_session_state_t *session) {
fastd_method_session_common_superseded(&session->common);
}
+/** Frees the session state */
static void method_session_free(fastd_method_session_state_t *session) {
if (session) {
session->cipher->free(session->cipher_state);
@@ -110,6 +130,8 @@ static void method_session_free(fastd_method_session_state_t *session) {
}
}
+
+/** Encrypts a packet and adds the common method header */
static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
size_t tail_len = alignto(in.len, sizeof(fastd_block128_t))-in.len;
*out = fastd_buffer_alloc(in.len, alignto(COMMON_HEADBYTES, 16), sizeof(fastd_block128_t)+tail_len);
@@ -140,6 +162,7 @@ static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state
return true;
}
+/** Decrypts a packet */
static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
if (in.len < COMMON_HEADBYTES)
return false;
@@ -184,6 +207,8 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses
return true;
}
+
+/** The cipher-test method provider */
const fastd_method_provider_t fastd_method_cipher_test = {
.max_overhead = COMMON_HEADBYTES,
.min_encrypt_head_space = 0,
diff --git a/src/methods/composed_gmac/composed_gmac.c b/src/methods/composed_gmac/composed_gmac.c
index 887fb5c..6636e49 100644
--- a/src/methods/composed_gmac/composed_gmac.c
+++ b/src/methods/composed_gmac/composed_gmac.c
@@ -23,37 +23,51 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ composed-gmac method provider
+
+ composed-gmac combines any cipher (or null) with GMAC, while another cipher is
+ used to generate the GHASH keys. Combining the null cipher with GMAC allows creating
+ unencrypted, authenticated-only methods.
+*/
+
#include "../../crypto.h"
#include "../../method.h"
#include "../common.h"
+/** A block of zeros */
static const fastd_block128_t ZERO_BLOCK = {};
+/** A specific method provided by this provider */
struct fastd_method {
- const fastd_cipher_info_t *cipher_info;
- const fastd_cipher_info_t *gmac_cipher_info;
- const fastd_mac_info_t *ghash_info;
+ const fastd_cipher_info_t *cipher_info; /**< The cipher used for encryption */
+ const fastd_cipher_info_t *gmac_cipher_info; /**< The cipher used for authenticaton */
+ const fastd_mac_info_t *ghash_info; /**< GHASH */
};
+/** The method-specific session state */
struct fastd_method_session_state {
- fastd_method_common_t common;
+ fastd_method_common_t common; /**< The common method state */
- const fastd_method_t *method;
+ const fastd_method_t *method; /**< The specific method used */
- const fastd_cipher_t *cipher;
- fastd_cipher_state_t *cipher_state;
+ const fastd_cipher_t *cipher; /**< The cipher implementation used for encryption */
+ fastd_cipher_state_t *cipher_state; /**< The cipher state for encryption */
- const fastd_cipher_t *gmac_cipher;
- fastd_cipher_state_t *gmac_cipher_state;
+ const fastd_cipher_t *gmac_cipher; /**< The cipher implementation used for authentication */
+ fastd_cipher_state_t *gmac_cipher_state; /**< The cipher state for authentication */
- const fastd_mac_t *ghash;
- fastd_mac_state_t *ghash_state;
+ const fastd_mac_t *ghash; /**< The GHASH implementation */
+ fastd_mac_state_t *ghash_state; /**< The GHASH state */
};
+/** Instanciates a method using a name of the pattern "<cipher>+<cipher>+gmac" (or "<cipher>+<cipher>-gmac" for block ciphers in counter mode, e.g. null+aes128-gmac instead of null+aes128-ctr+gmac) */
static bool method_create_by_name(const char *name, fastd_method_t **method) {
fastd_method_t m;
@@ -107,15 +121,17 @@ static bool method_create_by_name(const char *name, fastd_method_t **method) {
return true;
}
+/** Frees a method */
static void method_destroy(fastd_method_t *method) {
free(method);
}
-
+/** Returns the key length used by a method */
static size_t method_key_length(const fastd_method_t *method) {
return method->cipher_info->key_length + method->gmac_cipher_info->key_length;
}
+/** Initializes a session */
static fastd_method_session_state_t* method_session_init(const fastd_method_t *method, const uint8_t *secret, bool initiator) {
fastd_method_session_state_t *session = malloc(sizeof(fastd_method_session_state_t));
@@ -148,22 +164,27 @@ static fastd_method_session_state_t* method_session_init(const fastd_method_t *m
return session;
}
+/** Checks if the session is currently valid */
static bool method_session_is_valid(fastd_method_session_state_t *session) {
return (session && fastd_method_session_common_is_valid(&session->common));
}
+/** Checks if this side is the initator of the session */
static bool method_session_is_initiator(fastd_method_session_state_t *session) {
return fastd_method_session_common_is_initiator(&session->common);
}
+/** Checks if the session should be refreshed */
static bool method_session_want_refresh(fastd_method_session_state_t *session) {
return fastd_method_session_common_want_refresh(&session->common);
}
+/** Marks the session as superseded */
static void method_session_superseded(fastd_method_session_state_t *session) {
fastd_method_session_common_superseded(&session->common);
}
+/** Frees the session state */
static void method_session_free(fastd_method_session_state_t *session) {
if (session) {
session->cipher->free(session->cipher_state);
@@ -174,6 +195,7 @@ static void method_session_free(fastd_method_session_state_t *session) {
}
}
+/** Writes the size of the input in bits to a block (in a way different from the generic-gmac methods) */
static inline void put_size(fastd_block128_t *out, size_t len) {
memset(out, 0, sizeof(fastd_block128_t));
out->b[3] = len >> 29;
@@ -183,6 +205,7 @@ static inline void put_size(fastd_block128_t *out, size_t len) {
out->b[7] = len << 3;
}
+/** Encrypts and authenticates a packet */
static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
size_t tail_len = alignto(in.len, sizeof(fastd_block128_t))-in.len;
*out = fastd_buffer_alloc(sizeof(fastd_block128_t)+in.len, alignto(COMMON_HEADBYTES, 16), sizeof(fastd_block128_t)+tail_len);
@@ -232,6 +255,7 @@ static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state
return true;
}
+/** Verifies and decrypts a packet */
static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
if (in.len < COMMON_HEADBYTES+sizeof(fastd_block128_t))
return false;
@@ -294,6 +318,8 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses
return true;
}
+
+/** The composed-gmac method provider */
const fastd_method_provider_t fastd_method_composed_gmac = {
.max_overhead = COMMON_HEADBYTES + sizeof(fastd_block128_t),
.min_encrypt_head_space = 0,
diff --git a/src/methods/generic_gmac/generic_gmac.c b/src/methods/generic_gmac/generic_gmac.c
index 6b84a95..546cd50 100644
--- a/src/methods/generic_gmac/generic_gmac.c
+++ b/src/methods/generic_gmac/generic_gmac.c
@@ -23,30 +23,41 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ generic-gmac method provider
+
+ generic-gmac can combine any stream cipher with the GMAC authentication.
+*/
+
#include "../../crypto.h"
#include "../../method.h"
#include "../common.h"
+/** A specific method provided by this provider */
struct fastd_method {
- const fastd_cipher_info_t *cipher_info;
- const fastd_mac_info_t *ghash_info;
+ const fastd_cipher_info_t *cipher_info; /**< The cipher used */
+ const fastd_mac_info_t *ghash_info; /**< GHASH */
};
+/** The method-specific session state */
struct fastd_method_session_state {
- fastd_method_common_t common;
+ fastd_method_common_t common; /**< The common method state */
- const fastd_method_t *method;
+ const fastd_method_t *method; /**< The specific method used */
- const fastd_cipher_t *cipher;
- fastd_cipher_state_t *cipher_state;
+ const fastd_cipher_t *cipher; /**< The cipher implementation used */
+ fastd_cipher_state_t *cipher_state; /**< The cipher state */
- const fastd_mac_t *ghash;
- fastd_mac_state_t *ghash_state;
+ const fastd_mac_t *ghash; /**< The GHASH implementation */
+ fastd_mac_state_t *ghash_state; /**< The GHASH state */
};
+/** Instanciates a method using a name of the pattern "<cipher>+gmac" (or "<cipher>-gcm" for block ciphers in counter mode, e.g. aes128-gcm instead of aes128-ctr+gmac) */
static bool method_create_by_name(const char *name, fastd_method_t **method) {
fastd_method_t m;
@@ -85,14 +96,17 @@ static bool method_create_by_name(const char *name, fastd_method_t **method) {
return true;
}
+/** Frees a method */
static void method_destroy(fastd_method_t *method) {
free(method);
}
+/** Returns the key length used by a method */
static size_t method_key_length(const fastd_method_t *method) {
return method->cipher_info->key_length;
}
+/** Initializes a session */
static fastd_method_session_state_t* method_session_init(const fastd_method_t *method, const uint8_t *secret, bool initiator) {
fastd_method_session_state_t *session = malloc(sizeof(fastd_method_session_state_t));
@@ -121,22 +135,27 @@ static fastd_method_session_state_t* method_session_init(const fastd_method_t *m
return session;
}
+/** Checks if the session is currently valid */
static bool method_session_is_valid(fastd_method_session_state_t *session) {
return (session && fastd_method_session_common_is_valid(&session->common));
}
+/** Checks if this side is the initator of the session */
static bool method_session_is_initiator(fastd_method_session_state_t *session) {
return fastd_method_session_common_is_initiator(&session->common);
}
+/** Checks if the session should be refreshed */
static bool method_session_want_refresh(fastd_method_session_state_t *session) {
return fastd_method_session_common_want_refresh(&session->common);
}
+/** Marks the session as superseded */
static void method_session_superseded(fastd_method_session_state_t *session) {
fastd_method_session_common_superseded(&session->common);
}
+/** Frees the session state */
static void method_session_free(fastd_method_session_state_t *session) {
if (session) {
session->cipher->free(session->cipher_state);
@@ -146,6 +165,7 @@ static void method_session_free(fastd_method_session_state_t *session) {
}
}
+/** Writes the size of the input in bits to a block */
static inline void put_size(fastd_block128_t *out, size_t len) {
memset(out, 0, sizeof(fastd_block128_t));
out->b[11] = len >> 29;
@@ -155,6 +175,8 @@ static inline void put_size(fastd_block128_t *out, size_t len) {
out->b[15] = len << 3;
}
+
+/** Encrypts and authenticates a packet */
static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
fastd_buffer_pull_head_zero(&in, sizeof(fastd_block128_t));
@@ -199,6 +221,7 @@ static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state
return true;
}
+/** Verifies and decrypts a packet */
static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
if (in.len < COMMON_HEADBYTES+sizeof(fastd_block128_t))
return false;
@@ -255,6 +278,8 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses
return true;
}
+
+/** The generic-gmac method provider */
const fastd_method_provider_t fastd_method_generic_gmac = {
.max_overhead = COMMON_HEADBYTES + sizeof(fastd_block128_t),
.min_encrypt_head_space = sizeof(fastd_block128_t),
diff --git a/src/methods/generic_poly1305/generic_poly1305.c b/src/methods/generic_poly1305/generic_poly1305.c
index 0e2641c..142b50e 100644
--- a/src/methods/generic_poly1305/generic_poly1305.c
+++ b/src/methods/generic_poly1305/generic_poly1305.c
@@ -23,6 +23,15 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ generic-poly1305 method provider
+
+ The Poly1305 authenticator is very secure, but for performance reasons
+ not really recommendable on embedded systems.
+*/
+
#include "../../crypto.h"
#include "../../method.h"
@@ -31,23 +40,29 @@
#include <crypto_onetimeauth_poly1305.h>
+/** The length of the key used by Poly1305 */
#define KEYBYTES crypto_onetimeauth_poly1305_KEYBYTES
+
+/** The length of the authentication tag */
#define TAGBYTES crypto_onetimeauth_poly1305_BYTES
+/** A specific method provided by this provider */
struct fastd_method {
- const fastd_cipher_info_t *cipher_info;
+ const fastd_cipher_info_t *cipher_info; /**< The cipher used */
};
+/** The method-specific session state */
struct fastd_method_session_state {
- fastd_method_common_t common;
+ fastd_method_common_t common; /**< The common method state */
- const fastd_method_t *method;
- const fastd_cipher_t *cipher;
- fastd_cipher_state_t *cipher_state;
+ const fastd_method_t *method; /**< The specific method used */
+ const fastd_cipher_t *cipher; /**< The cipher implementation used */
+ fastd_cipher_state_t *cipher_state; /**< The cipher state */
};
+/** Instanciates a method using a name of the pattern "<cipher>+poly1305" */
static bool method_create_by_name(const char *name, fastd_method_t **method) {
fastd_method_t m;
@@ -75,14 +90,17 @@ static bool method_create_by_name(const char *name, fastd_method_t **method) {
return true;
}
+/** Frees a method */
static void method_destroy(fastd_method_t *method) {
free(method);
}
+/** Returns the key length used by a method */
static size_t method_key_length(const fastd_method_t *method) {
return method->cipher_info->key_length;
}
+/** Initializes a session */
static fastd_method_session_state_t* method_session_init(const fastd_method_t *method, const uint8_t *secret, bool initiator) {
fastd_method_session_state_t *session = malloc(sizeof(fastd_method_session_state_t));
@@ -94,22 +112,27 @@ static fastd_method_session_state_t* method_session_init(const fastd_method_t *m
return session;
}
+/** Checks if the session is currently valid */
static bool method_session_is_valid(fastd_method_session_state_t *session) {
return (session && fastd_method_session_common_is_valid(&session->common));
}
+/** Checks if this side is the initator of the session */
static bool method_session_is_initiator(fastd_method_session_state_t *session) {
return fastd_method_session_common_is_initiator(&session->common);
}
+/** Checks if the session should be refreshed */
static bool method_session_want_refresh(fastd_method_session_state_t *session) {
return fastd_method_session_common_want_refresh(&session->common);
}
+/** Marks the session as superseded */
static void method_session_superseded(fastd_method_session_state_t *session) {
fastd_method_session_common_superseded(&session->common);
}
+/** Frees the session state */
static void method_session_free(fastd_method_session_state_t *session) {
if (session) {
session->cipher->free(session->cipher_state);
@@ -117,6 +140,8 @@ static void method_session_free(fastd_method_session_state_t *session) {
}
}
+
+/** Encrypts and authenticates a packet */
static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
fastd_buffer_pull_head_zero(&in, KEYBYTES);
@@ -155,6 +180,7 @@ static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state
return true;
}
+/** Verifies and decrypts a packet */
static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
if (in.len < COMMON_HEADBYTES+TAGBYTES)
return false;
@@ -217,6 +243,8 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses
return true;
}
+
+/** The generic-poly1305 method provider */
const fastd_method_provider_t fastd_method_generic_poly1305 = {
.max_overhead = COMMON_HEADBYTES + TAGBYTES,
.min_encrypt_head_space = KEYBYTES,
diff --git a/src/methods/methods.c.in b/src/methods/methods.c.in
index 914d929..672ef70 100644
--- a/src/methods/methods.c.in
+++ b/src/methods/methods.c.in
@@ -23,16 +23,24 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Generated list of supported method providers
+*/
+
#include <src/method.h>
@METHOD_DEFINITIONS@
+/** The list of method providers */
static const fastd_method_provider_t *const providers[] = { @METHOD_LIST@
};
+/** Searches for a provider providing a method and instanciates it */
bool fastd_method_create_by_name(const char *name, const fastd_method_provider_t **provider, fastd_method_t **method) {
size_t i;
for (i = 0; i < array_size(providers); i++) {
diff --git a/src/methods/null/null.c b/src/methods/null/null.c
index 76fd961..3062fcf 100644
--- a/src/methods/null/null.c
+++ b/src/methods/null/null.c
@@ -23,27 +23,37 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The null method not providing any encryption or authenticaton
+*/
#include "../../method.h"
+/** The session state */
struct fastd_method_session_state {
- bool valid;
- bool initiator;
+ bool valid; /**< true if the session has not been invalidated */
+ bool initiator; /**< true if this side is the initiator of the session */
};
+/** Returns true if the name is "null" */
static bool method_create_by_name(const char *name, fastd_method_t **method UNUSED) {
return !strcmp(name, "null");
}
+/** Does nothing as the null provider provides only a single method */
static void method_destroy(fastd_method_t *method UNUSED) {
}
+/** Returns 0 */
static size_t method_key_length(const fastd_method_t *method UNUSED) {
return 0;
}
+/** Initiates a new null session */
static fastd_method_session_state_t* method_session_init(const fastd_method_t *method UNUSED, const uint8_t *secret UNUSED, bool initiator) {
fastd_method_session_state_t *session = malloc(sizeof(fastd_method_session_state_t));
@@ -53,35 +63,49 @@ static fastd_method_session_state_t* method_session_init(const fastd_method_t *m
return session;
}
+/** Initiates a new null session (pre-v11 compat handshake) */
static fastd_method_session_state_t* method_session_init_compat(const fastd_method_t *method, const uint8_t *secret, size_t length UNUSED, bool initiator) {
return method_session_init(method, secret, initiator);
}
+/** Checks if the session is valid */
static bool method_session_is_valid(fastd_method_session_state_t *session) {
return (session && session->valid);
}
+/** Checks if this side is the initiator of the session */
static bool method_session_is_initiator(fastd_method_session_state_t *session) {
return (session->initiator);
}
+/** Returns false */
static bool method_session_want_refresh(fastd_method_session_state_t *session UNUSED) {
return false;
}
+/**
+ Marks the session as invalid
+
+ The session in invalidated without any delay to prevent packets of the new session being
+ mistaken to be valid for the old session
+*/
static void method_session_superseded(fastd_method_session_state_t *session) {
session->valid = false;
}
+/** Frees the session state */
static void method_session_free(fastd_method_session_state_t *session) {
free(session);
}
+/** Just returns the input buffer as the output */
static bool method_passthrough(fastd_peer_t *peer UNUSED, fastd_method_session_state_t *session UNUSED, fastd_buffer_t *out, fastd_buffer_t in) {
*out = in;
return true;
}
+
+/** The null method provider */
const fastd_method_provider_t fastd_method_null = {
.max_overhead = 0,
.min_encrypt_head_space = 0,
diff --git a/src/methods/xsalsa20_poly1305/xsalsa20_poly1305.c b/src/methods/xsalsa20_poly1305/xsalsa20_poly1305.c
index f06e0f8..9f2d61c 100644
--- a/src/methods/xsalsa20_poly1305/xsalsa20_poly1305.c
+++ b/src/methods/xsalsa20_poly1305/xsalsa20_poly1305.c
@@ -23,6 +23,16 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ The xsalsa20-poly1305 method provider (deprecated)
+
+ This provider is included for compatiblity reasons as pre-v11
+ xsalsa20-poly1305 was the recommended method. In new setups salsa20+poly1305
+ provided by the generic-poly1305 provider should be used as a replacement.
+*/
+
#include "../../crypto.h"
#include "../../method.h"
@@ -31,24 +41,29 @@
#include <crypto_secretbox_xsalsa20poly1305.h>
+/** The session state */
struct fastd_method_session_state {
- fastd_method_common_t common;
+ fastd_method_common_t common; /**< The common method state */
- uint8_t key[crypto_secretbox_xsalsa20poly1305_KEYBYTES] __attribute__((aligned(8)));
+ uint8_t key[crypto_secretbox_xsalsa20poly1305_KEYBYTES] __attribute__((aligned(8))); /**< The encryption key */
};
+/** Matches the method name "xsalsa20-poly1305" */
static bool method_create_by_name(const char *name, fastd_method_t **method UNUSED) {
return !strcmp(name, "xsalsa20-poly1305");
}
+/** Does nothing as this provider has only a single method */
static void method_destroy(fastd_method_t *method UNUSED) {
}
+/** Returns the key length used by xsalsa20-poly1305 */
static size_t method_key_length(const fastd_method_t *method UNUSED) {
return crypto_secretbox_xsalsa20poly1305_KEYBYTES;
}
+/** Initializes the session state */
static fastd_method_session_state_t* method_session_init(const fastd_method_t *method UNUSED, const uint8_t *secret, bool initiator) {
fastd_method_session_state_t *session = malloc(sizeof(fastd_method_session_state_t));
@@ -59,6 +74,7 @@ static fastd_method_session_state_t* method_session_init(const fastd_method_t *m
return session;
}
+/** Initializes the session state (pre-v11 compat handshake) */
static fastd_method_session_state_t* method_session_init_compat(const fastd_method_t *method, const uint8_t *secret, size_t length, bool initiator) {
if (length < crypto_secretbox_xsalsa20poly1305_KEYBYTES)
exit_bug("xsalsa20-poly1305: tried to init with short secret");
@@ -66,22 +82,27 @@ static fastd_method_session_state_t* method_session_init_compat(const fastd_meth
return method_session_init(method, secret, initiator);
}
+/** Checks if a session is currently valid */
static bool method_session_is_valid(fastd_method_session_state_t *session) {
return (session && fastd_method_session_common_is_valid(&session->common));
}
+/** Checks if this side is the initiator of the session */
static bool method_session_is_initiator(fastd_method_session_state_t *session) {
return fastd_method_session_common_is_initiator(&session->common);
}
+/** Checks if the session should be refreshed */
static bool method_session_want_refresh(fastd_method_session_state_t *session) {
return fastd_method_session_common_want_refresh(&session->common);
}
+/** Marks the session as superseded */
static void method_session_superseded(fastd_method_session_state_t *session) {
fastd_method_session_common_superseded(&session->common);
}
+/** Frees the session state */
static void method_session_free(fastd_method_session_state_t *session) {
if(session) {
secure_memzero(session, sizeof(fastd_method_session_state_t));
@@ -90,12 +111,19 @@ static void method_session_free(fastd_method_session_state_t *session) {
}
+/**
+ Copies a nonce of length COMMON_NONCEBYTES to a buffer, reversing its byte order
+
+ To maintain compability with pre-v11 versions, which used a little-endian nonce,
+ the xsalsa20-poly1305 keeps using the old nonce format.
+*/
static inline void memcpy_nonce(uint8_t *dst, const uint8_t *src) {
size_t i;
for (i = 0; i < COMMON_NONCEBYTES; i++)
dst[i] = src[COMMON_NONCEBYTES-i-1];
}
+/** Adds the xsalsa20-poly1305 header to the head of a packet */
static inline void put_header(fastd_buffer_t *buffer, const uint8_t nonce[COMMON_NONCEBYTES], uint8_t flags) {
fastd_buffer_pull_head_from(buffer, &flags, 1);
@@ -103,19 +131,22 @@ static inline void put_header(fastd_buffer_t *buffer, const uint8_t nonce[COMMON
memcpy_nonce(buffer->data, nonce);
}
+/** Removes the xsalsa20-poly1305 header from the head of a packet */
static inline void take_header(fastd_buffer_t *buffer, uint8_t nonce[COMMON_NONCEBYTES], uint8_t *flags) {
- memcpy_nonce(nonce, buffer->data );
+ memcpy_nonce(nonce, buffer->data);
fastd_buffer_push_head(buffer, COMMON_NONCEBYTES);
fastd_buffer_push_head_to(buffer, flags, 1);
}
+/** Removes and handles the xsalsa20-poly1305 header from the head of a packet */
static inline bool handle_header(const fastd_method_common_t *session, fastd_buffer_t *buffer, uint8_t nonce[COMMON_NONCEBYTES], uint8_t *flags, int64_t *age) {
take_header(buffer, nonce, flags);
return fastd_method_is_nonce_valid(session, nonce, age);
}
+/** Performs encryption and authentication of a packet */
static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
fastd_buffer_pull_head_zero(&in, crypto_secretbox_xsalsa20poly1305_ZEROBYTES);
@@ -135,6 +166,7 @@ static bool method_encrypt(fastd_peer_t *peer UNUSED, fastd_method_session_state
return true;
}
+/** Performs validation and decryption of a packet */
static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *session, fastd_buffer_t *out, fastd_buffer_t in) {
if (in.len < COMMON_HEADBYTES)
return false;
@@ -180,6 +212,7 @@ static bool method_decrypt(fastd_peer_t *peer, fastd_method_session_state_t *ses
}
+/** The xsalsa20-poly1305 method provider */
const fastd_method_provider_t fastd_method_xsalsa20_poly1305 = {
.max_overhead = COMMON_HEADBYTES + crypto_secretbox_xsalsa20poly1305_ZEROBYTES - crypto_secretbox_xsalsa20poly1305_BOXZEROBYTES,
diff --git a/src/options.c b/src/options.c
index 2a84a06..7ac026e 100644
--- a/src/options.c
+++ b/src/options.c
@@ -23,6 +23,25 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Handling of command line options
+
+
+ \def OPTION
+ Defines a command line option without argument
+
+ \def OPTION_ARG
+ Defines a command line option with an argument
+
+ \def OR
+ Separates multiple alternative options with the same meaning
+
+ \def SEPARATOR
+ Separates groups of related options
+*/
+
#include "fastd.h"
#include "config.h"
@@ -32,6 +51,7 @@
#include <arpa/inet.h>
+/** Prints the usage message for a single command line option */
static void print_usage(const char *options, const char *message) {
/* 28 spaces */
static const char spaces[] = {[0 ... 27] = ' ', [28] = 0};
@@ -48,6 +68,8 @@ static void print_usage(const char *options, const char *message) {
puts(message);
}
+
+/** Prints the usage message and exits */
static void usage(void) {
puts("fastd (Fast and Secure Tunnelling Daemon) " FASTD_VERSION " usage:\n");
@@ -64,21 +86,27 @@ static void usage(void) {
exit(0);
}
+
+
+/** Prints fastd's version and exits */
static void version(void) {
puts("fastd " FASTD_VERSION);
exit(0);
}
+/** Handles the --daemon option */
static void option_daemon(void) {
conf.daemon = true;
}
+/** Handles the --pid-file option */
static void option_pid_file(const char *arg) {
free(conf.pid_file);
conf.pid_file = strdup(arg);
}
+/** Handles the --config option */
static void option_config(const char *arg) {
if (!strcmp(arg, "-"))
arg = NULL;
@@ -87,6 +115,7 @@ static void option_config(const char *arg) {
exit(1);
}
+/** Handles the --config-peer option */
static void option_config_peer(const char *arg) {
fastd_peer_config_new();
@@ -94,6 +123,7 @@ static void option_config_peer(const char *arg) {
exit(1);
}
+/** Handles the --config-peer-dir option */
static void option_config_peer_dir(const char *arg) {
fastd_add_peer_dir(arg);
}
@@ -101,11 +131,13 @@ static void option_config_peer_dir(const char *arg) {
#ifdef WITH_CMDLINE_USER
+/** Handles the --config-user option */
static void option_user(const char *arg) {
free(conf.user);
conf.user = strdup(arg);
}
+/** Handles the --config-group option */
static void option_group(const char *arg) {
free(conf.group);
conf.group = strdup(arg);
@@ -115,6 +147,7 @@ static void option_group(const char *arg) {
#ifdef WITH_CMDLINE_LOGGING
+/** Parses a log level argument */
static int parse_log_level(const char *arg) {
if (!strcmp(arg, "fatal"))
return LL_FATAL;
@@ -134,23 +167,28 @@ static int parse_log_level(const char *arg) {
exit_error("invalid log level `%s'", arg);
}
+/** Handles the --log-level option */
static void option_log_level(const char *arg) {
conf.log_stderr_level = parse_log_level(arg);
}
+/** Handles the --syslog-level option */
static void option_syslog_level(const char *arg) {
conf.log_syslog_level = parse_log_level(arg);
}
+/** Handles the --syslog-ident option */
static void option_syslog_ident(const char *arg) {
free(conf.log_syslog_ident);
conf.log_syslog_ident = strdup(arg);
}
+/** Handles the --hide-ip-addresses option */
static void option_hide_ip_addresses(void) {
conf.hide_ip_addresses = true;
}
+/** Handles the --hide-mac-addresses option */
static void option_hide_mac_addresses(void) {
conf.hide_mac_addresses = true;
}
@@ -159,6 +197,7 @@ static void option_hide_mac_addresses(void) {
#ifdef WITH_CMDLINE_OPERATION
+/** Handles the --mode option */
static void option_mode(const char *arg) {
if (!strcmp(arg, "tap"))
conf.mode = MODE_TAP;
@@ -168,11 +207,13 @@ static void option_mode(const char *arg) {
exit_error("invalid mode `%s'", arg);
}
+/** Handles the --interface option */
static void option_interface(const char *arg) {
free(conf.ifname);
conf.ifname = strdup(arg);
}
+/** Handles the --mtu option */
static void option_mtu(const char *arg) {
char *endptr;
long mtu = strtol(arg, &endptr, 10);
@@ -183,6 +224,7 @@ static void option_mtu(const char *arg) {
conf.mtu = mtu;
}
+/** Handles the --bind option */
static void option_bind(const char *arg) {
long l;
char *charptr;
@@ -253,14 +295,17 @@ static void option_bind(const char *arg) {
fastd_config_bind_address(&addr, ifname, false, false);
}
+/** Handles the --protocol option */
static void option_protocol(const char *arg) {
fastd_config_protocol(arg);
}
+/** Handles the --method option */
static void option_method(const char *arg) {
fastd_config_method(arg);
}
+/** Handles the --forward option */
static void option_forward(void) {
conf.forward = true;
}
@@ -269,36 +314,44 @@ static void option_forward(void) {
#ifdef WITH_CMDLINE_COMMANDS
+/** Handles the --on-pre-up option */
static void option_on_pre_up(const char *arg) {
fastd_shell_command_set(&conf.on_pre_up, arg, true);
}
+/** Handles the --on-up option */
static void option_on_up(const char *arg) {
fastd_shell_command_set(&conf.on_up, arg, true);
}
+/** Handles the --on-down option */
static void option_on_down(const char *arg) {
fastd_shell_command_set(&conf.on_down, arg, true);
}
+/** Handles the --on-post-down option */
static void option_on_post_down(const char *arg) {
fastd_shell_command_set(&conf.on_post_down, arg, true);
}
+/** Handles the --on-connect option */
static void option_on_connect(const char *arg) {
fastd_shell_command_set(&conf.on_connect, arg, false);
}
+/** Handles the --on-establish option */
static void option_on_establish(const char *arg) {
fastd_shell_command_set(&conf.on_establish, arg, false);
}
+/** Handles the --on-disestablish option */
static void option_on_disestablish(const char *arg) {
fastd_shell_command_set(&conf.on_disestablish, arg, false);
}
#ifdef WITH_VERIFY
+/** Handles the --on-verify option */
static void option_on_verify(const char *arg) {
fastd_shell_command_set(&conf.on_verify, arg, false);
}
@@ -307,25 +360,30 @@ static void option_on_verify(const char *arg) {
#endif
+/** Handles the --verify-config option */
static void option_verify_config(void) {
conf.verify_config = true;
}
+/** Handles the --generate-key option */
static void option_generate_key(void) {
conf.generate_key = true;
conf.show_key = false;
}
+/** Handles the --show-key option */
static void option_show_key(void) {
conf.generate_key = false;
conf.show_key = true;
}
+/** Handles the --machine-readable option */
static void option_machine_readable(void) {
conf.machine_readable = true;
}
+/** Matches a command line options agains a NULL-terminated list of arguments */
static bool config_match(const char *opt, ...) {
va_list ap;
bool match = false;
@@ -345,6 +403,7 @@ static bool config_match(const char *opt, ...) {
return match;
}
+/** Parses and handles the supplied command line options */
void fastd_config_handle_options(int argc, char *const argv[]) {
int i = 1;
diff --git a/src/peer_hashtable.c b/src/peer_hashtable.c
index 003a16c..475d7f9 100644
--- a/src/peer_hashtable.c
+++ b/src/peer_hashtable.c
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ A hashtable allowing fast lookup from an IP address to a peer
+*/
+
#include "peer_hashtable.h"
#include "fastd.h"
@@ -30,9 +36,11 @@
#include "peer.h"
+/** The number of hash buckets used */
#define PEER_ADDR_HT_SIZE 64
+/** Initializes the hashtable */
void fastd_peer_hashtable_init(void) {
fastd_random_bytes(&ctx.peer_addr_ht_seed, sizeof(ctx.peer_addr_ht_seed), false);
@@ -43,6 +51,7 @@ void fastd_peer_hashtable_init(void) {
VECTOR_ALLOC(ctx.peer_addr_ht[i], 0);
}
+/** Frees the resources used by the hashtable */
void fastd_peer_hashtable_free(void) {
size_t i;
for (i = 0; i < PEER_ADDR_HT_SIZE; i++)
@@ -51,6 +60,7 @@ void fastd_peer_hashtable_free(void) {
free(ctx.peer_addr_ht);
}
+/** Gets the hash bucket used for an address */
static size_t peer_address_bucket(const fastd_peer_address_t *addr) {
uint32_t hash = ctx.peer_addr_ht_seed;
@@ -72,11 +82,21 @@ static size_t peer_address_bucket(const fastd_peer_address_t *addr) {
return hash % PEER_ADDR_HT_SIZE;
}
+/**
+ Inserts a peer into the hash table
+
+ The peer address must not change while the peer is part of the table.
+*/
void fastd_peer_hashtable_insert(fastd_peer_t *peer) {
size_t b = peer_address_bucket(&peer->address);
VECTOR_ADD(ctx.peer_addr_ht[b], peer);
}
+/**
+ Removes a peer from the hash table
+
+ A peer must be removed from the table before it is deleted or its address is changed.
+*/
void fastd_peer_hashtable_remove(fastd_peer_t *peer) {
if (!peer->address.sa.sa_family)
return;
@@ -92,6 +112,7 @@ void fastd_peer_hashtable_remove(fastd_peer_t *peer) {
}
}
+/** Looks up a peer in the hashtable */
fastd_peer_t *fastd_peer_hashtable_lookup(const fastd_peer_address_t *addr) {
size_t b = peer_address_bucket(addr);
diff --git a/src/peer_hashtable.h b/src/peer_hashtable.h
index 6c026bc..fae2075 100644
--- a/src/peer_hashtable.h
+++ b/src/peer_hashtable.h
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ A hashtable allowing fast lookup from an IP address to a peer
+*/
+
#pragma once
diff --git a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c
index b97bf4d..86acbec 100644
--- a/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c
+++ b/src/protocols/ec25519_fhmqvc/ec25519_fhmqvc.c
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ ec25519-fhmqvc protocol: basic functions
+*/
+
#include "ec25519_fhmqvc.h"
diff --git a/src/protocols/ec25519_fhmqvc/handshake.c b/src/protocols/ec25519_fhmqvc/handshake.c
index c29b7b1..7374061 100644
--- a/src/protocols/ec25519_fhmqvc/handshake.c
+++ b/src/protocols/ec25519_fhmqvc/handshake.c
@@ -23,6 +23,11 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ ec25519-fhmqvc protocol: handshake handling
+*/
#include "handshake.h"
#include "../../handshake.h"
@@ -30,6 +35,7 @@
#include "../../verify.h"
+/** The size of the hash outputs used in the handshake */
#define HASHBYTES FASTD_SHA256_HASH_BYTES
@@ -42,13 +48,33 @@
#endif
+/** TLV field: sender public key */
#define RECORD_SENDER_KEY RECORD_PROTOCOL1
-#define RECORD_RECEIPIENT_KEY RECORD_PROTOCOL2
+
+/** TLV field: recipient public key */
+#define RECORD_RECIPIENT_KEY RECORD_PROTOCOL2
+
+/** TLV field: sender ephemeral public key */
#define RECORD_SENDER_HANDSHAKE_KEY RECORD_PROTOCOL3
-#define RECORD_RECEIPIENT_HANDSHAKE_KEY RECORD_PROTOCOL4
+
+/** TLV field: recipient ephemeral public key */
+#define RECORD_RECIPIENT_HANDSHAKE_KEY RECORD_PROTOCOL4
+
+/**
+ TLV field: pre-v11 compat handshake MAC
+
+ The pre-v11 handshake protocol only secured the four key fields
+ of the handshake with a MAC, which allowed manipulation of other fields like
+ the method list; it was replaced by the RECORD_TLV_MAC field in the new
+ handshake protocol.
+
+ In pre-v11 compat mode fastd ("secure handshakes no") will include both the old and the new
+ record in the handshake.
+*/
#define RECORD_T RECORD_PROTOCOL5
+/** Derives a key of arbitraty length from the shared key material after a handshake using the HKDF algorithm */
static void derive_key(fastd_sha256_t *out, size_t blocks, const uint32_t *salt, const char *method_name,
const aligned_int256_t *A, const aligned_int256_t *B, const aligned_int256_t *X, const aligned_int256_t *Y,
const aligned_int256_t *sigma) {
@@ -67,6 +93,7 @@ static void derive_key(fastd_sha256_t *out, size_t blocks, const uint32_t *salt,
fastd_hkdf_sha256_expand(out, blocks, &prk, info, sizeof(info));
}
+/** Marks the active session as superseded and moves it to the \e old_session field of the protocol peer state */
static inline void supersede_session(fastd_peer_t *peer, const fastd_method_info_t *method) {
if (is_session_valid(&peer->protocol_state->session) && !is_session_valid(&peer->protocol_state->old_session)) {
if (peer->protocol_state->old_session.method)
@@ -90,6 +117,7 @@ static inline void supersede_session(fastd_peer_t *peer, const fastd_method_info
}
}
+/** Initalizes a new session with a peer using a specified method */
static inline bool new_session(fastd_peer_t *peer, const fastd_method_info_t *method, bool initiator,
const aligned_int256_t *A, const aligned_int256_t *B, const aligned_int256_t *X, const aligned_int256_t *Y,
const aligned_int256_t *sigma, const uint32_t *salt, uint64_t serial) {
@@ -120,6 +148,7 @@ static inline bool new_session(fastd_peer_t *peer, const fastd_method_info_t *me
return true;
}
+/** Establishes a connection with a peer after a successful handshake */
static bool establish(fastd_peer_t *peer, const fastd_method_info_t *method, fastd_socket_t *sock,
const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, bool initiator,
const aligned_int256_t *A, const aligned_int256_t *B, const aligned_int256_t *X, const aligned_int256_t *Y,
@@ -143,7 +172,7 @@ static bool establish(fastd_peer_t *peer, const fastd_method_info_t *method, fas
}
if (!new_session(peer, method, initiator, A, B, X, Y, sigma, salt, serial)) {
- pr_error("failed to initialize method session for %P (method `%s'%s)", peer, method->name, salt ? "" : " (compat mode)");
+ pr_error("failed to initialize method session for %P (method `%s'%s)", peer, method->name, salt ? "" : ", compat mode");
fastd_peer_reset(peer);
return false;
}
@@ -163,15 +192,18 @@ static bool establish(fastd_peer_t *peer, const fastd_method_info_t *method, fas
}
+/** Checks if a handshake has a field of a given type and length */
static inline bool has_field(const fastd_handshake_t *handshake, uint8_t type, size_t length) {
return (handshake->records[type].length == length);
}
+/** Checks the handshake has a TLV MAC field, meaning the handshake was sent by fastd v11 or newer */
static inline bool secure_handshake(const fastd_handshake_t *handshake) {
return has_field(handshake, RECORD_TLV_MAC, HASHBYTES);
}
+/** Derives the shares handshake key for computing the MACs used in the handshake */
static bool make_shared_handshake_key(const ecc_int256_t *handshake_key, bool initiator,
const aligned_int256_t *A, const aligned_int256_t *B,
const aligned_int256_t *X, const aligned_int256_t *Y,
@@ -235,6 +267,7 @@ static bool make_shared_handshake_key(const ecc_int256_t *handshake_key, bool in
return true;
}
+/** Checks if the currently cached shared handshake key is valid and generates a new one otherwise */
static bool update_shared_handshake_key(const fastd_peer_t *peer, const handshake_key_t *handshake_key, const aligned_int256_t *peer_handshake_key) {
if (peer->protocol_state->last_handshake_serial == handshake_key->serial) {
if (memcmp(&peer->protocol_state->peer_handshake_key, peer_handshake_key, PUBLICKEYBYTES) == 0)
@@ -259,6 +292,7 @@ static bool update_shared_handshake_key(const fastd_peer_t *peer, const handshak
return true;
}
+/** Resets the handshake cache for a peer */
static void clear_shared_handshake_key(const fastd_peer_t *peer) {
memset(&peer->protocol_state->sigma, 0, sizeof(peer->protocol_state->sigma));
memset(&peer->protocol_state->shared_handshake_key, 0, sizeof(peer->protocol_state->shared_handshake_key));
@@ -268,6 +302,7 @@ static void clear_shared_handshake_key(const fastd_peer_t *peer) {
memset(&peer->protocol_state->peer_handshake_key, 0, sizeof(peer->protocol_state->peer_handshake_key));
}
+/** Sends a reply to an initial handshake (type 1) */
static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer,
const aligned_int256_t *peer_handshake_key, const fastd_method_info_t *method) {
pr_debug("responding handshake with %P[%I]...", peer, remote_addr);
@@ -280,9 +315,9 @@ static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_addre
fastd_buffer_t buffer = fastd_handshake_new_reply(2, method, true, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
- fastd_handshake_add(&buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key);
fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &handshake_key->key.public);
- fastd_handshake_add(&buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key);
fastd_sha256_t hmacbuf;
@@ -298,6 +333,7 @@ static void respond_handshake(const fastd_socket_t *sock, const fastd_peer_addre
fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
}
+/** Sends a reply to a handshake response (type 2) */
static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer, const handshake_key_t *handshake_key, const aligned_int256_t *peer_handshake_key,
const fastd_handshake_t *handshake, const fastd_method_info_t *method) {
pr_debug("finishing handshake with %P[%I]...", peer, remote_addr);
@@ -340,9 +376,9 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
fastd_buffer_t buffer = fastd_handshake_new_reply(3, method, false, 4*(4+PUBLICKEYBYTES) + 2*(4+HASHBYTES));
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
- fastd_handshake_add(&buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key);
fastd_handshake_add(&buffer, RECORD_SENDER_HANDSHAKE_KEY, PUBLICKEYBYTES, &handshake_key->key.public);
- fastd_handshake_add(&buffer, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES, peer_handshake_key);
if (!compat) {
fastd_sha256_t hmacbuf;
@@ -359,6 +395,7 @@ static void finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *l
fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
}
+/** Handles a reply to a handshake response (type 3) */
static void handle_finish_handshake(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
fastd_peer_t *peer, const handshake_key_t *handshake_key, const aligned_int256_t *peer_handshake_key,
const fastd_handshake_t *handshake, const fastd_method_info_t *method) {
@@ -392,6 +429,7 @@ static void handle_finish_handshake(fastd_socket_t *sock, const fastd_peer_addre
clear_shared_handshake_key(peer);
}
+/** Searches the peer a public key belongs to */
static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const unsigned char key[PUBLICKEYBYTES]) {
errno = 0;
@@ -423,6 +461,7 @@ static fastd_peer_t* find_sender_key(const fastd_peer_address_t *address, const
return ret;
}
+/** Checks if a key matches a peer and searches the correct peer if it doesn't */
static fastd_peer_t* match_sender_key(const fastd_socket_t *sock, const fastd_peer_address_t *address, fastd_peer_t *peer, const unsigned char key[PUBLICKEYBYTES]) {
errno = 0;
@@ -442,6 +481,7 @@ static fastd_peer_t* match_sender_key(const fastd_socket_t *sock, const fastd_pe
return find_sender_key(address, key);
}
+/** Counts how many peers with a key are configured */
static size_t key_count(const unsigned char key[PUBLICKEYBYTES]) {
size_t ret = 0;
@@ -457,6 +497,7 @@ static size_t key_count(const unsigned char key[PUBLICKEYBYTES]) {
return ret;
}
+/** Validates a peer config */
bool fastd_protocol_ec25519_fhmqvc_peer_check(fastd_peer_config_t *peer_conf) {
if (!peer_conf->protocol_config)
return false;
@@ -474,15 +515,16 @@ bool fastd_protocol_ec25519_fhmqvc_peer_check(fastd_peer_config_t *peer_conf) {
return true;
}
+/** Sends an initial handshake (type 1) to a peer */
void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, fastd_peer_t *peer) {
fastd_protocol_ec25519_fhmqvc_maintenance();
- fastd_buffer_t buffer = fastd_handshake_new_init(3*(4+PUBLICKEYBYTES) /* sender key, receipient key, handshake key */);
+ fastd_buffer_t buffer = fastd_handshake_new_init(3*(4+PUBLICKEYBYTES) /* sender key, recipient key, handshake key */);
fastd_handshake_add(&buffer, RECORD_SENDER_KEY, PUBLICKEYBYTES, &conf.protocol_config->key.public);
if (peer)
- fastd_handshake_add(&buffer, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key);
+ fastd_handshake_add(&buffer, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES, &peer->protocol_config->public_key);
else
pr_debug("sending handshake to unknown peer %I", remote_addr);
@@ -494,6 +536,7 @@ void fastd_protocol_ec25519_fhmqvc_handshake_init(fastd_socket_t *sock, const fa
fastd_send_handshake(sock, local_addr, remote_addr, peer, buffer);
}
+/** Checks if a temporary peer (added after an on-verify command) can stay after new peers have been configured */
bool fastd_protocol_ec25519_fhmqvc_peer_check_temporary(fastd_peer_t *peer) {
if (key_count(peer->protocol_config->public_key.u8)) {
char buf[65];
@@ -508,10 +551,12 @@ bool fastd_protocol_ec25519_fhmqvc_peer_check_temporary(fastd_peer_t *peer) {
#ifdef WITH_VERIFY
+/** Data attached to an asynchronous on-verify run */
typedef struct verify_data {
- aligned_int256_t peer_handshake_key;
+ aligned_int256_t peer_handshake_key; /**< The public key of the peer being verified */
} verify_data_t;
+/** Adds a temporary peer for an unknown key */
static fastd_peer_t * add_temporary(fastd_socket_t *sock, const fastd_peer_address_t *addr, const unsigned char key[PUBLICKEYBYTES]) {
if (!fastd_allow_verify()) {
pr_debug("ignoring handshake from %I (unknown key)", addr);
@@ -540,6 +585,7 @@ static fastd_peer_t * add_temporary(fastd_socket_t *sock, const fastd_peer_addre
return peer;
}
+/** Is called when a handshake from a temporary peer is received */
static bool handle_temporary(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, const fastd_method_info_t *method) {
if (handshake->type != 1 || !fastd_timed_out(&peer->verify_timeout))
@@ -564,6 +610,7 @@ static bool handle_temporary(fastd_socket_t *sock, const fastd_peer_address_t *l
return true;
}
+/** Handles a reply from an asynchronous on-verify command */
void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr,
const fastd_method_info_t *method, const void *protocol_data, bool ok) {
if (!ok)
@@ -578,6 +625,7 @@ void fastd_protocol_ec25519_fhmqvc_handle_verify_return(fastd_peer_t *peer, fast
#else
+/** Dummy add temporary function for fastd versions without on-verify support */
static inline fastd_peer_t * add_temporary(fastd_socket_t *sock UNUSED, const fastd_peer_address_t *addr, const unsigned char key[PUBLICKEYBYTES] UNUSED) {
pr_debug("ignoring handshake from %I (unknown key)", addr);
return NULL;
@@ -586,6 +634,7 @@ static inline fastd_peer_t * add_temporary(fastd_socket_t *sock UNUSED, const fa
#endif /* WITH_VERIFY */
+/** Handles a received handshake packet */
void fastd_protocol_ec25519_fhmqvc_handshake_handle(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, const fastd_method_info_t *method) {
fastd_protocol_ec25519_fhmqvc_maintenance();
@@ -629,9 +678,9 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const
return;
}
- if (has_field(handshake, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES)) {
- if (memcmp(&conf.protocol_config->key.public, handshake->records[RECORD_RECEIPIENT_KEY].data, PUBLICKEYBYTES) != 0) {
- pr_debug("received protocol handshake with wrong receipient key from %P[%I]", peer, remote_addr);
+ if (has_field(handshake, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES)) {
+ if (memcmp(&conf.protocol_config->key.public, handshake->records[RECORD_RECIPIENT_KEY].data, PUBLICKEYBYTES) != 0) {
+ pr_debug("received protocol handshake with wrong recipient key from %P[%I]", peer, remote_addr);
return;
}
}
@@ -661,12 +710,12 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const
return;
}
- if (!has_field(handshake, RECORD_RECEIPIENT_KEY, PUBLICKEYBYTES)) {
- pr_debug("received handshake reply without receipient key from %P[%I]", peer, remote_addr);
+ if (!has_field(handshake, RECORD_RECIPIENT_KEY, PUBLICKEYBYTES)) {
+ pr_debug("recived handshake reply without recipient key from %P[%I]", peer, remote_addr);
return;
}
- if (!has_field(handshake, RECORD_RECEIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES)) {
+ if (!has_field(handshake, RECORD_RECIPIENT_HANDSHAKE_KEY, PUBLICKEYBYTES)) {
pr_debug("received handshake reply without receipient handshake key from %P[%I]", peer, remote_addr);
return;
}
@@ -680,15 +729,15 @@ void fastd_protocol_ec25519_fhmqvc_handshake_handle(fastd_socket_t *sock, const
handshake_key_t *handshake_key;
if (is_handshake_key_valid(&ctx.protocol_state->handshake_key) &&
- memcmp(&ctx.protocol_state->handshake_key.key.public, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) {
+ memcmp(&ctx.protocol_state->handshake_key.key.public, handshake->records[RECORD_RECIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) {
handshake_key = &ctx.protocol_state->handshake_key;
}
else if (is_handshake_key_valid(&ctx.protocol_state->prev_handshake_key) &&
- memcmp(&ctx.protocol_state->prev_handshake_key.key.public, handshake->records[RECORD_RECEIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) {
+ memcmp(&ctx.protocol_state->prev_handshake_key.key.public, handshake->records[RECORD_RECIPIENT_HANDSHAKE_KEY].data, PUBLICKEYBYTES) == 0) {
handshake_key = &ctx.protocol_state->prev_handshake_key;
}
else {
- pr_debug("received handshake reply with unexpected receipient handshake key from %P[%I]", peer, remote_addr);
+ pr_debug("received handshake reply with unexpected recipient handshake key from %P[%I]", peer, remote_addr);
return;
}
diff --git a/src/protocols/ec25519_fhmqvc/state.c b/src/protocols/ec25519_fhmqvc/state.c
index f20b381..451e31d 100644
--- a/src/protocols/ec25519_fhmqvc/state.c
+++ b/src/protocols/ec25519_fhmqvc/state.c
@@ -23,11 +23,18 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ ec25519-fhmqvc protocol: state handling
+*/
+
#include "handshake.h"
#include "../../crypto.h"
+/** Allocates the protocol-specific state */
static void init_protocol_state(void) {
if (!ctx.protocol_state) {
ctx.protocol_state = calloc(1, sizeof(fastd_protocol_state_t));
@@ -37,6 +44,7 @@ static void init_protocol_state(void) {
}
}
+/** Generates a new ephemeral keypair */
static void new_handshake_key(keypair_t *key) {
fastd_random_bytes(key->secret.p, SECRETKEYBYTES, false);
ecc_25519_gf_sanitize_secret(&key->secret, &key->secret);
@@ -46,6 +54,12 @@ static void new_handshake_key(keypair_t *key) {
ecc_25519_store_packed(&key->public.int256, &work);
}
+/**
+ Performs maintenance tasks on the protocol state
+
+ If there is currently no preferred ephemeral keypair, a new one
+ will be generated.
+*/
void fastd_protocol_ec25519_fhmqvc_maintenance(void) {
init_protocol_state();
@@ -63,6 +77,7 @@ void fastd_protocol_ec25519_fhmqvc_maintenance(void) {
}
}
+/** Allocated protocol-specific peer state */
void fastd_protocol_ec25519_fhmqvc_init_peer_state(fastd_peer_t *peer) {
init_protocol_state();
@@ -73,12 +88,14 @@ void fastd_protocol_ec25519_fhmqvc_init_peer_state(fastd_peer_t *peer) {
peer->protocol_state->last_serial = ctx.protocol_state->handshake_key.serial;
}
+/** Resets a the state of a session, freeing method-specific state */
static void reset_session(protocol_session_t *session) {
if (session->method)
session->method->provider->session_free(session->method_state);
secure_memzero(session, sizeof(protocol_session_t));
}
+/** Resets all protocol-specific state of a peer */
void fastd_protocol_ec25519_fhmqvc_reset_peer_state(fastd_peer_t *peer) {
if (!peer->protocol_state)
return;
@@ -87,6 +104,7 @@ void fastd_protocol_ec25519_fhmqvc_reset_peer_state(fastd_peer_t *peer) {
reset_session(&peer->protocol_state->session);
}
+/** Frees the protocol-specific state */
void fastd_protocol_ec25519_fhmqvc_free_peer_state(fastd_peer_t *peer) {
if (peer->protocol_state) {
reset_session(&peer->protocol_state->old_session);
diff --git a/src/protocols/ec25519_fhmqvc/util.c b/src/protocols/ec25519_fhmqvc/util.c
index a53513f..e4a0c08 100644
--- a/src/protocols/ec25519_fhmqvc/util.c
+++ b/src/protocols/ec25519_fhmqvc/util.c
@@ -23,10 +23,17 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ ec25519-fhmqvc protocol: utilify functions
+*/
+
#include "ec25519_fhmqvc.h"
+/** Prints a private or public key on stdout with an optional descriptive text */
static inline void print_hexdump(const char *desc, unsigned char d[32]) {
char buf[65];
hexdump(buf, d);
@@ -34,6 +41,7 @@ static inline void print_hexdump(const char *desc, unsigned char d[32]) {
printf("%s%s\n", desc, buf);
}
+/** Generates a new keypair */
void fastd_protocol_ec25519_fhmqvc_generate_key(void) {
ecc_int256_t secret_key;
ecc_int256_t public_key;
@@ -57,6 +65,7 @@ void fastd_protocol_ec25519_fhmqvc_generate_key(void) {
}
}
+/** Prints the public key corresponding to the configured private key */
void fastd_protocol_ec25519_fhmqvc_show_key(void) {
if (conf.machine_readable)
print_hexdump("", conf.protocol_config->key.public.u8);
@@ -64,6 +73,7 @@ void fastd_protocol_ec25519_fhmqvc_show_key(void) {
print_hexdump("Public: ", conf.protocol_config->key.public.u8);
}
+/** Adds protocol- and peer-specific environment variables to an environment */
void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer) {
char buf[65];
@@ -79,6 +89,13 @@ void fastd_protocol_ec25519_fhmqvc_set_shell_env(fastd_shell_env_t *env, const f
}
}
+/**
+ Generates a protocol-specific string representation of a peer
+
+ This will only be used for peers without names (e.g. temporary peers) and
+ creates a string containing the first 16 hexadecimal digits of the peer's
+ public key.
+*/
bool fastd_protocol_ec25519_fhmqvc_describe_peer(const fastd_peer_t *peer, char *buf, size_t len) {
if (peer && peer->protocol_config) {
char dumpbuf[65];
diff --git a/src/shell.c b/src/shell.c
index c573a85..c161a9e 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -40,14 +40,14 @@
/** An environment variable */
typedef struct shell_env_entry {
- const char *key;
- char *value;
+ const char *key; /**< The name of the enviroment variable */
+ char *value; /**< The value of the environment variable */
} shell_env_entry_t;
/** A shell environment */
struct fastd_shell_env {
- VECTOR(shell_env_entry_t) entries;
+ VECTOR(shell_env_entry_t) entries; /**< Vector of the entries of the environment */
};
diff --git a/src/socket.c b/src/socket.c
index 49752fc..5ab9fc1 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -23,11 +23,21 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Socket handling
+*/
#include "fastd.h"
#include "poll.h"
+/**
+ Creates a new socket bound to a specific address
+
+ \return The new socket's file descriptor
+*/
static int bind_socket(const fastd_bind_address_t *addr, bool warn) {
int fd = -1;
int af = AF_UNSPEC;
@@ -160,6 +170,7 @@ static int bind_socket(const fastd_bind_address_t *addr, bool warn) {
return -1;
}
+/** Gets the address a socket is bound to and sets it in the socket structure */
static bool set_bound_address(fastd_socket_t *sock) {
fastd_peer_address_t addr = {};
socklen_t len = sizeof(addr);
diff --git a/src/verify.c b/src/verify.c
index 694206f..4cf0c67 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Handling of on-verify commands to add peers not configured statically ("temporary peers")
+*/
+
#include "verify.h"
@@ -35,6 +41,12 @@
#include <pthread.h>
+/**
+ Calls the on-verify command and returns the result
+
+ do_verify() may be called from secondary threads as all information about the peer
+ to verify is encoded in the supplied environment
+*/
static bool do_verify(const fastd_shell_env_t *env) {
int ret;
if (!fastd_shell_command_exec_sync(&conf.on_verify, env, &ret))
@@ -52,12 +64,14 @@ static bool do_verify(const fastd_shell_env_t *env) {
return true;
}
+/** The argument given to asynchronous verifier threads */
typedef struct verify_arg {
- fastd_shell_env_t *env;
- size_t ret_len;
- fastd_async_verify_return_t ret;
+ fastd_shell_env_t *env; /**< Enviroment containing information about the peer to verify */
+ size_t ret_len; /**< Length of the \e ret field (as it contains a flexible member) */
+ fastd_async_verify_return_t ret; /**< Information to return to the main thread after the verification */
} verify_arg_t;
+/** Verifier thread main function */
static void * do_verify_thread(void *p) {
verify_arg_t *arg = p;
@@ -71,6 +85,12 @@ static void * do_verify_thread(void *p) {
return NULL;
}
+/**
+ Verifies a peer
+
+ \return A tristate. If on-verify is a synchronous command, it will be \e true or \e false, but if the command is asynchronous (which is the default),
+ \e undef will be returned and the result is sent via the asyncronous notification mechanism.
+*/
fastd_tristate_t fastd_verify_peer(fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr, const fastd_method_info_t *method, const void *data, size_t data_len) {
if (!fastd_shell_command_isset(&conf.on_verify))
exit_bug("tried to verify peer without on-verify command");
diff --git a/src/verify.h b/src/verify.h
index 7f0d5c0..5203339 100644
--- a/src/verify.h
+++ b/src/verify.h
@@ -23,6 +23,12 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+/**
+ \file
+
+ Handling of on-verify commands to add peers not configured statically ("temporary peers")
+*/
+
#pragma once