From be5b441e58e15d7213e752ff50742eb19fef249d Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Tue, 9 Jun 2020 11:15:58 +0200 Subject: [PATCH 01/45] Fix default gateway routes The 128.0.0.0/1 route was missing causing some traffic to go outside the VPN --- edge_utils.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/edge_utils.c b/edge_utils.c index 825b8ef..11a7a7f 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -2325,10 +2325,12 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r * 2. Add the new default gateway route * * Instead of modifying the system default gateway, we use the trick - * of adding a route to the 0.0.0.0/1 network, which takes precedence - * over the default gateway (0.0.0.0/0). This leaves the default - * gateway unchanged so that after n2n is stopped the cleanup is - * easier. + * of adding a route to the networks 0.0.0.0/1 and 128.0.0.0/1, thus + * covering the whole IPv4 range. Such routes in linux take precedence + * over the default gateway (0.0.0.0/0) since are more specific. + * This leaves the default gateway unchanged so that after n2n is + * stopped the cleanup is easier. + * See https://github.com/zerotier/ZeroTierOne/issues/178#issuecomment-204599227 */ n2n_sock_t sn; n2n_route_t custom_route; @@ -2378,6 +2380,14 @@ static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_r custom_route.net_bitlen = 1; custom_route.gateway = route->gateway; + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx) < 0) + return(-1); + + /* ip route add 128.0.0.0/1 via n2n_gateway */ + custom_route.net_addr = 128; + custom_route.net_bitlen = 1; + custom_route.gateway = route->gateway; + if(routectl(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, &custom_route, eee->device.if_idx) < 0) return(-1); } else { From 8acac40ccd5991fe9c43f2ec78bb946b2cf767e5 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Thu, 11 Jun 2020 18:05:36 +0545 Subject: [PATCH 02/45] added portable endian code --- portable_endian.h | 125 ++++++++++++++++++++++++++++++++++++++++++++++ speck.c | 5 +- speck.h | 5 -- 3 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 portable_endian.h diff --git a/portable_endian.h b/portable_endian.h new file mode 100644 index 0000000..4db1ae7 --- /dev/null +++ b/portable_endian.h @@ -0,0 +1,125 @@ +// taken from +// https://gist.githubusercontent.com/PkmX/63dd23f28ba885be53a5/raw/c89538c921f08f8dbb5bc5957c871060c720605a/portable_endian.h +// as of June 11, 2020 + +// "License": Public Domain +// I, Mathias Panzenb�ck, place this file hereby into the public domain. Use it at your own risk for whatever you like. +// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to +// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it +// an example on how to get the endian conversion functions on different platforms. + +#ifndef PORTABLE_ENDIAN_H__ +#define PORTABLE_ENDIAN_H__ + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + +# include + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +# include + +# define be16toh(x) betoh16(x) +# define le16toh(x) letoh16(x) + +# define be32toh(x) betoh32(x) +# define le32toh(x) letoh32(x) + +# define be64toh(x) betoh64(x) +# define le64toh(x) letoh64(x) + +#elif defined(__WINDOWS__) + +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# if defined(_MSC_VER) +# include +# define htobe16(x) _byteswap_ushort(x) +# define htole16(x) (x) +# define be16toh(x) _byteswap_ushort(x) +# define le16toh(x) (x) + +# define htobe32(x) _byteswap_ulong(x) +# define htole32(x) (x) +# define be32toh(x) _byteswap_ulong(x) +# define le32toh(x) (x) + +# define htobe64(x) _byteswap_uint64(x) +# define htole64(x) (x) +# define be64toh(x) _byteswap_uint64(x) +# define le64toh(x) (x) + +# elif defined(__GNUC__) || defined(__clang__) + +# define htobe16(x) __builtin_bswap16(x) +# define htole16(x) (x) +# define be16toh(x) __builtin_bswap16(x) +# define le16toh(x) (x) + +# define htobe32(x) __builtin_bswap32(x) +# define htole32(x) (x) +# define be32toh(x) __builtin_bswap32(x) +# define le32toh(x) (x) + +# define htobe64(x) __builtin_bswap64(x) +# define htole64(x) (x) +# define be64toh(x) __builtin_bswap64(x) +# define le64toh(x) (x) +# else +# error platform not supported +# endif + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error platform not supported + +#endif + +#endif diff --git a/speck.c b/speck.c index 23aefd7..d9afca5 100644 --- a/speck.c +++ b/speck.c @@ -2,13 +2,12 @@ // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ -#include #include #include +#include "portable_endian.h" #include "speck.h" - #if defined (__AVX2__) // AVX support ---------------------------------------------------- @@ -682,6 +681,8 @@ int speck_test () { } /* +#include // for testing + int main (int argc, char* argv[]) { fprintf (stdout, "SPECK SELF TEST RESULT: %u\n", speck_test (0,NULL)); diff --git a/speck.h b/speck.h index ff92a5f..18a67b6 100644 --- a/speck.h +++ b/speck.h @@ -2,11 +2,6 @@ // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ -#ifdef __APPLE__ -#include -#define htole64(x) OSSwapHostToLittleInt64(x) -#endif - #define u32 uint32_t #define u64 uint64_t From 9e49a2cfc80a5878212063260de4840ab1b68fff Mon Sep 17 00:00:00 2001 From: Logan007 Date: Thu, 11 Jun 2020 18:41:33 +0545 Subject: [PATCH 03/45] added portable endian code --- portable_endian.h | 239 +++++++++++++++++++++++++++++++++------------- 1 file changed, 170 insertions(+), 69 deletions(-) diff --git a/portable_endian.h b/portable_endian.h index 4db1ae7..1b27491 100644 --- a/portable_endian.h +++ b/portable_endian.h @@ -1,9 +1,9 @@ // taken from -// https://gist.githubusercontent.com/PkmX/63dd23f28ba885be53a5/raw/c89538c921f08f8dbb5bc5957c871060c720605a/portable_endian.h +// https://raw.githubusercontent.com/pyca/bcrypt/master/src/_csrc/portable_endian.h // as of June 11, 2020 // "License": Public Domain -// I, Mathias Panzenb�ck, place this file hereby into the public domain. Use it at your own risk for whatever you like. +// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like. // In case there are jurisdictions that don't support putting things in the public domain you can also consider it to // be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it // an example on how to get the endian conversion functions on different platforms. @@ -13,112 +13,213 @@ #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) -# define __WINDOWS__ +# define __WINDOWS__ #endif #if defined(__linux__) || defined(__CYGWIN__) +/* Define necessary macros for the header to expose all fields. */ +# if !defined(_BSD_SOURCE) +# define _BSD_SOURCE +# endif +# if !defined(__USE_BSD) +# define __USE_BSD +# endif +# if !defined(_DEFAULT_SOURCE) +# define _DEFAULT_SOURCE +# endif +# include +# include +/* See http://linux.die.net/man/3/endian */ +# if defined(htobe16) && defined(htole16) && defined(be16toh) && defined(le16toh) && defined(htobe32) && defined(htole32) && defined(be32toh) && defined(htole32) && defined(htobe64) && defined(htole64) && defined(be64) && defined(le64) +/* Do nothing. The macros we need already exist. */ +# elif !defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 9))) +# include +# if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) -# include +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) (((uint64_t)htonl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htonl(((uint32_t)(x)))) << 32)) +# define htole64(x) (x) +# define be64toh(x) (((uint64_t)ntohl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)ntohl(((uint32_t)(x)))) << 32)) +# define le64toh(x) (x) +# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) +# define htobe16(x) (x) +# define htole16(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) +# define be16toh(x) (x) +# define le16toh(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) + +# define htobe32(x) (x) +# define htole32(x) (((uint32_t)htole16(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)htole16(((uint16_t)(x)))) << 16)) +# define be32toh(x) (x) +# define le32toh(x) (((uint32_t)le16toh(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)le16toh(((uint16_t)(x)))) << 16)) + +# define htobe64(x) (x) +# define htole64(x) (((uint64_t)htole32(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htole32(((uint32_t)(x)))) << 32)) +# define be64toh(x) (x) +# define le64toh(x) (((uint64_t)le32toh(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)le32toh(((uint32_t)(x)))) << 32)) +# else +# error Byte Order not supported or not defined. +# endif +# endif #elif defined(__APPLE__) -# include +# include -# define htobe16(x) OSSwapHostToBigInt16(x) -# define htole16(x) OSSwapHostToLittleInt16(x) -# define be16toh(x) OSSwapBigToHostInt16(x) -# define le16toh(x) OSSwapLittleToHostInt16(x) +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) -# define htobe32(x) OSSwapHostToBigInt32(x) -# define htole32(x) OSSwapHostToLittleInt32(x) -# define be32toh(x) OSSwapBigToHostInt32(x) -# define le32toh(x) OSSwapLittleToHostInt32(x) +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) -# define htobe64(x) OSSwapHostToBigInt64(x) -# define htole64(x) OSSwapHostToLittleInt64(x) -# define be64toh(x) OSSwapBigToHostInt64(x) -# define le64toh(x) OSSwapLittleToHostInt64(x) +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN #elif defined(__OpenBSD__) -# include +# include + +#elif defined(__HAIKU__) + +# include #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) -# include +# include -# define be16toh(x) betoh16(x) -# define le16toh(x) letoh16(x) +# if !defined(be16toh) + # define be16toh(x) betoh16(x) + # define le16toh(x) letoh16(x) +# endif -# define be32toh(x) betoh32(x) -# define le32toh(x) letoh32(x) +# if !defined(be32toh) + # define be32toh(x) betoh32(x) + # define le32toh(x) letoh32(x) +# endif -# define be64toh(x) betoh64(x) -# define le64toh(x) letoh64(x) +# if !defined(be64toh) + # define be64toh(x) betoh64(x) + # define le64toh(x) letoh64(x) +# endif #elif defined(__WINDOWS__) -# include +# if BYTE_ORDER == LITTLE_ENDIAN -# if BYTE_ORDER == LITTLE_ENDIAN +# define htobe16(x) _byteswap_ushort(x) +# define htole16(x) (x) +# define be16toh(x) _byteswap_ushort(x) +# define le16toh(x) (x) -# if defined(_MSC_VER) -# include -# define htobe16(x) _byteswap_ushort(x) -# define htole16(x) (x) -# define be16toh(x) _byteswap_ushort(x) -# define le16toh(x) (x) +# define htobe32(x) _byteswap_ulong(x) +# define htole32(x) (x) +# define be32toh(x) _byteswap_ulong(x) +# define le32toh(x) (x) -# define htobe32(x) _byteswap_ulong(x) -# define htole32(x) (x) -# define be32toh(x) _byteswap_ulong(x) -# define le32toh(x) (x) +# define htobe64(x) _byteswap_uint64(x) +# define be64toh(x) _byteswap_uint64(x) +# define htole64(x) (x) +# define le64toh(x) (x) -# define htobe64(x) _byteswap_uint64(x) -# define htole64(x) (x) -# define be64toh(x) _byteswap_uint64(x) -# define le64toh(x) (x) +# elif BYTE_ORDER == BIG_ENDIAN -# elif defined(__GNUC__) || defined(__clang__) + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) -# define htobe16(x) __builtin_bswap16(x) -# define htole16(x) (x) -# define be16toh(x) __builtin_bswap16(x) -# define le16toh(x) (x) +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) -# define htobe32(x) __builtin_bswap32(x) -# define htole32(x) (x) -# define be32toh(x) __builtin_bswap32(x) -# define le32toh(x) (x) +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) -# define htobe64(x) __builtin_bswap64(x) -# define htole64(x) (x) -# define be64toh(x) __builtin_bswap64(x) -# define le64toh(x) (x) -# else -# error platform not supported -# endif +# else -# else +# error byte order not supported -# error byte order not supported +# endif -# endif +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__sun) + +# include + +# define htobe16(x) BE_16(x) +# define htole16(x) LE_16(x) +# define be16toh(x) BE_16(x) +# define le16toh(x) LE_16(x) + +# define htobe32(x) BE_32(x) +# define htole32(x) LE_32(x) +# define be32toh(x) BE_32(x) +# define le32toh(x) LE_32(x) + +# define htobe64(x) BE_64(x) +# define htole64(x) LE_64(x) +# define be64toh(x) BE_64(x) +# define le64toh(x) LE_64(x) + +#elif defined _AIX /* AIX is always big endian */ +# define be64toh(x) (x) +# define be32toh(x) (x) +# define be16toh(x) (x) +# define le32toh(x) \ + ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) +# define le64toh(x) \ + ((((x) & 0x00000000000000ffL) << 56) | \ + (((x) & 0x000000000000ff00L) << 40) | \ + (((x) & 0x0000000000ff0000L) << 24) | \ + (((x) & 0x00000000ff000000L) << 8) | \ + (((x) & 0x000000ff00000000L) >> 8) | \ + (((x) & 0x0000ff0000000000L) >> 24) | \ + (((x) & 0x00ff000000000000L) >> 40) | \ + (((x) & 0xff00000000000000L) >> 56)) +# ifndef htobe64 +# define htobe64(x) be64toh(x) +# endif +# ifndef htobe32 +# define htobe32(x) be32toh(x) +# endif +# ifndef htobe16 +# define htobe16(x) be16toh(x) +# endif -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN #else -# error platform not supported +# error platform not supported #endif From 62097dee26b6167ae8080c79e6e3d637ff6cafdf Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Mon, 8 Jun 2020 15:34:35 +0200 Subject: [PATCH 04/45] CentOS compilation fixes --- random_numbers.c | 108 +++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/random_numbers.c b/random_numbers.c index 38d452e..3c2e410 100644 --- a/random_numbers.c +++ b/random_numbers.c @@ -1,7 +1,7 @@ /* The following code offers an alterate pseudo random number generator namely XORSHIFT128+ to use instead of C's rand(). Its performance is on par with C's rand(). - */ +*/ #include "random_numbers.h" @@ -10,46 +10,46 @@ /* The state must be seeded in a way that it is not all zero, choose some arbitrary defaults (in this case: taken from splitmix64) */ static struct rn_generator_state_t rn_current_state = { - .a = 0x9E3779B97F4A7C15, - .b = 0xBF58476D1CE4E5B9 }; + .a = 0x9E3779B97F4A7C15, + .b = 0xBF58476D1CE4E5B9 }; /* used for mixing the initializing seed */ static uint64_t splitmix64 (struct splitmix64_state_t *state) { - uint64_t result = state->s; + uint64_t result = state->s; - state->s = result + 0x9E3779B97F4A7C15; + state->s = result + 0x9E3779B97F4A7C15; - result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9; - result = (result ^ (result >> 27)) * 0x94D049BB133111EB; + result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9; + result = (result ^ (result >> 27)) * 0x94D049BB133111EB; - return result ^ (result >> 31); + return result ^ (result >> 31); } int n2n_srand (uint64_t seed) { + uint8_t i; + struct splitmix64_state_t smstate = {seed}; - struct splitmix64_state_t smstate = {seed}; + rn_current_state.a = 0; + rn_current_state.b = 0; - rn_current_state.a = 0; - rn_current_state.b = 0; + rn_current_state.a = splitmix64 (&smstate); + rn_current_state.b = splitmix64 (&smstate); - rn_current_state.a = splitmix64 (&smstate); - rn_current_state.b = splitmix64 (&smstate); + /* the following lines could be deleted as soon as it is formally prooved that + there is no seed leading to (a == b == 0). Until then, just to be safe: */ + if ( (rn_current_state.a == 0) && (rn_current_state.b == 0) ) { + rn_current_state.a = 0x9E3779B97F4A7C15; + rn_current_state.b = 0xBF58476D1CE4E5B9; + } - /* the following lines could be deleted as soon as it is formally prooved that - there is no seed leading to (a == b == 0). Until then, just to be safe: */ - if ( (rn_current_state.a == 0) && (rn_current_state.b == 0) ) { - rn_current_state.a = 0x9E3779B97F4A7C15; - rn_current_state.b = 0xBF58476D1CE4E5B9; - } + /* stabilize in unlikely case of weak state with only a few bits set */ + for(i = 0; i < 32; i++) + n2n_rand(); - /* stabilize in unlikely case of weak state with only a few bits set */ - for (uint8_t i = 0; i < 32; i++) - n2n_rand(); - - return 0; + return 0; } @@ -58,16 +58,16 @@ int n2n_srand (uint64_t seed) { and thus is considered public domain. */ uint64_t n2n_rand () { - uint64_t t = rn_current_state.a; - uint64_t const s = rn_current_state.b; + uint64_t t = rn_current_state.a; + uint64_t const s = rn_current_state.b; - rn_current_state.a = s; - t ^= t << 23; - t ^= t >> 17; - t ^= s ^ (s >> 26); - rn_current_state.b = t; + rn_current_state.a = s; + t ^= t << 23; + t ^= t >> 17; + t ^= s ^ (s >> 26); + rn_current_state.b = t; - return t + s; + return t + s; } @@ -80,37 +80,37 @@ uint64_t n2n_seed (void) { uint64_t ret = 0; #ifdef SYS_getrandom - syscall (SYS_getrandom, &seed, sizeof(seed), GRND_NONBLOCK); - ret += seed; + syscall (SYS_getrandom, &seed, sizeof(seed), GRND_NONBLOCK); + ret += seed; #endif -// __RDRND__ is set only if architecturual feature is set, e.g. compile with -march=native + // __RDRND__ is set only if architecturual feature is set, e.g. compile with -march=native #ifdef __RDRND__ - _rdrand64_step ((unsigned long long*)&seed); - ret += seed; + _rdrand64_step ((unsigned long long*)&seed); + ret += seed; #endif -// __RDSEED__ ist set only if architecturual feature is set, e.g. compile with -march=native + // __RDSEED__ ist set only if architecturual feature is set, e.g. compile with -march=native #ifdef __RDSEED__ - _rdseed64_step((unsigned long long*)&seed); - ret += seed; + _rdseed64_step((unsigned long long*)&seed); + ret += seed; #endif -/* The WIN32 code is still untested and thus commented -#ifdef WIN32 - HCRYPTPROV crypto_provider; - CryptAcquireContext (&crypto_provider, NULL, (LPCWSTR)L"Microsoft Base Cryptographic Provider v1.0", - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); - CryptGenRandom (crypto_provider, 8, &seed); - CryptReleaseContext (crypto_provider, 0); - ret += seed; -#endif */ + /* The WIN32 code is still untested and thus commented + #ifdef WIN32 + HCRYPTPROV crypto_provider; + CryptAcquireContext (&crypto_provider, NULL, (LPCWSTR)L"Microsoft Base Cryptographic Provider v1.0", + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); + CryptGenRandom (crypto_provider, 8, &seed); + CryptReleaseContext (crypto_provider, 0); + ret += seed; + #endif */ - seed = time(NULL); /* UTC in seconds */ - ret += seed; + seed = time(NULL); /* UTC in seconds */ + ret += seed; - seed = clock() * 8996146197; /* clock() = ticks since program start */ - ret += seed; + seed = clock() * 8996146197; /* clock() = ticks since program start */ + ret += seed; - return ret; + return ret; } From 72c058f9dd9fcfced69eb4a1d68989d24a63ec1d Mon Sep 17 00:00:00 2001 From: Logan007 Date: Thu, 11 Jun 2020 18:05:36 +0545 Subject: [PATCH 05/45] added portable endian code --- portable_endian.h | 125 ++++++++++++++++++++++++++++++++++++++++++++++ speck.c | 5 +- speck.h | 5 -- 3 files changed, 128 insertions(+), 7 deletions(-) create mode 100644 portable_endian.h diff --git a/portable_endian.h b/portable_endian.h new file mode 100644 index 0000000..4db1ae7 --- /dev/null +++ b/portable_endian.h @@ -0,0 +1,125 @@ +// taken from +// https://gist.githubusercontent.com/PkmX/63dd23f28ba885be53a5/raw/c89538c921f08f8dbb5bc5957c871060c720605a/portable_endian.h +// as of June 11, 2020 + +// "License": Public Domain +// I, Mathias Panzenb�ck, place this file hereby into the public domain. Use it at your own risk for whatever you like. +// In case there are jurisdictions that don't support putting things in the public domain you can also consider it to +// be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it +// an example on how to get the endian conversion functions on different platforms. + +#ifndef PORTABLE_ENDIAN_H__ +#define PORTABLE_ENDIAN_H__ + +#if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) + +# define __WINDOWS__ + +#endif + +#if defined(__linux__) || defined(__CYGWIN__) + +# include + +#elif defined(__APPLE__) + +# include + +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) + +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) + +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__OpenBSD__) + +# include + +#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) + +# include + +# define be16toh(x) betoh16(x) +# define le16toh(x) letoh16(x) + +# define be32toh(x) betoh32(x) +# define le32toh(x) letoh32(x) + +# define be64toh(x) betoh64(x) +# define le64toh(x) letoh64(x) + +#elif defined(__WINDOWS__) + +# include + +# if BYTE_ORDER == LITTLE_ENDIAN + +# if defined(_MSC_VER) +# include +# define htobe16(x) _byteswap_ushort(x) +# define htole16(x) (x) +# define be16toh(x) _byteswap_ushort(x) +# define le16toh(x) (x) + +# define htobe32(x) _byteswap_ulong(x) +# define htole32(x) (x) +# define be32toh(x) _byteswap_ulong(x) +# define le32toh(x) (x) + +# define htobe64(x) _byteswap_uint64(x) +# define htole64(x) (x) +# define be64toh(x) _byteswap_uint64(x) +# define le64toh(x) (x) + +# elif defined(__GNUC__) || defined(__clang__) + +# define htobe16(x) __builtin_bswap16(x) +# define htole16(x) (x) +# define be16toh(x) __builtin_bswap16(x) +# define le16toh(x) (x) + +# define htobe32(x) __builtin_bswap32(x) +# define htole32(x) (x) +# define be32toh(x) __builtin_bswap32(x) +# define le32toh(x) (x) + +# define htobe64(x) __builtin_bswap64(x) +# define htole64(x) (x) +# define be64toh(x) __builtin_bswap64(x) +# define le64toh(x) (x) +# else +# error platform not supported +# endif + +# else + +# error byte order not supported + +# endif + +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#else + +# error platform not supported + +#endif + +#endif diff --git a/speck.c b/speck.c index 23aefd7..d9afca5 100644 --- a/speck.c +++ b/speck.c @@ -2,13 +2,12 @@ // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ -#include #include #include +#include "portable_endian.h" #include "speck.h" - #if defined (__AVX2__) // AVX support ---------------------------------------------------- @@ -682,6 +681,8 @@ int speck_test () { } /* +#include // for testing + int main (int argc, char* argv[]) { fprintf (stdout, "SPECK SELF TEST RESULT: %u\n", speck_test (0,NULL)); diff --git a/speck.h b/speck.h index ff92a5f..18a67b6 100644 --- a/speck.h +++ b/speck.h @@ -2,11 +2,6 @@ // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ -#ifdef __APPLE__ -#include -#define htole64(x) OSSwapHostToLittleInt64(x) -#endif - #define u32 uint32_t #define u64 uint64_t From 2e60bccddbac4bae6d984214f75bf59985fba9a6 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Thu, 11 Jun 2020 18:41:33 +0545 Subject: [PATCH 06/45] added portable endian code --- portable_endian.h | 239 +++++++++++++++++++++++++++++++++------------- 1 file changed, 170 insertions(+), 69 deletions(-) diff --git a/portable_endian.h b/portable_endian.h index 4db1ae7..1b27491 100644 --- a/portable_endian.h +++ b/portable_endian.h @@ -1,9 +1,9 @@ // taken from -// https://gist.githubusercontent.com/PkmX/63dd23f28ba885be53a5/raw/c89538c921f08f8dbb5bc5957c871060c720605a/portable_endian.h +// https://raw.githubusercontent.com/pyca/bcrypt/master/src/_csrc/portable_endian.h // as of June 11, 2020 // "License": Public Domain -// I, Mathias Panzenb�ck, place this file hereby into the public domain. Use it at your own risk for whatever you like. +// I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like. // In case there are jurisdictions that don't support putting things in the public domain you can also consider it to // be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it // an example on how to get the endian conversion functions on different platforms. @@ -13,112 +13,213 @@ #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) -# define __WINDOWS__ +# define __WINDOWS__ #endif #if defined(__linux__) || defined(__CYGWIN__) +/* Define necessary macros for the header to expose all fields. */ +# if !defined(_BSD_SOURCE) +# define _BSD_SOURCE +# endif +# if !defined(__USE_BSD) +# define __USE_BSD +# endif +# if !defined(_DEFAULT_SOURCE) +# define _DEFAULT_SOURCE +# endif +# include +# include +/* See http://linux.die.net/man/3/endian */ +# if defined(htobe16) && defined(htole16) && defined(be16toh) && defined(le16toh) && defined(htobe32) && defined(htole32) && defined(be32toh) && defined(htole32) && defined(htobe64) && defined(htole64) && defined(be64) && defined(le64) +/* Do nothing. The macros we need already exist. */ +# elif !defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 9))) +# include +# if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN) +# define htobe16(x) htons(x) +# define htole16(x) (x) +# define be16toh(x) ntohs(x) +# define le16toh(x) (x) -# include +# define htobe32(x) htonl(x) +# define htole32(x) (x) +# define be32toh(x) ntohl(x) +# define le32toh(x) (x) + +# define htobe64(x) (((uint64_t)htonl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htonl(((uint32_t)(x)))) << 32)) +# define htole64(x) (x) +# define be64toh(x) (((uint64_t)ntohl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)ntohl(((uint32_t)(x)))) << 32)) +# define le64toh(x) (x) +# elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN) +# define htobe16(x) (x) +# define htole16(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) +# define be16toh(x) (x) +# define le16toh(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8))) + +# define htobe32(x) (x) +# define htole32(x) (((uint32_t)htole16(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)htole16(((uint16_t)(x)))) << 16)) +# define be32toh(x) (x) +# define le32toh(x) (((uint32_t)le16toh(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)le16toh(((uint16_t)(x)))) << 16)) + +# define htobe64(x) (x) +# define htole64(x) (((uint64_t)htole32(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htole32(((uint32_t)(x)))) << 32)) +# define be64toh(x) (x) +# define le64toh(x) (((uint64_t)le32toh(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)le32toh(((uint32_t)(x)))) << 32)) +# else +# error Byte Order not supported or not defined. +# endif +# endif #elif defined(__APPLE__) -# include +# include -# define htobe16(x) OSSwapHostToBigInt16(x) -# define htole16(x) OSSwapHostToLittleInt16(x) -# define be16toh(x) OSSwapBigToHostInt16(x) -# define le16toh(x) OSSwapLittleToHostInt16(x) +# define htobe16(x) OSSwapHostToBigInt16(x) +# define htole16(x) OSSwapHostToLittleInt16(x) +# define be16toh(x) OSSwapBigToHostInt16(x) +# define le16toh(x) OSSwapLittleToHostInt16(x) -# define htobe32(x) OSSwapHostToBigInt32(x) -# define htole32(x) OSSwapHostToLittleInt32(x) -# define be32toh(x) OSSwapBigToHostInt32(x) -# define le32toh(x) OSSwapLittleToHostInt32(x) +# define htobe32(x) OSSwapHostToBigInt32(x) +# define htole32(x) OSSwapHostToLittleInt32(x) +# define be32toh(x) OSSwapBigToHostInt32(x) +# define le32toh(x) OSSwapLittleToHostInt32(x) -# define htobe64(x) OSSwapHostToBigInt64(x) -# define htole64(x) OSSwapHostToLittleInt64(x) -# define be64toh(x) OSSwapBigToHostInt64(x) -# define le64toh(x) OSSwapLittleToHostInt64(x) +# define htobe64(x) OSSwapHostToBigInt64(x) +# define htole64(x) OSSwapHostToLittleInt64(x) +# define be64toh(x) OSSwapBigToHostInt64(x) +# define le64toh(x) OSSwapLittleToHostInt64(x) -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN #elif defined(__OpenBSD__) -# include +# include + +#elif defined(__HAIKU__) + +# include #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) -# include +# include -# define be16toh(x) betoh16(x) -# define le16toh(x) letoh16(x) +# if !defined(be16toh) + # define be16toh(x) betoh16(x) + # define le16toh(x) letoh16(x) +# endif -# define be32toh(x) betoh32(x) -# define le32toh(x) letoh32(x) +# if !defined(be32toh) + # define be32toh(x) betoh32(x) + # define le32toh(x) letoh32(x) +# endif -# define be64toh(x) betoh64(x) -# define le64toh(x) letoh64(x) +# if !defined(be64toh) + # define be64toh(x) betoh64(x) + # define le64toh(x) letoh64(x) +# endif #elif defined(__WINDOWS__) -# include +# if BYTE_ORDER == LITTLE_ENDIAN -# if BYTE_ORDER == LITTLE_ENDIAN +# define htobe16(x) _byteswap_ushort(x) +# define htole16(x) (x) +# define be16toh(x) _byteswap_ushort(x) +# define le16toh(x) (x) -# if defined(_MSC_VER) -# include -# define htobe16(x) _byteswap_ushort(x) -# define htole16(x) (x) -# define be16toh(x) _byteswap_ushort(x) -# define le16toh(x) (x) +# define htobe32(x) _byteswap_ulong(x) +# define htole32(x) (x) +# define be32toh(x) _byteswap_ulong(x) +# define le32toh(x) (x) -# define htobe32(x) _byteswap_ulong(x) -# define htole32(x) (x) -# define be32toh(x) _byteswap_ulong(x) -# define le32toh(x) (x) +# define htobe64(x) _byteswap_uint64(x) +# define be64toh(x) _byteswap_uint64(x) +# define htole64(x) (x) +# define le64toh(x) (x) -# define htobe64(x) _byteswap_uint64(x) -# define htole64(x) (x) -# define be64toh(x) _byteswap_uint64(x) -# define le64toh(x) (x) +# elif BYTE_ORDER == BIG_ENDIAN -# elif defined(__GNUC__) || defined(__clang__) + /* that would be xbox 360 */ +# define htobe16(x) (x) +# define htole16(x) __builtin_bswap16(x) +# define be16toh(x) (x) +# define le16toh(x) __builtin_bswap16(x) -# define htobe16(x) __builtin_bswap16(x) -# define htole16(x) (x) -# define be16toh(x) __builtin_bswap16(x) -# define le16toh(x) (x) +# define htobe32(x) (x) +# define htole32(x) __builtin_bswap32(x) +# define be32toh(x) (x) +# define le32toh(x) __builtin_bswap32(x) -# define htobe32(x) __builtin_bswap32(x) -# define htole32(x) (x) -# define be32toh(x) __builtin_bswap32(x) -# define le32toh(x) (x) +# define htobe64(x) (x) +# define htole64(x) __builtin_bswap64(x) +# define be64toh(x) (x) +# define le64toh(x) __builtin_bswap64(x) -# define htobe64(x) __builtin_bswap64(x) -# define htole64(x) (x) -# define be64toh(x) __builtin_bswap64(x) -# define le64toh(x) (x) -# else -# error platform not supported -# endif +# else -# else +# error byte order not supported -# error byte order not supported +# endif -# endif +# define __BYTE_ORDER BYTE_ORDER +# define __BIG_ENDIAN BIG_ENDIAN +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# define __PDP_ENDIAN PDP_ENDIAN + +#elif defined(__sun) + +# include + +# define htobe16(x) BE_16(x) +# define htole16(x) LE_16(x) +# define be16toh(x) BE_16(x) +# define le16toh(x) LE_16(x) + +# define htobe32(x) BE_32(x) +# define htole32(x) LE_32(x) +# define be32toh(x) BE_32(x) +# define le32toh(x) LE_32(x) + +# define htobe64(x) BE_64(x) +# define htole64(x) LE_64(x) +# define be64toh(x) BE_64(x) +# define le64toh(x) LE_64(x) + +#elif defined _AIX /* AIX is always big endian */ +# define be64toh(x) (x) +# define be32toh(x) (x) +# define be16toh(x) (x) +# define le32toh(x) \ + ((((x) & 0xff) << 24) | \ + (((x) & 0xff00) << 8) | \ + (((x) & 0xff0000) >> 8) | \ + (((x) & 0xff000000) >> 24)) +# define le64toh(x) \ + ((((x) & 0x00000000000000ffL) << 56) | \ + (((x) & 0x000000000000ff00L) << 40) | \ + (((x) & 0x0000000000ff0000L) << 24) | \ + (((x) & 0x00000000ff000000L) << 8) | \ + (((x) & 0x000000ff00000000L) >> 8) | \ + (((x) & 0x0000ff0000000000L) >> 24) | \ + (((x) & 0x00ff000000000000L) >> 40) | \ + (((x) & 0xff00000000000000L) >> 56)) +# ifndef htobe64 +# define htobe64(x) be64toh(x) +# endif +# ifndef htobe32 +# define htobe32(x) be32toh(x) +# endif +# ifndef htobe16 +# define htobe16(x) be16toh(x) +# endif -# define __BYTE_ORDER BYTE_ORDER -# define __BIG_ENDIAN BIG_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN -# define __PDP_ENDIAN PDP_ENDIAN #else -# error platform not supported +# error platform not supported #endif From 0393165570b4ee23cbd285d9c459949ee2b2cebe Mon Sep 17 00:00:00 2001 From: Logan007 Date: Sat, 13 Jun 2020 19:25:39 +0545 Subject: [PATCH 07/45] polished speck --- CMakeLists.txt | 1 + Makefile.in | 1 + edge.c | 8 ++- pearson.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ pearson.h | 1 + transform_speck.c | 12 ++-- 6 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 pearson.c create mode 100644 pearson.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b5fd37b..a1eb4c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ add_library(n2n n2n.c transform_tf.c transform_aes.c random_numbers.c + pearson.c tuntap_freebsd.c tuntap_netbsd.c tuntap_linux.c diff --git a/Makefile.in b/Makefile.in index b231aac..5b5a19d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -51,6 +51,7 @@ N2N_LIB=libn2n.a N2N_OBJS=n2n.o wire.o minilzo.o twofish.o speck.o \ edge_utils.o sn_utils.o \ transform_null.o transform_tf.o transform_aes.o transform_cc20.o transform_speck.o \ + pearson.o \ tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o random_numbers.o \ tuntap_osx.o LIBS_EDGE+=$(LIBS_EDGE_OPT) diff --git a/edge.c b/edge.c index 5b7b84a..8babd45 100644 --- a/edge.c +++ b/edge.c @@ -197,8 +197,7 @@ static void help() { #ifdef HAVE_OPENSSL_1_1 printf("-A4 | Use ChaCha20 for payload encryption. Requires a key.\n"); #endif -// COMING SOON, not yet implemented in setPayloadEncryption(...) -// printf("-A5 | Use Speck for payload encryption. Requires a key.\n"); + printf("-A5 | Use Speck for payload encryption. Requires a key.\n"); printf("-z1 or -z | Enable lzo1x compression for outgoing data packets\n"); #ifdef N2N_HAVE_ZSTD printf("-z2 | Enable zstd compression for outgoing data packets\n"); @@ -283,6 +282,11 @@ static void setPayloadEncryption( n2n_edge_conf_t *conf, int cipher) { break; } #endif + case 5: + { + conf->transop_id = N2N_TRANSFORM_ID_SPECK; + break; + } default: { conf->transop_id = N2N_TRANSFORM_ID_INVAL; diff --git a/pearson.c b/pearson.c new file mode 100644 index 0000000..2ec74bd --- /dev/null +++ b/pearson.c @@ -0,0 +1,137 @@ +#include +#include + +#include "pearson.h" + + +// table as in original paper "Fast Hashing of Variable-Length Text Strings" by Peter K. Pearson +// as published in The Communications of the ACM Vol.33, No. 6 (June 1990), pp. 677-680. +static const uint8_t t[256] ={ + 0x01, 0x57, 0x31, 0x0c, 0xb0, 0xb2, 0x66, 0xa6, 0x79, 0xc1, 0x06, 0x54, 0xf9, 0xe6, 0x2c, 0xa3, + 0x0e, 0xc5, 0xd5, 0xb5, 0xa1, 0x55, 0xda, 0x50, 0x40, 0xef, 0x18, 0xe2, 0xec, 0x8e, 0x26, 0xc8, + 0x6e, 0xb1, 0x68, 0x67, 0x8d, 0xfd, 0xff, 0x32, 0x4d, 0x65, 0x51, 0x12, 0x2d, 0x60, 0x1f, 0xde, + 0x19, 0x6b, 0xbe, 0x46, 0x56, 0xed, 0xf0, 0x22, 0x48, 0xf2, 0x14, 0xd6, 0xf4, 0xe3, 0x95, 0xeb, + 0x61, 0xea, 0x39, 0x16, 0x3c, 0xfa, 0x52, 0xaf, 0xd0, 0x05, 0x7f, 0xc7, 0x6f, 0x3e, 0x87, 0xf8, + 0xae, 0xa9, 0xd3, 0x3a, 0x42, 0x9a, 0x6a, 0xc3, 0xf5, 0xab, 0x11, 0xbb, 0xb6, 0xb3, 0x00, 0xf3, + 0x84, 0x38, 0x94, 0x4b, 0x80, 0x85, 0x9e, 0x64, 0x82, 0x7e, 0x5b, 0x0d, 0x99, 0xf6, 0xd8, 0xdb, + 0x77, 0x44, 0xdf, 0x4e, 0x53, 0x58, 0xc9, 0x63, 0x7a, 0x0b, 0x5c, 0x20, 0x88, 0x72, 0x34, 0x0a, + 0x8a, 0x1e, 0x30, 0xb7, 0x9c, 0x23, 0x3d, 0x1a, 0x8f, 0x4a, 0xfb, 0x5e, 0x81, 0xa2, 0x3f, 0x98, + 0xaa, 0x07, 0x73, 0xa7, 0xf1, 0xce, 0x03, 0x96, 0x37, 0x3b, 0x97, 0xdc, 0x5a, 0x35, 0x17, 0x83, + 0x7d, 0xad, 0x0f, 0xee, 0x4f, 0x5f, 0x59, 0x10, 0x69, 0x89, 0xe1, 0xe0, 0xd9, 0xa0, 0x25, 0x7b, + 0x76, 0x49, 0x02, 0x9d, 0x2e, 0x74, 0x09, 0x91, 0x86, 0xe4, 0xcf, 0xd4, 0xca, 0xd7, 0x45, 0xe5, + 0x1b, 0xbc, 0x43, 0x7c, 0xa8, 0xfc, 0x2a, 0x04, 0x1d, 0x6c, 0x15, 0xf7, 0x13, 0xcd, 0x27, 0xcb, + 0xe9, 0x28, 0xba, 0x93, 0xc6, 0xc0, 0x9b, 0x21, 0xa4, 0xbf, 0x62, 0xcc, 0xa5, 0xb4, 0x75, 0x4c, + 0x8c, 0x24, 0xd2, 0xac, 0x29, 0x36, 0x9f, 0x08, 0xb9, 0xe8, 0x71, 0xc4, 0xe7, 0x2f, 0x92, 0x78, + 0x33, 0x41, 0x1c, 0x90, 0xfe, 0xdd, 0x5d, 0xbd, 0xc2, 0x8b, 0x70, 0x2b, 0x47, 0x6d, 0xb8, 0xd1 }; + +/* +// alternative table as used in RFC 3074 and NOT as in original paper +static const uint8_t t[256] ={ + 0xfb, 0xaf, 0x77, 0xd7, 0x51, 0x0e, 0x4f, 0xbf, 0x67, 0x31, 0xb5, 0x8f, 0xba, 0x9d, 0x00, 0xe8, + 0x1f, 0x20, 0x37, 0x3c, 0x98, 0x3a, 0x11, 0xed, 0xae, 0x46, 0xa0, 0x90, 0xdc, 0x5a, 0x39, 0xdf, + 0x3b, 0x03, 0x12, 0x8c, 0x6f, 0xa6, 0xcb, 0xc4, 0x86, 0xf3, 0x7c, 0x5f, 0xde, 0xb3, 0xc5, 0x41, + 0xb4, 0x30, 0x24, 0x0f, 0x6b, 0x2e, 0xe9, 0x82, 0xa5, 0x1e, 0x7b, 0xa1, 0xd1, 0x17, 0x61, 0x10, + 0x28, 0x5b, 0xdb, 0x3d, 0x64, 0x0a, 0xd2, 0x6d, 0xfa, 0x7f, 0x16, 0x8a, 0x1d, 0x6c, 0xf4, 0x43, + 0xcf, 0x09, 0xb2, 0xcc, 0x4a, 0x62, 0x7e, 0xf9, 0xa7, 0x74, 0x22, 0x4d, 0xc1, 0xc8, 0x79, 0x05, + 0x14, 0x71, 0x47, 0x23, 0x80, 0x0d, 0xb6, 0x5e, 0x19, 0xe2, 0xe3, 0xc7, 0x4b, 0x1b, 0x29, 0xf5, + 0xe6, 0xe0, 0x2b, 0xe1, 0xb1, 0x1a, 0x9b, 0x96, 0xd4, 0x8e, 0xda, 0x73, 0xf1, 0x49, 0x58, 0x69, + 0x27, 0x72, 0x3e, 0xff, 0xc0, 0xc9, 0x91, 0xd6, 0xa8, 0x9e, 0xdd, 0x94, 0x9a, 0x7a, 0x0c, 0x54, + 0x52, 0xa3, 0x2c, 0x8b, 0xe4, 0xec, 0xcd, 0xf2, 0xd9, 0x0b, 0xbb, 0x92, 0x9f, 0x40, 0x56, 0xef, + 0xc3, 0x2a, 0x6a, 0xc6, 0x76, 0x70, 0xb8, 0xac, 0x57, 0x02, 0xad, 0x75, 0xb0, 0xe5, 0xf7, 0xfd, + 0x89, 0xb9, 0x63, 0xa4, 0x66, 0x93, 0x2d, 0x42, 0xe7, 0x34, 0x8d, 0xd3, 0xc2, 0xce, 0xf6, 0xee, + 0x38, 0x6e, 0x4e, 0xf8, 0x3f, 0xf0, 0xbd, 0x5d, 0x5c, 0x33, 0x35, 0xb7, 0x13, 0xab, 0x48, 0x32, + 0x21, 0x68, 0x65, 0x45, 0x08, 0xfc, 0x53, 0x78, 0x4c, 0x87, 0x55, 0x36, 0xca, 0x7d, 0xbc, 0xd5, + 0x60, 0xeb, 0x88, 0xd0, 0xa2, 0x81, 0xbe, 0x84, 0x9c, 0x26, 0x2f, 0x01, 0x07, 0xfe, 0x18, 0x04, + 0xd8, 0x83, 0x59, 0x15, 0x1c, 0x85, 0x25, 0x99, 0x95, 0x50, 0xaa, 0x44, 0x06, 0xa9, 0xea, 0x97 }; */ + + +#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) + + +void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len) { + + /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) + * works faster on well pipelined CPUs than loading the 64-bit value from memory. + * however, there is one advantage to loading from memory: as we also store back to + * memory at the end, we do not need to care about endianess! */ + uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + + uint64_t upper_hash_mask = *(uint64_t*)&upper; + uint64_t lower_hash_mask = *(uint64_t*)&lower; + uint64_t high_upper_hash_mask = upper_hash_mask + 0x1010101010101010; + uint64_t high_lower_hash_mask = lower_hash_mask + 0x1010101010101010; + + uint64_t upper_hash = 0; + uint64_t lower_hash = 0; + uint64_t high_upper_hash = 0; + uint64_t high_lower_hash = 0; + + for (size_t i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint64_t c = (uint8_t)in[i]; + c |= c << 8; + c |= c << 16; + c |= c << 32; + upper_hash ^= c ^ upper_hash_mask; + lower_hash ^= c ^ lower_hash_mask; + high_upper_hash ^= c ^ high_upper_hash_mask; + high_lower_hash ^= c ^ high_lower_hash_mask; + + // table lookup + uint8_t x; + uint64_t h = 0; + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + upper_hash = h; + + h = 0; + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + lower_hash = h; + + h = 0; + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + high_upper_hash = h; + + h = 0; + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + high_lower_hash = h; + } + // store output + uint64_t *o; + o = (uint64_t*)&out[0]; + *o = high_upper_hash; + o = (uint64_t*)&out[8]; + *o = high_lower_hash; + o = (uint64_t*)&out[16]; + *o = upper_hash; + o = (uint64_t*)&out[24]; + *o = lower_hash; +} diff --git a/pearson.h b/pearson.h new file mode 100644 index 0000000..43d1f98 --- /dev/null +++ b/pearson.h @@ -0,0 +1 @@ +void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); diff --git a/transform_speck.c b/transform_speck.c index 093475e..9ae5cd7 100644 --- a/transform_speck.c +++ b/transform_speck.c @@ -20,6 +20,7 @@ #include "n2n_transforms.h" #include "speck.h" #include "random_numbers.h" +#include "pearson.h" #define N2N_SPECK_TRANSFORM_VERSION 1 /* version of the transform encoding */ #define N2N_SPECK_IVEC_SIZE 16 @@ -175,13 +176,10 @@ static int setup_speck_key(transop_speck_t *priv, const uint8_t *key, ssize_t ke /* Clear out any old possibly longer key matter. */ memset(&(priv->ctx), 0, sizeof(speck_context_t) ); - /* TODO: The input key always gets hashed to make a more unpredictable and more complete use of the key space */ - // REVISIT: Hash the key to keymat (formerly used: SHA) - // SHA256(key, key_size, key_mat_buf) - // memcpy (priv->key, key_mat_buf, SHA256_DIGEST_LENGTH); - // ADD: Pearson Hashing - // FOR NOW: USE KEY ITSELF - memcpy (key_mat_buf, key, ((key_size>32)?32:key_size) ); + /* the input key always gets hashed to make a more unpredictable and more complete use of the key space */ + pearson_hash_256 (key_mat_buf, key, key_size); + + /* expand the key material to the context (= round keys) */ speck_expand_key (key_mat_buf, &(priv->ctx)); traceEvent(TRACE_DEBUG, "Speck key setup completed\n"); From 6774920ed0529c8e9eaa5720dbb3ef3829469b34 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 15 Jun 2020 12:53:37 +0545 Subject: [PATCH 08/45] drafted header encryption --- header_encryption.c | 104 +++++++++++++++++++++++++++++++++++++ speck.c | 123 +++++++++++++++++++++++++++++++++++++++----- speck.h | 7 +++ 3 files changed, 221 insertions(+), 13 deletions(-) create mode 100644 header_encryption.c diff --git a/header_encryption.c b/header_encryption.c new file mode 100644 index 0000000..e263cfc --- /dev/null +++ b/header_encryption.c @@ -0,0 +1,104 @@ +#include +#include + +// #include "n2n_wire.h" // n2n_community_t +#include "n2n.h" +#include "speck.h" +#include "portable_endian.h" + + +uint32_t decryt_packet_header (uint8_t packet[], uint8_t packet_len, + char * community_name, speck_ctx * ctx) { + + // assemble IV + // the last four are ASCII "n2n!" and do not get overwritten + uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6E, 0x32, 0x6E, 0x21 }; + // the first 96 bits of the packet are used padded with ASCII "n2n!" + // to full 128 bit IV + memcopy (iv, packet, 12); + + // alternatively, consider: pearson_hash_128 (iv, packet, 12) + + // try community name as possible key and check for magic bytes + uint32_t magic = 0x6E326E00; // ="n2n_" + uint32_t test_magic; + // check for magic bytes and resonable value in header len field + speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, ctx); + test_magic = be32toh (test_magic); + if ( ((test_magic << 8) == magic) + && ((test_magic >> 24) <= packet_len) // (test_masgic >> 24) is header_len + ) { + speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, ctx); + // restore original packet order + memcpy (&packet[0], &packet[16], 4); + memcpy (&packet[4], community_name, N2N_COMMUNITY_SIZE); + return (1); // successful + } else + return (0); // unsuccessful +} + + +int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community *communities) { + + if (packet_len < 20) + return (-1); + + // first, check if header is unenrypted to put it into the fast-lane then + + // the following check is around 99.99962 percent reliable + // it heavily relies on the structure of packet's common part + // changes to wire.c:encode/decode_common need to go together with this code + if ( (packet[19] == (uint8_t)0x00) // null terminated community name + && (packet[00] == N2N_PKT_VERSION) // correct packet version +// && (packet[01] <= N2N_DEFAULT_TTL) // reasonable TTL -- might interfere with hole-punching-related or cli passed higher values ?! + && ((be16toh (*(uint16_t*)&(packet[02])) & N2N_FLAGS_TYPE_MASK ) <= MSG_TYPE_MAX_TYPE ) // message type + && ( be16toh (*(uint16_t*)&(packet[02])) < N2N_FLAGS_OPTIONS) // flags + ) { + + // most probably unencrypted + return (1); + + } else { + + // most probably encrypted + // cycle through the known communities (as keys) to eventually decrypt + int32_t ret; + struct sn_community *c, *tmp; + HASH_ITER (hh, communities, c, tmp) { + // check if this is an encrypted community + if ( ret = decrypt_packet_header (packet, packet_len, c->community, c-> ctx) ) { + // no upgrade from unencrypted to encrypted + if (c->header_encryption == 1) + return (-2); + // set to 'encrypted' + c->header_encryption = 2; + // no need to test any further + return (2); + } + } + // no match + return (-3); + } +} + + +int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, speck_ctx * ctx) { + + if (header_len < 20) + return (-1); + + memcpy (&packet[16], &packet[00], 4); + + uint8_t iv[16]; + ((uint64_t*)iv)[0] = n2n_rand (); + ((uint64_t*)iv)[1] = n2n_rand (); + + const uint32_t magic = 0x006E326E; + ((uint32_t*)iv)[3] = htobe32 (magic); + + iv[12] = header_len; + + speck_he (&packet[12], &packet[12], header_len - 12, iv, ctx); +} diff --git a/speck.c b/speck.c index d9afca5..74a1426 100644 --- a/speck.c +++ b/speck.c @@ -1,4 +1,4 @@ -// cipher SPECK -- 128 bit block size -- 256 bit key size +// cipher SPECK -- 128 bit block size -- 256 bit key size -- CTR mode // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ @@ -565,9 +565,9 @@ int speck_expand_key (const unsigned char *k, speck_context_t *ctx) { #else // plain C ---------------------------------------------------------------- -#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) -#define ROL64(x,r) (((x)<<(r))|((x)>>(64-(r)))) -#define R(x,y,k) (x=ROR64(x,8), x+=y, x^=k, y=ROL64(y,3), y^=x) +#define ROR(x,r) (((x)>>(r))|((x)<<(64-(r)))) +#define ROL(x,r) (((x)<<(r))|((x)>>(64-(r)))) +#define R(x,y,k) (x=ROR(x,8), x+=y, x^=k, y=ROL(y,3), y^=x) static int speck_encrypt (u64 *u, u64 *v, speck_context_t *ctx) { @@ -642,6 +642,85 @@ int speck_expand_key (const unsigned char *k, speck_context_t *ctx) { #endif // AVX, SSE, NEON, plain C ------------------------------------------------ +// cipher SPECK -- 128 bit block size -- 128 bit key size -- CTR mode +// used for header encryption, thus the prefix 'he_' +// for now: just plain C -- AVX, SSE, NEON might follow + +#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) +#define ROL64(x,r) (((x)<<(r))|((x)>>(64-(r)))) +#define R64(x,y,k) (x=ROR64(x,8), x+=y, x^=k, y=ROL64(y,3), y^=x) + + +static int speck_encrypt_he (u64 *u, u64 *v, speck_context_t *ctx) { + + u64 i, x=*u, y=*v; + + for (i = 0; i < 32; i++) + R64 (x, y, ctx->key[i]); + + *u = x; *v = y; + + return 0; +} + + +int speck_he (unsigned char *out, const unsigned char *in, unsigned long long inlen, + const unsigned char *n, speck_context_t *ctx) { + + u64 i, nonce[2], x, y, t; + unsigned char *block = malloc(16); + + if (!inlen) { + free (block); + return 0; + } + nonce[0] = htole64 ( ((u64*)n)[0] ); + nonce[1] = htole64 ( ((u64*)n)[1] ); + + t = 0; + while (inlen >= 16) { + x = nonce[1]; y = nonce[0]; nonce[0]++; + speck_encrypt_he (&x, &y, ctx); + ((u64 *)out)[1+t] = htole64 (x ^ ((u64 *)in)[1+t]); + ((u64 *)out)[0+t] = htole64 (y ^ ((u64 *)in)[0+t]); + t += 2; + inlen -= 16; + } + + if (inlen > 0) { + x = nonce[1]; y = nonce[0]; + speck_encrypt_he (&x, &y, ctx); + ((u64 *)block)[1] = htole64 (x); ((u64 *)block)[0] = htole64 (y); + for (i = 0; i < inlen; i++) + out[i+8*t] = block[i] ^ in[i+8*t]; + } + + free(block); + return 0; +} + + +int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx) { + + u64 A, B; + u64 i; + + A = htole64 ( ((u64 *)k)[0] ); + B = htole64 ( ((u64 *)k)[1] ); + + for (i = 0; i < 32; i ++) { + ctx->key[i] = A; + R64 ( B, A, i); + } + return 1; +} + + +// code for testing -- to be removed when finished +/* +#include // for testing +#include + int speck_test () { uint8_t key[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -649,16 +728,23 @@ int speck_test () { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; - uint8_t iv[16] = { 0x70, 0x6f, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65 }; + uint8_t xv[16] = { 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x74, + 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c }; + + uint8_t pt[16] = { 0x00 }; // expected outcome (according to pp. 35 & 36 of Implementation Guide) uint8_t ct[16] = { 0x43, 0x8f, 0x18, 0x9c, 0x8d, 0xb4, 0xee, 0x4e, 0x3e, 0xf5, 0xc0, 0x05, 0x04, 0x01, 0x09, 0x41 }; + uint8_t xt[16] = { 0x18, 0x0d, 0x57, 0x5c, 0xdf, 0xfe, 0x60, 0x78, + 0x65, 0x32, 0x78, 0x79, 0x51, 0x98, 0x5d, 0xa6 }; + + speck_context_t ctx; speck_expand_key (key, &ctx); @@ -667,24 +753,35 @@ int speck_test () { #else speck_ctr (pt, pt, 16, iv, &ctx); #endif + u64 i; - // fprintf (stderr, "rk00: %016llx\n", ctx.key[0]); - // fprintf (stderr, "rk33: %016llx\n", ctx.key[33]); - // fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt); - // fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n"); + fprintf (stderr, "rk00: %016llx\n", ctx.key[0]); + fprintf (stderr, "rk33: %016llx\n", ctx.key[33]); + fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt); + fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n"); int ret = 1; for (i=0; i < 16; i++) if (pt[i] != ct[i]) ret = 0; + memset (pt, 0, 16); + speck_expand_key_he (key, &ctx); + speck_he (pt, pt, 16, xv, &ctx); + + fprintf (stderr, "rk00: %016llx\n", ctx.key[0]); + fprintf (stderr, "rk31: %016llx\n", ctx.key[31]); + fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt); + fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n"); + + for (i=0; i < 16; i++) + if (pt[i] != xt[i]) ret = 0; + return (ret); } -/* -#include // for testing - int main (int argc, char* argv[]) { +int main (int argc, char* argv[]) { fprintf (stdout, "SPECK SELF TEST RESULT: %u\n", speck_test (0,NULL)); - } +} */ diff --git a/speck.h b/speck.h index 18a67b6..3b8cba5 100644 --- a/speck.h +++ b/speck.h @@ -54,3 +54,10 @@ speck_context_t *ctx); int speck_expand_key (const unsigned char *k, speck_context_t *ctx); + + +int speck_he (unsigned char *out, const unsigned char *in, unsigned long long inlen, + const unsigned char *n, speck_context_t *ctx); + + +int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx); From eeedb509f89b8454601030774837cb8ba5df73ee Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Mon, 15 Jun 2020 15:04:54 +0545 Subject: [PATCH 09/45] indicated source --- pearson.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pearson.c b/pearson.c index 2ec74bd..ca2aa3e 100644 --- a/pearson.c +++ b/pearson.c @@ -1,3 +1,5 @@ +// taken from https://github.com/Logan007/pearson + #include #include From 365d2b2782b75f4a2b5516dd4f6a905a0efcc27c Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 13:27:38 +0545 Subject: [PATCH 10/45] prepared header encryption --- CMakeLists.txt | 5 ++ Makefile.in | 1 + header_encryption.c | 65 +++++++++------ header_encryption.h | 17 ++++ n2n.h | 8 +- pearson.c | 195 ++++++++++++++++++++++++++++++++++++++++++++ pearson.h | 3 + speck.h | 7 ++ 8 files changed, 276 insertions(+), 25 deletions(-) create mode 100644 header_encryption.h create mode 100644 pearson.c create mode 100644 pearson.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b5fd37b..36ee727 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,12 @@ add_library(n2n n2n.c transform_null.c transform_tf.c transform_aes.c + transform_cc20.c + transform_speck.c + speck.c + pearson.c random_numbers.c + header_encryption.c tuntap_freebsd.c tuntap_netbsd.c tuntap_linux.c diff --git a/Makefile.in b/Makefile.in index b231aac..1bca92c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -51,6 +51,7 @@ N2N_LIB=libn2n.a N2N_OBJS=n2n.o wire.o minilzo.o twofish.o speck.o \ edge_utils.o sn_utils.o \ transform_null.o transform_tf.o transform_aes.o transform_cc20.o transform_speck.o \ + header_encryption.o pearson.o \ tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o random_numbers.o \ tuntap_osx.o LIBS_EDGE+=$(LIBS_EDGE_OPT) diff --git a/header_encryption.c b/header_encryption.c index e263cfc..8f7ab97 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -1,35 +1,38 @@ -#include -#include +#include "header_encryption.h" + +#include -// #include "n2n_wire.h" // n2n_community_t #include "n2n.h" -#include "speck.h" +#include "random_numbers.h" +#include "pearson.h" #include "portable_endian.h" -uint32_t decryt_packet_header (uint8_t packet[], uint8_t packet_len, - char * community_name, speck_ctx * ctx) { +#include + + +uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, + char * community_name, he_context_t * ctx) { // assemble IV // the last four are ASCII "n2n!" and do not get overwritten uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x32, 0x6E, 0x21 }; - // the first 96 bits of the packet are used padded with ASCII "n2n!" + // the first 96 bits of the packet get padded with ASCII "n2n!" // to full 128 bit IV - memcopy (iv, packet, 12); - - // alternatively, consider: pearson_hash_128 (iv, packet, 12) + memcpy (iv, packet, 12); + // alternatively, consider: pearson_hash_128 (iv, packet, 12); // try community name as possible key and check for magic bytes uint32_t magic = 0x6E326E00; // ="n2n_" uint32_t test_magic; // check for magic bytes and resonable value in header len field - speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, ctx); + speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, (speck_context_t*)ctx); test_magic = be32toh (test_magic); if ( ((test_magic << 8) == magic) && ((test_magic >> 24) <= packet_len) // (test_masgic >> 24) is header_len ) { - speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, ctx); + speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, (speck_context_t*)ctx); // restore original packet order memcpy (&packet[0], &packet[16], 4); memcpy (&packet[4], community_name, N2N_COMMUNITY_SIZE); @@ -39,7 +42,7 @@ uint32_t decryt_packet_header (uint8_t packet[], uint8_t packet_len, } -int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, +int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, struct sn_community *communities) { if (packet_len < 20) @@ -58,8 +61,12 @@ int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, ) { // most probably unencrypted - return (1); + // TODO: + // !!! make sure, no downgrading happens here !!! + // NOT FOR DEFINETLY ENCRYPTED COMMUNITIES / NO DOWNGRADE, NO INJECTION + + return (HEADER_ENCRYPTION_NONE); } else { // most probably encrypted @@ -67,24 +74,23 @@ int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, int32_t ret; struct sn_community *c, *tmp; HASH_ITER (hh, communities, c, tmp) { - // check if this is an encrypted community - if ( ret = decrypt_packet_header (packet, packet_len, c->community, c-> ctx) ) { - // no upgrade from unencrypted to encrypted - if (c->header_encryption == 1) - return (-2); + // skip the definitely unencrypted communities + if (c->header_encryption == HEADER_ENCRYPTION_NONE) + continue; + if ( (ret = packet_header_decrypt (packet, packet_len, c->community, &(c->header_encryption_ctx))) ) { // set to 'encrypted' - c->header_encryption = 2; + c->header_encryption = HEADER_ENCRYPTION_ENABLED; // no need to test any further - return (2); + return (HEADER_ENCRYPTION_ENABLED); } } - // no match + // no matching key/community return (-3); } } -int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, speck_ctx * ctx) { +int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx) { if (header_len < 20) return (-1); @@ -100,5 +106,16 @@ int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, speck_ctx * iv[12] = header_len; - speck_he (&packet[12], &packet[12], header_len - 12, iv, ctx); + speck_he (&packet[12], &packet[12], header_len - 12, iv, (speck_context_t*)ctx); + + return (0); +} + + +void packet_header_setup_key (char * community_name, he_context_t * ctx) { + + uint8_t key[16]; + pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); + + speck_expand_key_he (key, ctx); } diff --git a/header_encryption.h b/header_encryption.h new file mode 100644 index 0000000..f8a31cb --- /dev/null +++ b/header_encryption.h @@ -0,0 +1,17 @@ +#include + +#include "speck.h" +typedef speck_context_t he_context_t; + + +#define HEADER_ENCRYPTION_UNKNOWN 0 +#define HEADER_ENCRYPTION_NONE 1 +#define HEADER_ENCRYPTION_ENABLED 2 + + +uint32_t decrypt_packet_header (uint8_t packet[], uint8_t packet_len, + char * community_name, he_context_t * ctx); + +int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); + +int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); diff --git a/n2n.h b/n2n.h index 7041fa3..d05e9cf 100644 --- a/n2n.h +++ b/n2n.h @@ -111,6 +111,7 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include "minilzo.h" +#include "header_encryption.h" #define closesocket(a) close(a) #endif /* #ifndef WIN32 */ @@ -160,6 +161,7 @@ typedef struct tuntap_dev { #define MSG_TYPE_FEDERATION 8 #define MSG_TYPE_PEER_INFO 9 #define MSG_TYPE_QUERY_PEER 10 +#define MSG_TYPE_MAX_TYPE 10 /* N2N compression indicators. */ /* Compression is disabled by default for outgoing packets if no cli @@ -225,6 +227,8 @@ typedef struct n2n_edge_conf { n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; n2n_route_t *routes; /**< Networks to route through n2n */ n2n_community_t community_name; /**< The community. 16 full octets. */ + uint8_t header_encryption; /**< Header encryption indicator. */ + he_context_t header_encryption_ctx; /**< Header encryption cipher context. */ n2n_transform_t transop_id; /**< The transop to use. */ uint16_t compression; /**< Compress outgoing data packets before encryption */ uint16_t num_routes; /**< Number of routes in routes */ @@ -270,7 +274,9 @@ typedef struct sn_stats struct sn_community { char community[N2N_COMMUNITY_SIZE]; - struct peer_info *edges; /* Link list of registered edges. */ + uint8_t header_encryption; /* Header encryption indicator. */ + he_context_t header_encryption_ctx; /* Header encryption cipher context. */ + struct peer_info *edges; /* Link list of registered edges. */ UT_hash_handle hh; /* makes this structure hashable */ }; diff --git a/pearson.c b/pearson.c new file mode 100644 index 0000000..80c90a6 --- /dev/null +++ b/pearson.c @@ -0,0 +1,195 @@ +// taken from https://github.com/Logan007/pearson + +#include +#include + +#include "pearson.h" + + +// table as in original paper "Fast Hashing of Variable-Length Text Strings" by Peter K. Pearson +// as published in The Communications of the ACM Vol.33, No. 6 (June 1990), pp. 677-680. +static const uint8_t t[256] ={ + 0x01, 0x57, 0x31, 0x0c, 0xb0, 0xb2, 0x66, 0xa6, 0x79, 0xc1, 0x06, 0x54, 0xf9, 0xe6, 0x2c, 0xa3, + 0x0e, 0xc5, 0xd5, 0xb5, 0xa1, 0x55, 0xda, 0x50, 0x40, 0xef, 0x18, 0xe2, 0xec, 0x8e, 0x26, 0xc8, + 0x6e, 0xb1, 0x68, 0x67, 0x8d, 0xfd, 0xff, 0x32, 0x4d, 0x65, 0x51, 0x12, 0x2d, 0x60, 0x1f, 0xde, + 0x19, 0x6b, 0xbe, 0x46, 0x56, 0xed, 0xf0, 0x22, 0x48, 0xf2, 0x14, 0xd6, 0xf4, 0xe3, 0x95, 0xeb, + 0x61, 0xea, 0x39, 0x16, 0x3c, 0xfa, 0x52, 0xaf, 0xd0, 0x05, 0x7f, 0xc7, 0x6f, 0x3e, 0x87, 0xf8, + 0xae, 0xa9, 0xd3, 0x3a, 0x42, 0x9a, 0x6a, 0xc3, 0xf5, 0xab, 0x11, 0xbb, 0xb6, 0xb3, 0x00, 0xf3, + 0x84, 0x38, 0x94, 0x4b, 0x80, 0x85, 0x9e, 0x64, 0x82, 0x7e, 0x5b, 0x0d, 0x99, 0xf6, 0xd8, 0xdb, + 0x77, 0x44, 0xdf, 0x4e, 0x53, 0x58, 0xc9, 0x63, 0x7a, 0x0b, 0x5c, 0x20, 0x88, 0x72, 0x34, 0x0a, + 0x8a, 0x1e, 0x30, 0xb7, 0x9c, 0x23, 0x3d, 0x1a, 0x8f, 0x4a, 0xfb, 0x5e, 0x81, 0xa2, 0x3f, 0x98, + 0xaa, 0x07, 0x73, 0xa7, 0xf1, 0xce, 0x03, 0x96, 0x37, 0x3b, 0x97, 0xdc, 0x5a, 0x35, 0x17, 0x83, + 0x7d, 0xad, 0x0f, 0xee, 0x4f, 0x5f, 0x59, 0x10, 0x69, 0x89, 0xe1, 0xe0, 0xd9, 0xa0, 0x25, 0x7b, + 0x76, 0x49, 0x02, 0x9d, 0x2e, 0x74, 0x09, 0x91, 0x86, 0xe4, 0xcf, 0xd4, 0xca, 0xd7, 0x45, 0xe5, + 0x1b, 0xbc, 0x43, 0x7c, 0xa8, 0xfc, 0x2a, 0x04, 0x1d, 0x6c, 0x15, 0xf7, 0x13, 0xcd, 0x27, 0xcb, + 0xe9, 0x28, 0xba, 0x93, 0xc6, 0xc0, 0x9b, 0x21, 0xa4, 0xbf, 0x62, 0xcc, 0xa5, 0xb4, 0x75, 0x4c, + 0x8c, 0x24, 0xd2, 0xac, 0x29, 0x36, 0x9f, 0x08, 0xb9, 0xe8, 0x71, 0xc4, 0xe7, 0x2f, 0x92, 0x78, + 0x33, 0x41, 0x1c, 0x90, 0xfe, 0xdd, 0x5d, 0xbd, 0xc2, 0x8b, 0x70, 0x2b, 0x47, 0x6d, 0xb8, 0xd1 }; + +/* +// alternative table as used in RFC 3074 and NOT as in original paper +static const uint8_t t[256] ={ + 0xfb, 0xaf, 0x77, 0xd7, 0x51, 0x0e, 0x4f, 0xbf, 0x67, 0x31, 0xb5, 0x8f, 0xba, 0x9d, 0x00, 0xe8, + 0x1f, 0x20, 0x37, 0x3c, 0x98, 0x3a, 0x11, 0xed, 0xae, 0x46, 0xa0, 0x90, 0xdc, 0x5a, 0x39, 0xdf, + 0x3b, 0x03, 0x12, 0x8c, 0x6f, 0xa6, 0xcb, 0xc4, 0x86, 0xf3, 0x7c, 0x5f, 0xde, 0xb3, 0xc5, 0x41, + 0xb4, 0x30, 0x24, 0x0f, 0x6b, 0x2e, 0xe9, 0x82, 0xa5, 0x1e, 0x7b, 0xa1, 0xd1, 0x17, 0x61, 0x10, + 0x28, 0x5b, 0xdb, 0x3d, 0x64, 0x0a, 0xd2, 0x6d, 0xfa, 0x7f, 0x16, 0x8a, 0x1d, 0x6c, 0xf4, 0x43, + 0xcf, 0x09, 0xb2, 0xcc, 0x4a, 0x62, 0x7e, 0xf9, 0xa7, 0x74, 0x22, 0x4d, 0xc1, 0xc8, 0x79, 0x05, + 0x14, 0x71, 0x47, 0x23, 0x80, 0x0d, 0xb6, 0x5e, 0x19, 0xe2, 0xe3, 0xc7, 0x4b, 0x1b, 0x29, 0xf5, + 0xe6, 0xe0, 0x2b, 0xe1, 0xb1, 0x1a, 0x9b, 0x96, 0xd4, 0x8e, 0xda, 0x73, 0xf1, 0x49, 0x58, 0x69, + 0x27, 0x72, 0x3e, 0xff, 0xc0, 0xc9, 0x91, 0xd6, 0xa8, 0x9e, 0xdd, 0x94, 0x9a, 0x7a, 0x0c, 0x54, + 0x52, 0xa3, 0x2c, 0x8b, 0xe4, 0xec, 0xcd, 0xf2, 0xd9, 0x0b, 0xbb, 0x92, 0x9f, 0x40, 0x56, 0xef, + 0xc3, 0x2a, 0x6a, 0xc6, 0x76, 0x70, 0xb8, 0xac, 0x57, 0x02, 0xad, 0x75, 0xb0, 0xe5, 0xf7, 0xfd, + 0x89, 0xb9, 0x63, 0xa4, 0x66, 0x93, 0x2d, 0x42, 0xe7, 0x34, 0x8d, 0xd3, 0xc2, 0xce, 0xf6, 0xee, + 0x38, 0x6e, 0x4e, 0xf8, 0x3f, 0xf0, 0xbd, 0x5d, 0x5c, 0x33, 0x35, 0xb7, 0x13, 0xab, 0x48, 0x32, + 0x21, 0x68, 0x65, 0x45, 0x08, 0xfc, 0x53, 0x78, 0x4c, 0x87, 0x55, 0x36, 0xca, 0x7d, 0xbc, 0xd5, + 0x60, 0xeb, 0x88, 0xd0, 0xa2, 0x81, 0xbe, 0x84, 0x9c, 0x26, 0x2f, 0x01, 0x07, 0xfe, 0x18, 0x04, + 0xd8, 0x83, 0x59, 0x15, 0x1c, 0x85, 0x25, 0x99, 0x95, 0x50, 0xaa, 0x44, 0x06, 0xa9, 0xea, 0x97 }; */ + + +#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) + + +void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len) { + + /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) + * works faster on well pipelined CPUs than loading the 64-bit value from memory. + * however, there is one advantage to loading from memory: as we also store back to + * memory at the end, we do not need to care about endianess! */ + uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + + uint64_t upper_hash_mask = *(uint64_t*)&upper; + uint64_t lower_hash_mask = *(uint64_t*)&lower; + uint64_t high_upper_hash_mask = upper_hash_mask + 0x1010101010101010; + uint64_t high_lower_hash_mask = lower_hash_mask + 0x1010101010101010; + + uint64_t upper_hash = 0; + uint64_t lower_hash = 0; + uint64_t high_upper_hash = 0; + uint64_t high_lower_hash = 0; + + for (size_t i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint64_t c = (uint8_t)in[i]; + c |= c << 8; + c |= c << 16; + c |= c << 32; + upper_hash ^= c ^ upper_hash_mask; + lower_hash ^= c ^ lower_hash_mask; + high_upper_hash ^= c ^ high_upper_hash_mask; + high_lower_hash ^= c ^ high_lower_hash_mask; + + // table lookup + uint8_t x; + uint64_t h = 0; + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + upper_hash = h; + + h = 0; + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + lower_hash = h; + + h = 0; + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + high_upper_hash = h; + + h = 0; + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + high_lower_hash = h; + } + // store output + uint64_t *o; + o = (uint64_t*)&out[0]; + *o = high_upper_hash; + o = (uint64_t*)&out[8]; + *o = high_lower_hash; + o = (uint64_t*)&out[16]; + *o = upper_hash; + o = (uint64_t*)&out[24]; + *o = lower_hash; +} + + +void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len) { + + /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) + * works faster on well pipelined CPUs than loading the 64-bit value from memory. + * however, there is one advantage to loading from memory: as we also store back to + * memory at the end, we do not need to care about endianess! */ + uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + + uint64_t upper_hash_mask = *(uint64_t*)&upper; + uint64_t lower_hash_mask = *(uint64_t*)&lower; + + uint64_t upper_hash = 0; + uint64_t lower_hash = 0; + + for (size_t i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint64_t c = (uint8_t)in[i]; + c |= c << 8; + c |= c << 16; + c |= c << 32; + upper_hash ^= c ^ upper_hash_mask; + lower_hash ^= c ^ lower_hash_mask; + // table lookup + uint8_t x; + uint64_t h = 0; + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + upper_hash = h; + + h = 0; + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + lower_hash = h; + } + // store output + uint64_t *o; + o = (uint64_t*)&out[0]; + *o = upper_hash; + o = (uint64_t*)&out[8]; + *o = lower_hash; +} diff --git a/pearson.h b/pearson.h new file mode 100644 index 0000000..f021f41 --- /dev/null +++ b/pearson.h @@ -0,0 +1,3 @@ +void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); + +void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len); diff --git a/speck.h b/speck.h index 3b8cba5..51df36b 100644 --- a/speck.h +++ b/speck.h @@ -2,6 +2,10 @@ // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ + +#ifndef SPECK_H +#define SPECK_H + #define u32 uint32_t #define u64 uint64_t @@ -61,3 +65,6 @@ int speck_he (unsigned char *out, const unsigned char *in, unsigned long long in int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx); + + +#endif From e6e4999f19ed2e3c628a7e9eed20f7314c83731f Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 23:06:06 +0545 Subject: [PATCH 11/45] woke up from a nightmare of missing typedefs --- header_encryption.c | 30 +++++++++++++++++++----------- header_encryption.h | 26 +++++++++++++++++++++----- n2n.h | 26 ++++++++++++++------------ sn_utils.c | 10 +++++++--- speck.c | 1 - speck.h | 1 + 6 files changed, 62 insertions(+), 32 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 8f7ab97..1966819 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -2,13 +2,15 @@ #include -#include "n2n.h" #include "random_numbers.h" #include "pearson.h" #include "portable_endian.h" -#include +#include // !!! + + +#define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, @@ -45,6 +47,9 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, struct sn_community *communities) { + struct sn_community *c, *tmp; + + if (packet_len < 20) return (-1); @@ -62,25 +67,28 @@ int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len // most probably unencrypted - // TODO: - // !!! make sure, no downgrading happens here !!! - // NOT FOR DEFINETLY ENCRYPTED COMMUNITIES / NO DOWNGRADE, NO INJECTION - + // make sure, no downgrading happens here and no unencrypted packets can be + // injected in a community which definitely deals with encrypted headers + HASH_FIND_COMMUNITY(communities, (char *)&packet[04], c); + if (!c) + if (c->header_encryption == HEADER_ENCRYPTION_ENABLED) + return (-2); + // set 'no encryption' in case it is not set yet + c->header_encryption = HEADER_ENCRYPTION_NONE; return (HEADER_ENCRYPTION_NONE); } else { // most probably encrypted // cycle through the known communities (as keys) to eventually decrypt int32_t ret; - struct sn_community *c, *tmp; HASH_ITER (hh, communities, c, tmp) { // skip the definitely unencrypted communities if (c->header_encryption == HEADER_ENCRYPTION_NONE) continue; - if ( (ret = packet_header_decrypt (packet, packet_len, c->community, &(c->header_encryption_ctx))) ) { - // set to 'encrypted' + if ( (ret = packet_header_decrypt (packet, packet_len, c->community, c->header_encryption_ctx)) ) { + // set 'encrypted' in case it is not set yet c->header_encryption = HEADER_ENCRYPTION_ENABLED; - // no need to test any further + // no need to test further communities return (HEADER_ENCRYPTION_ENABLED); } } @@ -117,5 +125,5 @@ void packet_header_setup_key (char * community_name, he_context_t * ctx) { uint8_t key[16]; pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); - speck_expand_key_he (key, ctx); + speck_expand_key_he (key, (speck_context_t*)ctx); } diff --git a/header_encryption.h b/header_encryption.h index f8a31cb..a4395e0 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -1,17 +1,33 @@ + + +#ifndef _HEADER_ENCRYPTION_H_ +#define _HEADER_ENCRYPTION_H_ + + #include - #include "speck.h" -typedef speck_context_t he_context_t; +#include "n2n.h" +//define he_context_t speck_context_t +typedef struct speck_context_t he_context_t; + + +/* Header encryption indicators */ #define HEADER_ENCRYPTION_UNKNOWN 0 #define HEADER_ENCRYPTION_NONE 1 #define HEADER_ENCRYPTION_ENABLED 2 -uint32_t decrypt_packet_header (uint8_t packet[], uint8_t packet_len, +uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, char * community_name, he_context_t * ctx); -int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); -int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); +int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community * communities); + + +int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); + + +#endif diff --git a/n2n.h b/n2n.h index d05e9cf..8b510a5 100644 --- a/n2n.h +++ b/n2n.h @@ -111,7 +111,6 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include "minilzo.h" -#include "header_encryption.h" #define closesocket(a) close(a) #endif /* #ifndef WIN32 */ @@ -180,6 +179,9 @@ typedef struct tuntap_dev { bits of transform_id; will be obsolete as soon as compression gets its own field in the packet. REVISIT then. */ +/* forward delcaration of header encryption context, see 'header_encryption.h' */ +typedef struct speck_context_t he_context_t; + #define DEFAULT_MTU 1290 /** Uncomment this to enable the MTU check, then try to ssh to generate a fragmented packet. */ @@ -228,7 +230,7 @@ typedef struct n2n_edge_conf { n2n_route_t *routes; /**< Networks to route through n2n */ n2n_community_t community_name; /**< The community. 16 full octets. */ uint8_t header_encryption; /**< Header encryption indicator. */ - he_context_t header_encryption_ctx; /**< Header encryption cipher context. */ + he_context_t *header_encryption_ctx; /**< Header encryption cipher context. */ n2n_transform_t transop_id; /**< The transop to use. */ uint16_t compression; /**< Compress outgoing data packets before encryption */ uint16_t num_routes; /**< Number of routes in routes */ @@ -259,6 +261,16 @@ typedef struct sn_stats time_t last_reg_super; /* Time when last REGISTER_SUPER was received. */ } sn_stats_t; + struct sn_community +{ + char community[N2N_COMMUNITY_SIZE]; + uint8_t header_encryption; /* Header encryption indicator. */ + he_context_t *header_encryption_ctx; /* Header encryption cipher context. */ + struct peer_info *edges; /* Link list of registered edges. */ + + UT_hash_handle hh; /* makes this structure hashable */ +}; + typedef struct n2n_sn { time_t start_time; /* Used to measure uptime. */ @@ -271,16 +283,6 @@ typedef struct sn_stats struct sn_community *communities; } n2n_sn_t; - struct sn_community -{ - char community[N2N_COMMUNITY_SIZE]; - uint8_t header_encryption; /* Header encryption indicator. */ - he_context_t header_encryption_ctx; /* Header encryption cipher context. */ - struct peer_info *edges; /* Link list of registered edges. */ - - UT_hash_handle hh; /* makes this structure hashable */ -}; - /* ************************************** */ #ifdef __ANDROID_NDK__ diff --git a/sn_utils.c b/sn_utils.c index ed1f85f..95a26b8 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -1,4 +1,5 @@ #include "n2n.h" +#include "header_encryption.h" #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) #define N2N_SN_LPORT_DEFAULT 7654 @@ -37,7 +38,7 @@ static int process_mgmt(n2n_sn_t *sss, static int process_udp(n2n_sn_t *sss, const struct sockaddr_in *sender_sock, - const uint8_t *udp_buf, + uint8_t *udp_buf, size_t udp_size, time_t now); @@ -372,13 +373,14 @@ static int process_mgmt(n2n_sn_t *sss, */ static int process_udp(n2n_sn_t *sss, const struct sockaddr_in *sender_sock, - const uint8_t *udp_buf, + uint8_t *udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; + int8_t he = HEADER_ENCRYPTION_UNKNOWN; size_t msg_type; uint8_t from_supernode; macstr_t mac_buf; @@ -390,6 +392,8 @@ static int process_udp(n2n_sn_t *sss, udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), ntohs(sender_sock->sin_port)); + he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); + /* Use decode_common() to determine the kind of packet then process it: * * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK @@ -781,4 +785,4 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) sn_term(sss); return 0; -} \ No newline at end of file +} diff --git a/speck.c b/speck.c index 74a1426..a5ced78 100644 --- a/speck.c +++ b/speck.c @@ -3,7 +3,6 @@ // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ #include -#include #include "portable_endian.h" #include "speck.h" diff --git a/speck.h b/speck.h index 51df36b..a456f77 100644 --- a/speck.h +++ b/speck.h @@ -6,6 +6,7 @@ #ifndef SPECK_H #define SPECK_H +#include #define u32 uint32_t #define u64 uint64_t From ec635aefa94296e0cda390966d9be323994cc7a7 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 23:12:51 +0545 Subject: [PATCH 12/45] made header encryption indicator 8-bit type --- header_encryption.c | 4 ++-- header_encryption.h | 4 ++-- sn_utils.c | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 1966819..756d198 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -44,8 +44,8 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, } -int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, - struct sn_community *communities) { +int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community *communities) { struct sn_community *c, *tmp; diff --git a/header_encryption.h b/header_encryption.h index a4395e0..65b9709 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -23,8 +23,8 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, char * community_name, he_context_t * ctx); -int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, - struct sn_community * communities); +int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community * communities); int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); diff --git a/sn_utils.c b/sn_utils.c index 95a26b8..b38e045 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -393,6 +393,8 @@ static int process_udp(n2n_sn_t *sss, ntohs(sender_sock->sin_port)); he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); + if (he < 0) + return -1; /* something wrong with packet decryption */ /* Use decode_common() to determine the kind of packet then process it: * From a553c8fe38374bd4e4c758e240441b254c360ae9 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 23:46:52 +0545 Subject: [PATCH 13/45] new communities have no header encryption --- sn.c | 11 ++++++++++- sn_utils.c | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sn.c b/sn.c index 9d7c26b..c14d5a9 100644 --- a/sn.c +++ b/sn.c @@ -19,6 +19,7 @@ /* Supernode for n2n-2.x */ #include "n2n.h" +#include "header_encryption.h" #ifdef WIN32 #include @@ -435,13 +436,14 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) { */ static int process_udp(n2n_sn_t * sss, const struct sockaddr_in * sender_sock, - const uint8_t * udp_buf, + uint8_t * udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; + int8_t he = HEADER_ENCRYPTION_UNKNOWN; size_t msg_type; uint8_t from_supernode; macstr_t mac_buf; @@ -453,6 +455,10 @@ static int process_udp(n2n_sn_t * sss, udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), ntohs(sender_sock->sin_port)); + he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); + if (he < 0) + return -1; /* something wrong during packet decryption */ + /* Use decode_common() to determine the kind of packet then process it: * * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK @@ -622,6 +628,9 @@ static int process_udp(n2n_sn_t * sss, if(comm) { strncpy(comm->community, (char*)cmn.community, N2N_COMMUNITY_SIZE-1); comm->community[N2N_COMMUNITY_SIZE-1] = '\0'; + /* new communities introduced by REGISTERs could not have had encrypted header */ + comm->header_encryption = HEADER_ENCRYPTION_NONE; + HASH_ADD_STR(sss->communities, community, comm); traceEvent(TRACE_INFO, "New community: %s", comm->community); diff --git a/sn_utils.c b/sn_utils.c index b38e045..51742f7 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -394,7 +394,7 @@ static int process_udp(n2n_sn_t *sss, he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); if (he < 0) - return -1; /* something wrong with packet decryption */ + return -1; /* something wrong during packet decryption */ /* Use decode_common() to determine the kind of packet then process it: * @@ -577,6 +577,9 @@ static int process_udp(n2n_sn_t *sss, { strncpy(comm->community, (char *)cmn.community, N2N_COMMUNITY_SIZE - 1); comm->community[N2N_COMMUNITY_SIZE - 1] = '\0'; + /* new communities introduced by REGISTERs could not have had encrypted header */ + comm->header_encryption = HEADER_ENCRYPTION_NONE; + HASH_ADD_STR(sss->communities, community, comm); traceEvent(TRACE_INFO, "New community: %s", comm->community); From 9d62263eca186a7a278852270c8eec351a39ce3f Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 17 Jun 2020 01:27:02 +0545 Subject: [PATCH 14/45] having supernode running again (unencryptedly) --- header_encryption.c | 2 ++ header_encryption.h | 14 ++++++++------ sn.c | 13 +++++++++++++ sn_utils.c | 8 +++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 756d198..7866eff 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -75,6 +75,7 @@ int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, return (-2); // set 'no encryption' in case it is not set yet c->header_encryption = HEADER_ENCRYPTION_NONE; + c->header_encryption_ctx = NULL; return (HEADER_ENCRYPTION_NONE); } else { @@ -125,5 +126,6 @@ void packet_header_setup_key (char * community_name, he_context_t * ctx) { uint8_t key[16]; pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); + ctx = calloc(1, sizeof(speck_context_t)); speck_expand_key_he (key, (speck_context_t*)ctx); } diff --git a/header_encryption.h b/header_encryption.h index 65b9709..dec8911 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -1,14 +1,13 @@ - - -#ifndef _HEADER_ENCRYPTION_H_ -#define _HEADER_ENCRYPTION_H_ +//#ifndef _HEADER_ENCRYPTION_H_ +//#define _HEADER_ENCRYPTION_H_ #include -#include "speck.h" #include "n2n.h" +#include "speck.h" + //define he_context_t speck_context_t typedef struct speck_context_t he_context_t; @@ -30,4 +29,7 @@ int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); -#endif +void packet_header_setup_key (char * community_name, he_context_t * ctx); + + +// #endif diff --git a/sn.c b/sn.c index c14d5a9..72d8a9f 100644 --- a/sn.c +++ b/sn.c @@ -81,6 +81,8 @@ static void deinit_sn(n2n_sn_t * sss) HASH_ITER(hh, sss->communities, community, tmp) { clear_peer_list(&community->edges); + if (NULL != community->header_encryption_ctx) + free (community->header_encryption_ctx); HASH_DEL(sss->communities, community); free(community); } @@ -390,6 +392,8 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) { HASH_ITER(hh, sss->communities, s, tmp) { HASH_DEL(sss->communities, s); + if (NULL != s->header_encryption_ctx) + free (s->header_encryption_ctx); free(s); } @@ -413,7 +417,12 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) { if(s != NULL) { strncpy((char*)s->community, line, N2N_COMMUNITY_SIZE-1); s->community[N2N_COMMUNITY_SIZE-1] = '\0'; + /* we do not know if header encryption is used in this community, + * first packet will show. just in case, setup the key. */ + s->header_encryption = HEADER_ENCRYPTION_UNKNOWN; + packet_header_setup_key (s->community, s->header_encryption_ctx); HASH_ADD_STR(sss->communities, community, s); + num_communities++; traceEvent(TRACE_INFO, "Added allowed community '%s' [total: %u]", (char*)s->community, num_communities); @@ -630,6 +639,7 @@ static int process_udp(n2n_sn_t * sss, comm->community[N2N_COMMUNITY_SIZE-1] = '\0'; /* new communities introduced by REGISTERs could not have had encrypted header */ comm->header_encryption = HEADER_ENCRYPTION_NONE; + comm->header_encryption_ctx = NULL; HASH_ADD_STR(sss->communities, community, comm); @@ -1122,6 +1132,9 @@ static int run_loop(n2n_sn_t * sss) { if((comm->edges == NULL) && (!sss->lock_communities)) { traceEvent(TRACE_INFO, "Purging idle community %s", comm->community); + if (NULL != comm->header_encryption_ctx) + /* this should not happen as no 'locked' and thus only communities w/o encrypted header here */ + free (comm->header_encryption_ctx); HASH_DEL(sss->communities, comm); free(comm); } diff --git a/sn_utils.c b/sn_utils.c index 51742f7..256e3af 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -226,6 +226,8 @@ void sn_term(n2n_sn_t *sss) HASH_ITER(hh, sss->communities, community, tmp) { clear_peer_list(&community->edges); + if (NULL != community->header_encryption_ctx) + free (community->header_encryption_ctx); HASH_DEL(sss->communities, community); free(community); } @@ -579,6 +581,7 @@ static int process_udp(n2n_sn_t *sss, comm->community[N2N_COMMUNITY_SIZE - 1] = '\0'; /* new communities introduced by REGISTERs could not have had encrypted header */ comm->header_encryption = HEADER_ENCRYPTION_NONE; + comm->header_encryption_ctx = NULL; HASH_ADD_STR(sss->communities, community, comm); @@ -780,7 +783,10 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) if ((comm->edges == NULL) && (!sss->lock_communities)) { traceEvent(TRACE_INFO, "Purging idle community %s", comm->community); - HASH_DEL(sss->communities, comm); + if (NULL != comm->header_encryption_ctx) + /* this should not happen as no 'locked' and thus only communities w/o encrypted header here */ + free (comm->header_encryption_ctx); + HASH_DEL(sss->communities, comm); free(comm); } } From a1670c52123911be41780d408a5c9ef7d296d59a Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Wed, 17 Jun 2020 02:47:26 +0545 Subject: [PATCH 15/45] updated pearson.c --- pearson.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pearson.c b/pearson.c index ca2aa3e..e91bd94 100644 --- a/pearson.c +++ b/pearson.c @@ -1,5 +1,7 @@ // taken from https://github.com/Logan007/pearson +// This is free and unencumbered software released into the public domain. + #include #include From 68428a8d2af1e418878c89f90c163d56611755a0 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 17 Jun 2020 06:54:02 +0200 Subject: [PATCH 16/45] Updated (C) --- edge.c | 2 +- edge_utils.c | 2 +- example_edge_embed_quick_edge_init.c | 2 +- n2n.c | 2 +- n2n.h | 2 +- n2n_transforms.h | 2 +- n2n_wire.h | 2 +- pearson.c | 18 ++++++++++++++++++ pearson.h | 18 ++++++++++++++++++ sn.c | 2 +- transform_null.c | 2 +- transform_tf.c | 2 +- tuntap_freebsd.c | 2 +- tuntap_linux.c | 2 +- tuntap_netbsd.c | 2 +- tuntap_osx.c | 2 +- wire.c | 2 +- 17 files changed, 51 insertions(+), 15 deletions(-) diff --git a/edge.c b/edge.c index 8babd45..b15762d 100644 --- a/edge.c +++ b/edge.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/edge_utils.c b/edge_utils.c index 825b8ef..cf2e80e 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/example_edge_embed_quick_edge_init.c b/example_edge_embed_quick_edge_init.c index ba0eb02..4618059 100644 --- a/example_edge_embed_quick_edge_init.c +++ b/example_edge_embed_quick_edge_init.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n.c b/n2n.c index b3479ce..fe8d39a 100644 --- a/n2n.c +++ b/n2n.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n.h b/n2n.h index 7041fa3..7737213 100644 --- a/n2n.h +++ b/n2n.h @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n_transforms.h b/n2n_transforms.h index 1734ec1..589e36b 100644 --- a/n2n_transforms.h +++ b/n2n_transforms.h @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n_wire.h b/n2n_wire.h index 0a64f4a..7cd0e41 100644 --- a/n2n_wire.h +++ b/n2n_wire.h @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/pearson.c b/pearson.c index e91bd94..0ff0e0d 100644 --- a/pearson.c +++ b/pearson.c @@ -1,3 +1,21 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + // taken from https://github.com/Logan007/pearson // This is free and unencumbered software released into the public domain. diff --git a/pearson.h b/pearson.h index 43d1f98..5e4ca66 100644 --- a/pearson.h +++ b/pearson.h @@ -1 +1,19 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); diff --git a/sn.c b/sn.c index 9d7c26b..8c01a7b 100644 --- a/sn.c +++ b/sn.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/transform_null.c b/transform_null.c index 062ddf2..830bcfa 100644 --- a/transform_null.c +++ b/transform_null.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/transform_tf.c b/transform_tf.c index 412f65f..481e972 100644 --- a/transform_tf.c +++ b/transform_tf.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_freebsd.c b/tuntap_freebsd.c index 7404c95..d871e89 100644 --- a/tuntap_freebsd.c +++ b/tuntap_freebsd.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_linux.c b/tuntap_linux.c index 6e1e770..7a5cbb4 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_netbsd.c b/tuntap_netbsd.c index 2d948d9..617e2b2 100644 --- a/tuntap_netbsd.c +++ b/tuntap_netbsd.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_osx.c b/tuntap_osx.c index 52a1d28..ef166ff 100644 --- a/tuntap_osx.c +++ b/tuntap_osx.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/wire.c b/wire.c index e2f2974..7febcc4 100644 --- a/wire.c +++ b/wire.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 11c61d492756f6f74a593bd0c323cf82978cb8b8 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Thu, 11 Jun 2020 18:05:36 +0545 Subject: [PATCH 17/45] added portable endian code --- portable_endian.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/portable_endian.h b/portable_endian.h index 1b27491..bbabf19 100644 --- a/portable_endian.h +++ b/portable_endian.h @@ -222,5 +222,3 @@ # error platform not supported #endif - -#endif From 67a1cb1792fafb8666f13760b15523ef7c2c8cf0 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Sat, 13 Jun 2020 19:25:39 +0545 Subject: [PATCH 18/45] polished speck --- CMakeLists.txt | 1 + Makefile.in | 1 + edge.c | 8 ++- pearson.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++ pearson.h | 1 + transform_speck.c | 12 ++-- 6 files changed, 151 insertions(+), 9 deletions(-) create mode 100644 pearson.c create mode 100644 pearson.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b5fd37b..a1eb4c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,7 @@ add_library(n2n n2n.c transform_tf.c transform_aes.c random_numbers.c + pearson.c tuntap_freebsd.c tuntap_netbsd.c tuntap_linux.c diff --git a/Makefile.in b/Makefile.in index b231aac..5b5a19d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -51,6 +51,7 @@ N2N_LIB=libn2n.a N2N_OBJS=n2n.o wire.o minilzo.o twofish.o speck.o \ edge_utils.o sn_utils.o \ transform_null.o transform_tf.o transform_aes.o transform_cc20.o transform_speck.o \ + pearson.o \ tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o random_numbers.o \ tuntap_osx.o LIBS_EDGE+=$(LIBS_EDGE_OPT) diff --git a/edge.c b/edge.c index 5b7b84a..8babd45 100644 --- a/edge.c +++ b/edge.c @@ -197,8 +197,7 @@ static void help() { #ifdef HAVE_OPENSSL_1_1 printf("-A4 | Use ChaCha20 for payload encryption. Requires a key.\n"); #endif -// COMING SOON, not yet implemented in setPayloadEncryption(...) -// printf("-A5 | Use Speck for payload encryption. Requires a key.\n"); + printf("-A5 | Use Speck for payload encryption. Requires a key.\n"); printf("-z1 or -z | Enable lzo1x compression for outgoing data packets\n"); #ifdef N2N_HAVE_ZSTD printf("-z2 | Enable zstd compression for outgoing data packets\n"); @@ -283,6 +282,11 @@ static void setPayloadEncryption( n2n_edge_conf_t *conf, int cipher) { break; } #endif + case 5: + { + conf->transop_id = N2N_TRANSFORM_ID_SPECK; + break; + } default: { conf->transop_id = N2N_TRANSFORM_ID_INVAL; diff --git a/pearson.c b/pearson.c new file mode 100644 index 0000000..2ec74bd --- /dev/null +++ b/pearson.c @@ -0,0 +1,137 @@ +#include +#include + +#include "pearson.h" + + +// table as in original paper "Fast Hashing of Variable-Length Text Strings" by Peter K. Pearson +// as published in The Communications of the ACM Vol.33, No. 6 (June 1990), pp. 677-680. +static const uint8_t t[256] ={ + 0x01, 0x57, 0x31, 0x0c, 0xb0, 0xb2, 0x66, 0xa6, 0x79, 0xc1, 0x06, 0x54, 0xf9, 0xe6, 0x2c, 0xa3, + 0x0e, 0xc5, 0xd5, 0xb5, 0xa1, 0x55, 0xda, 0x50, 0x40, 0xef, 0x18, 0xe2, 0xec, 0x8e, 0x26, 0xc8, + 0x6e, 0xb1, 0x68, 0x67, 0x8d, 0xfd, 0xff, 0x32, 0x4d, 0x65, 0x51, 0x12, 0x2d, 0x60, 0x1f, 0xde, + 0x19, 0x6b, 0xbe, 0x46, 0x56, 0xed, 0xf0, 0x22, 0x48, 0xf2, 0x14, 0xd6, 0xf4, 0xe3, 0x95, 0xeb, + 0x61, 0xea, 0x39, 0x16, 0x3c, 0xfa, 0x52, 0xaf, 0xd0, 0x05, 0x7f, 0xc7, 0x6f, 0x3e, 0x87, 0xf8, + 0xae, 0xa9, 0xd3, 0x3a, 0x42, 0x9a, 0x6a, 0xc3, 0xf5, 0xab, 0x11, 0xbb, 0xb6, 0xb3, 0x00, 0xf3, + 0x84, 0x38, 0x94, 0x4b, 0x80, 0x85, 0x9e, 0x64, 0x82, 0x7e, 0x5b, 0x0d, 0x99, 0xf6, 0xd8, 0xdb, + 0x77, 0x44, 0xdf, 0x4e, 0x53, 0x58, 0xc9, 0x63, 0x7a, 0x0b, 0x5c, 0x20, 0x88, 0x72, 0x34, 0x0a, + 0x8a, 0x1e, 0x30, 0xb7, 0x9c, 0x23, 0x3d, 0x1a, 0x8f, 0x4a, 0xfb, 0x5e, 0x81, 0xa2, 0x3f, 0x98, + 0xaa, 0x07, 0x73, 0xa7, 0xf1, 0xce, 0x03, 0x96, 0x37, 0x3b, 0x97, 0xdc, 0x5a, 0x35, 0x17, 0x83, + 0x7d, 0xad, 0x0f, 0xee, 0x4f, 0x5f, 0x59, 0x10, 0x69, 0x89, 0xe1, 0xe0, 0xd9, 0xa0, 0x25, 0x7b, + 0x76, 0x49, 0x02, 0x9d, 0x2e, 0x74, 0x09, 0x91, 0x86, 0xe4, 0xcf, 0xd4, 0xca, 0xd7, 0x45, 0xe5, + 0x1b, 0xbc, 0x43, 0x7c, 0xa8, 0xfc, 0x2a, 0x04, 0x1d, 0x6c, 0x15, 0xf7, 0x13, 0xcd, 0x27, 0xcb, + 0xe9, 0x28, 0xba, 0x93, 0xc6, 0xc0, 0x9b, 0x21, 0xa4, 0xbf, 0x62, 0xcc, 0xa5, 0xb4, 0x75, 0x4c, + 0x8c, 0x24, 0xd2, 0xac, 0x29, 0x36, 0x9f, 0x08, 0xb9, 0xe8, 0x71, 0xc4, 0xe7, 0x2f, 0x92, 0x78, + 0x33, 0x41, 0x1c, 0x90, 0xfe, 0xdd, 0x5d, 0xbd, 0xc2, 0x8b, 0x70, 0x2b, 0x47, 0x6d, 0xb8, 0xd1 }; + +/* +// alternative table as used in RFC 3074 and NOT as in original paper +static const uint8_t t[256] ={ + 0xfb, 0xaf, 0x77, 0xd7, 0x51, 0x0e, 0x4f, 0xbf, 0x67, 0x31, 0xb5, 0x8f, 0xba, 0x9d, 0x00, 0xe8, + 0x1f, 0x20, 0x37, 0x3c, 0x98, 0x3a, 0x11, 0xed, 0xae, 0x46, 0xa0, 0x90, 0xdc, 0x5a, 0x39, 0xdf, + 0x3b, 0x03, 0x12, 0x8c, 0x6f, 0xa6, 0xcb, 0xc4, 0x86, 0xf3, 0x7c, 0x5f, 0xde, 0xb3, 0xc5, 0x41, + 0xb4, 0x30, 0x24, 0x0f, 0x6b, 0x2e, 0xe9, 0x82, 0xa5, 0x1e, 0x7b, 0xa1, 0xd1, 0x17, 0x61, 0x10, + 0x28, 0x5b, 0xdb, 0x3d, 0x64, 0x0a, 0xd2, 0x6d, 0xfa, 0x7f, 0x16, 0x8a, 0x1d, 0x6c, 0xf4, 0x43, + 0xcf, 0x09, 0xb2, 0xcc, 0x4a, 0x62, 0x7e, 0xf9, 0xa7, 0x74, 0x22, 0x4d, 0xc1, 0xc8, 0x79, 0x05, + 0x14, 0x71, 0x47, 0x23, 0x80, 0x0d, 0xb6, 0x5e, 0x19, 0xe2, 0xe3, 0xc7, 0x4b, 0x1b, 0x29, 0xf5, + 0xe6, 0xe0, 0x2b, 0xe1, 0xb1, 0x1a, 0x9b, 0x96, 0xd4, 0x8e, 0xda, 0x73, 0xf1, 0x49, 0x58, 0x69, + 0x27, 0x72, 0x3e, 0xff, 0xc0, 0xc9, 0x91, 0xd6, 0xa8, 0x9e, 0xdd, 0x94, 0x9a, 0x7a, 0x0c, 0x54, + 0x52, 0xa3, 0x2c, 0x8b, 0xe4, 0xec, 0xcd, 0xf2, 0xd9, 0x0b, 0xbb, 0x92, 0x9f, 0x40, 0x56, 0xef, + 0xc3, 0x2a, 0x6a, 0xc6, 0x76, 0x70, 0xb8, 0xac, 0x57, 0x02, 0xad, 0x75, 0xb0, 0xe5, 0xf7, 0xfd, + 0x89, 0xb9, 0x63, 0xa4, 0x66, 0x93, 0x2d, 0x42, 0xe7, 0x34, 0x8d, 0xd3, 0xc2, 0xce, 0xf6, 0xee, + 0x38, 0x6e, 0x4e, 0xf8, 0x3f, 0xf0, 0xbd, 0x5d, 0x5c, 0x33, 0x35, 0xb7, 0x13, 0xab, 0x48, 0x32, + 0x21, 0x68, 0x65, 0x45, 0x08, 0xfc, 0x53, 0x78, 0x4c, 0x87, 0x55, 0x36, 0xca, 0x7d, 0xbc, 0xd5, + 0x60, 0xeb, 0x88, 0xd0, 0xa2, 0x81, 0xbe, 0x84, 0x9c, 0x26, 0x2f, 0x01, 0x07, 0xfe, 0x18, 0x04, + 0xd8, 0x83, 0x59, 0x15, 0x1c, 0x85, 0x25, 0x99, 0x95, 0x50, 0xaa, 0x44, 0x06, 0xa9, 0xea, 0x97 }; */ + + +#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) + + +void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len) { + + /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) + * works faster on well pipelined CPUs than loading the 64-bit value from memory. + * however, there is one advantage to loading from memory: as we also store back to + * memory at the end, we do not need to care about endianess! */ + uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + + uint64_t upper_hash_mask = *(uint64_t*)&upper; + uint64_t lower_hash_mask = *(uint64_t*)&lower; + uint64_t high_upper_hash_mask = upper_hash_mask + 0x1010101010101010; + uint64_t high_lower_hash_mask = lower_hash_mask + 0x1010101010101010; + + uint64_t upper_hash = 0; + uint64_t lower_hash = 0; + uint64_t high_upper_hash = 0; + uint64_t high_lower_hash = 0; + + for (size_t i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint64_t c = (uint8_t)in[i]; + c |= c << 8; + c |= c << 16; + c |= c << 32; + upper_hash ^= c ^ upper_hash_mask; + lower_hash ^= c ^ lower_hash_mask; + high_upper_hash ^= c ^ high_upper_hash_mask; + high_lower_hash ^= c ^ high_lower_hash_mask; + + // table lookup + uint8_t x; + uint64_t h = 0; + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + upper_hash = h; + + h = 0; + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + lower_hash = h; + + h = 0; + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + high_upper_hash = h; + + h = 0; + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + high_lower_hash = h; + } + // store output + uint64_t *o; + o = (uint64_t*)&out[0]; + *o = high_upper_hash; + o = (uint64_t*)&out[8]; + *o = high_lower_hash; + o = (uint64_t*)&out[16]; + *o = upper_hash; + o = (uint64_t*)&out[24]; + *o = lower_hash; +} diff --git a/pearson.h b/pearson.h new file mode 100644 index 0000000..43d1f98 --- /dev/null +++ b/pearson.h @@ -0,0 +1 @@ +void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); diff --git a/transform_speck.c b/transform_speck.c index 093475e..9ae5cd7 100644 --- a/transform_speck.c +++ b/transform_speck.c @@ -20,6 +20,7 @@ #include "n2n_transforms.h" #include "speck.h" #include "random_numbers.h" +#include "pearson.h" #define N2N_SPECK_TRANSFORM_VERSION 1 /* version of the transform encoding */ #define N2N_SPECK_IVEC_SIZE 16 @@ -175,13 +176,10 @@ static int setup_speck_key(transop_speck_t *priv, const uint8_t *key, ssize_t ke /* Clear out any old possibly longer key matter. */ memset(&(priv->ctx), 0, sizeof(speck_context_t) ); - /* TODO: The input key always gets hashed to make a more unpredictable and more complete use of the key space */ - // REVISIT: Hash the key to keymat (formerly used: SHA) - // SHA256(key, key_size, key_mat_buf) - // memcpy (priv->key, key_mat_buf, SHA256_DIGEST_LENGTH); - // ADD: Pearson Hashing - // FOR NOW: USE KEY ITSELF - memcpy (key_mat_buf, key, ((key_size>32)?32:key_size) ); + /* the input key always gets hashed to make a more unpredictable and more complete use of the key space */ + pearson_hash_256 (key_mat_buf, key, key_size); + + /* expand the key material to the context (= round keys) */ speck_expand_key (key_mat_buf, &(priv->ctx)); traceEvent(TRACE_DEBUG, "Speck key setup completed\n"); From 633d6d368782cd43b2e6b637d944fac4b8935673 Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Mon, 15 Jun 2020 15:04:54 +0545 Subject: [PATCH 19/45] indicated source --- pearson.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pearson.c b/pearson.c index 2ec74bd..ca2aa3e 100644 --- a/pearson.c +++ b/pearson.c @@ -1,3 +1,5 @@ +// taken from https://github.com/Logan007/pearson + #include #include From 12e9322a606c7cfc6af3b31ba06a02e8e2987327 Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Wed, 17 Jun 2020 02:47:26 +0545 Subject: [PATCH 20/45] updated pearson.c --- pearson.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pearson.c b/pearson.c index ca2aa3e..e91bd94 100644 --- a/pearson.c +++ b/pearson.c @@ -1,5 +1,7 @@ // taken from https://github.com/Logan007/pearson +// This is free and unencumbered software released into the public domain. + #include #include From 9951a917c70139ddb1e978b6e1e87502b10dcf24 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 17 Jun 2020 06:54:02 +0200 Subject: [PATCH 21/45] Updated (C) --- edge.c | 2 +- edge_utils.c | 2 +- example_edge_embed_quick_edge_init.c | 2 +- n2n.c | 2 +- n2n.h | 2 +- n2n_transforms.h | 2 +- n2n_wire.h | 2 +- pearson.c | 18 ++++++++++++++++++ pearson.h | 18 ++++++++++++++++++ sn.c | 2 +- transform_null.c | 2 +- transform_tf.c | 2 +- tuntap_freebsd.c | 2 +- tuntap_linux.c | 2 +- tuntap_netbsd.c | 2 +- tuntap_osx.c | 2 +- wire.c | 2 +- 17 files changed, 51 insertions(+), 15 deletions(-) diff --git a/edge.c b/edge.c index 8babd45..b15762d 100644 --- a/edge.c +++ b/edge.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/edge_utils.c b/edge_utils.c index 825b8ef..cf2e80e 100644 --- a/edge_utils.c +++ b/edge_utils.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/example_edge_embed_quick_edge_init.c b/example_edge_embed_quick_edge_init.c index ba0eb02..4618059 100644 --- a/example_edge_embed_quick_edge_init.c +++ b/example_edge_embed_quick_edge_init.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n.c b/n2n.c index b3479ce..fe8d39a 100644 --- a/n2n.c +++ b/n2n.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n.h b/n2n.h index 7041fa3..7737213 100644 --- a/n2n.h +++ b/n2n.h @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n_transforms.h b/n2n_transforms.h index 1734ec1..589e36b 100644 --- a/n2n_transforms.h +++ b/n2n_transforms.h @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/n2n_wire.h b/n2n_wire.h index 0a64f4a..7cd0e41 100644 --- a/n2n_wire.h +++ b/n2n_wire.h @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/pearson.c b/pearson.c index e91bd94..0ff0e0d 100644 --- a/pearson.c +++ b/pearson.c @@ -1,3 +1,21 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + // taken from https://github.com/Logan007/pearson // This is free and unencumbered software released into the public domain. diff --git a/pearson.h b/pearson.h index 43d1f98..5e4ca66 100644 --- a/pearson.h +++ b/pearson.h @@ -1 +1,19 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); diff --git a/sn.c b/sn.c index 9d7c26b..8c01a7b 100644 --- a/sn.c +++ b/sn.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/transform_null.c b/transform_null.c index 062ddf2..830bcfa 100644 --- a/transform_null.c +++ b/transform_null.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/transform_tf.c b/transform_tf.c index 412f65f..481e972 100644 --- a/transform_tf.c +++ b/transform_tf.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_freebsd.c b/tuntap_freebsd.c index 7404c95..d871e89 100644 --- a/tuntap_freebsd.c +++ b/tuntap_freebsd.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_linux.c b/tuntap_linux.c index 6e1e770..7a5cbb4 100644 --- a/tuntap_linux.c +++ b/tuntap_linux.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_netbsd.c b/tuntap_netbsd.c index 2d948d9..617e2b2 100644 --- a/tuntap_netbsd.c +++ b/tuntap_netbsd.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/tuntap_osx.c b/tuntap_osx.c index 52a1d28..ef166ff 100644 --- a/tuntap_osx.c +++ b/tuntap_osx.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/wire.c b/wire.c index e2f2974..7febcc4 100644 --- a/wire.c +++ b/wire.c @@ -1,5 +1,5 @@ /** - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 105cc40bd4f1f87887c45687b8535472b2473b46 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 15 Jun 2020 12:53:37 +0545 Subject: [PATCH 22/45] drafted header encryption --- header_encryption.c | 104 +++++++++++++++++++++++++++++++++++++ speck.c | 123 +++++++++++++++++++++++++++++++++++++++----- speck.h | 7 +++ 3 files changed, 221 insertions(+), 13 deletions(-) create mode 100644 header_encryption.c diff --git a/header_encryption.c b/header_encryption.c new file mode 100644 index 0000000..e263cfc --- /dev/null +++ b/header_encryption.c @@ -0,0 +1,104 @@ +#include +#include + +// #include "n2n_wire.h" // n2n_community_t +#include "n2n.h" +#include "speck.h" +#include "portable_endian.h" + + +uint32_t decryt_packet_header (uint8_t packet[], uint8_t packet_len, + char * community_name, speck_ctx * ctx) { + + // assemble IV + // the last four are ASCII "n2n!" and do not get overwritten + uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6E, 0x32, 0x6E, 0x21 }; + // the first 96 bits of the packet are used padded with ASCII "n2n!" + // to full 128 bit IV + memcopy (iv, packet, 12); + + // alternatively, consider: pearson_hash_128 (iv, packet, 12) + + // try community name as possible key and check for magic bytes + uint32_t magic = 0x6E326E00; // ="n2n_" + uint32_t test_magic; + // check for magic bytes and resonable value in header len field + speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, ctx); + test_magic = be32toh (test_magic); + if ( ((test_magic << 8) == magic) + && ((test_magic >> 24) <= packet_len) // (test_masgic >> 24) is header_len + ) { + speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, ctx); + // restore original packet order + memcpy (&packet[0], &packet[16], 4); + memcpy (&packet[4], community_name, N2N_COMMUNITY_SIZE); + return (1); // successful + } else + return (0); // unsuccessful +} + + +int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community *communities) { + + if (packet_len < 20) + return (-1); + + // first, check if header is unenrypted to put it into the fast-lane then + + // the following check is around 99.99962 percent reliable + // it heavily relies on the structure of packet's common part + // changes to wire.c:encode/decode_common need to go together with this code + if ( (packet[19] == (uint8_t)0x00) // null terminated community name + && (packet[00] == N2N_PKT_VERSION) // correct packet version +// && (packet[01] <= N2N_DEFAULT_TTL) // reasonable TTL -- might interfere with hole-punching-related or cli passed higher values ?! + && ((be16toh (*(uint16_t*)&(packet[02])) & N2N_FLAGS_TYPE_MASK ) <= MSG_TYPE_MAX_TYPE ) // message type + && ( be16toh (*(uint16_t*)&(packet[02])) < N2N_FLAGS_OPTIONS) // flags + ) { + + // most probably unencrypted + return (1); + + } else { + + // most probably encrypted + // cycle through the known communities (as keys) to eventually decrypt + int32_t ret; + struct sn_community *c, *tmp; + HASH_ITER (hh, communities, c, tmp) { + // check if this is an encrypted community + if ( ret = decrypt_packet_header (packet, packet_len, c->community, c-> ctx) ) { + // no upgrade from unencrypted to encrypted + if (c->header_encryption == 1) + return (-2); + // set to 'encrypted' + c->header_encryption = 2; + // no need to test any further + return (2); + } + } + // no match + return (-3); + } +} + + +int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, speck_ctx * ctx) { + + if (header_len < 20) + return (-1); + + memcpy (&packet[16], &packet[00], 4); + + uint8_t iv[16]; + ((uint64_t*)iv)[0] = n2n_rand (); + ((uint64_t*)iv)[1] = n2n_rand (); + + const uint32_t magic = 0x006E326E; + ((uint32_t*)iv)[3] = htobe32 (magic); + + iv[12] = header_len; + + speck_he (&packet[12], &packet[12], header_len - 12, iv, ctx); +} diff --git a/speck.c b/speck.c index d9afca5..74a1426 100644 --- a/speck.c +++ b/speck.c @@ -1,4 +1,4 @@ -// cipher SPECK -- 128 bit block size -- 256 bit key size +// cipher SPECK -- 128 bit block size -- 256 bit key size -- CTR mode // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ @@ -565,9 +565,9 @@ int speck_expand_key (const unsigned char *k, speck_context_t *ctx) { #else // plain C ---------------------------------------------------------------- -#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) -#define ROL64(x,r) (((x)<<(r))|((x)>>(64-(r)))) -#define R(x,y,k) (x=ROR64(x,8), x+=y, x^=k, y=ROL64(y,3), y^=x) +#define ROR(x,r) (((x)>>(r))|((x)<<(64-(r)))) +#define ROL(x,r) (((x)<<(r))|((x)>>(64-(r)))) +#define R(x,y,k) (x=ROR(x,8), x+=y, x^=k, y=ROL(y,3), y^=x) static int speck_encrypt (u64 *u, u64 *v, speck_context_t *ctx) { @@ -642,6 +642,85 @@ int speck_expand_key (const unsigned char *k, speck_context_t *ctx) { #endif // AVX, SSE, NEON, plain C ------------------------------------------------ +// cipher SPECK -- 128 bit block size -- 128 bit key size -- CTR mode +// used for header encryption, thus the prefix 'he_' +// for now: just plain C -- AVX, SSE, NEON might follow + +#define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) +#define ROL64(x,r) (((x)<<(r))|((x)>>(64-(r)))) +#define R64(x,y,k) (x=ROR64(x,8), x+=y, x^=k, y=ROL64(y,3), y^=x) + + +static int speck_encrypt_he (u64 *u, u64 *v, speck_context_t *ctx) { + + u64 i, x=*u, y=*v; + + for (i = 0; i < 32; i++) + R64 (x, y, ctx->key[i]); + + *u = x; *v = y; + + return 0; +} + + +int speck_he (unsigned char *out, const unsigned char *in, unsigned long long inlen, + const unsigned char *n, speck_context_t *ctx) { + + u64 i, nonce[2], x, y, t; + unsigned char *block = malloc(16); + + if (!inlen) { + free (block); + return 0; + } + nonce[0] = htole64 ( ((u64*)n)[0] ); + nonce[1] = htole64 ( ((u64*)n)[1] ); + + t = 0; + while (inlen >= 16) { + x = nonce[1]; y = nonce[0]; nonce[0]++; + speck_encrypt_he (&x, &y, ctx); + ((u64 *)out)[1+t] = htole64 (x ^ ((u64 *)in)[1+t]); + ((u64 *)out)[0+t] = htole64 (y ^ ((u64 *)in)[0+t]); + t += 2; + inlen -= 16; + } + + if (inlen > 0) { + x = nonce[1]; y = nonce[0]; + speck_encrypt_he (&x, &y, ctx); + ((u64 *)block)[1] = htole64 (x); ((u64 *)block)[0] = htole64 (y); + for (i = 0; i < inlen; i++) + out[i+8*t] = block[i] ^ in[i+8*t]; + } + + free(block); + return 0; +} + + +int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx) { + + u64 A, B; + u64 i; + + A = htole64 ( ((u64 *)k)[0] ); + B = htole64 ( ((u64 *)k)[1] ); + + for (i = 0; i < 32; i ++) { + ctx->key[i] = A; + R64 ( B, A, i); + } + return 1; +} + + +// code for testing -- to be removed when finished +/* +#include // for testing +#include + int speck_test () { uint8_t key[32] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -649,16 +728,23 @@ int speck_test () { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; - uint8_t iv[16] = { 0x70, 0x6f, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x20, 0x49, 0x6e, 0x20, 0x74, 0x68, 0x6f, 0x73, 0x65 }; + uint8_t xv[16] = { 0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x69, 0x74, + 0x20, 0x65, 0x71, 0x75, 0x69, 0x76, 0x61, 0x6c }; + + uint8_t pt[16] = { 0x00 }; // expected outcome (according to pp. 35 & 36 of Implementation Guide) uint8_t ct[16] = { 0x43, 0x8f, 0x18, 0x9c, 0x8d, 0xb4, 0xee, 0x4e, 0x3e, 0xf5, 0xc0, 0x05, 0x04, 0x01, 0x09, 0x41 }; + uint8_t xt[16] = { 0x18, 0x0d, 0x57, 0x5c, 0xdf, 0xfe, 0x60, 0x78, + 0x65, 0x32, 0x78, 0x79, 0x51, 0x98, 0x5d, 0xa6 }; + + speck_context_t ctx; speck_expand_key (key, &ctx); @@ -667,24 +753,35 @@ int speck_test () { #else speck_ctr (pt, pt, 16, iv, &ctx); #endif + u64 i; - // fprintf (stderr, "rk00: %016llx\n", ctx.key[0]); - // fprintf (stderr, "rk33: %016llx\n", ctx.key[33]); - // fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt); - // fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n"); + fprintf (stderr, "rk00: %016llx\n", ctx.key[0]); + fprintf (stderr, "rk33: %016llx\n", ctx.key[33]); + fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt); + fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n"); int ret = 1; for (i=0; i < 16; i++) if (pt[i] != ct[i]) ret = 0; + memset (pt, 0, 16); + speck_expand_key_he (key, &ctx); + speck_he (pt, pt, 16, xv, &ctx); + + fprintf (stderr, "rk00: %016llx\n", ctx.key[0]); + fprintf (stderr, "rk31: %016llx\n", ctx.key[31]); + fprintf (stderr, "out : %016lx\n", *(uint64_t*)pt); + fprintf (stderr, "mem : " ); for (i=0; i < 16; i++) fprintf (stderr, "%02x ", pt[i]); fprintf (stderr, "\n"); + + for (i=0; i < 16; i++) + if (pt[i] != xt[i]) ret = 0; + return (ret); } -/* -#include // for testing - int main (int argc, char* argv[]) { +int main (int argc, char* argv[]) { fprintf (stdout, "SPECK SELF TEST RESULT: %u\n", speck_test (0,NULL)); - } +} */ diff --git a/speck.h b/speck.h index 18a67b6..3b8cba5 100644 --- a/speck.h +++ b/speck.h @@ -54,3 +54,10 @@ speck_context_t *ctx); int speck_expand_key (const unsigned char *k, speck_context_t *ctx); + + +int speck_he (unsigned char *out, const unsigned char *in, unsigned long long inlen, + const unsigned char *n, speck_context_t *ctx); + + +int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx); From 43feafa1b6587d5592c2761dff8f83dc04faec28 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 13:27:38 +0545 Subject: [PATCH 23/45] prepared header encryption --- CMakeLists.txt | 4 +++ Makefile.in | 2 +- header_encryption.c | 65 ++++++++++++++++++++++++++++----------------- header_encryption.h | 17 ++++++++++++ n2n.h | 8 +++++- pearson.c | 56 ++++++++++++++++++++++++++++++++++++++ pearson.h | 2 ++ speck.h | 7 +++++ 8 files changed, 135 insertions(+), 26 deletions(-) create mode 100644 header_encryption.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a1eb4c6..324bac0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,8 +61,12 @@ add_library(n2n n2n.c transform_null.c transform_tf.c transform_aes.c + transform_cc20.c + transform_speck.c + speck.c random_numbers.c pearson.c + header_encryption.c tuntap_freebsd.c tuntap_netbsd.c tuntap_linux.c diff --git a/Makefile.in b/Makefile.in index 5b5a19d..1bca92c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -51,7 +51,7 @@ N2N_LIB=libn2n.a N2N_OBJS=n2n.o wire.o minilzo.o twofish.o speck.o \ edge_utils.o sn_utils.o \ transform_null.o transform_tf.o transform_aes.o transform_cc20.o transform_speck.o \ - pearson.o \ + header_encryption.o pearson.o \ tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o random_numbers.o \ tuntap_osx.o LIBS_EDGE+=$(LIBS_EDGE_OPT) diff --git a/header_encryption.c b/header_encryption.c index e263cfc..8f7ab97 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -1,35 +1,38 @@ -#include -#include +#include "header_encryption.h" + +#include -// #include "n2n_wire.h" // n2n_community_t #include "n2n.h" -#include "speck.h" +#include "random_numbers.h" +#include "pearson.h" #include "portable_endian.h" -uint32_t decryt_packet_header (uint8_t packet[], uint8_t packet_len, - char * community_name, speck_ctx * ctx) { +#include + + +uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, + char * community_name, he_context_t * ctx) { // assemble IV // the last four are ASCII "n2n!" and do not get overwritten uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6E, 0x32, 0x6E, 0x21 }; - // the first 96 bits of the packet are used padded with ASCII "n2n!" + // the first 96 bits of the packet get padded with ASCII "n2n!" // to full 128 bit IV - memcopy (iv, packet, 12); - - // alternatively, consider: pearson_hash_128 (iv, packet, 12) + memcpy (iv, packet, 12); + // alternatively, consider: pearson_hash_128 (iv, packet, 12); // try community name as possible key and check for magic bytes uint32_t magic = 0x6E326E00; // ="n2n_" uint32_t test_magic; // check for magic bytes and resonable value in header len field - speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, ctx); + speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, (speck_context_t*)ctx); test_magic = be32toh (test_magic); if ( ((test_magic << 8) == magic) && ((test_magic >> 24) <= packet_len) // (test_masgic >> 24) is header_len ) { - speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, ctx); + speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, (speck_context_t*)ctx); // restore original packet order memcpy (&packet[0], &packet[16], 4); memcpy (&packet[4], community_name, N2N_COMMUNITY_SIZE); @@ -39,7 +42,7 @@ uint32_t decryt_packet_header (uint8_t packet[], uint8_t packet_len, } -int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, +int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, struct sn_community *communities) { if (packet_len < 20) @@ -58,8 +61,12 @@ int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, ) { // most probably unencrypted - return (1); + // TODO: + // !!! make sure, no downgrading happens here !!! + // NOT FOR DEFINETLY ENCRYPTED COMMUNITIES / NO DOWNGRADE, NO INJECTION + + return (HEADER_ENCRYPTION_NONE); } else { // most probably encrypted @@ -67,24 +74,23 @@ int32_t decryt_packet_header_if_required (uint8_t packet[], uint16_t packet_len, int32_t ret; struct sn_community *c, *tmp; HASH_ITER (hh, communities, c, tmp) { - // check if this is an encrypted community - if ( ret = decrypt_packet_header (packet, packet_len, c->community, c-> ctx) ) { - // no upgrade from unencrypted to encrypted - if (c->header_encryption == 1) - return (-2); + // skip the definitely unencrypted communities + if (c->header_encryption == HEADER_ENCRYPTION_NONE) + continue; + if ( (ret = packet_header_decrypt (packet, packet_len, c->community, &(c->header_encryption_ctx))) ) { // set to 'encrypted' - c->header_encryption = 2; + c->header_encryption = HEADER_ENCRYPTION_ENABLED; // no need to test any further - return (2); + return (HEADER_ENCRYPTION_ENABLED); } } - // no match + // no matching key/community return (-3); } } -int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, speck_ctx * ctx) { +int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx) { if (header_len < 20) return (-1); @@ -100,5 +106,16 @@ int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, speck_ctx * iv[12] = header_len; - speck_he (&packet[12], &packet[12], header_len - 12, iv, ctx); + speck_he (&packet[12], &packet[12], header_len - 12, iv, (speck_context_t*)ctx); + + return (0); +} + + +void packet_header_setup_key (char * community_name, he_context_t * ctx) { + + uint8_t key[16]; + pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); + + speck_expand_key_he (key, ctx); } diff --git a/header_encryption.h b/header_encryption.h new file mode 100644 index 0000000..f8a31cb --- /dev/null +++ b/header_encryption.h @@ -0,0 +1,17 @@ +#include + +#include "speck.h" +typedef speck_context_t he_context_t; + + +#define HEADER_ENCRYPTION_UNKNOWN 0 +#define HEADER_ENCRYPTION_NONE 1 +#define HEADER_ENCRYPTION_ENABLED 2 + + +uint32_t decrypt_packet_header (uint8_t packet[], uint8_t packet_len, + char * community_name, he_context_t * ctx); + +int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); + +int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); diff --git a/n2n.h b/n2n.h index 7737213..c503bef 100644 --- a/n2n.h +++ b/n2n.h @@ -111,6 +111,7 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include "minilzo.h" +#include "header_encryption.h" #define closesocket(a) close(a) #endif /* #ifndef WIN32 */ @@ -160,6 +161,7 @@ typedef struct tuntap_dev { #define MSG_TYPE_FEDERATION 8 #define MSG_TYPE_PEER_INFO 9 #define MSG_TYPE_QUERY_PEER 10 +#define MSG_TYPE_MAX_TYPE 10 /* N2N compression indicators. */ /* Compression is disabled by default for outgoing packets if no cli @@ -225,6 +227,8 @@ typedef struct n2n_edge_conf { n2n_sn_name_t sn_ip_array[N2N_EDGE_NUM_SUPERNODES]; n2n_route_t *routes; /**< Networks to route through n2n */ n2n_community_t community_name; /**< The community. 16 full octets. */ + uint8_t header_encryption; /**< Header encryption indicator. */ + he_context_t header_encryption_ctx; /**< Header encryption cipher context. */ n2n_transform_t transop_id; /**< The transop to use. */ uint16_t compression; /**< Compress outgoing data packets before encryption */ uint16_t num_routes; /**< Number of routes in routes */ @@ -270,7 +274,9 @@ typedef struct sn_stats struct sn_community { char community[N2N_COMMUNITY_SIZE]; - struct peer_info *edges; /* Link list of registered edges. */ + uint8_t header_encryption; /* Header encryption indicator. */ + he_context_t header_encryption_ctx; /* Header encryption cipher context. */ + struct peer_info *edges; /* Link list of registered edges. */ UT_hash_handle hh; /* makes this structure hashable */ }; diff --git a/pearson.c b/pearson.c index 0ff0e0d..76f7953 100644 --- a/pearson.c +++ b/pearson.c @@ -157,3 +157,59 @@ void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len) { o = (uint64_t*)&out[24]; *o = lower_hash; } + + +void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len) { + + /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) + * works faster on well pipelined CPUs than loading the 64-bit value from memory. + * however, there is one advantage to loading from memory: as we also store back to + * memory at the end, we do not need to care about endianess! */ + uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + + uint64_t upper_hash_mask = *(uint64_t*)&upper; + uint64_t lower_hash_mask = *(uint64_t*)&lower; + + uint64_t upper_hash = 0; + uint64_t lower_hash = 0; + + for (size_t i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint64_t c = (uint8_t)in[i]; + c |= c << 8; + c |= c << 16; + c |= c << 32; + upper_hash ^= c ^ upper_hash_mask; + lower_hash ^= c ^ lower_hash_mask; + // table lookup + uint8_t x; + uint64_t h = 0; + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + upper_hash = h; + + h = 0; + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + lower_hash = h; + } + // store output + uint64_t *o; + o = (uint64_t*)&out[0]; + *o = upper_hash; + o = (uint64_t*)&out[8]; + *o = lower_hash; +} diff --git a/pearson.h b/pearson.h index 5e4ca66..6aaa604 100644 --- a/pearson.h +++ b/pearson.h @@ -17,3 +17,5 @@ */ void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len); + +void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len); diff --git a/speck.h b/speck.h index 3b8cba5..51df36b 100644 --- a/speck.h +++ b/speck.h @@ -2,6 +2,10 @@ // taken from (and modified: removed pure crypto-stream generation and seperated key expansion) // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ + +#ifndef SPECK_H +#define SPECK_H + #define u32 uint32_t #define u64 uint64_t @@ -61,3 +65,6 @@ int speck_he (unsigned char *out, const unsigned char *in, unsigned long long in int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx); + + +#endif From 9a829edb15f396d2b4dd833292af79cb5c505876 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 23:06:06 +0545 Subject: [PATCH 24/45] woke up from a nightmare of missing typedefs --- header_encryption.c | 30 +++++++++++++++++++----------- header_encryption.h | 26 +++++++++++++++++++++----- n2n.h | 26 ++++++++++++++------------ sn_utils.c | 10 +++++++--- speck.c | 1 - speck.h | 1 + 6 files changed, 62 insertions(+), 32 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 8f7ab97..1966819 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -2,13 +2,15 @@ #include -#include "n2n.h" #include "random_numbers.h" #include "pearson.h" #include "portable_endian.h" -#include +#include // !!! + + +#define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, @@ -45,6 +47,9 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, struct sn_community *communities) { + struct sn_community *c, *tmp; + + if (packet_len < 20) return (-1); @@ -62,25 +67,28 @@ int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len // most probably unencrypted - // TODO: - // !!! make sure, no downgrading happens here !!! - // NOT FOR DEFINETLY ENCRYPTED COMMUNITIES / NO DOWNGRADE, NO INJECTION - + // make sure, no downgrading happens here and no unencrypted packets can be + // injected in a community which definitely deals with encrypted headers + HASH_FIND_COMMUNITY(communities, (char *)&packet[04], c); + if (!c) + if (c->header_encryption == HEADER_ENCRYPTION_ENABLED) + return (-2); + // set 'no encryption' in case it is not set yet + c->header_encryption = HEADER_ENCRYPTION_NONE; return (HEADER_ENCRYPTION_NONE); } else { // most probably encrypted // cycle through the known communities (as keys) to eventually decrypt int32_t ret; - struct sn_community *c, *tmp; HASH_ITER (hh, communities, c, tmp) { // skip the definitely unencrypted communities if (c->header_encryption == HEADER_ENCRYPTION_NONE) continue; - if ( (ret = packet_header_decrypt (packet, packet_len, c->community, &(c->header_encryption_ctx))) ) { - // set to 'encrypted' + if ( (ret = packet_header_decrypt (packet, packet_len, c->community, c->header_encryption_ctx)) ) { + // set 'encrypted' in case it is not set yet c->header_encryption = HEADER_ENCRYPTION_ENABLED; - // no need to test any further + // no need to test further communities return (HEADER_ENCRYPTION_ENABLED); } } @@ -117,5 +125,5 @@ void packet_header_setup_key (char * community_name, he_context_t * ctx) { uint8_t key[16]; pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); - speck_expand_key_he (key, ctx); + speck_expand_key_he (key, (speck_context_t*)ctx); } diff --git a/header_encryption.h b/header_encryption.h index f8a31cb..a4395e0 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -1,17 +1,33 @@ + + +#ifndef _HEADER_ENCRYPTION_H_ +#define _HEADER_ENCRYPTION_H_ + + #include - #include "speck.h" -typedef speck_context_t he_context_t; +#include "n2n.h" +//define he_context_t speck_context_t +typedef struct speck_context_t he_context_t; + + +/* Header encryption indicators */ #define HEADER_ENCRYPTION_UNKNOWN 0 #define HEADER_ENCRYPTION_NONE 1 #define HEADER_ENCRYPTION_ENABLED 2 -uint32_t decrypt_packet_header (uint8_t packet[], uint8_t packet_len, +uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, char * community_name, he_context_t * ctx); -int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); -int32_t encryt_packet_header (uint8_t packet[], uint8_t header_len, he_context_t * ctx); +int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community * communities); + + +int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); + + +#endif diff --git a/n2n.h b/n2n.h index c503bef..1cbb6b3 100644 --- a/n2n.h +++ b/n2n.h @@ -111,7 +111,6 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include "minilzo.h" -#include "header_encryption.h" #define closesocket(a) close(a) #endif /* #ifndef WIN32 */ @@ -180,6 +179,9 @@ typedef struct tuntap_dev { bits of transform_id; will be obsolete as soon as compression gets its own field in the packet. REVISIT then. */ +/* forward delcaration of header encryption context, see 'header_encryption.h' */ +typedef struct speck_context_t he_context_t; + #define DEFAULT_MTU 1290 /** Uncomment this to enable the MTU check, then try to ssh to generate a fragmented packet. */ @@ -228,7 +230,7 @@ typedef struct n2n_edge_conf { n2n_route_t *routes; /**< Networks to route through n2n */ n2n_community_t community_name; /**< The community. 16 full octets. */ uint8_t header_encryption; /**< Header encryption indicator. */ - he_context_t header_encryption_ctx; /**< Header encryption cipher context. */ + he_context_t *header_encryption_ctx; /**< Header encryption cipher context. */ n2n_transform_t transop_id; /**< The transop to use. */ uint16_t compression; /**< Compress outgoing data packets before encryption */ uint16_t num_routes; /**< Number of routes in routes */ @@ -259,6 +261,16 @@ typedef struct sn_stats time_t last_reg_super; /* Time when last REGISTER_SUPER was received. */ } sn_stats_t; + struct sn_community +{ + char community[N2N_COMMUNITY_SIZE]; + uint8_t header_encryption; /* Header encryption indicator. */ + he_context_t *header_encryption_ctx; /* Header encryption cipher context. */ + struct peer_info *edges; /* Link list of registered edges. */ + + UT_hash_handle hh; /* makes this structure hashable */ +}; + typedef struct n2n_sn { time_t start_time; /* Used to measure uptime. */ @@ -271,16 +283,6 @@ typedef struct sn_stats struct sn_community *communities; } n2n_sn_t; - struct sn_community -{ - char community[N2N_COMMUNITY_SIZE]; - uint8_t header_encryption; /* Header encryption indicator. */ - he_context_t header_encryption_ctx; /* Header encryption cipher context. */ - struct peer_info *edges; /* Link list of registered edges. */ - - UT_hash_handle hh; /* makes this structure hashable */ -}; - /* ************************************** */ #ifdef __ANDROID_NDK__ diff --git a/sn_utils.c b/sn_utils.c index ed1f85f..95a26b8 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -1,4 +1,5 @@ #include "n2n.h" +#include "header_encryption.h" #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) #define N2N_SN_LPORT_DEFAULT 7654 @@ -37,7 +38,7 @@ static int process_mgmt(n2n_sn_t *sss, static int process_udp(n2n_sn_t *sss, const struct sockaddr_in *sender_sock, - const uint8_t *udp_buf, + uint8_t *udp_buf, size_t udp_size, time_t now); @@ -372,13 +373,14 @@ static int process_mgmt(n2n_sn_t *sss, */ static int process_udp(n2n_sn_t *sss, const struct sockaddr_in *sender_sock, - const uint8_t *udp_buf, + uint8_t *udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; + int8_t he = HEADER_ENCRYPTION_UNKNOWN; size_t msg_type; uint8_t from_supernode; macstr_t mac_buf; @@ -390,6 +392,8 @@ static int process_udp(n2n_sn_t *sss, udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), ntohs(sender_sock->sin_port)); + he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); + /* Use decode_common() to determine the kind of packet then process it: * * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK @@ -781,4 +785,4 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) sn_term(sss); return 0; -} \ No newline at end of file +} diff --git a/speck.c b/speck.c index 74a1426..a5ced78 100644 --- a/speck.c +++ b/speck.c @@ -3,7 +3,6 @@ // https://github.com/nsacyber/simon-speck-supercop/blob/master/crypto_stream/speck128256ctr/ #include -#include #include "portable_endian.h" #include "speck.h" diff --git a/speck.h b/speck.h index 51df36b..a456f77 100644 --- a/speck.h +++ b/speck.h @@ -6,6 +6,7 @@ #ifndef SPECK_H #define SPECK_H +#include #define u32 uint32_t #define u64 uint64_t From 5972f5ddff7b914a4e61a8374ecbfba4d1caed59 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 23:12:51 +0545 Subject: [PATCH 25/45] made header encryption indicator 8-bit type --- header_encryption.c | 4 ++-- header_encryption.h | 4 ++-- sn_utils.c | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 1966819..756d198 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -44,8 +44,8 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, } -int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, - struct sn_community *communities) { +int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community *communities) { struct sn_community *c, *tmp; diff --git a/header_encryption.h b/header_encryption.h index a4395e0..65b9709 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -23,8 +23,8 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, char * community_name, he_context_t * ctx); -int32_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, - struct sn_community * communities); +int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, + struct sn_community * communities); int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); diff --git a/sn_utils.c b/sn_utils.c index 95a26b8..b38e045 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -393,6 +393,8 @@ static int process_udp(n2n_sn_t *sss, ntohs(sender_sock->sin_port)); he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); + if (he < 0) + return -1; /* something wrong with packet decryption */ /* Use decode_common() to determine the kind of packet then process it: * From 2ce891748d3b379232ad09b45159a82d1571fe28 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 16 Jun 2020 23:46:52 +0545 Subject: [PATCH 26/45] new communities have no header encryption --- sn.c | 11 ++++++++++- sn_utils.c | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sn.c b/sn.c index 8c01a7b..60549e3 100644 --- a/sn.c +++ b/sn.c @@ -19,6 +19,7 @@ /* Supernode for n2n-2.x */ #include "n2n.h" +#include "header_encryption.h" #ifdef WIN32 #include @@ -435,13 +436,14 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) { */ static int process_udp(n2n_sn_t * sss, const struct sockaddr_in * sender_sock, - const uint8_t * udp_buf, + uint8_t * udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; + int8_t he = HEADER_ENCRYPTION_UNKNOWN; size_t msg_type; uint8_t from_supernode; macstr_t mac_buf; @@ -453,6 +455,10 @@ static int process_udp(n2n_sn_t * sss, udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), ntohs(sender_sock->sin_port)); + he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); + if (he < 0) + return -1; /* something wrong during packet decryption */ + /* Use decode_common() to determine the kind of packet then process it: * * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK @@ -622,6 +628,9 @@ static int process_udp(n2n_sn_t * sss, if(comm) { strncpy(comm->community, (char*)cmn.community, N2N_COMMUNITY_SIZE-1); comm->community[N2N_COMMUNITY_SIZE-1] = '\0'; + /* new communities introduced by REGISTERs could not have had encrypted header */ + comm->header_encryption = HEADER_ENCRYPTION_NONE; + HASH_ADD_STR(sss->communities, community, comm); traceEvent(TRACE_INFO, "New community: %s", comm->community); diff --git a/sn_utils.c b/sn_utils.c index b38e045..51742f7 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -394,7 +394,7 @@ static int process_udp(n2n_sn_t *sss, he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); if (he < 0) - return -1; /* something wrong with packet decryption */ + return -1; /* something wrong during packet decryption */ /* Use decode_common() to determine the kind of packet then process it: * @@ -577,6 +577,9 @@ static int process_udp(n2n_sn_t *sss, { strncpy(comm->community, (char *)cmn.community, N2N_COMMUNITY_SIZE - 1); comm->community[N2N_COMMUNITY_SIZE - 1] = '\0'; + /* new communities introduced by REGISTERs could not have had encrypted header */ + comm->header_encryption = HEADER_ENCRYPTION_NONE; + HASH_ADD_STR(sss->communities, community, comm); traceEvent(TRACE_INFO, "New community: %s", comm->community); From 2f00b21d439810da46ac7f8a13f8d1a3594d0983 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 17 Jun 2020 01:27:02 +0545 Subject: [PATCH 27/45] having supernode running again (unencryptedly) --- header_encryption.c | 2 ++ header_encryption.h | 14 ++++++++------ sn.c | 13 +++++++++++++ sn_utils.c | 8 +++++++- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 756d198..7866eff 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -75,6 +75,7 @@ int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, return (-2); // set 'no encryption' in case it is not set yet c->header_encryption = HEADER_ENCRYPTION_NONE; + c->header_encryption_ctx = NULL; return (HEADER_ENCRYPTION_NONE); } else { @@ -125,5 +126,6 @@ void packet_header_setup_key (char * community_name, he_context_t * ctx) { uint8_t key[16]; pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); + ctx = calloc(1, sizeof(speck_context_t)); speck_expand_key_he (key, (speck_context_t*)ctx); } diff --git a/header_encryption.h b/header_encryption.h index 65b9709..dec8911 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -1,14 +1,13 @@ - - -#ifndef _HEADER_ENCRYPTION_H_ -#define _HEADER_ENCRYPTION_H_ +//#ifndef _HEADER_ENCRYPTION_H_ +//#define _HEADER_ENCRYPTION_H_ #include -#include "speck.h" #include "n2n.h" +#include "speck.h" + //define he_context_t speck_context_t typedef struct speck_context_t he_context_t; @@ -30,4 +29,7 @@ int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); -#endif +void packet_header_setup_key (char * community_name, he_context_t * ctx); + + +// #endif diff --git a/sn.c b/sn.c index 60549e3..636b3b3 100644 --- a/sn.c +++ b/sn.c @@ -81,6 +81,8 @@ static void deinit_sn(n2n_sn_t * sss) HASH_ITER(hh, sss->communities, community, tmp) { clear_peer_list(&community->edges); + if (NULL != community->header_encryption_ctx) + free (community->header_encryption_ctx); HASH_DEL(sss->communities, community); free(community); } @@ -390,6 +392,8 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) { HASH_ITER(hh, sss->communities, s, tmp) { HASH_DEL(sss->communities, s); + if (NULL != s->header_encryption_ctx) + free (s->header_encryption_ctx); free(s); } @@ -413,7 +417,12 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) { if(s != NULL) { strncpy((char*)s->community, line, N2N_COMMUNITY_SIZE-1); s->community[N2N_COMMUNITY_SIZE-1] = '\0'; + /* we do not know if header encryption is used in this community, + * first packet will show. just in case, setup the key. */ + s->header_encryption = HEADER_ENCRYPTION_UNKNOWN; + packet_header_setup_key (s->community, s->header_encryption_ctx); HASH_ADD_STR(sss->communities, community, s); + num_communities++; traceEvent(TRACE_INFO, "Added allowed community '%s' [total: %u]", (char*)s->community, num_communities); @@ -630,6 +639,7 @@ static int process_udp(n2n_sn_t * sss, comm->community[N2N_COMMUNITY_SIZE-1] = '\0'; /* new communities introduced by REGISTERs could not have had encrypted header */ comm->header_encryption = HEADER_ENCRYPTION_NONE; + comm->header_encryption_ctx = NULL; HASH_ADD_STR(sss->communities, community, comm); @@ -1122,6 +1132,9 @@ static int run_loop(n2n_sn_t * sss) { if((comm->edges == NULL) && (!sss->lock_communities)) { traceEvent(TRACE_INFO, "Purging idle community %s", comm->community); + if (NULL != comm->header_encryption_ctx) + /* this should not happen as no 'locked' and thus only communities w/o encrypted header here */ + free (comm->header_encryption_ctx); HASH_DEL(sss->communities, comm); free(comm); } diff --git a/sn_utils.c b/sn_utils.c index 51742f7..256e3af 100644 --- a/sn_utils.c +++ b/sn_utils.c @@ -226,6 +226,8 @@ void sn_term(n2n_sn_t *sss) HASH_ITER(hh, sss->communities, community, tmp) { clear_peer_list(&community->edges); + if (NULL != community->header_encryption_ctx) + free (community->header_encryption_ctx); HASH_DEL(sss->communities, community); free(community); } @@ -579,6 +581,7 @@ static int process_udp(n2n_sn_t *sss, comm->community[N2N_COMMUNITY_SIZE - 1] = '\0'; /* new communities introduced by REGISTERs could not have had encrypted header */ comm->header_encryption = HEADER_ENCRYPTION_NONE; + comm->header_encryption_ctx = NULL; HASH_ADD_STR(sss->communities, community, comm); @@ -780,7 +783,10 @@ int run_sn_loop(n2n_sn_t *sss, int *keep_running) if ((comm->edges == NULL) && (!sss->lock_communities)) { traceEvent(TRACE_INFO, "Purging idle community %s", comm->community); - HASH_DEL(sss->communities, comm); + if (NULL != comm->header_encryption_ctx) + /* this should not happen as no 'locked' and thus only communities w/o encrypted header here */ + free (comm->header_encryption_ctx); + HASH_DEL(sss->communities, comm); free(comm); } } From 3b95afc469d8905929556eb25b6820a4e3e56df1 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 17 Jun 2020 13:50:50 +0545 Subject: [PATCH 28/45] prepared header encryption --- header_encryption.c | 3 --- header_encryption.h | 9 +-------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 7866eff..7d3184c 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -7,9 +7,6 @@ #include "portable_endian.h" -#include // !!! - - #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) diff --git a/header_encryption.h b/header_encryption.h index dec8911..4fafd0c 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -1,14 +1,10 @@ -//#ifndef _HEADER_ENCRYPTION_H_ -//#define _HEADER_ENCRYPTION_H_ - - #include #include "n2n.h" #include "speck.h" -//define he_context_t speck_context_t + typedef struct speck_context_t he_context_t; @@ -30,6 +26,3 @@ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_ void packet_header_setup_key (char * community_name, he_context_t * ctx); - - -// #endif From 7d11e8f9022801068fde9c85d254b808da4d1a36 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 17 Jun 2020 12:15:16 +0200 Subject: [PATCH 29/45] Added copyright --- header_encryption.c | 18 ++++++++++++++++++ header_encryption.h | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/header_encryption.c b/header_encryption.c index 7d3184c..0da17ef 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -1,3 +1,21 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + #include "header_encryption.h" #include diff --git a/header_encryption.h b/header_encryption.h index 4fafd0c..504b106 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -1,3 +1,21 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + #include From d6103081564651d3f4161a83090db208f4509f5a Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 17 Jun 2020 15:23:00 +0200 Subject: [PATCH 30/45] Compilation fixes on specific platforms (e.g. debian 8) --- pearson.c | 318 +++++++++++++++++++++++++++--------------------------- 1 file changed, 162 insertions(+), 156 deletions(-) diff --git a/pearson.c b/pearson.c index 76f7953..2e5313b 100644 --- a/pearson.c +++ b/pearson.c @@ -29,42 +29,42 @@ // table as in original paper "Fast Hashing of Variable-Length Text Strings" by Peter K. Pearson // as published in The Communications of the ACM Vol.33, No. 6 (June 1990), pp. 677-680. static const uint8_t t[256] ={ - 0x01, 0x57, 0x31, 0x0c, 0xb0, 0xb2, 0x66, 0xa6, 0x79, 0xc1, 0x06, 0x54, 0xf9, 0xe6, 0x2c, 0xa3, - 0x0e, 0xc5, 0xd5, 0xb5, 0xa1, 0x55, 0xda, 0x50, 0x40, 0xef, 0x18, 0xe2, 0xec, 0x8e, 0x26, 0xc8, - 0x6e, 0xb1, 0x68, 0x67, 0x8d, 0xfd, 0xff, 0x32, 0x4d, 0x65, 0x51, 0x12, 0x2d, 0x60, 0x1f, 0xde, - 0x19, 0x6b, 0xbe, 0x46, 0x56, 0xed, 0xf0, 0x22, 0x48, 0xf2, 0x14, 0xd6, 0xf4, 0xe3, 0x95, 0xeb, - 0x61, 0xea, 0x39, 0x16, 0x3c, 0xfa, 0x52, 0xaf, 0xd0, 0x05, 0x7f, 0xc7, 0x6f, 0x3e, 0x87, 0xf8, - 0xae, 0xa9, 0xd3, 0x3a, 0x42, 0x9a, 0x6a, 0xc3, 0xf5, 0xab, 0x11, 0xbb, 0xb6, 0xb3, 0x00, 0xf3, - 0x84, 0x38, 0x94, 0x4b, 0x80, 0x85, 0x9e, 0x64, 0x82, 0x7e, 0x5b, 0x0d, 0x99, 0xf6, 0xd8, 0xdb, - 0x77, 0x44, 0xdf, 0x4e, 0x53, 0x58, 0xc9, 0x63, 0x7a, 0x0b, 0x5c, 0x20, 0x88, 0x72, 0x34, 0x0a, - 0x8a, 0x1e, 0x30, 0xb7, 0x9c, 0x23, 0x3d, 0x1a, 0x8f, 0x4a, 0xfb, 0x5e, 0x81, 0xa2, 0x3f, 0x98, - 0xaa, 0x07, 0x73, 0xa7, 0xf1, 0xce, 0x03, 0x96, 0x37, 0x3b, 0x97, 0xdc, 0x5a, 0x35, 0x17, 0x83, - 0x7d, 0xad, 0x0f, 0xee, 0x4f, 0x5f, 0x59, 0x10, 0x69, 0x89, 0xe1, 0xe0, 0xd9, 0xa0, 0x25, 0x7b, - 0x76, 0x49, 0x02, 0x9d, 0x2e, 0x74, 0x09, 0x91, 0x86, 0xe4, 0xcf, 0xd4, 0xca, 0xd7, 0x45, 0xe5, - 0x1b, 0xbc, 0x43, 0x7c, 0xa8, 0xfc, 0x2a, 0x04, 0x1d, 0x6c, 0x15, 0xf7, 0x13, 0xcd, 0x27, 0xcb, - 0xe9, 0x28, 0xba, 0x93, 0xc6, 0xc0, 0x9b, 0x21, 0xa4, 0xbf, 0x62, 0xcc, 0xa5, 0xb4, 0x75, 0x4c, - 0x8c, 0x24, 0xd2, 0xac, 0x29, 0x36, 0x9f, 0x08, 0xb9, 0xe8, 0x71, 0xc4, 0xe7, 0x2f, 0x92, 0x78, - 0x33, 0x41, 0x1c, 0x90, 0xfe, 0xdd, 0x5d, 0xbd, 0xc2, 0x8b, 0x70, 0x2b, 0x47, 0x6d, 0xb8, 0xd1 }; + 0x01, 0x57, 0x31, 0x0c, 0xb0, 0xb2, 0x66, 0xa6, 0x79, 0xc1, 0x06, 0x54, 0xf9, 0xe6, 0x2c, 0xa3, + 0x0e, 0xc5, 0xd5, 0xb5, 0xa1, 0x55, 0xda, 0x50, 0x40, 0xef, 0x18, 0xe2, 0xec, 0x8e, 0x26, 0xc8, + 0x6e, 0xb1, 0x68, 0x67, 0x8d, 0xfd, 0xff, 0x32, 0x4d, 0x65, 0x51, 0x12, 0x2d, 0x60, 0x1f, 0xde, + 0x19, 0x6b, 0xbe, 0x46, 0x56, 0xed, 0xf0, 0x22, 0x48, 0xf2, 0x14, 0xd6, 0xf4, 0xe3, 0x95, 0xeb, + 0x61, 0xea, 0x39, 0x16, 0x3c, 0xfa, 0x52, 0xaf, 0xd0, 0x05, 0x7f, 0xc7, 0x6f, 0x3e, 0x87, 0xf8, + 0xae, 0xa9, 0xd3, 0x3a, 0x42, 0x9a, 0x6a, 0xc3, 0xf5, 0xab, 0x11, 0xbb, 0xb6, 0xb3, 0x00, 0xf3, + 0x84, 0x38, 0x94, 0x4b, 0x80, 0x85, 0x9e, 0x64, 0x82, 0x7e, 0x5b, 0x0d, 0x99, 0xf6, 0xd8, 0xdb, + 0x77, 0x44, 0xdf, 0x4e, 0x53, 0x58, 0xc9, 0x63, 0x7a, 0x0b, 0x5c, 0x20, 0x88, 0x72, 0x34, 0x0a, + 0x8a, 0x1e, 0x30, 0xb7, 0x9c, 0x23, 0x3d, 0x1a, 0x8f, 0x4a, 0xfb, 0x5e, 0x81, 0xa2, 0x3f, 0x98, + 0xaa, 0x07, 0x73, 0xa7, 0xf1, 0xce, 0x03, 0x96, 0x37, 0x3b, 0x97, 0xdc, 0x5a, 0x35, 0x17, 0x83, + 0x7d, 0xad, 0x0f, 0xee, 0x4f, 0x5f, 0x59, 0x10, 0x69, 0x89, 0xe1, 0xe0, 0xd9, 0xa0, 0x25, 0x7b, + 0x76, 0x49, 0x02, 0x9d, 0x2e, 0x74, 0x09, 0x91, 0x86, 0xe4, 0xcf, 0xd4, 0xca, 0xd7, 0x45, 0xe5, + 0x1b, 0xbc, 0x43, 0x7c, 0xa8, 0xfc, 0x2a, 0x04, 0x1d, 0x6c, 0x15, 0xf7, 0x13, 0xcd, 0x27, 0xcb, + 0xe9, 0x28, 0xba, 0x93, 0xc6, 0xc0, 0x9b, 0x21, 0xa4, 0xbf, 0x62, 0xcc, 0xa5, 0xb4, 0x75, 0x4c, + 0x8c, 0x24, 0xd2, 0xac, 0x29, 0x36, 0x9f, 0x08, 0xb9, 0xe8, 0x71, 0xc4, 0xe7, 0x2f, 0x92, 0x78, + 0x33, 0x41, 0x1c, 0x90, 0xfe, 0xdd, 0x5d, 0xbd, 0xc2, 0x8b, 0x70, 0x2b, 0x47, 0x6d, 0xb8, 0xd1 }; /* // alternative table as used in RFC 3074 and NOT as in original paper static const uint8_t t[256] ={ - 0xfb, 0xaf, 0x77, 0xd7, 0x51, 0x0e, 0x4f, 0xbf, 0x67, 0x31, 0xb5, 0x8f, 0xba, 0x9d, 0x00, 0xe8, - 0x1f, 0x20, 0x37, 0x3c, 0x98, 0x3a, 0x11, 0xed, 0xae, 0x46, 0xa0, 0x90, 0xdc, 0x5a, 0x39, 0xdf, - 0x3b, 0x03, 0x12, 0x8c, 0x6f, 0xa6, 0xcb, 0xc4, 0x86, 0xf3, 0x7c, 0x5f, 0xde, 0xb3, 0xc5, 0x41, - 0xb4, 0x30, 0x24, 0x0f, 0x6b, 0x2e, 0xe9, 0x82, 0xa5, 0x1e, 0x7b, 0xa1, 0xd1, 0x17, 0x61, 0x10, - 0x28, 0x5b, 0xdb, 0x3d, 0x64, 0x0a, 0xd2, 0x6d, 0xfa, 0x7f, 0x16, 0x8a, 0x1d, 0x6c, 0xf4, 0x43, - 0xcf, 0x09, 0xb2, 0xcc, 0x4a, 0x62, 0x7e, 0xf9, 0xa7, 0x74, 0x22, 0x4d, 0xc1, 0xc8, 0x79, 0x05, - 0x14, 0x71, 0x47, 0x23, 0x80, 0x0d, 0xb6, 0x5e, 0x19, 0xe2, 0xe3, 0xc7, 0x4b, 0x1b, 0x29, 0xf5, - 0xe6, 0xe0, 0x2b, 0xe1, 0xb1, 0x1a, 0x9b, 0x96, 0xd4, 0x8e, 0xda, 0x73, 0xf1, 0x49, 0x58, 0x69, - 0x27, 0x72, 0x3e, 0xff, 0xc0, 0xc9, 0x91, 0xd6, 0xa8, 0x9e, 0xdd, 0x94, 0x9a, 0x7a, 0x0c, 0x54, - 0x52, 0xa3, 0x2c, 0x8b, 0xe4, 0xec, 0xcd, 0xf2, 0xd9, 0x0b, 0xbb, 0x92, 0x9f, 0x40, 0x56, 0xef, - 0xc3, 0x2a, 0x6a, 0xc6, 0x76, 0x70, 0xb8, 0xac, 0x57, 0x02, 0xad, 0x75, 0xb0, 0xe5, 0xf7, 0xfd, - 0x89, 0xb9, 0x63, 0xa4, 0x66, 0x93, 0x2d, 0x42, 0xe7, 0x34, 0x8d, 0xd3, 0xc2, 0xce, 0xf6, 0xee, - 0x38, 0x6e, 0x4e, 0xf8, 0x3f, 0xf0, 0xbd, 0x5d, 0x5c, 0x33, 0x35, 0xb7, 0x13, 0xab, 0x48, 0x32, - 0x21, 0x68, 0x65, 0x45, 0x08, 0xfc, 0x53, 0x78, 0x4c, 0x87, 0x55, 0x36, 0xca, 0x7d, 0xbc, 0xd5, - 0x60, 0xeb, 0x88, 0xd0, 0xa2, 0x81, 0xbe, 0x84, 0x9c, 0x26, 0x2f, 0x01, 0x07, 0xfe, 0x18, 0x04, - 0xd8, 0x83, 0x59, 0x15, 0x1c, 0x85, 0x25, 0x99, 0x95, 0x50, 0xaa, 0x44, 0x06, 0xa9, 0xea, 0x97 }; */ +0xfb, 0xaf, 0x77, 0xd7, 0x51, 0x0e, 0x4f, 0xbf, 0x67, 0x31, 0xb5, 0x8f, 0xba, 0x9d, 0x00, 0xe8, +0x1f, 0x20, 0x37, 0x3c, 0x98, 0x3a, 0x11, 0xed, 0xae, 0x46, 0xa0, 0x90, 0xdc, 0x5a, 0x39, 0xdf, +0x3b, 0x03, 0x12, 0x8c, 0x6f, 0xa6, 0xcb, 0xc4, 0x86, 0xf3, 0x7c, 0x5f, 0xde, 0xb3, 0xc5, 0x41, +0xb4, 0x30, 0x24, 0x0f, 0x6b, 0x2e, 0xe9, 0x82, 0xa5, 0x1e, 0x7b, 0xa1, 0xd1, 0x17, 0x61, 0x10, +0x28, 0x5b, 0xdb, 0x3d, 0x64, 0x0a, 0xd2, 0x6d, 0xfa, 0x7f, 0x16, 0x8a, 0x1d, 0x6c, 0xf4, 0x43, +0xcf, 0x09, 0xb2, 0xcc, 0x4a, 0x62, 0x7e, 0xf9, 0xa7, 0x74, 0x22, 0x4d, 0xc1, 0xc8, 0x79, 0x05, +0x14, 0x71, 0x47, 0x23, 0x80, 0x0d, 0xb6, 0x5e, 0x19, 0xe2, 0xe3, 0xc7, 0x4b, 0x1b, 0x29, 0xf5, +0xe6, 0xe0, 0x2b, 0xe1, 0xb1, 0x1a, 0x9b, 0x96, 0xd4, 0x8e, 0xda, 0x73, 0xf1, 0x49, 0x58, 0x69, +0x27, 0x72, 0x3e, 0xff, 0xc0, 0xc9, 0x91, 0xd6, 0xa8, 0x9e, 0xdd, 0x94, 0x9a, 0x7a, 0x0c, 0x54, +0x52, 0xa3, 0x2c, 0x8b, 0xe4, 0xec, 0xcd, 0xf2, 0xd9, 0x0b, 0xbb, 0x92, 0x9f, 0x40, 0x56, 0xef, +0xc3, 0x2a, 0x6a, 0xc6, 0x76, 0x70, 0xb8, 0xac, 0x57, 0x02, 0xad, 0x75, 0xb0, 0xe5, 0xf7, 0xfd, +0x89, 0xb9, 0x63, 0xa4, 0x66, 0x93, 0x2d, 0x42, 0xe7, 0x34, 0x8d, 0xd3, 0xc2, 0xce, 0xf6, 0xee, +0x38, 0x6e, 0x4e, 0xf8, 0x3f, 0xf0, 0xbd, 0x5d, 0x5c, 0x33, 0x35, 0xb7, 0x13, 0xab, 0x48, 0x32, +0x21, 0x68, 0x65, 0x45, 0x08, 0xfc, 0x53, 0x78, 0x4c, 0x87, 0x55, 0x36, 0xca, 0x7d, 0xbc, 0xd5, +0x60, 0xeb, 0x88, 0xd0, 0xa2, 0x81, 0xbe, 0x84, 0x9c, 0x26, 0x2f, 0x01, 0x07, 0xfe, 0x18, 0x04, +0xd8, 0x83, 0x59, 0x15, 0x1c, 0x85, 0x25, 0x99, 0x95, 0x50, 0xaa, 0x44, 0x06, 0xa9, 0xea, 0x97 }; */ #define ROR64(x,r) (((x)>>(r))|((x)<<(64-(r)))) @@ -72,144 +72,150 @@ static const uint8_t t[256] ={ void pearson_hash_256 (uint8_t *out, const uint8_t *in, size_t len) { - /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) - * works faster on well pipelined CPUs than loading the 64-bit value from memory. - * however, there is one advantage to loading from memory: as we also store back to - * memory at the end, we do not need to care about endianess! */ - uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; - uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) + * works faster on well pipelined CPUs than loading the 64-bit value from memory. + * however, there is one advantage to loading from memory: as we also store back to + * memory at the end, we do not need to care about endianess! */ + uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; - uint64_t upper_hash_mask = *(uint64_t*)&upper; - uint64_t lower_hash_mask = *(uint64_t*)&lower; - uint64_t high_upper_hash_mask = upper_hash_mask + 0x1010101010101010; - uint64_t high_lower_hash_mask = lower_hash_mask + 0x1010101010101010; + uint64_t *upper_hash_mask_ptr = (uint64_t*)&upper; + uint64_t *lower_hash_mask_ptr = (uint64_t*)&lower; + uint64_t upper_hash_mask = *upper_hash_mask_ptr; + uint64_t lower_hash_mask = *lower_hash_mask_ptr; + uint64_t high_upper_hash_mask = upper_hash_mask + 0x1010101010101010; + uint64_t high_lower_hash_mask = lower_hash_mask + 0x1010101010101010; - uint64_t upper_hash = 0; - uint64_t lower_hash = 0; - uint64_t high_upper_hash = 0; - uint64_t high_lower_hash = 0; + uint64_t upper_hash = 0; + uint64_t lower_hash = 0; + uint64_t high_upper_hash = 0; + uint64_t high_lower_hash = 0; + size_t i; - for (size_t i = 0; i < len; i++) { - // broadcast the character, xor into hash, make them different permutations - uint64_t c = (uint8_t)in[i]; - c |= c << 8; - c |= c << 16; - c |= c << 32; - upper_hash ^= c ^ upper_hash_mask; - lower_hash ^= c ^ lower_hash_mask; - high_upper_hash ^= c ^ high_upper_hash_mask; - high_lower_hash ^= c ^ high_lower_hash_mask; + for (i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint64_t c = (uint8_t)in[i]; + c |= c << 8; + c |= c << 16; + c |= c << 32; + upper_hash ^= c ^ upper_hash_mask; + lower_hash ^= c ^ lower_hash_mask; + high_upper_hash ^= c ^ high_upper_hash_mask; + high_lower_hash ^= c ^ high_lower_hash_mask; - // table lookup - uint8_t x; - uint64_t h = 0; - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - upper_hash = h; + // table lookup + uint8_t x; + uint64_t h = 0; + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + upper_hash = h; - h = 0; - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - lower_hash = h; + h = 0; + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + lower_hash = h; - h = 0; - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); - high_upper_hash = h; + h = 0; + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_upper_hash; x = t[x]; high_upper_hash >>= 8; h |= x; h=ROR64(h,8); + high_upper_hash = h; - h = 0; - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); - high_lower_hash = h; - } - // store output - uint64_t *o; - o = (uint64_t*)&out[0]; - *o = high_upper_hash; - o = (uint64_t*)&out[8]; - *o = high_lower_hash; - o = (uint64_t*)&out[16]; - *o = upper_hash; - o = (uint64_t*)&out[24]; - *o = lower_hash; + h = 0; + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = high_lower_hash; x = t[x]; high_lower_hash >>= 8; h |= x; h=ROR64(h,8); + high_lower_hash = h; + } + // store output + uint64_t *o; + o = (uint64_t*)&out[0]; + *o = high_upper_hash; + o = (uint64_t*)&out[8]; + *o = high_lower_hash; + o = (uint64_t*)&out[16]; + *o = upper_hash; + o = (uint64_t*)&out[24]; + *o = lower_hash; } void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len) { - /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) - * works faster on well pipelined CPUs than loading the 64-bit value from memory. - * however, there is one advantage to loading from memory: as we also store back to - * memory at the end, we do not need to care about endianess! */ - uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; - uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; + /* initial values - astonishingly, assembling using SHIFTs and ORs (in register) + * works faster on well pipelined CPUs than loading the 64-bit value from memory. + * however, there is one advantage to loading from memory: as we also store back to + * memory at the end, we do not need to care about endianess! */ + uint8_t upper[8] = { 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08 }; + uint8_t lower[8] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; - uint64_t upper_hash_mask = *(uint64_t*)&upper; - uint64_t lower_hash_mask = *(uint64_t*)&lower; + uint64_t *upper_hash_mask_ptr = (uint64_t*)&upper; + uint64_t *lower_hash_mask_ptr = (uint64_t*)&lower; + uint64_t upper_hash_mask = *upper_hash_mask_ptr; + uint64_t lower_hash_mask = *lower_hash_mask_ptr; - uint64_t upper_hash = 0; - uint64_t lower_hash = 0; + uint64_t upper_hash = 0; + uint64_t lower_hash = 0; + size_t i; - for (size_t i = 0; i < len; i++) { - // broadcast the character, xor into hash, make them different permutations - uint64_t c = (uint8_t)in[i]; - c |= c << 8; - c |= c << 16; - c |= c << 32; - upper_hash ^= c ^ upper_hash_mask; - lower_hash ^= c ^ lower_hash_mask; - // table lookup - uint8_t x; - uint64_t h = 0; - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); - upper_hash = h; + for (i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint64_t c = (uint8_t)in[i]; + c |= c << 8; + c |= c << 16; + c |= c << 32; + upper_hash ^= c ^ upper_hash_mask; + lower_hash ^= c ^ lower_hash_mask; + // table lookup + uint8_t x; + uint64_t h = 0; + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + x = upper_hash; x = t[x]; upper_hash >>= 8; h |= x; h=ROR64(h,8); + upper_hash = h; - h = 0; - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); - lower_hash = h; - } - // store output - uint64_t *o; - o = (uint64_t*)&out[0]; - *o = upper_hash; - o = (uint64_t*)&out[8]; - *o = lower_hash; + h = 0; + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + x = lower_hash; x = t[x]; lower_hash >>= 8; h |= x; h=ROR64(h,8); + lower_hash = h; + } + // store output + uint64_t *o; + o = (uint64_t*)&out[0]; + *o = upper_hash; + o = (uint64_t*)&out[8]; + *o = lower_hash; } From 75fd32b48a214acb44d1b0266d629171b57828a6 Mon Sep 17 00:00:00 2001 From: lucaderi Date: Wed, 17 Jun 2020 15:40:07 +0200 Subject: [PATCH 31/45] CentOS 6 compilation fixes --- header_encryption.c | 167 ++++++++++++++++++++++---------------------- header_encryption.h | 3 - 2 files changed, 83 insertions(+), 87 deletions(-) diff --git a/header_encryption.c b/header_encryption.c index 0da17ef..6ce8ab4 100644 --- a/header_encryption.c +++ b/header_encryption.c @@ -31,116 +31,115 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, char * community_name, he_context_t * ctx) { - // assemble IV - // the last four are ASCII "n2n!" and do not get overwritten - uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x6E, 0x32, 0x6E, 0x21 }; - // the first 96 bits of the packet get padded with ASCII "n2n!" - // to full 128 bit IV - memcpy (iv, packet, 12); - // alternatively, consider: pearson_hash_128 (iv, packet, 12); + // assemble IV + // the last four are ASCII "n2n!" and do not get overwritten + uint8_t iv[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6E, 0x32, 0x6E, 0x21 }; + // the first 96 bits of the packet get padded with ASCII "n2n!" + // to full 128 bit IV + memcpy (iv, packet, 12); + // alternatively, consider: pearson_hash_128 (iv, packet, 12); - // try community name as possible key and check for magic bytes - uint32_t magic = 0x6E326E00; // ="n2n_" - uint32_t test_magic; - // check for magic bytes and resonable value in header len field - speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, (speck_context_t*)ctx); - test_magic = be32toh (test_magic); - if ( ((test_magic << 8) == magic) - && ((test_magic >> 24) <= packet_len) // (test_masgic >> 24) is header_len - ) { - speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, (speck_context_t*)ctx); - // restore original packet order - memcpy (&packet[0], &packet[16], 4); - memcpy (&packet[4], community_name, N2N_COMMUNITY_SIZE); - return (1); // successful - } else - return (0); // unsuccessful + // try community name as possible key and check for magic bytes + uint32_t magic = 0x6E326E00; // ="n2n_" + uint32_t test_magic; + // check for magic bytes and resonable value in header len field + speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, (speck_context_t*)ctx); + test_magic = be32toh (test_magic); + if ( ((test_magic << 8) == magic) + && ((test_magic >> 24) <= packet_len) // (test_masgic >> 24) is header_len + ) { + speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, (speck_context_t*)ctx); + // restore original packet order + memcpy (&packet[0], &packet[16], 4); + memcpy (&packet[4], community_name, N2N_COMMUNITY_SIZE); + return (1); // successful + } else + return (0); // unsuccessful } int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, struct sn_community *communities) { - struct sn_community *c, *tmp; + struct sn_community *c, *tmp; - if (packet_len < 20) - return (-1); + if (packet_len < 20) + return (-1); - // first, check if header is unenrypted to put it into the fast-lane then + // first, check if header is unenrypted to put it into the fast-lane then - // the following check is around 99.99962 percent reliable - // it heavily relies on the structure of packet's common part - // changes to wire.c:encode/decode_common need to go together with this code - if ( (packet[19] == (uint8_t)0x00) // null terminated community name - && (packet[00] == N2N_PKT_VERSION) // correct packet version -// && (packet[01] <= N2N_DEFAULT_TTL) // reasonable TTL -- might interfere with hole-punching-related or cli passed higher values ?! - && ((be16toh (*(uint16_t*)&(packet[02])) & N2N_FLAGS_TYPE_MASK ) <= MSG_TYPE_MAX_TYPE ) // message type - && ( be16toh (*(uint16_t*)&(packet[02])) < N2N_FLAGS_OPTIONS) // flags - ) { + // the following check is around 99.99962 percent reliable + // it heavily relies on the structure of packet's common part + // changes to wire.c:encode/decode_common need to go together with this code + if ( (packet[19] == (uint8_t)0x00) // null terminated community name + && (packet[00] == N2N_PKT_VERSION) // correct packet version + // && (packet[01] <= N2N_DEFAULT_TTL) // reasonable TTL -- might interfere with hole-punching-related or cli passed higher values ?! + && ((be16toh (*(uint16_t*)&(packet[02])) & N2N_FLAGS_TYPE_MASK ) <= MSG_TYPE_MAX_TYPE ) // message type + && ( be16toh (*(uint16_t*)&(packet[02])) < N2N_FLAGS_OPTIONS) // flags + ) { - // most probably unencrypted + // most probably unencrypted - // make sure, no downgrading happens here and no unencrypted packets can be - // injected in a community which definitely deals with encrypted headers - HASH_FIND_COMMUNITY(communities, (char *)&packet[04], c); - if (!c) - if (c->header_encryption == HEADER_ENCRYPTION_ENABLED) - return (-2); - // set 'no encryption' in case it is not set yet - c->header_encryption = HEADER_ENCRYPTION_NONE; - c->header_encryption_ctx = NULL; - return (HEADER_ENCRYPTION_NONE); - } else { + // make sure, no downgrading happens here and no unencrypted packets can be + // injected in a community which definitely deals with encrypted headers + HASH_FIND_COMMUNITY(communities, (char *)&packet[04], c); + if (!c) + if (c->header_encryption == HEADER_ENCRYPTION_ENABLED) + return (-2); + // set 'no encryption' in case it is not set yet + c->header_encryption = HEADER_ENCRYPTION_NONE; + c->header_encryption_ctx = NULL; + return (HEADER_ENCRYPTION_NONE); + } else { - // most probably encrypted - // cycle through the known communities (as keys) to eventually decrypt - int32_t ret; - HASH_ITER (hh, communities, c, tmp) { - // skip the definitely unencrypted communities - if (c->header_encryption == HEADER_ENCRYPTION_NONE) - continue; - if ( (ret = packet_header_decrypt (packet, packet_len, c->community, c->header_encryption_ctx)) ) { - // set 'encrypted' in case it is not set yet - c->header_encryption = HEADER_ENCRYPTION_ENABLED; - // no need to test further communities - return (HEADER_ENCRYPTION_ENABLED); - } - } - // no matching key/community - return (-3); - } + // most probably encrypted + // cycle through the known communities (as keys) to eventually decrypt + int32_t ret; + HASH_ITER (hh, communities, c, tmp) { + // skip the definitely unencrypted communities + if (c->header_encryption == HEADER_ENCRYPTION_NONE) + continue; + if ( (ret = packet_header_decrypt (packet, packet_len, c->community, c->header_encryption_ctx)) ) { + // set 'encrypted' in case it is not set yet + c->header_encryption = HEADER_ENCRYPTION_ENABLED; + // no need to test further communities + return (HEADER_ENCRYPTION_ENABLED); + } + } + // no matching key/community + return (-3); + } } int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx) { + uint8_t iv[16]; + uint64_t *iv64 = (uint64_t*)&iv; + const uint32_t magic = 0x006E326E; - if (header_len < 20) - return (-1); + if (header_len < 20) + return (-1); - memcpy (&packet[16], &packet[00], 4); + memcpy (&packet[16], &packet[00], 4); + + iv64[0] = n2n_rand(); + iv64[1] = n2n_rand(); + iv64[3] = htobe32(magic); + iv[12] = header_len; - uint8_t iv[16]; - ((uint64_t*)iv)[0] = n2n_rand (); - ((uint64_t*)iv)[1] = n2n_rand (); + speck_he (&packet[12], &packet[12], header_len - 12, iv, (speck_context_t*)ctx); - const uint32_t magic = 0x006E326E; - ((uint32_t*)iv)[3] = htobe32 (magic); - - iv[12] = header_len; - - speck_he (&packet[12], &packet[12], header_len - 12, iv, (speck_context_t*)ctx); - - return (0); + return (0); } void packet_header_setup_key (char * community_name, he_context_t * ctx) { - uint8_t key[16]; - pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); + uint8_t key[16]; + pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); - ctx = calloc(1, sizeof(speck_context_t)); - speck_expand_key_he (key, (speck_context_t*)ctx); + ctx = calloc(1, sizeof(speck_context_t)); + speck_expand_key_he (key, (speck_context_t*)ctx); } diff --git a/header_encryption.h b/header_encryption.h index 504b106..55b017b 100644 --- a/header_encryption.h +++ b/header_encryption.h @@ -23,9 +23,6 @@ #include "speck.h" -typedef struct speck_context_t he_context_t; - - /* Header encryption indicators */ #define HEADER_ENCRYPTION_UNKNOWN 0 #define HEADER_ENCRYPTION_NONE 1 From 3eb82b2a323d803e9cf2580552fdcefab58827f6 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Sun, 21 Jun 2020 22:26:27 +0200 Subject: [PATCH 32/45] Code reorganization --- Makefile.in | 26 +- configure.seed | 4 +- include/edge_utils_win32.h | 34 + .../header_encryption.h | 8 - lzoconf.h => include/lzoconf.h | 0 lzodefs.h => include/lzodefs.h | 0 minilzo.h => include/minilzo.h | 0 n2n.h => include/n2n.h | 155 ++-- include/n2n_define.h | 94 ++ n2n_transforms.h => include/n2n_transforms.h | 0 n2n_wire.h => include/n2n_wire.h | 0 pearson.h => include/pearson.h | 0 .../portable_endian.h | 0 include/random_numbers.h | 38 + speck.h => include/speck.h | 0 twofish.h => include/twofish.h | 0 uthash.h => include/uthash.h | 0 random_numbers.h | 34 - edge.c => src/edge.c | 6 - edge_utils.c => src/edge_utils.c | 859 ++++++++---------- src/edge_utils_win32.c | 49 + .../example_edge_embed.c | 0 .../example_edge_embed_quick_edge_init.c | 1 - example_sn_embed.c => src/example_sn_embed.c | 0 .../header_encryption.c | 12 +- minilzo.c => src/minilzo.c | 0 n2n.c => src/n2n.c | 0 pearson.c => src/pearson.c | 0 random_numbers.c => src/random_numbers.c | 23 +- sn.c => src/sn.c | 0 sn_utils.c => src/sn_utils.c | 0 speck.c => src/speck.c | 0 transform_aes.c => src/transform_aes.c | 2 - transform_cc20.c => src/transform_cc20.c | 2 - transform_null.c => src/transform_null.c | 0 transform_speck.c => src/transform_speck.c | 4 - transform_tf.c => src/transform_tf.c | 7 - tuntap_freebsd.c => src/tuntap_freebsd.c | 0 tuntap_linux.c => src/tuntap_linux.c | 9 +- tuntap_netbsd.c => src/tuntap_netbsd.c | 0 tuntap_osx.c => src/tuntap_osx.c | 0 twofish.c => src/twofish.c | 8 +- wire.c => src/wire.c | 0 tools/Makefile.in | 4 +- 44 files changed, 712 insertions(+), 667 deletions(-) create mode 100644 include/edge_utils_win32.h rename header_encryption.h => include/header_encryption.h (95%) rename lzoconf.h => include/lzoconf.h (100%) rename lzodefs.h => include/lzodefs.h (100%) rename minilzo.h => include/minilzo.h (100%) rename n2n.h => include/n2n.h (69%) create mode 100644 include/n2n_define.h rename n2n_transforms.h => include/n2n_transforms.h (100%) rename n2n_wire.h => include/n2n_wire.h (100%) rename pearson.h => include/pearson.h (100%) rename portable_endian.h => include/portable_endian.h (100%) create mode 100644 include/random_numbers.h rename speck.h => include/speck.h (100%) rename twofish.h => include/twofish.h (100%) rename uthash.h => include/uthash.h (100%) delete mode 100644 random_numbers.h rename edge.c => src/edge.c (99%) rename edge_utils.c => src/edge_utils.c (77%) create mode 100644 src/edge_utils_win32.c rename example_edge_embed.c => src/example_edge_embed.c (100%) rename example_edge_embed_quick_edge_init.c => src/example_edge_embed_quick_edge_init.c (98%) rename example_sn_embed.c => src/example_sn_embed.c (100%) rename header_encryption.c => src/header_encryption.c (93%) rename minilzo.c => src/minilzo.c (100%) rename n2n.c => src/n2n.c (100%) rename pearson.c => src/pearson.c (100%) rename random_numbers.c => src/random_numbers.c (81%) rename sn.c => src/sn.c (100%) rename sn_utils.c => src/sn_utils.c (100%) rename speck.c => src/speck.c (100%) rename transform_aes.c => src/transform_aes.c (99%) rename transform_cc20.c => src/transform_cc20.c (99%) rename transform_null.c => src/transform_null.c (100%) rename transform_speck.c => src/transform_speck.c (98%) rename transform_tf.c => src/transform_tf.c (97%) rename tuntap_freebsd.c => src/tuntap_freebsd.c (100%) rename tuntap_linux.c => src/tuntap_linux.c (98%) rename tuntap_netbsd.c => src/tuntap_netbsd.c (100%) rename tuntap_osx.c => src/tuntap_osx.c (100%) rename twofish.c => src/twofish.c (99%) rename wire.c => src/wire.c (100%) diff --git a/Makefile.in b/Makefile.in index 1bca92c..f243a8d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -5,10 +5,7 @@ GIT_COMMITS=@GIT_COMMITS@ ######## -CC?=gcc -DEBUG?=-g3 -OPTIMIZATION?=-O3 #-march=native -WARN?=-Wall +CC=@CC@ #Ultrasparc64 users experiencing SIGBUS should try the following gcc options #(thanks to Robert Gibbon) @@ -16,7 +13,7 @@ PLATOPTS_SPARC64=-mcpu=ultrasparc -pipe -fomit-frame-pointer -ffast-math -finlin N2N_OBJS_OPT= LIBS_EDGE_OPT=@N2N_LIBS@ -CFLAGS=@CFLAGS@ +CFLAGS=@CFLAGS@ -I ./include LDFLAGS=@LDFLAGS@ OPENSSL_CFLAGS=$(shell pkg-config openssl; echo $$?) @@ -48,12 +45,9 @@ MAN7DIR=$(MANDIR)/man7 MAN8DIR=$(MANDIR)/man8 N2N_LIB=libn2n.a -N2N_OBJS=n2n.o wire.o minilzo.o twofish.o speck.o \ - edge_utils.o sn_utils.o \ - transform_null.o transform_tf.o transform_aes.o transform_cc20.o transform_speck.o \ - header_encryption.o pearson.o \ - tuntap_freebsd.o tuntap_netbsd.o tuntap_linux.o random_numbers.o \ - tuntap_osx.o +N2N_OBJS=$(patsubst src/%.c, src/%.o, $(wildcard src/*.c)) +N2N_DEPS=$(wildcard include/*.h) $(wildcard src/*.c) Makefile + LIBS_EDGE+=$(LIBS_EDGE_OPT) LIBS_SN= @@ -77,19 +71,19 @@ all: $(APPS) $(DOCS) tools tools: $(N2N_LIB) $(MAKE) -C $@ -edge: edge.c $(N2N_LIB) n2n_wire.h n2n.h Makefile +edge: src/edge.c $(N2N_LIB) $(N2N_DEPS) $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ -supernode: sn.c $(N2N_LIB) n2n.h Makefile +supernode: src/sn.c $(N2N_LIB) $(N2N_DEPS) $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_SN) -o $@ -example_edge_embed_quick_edge_init: example_edge_embed_quick_edge_init.c $(N2N_LIB) n2n.h +example_edge_embed_quick_edge_init: src/example_edge_embed_quick_edge_init.c $(N2N_DEPS) $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ -example_sn_embed: example_sn_embed.c $(N2N_LIB) n2n.h +example_sn_embed: src/example_sn_embed.c $(N2N_DEPS) $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ -example_edge_embed: example_edge_embed.c $(N2N_LIB) n2n.h +example_edge_embed: src/example_edge_embed.c $(N2N_DEPS) $(CC) $(CFLAGS) $< $(LDFLAGS) $(N2N_LIB) $(LIBS_EDGE) -o $@ %.gz : % diff --git a/configure.seed b/configure.seed index db8c933..f26907e 100644 --- a/configure.seed +++ b/configure.seed @@ -15,6 +15,7 @@ fi N2N_LIBS= +AC_PROG_CC([clang]) AC_CHECK_LIB([zstd], [ZSTD_compress]) if test "x$ac_cv_lib_zstd_ZSTD_compress" != xyes; then @@ -92,6 +93,7 @@ fi DATE=`date +"%Y-%m-%d"` +AC_SUBST(CC) AC_SUBST(CFLAGS) AC_SUBST(LDFLAGS) AC_SUBST(N2N_MAJOR) @@ -104,7 +106,7 @@ AC_SUBST(GIT_RELEASE) AC_SUBST(N2N_DEFINES) AC_SUBST(N2N_LIBS) AC_SUBST(ADDITIONAL_TOOLS) -AC_CONFIG_HEADERS(config.h) +AC_CONFIG_HEADERS(include/config.h) AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(tools/Makefile) diff --git a/include/edge_utils_win32.h b/include/edge_utils_win32.h new file mode 100644 index 0000000..e82b50d --- /dev/null +++ b/include/edge_utils_win32.h @@ -0,0 +1,34 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + +#ifdef WIN32 + +#include + +/* Multicast peers discovery disabled due to https://github.com/ntop/n2n/issues/65 */ +#define SKIP_MULTICAST_PEERS_DISCOVERY + +struct tunread_arg { + n2n_edge_t *eee; + int *keep_running; +}; + +extern HANDLE startTunReadThread(struct tunread_arg *arg); + +#endif + diff --git a/header_encryption.h b/include/header_encryption.h similarity index 95% rename from header_encryption.h rename to include/header_encryption.h index 55b017b..6f8bdee 100644 --- a/header_encryption.h +++ b/include/header_encryption.h @@ -16,11 +16,6 @@ * */ -#include - - -#include "n2n.h" -#include "speck.h" /* Header encryption indicators */ @@ -28,15 +23,12 @@ #define HEADER_ENCRYPTION_NONE 1 #define HEADER_ENCRYPTION_ENABLED 2 - uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, char * community_name, he_context_t * ctx); - int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, struct sn_community * communities); - int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); diff --git a/lzoconf.h b/include/lzoconf.h similarity index 100% rename from lzoconf.h rename to include/lzoconf.h diff --git a/lzodefs.h b/include/lzodefs.h similarity index 100% rename from lzodefs.h rename to include/lzodefs.h diff --git a/minilzo.h b/include/minilzo.h similarity index 100% rename from minilzo.h rename to include/minilzo.h diff --git a/n2n.h b/include/n2n.h similarity index 69% rename from n2n.h rename to include/n2n.h index 1cbb6b3..6545143 100644 --- a/n2n.h +++ b/include/n2n.h @@ -64,6 +64,8 @@ #include #include #include +#include +#include #ifndef WIN32 #include @@ -74,6 +76,16 @@ #ifdef __linux__ #define N2N_CAN_NAME_IFACE 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define GRND_NONBLOCK 1 #endif /* #ifdef __linux__ */ #ifdef __FreeBSD__ @@ -83,7 +95,12 @@ #include #include +#if defined (__RDRND__) || defined (__RDSEED__) +#include +#endif + #define ETH_ADDR_LEN 6 + struct ether_hdr { uint8_t dhost[ETH_ADDR_LEN]; @@ -93,10 +110,17 @@ struct ether_hdr typedef struct ether_hdr ether_hdr_t; +#ifdef HAVE_LIBZSTD +#include +#endif + #ifdef __ANDROID_NDK__ #undef N2N_HAVE_DAEMON #undef N2N_HAVE_SETUID #undef N2N_CAN_NAME_IFACE +#include "android/edge_android.h" +#include +#define ARP_PERIOD_INTERVAL (10) /* sec */ #endif /* #ifdef __ANDROID_NDK__ */ #include @@ -106,27 +130,37 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include +#include #include #include +#include #include #include + #include "minilzo.h" +#include "n2n_define.h" #define closesocket(a) close(a) #endif /* #ifndef WIN32 */ #include - #include - #include "uthash.h" +#include "lzoconf.h" #ifdef WIN32 #include "win32/wintap.h" +#include +#else +#include #endif /* #ifdef WIN32 */ #include "n2n_wire.h" #include "n2n_transforms.h" +#include "random_numbers.h" +#include "pearson.h" +#include "portable_endian.h" +#include "speck.h" #ifdef WIN32 #define N2N_IFNAMSIZ 64 @@ -147,43 +181,6 @@ typedef struct tuntap_dev { #define SOCKET int #endif /* #ifndef WIN32 */ -#define QUICKLZ 1 - -/* N2N packet header indicators. */ -#define MSG_TYPE_REGISTER 1 -#define MSG_TYPE_DEREGISTER 2 -#define MSG_TYPE_PACKET 3 -#define MSG_TYPE_REGISTER_ACK 4 -#define MSG_TYPE_REGISTER_SUPER 5 -#define MSG_TYPE_REGISTER_SUPER_ACK 6 -#define MSG_TYPE_REGISTER_SUPER_NAK 7 -#define MSG_TYPE_FEDERATION 8 -#define MSG_TYPE_PEER_INFO 9 -#define MSG_TYPE_QUERY_PEER 10 -#define MSG_TYPE_MAX_TYPE 10 - -/* N2N compression indicators. */ -/* Compression is disabled by default for outgoing packets if no cli - * option is given. All edges are built with decompression support so - * they are able to understand each other (this applies to lzo only). */ -#define N2N_COMPRESSION_ID_NONE 0 /* default, see edge_init_conf_defaults(...) in edge_utils.c */ -#define N2N_COMPRESSION_ID_LZO 1 /* set if '-z1' or '-z' cli option is present, see setOption(...) in edge.c */ -#ifdef N2N_HAVE_ZSTD -#define N2N_COMPRESSION_ID_ZSTD 2 /* set if '-z2' cli option is present, available only if compiled with zstd lib */ -#define ZSTD_COMPRESSION_LEVEL 7 /* 1 (faster) ... 22 (more compression) */ -#endif -// with the next major packet structure update, make '0' = invalid, and '1' = no compression -// '2' = LZO, '3' = ZSTD, ... REVISIT then (also: change all occurences in source). - -#define N2N_COMPRESSION_ID_BITLEN 3 /* number of bits used for encoding compression id in the uppermost - bits of transform_id; will be obsolete as soon as compression gets - its own field in the packet. REVISIT then. */ - -/* forward delcaration of header encryption context, see 'header_encryption.h' */ -typedef struct speck_context_t he_context_t; - -#define DEFAULT_MTU 1290 - /** Uncomment this to enable the MTU check, then try to ssh to generate a fragmented packet. */ /** NOTE: see doc/MTU.md for an explanation on the 1400 value */ //#define MTU_ASSERT_VALUE 1400 @@ -206,17 +203,7 @@ struct peer_info { UT_hash_handle hh; /* makes this structure hashable */ }; -#define HASH_ADD_PEER(head,add) \ - HASH_ADD(hh,head,mac_addr,sizeof(n2n_mac_t),add) -#define HASH_FIND_PEER(head,mac,out) \ - HASH_FIND(hh,head,mac,sizeof(n2n_mac_t),out) -#define N2N_EDGE_SN_HOST_SIZE 48 -#define N2N_EDGE_NUM_SUPERNODES 2 -#define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */ -#define N2N_PATHNAME_MAXLEN 256 -#define N2N_EDGE_MGMT_PORT 5644 - - +typedef struct speck_context_t he_context_t; typedef char n2n_sn_name_t[N2N_EDGE_SN_HOST_SIZE]; typedef struct n2n_route { @@ -252,39 +239,42 @@ typedef struct n2n_edge n2n_edge_t; /* Opaque, see edge_utils.c */ typedef struct sn_stats { - size_t errors; /* Number of errors encountered. */ - size_t reg_super; /* Number of REGISTER_SUPER requests received. */ - size_t reg_super_nak; /* Number of REGISTER_SUPER requests declined. */ - size_t fwd; /* Number of messages forwarded. */ - size_t broadcast; /* Number of messages broadcast to a community. */ - time_t last_fwd; /* Time when last message was forwarded. */ - time_t last_reg_super; /* Time when last REGISTER_SUPER was received. */ + size_t errors; /* Number of errors encountered. */ + size_t reg_super; /* Number of REGISTER_SUPER requests received. */ + size_t reg_super_nak; /* Number of REGISTER_SUPER requests declined. */ + size_t fwd; /* Number of messages forwarded. */ + size_t broadcast; /* Number of messages broadcast to a community. */ + time_t last_fwd; /* Time when last message was forwarded. */ + time_t last_reg_super; /* Time when last REGISTER_SUPER was received. */ } sn_stats_t; - struct sn_community +struct sn_community { - char community[N2N_COMMUNITY_SIZE]; - uint8_t header_encryption; /* Header encryption indicator. */ - he_context_t *header_encryption_ctx; /* Header encryption cipher context. */ - struct peer_info *edges; /* Link list of registered edges. */ + char community[N2N_COMMUNITY_SIZE]; + uint8_t header_encryption; /* Header encryption indicator. */ + he_context_t *header_encryption_ctx; /* Header encryption cipher context. */ + struct peer_info *edges; /* Link list of registered edges. */ - UT_hash_handle hh; /* makes this structure hashable */ + UT_hash_handle hh; /* makes this structure hashable */ }; - typedef struct n2n_sn +typedef struct n2n_sn { - time_t start_time; /* Used to measure uptime. */ - sn_stats_t stats; - int daemon; /* If non-zero then daemonise. */ - uint16_t lport; /* Local UDP port to bind to. */ - int sock; /* Main socket for UDP traffic with edges. */ - int mgmt_sock; /* management socket. */ - int lock_communities; /* If true, only loaded communities can be used. */ - struct sn_community *communities; + time_t start_time; /* Used to measure uptime. */ + sn_stats_t stats; + int daemon; /* If non-zero then daemonise. */ + uint16_t lport; /* Local UDP port to bind to. */ + int sock; /* Main socket for UDP traffic with edges. */ + int mgmt_sock; /* management socket. */ + int lock_communities; /* If true, only loaded communities can be used. */ + struct sn_community *communities; } n2n_sn_t; /* ************************************** */ +#include "header_encryption.h" +#include "twofish.h" + #ifdef __ANDROID_NDK__ #include #endif /* #ifdef __ANDROID_NDK__ */ @@ -298,21 +288,6 @@ typedef struct sn_stats /* ************************************** */ -#define SUPERNODE_IP "127.0.0.1" -#define SUPERNODE_PORT 1234 - -/* ************************************** */ - -#ifndef max -#define max(a, b) ((a < b) ? b : a) -#endif - -#ifndef min -#define min(a, b) ((a > b) ? b : a) -#endif - -/* ************************************** */ - /* Transop Init Functions */ int n2n_transop_null_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_twofish_init(const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); @@ -333,7 +308,7 @@ void traceEvent(int eventTraceLevel, char* file, int line, char * format, ...); /* Tuntap API */ int tuntap_open(tuntap_dev *device, char *dev, const char *address_mode, char *device_ip, - char *device_mask, const char * device_mac, int mtu); + char *device_mask, const char * device_mac, int mtu); int tuntap_read(struct tuntap_dev *tuntap, unsigned char *buf, int len); int tuntap_write(struct tuntap_dev *tuntap, unsigned char *buf, int len); void tuntap_close(struct tuntap_dev *tuntap); @@ -352,10 +327,10 @@ void print_edge_stats(const n2n_edge_t *eee); /* Sockets */ char* sock_to_cstr( n2n_sock_str_t out, - const n2n_sock_t * sock ); + const n2n_sock_t * sock ); SOCKET open_socket(int local_port, int bind_any); int sock_equal( const n2n_sock_t * a, - const n2n_sock_t * b ); + const n2n_sock_t * b ); /* Operations on peer_info lists. */ size_t purge_peer_list( struct peer_info ** peer_list, diff --git a/include/n2n_define.h b/include/n2n_define.h new file mode 100644 index 0000000..f56297a --- /dev/null +++ b/include/n2n_define.h @@ -0,0 +1,94 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + +#define QUICKLZ 1 + +/* N2N packet header indicators. */ +#define MSG_TYPE_REGISTER 1 +#define MSG_TYPE_DEREGISTER 2 +#define MSG_TYPE_PACKET 3 +#define MSG_TYPE_REGISTER_ACK 4 +#define MSG_TYPE_REGISTER_SUPER 5 +#define MSG_TYPE_REGISTER_SUPER_ACK 6 +#define MSG_TYPE_REGISTER_SUPER_NAK 7 +#define MSG_TYPE_FEDERATION 8 +#define MSG_TYPE_PEER_INFO 9 +#define MSG_TYPE_QUERY_PEER 10 +#define MSG_TYPE_MAX_TYPE 10 + +#define SOCKET_TIMEOUT_INTERVAL_SECS 10 +#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec, usually UDP NAT entries in a firewall expire after 30 seconds */ + +#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ +#define TRANSOP_TICK_INTERVAL (10) /* sec */ + +#define ETH_FRAMESIZE 14 +#define IP4_SRCOFFSET 12 +#define IP4_DSTOFFSET 16 +#define IP4_MIN_SIZE 20 +#define UDP_SIZE 8 + +/* heap allocation for compression as per lzo example doc */ +#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] +static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); + + +/* N2N compression indicators. */ +/* Compression is disabled by default for outgoing packets if no cli + * option is given. All edges are built with decompression support so + * they are able to understand each other (this applies to lzo only). */ +#define N2N_COMPRESSION_ID_NONE 0 /* default, see edge_init_conf_defaults(...) in edge_utils.c */ +#define N2N_COMPRESSION_ID_LZO 1 /* set if '-z1' or '-z' cli option is present, see setOption(...) in edge.c */ +#ifdef N2N_HAVE_ZSTD +#define N2N_COMPRESSION_ID_ZSTD 2 /* set if '-z2' cli option is present, available only if compiled with zstd lib */ +#define ZSTD_COMPRESSION_LEVEL 7 /* 1 (faster) ... 22 (more compression) */ +#endif +// with the next major packet structure update, make '0' = invalid, and '1' = no compression +// '2' = LZO, '3' = ZSTD, ... REVISIT then (also: change all occurences in source). + +#define N2N_COMPRESSION_ID_BITLEN 3 /* number of bits used for encoding compression id in the uppermost + bits of transform_id; will be obsolete as soon as compression gets + its own field in the packet. REVISIT then. */ + +#define DEFAULT_MTU 1290 + +#define HASH_ADD_PEER(head,add) \ + HASH_ADD(hh,head,mac_addr,sizeof(n2n_mac_t),add) +#define HASH_FIND_PEER(head,mac,out) \ + HASH_FIND(hh,head,mac,sizeof(n2n_mac_t),out) +#define N2N_EDGE_SN_HOST_SIZE 48 +#define N2N_EDGE_NUM_SUPERNODES 2 +#define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */ +#define N2N_PATHNAME_MAXLEN 256 +#define N2N_EDGE_MGMT_PORT 5644 + +/* ************************************** */ + +#define SUPERNODE_IP "127.0.0.1" +#define SUPERNODE_PORT 1234 + +/* ************************************** */ + +#ifndef max +#define max(a, b) ((a < b) ? b : a) +#endif + +#ifndef min +#define min(a, b) ((a > b) ? b : a) +#endif + diff --git a/n2n_transforms.h b/include/n2n_transforms.h similarity index 100% rename from n2n_transforms.h rename to include/n2n_transforms.h diff --git a/n2n_wire.h b/include/n2n_wire.h similarity index 100% rename from n2n_wire.h rename to include/n2n_wire.h diff --git a/pearson.h b/include/pearson.h similarity index 100% rename from pearson.h rename to include/pearson.h diff --git a/portable_endian.h b/include/portable_endian.h similarity index 100% rename from portable_endian.h rename to include/portable_endian.h diff --git a/include/random_numbers.h b/include/random_numbers.h new file mode 100644 index 0000000..6271163 --- /dev/null +++ b/include/random_numbers.h @@ -0,0 +1,38 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + +/* The WIN32 code is still untested and thus commented + #if defined (WIN32) + #include + #endif +*/ + +struct rn_generator_state_t { + uint64_t a, b; +}; + +struct splitmix64_state_t { + uint64_t s; +}; + + +int n2n_srand (uint64_t seed); + +uint64_t n2n_rand (); + +uint64_t n2n_seed (); diff --git a/speck.h b/include/speck.h similarity index 100% rename from speck.h rename to include/speck.h diff --git a/twofish.h b/include/twofish.h similarity index 100% rename from twofish.h rename to include/twofish.h diff --git a/uthash.h b/include/uthash.h similarity index 100% rename from uthash.h rename to include/uthash.h diff --git a/random_numbers.h b/random_numbers.h deleted file mode 100644 index aa0b0a0..0000000 --- a/random_numbers.h +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include - - -#if defined (__linux__) - #include - #include - #define GRND_NONBLOCK 1 -#endif - -#if defined (__RDRND__) || defined (__RDSEED__) - #include -#endif - -/* The WIN32 code is still untested and thus commented -#if defined (WIN32) - #include -#endif */ - - -struct rn_generator_state_t { - uint64_t a, b; -}; - -struct splitmix64_state_t { - uint64_t s; -}; - - -int n2n_srand (uint64_t seed); - -uint64_t n2n_rand (); - -uint64_t n2n_seed (); diff --git a/edge.c b/src/edge.c similarity index 99% rename from edge.c rename to src/edge.c index b15762d..9000a41 100644 --- a/edge.c +++ b/src/edge.c @@ -17,12 +17,6 @@ */ #include "n2n.h" -#include "random_numbers.h" -#ifdef WIN32 -#include -#else -#include -#endif #define N2N_NETMASK_STR_SIZE 16 /* dotted decimal 12 numbers + 3 dots */ #define N2N_MACNAMSIZ 18 /* AA:BB:CC:DD:EE:FF + NULL*/ diff --git a/edge_utils.c b/src/edge_utils.c similarity index 77% rename from edge_utils.c rename to src/edge_utils.c index ddea110..f4487c6 100644 --- a/edge_utils.c +++ b/src/edge_utils.c @@ -17,67 +17,24 @@ */ #include "n2n.h" -#include "lzoconf.h" -#include "random_numbers.h" - -#ifdef HAVE_LIBZSTD -#include -#endif - -#ifdef WIN32 -#include -/* Multicast peers discovery disabled due to https://github.com/ntop/n2n/issues/65 */ -#define SKIP_MULTICAST_PEERS_DISCOVERY -#endif - -#ifdef __ANDROID_NDK__ -#include "android/edge_android.h" -#include -#endif /* __ANDROID_NDK__ */ - - -#define SOCKET_TIMEOUT_INTERVAL_SECS 10 -#define REGISTER_SUPER_INTERVAL_DFL 20 /* sec, usually UDP NAT entries in a firewall expire after 30 seconds */ - -#define IFACE_UPDATE_INTERVAL (30) /* sec. How long it usually takes to get an IP lease. */ -#define TRANSOP_TICK_INTERVAL (10) /* sec */ - -#ifdef __ANDROID_NDK__ -#define ARP_PERIOD_INTERVAL (10) /* sec */ -#endif - -#ifdef __linux__ -#include -#include -#endif - -#define ETH_FRAMESIZE 14 -#define IP4_SRCOFFSET 12 -#define IP4_DSTOFFSET 16 -#define IP4_MIN_SIZE 20 -#define UDP_SIZE 8 - -/* heap allocation for compression as per lzo example doc */ -#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] -static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); /* ************************************** */ static const char * supernode_ip(const n2n_edge_t * eee); static void send_register(n2n_edge_t *eee, const n2n_sock_t *remote_peer, const n2n_mac_t peer_mac); static void check_peer_registration_needed(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer); + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer); static int edge_init_sockets(n2n_edge_t *eee, int udp_local_port, int mgmt_port, uint8_t tos); static int edge_init_routes(n2n_edge_t *eee, n2n_route_t *routes, uint16_t num_routes); static void edge_cleanup_routes(n2n_edge_t *eee); static int supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn); static void check_known_peer_sock_change(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer, - time_t when); + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer, + time_t when); /* ************************************** */ @@ -184,16 +141,16 @@ static int is_ethMulticast(const void * buf, size_t bufsize) { /* Match 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF */ if(bufsize >= sizeof(ether_hdr_t)) { - /* copy to aligned memory */ - ether_hdr_t eh; - memcpy(&eh, buf, sizeof(ether_hdr_t)); + /* copy to aligned memory */ + ether_hdr_t eh; + memcpy(&eh, buf, sizeof(ether_hdr_t)); - if((0x01 == eh.dhost[0]) && - (0x00 == eh.dhost[1]) && - (0x5E == eh.dhost[2]) && - (0 == (0x80 & eh.dhost[3]))) - retval = 1; /* This is an ethernet multicast packet [RFC1112]. */ - } + if((0x01 == eh.dhost[0]) && + (0x00 == eh.dhost[1]) && + (0x5E == eh.dhost[2]) && + (0 == (0x80 & eh.dhost[3]))) + retval = 1; /* This is an ethernet multicast packet [RFC1112]. */ + } return retval; } @@ -207,14 +164,14 @@ static int is_ip6_discovery(const void * buf, size_t bufsize) { int retval = 0; if(bufsize >= sizeof(ether_hdr_t)) { - /* copy to aligned memory */ - ether_hdr_t eh; + /* copy to aligned memory */ + ether_hdr_t eh; - memcpy(&eh, buf, sizeof(ether_hdr_t)); + memcpy(&eh, buf, sizeof(ether_hdr_t)); - if((0x33 == eh.dhost[0]) && (0x33 == eh.dhost[1])) - retval = 1; /* This is an IPv6 multicast packet [RFC2464]. */ - } + if((0x33 == eh.dhost[0]) && (0x33 == eh.dhost[1])) + retval = 1; /* This is an IPv6 multicast packet [RFC2464]. */ + } return retval; } @@ -306,11 +263,11 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r goto edge_init_error; } -//edge_init_success: + //edge_init_success: *rv = 0; return(eee); -edge_init_error: + edge_init_error: if(eee) free(eee); *rv = rc; @@ -377,49 +334,49 @@ static int supernode2addr(n2n_sock_t * sn, const n2n_sn_name_t addrIn) { supernode_host = strtok(addr, ":"); if(supernode_host) { - in_addr_t sn_addr; - char *supernode_port = strtok(NULL, ":"); - const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; - struct addrinfo * ainfo = NULL; - int nameerr; + in_addr_t sn_addr; + char *supernode_port = strtok(NULL, ":"); + const struct addrinfo aihints = {0, PF_INET, 0, 0, 0, NULL, NULL, NULL}; + struct addrinfo * ainfo = NULL; + int nameerr; - if(supernode_port) - sn->port = atoi(supernode_port); - else - traceEvent(TRACE_WARNING, "Bad supernode parameter (-l ) %s %s:%s", - addr, supernode_host, supernode_port); + if(supernode_port) + sn->port = atoi(supernode_port); + else + traceEvent(TRACE_WARNING, "Bad supernode parameter (-l ) %s %s:%s", + addr, supernode_host, supernode_port); - nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo); + nameerr = getaddrinfo(supernode_host, NULL, &aihints, &ainfo); - if(0 == nameerr) - { - struct sockaddr_in * saddr; + if(0 == nameerr) + { + struct sockaddr_in * saddr; - /* ainfo s the head of a linked list if non-NULL. */ - if(ainfo && (PF_INET == ainfo->ai_family)) - { - /* It is definitely and IPv4 address -> sockaddr_in */ - saddr = (struct sockaddr_in *)ainfo->ai_addr; + /* ainfo s the head of a linked list if non-NULL. */ + if(ainfo && (PF_INET == ainfo->ai_family)) + { + /* It is definitely and IPv4 address -> sockaddr_in */ + saddr = (struct sockaddr_in *)ainfo->ai_addr; - memcpy(sn->addr.v4, &(saddr->sin_addr.s_addr), IPV4_SIZE); - sn->family=AF_INET; - } - else - { - /* Should only return IPv4 addresses due to aihints. */ - traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); - rv = -1; - } + memcpy(sn->addr.v4, &(saddr->sin_addr.s_addr), IPV4_SIZE); + sn->family=AF_INET; + } + else + { + /* Should only return IPv4 addresses due to aihints. */ + traceEvent(TRACE_WARNING, "Failed to resolve supernode IPv4 address for %s", supernode_host); + rv = -1; + } - freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ - ainfo = NULL; - } else { - traceEvent(TRACE_WARNING, "Failed to resolve supernode host %s, assuming numeric", supernode_host); - sn_addr = inet_addr(supernode_host); /* uint32_t */ - memcpy(sn->addr.v4, &(sn_addr), IPV4_SIZE); - sn->family=AF_INET; - rv = -2; - } + freeaddrinfo(ainfo); /* free everything allocated by getaddrinfo(). */ + ainfo = NULL; + } else { + traceEvent(TRACE_WARNING, "Failed to resolve supernode host %s, assuming numeric", supernode_host); + sn_addr = inet_addr(supernode_host); /* uint32_t */ + memcpy(sn->addr.v4, &(sn_addr), IPV4_SIZE); + sn->family=AF_INET; + rv = -2; + } } else { traceEvent(TRACE_WARNING, "Wrong supernode parameter (-l )"); @@ -440,7 +397,7 @@ static void register_with_local_peers(n2n_edge_t * eee) { if(eee->multicast_joined && eee->conf.allow_p2p) { /* send registration to the local multicast group */ traceEvent(TRACE_DEBUG, "Registering with multicast group %s:%u", - N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT); + N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT); send_register(eee, &(eee->multicast_peer), NULL); } #else @@ -464,9 +421,9 @@ static void register_with_local_peers(n2n_edge_t * eee) { * Called from the main loop when Rx a packet for our device mac. */ static void register_with_new_peer(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer) { + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer) { /* REVISIT: purge of pending_peers not yet done. */ struct peer_info * scan; macstr_t mac_buf; @@ -494,7 +451,7 @@ static void register_with_new_peer(n2n_edge_t * eee, /* trace Sending REGISTER */ if(from_supernode) { - /* UDP NAT hole punching through supernode. Send to peer first(punch local UDP hole) + /* UDP NAT hole punching through supernode. Send to peer first(punch local UDP hole) * and then ask supernode to forward. Supernode then ask peer to ack. Some nat device * drop and block ports with incoming UDP packet if out-come traffic does not exist. * So we can alternatively set TTL so that the packet sent to peer never really reaches @@ -514,12 +471,12 @@ static void register_with_new_peer(n2n_edge_t * eee, getsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, (void *)(char *)&curTTL, &lenTTL); setsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, - (void *)(char *)&eee->conf.register_ttl, - sizeof(eee->conf.register_ttl)); + (void *)(char *)&eee->conf.register_ttl, + sizeof(eee->conf.register_ttl)); for (; alter > 0; alter--, sock.port++) - { - send_register(eee, &sock, mac); - } + { + send_register(eee, &sock, mac); + } setsockopt(eee->udp_sock, IPPROTO_IP, IP_TTL, (void *)(char *)&curTTL, sizeof(curTTL)); #endif } else { /* eee->conf.register_ttl <= 0 */ @@ -541,9 +498,9 @@ static void register_with_new_peer(n2n_edge_t * eee, /** Update the last_seen time for this peer, or get registered. */ static void check_peer_registration_needed(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer) { + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer) { struct peer_info *scan; HASH_FIND_PEER(eee->known_peers, mac, scan); @@ -572,9 +529,9 @@ static void check_peer_registration_needed(n2n_edge_t * eee, * peer must be a pointer to an element of the pending_peers list. */ static void peer_set_p2p_confirmed(n2n_edge_t * eee, - const n2n_mac_t mac, - const n2n_sock_t * peer, - time_t now) { + const n2n_mac_t mac, + const n2n_sock_t * peer, + time_t now) { struct peer_info *scan; macstr_t mac_buf; n2n_sock_str_t sockbuf; @@ -591,8 +548,8 @@ static void peer_set_p2p_confirmed(n2n_edge_t * eee, scan->last_p2p = now; traceEvent(TRACE_NORMAL, "P2P connection established: %s [%s]", - macaddr_str(mac_buf, mac), - sock_to_cstr(sockbuf, peer)); + macaddr_str(mac_buf, mac), + sock_to_cstr(sockbuf, peer)); traceEvent(TRACE_DEBUG, "=== new peer %s -> %s", macaddr_str(mac_buf, scan->mac_addr), @@ -646,10 +603,10 @@ static n2n_mac_t broadcast_mac = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; /** Check if a known peer socket has changed and possibly register again. */ static void check_known_peer_sock_change(n2n_edge_t * eee, - uint8_t from_supernode, - const n2n_mac_t mac, - const n2n_sock_t * peer, - time_t when) { + uint8_t from_supernode, + const n2n_mac_t mac, + const n2n_sock_t * peer, + time_t when) { struct peer_info *scan; n2n_sock_str_t sockbuf1; n2n_sock_str_t sockbuf2; /* don't clobber sockbuf1 if writing two addresses to trace */ @@ -669,20 +626,20 @@ static void check_known_peer_sock_change(n2n_edge_t * eee, return; if(!sock_equal(&(scan->sock), peer)) { - if(!from_supernode) { - /* This is a P2P packet */ - traceEvent(TRACE_NORMAL, "Peer changed %s: %s -> %s", - macaddr_str(mac_buf, scan->mac_addr), - sock_to_cstr(sockbuf1, &(scan->sock)), - sock_to_cstr(sockbuf2, peer)); - /* The peer has changed public socket. It can no longer be assumed to be reachable. */ - HASH_DEL(eee->known_peers, scan); - free(scan); + if(!from_supernode) { + /* This is a P2P packet */ + traceEvent(TRACE_NORMAL, "Peer changed %s: %s -> %s", + macaddr_str(mac_buf, scan->mac_addr), + sock_to_cstr(sockbuf1, &(scan->sock)), + sock_to_cstr(sockbuf2, peer)); + /* The peer has changed public socket. It can no longer be assumed to be reachable. */ + HASH_DEL(eee->known_peers, scan); + free(scan); - register_with_new_peer(eee, from_supernode, mac, peer); - } else { - /* Don't worry about what the supernode reports, it could be seeing a different socket. */ - } + register_with_new_peer(eee, from_supernode, mac, peer); + } else { + /* Don't worry about what the supernode reports, it could be seeing a different socket. */ + } } else scan->last_seen = when; } @@ -726,14 +683,14 @@ static void check_join_multicast_group(n2n_edge_t *eee) { if(setsockopt(eee->udp_multicast_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mreq, sizeof(mreq)) < 0) { traceEvent(TRACE_WARNING, "Failed to bind to local multicast group %s:%u [errno %u]", - N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT, errno); + N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT, errno); #ifdef WIN32 traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); #endif } else { traceEvent(TRACE_NORMAL, "Successfully joined multicast group %s:%u", - N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT); + N2N_MULTICAST_GROUP, N2N_MULTICAST_PORT); eee->multicast_joined = 1; } } @@ -782,33 +739,33 @@ static void send_register_super(n2n_edge_t * eee, /** Send a QUERY_PEER packet to the current supernode. */ static void send_query_peer( n2n_edge_t * eee, const n2n_mac_t dstMac) { - uint8_t pktbuf[N2N_PKT_BUF_SIZE]; - size_t idx; - n2n_common_t cmn = {0}; - n2n_QUERY_PEER_t query = {{0}}; + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; + size_t idx; + n2n_common_t cmn = {0}; + n2n_QUERY_PEER_t query = {{0}}; - cmn.ttl=N2N_DEFAULT_TTL; - cmn.pc = n2n_query_peer; - cmn.flags = 0; - memcpy( cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE ); + cmn.ttl=N2N_DEFAULT_TTL; + cmn.pc = n2n_query_peer; + cmn.flags = 0; + memcpy( cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE ); - idx=0; - encode_mac( query.srcMac, &idx, eee->device.mac_addr ); - idx=0; - encode_mac( query.targetMac, &idx, dstMac ); + idx=0; + encode_mac( query.srcMac, &idx, eee->device.mac_addr ); + idx=0; + encode_mac( query.targetMac, &idx, dstMac ); - idx=0; - encode_QUERY_PEER( pktbuf, &idx, &cmn, &query ); + idx=0; + encode_QUERY_PEER( pktbuf, &idx, &cmn, &query ); - traceEvent( TRACE_DEBUG, "send QUERY_PEER to supernode" ); + traceEvent( TRACE_DEBUG, "send QUERY_PEER to supernode" ); - sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); + sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); } /** Send a REGISTER packet to another edge. */ static void send_register(n2n_edge_t * eee, - const n2n_sock_t * remote_peer, - const n2n_mac_t peer_mac) { + const n2n_sock_t * remote_peer, + const n2n_mac_t peer_mac) { uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx; /* ssize_t sent; */ @@ -1021,88 +978,88 @@ static int handle_PACKET(n2n_edge_t * eee, rx_transop_id &= (1 << (8*sizeof((uint16_t)rx_transop_id)-N2N_COMPRESSION_ID_BITLEN)) -1; if(rx_transop_id == eee->conf.transop_id) { - uint8_t is_multicast; - eth_payload = decodebuf; - eh = (ether_hdr_t*)eth_payload; - eth_size = eee->transop.rev(&eee->transop, - eth_payload, N2N_PKT_BUF_SIZE, - payload, psize, pkt->srcMac); - ++(eee->transop.rx_cnt); /* stats */ + uint8_t is_multicast; + eth_payload = decodebuf; + eh = (ether_hdr_t*)eth_payload; + eth_size = eee->transop.rev(&eee->transop, + eth_payload, N2N_PKT_BUF_SIZE, + payload, psize, pkt->srcMac); + ++(eee->transop.rx_cnt); /* stats */ - /* decompress if necessary */ - uint8_t * deflation_buffer = 0; - int32_t deflated_len; - switch (rx_compression_id) { - case N2N_COMPRESSION_ID_NONE: - break; // continue afterwards + /* decompress if necessary */ + uint8_t * deflation_buffer = 0; + int32_t deflated_len; + switch (rx_compression_id) { + case N2N_COMPRESSION_ID_NONE: + break; // continue afterwards - case N2N_COMPRESSION_ID_LZO: - deflation_buffer = malloc (N2N_PKT_BUF_SIZE); - lzo1x_decompress (eth_payload, eth_size, deflation_buffer, (lzo_uint*)&deflated_len, NULL); - break; + case N2N_COMPRESSION_ID_LZO: + deflation_buffer = malloc (N2N_PKT_BUF_SIZE); + lzo1x_decompress (eth_payload, eth_size, deflation_buffer, (lzo_uint*)&deflated_len, NULL); + break; #ifdef N2N_HAVE_ZSTD - case N2N_COMPRESSION_ID_ZSTD: - deflated_len = N2N_PKT_BUF_SIZE; - deflation_buffer = malloc (deflated_len); - deflated_len = (int32_t)ZSTD_decompress (deflation_buffer, deflated_len, eth_payload, eth_size); - if (ZSTD_isError(deflated_len)) { - traceEvent (TRACE_ERROR, "payload decompression failed with zstd error '%s'.", - ZSTD_getErrorName(deflated_len)); - free (deflation_buffer); - return (-1); // cannot help it - } - break; + case N2N_COMPRESSION_ID_ZSTD: + deflated_len = N2N_PKT_BUF_SIZE; + deflation_buffer = malloc (deflated_len); + deflated_len = (int32_t)ZSTD_decompress (deflation_buffer, deflated_len, eth_payload, eth_size); + if (ZSTD_isError(deflated_len)) { + traceEvent (TRACE_ERROR, "payload decompression failed with zstd error '%s'.", + ZSTD_getErrorName(deflated_len)); + free (deflation_buffer); + return (-1); // cannot help it + } + break; #endif - default: - traceEvent (TRACE_ERROR, "payload decompression failed: received packet indicating unsupported %s compression.", - compression_str(rx_compression_id)); - return (-1); // cannot handle it - } + default: + traceEvent (TRACE_ERROR, "payload decompression failed: received packet indicating unsupported %s compression.", + compression_str(rx_compression_id)); + return (-1); // cannot handle it + } - if (rx_compression_id) { - traceEvent (TRACE_DEBUG, "payload decompression [%s]: deflated %u bytes to %u bytes", - compression_str(rx_compression_id), eth_size, (int)deflated_len); - memcpy(eth_payload ,deflation_buffer, deflated_len ); - eth_size = deflated_len; - free (deflation_buffer); - } + if (rx_compression_id) { + traceEvent (TRACE_DEBUG, "payload decompression [%s]: deflated %u bytes to %u bytes", + compression_str(rx_compression_id), eth_size, (int)deflated_len); + memcpy(eth_payload ,deflation_buffer, deflated_len ); + eth_size = deflated_len; + free (deflation_buffer); + } - is_multicast = (is_ip6_discovery(eth_payload, eth_size) || is_ethMulticast(eth_payload, eth_size)); + is_multicast = (is_ip6_discovery(eth_payload, eth_size) || is_ethMulticast(eth_payload, eth_size)); - if(eee->conf.drop_multicast && is_multicast) { - traceEvent(TRACE_INFO, "Dropping RX multicast"); - return(-1); - } else if((!eee->conf.allow_routing) && (!is_multicast)) { - /* Check if it is a routed packet */ - if((ntohs(eh->type) == 0x0800) && (eth_size >= ETH_FRAMESIZE + IP4_MIN_SIZE)) { - uint32_t *dst = (uint32_t*)ð_payload[ETH_FRAMESIZE + IP4_DSTOFFSET]; - u_int8_t *dst_mac = (u_int8_t*)eth_payload; + if(eee->conf.drop_multicast && is_multicast) { + traceEvent(TRACE_INFO, "Dropping RX multicast"); + return(-1); + } else if((!eee->conf.allow_routing) && (!is_multicast)) { + /* Check if it is a routed packet */ + if((ntohs(eh->type) == 0x0800) && (eth_size >= ETH_FRAMESIZE + IP4_MIN_SIZE)) { + uint32_t *dst = (uint32_t*)ð_payload[ETH_FRAMESIZE + IP4_DSTOFFSET]; + u_int8_t *dst_mac = (u_int8_t*)eth_payload; - /* Note: all elements of the_ip are in network order */ - if(!memcmp(dst_mac, broadcast_mac, 6)) - traceEvent(TRACE_DEBUG, "Broadcast packet [%s]", - intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); - else if((*dst != eee->device.ip_addr)) { - /* This is a packet that needs to be routed */ - traceEvent(TRACE_INFO, "Discarding routed packet [%s]", - intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); - return(-1); - } else { - /* This packet is directed to us */ - /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ - } + /* Note: all elements of the_ip are in network order */ + if(!memcmp(dst_mac, broadcast_mac, 6)) + traceEvent(TRACE_DEBUG, "Broadcast packet [%s]", + intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); + else if((*dst != eee->device.ip_addr)) { + /* This is a packet that needs to be routed */ + traceEvent(TRACE_INFO, "Discarding routed packet [%s]", + intoa(ntohl(*dst), ip_buf, sizeof(ip_buf))); + return(-1); + } else { + /* This packet is directed to us */ + /* traceEvent(TRACE_INFO, "Sending non-routed packet"); */ } } - - /* Write ethernet packet to tap device. */ - traceEvent(TRACE_DEBUG, "sending to TAP %u", (unsigned int)eth_size); - data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); - - if (data_sent_len == eth_size) - { - retval = 0; - } } + + /* Write ethernet packet to tap device. */ + traceEvent(TRACE_DEBUG, "sending to TAP %u", (unsigned int)eth_size); + data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); + + if (data_sent_len == eth_size) + { + retval = 0; + } + } else { traceEvent(TRACE_ERROR, "invalid transop ID: expected %s(%u), got %s(%u)", @@ -1317,8 +1274,8 @@ static int find_peer_destination(n2n_edge_t * eee, if(retval == 0) { memcpy(destination, &(eee->supernode), sizeof(struct sockaddr_in)); traceEvent(TRACE_DEBUG, "P2P Peer [MAC=%02X:%02X:%02X:%02X:%02X:%02X] not found, using supernode", - mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, - mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); + mac_address[0] & 0xFF, mac_address[1] & 0xFF, mac_address[2] & 0xFF, + mac_address[3] & 0xFF, mac_address[4] & 0xFF, mac_address[5] & 0xFF); check_query_peer_info(eee, now, mac_address); } @@ -1358,8 +1315,8 @@ static int send_packet(n2n_edge_t * eee, } traceEvent(TRACE_INFO, "Tx PACKET to %s (dest=%s) [%u B]", - sock_to_cstr(sockbuf, &destination), - macaddr_str(mac_buf, dstMac), pktlen); + sock_to_cstr(sockbuf, &destination), + macaddr_str(mac_buf, dstMac), pktlen); /* s = */ sendto_sock(eee->udp_sock, pktbuf, pktlen, &destination); @@ -1370,7 +1327,7 @@ static int send_packet(n2n_edge_t * eee, /** A layer-2 packet was received at the tunnel and needs to be sent via UDP. */ static void send_packet2net(n2n_edge_t * eee, - uint8_t *tap_pkt, size_t len) { + uint8_t *tap_pkt, size_t len) { ipstr_t ip_buf; n2n_mac_t destMac; @@ -1432,38 +1389,38 @@ static void send_packet2net(n2n_edge_t * eee, int32_t compression_len; switch (eee->conf.compression) { - case N2N_COMPRESSION_ID_LZO: - compression_buffer = malloc (len + len / 16 + 64 + 3); - if (lzo1x_1_compress(tap_pkt, len, compression_buffer, (lzo_uint*)&compression_len, wrkmem) == LZO_E_OK) { - if (compression_len < len) { - pkt.compression = N2N_COMPRESSION_ID_LZO; - } - } - break; + case N2N_COMPRESSION_ID_LZO: + compression_buffer = malloc (len + len / 16 + 64 + 3); + if (lzo1x_1_compress(tap_pkt, len, compression_buffer, (lzo_uint*)&compression_len, wrkmem) == LZO_E_OK) { + if (compression_len < len) { + pkt.compression = N2N_COMPRESSION_ID_LZO; + } + } + break; #ifdef N2N_HAVE_ZSTD - case N2N_COMPRESSION_ID_ZSTD: - compression_len = N2N_PKT_BUF_SIZE + 128; - compression_buffer = malloc (compression_len); // leaves enough room, for exact size call compression_len = ZSTD_compressBound (len); (slower) - compression_len = (int32_t)ZSTD_compress(compression_buffer, compression_len, tap_pkt, len, ZSTD_COMPRESSION_LEVEL) ; - if (!ZSTD_isError(compression_len)) { - if (compression_len < len) { - pkt.compression = N2N_COMPRESSION_ID_ZSTD; - } - } else { - traceEvent (TRACE_ERROR, "payload compression failed with zstd error '%s'.", - ZSTD_getErrorName(compression_len)); - free (compression_buffer); - // continue with unset without pkt.compression --> will send uncompressed - } - break; + case N2N_COMPRESSION_ID_ZSTD: + compression_len = N2N_PKT_BUF_SIZE + 128; + compression_buffer = malloc (compression_len); // leaves enough room, for exact size call compression_len = ZSTD_compressBound (len); (slower) + compression_len = (int32_t)ZSTD_compress(compression_buffer, compression_len, tap_pkt, len, ZSTD_COMPRESSION_LEVEL) ; + if (!ZSTD_isError(compression_len)) { + if (compression_len < len) { + pkt.compression = N2N_COMPRESSION_ID_ZSTD; + } + } else { + traceEvent (TRACE_ERROR, "payload compression failed with zstd error '%s'.", + ZSTD_getErrorName(compression_len)); + free (compression_buffer); + // continue with unset without pkt.compression --> will send uncompressed + } + break; #endif - default: - break; + default: + break; } if (pkt.compression) { traceEvent (TRACE_DEBUG, "payload compression [%s]: compressed %u bytes to %u bytes\n", - compression_str(pkt.compression), len, compression_len); + compression_str(pkt.compression), len, compression_len); memcpy (tap_pkt, compression_buffer, compression_len); len = compression_len; @@ -1481,11 +1438,11 @@ static void send_packet2net(n2n_edge_t * eee, encode_PACKET(pktbuf, &idx, &cmn, &pkt); idx += eee->transop.fwd(&eee->transop, - pktbuf+idx, N2N_PKT_BUF_SIZE-idx, - tap_pkt, len, pkt.dstMac); + pktbuf+idx, N2N_PKT_BUF_SIZE-idx, + tap_pkt, len, pkt.dstMac); traceEvent(TRACE_DEBUG, "Encode %u B PACKET [%u B data, %u B overhead] transform %u", - (u_int)idx, (u_int)len, (u_int)(idx-len), tx_transop_idx); + (u_int)idx, (u_int)len, (u_int)(idx-len), tx_transop_idx); #ifdef MTU_ASSERT_VALUE { @@ -1517,19 +1474,17 @@ static void readFromTAPSocket(n2n_edge_t * eee) { len = uip_arp_len; memcpy(eth_pkt, uip_arp_buf, MIN(uip_arp_len, N2N_PKT_BUF_SIZE)); traceEvent(TRACE_DEBUG, "ARP reply packet to send"); - } - else - { + } else { #endif /* #ifdef __ANDROID_NDK__ */ - len = tuntap_read( &(eee->device), eth_pkt, N2N_PKT_BUF_SIZE ); + len = tuntap_read( &(eee->device), eth_pkt, N2N_PKT_BUF_SIZE ); #ifdef __ANDROID_NDK__ - } + } #endif /* #ifdef __ANDROID_NDK__ */ if((len <= 0) || (len > N2N_PKT_BUF_SIZE)) { traceEvent(TRACE_WARNING, "read()=%d [%d/%s]", - (signed int)len, errno, strerror(errno)); + (signed int)len, errno, strerror(errno)); } else { @@ -1554,40 +1509,6 @@ static void readFromTAPSocket(n2n_edge_t * eee) { /* ************************************** */ -#ifdef WIN32 - -struct tunread_arg { - n2n_edge_t *eee; - int *keep_running; -}; - -static DWORD* tunReadThread(LPVOID lpArg) { - struct tunread_arg *arg = (struct tunread_arg*)lpArg; - - while(*arg->keep_running) - readFromTAPSocket(arg->eee); - - return((DWORD*)NULL); -} - -/* ************************************** */ - -/** Start a second thread in Windows because TUNTAP interfaces do not expose - * file descriptors. */ -static HANDLE startTunReadThread(struct tunread_arg *arg) { - DWORD dwThreadId; - - return(CreateThread(NULL, /* security attributes */ - 0, /* use default stack size */ - (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ - (void*)arg, /* argument to thread function */ - 0, /* thread creation flags */ - &dwThreadId)); /* thread id out */ -} -#endif - -/* ************************************** */ - /** Read a datagram from the main UDP socket to the internet. */ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { n2n_common_t cmn; /* common fields in the packet header */ @@ -1618,12 +1539,12 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { #ifdef WIN32 if(WSAGetLastError() != WSAECONNRESET) #endif - { - traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", recvlen, errno, strerror(errno)); + { + traceEvent(TRACE_ERROR, "recvfrom() failed %d errno %d (%s)", recvlen, errno, strerror(errno)); #ifdef WIN32 - traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); + traceEvent(TRACE_ERROR, "WSAGetLastError(): %u", WSAGetLastError()); #endif - } + } return; /* failed to receive data from UDP */ } @@ -1657,174 +1578,174 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; if(0 == memcmp(cmn.community, eee->conf.community_name, N2N_COMMUNITY_SIZE)) { - switch(msg_type) { - case MSG_TYPE_PACKET: + switch(msg_type) { + case MSG_TYPE_PACKET: { - /* process PACKET - most frequent so first in list. */ - n2n_PACKET_t pkt; + /* process PACKET - most frequent so first in list. */ + n2n_PACKET_t pkt; - decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); + decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); - if(is_valid_peer_sock(&pkt.sock)) - orig_sender = &(pkt.sock); + if(is_valid_peer_sock(&pkt.sock)) + orig_sender = &(pkt.sock); - if(!from_supernode) { - /* This is a P2P packet from the peer. We purge a pending - * registration towards the possibly nat-ted peer address as we now have - * a valid channel. We still use check_peer_registration_needed in - * handle_PACKET to double check this. - */ - traceEvent(TRACE_DEBUG, "Got P2P packet"); - find_and_remove_peer(&eee->pending_peers, pkt.srcMac); - } + if(!from_supernode) { + /* This is a P2P packet from the peer. We purge a pending + * registration towards the possibly nat-ted peer address as we now have + * a valid channel. We still use check_peer_registration_needed in + * handle_PACKET to double check this. + */ + traceEvent(TRACE_DEBUG, "Got P2P packet"); + find_and_remove_peer(&eee->pending_peers, pkt.srcMac); + } - traceEvent(TRACE_INFO, "Rx PACKET from %s (sender=%s) [%u B]", - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender), - recvlen); + traceEvent(TRACE_INFO, "Rx PACKET from %s (sender=%s) [%u B]", + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender), + recvlen); - handle_PACKET(eee, &cmn, &pkt, orig_sender, udp_buf+idx, recvlen-idx); - break; + handle_PACKET(eee, &cmn, &pkt, orig_sender, udp_buf+idx, recvlen-idx); + break; } - case MSG_TYPE_REGISTER: + case MSG_TYPE_REGISTER: { - /* Another edge is registering with us */ - n2n_REGISTER_t reg; - n2n_mac_t null_mac = { '\0' }; - int via_multicast; + /* Another edge is registering with us */ + n2n_REGISTER_t reg; + n2n_mac_t null_mac = { '\0' }; + int via_multicast; - decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); + decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); - if(is_valid_peer_sock(®.sock)) - orig_sender = &(reg.sock); + if(is_valid_peer_sock(®.sock)) + orig_sender = &(reg.sock); - via_multicast = !memcmp(reg.dstMac, null_mac, 6); + via_multicast = !memcmp(reg.dstMac, null_mac, 6); - if(via_multicast && !memcmp(reg.srcMac, eee->device.mac_addr, 6)) { - traceEvent(TRACE_DEBUG, "Skipping REGISTER from self"); - break; - } - - if(!via_multicast && memcmp(reg.dstMac, eee->device.mac_addr, 6)) { - traceEvent(TRACE_DEBUG, "Skipping REGISTER for other peer"); - break; - } - - if(!from_supernode) { - /* This is a P2P registration from the peer. We purge a pending - * registration towards the possibly nat-ted peer address as we now have - * a valid channel. We still use check_peer_registration_needed below - * to double check this. - */ - traceEvent(TRACE_DEBUG, "Got P2P register"); - find_and_remove_peer(&eee->pending_peers, reg.srcMac); - - /* NOTE: only ACK to peers */ - send_register_ack(eee, orig_sender, ®); - } - - traceEvent(TRACE_INFO, "Rx REGISTER src=%s dst=%s from peer %s (%s)", - macaddr_str(mac_buf1, reg.srcMac), - macaddr_str(mac_buf2, reg.dstMac), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender)); - - check_peer_registration_needed(eee, from_supernode, reg.srcMac, orig_sender); + if(via_multicast && !memcmp(reg.srcMac, eee->device.mac_addr, 6)) { + traceEvent(TRACE_DEBUG, "Skipping REGISTER from self"); break; + } + + if(!via_multicast && memcmp(reg.dstMac, eee->device.mac_addr, 6)) { + traceEvent(TRACE_DEBUG, "Skipping REGISTER for other peer"); + break; + } + + if(!from_supernode) { + /* This is a P2P registration from the peer. We purge a pending + * registration towards the possibly nat-ted peer address as we now have + * a valid channel. We still use check_peer_registration_needed below + * to double check this. + */ + traceEvent(TRACE_DEBUG, "Got P2P register"); + find_and_remove_peer(&eee->pending_peers, reg.srcMac); + + /* NOTE: only ACK to peers */ + send_register_ack(eee, orig_sender, ®); + } + + traceEvent(TRACE_INFO, "Rx REGISTER src=%s dst=%s from peer %s (%s)", + macaddr_str(mac_buf1, reg.srcMac), + macaddr_str(mac_buf2, reg.dstMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); + + check_peer_registration_needed(eee, from_supernode, reg.srcMac, orig_sender); + break; } - case MSG_TYPE_REGISTER_ACK: + case MSG_TYPE_REGISTER_ACK: { - /* Peer edge is acknowledging our register request */ - n2n_REGISTER_ACK_t ra; + /* Peer edge is acknowledging our register request */ + n2n_REGISTER_ACK_t ra; - decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); + decode_REGISTER_ACK(&ra, &cmn, udp_buf, &rem, &idx); - if(is_valid_peer_sock(&ra.sock)) - orig_sender = &(ra.sock); + if(is_valid_peer_sock(&ra.sock)) + orig_sender = &(ra.sock); - traceEvent(TRACE_INFO, "Rx REGISTER_ACK src=%s dst=%s from peer %s (%s)", - macaddr_str(mac_buf1, ra.srcMac), - macaddr_str(mac_buf2, ra.dstMac), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender)); + traceEvent(TRACE_INFO, "Rx REGISTER_ACK src=%s dst=%s from peer %s (%s)", + macaddr_str(mac_buf1, ra.srcMac), + macaddr_str(mac_buf2, ra.dstMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender)); - peer_set_p2p_confirmed(eee, ra.srcMac, &sender, now); - break; + peer_set_p2p_confirmed(eee, ra.srcMac, &sender, now); + break; } - case MSG_TYPE_REGISTER_SUPER_ACK: + case MSG_TYPE_REGISTER_SUPER_ACK: { - n2n_REGISTER_SUPER_ACK_t ra; + n2n_REGISTER_SUPER_ACK_t ra; - if(eee->sn_wait) - { - decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx); + if(eee->sn_wait) + { + decode_REGISTER_SUPER_ACK(&ra, &cmn, udp_buf, &rem, &idx); - if(is_valid_peer_sock(&ra.sock)) - orig_sender = &(ra.sock); + if(is_valid_peer_sock(&ra.sock)) + orig_sender = &(ra.sock); - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", - macaddr_str(mac_buf1, ra.edgeMac), - sock_to_cstr(sockbuf1, &sender), - sock_to_cstr(sockbuf2, orig_sender), - (unsigned int)eee->sup_attempts); + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK myMAC=%s [%s] (external %s). Attempts %u", + macaddr_str(mac_buf1, ra.edgeMac), + sock_to_cstr(sockbuf1, &sender), + sock_to_cstr(sockbuf2, orig_sender), + (unsigned int)eee->sup_attempts); - if(0 == memcmp(ra.cookie, eee->last_cookie, N2N_COOKIE_SIZE)) - { - if(ra.num_sn > 0) - { - traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", - sock_to_cstr(sockbuf1, &(ra.sn_bak))); - } + if(0 == memcmp(ra.cookie, eee->last_cookie, N2N_COOKIE_SIZE)) + { + if(ra.num_sn > 0) + { + traceEvent(TRACE_NORMAL, "Rx REGISTER_SUPER_ACK backup supernode at %s", + sock_to_cstr(sockbuf1, &(ra.sn_bak))); + } - eee->last_sup = now; - eee->sn_wait=0; - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */ + eee->last_sup = now; + eee->sn_wait=0; + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; /* refresh because we got a response */ - /* NOTE: the register_interval should be chosen by the edge node - * based on its NAT configuration. */ - //eee->conf.register_interval = ra.lifetime; - } - else - { - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie."); - } - } - else - { - traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER."); - } - break; + /* NOTE: the register_interval should be chosen by the edge node + * based on its NAT configuration. */ + //eee->conf.register_interval = ra.lifetime; + } + else + { + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with wrong or old cookie."); + } + } + else + { + traceEvent(TRACE_INFO, "Rx REGISTER_SUPER_ACK with no outstanding REGISTER_SUPER."); + } + break; } case MSG_TYPE_PEER_INFO: { - n2n_PEER_INFO_t pi; - struct peer_info * scan; - decode_PEER_INFO( &pi, &cmn, udp_buf, &rem, &idx ); + n2n_PEER_INFO_t pi; + struct peer_info * scan; + decode_PEER_INFO( &pi, &cmn, udp_buf, &rem, &idx ); - if(!is_valid_peer_sock(&pi.sock)) { - traceEvent(TRACE_DEBUG, "Skip invalid PEER_INFO %s [%s]", - sock_to_cstr(sockbuf1, &pi.sock), - macaddr_str(mac_buf1, pi.mac) ); - break; - } + if(!is_valid_peer_sock(&pi.sock)) { + traceEvent(TRACE_DEBUG, "Skip invalid PEER_INFO %s [%s]", + sock_to_cstr(sockbuf1, &pi.sock), + macaddr_str(mac_buf1, pi.mac) ); + break; + } - HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); - if (scan) { + HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); + if (scan) { scan->sock = pi.sock; traceEvent(TRACE_INFO, "Rx PEER_INFO for %s: is at %s", macaddr_str(mac_buf1, pi.mac), sock_to_cstr(sockbuf1, &pi.sock)); send_register(eee, &scan->sock, scan->mac_addr); - } else { + } else { traceEvent(TRACE_INFO, "Rx PEER_INFO unknown peer %s", macaddr_str(mac_buf1, pi.mac) ); - } + } - break; - } - default: - /* Not a known message type */ - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); - return; - } /* switch(msg_type) */ + break; + } + default: + /* Not a known message type */ + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); + return; + } /* switch(msg_type) */ } else if(from_supernode) /* if (community match) */ traceEvent(TRACE_WARNING, "Received packet with unknown community"); else @@ -1919,10 +1840,10 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) { #ifndef SKIP_MULTICAST_PEERS_DISCOVERY if(FD_ISSET(eee->udp_multicast_sock, &socket_mask)) { - /* Read a cooked socket from the internet socket (multicast). Writes on the TAP - * socket. */ - traceEvent(TRACE_DEBUG, "Received packet from multicast socket"); - readFromIPSocket(eee, eee->udp_multicast_sock); + /* Read a cooked socket from the internet socket (multicast). Writes on the TAP + * socket. */ + traceEvent(TRACE_DEBUG, "Received packet from multicast socket"); + readFromIPSocket(eee, eee->udp_multicast_sock); } #endif @@ -1955,7 +1876,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) { numPurged += purge_expired_registrations(&eee->pending_peers, &last_purge_pending); if(numPurged > 0) { - traceEvent(TRACE_INFO, "%u peers removed. now: pending=%u, operational=%u", + traceEvent(TRACE_INFO, "%u peers removed. now: pending=%u, operational=%u", numPurged, HASH_COUNT(eee->pending_peers), HASH_COUNT(eee->known_peers)); @@ -2041,7 +1962,7 @@ static int edge_init_sockets(n2n_edge_t *eee, int udp_local_port, int mgmt_port, if(setsockopt(eee->udp_sock, IPPROTO_IP, IP_MTU_DISCOVER, &sockopt, sizeof(sockopt)) < 0) traceEvent(TRACE_WARNING, "Could not %s PMTU discovery[%d]: %s", - (eee->conf.disable_pmtu_discovery) ? "disable" : "enable", errno, strerror(errno)); + (eee->conf.disable_pmtu_discovery) ? "disable" : "enable", errno, strerror(errno)); else traceEvent(TRACE_DEBUG, "PMTU discovery %s", (eee->conf.disable_pmtu_discovery) ? "disabled" : "enabled"); #endif @@ -2121,14 +2042,14 @@ static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size char netbuf[64], gwbuf[64]; switch(cmd) { - case RTM_NEWROUTE: - cmd_str = "Add"; - break; - case RTM_DELROUTE: - cmd_str = "Delete"; - break; - default: - cmd_str = "?"; + case RTM_NEWROUTE: + cmd_str = "Add"; + break; + case RTM_DELROUTE: + cmd_str = "Delete"; + break; + default: + cmd_str = "?"; } addr.s_addr = route->net_addr; @@ -2142,30 +2063,30 @@ static char* route_cmd_to_str(int cmd, const n2n_route_t *route, char *buf, size } /* Adapted from https://olegkutkov.me/2019/08/29/modifying-linux-network-routes-using-netlink/ */ -#define NLMSG_TAIL(nmsg) \ - ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) +#define NLMSG_TAIL(nmsg) \ + ((struct rtattr *) (((char *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len))) /* Add new data to rtattr */ static int rtattr_add(struct nlmsghdr *n, int maxlen, int type, const void *data, int alen) { - int len = RTA_LENGTH(alen); - struct rtattr *rta; + int len = RTA_LENGTH(alen); + struct rtattr *rta; - if(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { - traceEvent(TRACE_ERROR, "rtattr_add error: message exceeded bound of %d\n", maxlen); - return -1; - } + if(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) { + traceEvent(TRACE_ERROR, "rtattr_add error: message exceeded bound of %d\n", maxlen); + return -1; + } - rta = NLMSG_TAIL(n); - rta->rta_type = type; - rta->rta_len = len; + rta = NLMSG_TAIL(n); + rta->rta_type = type; + rta->rta_len = len; - if(alen) - memcpy(RTA_DATA(rta), data, alen); + if(alen) + memcpy(RTA_DATA(rta), data, alen); - n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); + n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len); - return 0; + return 0; } static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx) { @@ -2301,7 +2222,7 @@ static int routectl(int cmd, int flags, n2n_route_t *route, int if_idx) { traceEvent(TRACE_DEBUG, route_cmd_to_str(cmd, route, route_buf, sizeof(route_buf))); rv = 0; -out: + out: close(nl_sock); return(rv); @@ -2495,7 +2416,7 @@ int quick_edge_init(char *device_name, char *community_name, edge_term(eee); edge_term_conf(&conf); -quick_edge_init_end: + quick_edge_init_end: tuntap_close(&tuntap); return(rv); } diff --git a/src/edge_utils_win32.c b/src/edge_utils_win32.c new file mode 100644 index 0000000..5f5caba --- /dev/null +++ b/src/edge_utils_win32.c @@ -0,0 +1,49 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + +#ifdef WIN32 + +#include "edge_utils_win32.h" + +/* ************************************** */ + +static DWORD* tunReadThread(LPVOID lpArg) { + struct tunread_arg *arg = (struct tunread_arg*)lpArg; + + while(*arg->keep_running) + readFromTAPSocket(arg->eee); + + return((DWORD*)NULL); +} + +/* ************************************** */ + +/** Start a second thread in Windows because TUNTAP interfaces do not expose + * file descriptors. */ +HANDLE startTunReadThread(struct tunread_arg *arg) { + DWORD dwThreadId; + + return(CreateThread(NULL, /* security attributes */ + 0, /* use default stack size */ + (LPTHREAD_START_ROUTINE)tunReadThread, /* thread function */ + (void*)arg, /* argument to thread function */ + 0, /* thread creation flags */ + &dwThreadId)); /* thread id out */ +} +#endif + diff --git a/example_edge_embed.c b/src/example_edge_embed.c similarity index 100% rename from example_edge_embed.c rename to src/example_edge_embed.c diff --git a/example_edge_embed_quick_edge_init.c b/src/example_edge_embed_quick_edge_init.c similarity index 98% rename from example_edge_embed_quick_edge_init.c rename to src/example_edge_embed_quick_edge_init.c index 4618059..39d1cd0 100644 --- a/example_edge_embed_quick_edge_init.c +++ b/src/example_edge_embed_quick_edge_init.c @@ -17,7 +17,6 @@ */ #include "n2n.h" -#include "random_numbers.h" /* This tool demonstrates how to easily embed diff --git a/example_sn_embed.c b/src/example_sn_embed.c similarity index 100% rename from example_sn_embed.c rename to src/example_sn_embed.c diff --git a/header_encryption.c b/src/header_encryption.c similarity index 93% rename from header_encryption.c rename to src/header_encryption.c index 6ce8ab4..ff61588 100644 --- a/header_encryption.c +++ b/src/header_encryption.c @@ -16,17 +16,12 @@ * */ -#include "header_encryption.h" - -#include - -#include "random_numbers.h" -#include "pearson.h" -#include "portable_endian.h" +#include "n2n.h" #define HASH_FIND_COMMUNITY(head, name, out) HASH_FIND_STR(head, name, out) +/* ********************************************************************** */ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, char * community_name, he_context_t * ctx) { @@ -58,6 +53,7 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, return (0); // unsuccessful } +/* ********************************************************************** */ int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, struct sn_community *communities) { @@ -113,6 +109,7 @@ int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, } } +/* ********************************************************************** */ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx) { uint8_t iv[16]; @@ -134,6 +131,7 @@ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_ return (0); } +/* ********************************************************************** */ void packet_header_setup_key (char * community_name, he_context_t * ctx) { diff --git a/minilzo.c b/src/minilzo.c similarity index 100% rename from minilzo.c rename to src/minilzo.c diff --git a/n2n.c b/src/n2n.c similarity index 100% rename from n2n.c rename to src/n2n.c diff --git a/pearson.c b/src/pearson.c similarity index 100% rename from pearson.c rename to src/pearson.c diff --git a/random_numbers.c b/src/random_numbers.c similarity index 81% rename from random_numbers.c rename to src/random_numbers.c index 3c2e410..35a7753 100644 --- a/random_numbers.c +++ b/src/random_numbers.c @@ -1,12 +1,29 @@ +/** + * (C) 2007-20 - ntop.org and contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not see see + * + */ + +#include "n2n.h" + /* The following code offers an alterate pseudo random number generator namely XORSHIFT128+ to use instead of C's rand(). Its performance is on par with C's rand(). */ -#include "random_numbers.h" - - /* The state must be seeded in a way that it is not all zero, choose some arbitrary defaults (in this case: taken from splitmix64) */ static struct rn_generator_state_t rn_current_state = { diff --git a/sn.c b/src/sn.c similarity index 100% rename from sn.c rename to src/sn.c diff --git a/sn_utils.c b/src/sn_utils.c similarity index 100% rename from sn_utils.c rename to src/sn_utils.c diff --git a/speck.c b/src/speck.c similarity index 100% rename from speck.c rename to src/speck.c diff --git a/transform_aes.c b/src/transform_aes.c similarity index 99% rename from transform_aes.c rename to src/transform_aes.c index 40d652a..27eeaaf 100644 --- a/transform_aes.c +++ b/src/transform_aes.c @@ -17,8 +17,6 @@ */ #include "n2n.h" -#include "n2n_transforms.h" -#include "random_numbers.h" #ifdef N2N_HAVE_AES diff --git a/transform_cc20.c b/src/transform_cc20.c similarity index 99% rename from transform_cc20.c rename to src/transform_cc20.c index 90c92b2..44fd70b 100644 --- a/transform_cc20.c +++ b/src/transform_cc20.c @@ -17,8 +17,6 @@ */ #include "n2n.h" -#include "n2n_transforms.h" -#include "random_numbers.h" #ifdef HAVE_OPENSSL_1_1 diff --git a/transform_null.c b/src/transform_null.c similarity index 100% rename from transform_null.c rename to src/transform_null.c diff --git a/transform_speck.c b/src/transform_speck.c similarity index 98% rename from transform_speck.c rename to src/transform_speck.c index 9ae5cd7..ede1378 100644 --- a/transform_speck.c +++ b/src/transform_speck.c @@ -17,10 +17,6 @@ */ #include "n2n.h" -#include "n2n_transforms.h" -#include "speck.h" -#include "random_numbers.h" -#include "pearson.h" #define N2N_SPECK_TRANSFORM_VERSION 1 /* version of the transform encoding */ #define N2N_SPECK_IVEC_SIZE 16 diff --git a/transform_tf.c b/src/transform_tf.c similarity index 97% rename from transform_tf.c rename to src/transform_tf.c index 481e972..a630d51 100644 --- a/transform_tf.c +++ b/src/transform_tf.c @@ -17,13 +17,6 @@ */ #include "n2n.h" -#include "n2n_transforms.h" -#include "twofish.h" -#include "random_numbers.h" -#ifndef _MSC_VER -/* Not included in Visual Studio 2008 */ -#include /* index() */ -#endif #define N2N_TWOFISH_NUM_SA 32 /* space for SAa */ diff --git a/tuntap_freebsd.c b/src/tuntap_freebsd.c similarity index 100% rename from tuntap_freebsd.c rename to src/tuntap_freebsd.c diff --git a/tuntap_linux.c b/src/tuntap_linux.c similarity index 98% rename from tuntap_linux.c rename to src/tuntap_linux.c index 7a5cbb4..94b3766 100644 --- a/tuntap_linux.c +++ b/src/tuntap_linux.c @@ -16,16 +16,9 @@ * */ -#include "n2n.h" - #ifdef __linux__ -#include -#include -#include -#include -#include -#include "random_numbers.h" +#include "n2n.h" /* ********************************** */ diff --git a/tuntap_netbsd.c b/src/tuntap_netbsd.c similarity index 100% rename from tuntap_netbsd.c rename to src/tuntap_netbsd.c diff --git a/tuntap_osx.c b/src/tuntap_osx.c similarity index 100% rename from tuntap_osx.c rename to src/tuntap_osx.c diff --git a/twofish.c b/src/twofish.c similarity index 99% rename from twofish.c rename to src/twofish.c index 7c7b8de..f1e1fbc 100644 --- a/twofish.c +++ b/src/twofish.c @@ -35,13 +35,7 @@ #ifndef __TWOFISH_LIBRARY_SOURCE__ #define __TWOFISH_LIBRARY_SOURCE__ -#include -#include -#include -#include -#include -#include "twofish.h" -#include "random_numbers.h" +#include "n2n.h" /* Fixed 8x8 permutation S-boxes */ static const uint8_t TwoFish_P[2][256] = diff --git a/wire.c b/src/wire.c similarity index 100% rename from wire.c rename to src/wire.c diff --git a/tools/Makefile.in b/tools/Makefile.in index 7df143c..63176f0 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -16,8 +16,8 @@ endif LIBS_EDGE_OPT=@N2N_LIBS@ LIBS_EDGE+=$(LIBS_EDGE_OPT) -HEADERS=../n2n_wire.h ../n2n.h ../twofish.h ../n2n_transforms.h -CFLAGS+=-I.. @CFLAGS@ +HEADERS=$(wildcard include/*.h) +CFLAGS+=-I../include @CFLAGS@ LDFLAGS+=-L.. CFLAGS+=$(DEBUG) $(OPTIMIZATION) $(WARN) LDFLAGS=@LDFLAGS@ From de86a227056a5f9765960390db646e960980f310 Mon Sep 17 00:00:00 2001 From: lucaderi Date: Sun, 21 Jun 2020 22:28:38 +0200 Subject: [PATCH 33/45] CentOS fix --- configure.seed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.seed b/configure.seed index f26907e..3b12a16 100644 --- a/configure.seed +++ b/configure.seed @@ -15,7 +15,7 @@ fi N2N_LIBS= -AC_PROG_CC([clang]) +AC_PROG_CC AC_CHECK_LIB([zstd], [ZSTD_compress]) if test "x$ac_cv_lib_zstd_ZSTD_compress" != xyes; then From 0bf7ae0a01717391171643718c3069c86447c9b9 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Sun, 21 Jun 2020 22:33:28 +0200 Subject: [PATCH 34/45] Minor code claanup --- include/n2n.h | 1 + include/n2n_define.h | 3 ++- src/edge_utils.c | 4 ++++ tools/Makefile.in | 2 +- tools/benchmark.c | 53 ++++++++++++++++++-------------------------- 5 files changed, 29 insertions(+), 34 deletions(-) diff --git a/include/n2n.h b/include/n2n.h index 6545143..f38b09d 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -129,6 +129,7 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include +#include #include #include #include diff --git a/include/n2n_define.h b/include/n2n_define.h index f56297a..21b31ff 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -43,10 +43,11 @@ #define IP4_MIN_SIZE 20 #define UDP_SIZE 8 +#if 0 /* heap allocation for compression as per lzo example doc */ #define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); - +#endif /* N2N compression indicators. */ /* Compression is disabled by default for outgoing packets if no cli diff --git a/src/edge_utils.c b/src/edge_utils.c index f4487c6..ecb616c 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -18,6 +18,10 @@ #include "n2n.h" +/* heap allocation for compression as per lzo example doc */ +#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] +static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); + /* ************************************** */ static const char * supernode_ip(const n2n_edge_t * eee); diff --git a/tools/Makefile.in b/tools/Makefile.in index 63176f0..631d5d9 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -40,7 +40,7 @@ n2n-decode: n2n_decode.c $(N2N_LIB) $(HEADERS) $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -rf $(TOOLS) $(N2N_LIB) *.o *.dSYM *~ + rm -rf $(TOOLS) *.o *.dSYM *~ install: $(TOOLS) $(INSTALL_PROG) $(TOOLS) $(SBINDIR)/ diff --git a/tools/benchmark.c b/tools/benchmark.c index 748b0e7..671b639 100644 --- a/tools/benchmark.c +++ b/tools/benchmark.c @@ -1,5 +1,5 @@ /* - * (C) 2007-18 - ntop.org and contributors + * (C) 2007-20 - ntop.org and contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,37 +16,26 @@ * */ -#include "n2n_wire.h" -#include "n2n_transforms.h" #include "n2n.h" -#ifdef __GNUC__ -#include -#endif -#include -#include -#include - #if defined(WIN32) && !defined(__GNUC__) -#include - static int gettimeofday(struct timeval *tp, void *tzp) { - time_t clock; - struct tm tm; - SYSTEMTIME wtm; - GetLocalTime(&wtm); - tm.tm_year = wtm.wYear - 1900; - tm.tm_mon = wtm.wMonth - 1; - tm.tm_mday = wtm.wDay; - tm.tm_hour = wtm.wHour; - tm.tm_min = wtm.wMinute; - tm.tm_sec = wtm.wSecond; - tm.tm_isdst = -1; - clock = mktime(&tm); - tp->tv_sec = clock; - tp->tv_usec = wtm.wMilliseconds * 1000; - return (0); + time_t clock; + struct tm tm; + SYSTEMTIME wtm; + GetLocalTime(&wtm); + tm.tm_year = wtm.wYear - 1900; + tm.tm_mon = wtm.wMonth - 1; + tm.tm_mday = wtm.wDay; + tm.tm_hour = wtm.wHour; + tm.tm_min = wtm.wMinute; + tm.tm_sec = wtm.wSecond; + tm.tm_isdst = -1; + clock = mktime(&tm); + tp->tv_sec = clock; + tp->tv_usec = wtm.wMilliseconds * 1000; + return (0); } #endif @@ -75,7 +64,7 @@ static int perform_decryption = 0; static void usage() { fprintf(stderr, "Usage: benchmark [-d]\n" - " -d\t\tEnable decryption. Default: only encryption is performed\n"); + " -d\t\tEnable decryption. Default: only encryption is performed\n"); exit(1); } @@ -162,7 +151,7 @@ static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, n2 size_t num_packets = 0; printf("Run %s[%s] for %us (%u bytes): ", perform_decryption ? "enc/dec" : "enc", - op_name, target_sec, (unsigned int)sizeof(PKT_CONTENT)); + op_name, target_sec, (unsigned int)sizeof(PKT_CONTENT)); fflush(stdout); memset(mac_buf, 0, sizeof(mac_buf)); @@ -172,8 +161,8 @@ static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, n2 nw = do_encode_packet( pktbuf, N2N_PKT_BUF_SIZE, conf->community_name); nw += op_fn->fwd(op_fn, - pktbuf+nw, N2N_PKT_BUF_SIZE-nw, - PKT_CONTENT, sizeof(PKT_CONTENT), mac_buf); + pktbuf+nw, N2N_PKT_BUF_SIZE-nw, + PKT_CONTENT, sizeof(PKT_CONTENT), mac_buf); idx=0; rem=nw; @@ -198,7 +187,7 @@ static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, n2 float mpps = num_packets / (tdiff / 1e6) / 1e6; printf("\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", - (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); + (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); } static ssize_t do_encode_packet( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ) From 3344065cab6ce3b7b37882b63130d85811e0be3e Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Sun, 21 Jun 2020 22:34:32 +0200 Subject: [PATCH 35/45] Removed unnecessary code --- include/n2n_define.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/include/n2n_define.h b/include/n2n_define.h index 21b31ff..74fea21 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -43,12 +43,6 @@ #define IP4_MIN_SIZE 20 #define UDP_SIZE 8 -#if 0 -/* heap allocation for compression as per lzo example doc */ -#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] -static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); -#endif - /* N2N compression indicators. */ /* Compression is disabled by default for outgoing packets if no cli * option is given. All edges are built with decompression support so From 159a088696f44cd7f89fc35453a1b40546f52b43 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Mon, 22 Jun 2020 00:54:25 +0200 Subject: [PATCH 36/45] Added missing makefile dependency --- Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.in b/Makefile.in index f243a8d..60aaf19 100644 --- a/Makefile.in +++ b/Makefile.in @@ -46,7 +46,7 @@ MAN8DIR=$(MANDIR)/man8 N2N_LIB=libn2n.a N2N_OBJS=$(patsubst src/%.c, src/%.o, $(wildcard src/*.c)) -N2N_DEPS=$(wildcard include/*.h) $(wildcard src/*.c) Makefile +N2N_DEPS=$(wildcard include/*.h) $(wildcard src/*.c) Makefile $(N2N_LIB) LIBS_EDGE+=$(LIBS_EDGE_OPT) LIBS_SN= From 789dd902720564e0ec2c8a3bb181652dd74f10fd Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 23 Jun 2020 00:34:19 +0545 Subject: [PATCH 37/45] Header Encryption --- include/header_encryption.h | 12 +- include/n2n_define.h | 5 + src/edge.c | 13 +- src/edge_utils.c | 28 ++ src/header_encryption.c | 100 ++--- src/sn.c | 216 ++++++---- src/sn_utils.c | 790 +++++++++++++++++++----------------- 7 files changed, 626 insertions(+), 538 deletions(-) diff --git a/include/header_encryption.h b/include/header_encryption.h index 6f8bdee..74ad647 100644 --- a/include/header_encryption.h +++ b/include/header_encryption.h @@ -17,19 +17,11 @@ */ - -/* Header encryption indicators */ -#define HEADER_ENCRYPTION_UNKNOWN 0 -#define HEADER_ENCRYPTION_NONE 1 -#define HEADER_ENCRYPTION_ENABLED 2 - -uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, +uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, char * community_name, he_context_t * ctx); -int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, - struct sn_community * communities); int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); -void packet_header_setup_key (char * community_name, he_context_t * ctx); +void packet_header_setup_key (const char * community_name, he_context_t ** ctx); diff --git a/include/n2n_define.h b/include/n2n_define.h index 74fea21..304f443 100644 --- a/include/n2n_define.h +++ b/include/n2n_define.h @@ -60,6 +60,11 @@ bits of transform_id; will be obsolete as soon as compression gets its own field in the packet. REVISIT then. */ +/* Header encryption indicators */ +#define HEADER_ENCRYPTION_UNKNOWN 0 +#define HEADER_ENCRYPTION_NONE 1 +#define HEADER_ENCRYPTION_ENABLED 2 + #define DEFAULT_MTU 1290 #define HASH_ADD_PEER(head,add) \ diff --git a/src/edge.c b/src/edge.c index 9000a41..db6bd09 100644 --- a/src/edge.c +++ b/src/edge.c @@ -154,7 +154,7 @@ static void help() { #ifndef __APPLE__ "[-D] " #endif - "[-r] [-E] [-v] [-i ] [-L ] [-t ] [-A[]] [-z[]] [-h]\n\n"); + "[-r] [-E] [-v] [-i ] [-L ] [-t ] [-A[]] [-H] [-z[]] [-h]\n\n"); #if defined(N2N_CAN_NAME_IFACE) printf("-d | tun device name\n"); @@ -192,6 +192,7 @@ static void help() { printf("-A4 | Use ChaCha20 for payload encryption. Requires a key.\n"); #endif printf("-A5 | Use Speck for payload encryption. Requires a key.\n"); + printf("-H | Enable full header encryption. Requires supernode with fixed community.\n"); printf("-z1 or -z | Enable lzo1x compression for outgoing data packets\n"); #ifdef N2N_HAVE_ZSTD printf("-z2 | Enable zstd compression for outgoing data packets\n"); @@ -393,6 +394,14 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e break; } + case 'H': /* indicate header encryption */ + { + /* we cannot be sure if this gets parsed before the community name is set. + * so, only an indicator is set, action is taken later*/ + conf->header_encryption = HEADER_ENCRYPTION_ENABLED; + break; + } + case 'z': { int compression; @@ -551,7 +560,7 @@ static int loadFromCLI(int argc, char *argv[], n2n_edge_conf_t *conf, n2n_priv_c u_char c; while((c = getopt_long(argc, argv, - "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:z::A::" + "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:z::A::H" #ifdef __linux__ "T:n:" #endif diff --git a/src/edge_utils.c b/src/edge_utils.c index ecb616c..0b412c4 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -17,6 +17,7 @@ */ #include "n2n.h" +#include "header_encryption.h" /* heap allocation for compression as per lzo example doc */ #define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] @@ -254,6 +255,12 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r goto edge_init_error; } + /* Set the key schedule (context) for header encryption if enabled */ + if (conf->header_encryption == HEADER_ENCRYPTION_ENABLED) { + traceEvent(TRACE_NORMAL, "Header encryption is enabled."); + packet_header_setup_key ((char *)(conf->community_name), &(eee->conf.header_encryption_ctx)); + } + if(eee->transop.no_encryption) traceEvent(TRACE_WARNING, "Encryption is disabled in edge"); @@ -735,6 +742,9 @@ static void send_register_super(n2n_edge_t * eee, traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s", sock_to_cstr(sockbuf, supernode)); + if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); } @@ -763,6 +773,9 @@ static void send_query_peer( n2n_edge_t * eee, traceEvent( TRACE_DEBUG, "send QUERY_PEER to supernode" ); + if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); } @@ -806,6 +819,9 @@ static void send_register(n2n_edge_t * eee, traceEvent(TRACE_INFO, "Send REGISTER to %s", sock_to_cstr(sockbuf, remote_peer)); + if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -845,6 +861,8 @@ static void send_register_ack(n2n_edge_t * eee, traceEvent(TRACE_INFO, "send REGISTER_ACK %s", sock_to_cstr(sockbuf, remote_peer)); + if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -1441,6 +1459,9 @@ static void send_packet2net(n2n_edge_t * eee, idx=0; encode_PACKET(pktbuf, &idx, &cmn, &pkt); + if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + idx += eee->transop.fwd(&eee->transop, pktbuf+idx, N2N_PKT_BUF_SIZE-idx, tap_pkt, len, pkt.dstMac); @@ -1566,6 +1587,12 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { traceEvent(TRACE_DEBUG, "### Rx N2N UDP (%d) from %s", (signed int)recvlen, sock_to_cstr(sockbuf1, &sender)); + if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + if ( packet_header_decrypt (udp_buf, recvlen, (char *)eee->conf.community_name, eee->conf.header_encryption_ctx) < 0) { + traceEvent(TRACE_DEBUG, "readFromIPSocket failed to decrypt header."); + return; + } + /* hexdump(udp_buf, recvlen); */ rem = recvlen; /* Counts down bytes of packet to protect against buffer overruns. */ @@ -2346,6 +2373,7 @@ void edge_init_conf_defaults(n2n_edge_conf_t *conf) { conf->local_port = 0 /* any port */; conf->mgmt_port = N2N_EDGE_MGMT_PORT; /* 5644 by default */ conf->transop_id = N2N_TRANSFORM_ID_NULL; + conf->header_encryption = HEADER_ENCRYPTION_NONE; conf->compression = N2N_COMPRESSION_ID_NONE; conf->drop_multicast = 1; conf->allow_p2p = 1; diff --git a/src/header_encryption.c b/src/header_encryption.c index ff61588..4151432 100644 --- a/src/header_encryption.c +++ b/src/header_encryption.c @@ -23,7 +23,7 @@ /* ********************************************************************** */ -uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, +uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, char * community_name, he_context_t * ctx) { // assemble IV @@ -33,18 +33,19 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, // the first 96 bits of the packet get padded with ASCII "n2n!" // to full 128 bit IV memcpy (iv, packet, 12); - // alternatively, consider: pearson_hash_128 (iv, packet, 12); // try community name as possible key and check for magic bytes uint32_t magic = 0x6E326E00; // ="n2n_" uint32_t test_magic; - // check for magic bytes and resonable value in header len field + // check for magic bytes and reasonable value in header len field + // so, as a first step, decrypt 4 bytes only starting at byte 12 speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, (speck_context_t*)ctx); test_magic = be32toh (test_magic); - if ( ((test_magic << 8) == magic) - && ((test_magic >> 24) <= packet_len) // (test_masgic >> 24) is header_len + if ( (((test_magic >> 8) << 8) == magic) // check the thre uppermost bytes + && (((uint8_t)test_magic) <= packet_len) // lowest 8 bit of test_magic are header_len ) { - speck_he (&packet[12], &packet[12], (test_magic >> 24) - 12, iv, (speck_context_t*)ctx); + // decrypt the complete header + speck_he (&packet[12], &packet[12], (uint8_t)(test_magic) - 12, iv, (speck_context_t*)ctx); // restore original packet order memcpy (&packet[0], &packet[16], 4); memcpy (&packet[4], community_name, N2N_COMMUNITY_SIZE); @@ -55,89 +56,38 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint8_t packet_len, /* ********************************************************************** */ -int8_t packet_header_decrypt_if_required (uint8_t packet[], uint16_t packet_len, - struct sn_community *communities) { - - struct sn_community *c, *tmp; - - - if (packet_len < 20) - return (-1); - - // first, check if header is unenrypted to put it into the fast-lane then - - // the following check is around 99.99962 percent reliable - // it heavily relies on the structure of packet's common part - // changes to wire.c:encode/decode_common need to go together with this code - if ( (packet[19] == (uint8_t)0x00) // null terminated community name - && (packet[00] == N2N_PKT_VERSION) // correct packet version - // && (packet[01] <= N2N_DEFAULT_TTL) // reasonable TTL -- might interfere with hole-punching-related or cli passed higher values ?! - && ((be16toh (*(uint16_t*)&(packet[02])) & N2N_FLAGS_TYPE_MASK ) <= MSG_TYPE_MAX_TYPE ) // message type - && ( be16toh (*(uint16_t*)&(packet[02])) < N2N_FLAGS_OPTIONS) // flags - ) { - - // most probably unencrypted - - // make sure, no downgrading happens here and no unencrypted packets can be - // injected in a community which definitely deals with encrypted headers - HASH_FIND_COMMUNITY(communities, (char *)&packet[04], c); - if (!c) - if (c->header_encryption == HEADER_ENCRYPTION_ENABLED) - return (-2); - // set 'no encryption' in case it is not set yet - c->header_encryption = HEADER_ENCRYPTION_NONE; - c->header_encryption_ctx = NULL; - return (HEADER_ENCRYPTION_NONE); - } else { - - // most probably encrypted - // cycle through the known communities (as keys) to eventually decrypt - int32_t ret; - HASH_ITER (hh, communities, c, tmp) { - // skip the definitely unencrypted communities - if (c->header_encryption == HEADER_ENCRYPTION_NONE) - continue; - if ( (ret = packet_header_decrypt (packet, packet_len, c->community, c->header_encryption_ctx)) ) { - // set 'encrypted' in case it is not set yet - c->header_encryption = HEADER_ENCRYPTION_ENABLED; - // no need to test further communities - return (HEADER_ENCRYPTION_ENABLED); - } - } - // no matching key/community - return (-3); - } -} - -/* ********************************************************************** */ - int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx) { - uint8_t iv[16]; - uint64_t *iv64 = (uint64_t*)&iv; - const uint32_t magic = 0x006E326E; - if (header_len < 20) + uint8_t iv[16]; + uint32_t *iv32 = (uint32_t*)&iv; + uint64_t *iv64 = (uint64_t*)&iv; + const uint32_t magic = 0x6E326E21; // = ASCII "n2n!" + + if (header_len < 20) { + traceEvent(TRACE_DEBUG, "packet_header_encrypt dropped a packet too short to be valid."); return (-1); + } memcpy (&packet[16], &packet[00], 4); - - iv64[0] = n2n_rand(); - iv64[1] = n2n_rand(); - iv64[3] = htobe32(magic); - iv[12] = header_len; + + iv64[0] = n2n_rand (); + iv32[2] = n2n_rand (); + iv32[3] = htobe32 (magic); + + memcpy (packet, iv, 16); + packet[15] = header_len; speck_he (&packet[12], &packet[12], header_len - 12, iv, (speck_context_t*)ctx); - return (0); } /* ********************************************************************** */ -void packet_header_setup_key (char * community_name, he_context_t * ctx) { +void packet_header_setup_key (const char * community_name, he_context_t ** ctx) { uint8_t key[16]; pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); - ctx = calloc(1, sizeof(speck_context_t)); - speck_expand_key_he (key, (speck_context_t*)ctx); + *ctx = (he_context_t*)calloc(1, sizeof (speck_context_t)); + speck_expand_key_he (key, (speck_context_t*)*ctx); } diff --git a/src/sn.c b/src/sn.c index 636b3b3..ec6d211 100644 --- a/src/sn.c +++ b/src/sn.c @@ -33,12 +33,14 @@ #define HASH_FIND_COMMUNITY(head,name,out) HASH_FIND_STR(head,name,out) static int try_forward(n2n_sn_t * sss, + const struct sn_community *comm, const n2n_common_t * cmn, const n2n_mac_t dstMac, const uint8_t * pktbuf, size_t pktsize); static int try_broadcast(n2n_sn_t * sss, + const struct sn_community *comm, const n2n_common_t * cmn, const n2n_mac_t srcMac, const uint8_t * pktbuf, @@ -188,24 +190,17 @@ static ssize_t sendto_sock(n2n_sn_t * sss, } static int try_forward(n2n_sn_t * sss, + const struct sn_community *comm, const n2n_common_t * cmn, const n2n_mac_t dstMac, const uint8_t * pktbuf, size_t pktsize) { struct peer_info * scan; - struct sn_community *community; macstr_t mac_buf; n2n_sock_str_t sockbuf; - HASH_FIND_COMMUNITY(sss->communities, (char*)cmn->community, community); - - if(!community) { - traceEvent(TRACE_DEBUG, "try_forward unknown community %s", cmn->community); - return(-1); - } - - HASH_FIND_PEER(community->edges, dstMac, scan); + HASH_FIND_PEER(comm->edges, dstMac, scan); if(NULL != scan) { @@ -248,51 +243,44 @@ static int try_forward(n2n_sn_t * sss, * the supernode. */ static int try_broadcast(n2n_sn_t * sss, + const struct sn_community *comm, const n2n_common_t * cmn, const n2n_mac_t srcMac, const uint8_t * pktbuf, size_t pktsize) { struct peer_info *scan, *tmp; - struct sn_community *community; macstr_t mac_buf; n2n_sock_str_t sockbuf; traceEvent(TRACE_DEBUG, "try_broadcast"); - HASH_FIND_COMMUNITY(sss->communities, (char*)cmn->community, community); + HASH_ITER(hh, comm->edges, scan, tmp) { + if(memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) != 0) { + /* REVISIT: exclude if the destination socket is where the packet came from. */ + int data_sent_len; - if(community) { - HASH_ITER(hh, community->edges, scan, tmp) { - if(memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) != 0) { - /* REVISIT: exclude if the destination socket is where the packet came from. */ - int data_sent_len; + data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); - data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); - - if(data_sent_len != pktsize) - { - ++(sss->stats.errors); - traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", - pktsize, - sock_to_cstr(sockbuf, &(scan->sock)), - macaddr_str(mac_buf, scan->mac_addr), - strerror(errno)); - } - else - { - ++(sss->stats.broadcast); - traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", - pktsize, - sock_to_cstr(sockbuf, &(scan->sock)), - macaddr_str(mac_buf, scan->mac_addr)); - } + if(data_sent_len != pktsize) + { + ++(sss->stats.errors); + traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", + pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr), + strerror(errno)); + } + else + { + ++(sss->stats.broadcast); + traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", + pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr)); } } - } else - traceEvent(TRACE_INFO, "ignoring broadcast on unknown community %s\n", - cmn->community); - + } return 0; } @@ -420,7 +408,7 @@ static int load_allowed_sn_community(n2n_sn_t *sss, char *path) { /* we do not know if header encryption is used in this community, * first packet will show. just in case, setup the key. */ s->header_encryption = HEADER_ENCRYPTION_UNKNOWN; - packet_header_setup_key (s->community, s->header_encryption_ctx); + packet_header_setup_key (s->community, &(s->header_encryption_ctx)); HASH_ADD_STR(sss->communities, community, s); num_communities++; @@ -452,21 +440,75 @@ static int process_udp(n2n_sn_t * sss, n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; - int8_t he = HEADER_ENCRYPTION_UNKNOWN; size_t msg_type; uint8_t from_supernode; macstr_t mac_buf; macstr_t mac_buf2; n2n_sock_str_t sockbuf; char buf[32]; + struct sn_community *comm, *tmp; traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]", udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), ntohs(sender_sock->sin_port)); - he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); - if (he < 0) - return -1; /* something wrong during packet decryption */ + /* check if header is unenrypted. the following check is around 99.99962 percent reliable. + * it heavily relies on the structure of packet's common part + * changes to wire.c:encode/decode_common need to go together with this code */ + if (udp_size < 20) { + traceEvent(TRACE_DEBUG, "process_udp dropped a packet too short to be valid."); + return -1; + } + if ( (udp_buf[19] == (uint8_t)0x00) // null terminated community name + && (udp_buf[00] == N2N_PKT_VERSION) // correct packet version + && ((be16toh (*(uint16_t*)&(udp_buf[02])) & N2N_FLAGS_TYPE_MASK ) <= MSG_TYPE_MAX_TYPE ) // message type + && ( be16toh (*(uint16_t*)&(udp_buf[02])) < N2N_FLAGS_OPTIONS) // flags + ) { + /* most probably unencrypted */ + /* make sure, no downgrading happens here and no unencrypted packets can be + * injected in a community which definitely deals with encrypted headers */ + HASH_FIND_COMMUNITY(sss->communities, (char *)&udp_buf[04], comm); + if (comm) { + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { + traceEvent(TRACE_DEBUG, "process_udp dropped a packet with unencrypted header " + "addressed to community '%s' which uses encrypted headers.", + comm->community); + return -1; + } + if (comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { + traceEvent (TRACE_INFO, "process_udp locked community '%s' to using " + "unencrypted headers.", comm->community); + /* set 'no encryption' in case it is not set yet */ + comm->header_encryption = HEADER_ENCRYPTION_NONE; + comm->header_encryption_ctx = NULL; + } + } + } else { + /* most probably encrypted */ + /* cycle through the known communities (as keys) to eventually decrypt */ + uint32_t ret = 0; + HASH_ITER (hh, sss->communities, comm, tmp) { + /* skip the definitely unencrypted communities */ + if (comm->header_encryption == HEADER_ENCRYPTION_NONE) + continue; + if ( (ret = packet_header_decrypt (udp_buf, udp_size, comm->community, comm->header_encryption_ctx)) ) { + if (comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { + traceEvent (TRACE_INFO, "process_udp locked community '%s' to using " + "encrypted headers.", comm->community); + /* set 'encrypted' in case it is not set yet */ + comm->header_encryption = HEADER_ENCRYPTION_ENABLED; + } + // no need to test further communities + break; + } + } + if (!ret) { + // no matching key/community + traceEvent(TRACE_DEBUG, "process_udp dropped a packet with seemingly encrypted header " + "for which no matching community which uses encrypted headers was found."); + return -1; + } + } /* Use decode_common() to determine the kind of packet then process it: * @@ -506,8 +548,12 @@ static int process_udp(n2n_sn_t * sss, uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; int unicast; /* non-zero if unicast */ - const uint8_t * rec_buf; /* either udp_buf or encbuf */ + uint8_t * rec_buf; /* either udp_buf or encbuf */ + if(!comm) { + traceEvent(TRACE_DEBUG, "process_udp PACKET with unknown community %s", cmn.community); + return -1; + } sss->stats.last_fwd=now; decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); @@ -535,6 +581,9 @@ static int process_udp(n2n_sn_t * sss, /* Re-encode the header. */ encode_PACKET(encbuf, &encx, &cmn2, &pkt); + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, encx, comm->header_encryption_ctx); + /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); } else { @@ -545,13 +594,16 @@ static int process_udp(n2n_sn_t * sss, rec_buf = udp_buf; encx = udp_size; + + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); } /* Common section to forward the final product. */ if(unicast) - try_forward(sss, &cmn, pkt.dstMac, rec_buf, encx); + try_forward(sss, comm, &cmn, pkt.dstMac, rec_buf, encx); else - try_broadcast(sss, &cmn, pkt.srcMac, rec_buf, encx); + try_broadcast(sss, comm, &cmn, pkt.srcMac, rec_buf, encx); break; } case MSG_TYPE_REGISTER: @@ -563,7 +615,12 @@ static int process_udp(n2n_sn_t * sss, uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; int unicast; /* non-zero if unicast */ - const uint8_t * rec_buf; /* either udp_buf or encbuf */ + uint8_t * rec_buf; /* either udp_buf or encbuf */ + + if(!comm) { + traceEvent(TRACE_DEBUG, "process_udp REGISTER from unknown community %s", cmn.community); + return -1; + } sss->stats.last_fwd=now; decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); @@ -601,7 +658,10 @@ static int process_udp(n2n_sn_t * sss, encx = udp_size; } - try_forward(sss, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); + + try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ } else traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); break; @@ -616,15 +676,12 @@ static int process_udp(n2n_sn_t * sss, n2n_common_t cmn2; uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; - struct sn_community *comm; /* Edge requesting registration with us. */ sss->stats.last_reg_super=now; ++(sss->stats.reg_super); decode_REGISTER_SUPER(®, &cmn, udp_buf, &rem, &idx); - HASH_FIND_COMMUNITY(sss->communities, (char*)cmn.community, comm); - /* Before we move any further, we need to check if the requested community is allowed by the supernode. In case it is not we do @@ -672,6 +729,9 @@ static int process_udp(n2n_sn_t * sss, encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx); + sendto(sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); @@ -682,13 +742,18 @@ static int process_udp(n2n_sn_t * sss, traceEvent(TRACE_INFO, "Discarded registration: unallowed community '%s'", (char*)cmn.community); break; - } case MSG_TYPE_QUERY_PEER: { + } + case MSG_TYPE_QUERY_PEER: { n2n_QUERY_PEER_t query; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; n2n_common_t cmn2; n2n_PEER_INFO_t pi; - struct sn_community *community; + + if(!comm) { + traceEvent(TRACE_DEBUG, "process_udp QUERY_PEER from unknown community %s", cmn.community); + return -1; + } decode_QUERY_PEER( &query, &cmn, udp_buf, &rem, &idx ); @@ -696,36 +761,35 @@ static int process_udp(n2n_sn_t * sss, macaddr_str( mac_buf, query.srcMac ), macaddr_str( mac_buf2, query.targetMac ) ); - HASH_FIND_COMMUNITY(sss->communities, (char*)cmn.community, community); + struct peer_info *scan; + HASH_FIND_PEER(comm->edges, query.targetMac, scan); - if(community) { - struct peer_info *scan; - HASH_FIND_PEER(community->edges, query.targetMac, scan); + if (scan) { + cmn2.ttl = N2N_DEFAULT_TTL; + cmn2.pc = n2n_peer_info; + cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; + memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); - if (scan) { - cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_peer_info; - cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; - memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); + pi.aflags = 0; + memcpy( pi.mac, query.targetMac, sizeof(n2n_mac_t) ); + pi.sock = scan->sock; - pi.aflags = 0; - memcpy( pi.mac, query.targetMac, sizeof(n2n_mac_t) ); - pi.sock = scan->sock; + encode_PEER_INFO( encbuf, &encx, &cmn2, &pi ); - encode_PEER_INFO( encbuf, &encx, &cmn2, &pi ); + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx); - sendto( sss->sock, encbuf, encx, 0, - (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); + sendto( sss->sock, encbuf, encx, 0, + (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); - traceEvent( TRACE_DEBUG, "Tx PEER_INFO to %s", - macaddr_str( mac_buf, query.srcMac ) ); - } else { - traceEvent( TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s", - macaddr_str( mac_buf, query.targetMac ) ); - } + traceEvent( TRACE_DEBUG, "Tx PEER_INFO to %s", + macaddr_str( mac_buf, query.srcMac ) ); + } else { + traceEvent( TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s", + macaddr_str( mac_buf, query.targetMac ) ); } - break; + break; } default: /* Not a known message type */ diff --git a/src/sn_utils.c b/src/sn_utils.c index 256e3af..2c8ef90 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -5,22 +5,24 @@ #define N2N_SN_LPORT_DEFAULT 7654 #define N2N_SN_PKTBUF_SIZE 2048 -static int try_forward(n2n_sn_t *sss, - const n2n_common_t *cmn, - const n2n_mac_t dstMac, - const uint8_t *pktbuf, - size_t pktsize); +static int try_forward(n2n_sn_t * sss, + const struct sn_community *comm, + const n2n_common_t * cmn, + const n2n_mac_t dstMac, + const uint8_t * pktbuf, + size_t pktsize); static ssize_t sendto_sock(n2n_sn_t *sss, const n2n_sock_t *sock, const uint8_t *pktbuf, size_t pktsize); -static int try_broadcast(n2n_sn_t *sss, - const n2n_common_t *cmn, - const n2n_mac_t srcMac, - const uint8_t *pktbuf, - size_t pktsize); +static int try_broadcast(n2n_sn_t * sss, + const struct sn_community *comm, + const n2n_common_t * cmn, + const n2n_mac_t srcMac, + const uint8_t * pktbuf, + size_t pktsize); static uint16_t reg_lifetime(n2n_sn_t *sss); @@ -42,59 +44,51 @@ static int process_udp(n2n_sn_t *sss, size_t udp_size, time_t now); -static int try_forward(n2n_sn_t *sss, - const n2n_common_t *cmn, - const n2n_mac_t dstMac, - const uint8_t *pktbuf, - size_t pktsize) +static int try_forward(n2n_sn_t * sss, + const struct sn_community *comm, + const n2n_common_t * cmn, + const n2n_mac_t dstMac, + const uint8_t * pktbuf, + size_t pktsize) { - struct peer_info *scan; - struct sn_community *community; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; + struct peer_info * scan; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; - HASH_FIND_COMMUNITY(sss->communities, (char *)cmn->community, community); + HASH_FIND_PEER(comm->edges, dstMac, scan); - if (!community) + if(NULL != scan) { - traceEvent(TRACE_DEBUG, "try_forward unknown community %s", cmn->community); - return (-1); - } + int data_sent_len; + data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); - HASH_FIND_PEER(community->edges, dstMac, scan); - - if (NULL != scan) - { - int data_sent_len; - data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); - - if (data_sent_len == pktsize) + if(data_sent_len == pktsize) { - ++(sss->stats.fwd); - traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %s", - pktsize, - sock_to_cstr(sockbuf, &(scan->sock)), - macaddr_str(mac_buf, scan->mac_addr)); + ++(sss->stats.fwd); + traceEvent(TRACE_DEBUG, "unicast %lu to [%s] %s", + pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr)); } - else + else { - ++(sss->stats.errors); - traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", - pktsize, - sock_to_cstr(sockbuf, &(scan->sock)), - macaddr_str(mac_buf, scan->mac_addr), - errno, strerror(errno)); + ++(sss->stats.errors); + traceEvent(TRACE_ERROR, "unicast %lu to [%s] %s FAILED (%d: %s)", + pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr), + errno, strerror(errno)); } } - else + else { - traceEvent(TRACE_DEBUG, "try_forward unknown MAC"); + traceEvent(TRACE_DEBUG, "try_forward unknown MAC"); - /* Not a known MAC so drop. */ - return (-2); + /* Not a known MAC so drop. */ + return(-2); } - return (0); + return(0); } /** Send a datagram to the destination embodied in a n2n_sock_t. @@ -136,59 +130,49 @@ static ssize_t sendto_sock(n2n_sn_t *sss, * This will send the exact same datagram to zero or more edges registered to * the supernode. */ -static int try_broadcast(n2n_sn_t *sss, - const n2n_common_t *cmn, - const n2n_mac_t srcMac, - const uint8_t *pktbuf, - size_t pktsize) +static int try_broadcast(n2n_sn_t * sss, + const struct sn_community *comm, + const n2n_common_t * cmn, + const n2n_mac_t srcMac, + const uint8_t * pktbuf, + size_t pktsize) { - struct peer_info *scan, *tmp; - struct sn_community *community; - macstr_t mac_buf; - n2n_sock_str_t sockbuf; + struct peer_info *scan, *tmp; + macstr_t mac_buf; + n2n_sock_str_t sockbuf; - traceEvent(TRACE_DEBUG, "try_broadcast"); + traceEvent(TRACE_DEBUG, "try_broadcast"); - HASH_FIND_COMMUNITY(sss->communities, (char *)cmn->community, community); + HASH_ITER(hh, comm->edges, scan, tmp) { + if(memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) != 0) { + /* REVISIT: exclude if the destination socket is where the packet came from. */ + int data_sent_len; - if (community) - { - HASH_ITER(hh, community->edges, scan, tmp) - { - if (memcmp(srcMac, scan->mac_addr, sizeof(n2n_mac_t)) != 0) - { - /* REVISIT: exclude if the destination socket is where the packet came from. */ - int data_sent_len; + data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); - data_sent_len = sendto_sock(sss, &(scan->sock), pktbuf, pktsize); - - if (data_sent_len != pktsize) - { - ++(sss->stats.errors); - traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", - pktsize, - sock_to_cstr(sockbuf, &(scan->sock)), - macaddr_str(mac_buf, scan->mac_addr), - strerror(errno)); - } - else - { - ++(sss->stats.broadcast); - traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", - pktsize, - sock_to_cstr(sockbuf, &(scan->sock)), - macaddr_str(mac_buf, scan->mac_addr)); - } - } - } + if(data_sent_len != pktsize) + { + ++(sss->stats.errors); + traceEvent(TRACE_WARNING, "multicast %lu to [%s] %s failed %s", + pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr), + strerror(errno)); + } + else + { + ++(sss->stats.broadcast); + traceEvent(TRACE_DEBUG, "multicast %lu to [%s] %s", + pktsize, + sock_to_cstr(sockbuf, &(scan->sock)), + macaddr_str(mac_buf, scan->mac_addr)); + } } - else - traceEvent(TRACE_INFO, "ignoring broadcast on unknown community %s\n", - cmn->community); - - return 0; + } + return 0; } + /** Initialise the supernode structure */ int sn_init(n2n_sn_t *sss) { @@ -373,316 +357,372 @@ static int process_mgmt(n2n_sn_t *sss, /** Examine a datagram and determine what to do with it. * */ -static int process_udp(n2n_sn_t *sss, - const struct sockaddr_in *sender_sock, - uint8_t *udp_buf, - size_t udp_size, - time_t now) +static int process_udp(n2n_sn_t * sss, + const struct sockaddr_in * sender_sock, + uint8_t * udp_buf, + size_t udp_size, + time_t now) { - n2n_common_t cmn; /* common fields in the packet header */ - size_t rem; - size_t idx; - int8_t he = HEADER_ENCRYPTION_UNKNOWN; - size_t msg_type; - uint8_t from_supernode; - macstr_t mac_buf; - macstr_t mac_buf2; - n2n_sock_str_t sockbuf; - char buf[32]; + n2n_common_t cmn; /* common fields in the packet header */ + size_t rem; + size_t idx; + size_t msg_type; + uint8_t from_supernode; + macstr_t mac_buf; + macstr_t mac_buf2; + n2n_sock_str_t sockbuf; + char buf[32]; + struct sn_community *comm, *tmp; - traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]", - udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), - ntohs(sender_sock->sin_port)); + traceEvent(TRACE_DEBUG, "Processing incoming UDP packet [len: %lu][sender: %s:%u]", + udp_size, intoa(ntohl(sender_sock->sin_addr.s_addr), buf, sizeof(buf)), + ntohs(sender_sock->sin_port)); - he = packet_header_decrypt_if_required (udp_buf, udp_size, sss->communities); - if (he < 0) - return -1; /* something wrong during packet decryption */ - - /* Use decode_common() to determine the kind of packet then process it: - * - * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK - * - * REGISTER, REGISTER_ACK and PACKET messages are forwarded to their - * destination edge. If the destination is not known then PACKETs are - * broadcast. - */ - - rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */ - idx = 0; /* marches through packet header as parts are decoded. */ - if (decode_common(&cmn, udp_buf, &rem, &idx) < 0) - { - traceEvent(TRACE_ERROR, "Failed to decode common section"); - return -1; /* failed to decode packet */ + /* check if header is unenrypted. the following check is around 99.99962 percent reliable. + * it heavily relies on the structure of packet's common part + * changes to wire.c:encode/decode_common need to go together with this code */ + if (udp_size < 20) { + traceEvent(TRACE_DEBUG, "process_udp dropped a packet too short to be valid."); + return -1; + } + if ( (udp_buf[19] == (uint8_t)0x00) // null terminated community name + && (udp_buf[00] == N2N_PKT_VERSION) // correct packet version + && ((be16toh (*(uint16_t*)&(udp_buf[02])) & N2N_FLAGS_TYPE_MASK ) <= MSG_TYPE_MAX_TYPE ) // message type + && ( be16toh (*(uint16_t*)&(udp_buf[02])) < N2N_FLAGS_OPTIONS) // flags + ) { + /* most probably unencrypted */ + /* make sure, no downgrading happens here and no unencrypted packets can be + * injected in a community which definitely deals with encrypted headers */ + HASH_FIND_COMMUNITY(sss->communities, (char *)&udp_buf[04], comm); + if (comm) { + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) { + traceEvent(TRACE_DEBUG, "process_udp dropped a packet with unencrypted header " + "addressed to community '%s' which uses encrypted headers.", + comm->community); + return -1; + } + if (comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { + traceEvent (TRACE_INFO, "process_udp locked community '%s' to using " + "unencrypted headers.", comm->community); + /* set 'no encryption' in case it is not set yet */ + comm->header_encryption = HEADER_ENCRYPTION_NONE; + comm->header_encryption_ctx = NULL; + } } - - msg_type = cmn.pc; /* packet code */ - from_supernode = cmn.flags & N2N_FLAGS_FROM_SUPERNODE; - - if (cmn.ttl < 1) - { - traceEvent(TRACE_WARNING, "Expired TTL"); - return 0; /* Don't process further */ - } - - --(cmn.ttl); /* The value copied into all forwarded packets. */ - - switch (msg_type) - { - case MSG_TYPE_PACKET: - { - /* PACKET from one edge to another edge via supernode. */ - - /* pkt will be modified in place and recoded to an output of potentially - * different size due to addition of the socket.*/ - n2n_PACKET_t pkt; - n2n_common_t cmn2; - uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; - size_t encx = 0; - int unicast; /* non-zero if unicast */ - const uint8_t *rec_buf; /* either udp_buf or encbuf */ - - sss->stats.last_fwd = now; - decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); - - unicast = (0 == is_multi_broadcast(pkt.dstMac)); - - traceEvent(TRACE_DEBUG, "RX PACKET (%s) %s -> %s %s", - (unicast ? "unicast" : "multicast"), - macaddr_str(mac_buf, pkt.srcMac), - macaddr_str(mac_buf2, pkt.dstMac), - (from_supernode ? "from sn" : "local")); - - if (!from_supernode) - { - memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); - - /* We are going to add socket even if it was not there before */ - cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; - - pkt.sock.family = AF_INET; - pkt.sock.port = ntohs(sender_sock->sin_port); - memcpy(pkt.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); - - rec_buf = encbuf; - - /* Re-encode the header. */ - encode_PACKET(encbuf, &encx, &cmn2, &pkt); - - /* Copy the original payload unchanged */ - encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); + } else { + /* most probably encrypted */ + /* cycle through the known communities (as keys) to eventually decrypt */ + uint32_t ret = 0; + HASH_ITER (hh, sss->communities, comm, tmp) { + /* skip the definitely unencrypted communities */ + if (comm->header_encryption == HEADER_ENCRYPTION_NONE) + continue; + if ( (ret = packet_header_decrypt (udp_buf, udp_size, comm->community, comm->header_encryption_ctx)) ) { + if (comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { + traceEvent (TRACE_INFO, "process_udp locked community '%s' to using " + "encrypted headers.", comm->community); + /* set 'encrypted' in case it is not set yet */ + comm->header_encryption = HEADER_ENCRYPTION_ENABLED; } - else - { - /* Already from a supernode. Nothing to modify, just pass to - * destination. */ - - traceEvent(TRACE_DEBUG, "Rx PACKET fwd unmodified"); - - rec_buf = udp_buf; - encx = udp_size; - } - - /* Common section to forward the final product. */ - if (unicast) - try_forward(sss, &cmn, pkt.dstMac, rec_buf, encx); - else - try_broadcast(sss, &cmn, pkt.srcMac, rec_buf, encx); + // no need to test further communities break; + } } - case MSG_TYPE_REGISTER: - { - /* Forwarding a REGISTER from one edge to the next */ - - n2n_REGISTER_t reg; - n2n_common_t cmn2; - uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; - size_t encx = 0; - int unicast; /* non-zero if unicast */ - const uint8_t *rec_buf; /* either udp_buf or encbuf */ - - sss->stats.last_fwd = now; - decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); - - unicast = (0 == is_multi_broadcast(reg.dstMac)); - - if (unicast) - { - traceEvent(TRACE_DEBUG, "Rx REGISTER %s -> %s %s", - macaddr_str(mac_buf, reg.srcMac), - macaddr_str(mac_buf2, reg.dstMac), - ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE) ? "from sn" : "local")); - - if (0 == (cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) - { - memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); - - /* We are going to add socket even if it was not there before */ - cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; - - reg.sock.family = AF_INET; - reg.sock.port = ntohs(sender_sock->sin_port); - memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); - - rec_buf = encbuf; - - /* Re-encode the header. */ - encode_REGISTER(encbuf, &encx, &cmn2, ®); - - /* Copy the original payload unchanged */ - encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); - } - else - { - /* Already from a supernode. Nothing to modify, just pass to - * destination. */ - - rec_buf = udp_buf; - encx = udp_size; - } - - try_forward(sss, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ - } - else - traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); - break; + if (!ret) { + // no matching key/community + traceEvent(TRACE_DEBUG, "process_udp dropped a packet with seemingly encrypted header " + "for which no matching community which uses encrypted headers was found."); + return -1; } - case MSG_TYPE_REGISTER_ACK: - traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode"); - break; - case MSG_TYPE_REGISTER_SUPER: - { - n2n_REGISTER_SUPER_t reg; - n2n_REGISTER_SUPER_ACK_t ack; - n2n_common_t cmn2; - uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; - size_t encx = 0; - struct sn_community *comm; + } - /* Edge requesting registration with us. */ - sss->stats.last_reg_super = now; - ++(sss->stats.reg_super); - decode_REGISTER_SUPER(®, &cmn, udp_buf, &rem, &idx); + /* Use decode_common() to determine the kind of packet then process it: + * + * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK + * + * REGISTER, REGISTER_ACK and PACKET messages are forwarded to their + * destination edge. If the destination is not known then PACKETs are + * broadcast. + */ - HASH_FIND_COMMUNITY(sss->communities, (char *)cmn.community, comm); + rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */ + idx = 0; /* marches through packet header as parts are decoded. */ + if(decode_common(&cmn, udp_buf, &rem, &idx) < 0) { + traceEvent(TRACE_ERROR, "Failed to decode common section"); + return -1; /* failed to decode packet */ + } - /* - Before we move any further, we need to check if the requested - community is allowed by the supernode. In case it is not we do - not report any message back to the edge to hide the supernode - existance (better from the security standpoint) - */ - if (!comm && !sss->lock_communities) - { - comm = calloc(1, sizeof(struct sn_community)); + msg_type = cmn.pc; /* packet code */ + from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; - if (comm) - { - strncpy(comm->community, (char *)cmn.community, N2N_COMMUNITY_SIZE - 1); - comm->community[N2N_COMMUNITY_SIZE - 1] = '\0'; - /* new communities introduced by REGISTERs could not have had encrypted header */ - comm->header_encryption = HEADER_ENCRYPTION_NONE; - comm->header_encryption_ctx = NULL; + if(cmn.ttl < 1) { + traceEvent(TRACE_WARNING, "Expired TTL"); + return 0; /* Don't process further */ + } - HASH_ADD_STR(sss->communities, community, comm); + --(cmn.ttl); /* The value copied into all forwarded packets. */ - traceEvent(TRACE_INFO, "New community: %s", comm->community); - } - } + switch(msg_type) { + case MSG_TYPE_PACKET: + { + /* PACKET from one edge to another edge via supernode. */ - if (comm) - { - cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_register_super_ack; - cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; - memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); + /* pkt will be modified in place and recoded to an output of potentially + * different size due to addition of the socket.*/ + n2n_PACKET_t pkt; + n2n_common_t cmn2; + uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; + size_t encx=0; + int unicast; /* non-zero if unicast */ + uint8_t * rec_buf; /* either udp_buf or encbuf */ - memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t)); - memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t)); - ack.lifetime = reg_lifetime(sss); - - ack.sock.family = AF_INET; - ack.sock.port = ntohs(sender_sock->sin_port); - memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); - - ack.num_sn = 0; /* No backup */ - memset(&(ack.sn_bak), 0, sizeof(n2n_sock_t)); - - traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", - macaddr_str(mac_buf, reg.edgeMac), - sock_to_cstr(sockbuf, &(ack.sock))); - - update_edge(sss, reg.edgeMac, comm, &(ack.sock), now); - - encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); - - sendto(sss->sock, ackbuf, encx, 0, - (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); - - traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", - macaddr_str(mac_buf, reg.edgeMac), - sock_to_cstr(sockbuf, &(ack.sock))); - } - else - traceEvent(TRACE_INFO, "Discarded registration: unallowed community '%s'", - (char *)cmn.community); - break; + if(!comm) { + traceEvent(TRACE_DEBUG, "process_udp PACKET with unknown community %s", cmn.community); + return -1; } - case MSG_TYPE_QUERY_PEER: - { - n2n_QUERY_PEER_t query; - uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; - size_t encx = 0; - n2n_common_t cmn2; - n2n_PEER_INFO_t pi; - struct sn_community *community; - decode_QUERY_PEER(&query, &cmn, udp_buf, &rem, &idx); + sss->stats.last_fwd=now; + decode_PACKET(&pkt, &cmn, udp_buf, &rem, &idx); - traceEvent(TRACE_DEBUG, "Rx QUERY_PEER from %s for %s", - macaddr_str(mac_buf, query.srcMac), - macaddr_str(mac_buf2, query.targetMac)); + unicast = (0 == is_multi_broadcast(pkt.dstMac)); - HASH_FIND_COMMUNITY(sss->communities, (char *)cmn.community, community); + traceEvent(TRACE_DEBUG, "RX PACKET (%s) %s -> %s %s", + (unicast?"unicast":"multicast"), + macaddr_str(mac_buf, pkt.srcMac), + macaddr_str(mac_buf2, pkt.dstMac), + (from_supernode?"from sn":"local")); - if (community) - { - struct peer_info *scan; - HASH_FIND_PEER(community->edges, query.targetMac, scan); + if(!from_supernode) { + memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); - if (scan) - { - cmn2.ttl = N2N_DEFAULT_TTL; - cmn2.pc = n2n_peer_info; - cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; - memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); + /* We are going to add socket even if it was not there before */ + cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; - pi.aflags = 0; - memcpy(pi.mac, query.targetMac, sizeof(n2n_mac_t)); - pi.sock = scan->sock; + pkt.sock.family = AF_INET; + pkt.sock.port = ntohs(sender_sock->sin_port); + memcpy(pkt.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); - encode_PEER_INFO(encbuf, &encx, &cmn2, &pi); + rec_buf = encbuf; - sendto(sss->sock, encbuf, encx, 0, - (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); + /* Re-encode the header. */ + encode_PACKET(encbuf, &encx, &cmn2, &pkt); - traceEvent(TRACE_DEBUG, "Tx PEER_INFO to %s", - macaddr_str(mac_buf, query.srcMac)); - } - else - { - traceEvent(TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s", - macaddr_str(mac_buf, query.targetMac)); - } - } + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, encx, comm->header_encryption_ctx); - break; + /* Copy the original payload unchanged */ + encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); + } else { + /* Already from a supernode. Nothing to modify, just pass to + * destination. */ + + traceEvent(TRACE_DEBUG, "Rx PACKET fwd unmodified"); + + rec_buf = udp_buf; + encx = udp_size; + + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); } - default: - /* Not a known message type */ - traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); - } /* switch(msg_type) */ - return 0; + /* Common section to forward the final product. */ + if(unicast) + try_forward(sss, comm, &cmn, pkt.dstMac, rec_buf, encx); + else + try_broadcast(sss, comm, &cmn, pkt.srcMac, rec_buf, encx); + break; + } + case MSG_TYPE_REGISTER: + { + /* Forwarding a REGISTER from one edge to the next */ + + n2n_REGISTER_t reg; + n2n_common_t cmn2; + uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; + size_t encx=0; + int unicast; /* non-zero if unicast */ + uint8_t * rec_buf; /* either udp_buf or encbuf */ + + if(!comm) { + traceEvent(TRACE_DEBUG, "process_udp REGISTER from unknown community %s", cmn.community); + return -1; + } + + sss->stats.last_fwd=now; + decode_REGISTER(®, &cmn, udp_buf, &rem, &idx); + + unicast = (0 == is_multi_broadcast(reg.dstMac)); + + if(unicast) { + traceEvent(TRACE_DEBUG, "Rx REGISTER %s -> %s %s", + macaddr_str(mac_buf, reg.srcMac), + macaddr_str(mac_buf2, reg.dstMac), + ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local")); + + if(0 == (cmn.flags & N2N_FLAGS_FROM_SUPERNODE)) { + memcpy(&cmn2, &cmn, sizeof(n2n_common_t)); + + /* We are going to add socket even if it was not there before */ + cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; + + reg.sock.family = AF_INET; + reg.sock.port = ntohs(sender_sock->sin_port); + memcpy(reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); + + rec_buf = encbuf; + + /* Re-encode the header. */ + encode_REGISTER(encbuf, &encx, &cmn2, ®); + + /* Copy the original payload unchanged */ + encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); + } else { + /* Already from a supernode. Nothing to modify, just pass to + * destination. */ + + rec_buf = udp_buf; + encx = udp_size; + } + + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); + + try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ + } else + traceEvent(TRACE_ERROR, "Rx REGISTER with multicast destination"); + break; + } + case MSG_TYPE_REGISTER_ACK: + traceEvent(TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode"); + break; + case MSG_TYPE_REGISTER_SUPER: + { + n2n_REGISTER_SUPER_t reg; + n2n_REGISTER_SUPER_ACK_t ack; + n2n_common_t cmn2; + uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; + size_t encx=0; + + /* Edge requesting registration with us. */ + sss->stats.last_reg_super=now; + ++(sss->stats.reg_super); + decode_REGISTER_SUPER(®, &cmn, udp_buf, &rem, &idx); + + /* + Before we move any further, we need to check if the requested + community is allowed by the supernode. In case it is not we do + not report any message back to the edge to hide the supernode + existance (better from the security standpoint) + */ + if(!comm && !sss->lock_communities) { + comm = calloc(1, sizeof(struct sn_community)); + + if(comm) { + strncpy(comm->community, (char*)cmn.community, N2N_COMMUNITY_SIZE-1); + comm->community[N2N_COMMUNITY_SIZE-1] = '\0'; + /* new communities introduced by REGISTERs could not have had encrypted header */ + comm->header_encryption = HEADER_ENCRYPTION_NONE; + comm->header_encryption_ctx = NULL; + + HASH_ADD_STR(sss->communities, community, comm); + + traceEvent(TRACE_INFO, "New community: %s", comm->community); + } + } + + if(comm) { + cmn2.ttl = N2N_DEFAULT_TTL; + cmn2.pc = n2n_register_super_ack; + cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; + memcpy(cmn2.community, cmn.community, sizeof(n2n_community_t)); + + memcpy(&(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t)); + memcpy(ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t)); + ack.lifetime = reg_lifetime(sss); + + ack.sock.family = AF_INET; + ack.sock.port = ntohs(sender_sock->sin_port); + memcpy(ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE); + + ack.num_sn=0; /* No backup */ + memset(&(ack.sn_bak), 0, sizeof(n2n_sock_t)); + + traceEvent(TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", + macaddr_str(mac_buf, reg.edgeMac), + sock_to_cstr(sockbuf, &(ack.sock))); + + update_edge(sss, reg.edgeMac, comm, &(ack.sock), now); + + encode_REGISTER_SUPER_ACK(ackbuf, &encx, &cmn2, &ack); + + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx); + + sendto(sss->sock, ackbuf, encx, 0, + (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); + + traceEvent(TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", + macaddr_str(mac_buf, reg.edgeMac), + sock_to_cstr(sockbuf, &(ack.sock))); + } else + traceEvent(TRACE_INFO, "Discarded registration: unallowed community '%s'", + (char*)cmn.community); + break; + } + case MSG_TYPE_QUERY_PEER: { + n2n_QUERY_PEER_t query; + uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; + size_t encx=0; + n2n_common_t cmn2; + n2n_PEER_INFO_t pi; + + if(!comm) { + traceEvent(TRACE_DEBUG, "process_udp QUERY_PEER from unknown community %s", cmn.community); + return -1; + } + + decode_QUERY_PEER( &query, &cmn, udp_buf, &rem, &idx ); + + traceEvent( TRACE_DEBUG, "Rx QUERY_PEER from %s for %s", + macaddr_str( mac_buf, query.srcMac ), + macaddr_str( mac_buf2, query.targetMac ) ); + + struct peer_info *scan; + HASH_FIND_PEER(comm->edges, query.targetMac, scan); + + if (scan) { + cmn2.ttl = N2N_DEFAULT_TTL; + cmn2.pc = n2n_peer_info; + cmn2.flags = N2N_FLAGS_FROM_SUPERNODE; + memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); + + pi.aflags = 0; + memcpy( pi.mac, query.targetMac, sizeof(n2n_mac_t) ); + pi.sock = scan->sock; + + encode_PEER_INFO( encbuf, &encx, &cmn2, &pi ); + + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx); + + sendto( sss->sock, encbuf, encx, 0, + (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); + + traceEvent( TRACE_DEBUG, "Tx PEER_INFO to %s", + macaddr_str( mac_buf, query.srcMac ) ); + } else { + traceEvent( TRACE_DEBUG, "Ignoring QUERY_PEER for unknown edge %s", + macaddr_str( mac_buf, query.targetMac ) ); + } + + break; + } + default: + /* Not a known message type */ + traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); + } /* switch(msg_type) */ + + return 0; } /** Long lived processing entry point. Split out from main to simply From 62d811edf5f054cae1cad3e5d476b7a6cc73d348 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Tue, 23 Jun 2020 00:47:54 +0545 Subject: [PATCH 38/45] ifdef'ed openSSL-includes for use with AES present only --- include/n2n.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/n2n.h b/include/n2n.h index f38b09d..d39471a 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -135,8 +135,10 @@ typedef struct ether_hdr ether_hdr_t; #include #include #include +#ifdef N2N_HAVE_AES #include #include +#endif #include "minilzo.h" #include "n2n_define.h" From 1a5d753b98f1415bf3b1df7c64e21152f436bada Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Wed, 24 Jun 2020 09:49:36 +0200 Subject: [PATCH 39/45] Warning fix --- src/edge_utils.c | 48 ++++++++++++++++++++--------------------- src/header_encryption.c | 4 ++-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/edge_utils.c b/src/edge_utils.c index 0b412c4..ca054b2 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -256,7 +256,7 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r } /* Set the key schedule (context) for header encryption if enabled */ - if (conf->header_encryption == HEADER_ENCRYPTION_ENABLED) { + if(conf->header_encryption == HEADER_ENCRYPTION_ENABLED) { traceEvent(TRACE_NORMAL, "Header encryption is enabled."); packet_header_setup_key ((char *)(conf->community_name), &(eee->conf.header_encryption_ctx)); } @@ -468,7 +468,7 @@ static void register_with_new_peer(n2n_edge_t * eee, * So we can alternatively set TTL so that the packet sent to peer never really reaches * The register_ttl is basically nat level + 1. Set it to 1 means host like DMZ. */ - if (eee->conf.register_ttl == 1) { + if(eee->conf.register_ttl == 1) { /* We are DMZ host or port is directly accessible. Just let peer to send back the ack */ #ifndef WIN32 } else if(eee->conf.register_ttl > 1) { @@ -742,7 +742,7 @@ static void send_register_super(n2n_edge_t * eee, traceEvent(TRACE_DEBUG, "send REGISTER_SUPER to %s", sock_to_cstr(sockbuf, supernode)); - if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); @@ -773,7 +773,7 @@ static void send_query_peer( n2n_edge_t * eee, traceEvent( TRACE_DEBUG, "send QUERY_PEER to supernode" ); - if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); @@ -819,7 +819,7 @@ static void send_register(n2n_edge_t * eee, traceEvent(TRACE_INFO, "Send REGISTER to %s", sock_to_cstr(sockbuf, remote_peer)); - if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); @@ -861,7 +861,7 @@ static void send_register_ack(n2n_edge_t * eee, traceEvent(TRACE_INFO, "send REGISTER_ACK %s", sock_to_cstr(sockbuf, remote_peer)); - if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); @@ -888,7 +888,7 @@ static void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) { /* Give up on that supernode and try the next one. */ ++(eee->sn_idx); - if (eee->sn_idx >= eee->conf.sn_num) { + if(eee->sn_idx >= eee->conf.sn_num) { /* Got to end of list, go back to the start. Also works for list of one entry. */ eee->sn_idx=0; } @@ -1024,7 +1024,7 @@ static int handle_PACKET(n2n_edge_t * eee, deflated_len = N2N_PKT_BUF_SIZE; deflation_buffer = malloc (deflated_len); deflated_len = (int32_t)ZSTD_decompress (deflation_buffer, deflated_len, eth_payload, eth_size); - if (ZSTD_isError(deflated_len)) { + if(ZSTD_isError(deflated_len)) { traceEvent (TRACE_ERROR, "payload decompression failed with zstd error '%s'.", ZSTD_getErrorName(deflated_len)); free (deflation_buffer); @@ -1038,7 +1038,7 @@ static int handle_PACKET(n2n_edge_t * eee, return (-1); // cannot handle it } - if (rx_compression_id) { + if(rx_compression_id) { traceEvent (TRACE_DEBUG, "payload decompression [%s]: deflated %u bytes to %u bytes", compression_str(rx_compression_id), eth_size, (int)deflated_len); memcpy(eth_payload ,deflation_buffer, deflated_len ); @@ -1077,7 +1077,7 @@ static int handle_PACKET(n2n_edge_t * eee, traceEvent(TRACE_DEBUG, "sending to TAP %u", (unsigned int)eth_size); data_sent_len = tuntap_write(&(eee->device), eth_payload, eth_size); - if (data_sent_len == eth_size) + if(data_sent_len == eth_size) { retval = 0; } @@ -1406,15 +1406,15 @@ static void send_packet2net(n2n_edge_t * eee, // compression needs to be tried before encode_PACKET is called for compression indication gets encoded there pkt.compression = N2N_COMPRESSION_ID_NONE; - if (eee->conf.compression) { + if(eee->conf.compression) { uint8_t * compression_buffer; int32_t compression_len; switch (eee->conf.compression) { case N2N_COMPRESSION_ID_LZO: compression_buffer = malloc (len + len / 16 + 64 + 3); - if (lzo1x_1_compress(tap_pkt, len, compression_buffer, (lzo_uint*)&compression_len, wrkmem) == LZO_E_OK) { - if (compression_len < len) { + if(lzo1x_1_compress(tap_pkt, len, compression_buffer, (lzo_uint*)&compression_len, wrkmem) == LZO_E_OK) { + if(compression_len < len) { pkt.compression = N2N_COMPRESSION_ID_LZO; } } @@ -1424,8 +1424,8 @@ static void send_packet2net(n2n_edge_t * eee, compression_len = N2N_PKT_BUF_SIZE + 128; compression_buffer = malloc (compression_len); // leaves enough room, for exact size call compression_len = ZSTD_compressBound (len); (slower) compression_len = (int32_t)ZSTD_compress(compression_buffer, compression_len, tap_pkt, len, ZSTD_COMPRESSION_LEVEL) ; - if (!ZSTD_isError(compression_len)) { - if (compression_len < len) { + if(!ZSTD_isError(compression_len)) { + if(compression_len < len) { pkt.compression = N2N_COMPRESSION_ID_ZSTD; } } else { @@ -1440,7 +1440,7 @@ static void send_packet2net(n2n_edge_t * eee, break; } - if (pkt.compression) { + if(pkt.compression) { traceEvent (TRACE_DEBUG, "payload compression [%s]: compressed %u bytes to %u bytes\n", compression_str(pkt.compression), len, compression_len); @@ -1459,7 +1459,7 @@ static void send_packet2net(n2n_edge_t * eee, idx=0; encode_PACKET(pktbuf, &idx, &cmn, &pkt); - if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); idx += eee->transop.fwd(&eee->transop, @@ -1495,7 +1495,7 @@ static void readFromTAPSocket(n2n_edge_t * eee) { ssize_t len; #ifdef __ANDROID_NDK__ - if (uip_arp_len != 0) { + if(uip_arp_len != 0) { len = uip_arp_len; memcpy(eth_pkt, uip_arp_buf, MIN(uip_arp_len, N2N_PKT_BUF_SIZE)); traceEvent(TRACE_DEBUG, "ARP reply packet to send"); @@ -1587,8 +1587,8 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { traceEvent(TRACE_DEBUG, "### Rx N2N UDP (%d) from %s", (signed int)recvlen, sock_to_cstr(sockbuf1, &sender)); - if (eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) - if ( packet_header_decrypt (udp_buf, recvlen, (char *)eee->conf.community_name, eee->conf.header_encryption_ctx) < 0) { + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + if( packet_header_decrypt (udp_buf, recvlen, (char *)eee->conf.community_name, eee->conf.header_encryption_ctx) == 0) { traceEvent(TRACE_DEBUG, "readFromIPSocket failed to decrypt header."); return; } @@ -1759,7 +1759,7 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { } HASH_FIND_PEER(eee->pending_peers, pi.mac, scan); - if (scan) { + if(scan) { scan->sock = pi.sock; traceEvent(TRACE_INFO, "Rx PEER_INFO for %s: is at %s", macaddr_str(mac_buf1, pi.mac), @@ -1777,7 +1777,7 @@ static void readFromIPSocket(n2n_edge_t * eee, int in_sock) { traceEvent(TRACE_WARNING, "Unable to handle packet type %d: ignored", (signed int)msg_type); return; } /* switch(msg_type) */ - } else if(from_supernode) /* if (community match) */ + } else if(from_supernode) /* if(community match) */ traceEvent(TRACE_WARNING, "Received packet with unknown community"); else traceEvent(TRACE_INFO, "Ignoring packet with unknown community"); @@ -1879,7 +1879,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) { #endif #ifdef __ANDROID_NDK__ - if (uip_arp_len != 0) { + if(uip_arp_len != 0) { readFromTAPSocket(eee); uip_arp_len = 0; } @@ -1921,7 +1921,7 @@ int run_edge_loop(n2n_edge_t * eee, int *keep_running) { } #ifdef __ANDROID_NDK__ - if ((nowTime - lastArpPeriod) > ARP_PERIOD_INTERVAL) { + if((nowTime - lastArpPeriod) > ARP_PERIOD_INTERVAL) { uip_arp_timer(); lastArpPeriod = nowTime; } diff --git a/src/header_encryption.c b/src/header_encryption.c index 4151432..4d8c618 100644 --- a/src/header_encryption.c +++ b/src/header_encryption.c @@ -41,7 +41,7 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, // so, as a first step, decrypt 4 bytes only starting at byte 12 speck_he ((uint8_t*)&test_magic, &packet[12], 4, iv, (speck_context_t*)ctx); test_magic = be32toh (test_magic); - if ( (((test_magic >> 8) << 8) == magic) // check the thre uppermost bytes + if( (((test_magic >> 8) << 8) == magic) // check the thre uppermost bytes && (((uint8_t)test_magic) <= packet_len) // lowest 8 bit of test_magic are header_len ) { // decrypt the complete header @@ -63,7 +63,7 @@ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_ uint64_t *iv64 = (uint64_t*)&iv; const uint32_t magic = 0x6E326E21; // = ASCII "n2n!" - if (header_len < 20) { + if(header_len < 20) { traceEvent(TRACE_DEBUG, "packet_header_encrypt dropped a packet too short to be valid."); return (-1); } From 1caf3b45918136c000282c5064b93abd38a06243 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 24 Jun 2020 15:15:42 +0545 Subject: [PATCH 40/45] shortened help text by three lines --- src/edge.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/edge.c b/src/edge.c index db6bd09..b88e524 100644 --- a/src/edge.c +++ b/src/edge.c @@ -184,20 +184,21 @@ static void help() { #endif printf("-r | Enable packet forwarding through n2n community.\n"); printf("-A1 | Disable payload encryption. Do not use with key (defaulting to Twofish then).\n"); - printf("-A2 | Use Twofish for payload encryption (default). Requires a key.\n"); + printf("-A2 ... -A5 or -A | Choose a cipher for payload encryption, requires a key: -A2 = Twofish (default),\n"); + printf(" | " #ifdef N2N_HAVE_AES - printf("-A3 or -A (deprecated) | Use AES-CBC for payload encryption. Requires a key.\n"); + "-A3 or -A (deprecated) = AES-CBC, " #endif #ifdef HAVE_OPENSSL_1_1 - printf("-A4 | Use ChaCha20 for payload encryption. Requires a key.\n"); + "-A4 = ChaCha20, " #endif - printf("-A5 | Use Speck for payload encryption. Requires a key.\n"); + "-A5 = Speck-CTR.\n"); printf("-H | Enable full header encryption. Requires supernode with fixed community.\n"); - printf("-z1 or -z | Enable lzo1x compression for outgoing data packets\n"); + printf("-z1 ... -z2 or -z | Enable compression for outgoing data packets: -z1 or -z = lzo1x" #ifdef N2N_HAVE_ZSTD - printf("-z2 | Enable zstd compression for outgoing data packets\n"); + ", -z2 = zstd" #endif - printf(" | (default=compression disabled)\n"); + " (default=disabled).\n"); printf("-E | Accept multicast MAC addresses (default=drop).\n"); printf("-S | Do not connect P2P. Always use the supernode.\n"); #ifdef __linux__ From 4d5a835553401820ab463a7f9dec8d58ea3eff85 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 24 Jun 2020 16:10:00 +0545 Subject: [PATCH 41/45] updated README.md --- README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index fb99257..5109b9e 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ A virtual network shared between multiple edge nodes in n2n is called a _communi N2N tries to establish a direct P2P connection between the edge nodes when possible. When this is not possible (usually due to special NAT devices), the supernode is also used to relay the packets. + ## Quick Setup Some Linux distributions already provide n2n as a package so a simple `sudo apt install n2n` will do the work. Alternatively, up to date packages for most distributions are available on [ntop repositories](http://packages.ntop.org/). @@ -73,6 +74,8 @@ On linux, compilation from source is straight forward: ./configure make +Parts of the code – especially Speck cipher and the header encryption – speedwise benefit from compiler optimizations and platform features such as NEON, SSE and AVX. To enable, use `./configure CFLAGS="-O3 -march=native"` instead. + # optionally install make install ``` @@ -102,18 +105,25 @@ Check out [IPv6.md](https://github.com/ntop/n2n/blob/dev/doc/IPv6.md) for more i n2n edge nodes use twofish encryption by default for compatibility reasons with existing versions. -**IMPORTANT** Encryption is only applied to the packet payload. Some metadata like the virtual MAC address -of the edge nodes, their IP address and the community are sent in cleartext. +Different encryption schemes are applied to the packet payload and to the header which +contains some metadata like the virtual MAC address of the edge nodes, their IP address and the community +name. When encryption is enabled, the supernode will not be able to decrypt the traffic exchanged between two edge nodes, but it will know that edge A is talking with edge B. Recently AES encryption support has been implemented, which increases both security and performance, so it is recommended to enable it on all the edge nodes that must have the -Ax value. When possible -(i.e. when n2n is compiled with OpenSSL 1.1) we recommend to use -A4 +(i.e. when n2n is compiled with OpenSSL 1.1) we recommend to use `-A3`. A benchmark of the encryption methods is available when compiled from source with `tools/n2n-benchmark`. +Use `-H` on the edges to enable header encryption. Note, that header encryption is a per-community +decision, i.e. all edges of one community need to have it either enabled or disabled. The supernode +can handle encrypted and unencrypted headers. As the key fro header encryption is derived from the +community names, it requires the supernode to be used with fixed communities `-c ` +parameter. + ## Contribution You can contribute to n2n in various ways: @@ -136,4 +146,4 @@ Here is a list of third-party projects connected to this repository. --- -(C) 2007-2019 - ntop.org and contributors +(C) 2007-2020 - ntop.org and contributors From 06e5ea2b85c4c932270a79c4648f86bdd83919db Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 24 Jun 2020 16:11:59 +0545 Subject: [PATCH 42/45] updated README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 5109b9e..e25d12a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,6 @@ A virtual network shared between multiple edge nodes in n2n is called a _communi N2N tries to establish a direct P2P connection between the edge nodes when possible. When this is not possible (usually due to special NAT devices), the supernode is also used to relay the packets. - ## Quick Setup Some Linux distributions already provide n2n as a package so a simple `sudo apt install n2n` will do the work. Alternatively, up to date packages for most distributions are available on [ntop repositories](http://packages.ntop.org/). From be89963884b79a0976c02048a2d6f370ba496e2a Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 24 Jun 2020 16:17:25 +0545 Subject: [PATCH 43/45] updated README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e25d12a..522da3e 100644 --- a/README.md +++ b/README.md @@ -73,12 +73,14 @@ On linux, compilation from source is straight forward: ./configure make -Parts of the code – especially Speck cipher and the header encryption – speedwise benefit from compiler optimizations and platform features such as NEON, SSE and AVX. To enable, use `./configure CFLAGS="-O3 -march=native"` instead. - # optionally install make install ``` +Parts of the code – especially Speck cipher and the header encryption – speedwise benefit +from compiler optimizations and platform features such as NEON, SSE and AVX. To enable, +use `./configure CFLAGS="-O3 -march=native"` for configuration instead. + For Windows, check out [Windows.md](doc/Windows.md) for compilation and run instuctions. For MacOS, check out [macOS.md](doc/macOS.md). From fe602751424da12174099dc2bb01f267c4e52a1a Mon Sep 17 00:00:00 2001 From: Logan007 Date: Wed, 24 Jun 2020 16:21:58 +0545 Subject: [PATCH 44/45] updated README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 522da3e..155a9e0 100644 --- a/README.md +++ b/README.md @@ -121,9 +121,9 @@ A benchmark of the encryption methods is available when compiled from source wit Use `-H` on the edges to enable header encryption. Note, that header encryption is a per-community decision, i.e. all edges of one community need to have it either enabled or disabled. The supernode -can handle encrypted and unencrypted headers. As the key fro header encryption is derived from the -community names, it requires the supernode to be used with fixed communities `-c ` -parameter. +can handle encrypted and unencrypted headers. As the key for header encryption is derived from the +community names, it requires the supernode to be used with fixed communities `-c ` +parameter. Also, reuse of once-publically-used community names for header encryption is not recomended. ## Contribution From f6229fefa9f5e7199f2ed80b7748f443063ed648 Mon Sep 17 00:00:00 2001 From: Logan oos Even <46396513+Logan007@users.noreply.github.com> Date: Wed, 24 Jun 2020 16:23:44 +0545 Subject: [PATCH 45/45] updated README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 155a9e0..385d713 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ so it is recommended to enable it on all the edge nodes that must have the -Ax v A benchmark of the encryption methods is available when compiled from source with `tools/n2n-benchmark`. Use `-H` on the edges to enable header encryption. Note, that header encryption is a per-community -decision, i.e. all edges of one community need to have it either enabled or disabled. The supernode +decision, i.e. _all_ edges of one community need to have it either enabled or disabled. The supernode can handle encrypted and unencrypted headers. As the key for header encryption is derived from the community names, it requires the supernode to be used with fixed communities `-c ` parameter. Also, reuse of once-publically-used community names for header encryption is not recomended.