mirror of
https://github.com/ntop/n2n.git
synced 2024-09-19 16:41:11 +02:00
commit
9dd0387d36
|
@ -18,10 +18,13 @@
|
|||
|
||||
|
||||
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);
|
||||
|
||||
|
||||
int32_t packet_header_encrypt (uint8_t packet[], uint8_t header_len, he_context_t * ctx);
|
||||
void packet_header_setup_key (const char * community_name, he_context_t ** ctx,
|
||||
he_context_t ** ctx_iv);
|
||||
|
||||
|
||||
void packet_header_setup_key (const char * community_name, he_context_t ** ctx);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -271,7 +271,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)
|
||||
|
@ -757,7 +757,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,
|
||||
eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx));
|
||||
|
||||
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, supernode);
|
||||
}
|
||||
|
@ -788,7 +789,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,
|
||||
eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx));
|
||||
|
||||
sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) );
|
||||
}
|
||||
|
@ -834,7 +836,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,
|
||||
eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx));
|
||||
|
||||
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer);
|
||||
}
|
||||
|
@ -876,7 +879,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,
|
||||
eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx));
|
||||
|
||||
/* sent = */ sendto_sock(eee->udp_sock, pktbuf, idx, remote_peer);
|
||||
}
|
||||
|
@ -1504,8 +1508,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,
|
||||
|
@ -1514,6 +1517,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,
|
||||
eee->conf.header_iv_ctx, pearson_hash_16 (pktbuf, idx));
|
||||
|
||||
#ifdef MTU_ASSERT_VALUE
|
||||
{
|
||||
const u_int eth_udp_overhead = ETH_FRAMESIZE + IP4_MIN_SIZE + UDP_SIZE;
|
||||
|
@ -1635,11 +1642,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); */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -56,9 +61,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,
|
||||
he_context_t * ctx_iv, 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,8 +78,11 @@ 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);
|
||||
// blend checksum into 96-bit IV
|
||||
speck_he_iv_encrypt (iv, (speck_context_t*)ctx_iv);
|
||||
|
||||
memcpy (packet, iv, 16);
|
||||
packet[15] = header_len;
|
||||
|
@ -83,11 +93,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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
31
src/sn.c
31
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++;
|
||||
|
@ -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);
|
||||
|
@ -580,12 +586,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx));
|
||||
} else {
|
||||
/* Already from a supernode. Nothing to modify, just pass to
|
||||
* destination. */
|
||||
|
@ -596,7 +604,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (rec_buf, udp_size));
|
||||
}
|
||||
|
||||
/* Common section to forward the final product. */
|
||||
|
@ -659,7 +668,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx));
|
||||
|
||||
|
||||
try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */
|
||||
} else
|
||||
|
@ -730,7 +741,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (ackbuf, encx));
|
||||
|
||||
sendto(sss->sock, ackbuf, encx, 0,
|
||||
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
|
||||
|
@ -777,7 +789,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (encbuf, encx));
|
||||
|
||||
sendto( sss->sock, encbuf, encx, 0,
|
||||
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) );
|
||||
|
|
|
@ -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);
|
||||
|
@ -506,12 +512,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx));
|
||||
|
||||
} else {
|
||||
/* Already from a supernode. Nothing to modify, just pass to
|
||||
* destination. */
|
||||
|
@ -522,7 +531,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (rec_buf, udp_size));
|
||||
}
|
||||
|
||||
/* Common section to forward the final product. */
|
||||
|
@ -585,7 +595,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (rec_buf, encx));
|
||||
|
||||
try_forward(sss, comm, &cmn, reg.dstMac, rec_buf, encx); /* unicast only */
|
||||
} else
|
||||
|
@ -656,7 +667,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (ackbuf, encx));
|
||||
|
||||
sendto(sss->sock, ackbuf, encx, 0,
|
||||
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in));
|
||||
|
@ -703,7 +715,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,
|
||||
comm->header_iv_ctx, pearson_hash_16 (encbuf, encx));
|
||||
|
||||
sendto( sss->sock, encbuf, encx, 0,
|
||||
(struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) );
|
||||
|
|
105
src/speck.c
105
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 <stdio.h> // for testing
|
||||
#include <string.h>
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Block a user