From c7a8210078c65c7288b8eae7ba3230da423240a0 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 29 Jun 2020 15:13:36 +0545 Subject: [PATCH 1/6] added 96 bit block size for header iv encryption --- include/speck.h | 9 +++++ src/speck.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 4 deletions(-) diff --git a/include/speck.h b/include/speck.h index a456f77..4179e74 100644 --- a/include/speck.h +++ b/include/speck.h @@ -68,4 +68,13 @@ 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); +int speck_he_iv_encrypt (unsigned char *inout, speck_context_t *ctx); + + +int speck_he_iv_decrypt (unsigned char *inout, speck_context_t *ctx); + + +int speck_expand_key_he_iv (const unsigned char *k, speck_context_t *ctx); + + #endif diff --git a/src/speck.c b/src/speck.c index a5ced78..9ca7811 100644 --- a/src/speck.c +++ b/src/speck.c @@ -707,7 +707,7 @@ int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx) { A = htole64 ( ((u64 *)k)[0] ); B = htole64 ( ((u64 *)k)[1] ); - for (i = 0; i < 32; i ++) { + for (i = 0; i < 32; i++) { ctx->key[i] = A; R64 ( B, A, i); } @@ -715,8 +715,84 @@ int speck_expand_key_he (const unsigned char *k, speck_context_t *ctx) { } -// code for testing -- to be removed when finished +// ---------------------------------------------------------------------------------------- + + +// cipher SPECK -- 96 bit block size -- 96 bit key size -- ECB mode +// follows endianess rules as used in official implementation guide and NOT as in original 2013 cipher presentation +// used for IV in header encryption, thus the prefix 'he_iv_' +// for now: just plain C -- probably no need for AVX, SSE, NEON + +// prerequisite: lower 16 bit reset +#define ROTL48(x,r) (((((x)<<(r)) | (x>>(48-(r)))) >> 16) << 16) +#define ROTR48(x,r) (((((x)>>(r)) | ((x)<<(48-(r)))) >> 16) << 16) +#define ER96(x,y,k) (x=ROTR48(x,8), x+=y, x^=k, y=ROTL48(y,3), y^=x) +#define DR96(x,y,k) (y^=x, y=ROTR48(y,3), x^=k, x-=y, x=ROTL48(x,8)) + + +int speck_he_iv_encrypt (unsigned char *inout, speck_context_t *ctx) { + + u64 x, y; + int i; + + x = htole64 ( *(u64*)&inout[0] ); x <<= 16; + y = htole64 ( *(u64*)&inout[4] ); y >>= 16; y <<= 16; + + for (i = 0; i < 28; i++) + ER96 (y, x, ctx->key[i]); + + x >>= 16; x |= y << 32; + y >>= 32; + + ((u64*)inout)[0] = le64toh (x); + ((u32*)inout)[2] = le32toh (y); + + return 0; +} + + +int speck_he_iv_decrypt (unsigned char *inout, speck_context_t *ctx) { + + u64 x, y; + int i; + + x = htole64 ( *(u64*)&inout[0] ); x <<= 16; + y = htole64 ( *(u64*)&inout[4] ); y >>= 16; y <<= 16; + + for (i = 27; i >= 0; i--) + DR96 (y, x, ctx->key[i]); + + x >>= 16; x |= y << 32; + y >>= 32; + + ((u64*)inout)[0] = le64toh (x); + ((u32*)inout)[2] = le32toh (y); + + return 0; +} + + +int speck_expand_key_he_iv (const unsigned char *k, speck_context_t *ctx) { + + u64 A, B; + int i; + + A = htole64 ( *(u64 *)&k[0] ); A <<= 16; + B = htole64 ( *(u64 *)&k[4] ); B >>= 16; B <<= 16; + + for (i = 0; i < 28; i++) { + ctx->key[i] = A; + ER96 ( B, A, i << 16); + } + + return 1; +} + + +// ---------------------------------------------------------------------------------------- + /* +// code for testing -- to be removed when finished #include // for testing #include @@ -727,23 +803,30 @@ int speck_test () { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; + uint8_t k96[12] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D }; + 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 p96[12] = { 0x20, 0x75, 0x73, 0x61, 0x67, 0x65, + 0x2C, 0x20, 0x68, 0x6F, 0x77, 0x65 }; uint8_t pt[16] = { 0x00 }; - // expected outcome (according to pp. 35 & 36 of Implementation Guide) + // expected outcome (according to pp. 35 & 36 of Implementation Guide 1.1 as of 2019) and + // original cipher presentation as of 2013 in which notably a different endianess is used 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 }; - + uint8_t x96[12] = { 0xAA, 0x79, 0x8F, 0xDE, 0xBD, 0x62, + 0x78, 0x71, 0xAB, 0x09, 0x4D, 0x9E }; speck_context_t ctx; speck_expand_key (key, &ctx); @@ -775,6 +858,19 @@ int speck_test () { for (i=0; i < 16; i++) if (pt[i] != xt[i]) ret = 0; + speck_expand_key_he_iv (k96, &ctx); + speck_he_iv_encrypt (p96, &ctx); +// speck_he_iv_decrypt (p96, &ctx); +// speck_he_iv_encrypt (p96, &ctx); + + fprintf (stderr, "rk00: %016llx\n", ctx.key[0]); + fprintf (stderr, "rk27: %016llx\n", ctx.key[27]); + fprintf (stderr, "out : %016lx\n", *(uint64_t*)p96); + fprintf (stderr, "mem : " ); for (i=0; i < 12; i++) fprintf (stderr, "%02x ", p96[i]); fprintf (stderr, "\n"); + + for (i=0; i < 12; i++) + if (p96[i] != x96[i]) ret = 0; + return (ret); } @@ -783,4 +879,5 @@ int main (int argc, char* argv[]) { fprintf (stdout, "SPECK SELF TEST RESULT: %u\n", speck_test (0,NULL)); } + */ From a64cfa450eeac5ee2d7fc91b8286cbf9c04af100 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 29 Jun 2020 15:44:51 +0545 Subject: [PATCH 2/6] added 16-bit hashing --- include/pearson.h | 2 ++ src/pearson.c | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/include/pearson.h b/include/pearson.h index 6aaa604..2e32278 100644 --- a/include/pearson.h +++ b/include/pearson.h @@ -19,3 +19,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); + +uint16_t pearson_hash_16 (const uint8_t *in, size_t len); diff --git a/src/pearson.c b/src/pearson.c index 2e5313b..882e105 100644 --- a/src/pearson.c +++ b/src/pearson.c @@ -219,3 +219,23 @@ void pearson_hash_128 (uint8_t *out, const uint8_t *in, size_t len) { o = (uint64_t*)&out[8]; *o = lower_hash; } + + +// 16-bit hash: the return value has to be interpreted as uint16_t and +// follows machine-specific endianess in memory +uint16_t pearson_hash_16 (const uint8_t *in, size_t len) { + + uint16_t hash = 0; + uint16_t hash_mask = 0x0100; + + for (size_t i = 0; i < len; i++) { + // broadcast the character, xor into hash, make them different permutations + uint16_t c = (uint8_t)in[i]; + c |= c << 8; + hash ^= c ^ hash_mask; + // table lookup + hash = t[(uint8_t)hash] + (t[hash >> 8] << 8); + } + // output + return hash; +} From a6915fd6af117d00f7b3932b517f37145a8d261b Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 29 Jun 2020 15:50:05 +0545 Subject: [PATCH 3/6] prepared header iv encryption handling --- include/header_encryption.h | 7 +++++-- include/n2n.h | 4 +++- src/header_encryption.c | 16 +++++++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/include/header_encryption.h b/include/header_encryption.h index 74ad647..05e28a0 100644 --- a/include/header_encryption.h +++ b/include/header_encryption.h @@ -21,7 +21,10 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, char * community_name, he_context_t * ctx); -int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx); +int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx, + uint16_t checksum); -void packet_header_setup_key (const char * community_name, he_context_t ** ctx); +void packet_header_setup_key (const char * community_name, he_context_t ** ctx, + he_context_t ** ctx_iv); + diff --git a/include/n2n.h b/include/n2n.h index d39471a..a155d72 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -221,6 +221,7 @@ typedef struct n2n_edge_conf { 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_iv_ctx; /**< Header IV ecnryption cipher context, REMOVE as soon as seperte fileds for checksum and replay protection available */ 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 */ @@ -255,7 +256,8 @@ 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. */ + he_context_t *header_encryption_ctx; /* Header encryption cipher context. */ + he_context_t *header_iv_ctx; /* Header IV ecnryption cipher context, REMOVE as soon as seperte fileds for checksum and replay protection available */ struct peer_info *edges; /* Link list of registered edges. */ UT_hash_handle hh; /* makes this structure hashable */ diff --git a/src/header_encryption.c b/src/header_encryption.c index 4d8c618..948fd33 100644 --- a/src/header_encryption.c +++ b/src/header_encryption.c @@ -56,9 +56,11 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, /* ********************************************************************** */ -int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx) { +int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx, + uint16_t checksum) { uint8_t iv[16]; + uint16_t *iv16 = (uint16_t*)&iv; uint32_t *iv32 = (uint32_t*)&iv; uint64_t *iv64 = (uint64_t*)&iv; const uint32_t magic = 0x6E326E21; // = ASCII "n2n!" @@ -71,7 +73,8 @@ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_ memcpy (&packet[16], &packet[00], 4); iv64[0] = n2n_rand (); - iv32[2] = n2n_rand (); + iv16[4] = n2n_rand (); + iv16[5] = htobe16 (checksum); iv32[3] = htobe32 (magic); memcpy (packet, iv, 16); @@ -83,11 +86,18 @@ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_ /* ********************************************************************** */ -void packet_header_setup_key (const char * community_name, he_context_t ** ctx) { +void packet_header_setup_key (const char * community_name, he_context_t ** ctx, + he_context_t ** ctx_iv) { uint8_t key[16]; pearson_hash_128 (key, (uint8_t*)community_name, N2N_COMMUNITY_SIZE); *ctx = (he_context_t*)calloc(1, sizeof (speck_context_t)); speck_expand_key_he (key, (speck_context_t*)*ctx); + + // hash again and use last 96 bit (skipping 4 bytes) as key for IV encryption + // REMOVE as soon as checksum and replay protection get their own fields + pearson_hash_128 (key, key, sizeof (key)); + *ctx_iv = (he_context_t*)calloc(1, sizeof (speck_context_t)); + speck_expand_key_he_iv (&key[4], (speck_context_t*)*ctx_iv); } From 033b1890f2c6bb0fe9eb2086866e45a5398463e8 Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 29 Jun 2020 16:31:44 +0545 Subject: [PATCH 4/6] blended checksum into header iv --- src/edge_utils.c | 21 ++++++++++++++------- src/sn.c | 25 ++++++++++++++++--------- src/sn_utils.c | 23 +++++++++++++++-------- 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/edge_utils.c b/src/edge_utils.c index ca054b2..5183972 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -258,7 +258,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) { traceEvent(TRACE_NORMAL, "Header encryption is enabled."); - packet_header_setup_key ((char *)(conf->community_name), &(eee->conf.header_encryption_ctx)); + packet_header_setup_key ((char *)(conf->community_name), &(eee->conf.header_encryption_ctx),&(eee->conf.header_iv_ctx)); } if(eee->transop.no_encryption) @@ -743,7 +743,8 @@ static void send_register_super(n2n_edge_t * eee, sock_to_cstr(sockbuf, supernode)); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, + pearson_hash_16 (pktbuf, idx)); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); } @@ -774,7 +775,8 @@ 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); + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, + pearson_hash_16 (pktbuf, idx)); sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); } @@ -820,7 +822,8 @@ static void send_register(n2n_edge_t * eee, sock_to_cstr(sockbuf, remote_peer)); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, + pearson_hash_16 (pktbuf, idx)); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -862,7 +865,8 @@ static void send_register_ack(n2n_edge_t * eee, sock_to_cstr(sockbuf, remote_peer)); if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, + pearson_hash_16 (pktbuf, idx)); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -1459,8 +1463,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) - packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx); + uint16_t headerIdx = idx; idx += eee->transop.fwd(&eee->transop, pktbuf+idx, N2N_PKT_BUF_SIZE-idx, @@ -1469,6 +1472,10 @@ static void send_packet2net(n2n_edge_t * eee, 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); + if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (pktbuf, headerIdx, eee->conf.header_encryption_ctx, + pearson_hash_16 (pktbuf, idx)); + #ifdef MTU_ASSERT_VALUE { const u_int eth_udp_overhead = ETH_FRAMESIZE + IP4_MIN_SIZE + UDP_SIZE; diff --git a/src/sn.c b/src/sn.c index ec6d211..87c40ce 100644 --- a/src/sn.c +++ b/src/sn.c @@ -408,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), &(s->header_iv_ctx)); HASH_ADD_STR(sss->communities, community, s); num_communities++; @@ -580,12 +580,14 @@ 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); + uint16_t oldEncx = encx; /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); + + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, oldEncx, comm->header_encryption_ctx, + pearson_hash_16 (rec_buf, encx)); } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ @@ -596,7 +598,8 @@ static int process_udp(n2n_sn_t * sss, encx = udp_size; if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); + packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx, + pearson_hash_16 (rec_buf, udp_size)); } /* Common section to forward the final product. */ @@ -647,7 +650,7 @@ static int process_udp(n2n_sn_t * sss, /* Re-encode the header. */ encode_REGISTER(encbuf, &encx, &cmn2, ®); - +// !!! does this ever happen? does REGISTER ever come with a payload ??? !!! /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); } else { @@ -659,7 +662,9 @@ static int process_udp(n2n_sn_t * sss, } if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); + packet_header_encrypt (rec_buf, encx, comm->header_encryption_ctx, + pearson_hash_16 (rec_buf, encx)); + try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ } else @@ -730,7 +735,8 @@ 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); + packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx, + pearson_hash_16 (ackbuf, encx)); sendto(sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); @@ -777,7 +783,8 @@ static int process_udp(n2n_sn_t * sss, encode_PEER_INFO( encbuf, &encx, &cmn2, &pi ); if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx); + packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx, + pearson_hash_16 (encbuf, encx)); sendto( sss->sock, encbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); diff --git a/src/sn_utils.c b/src/sn_utils.c index 2c8ef90..d176b11 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -506,12 +506,15 @@ 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); + uint16_t oldEncx = encx; /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); + + if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) + packet_header_encrypt (rec_buf, oldEncx, comm->header_encryption_ctx, + pearson_hash_16 (rec_buf, encx)); + } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ @@ -522,7 +525,8 @@ static int process_udp(n2n_sn_t * sss, encx = udp_size; if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); + packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx, + pearson_hash_16 (rec_buf, udp_size)); } /* Common section to forward the final product. */ @@ -573,7 +577,7 @@ static int process_udp(n2n_sn_t * sss, /* Re-encode the header. */ encode_REGISTER(encbuf, &encx, &cmn2, ®); - +// !!! does this ever happen? does REGISTER ever come with a payload ??? !!! /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); } else { @@ -585,7 +589,8 @@ static int process_udp(n2n_sn_t * sss, } if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx); + packet_header_encrypt (rec_buf, encx, comm->header_encryption_ctx, + pearson_hash_16 (rec_buf, encx)); try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ } else @@ -656,7 +661,8 @@ 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); + packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx, + pearson_hash_16 (ackbuf, encx)); sendto(sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); @@ -703,7 +709,8 @@ static int process_udp(n2n_sn_t * sss, encode_PEER_INFO( encbuf, &encx, &cmn2, &pi ); if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) - packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx); + packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx, + pearson_hash_16 (encbuf, encx)); sendto( sss->sock, encbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); From e8d5e939a7329e84791e50cca7c4de677acdbeef Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 29 Jun 2020 16:49:54 +0545 Subject: [PATCH 5/6] added encryption step --- include/header_encryption.h | 2 +- src/edge_utils.c | 10 +++++----- src/header_encryption.c | 4 +++- src/sn.c | 10 +++++----- src/sn_utils.c | 10 +++++----- 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/include/header_encryption.h b/include/header_encryption.h index 05e28a0..b84554a 100644 --- a/include/header_encryption.h +++ b/include/header_encryption.h @@ -22,7 +22,7 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx, - uint16_t checksum); + he_context_t * ctx_iv, uint16_t checksum); void packet_header_setup_key (const char * community_name, he_context_t ** ctx, diff --git a/src/edge_utils.c b/src/edge_utils.c index 5183972..825962c 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -744,7 +744,7 @@ static void send_register_super(n2n_edge_t * eee, if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, - pearson_hash_16 (pktbuf, idx)); + eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx)); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode); } @@ -776,7 +776,7 @@ static void send_query_peer( n2n_edge_t * eee, if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, - pearson_hash_16 (pktbuf, idx)); + eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx)); sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); } @@ -823,7 +823,7 @@ static void send_register(n2n_edge_t * eee, if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, - pearson_hash_16 (pktbuf, idx)); + eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx)); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -866,7 +866,7 @@ static void send_register_ack(n2n_edge_t * eee, if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, - pearson_hash_16 (pktbuf, idx)); + eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx)); /* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer); } @@ -1474,7 +1474,7 @@ static void send_packet2net(n2n_edge_t * eee, if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (pktbuf, headerIdx, eee->conf.header_encryption_ctx, - pearson_hash_16 (pktbuf, idx)); + eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx)); #ifdef MTU_ASSERT_VALUE { diff --git a/src/header_encryption.c b/src/header_encryption.c index 948fd33..7bd9ae4 100644 --- a/src/header_encryption.c +++ b/src/header_encryption.c @@ -57,7 +57,7 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, /* ********************************************************************** */ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx, - uint16_t checksum) { + he_context_t * ctx_iv, uint16_t checksum) { uint8_t iv[16]; uint16_t *iv16 = (uint16_t*)&iv; @@ -76,6 +76,8 @@ int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_ iv16[4] = n2n_rand (); iv16[5] = htobe16 (checksum); iv32[3] = htobe32 (magic); + // blend checksum into 96-bit IV + speck_he_iv_encrypt (iv, (speck_context_t*)ctx_iv); memcpy (packet, iv, 16); packet[15] = header_len; diff --git a/src/sn.c b/src/sn.c index 87c40ce..a7f508e 100644 --- a/src/sn.c +++ b/src/sn.c @@ -587,7 +587,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (rec_buf, oldEncx, comm->header_encryption_ctx, - pearson_hash_16 (rec_buf, encx)); + comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx)); } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ @@ -599,7 +599,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx, - pearson_hash_16 (rec_buf, udp_size)); + comm->header_iv_ctx, pearson_hash_16 (rec_buf, udp_size)); } /* Common section to forward the final product. */ @@ -663,7 +663,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (rec_buf, encx, comm->header_encryption_ctx, - pearson_hash_16 (rec_buf, encx)); + comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx)); try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ @@ -736,7 +736,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx, - pearson_hash_16 (ackbuf, encx)); + comm->header_iv_ctx, pearson_hash_16 (ackbuf, encx)); sendto(sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); @@ -784,7 +784,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx, - pearson_hash_16 (encbuf, encx)); + comm->header_iv_ctx, pearson_hash_16 (encbuf, encx)); sendto( sss->sock, encbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); diff --git a/src/sn_utils.c b/src/sn_utils.c index d176b11..fc7ba03 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -513,7 +513,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (rec_buf, oldEncx, comm->header_encryption_ctx, - pearson_hash_16 (rec_buf, encx)); + comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx)); } else { /* Already from a supernode. Nothing to modify, just pass to @@ -526,7 +526,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (rec_buf, idx, comm->header_encryption_ctx, - pearson_hash_16 (rec_buf, udp_size)); + comm->header_iv_ctx, pearson_hash_16 (rec_buf, udp_size)); } /* Common section to forward the final product. */ @@ -590,7 +590,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (rec_buf, encx, comm->header_encryption_ctx, - pearson_hash_16 (rec_buf, encx)); + comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx)); try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */ } else @@ -662,7 +662,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (ackbuf, encx, comm->header_encryption_ctx, - pearson_hash_16 (ackbuf, encx)); + comm->header_iv_ctx, pearson_hash_16 (ackbuf, encx)); sendto(sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in)); @@ -710,7 +710,7 @@ static int process_udp(n2n_sn_t * sss, if (comm->header_encryption == HEADER_ENCRYPTION_ENABLED) packet_header_encrypt (encbuf, encx, comm->header_encryption_ctx, - pearson_hash_16 (encbuf, encx)); + comm->header_iv_ctx, pearson_hash_16 (encbuf, encx)); sendto( sss->sock, encbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); From 0e0d662dbb82dca0f8e2908e4c93ed46048be94d Mon Sep 17 00:00:00 2001 From: Logan007 Date: Mon, 29 Jun 2020 19:20:40 +0545 Subject: [PATCH 6/6] added decryption step --- include/header_encryption.h | 4 ++-- src/edge_utils.c | 11 +++++++++-- src/header_encryption.c | 7 ++++++- src/sn.c | 10 ++++++++-- src/sn_utils.c | 10 ++++++++-- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/header_encryption.h b/include/header_encryption.h index b84554a..0e8a708 100644 --- a/include/header_encryption.h +++ b/include/header_encryption.h @@ -18,8 +18,8 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, - char * community_name, he_context_t * ctx); - + char * community_name, he_context_t * ctx, + he_context_t * ctx_iv, uint16_t * checksum); int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx, he_context_t * ctx_iv, uint16_t checksum); diff --git a/src/edge_utils.c b/src/edge_utils.c index 825962c..e65b7df 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -1594,11 +1594,18 @@ 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) { + uint16_t checksum = 0; + if( packet_header_decrypt (udp_buf, recvlen, (char *)eee->conf.community_name, eee->conf.header_encryption_ctx, + eee->conf.header_iv_ctx, &checksum) == 0) { traceEvent(TRACE_DEBUG, "readFromIPSocket failed to decrypt header."); return; } + if (checksum != pearson_hash_16 (udp_buf, recvlen)) { + traceEvent(TRACE_DEBUG, "readFromIPSocket dropped packet due to checksum error."); + return; + } + } /* hexdump(udp_buf, recvlen); */ diff --git a/src/header_encryption.c b/src/header_encryption.c index 7bd9ae4..d7b1616 100644 --- a/src/header_encryption.c +++ b/src/header_encryption.c @@ -24,7 +24,8 @@ /* ********************************************************************** */ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, - char * community_name, he_context_t * ctx) { + char * community_name, he_context_t * ctx, + he_context_t * ctx_iv, uint16_t * checksum) { // assemble IV // the last four are ASCII "n2n!" and do not get overwritten @@ -34,6 +35,10 @@ uint32_t packet_header_decrypt (uint8_t packet[], uint16_t packet_len, // to full 128 bit IV memcpy (iv, packet, 12); + // extract checksum (last 16 bit) blended in IV + speck_he_iv_decrypt (packet, (speck_context_t*)ctx_iv); + *checksum = be16toh (((uint16_t*)packet)[5]); + // try community name as possible key and check for magic bytes uint32_t magic = 0x6E326E00; // ="n2n_" uint32_t test_magic; diff --git a/src/sn.c b/src/sn.c index a7f508e..608a31c 100644 --- a/src/sn.c +++ b/src/sn.c @@ -491,7 +491,13 @@ static int process_udp(n2n_sn_t * sss, /* 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)) ) { + uint16_t checksum = 0; + if ( (ret = packet_header_decrypt (udp_buf, udp_size, comm->community, comm->header_encryption_ctx, + comm->header_iv_ctx, &checksum)) ) { + if (checksum != pearson_hash_16 (udp_buf, udp_size)) { + traceEvent(TRACE_DEBUG, "process_udp dropped packet due to checksum error."); + return -1; + } if (comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { traceEvent (TRACE_INFO, "process_udp locked community '%s' to using " "encrypted headers.", comm->community); @@ -650,7 +656,7 @@ static int process_udp(n2n_sn_t * sss, /* Re-encode the header. */ encode_REGISTER(encbuf, &encx, &cmn2, ®); -// !!! does this ever happen? does REGISTER ever come with a payload ??? !!! + /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); } else { diff --git a/src/sn_utils.c b/src/sn_utils.c index fc7ba03..c732f40 100644 --- a/src/sn_utils.c +++ b/src/sn_utils.c @@ -417,7 +417,13 @@ static int process_udp(n2n_sn_t * sss, /* 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)) ) { + uint16_t checksum = 0; + if ( (ret = packet_header_decrypt (udp_buf, udp_size, comm->community, comm->header_encryption_ctx, + comm->header_iv_ctx, &checksum)) ) { + if (checksum != pearson_hash_16 (udp_buf, udp_size)) { + traceEvent(TRACE_DEBUG, "process_udp dropped packet due to checksum error."); + return -1; + } if (comm->header_encryption == HEADER_ENCRYPTION_UNKNOWN) { traceEvent (TRACE_INFO, "process_udp locked community '%s' to using " "encrypted headers.", comm->community); @@ -577,7 +583,7 @@ static int process_udp(n2n_sn_t * sss, /* Re-encode the header. */ encode_REGISTER(encbuf, &encx, &cmn2, ®); -// !!! does this ever happen? does REGISTER ever come with a payload ??? !!! + /* Copy the original payload unchanged */ encode_buf(encbuf, &encx, (udp_buf + idx), (udp_size - idx)); } else {