diff options
Diffstat (limited to 'src/methods')
-rw-r--r-- | src/methods/cipher_test/cipher_test.c | 35 | ||||
-rw-r--r-- | src/methods/composed_gmac/composed_gmac.c | 50 | ||||
-rw-r--r-- | src/methods/generic_gmac/generic_gmac.c | 41 | ||||
-rw-r--r-- | src/methods/generic_poly1305/generic_poly1305.c | 38 | ||||
-rw-r--r-- | src/methods/methods.c.in | 8 | ||||
-rw-r--r-- | src/methods/null/null.c | 28 | ||||
-rw-r--r-- | src/methods/xsalsa20_poly1305/xsalsa20_poly1305.c | 39 |
7 files changed, 204 insertions, 35 deletions
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, |