Browse Source

Fixes packet drops while communicating with multiple nodes in AES PSK

Per-node AES structures must be kept as CBC cannot work with a single structure across multiple nodes
pull/67/head
emanuele-f 6 years ago
parent
commit
37233553a4
  1. 4
      benchmark.c
  2. 4
      edge_utils.c
  3. 3
      n2n_transforms.h
  4. 140
      transform_aes.c
  5. 6
      transform_null.c
  6. 6
      transform_tf.c

4
benchmark.c

@ -102,6 +102,7 @@ int main(int argc, char * argv[]) {
static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, uint8_t *pktbuf, n2n_community_t c) { static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, uint8_t *pktbuf, n2n_community_t c) {
n2n_common_t cmn; n2n_common_t cmn;
n2n_PACKET_t pkt; n2n_PACKET_t pkt;
n2n_mac_t mac_buf;
struct timeval t1; struct timeval t1;
struct timeval t2; struct timeval t2;
@ -115,6 +116,7 @@ static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, ui
n=10000; n=10000;
memset(mac_buf, 0, sizeof(mac_buf));
gettimeofday( &t1, NULL ); gettimeofday( &t1, NULL );
for(i=0; i<n; ++i) for(i=0; i<n; ++i)
{ {
@ -122,7 +124,7 @@ static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, ui
nw += op_fn->fwd( op_fn, nw += op_fn->fwd( op_fn,
pktbuf+nw, N2N_PKT_BUF_SIZE-nw, pktbuf+nw, N2N_PKT_BUF_SIZE-nw,
PKT_CONTENT, sizeof(PKT_CONTENT) ); PKT_CONTENT, sizeof(PKT_CONTENT), mac_buf);
idx=0; idx=0;
rem=nw; rem=nw;

4
edge_utils.c

@ -791,7 +791,7 @@ static int handle_PACKET(n2n_edge_t * eee,
eh = (ether_hdr_t*)eth_payload; eh = (ether_hdr_t*)eth_payload;
eth_size = eee->transop[rx_transop_idx].rev(&(eee->transop[rx_transop_idx]), eth_size = eee->transop[rx_transop_idx].rev(&(eee->transop[rx_transop_idx]),
eth_payload, N2N_PKT_BUF_SIZE, eth_payload, N2N_PKT_BUF_SIZE,
payload, psize); payload, psize, pkt->srcMac);
++(eee->transop[rx_transop_idx].rx_cnt); /* stats */ ++(eee->transop[rx_transop_idx].rx_cnt); /* stats */
if(!(eee->allow_routing)) { if(!(eee->allow_routing)) {
@ -1192,7 +1192,7 @@ void send_packet2net(n2n_edge_t * eee,
idx += eee->transop[tx_transop_idx].fwd(&(eee->transop[tx_transop_idx]), idx += eee->transop[tx_transop_idx].fwd(&(eee->transop[tx_transop_idx]),
pktbuf+idx, N2N_PKT_BUF_SIZE-idx, pktbuf+idx, N2N_PKT_BUF_SIZE-idx,
tap_pkt, len); tap_pkt, len, pkt.dstMac);
++(eee->transop[tx_transop_idx].tx_cnt); /* stats */ ++(eee->transop[tx_transop_idx].tx_cnt); /* stats */
send_packet(eee, destMac, pktbuf, idx); /* to peer or supernode */ send_packet(eee, destMac, pktbuf, idx); /* to peer or supernode */

3
n2n_transforms.h

@ -55,7 +55,8 @@ typedef int (*n2n_transform_f)( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len ); size_t in_len,
const n2n_mac_t peer_mac);
/** Holds the info associated with a data transform plugin. /** Holds the info associated with a data transform plugin.
* *

140
transform_aes.c

@ -59,10 +59,20 @@ struct transop_aes
ssize_t tx_sa; ssize_t tx_sa;
size_t num_sa; size_t num_sa;
sa_aes_t sa[N2N_AES_NUM_SA]; sa_aes_t sa[N2N_AES_NUM_SA];
/* PSK mode only */
int psk_mode;
u_int8_t mac_sa[N2N_AES_NUM_SA][N2N_MAC_SIZE]; /* this is used as a key in the sa array */
uint8_t *encrypt_pwd;
uint32_t encrypt_pwd_len;
size_t sa_to_replace;
}; };
typedef struct transop_aes transop_aes_t; typedef struct transop_aes transop_aes_t;
static ssize_t aes_find_sa( const transop_aes_t * priv, const n2n_sa_t req_id );
static int setup_aes_key(transop_aes_t *priv, uint8_t *keybuf, ssize_t pstat, size_t sa_num);
static int transop_deinit_aes( n2n_trans_op_t * arg ) static int transop_deinit_aes( n2n_trans_op_t * arg )
{ {
transop_aes_t * priv = (transop_aes_t *)arg->priv; transop_aes_t * priv = (transop_aes_t *)arg->priv;
@ -89,9 +99,51 @@ static int transop_deinit_aes( n2n_trans_op_t * arg )
return 0; return 0;
} }
static size_t aes_choose_tx_sa( transop_aes_t * priv ) /* Find the peer_mac sa */
{ static size_t aes_psk_get_peer_sa(transop_aes_t * priv, const u_int8_t * peer_mac) {
return priv->tx_sa; /* set in tick */ size_t i;
int found = 0;
/* Find the MAC sa */
for(i=0; i<priv->num_sa; i++) {
if(!memcmp(priv->mac_sa[i], peer_mac, N2N_MAC_SIZE)) {
found = 1;
break;
}
}
if(found)
return(i);
size_t new_sa = priv->sa_to_replace;
macstr_t mac_buf;
macaddr_str(mac_buf, peer_mac);
traceEvent(TRACE_DEBUG, "Assigning SA %u to %s", new_sa, mac_buf);
setup_aes_key(priv, priv->encrypt_pwd, priv->encrypt_pwd_len, new_sa);
priv->num_sa = max(priv->num_sa, new_sa + 1);
memcpy(priv->mac_sa[new_sa], peer_mac, N2N_MAC_SIZE);
priv->sa[new_sa].sa_id = new_sa;
/* Use sa_to_replace round-robin */
priv->sa_to_replace = (priv->sa_to_replace + 1) % N2N_AES_NUM_SA;
return new_sa;
}
static size_t aes_choose_tx_sa( transop_aes_t * priv, const u_int8_t * peer_mac ) {
if(!priv->psk_mode)
return priv->tx_sa; /* set in tick */
else
return aes_psk_get_peer_sa(priv, peer_mac);
}
static ssize_t aes_choose_rx_sa( transop_aes_t * priv, const u_int8_t * peer_mac, ssize_t sa_rx) {
if(!priv->psk_mode)
return aes_find_sa(priv, sa_rx);
else
/* NOTE the sa_rx of the packet is ignored in this case */
return aes_psk_get_peer_sa(priv, peer_mac);
} }
#define TRANSOP_AES_VER_SIZE 1 /* Support minor variants in encoding in one module. */ #define TRANSOP_AES_VER_SIZE 1 /* Support minor variants in encoding in one module. */
@ -137,7 +189,8 @@ static int transop_encode_aes( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len ) size_t in_len,
const uint8_t * peer_mac)
{ {
int len2=-1; int len2=-1;
transop_aes_t * priv = (transop_aes_t *)arg->priv; transop_aes_t * priv = (transop_aes_t *)arg->priv;
@ -154,7 +207,7 @@ static int transop_encode_aes( n2n_trans_op_t * arg,
size_t tx_sa_num = 0; size_t tx_sa_num = 0;
/* The transmit sa is periodically updated */ /* The transmit sa is periodically updated */
tx_sa_num = aes_choose_tx_sa( priv ); tx_sa_num = aes_choose_tx_sa( priv, peer_mac );
sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */ sa = &(priv->sa[tx_sa_num]); /* Proper Tx SA index */
@ -239,7 +292,8 @@ static int transop_decode_aes( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len ) size_t in_len,
const uint8_t * peer_mac)
{ {
int len=0; int len=0;
transop_aes_t * priv = (transop_aes_t *)arg->priv; transop_aes_t * priv = (transop_aes_t *)arg->priv;
@ -263,7 +317,8 @@ static int transop_decode_aes( n2n_trans_op_t * arg,
/* Get the SA number and make sure we are decrypting with the right one. */ /* Get the SA number and make sure we are decrypting with the right one. */
decode_uint32( &sa_rx, inbuf, &rem, &idx ); decode_uint32( &sa_rx, inbuf, &rem, &idx );
sa_idx = aes_find_sa(priv, sa_rx); sa_idx = aes_choose_rx_sa(priv, peer_mac, sa_rx);
if ( sa_idx >= 0 ) if ( sa_idx >= 0 )
{ {
sa_aes_t * sa = &(priv->sa[sa_idx]); sa_aes_t * sa = &(priv->sa[sa_idx]);
@ -338,16 +393,13 @@ static int transop_decode_aes( n2n_trans_op_t * arg,
return len; return len;
} }
/* /* NOTE: the caller should adjust priv->num_sa accordingly */
* priv: pointer to transform state static int setup_aes_key(transop_aes_t *priv, uint8_t *keybuf, ssize_t pstat, size_t sa_num) {
* keybuf: buffer holding the key
* pstat: length of keybuf
*/
static void add_aes_key(transop_aes_t *priv, uint8_t *keybuf, ssize_t pstat) {
/* pstat is number of bytes read into keybuf. */ /* pstat is number of bytes read into keybuf. */
sa_aes_t * sa = &(priv->sa[priv->num_sa]); sa_aes_t * sa = &(priv->sa[sa_num]);
size_t aes_keysize_bytes; size_t aes_keysize_bytes;
size_t aes_keysize_bits; size_t aes_keysize_bits;
uint8_t * padded_keybuf;
/* Clear out any old possibly longer key matter. */ /* Clear out any old possibly longer key matter. */
memset( &(sa->enc_key), 0, sizeof(AES_KEY) ); memset( &(sa->enc_key), 0, sizeof(AES_KEY) );
@ -359,17 +411,34 @@ static void add_aes_key(transop_aes_t *priv, uint8_t *keybuf, ssize_t pstat) {
aes_keysize_bytes = aes_best_keysize(pstat); aes_keysize_bytes = aes_best_keysize(pstat);
aes_keysize_bits = 8 * aes_keysize_bytes; aes_keysize_bits = 8 * aes_keysize_bytes;
/* The aes_keysize_bytes may differ from pstat, possibly pad */
padded_keybuf = calloc(1, aes_keysize_bytes);
if(!padded_keybuf)
return(1);
memcpy(keybuf, padded_keybuf, pstat);
/* Use N2N_MAX_KEYSIZE because the AES key needs to be of fixed /* Use N2N_MAX_KEYSIZE because the AES key needs to be of fixed
* size. If fewer bits specified then the rest will be * size. If fewer bits specified then the rest will be
* zeroes. AES acceptable key sizes are 128, 192 and 256 * zeroes. AES acceptable key sizes are 128, 192 and 256
* bits. */ * bits. */
AES_set_encrypt_key( keybuf, aes_keysize_bits, &(sa->enc_key)); AES_set_encrypt_key(padded_keybuf, aes_keysize_bits, &(sa->enc_key));
AES_set_decrypt_key( keybuf, aes_keysize_bits, &(sa->dec_key)); AES_set_decrypt_key(padded_keybuf, aes_keysize_bits, &(sa->dec_key));
/* Leave ivecs set to all zeroes */ /* Leave ivecs set to all zeroes */
traceEvent( TRACE_DEBUG, "transop_addspec_aes sa_id=%u, %u bits data=%s.\n", traceEvent( TRACE_DEBUG, "transop_addspec_aes sa_id=%u, %u bits data=%s.\n",
priv->sa[priv->num_sa].sa_id, aes_keysize_bits, keybuf); priv->sa[sa_num].sa_id, aes_keysize_bits, keybuf);
free(padded_keybuf);
return(0);
}
/*
* priv: pointer to transform state
* keybuf: buffer holding the key
* pstat: length of keybuf
*/
static void add_aes_key(transop_aes_t *priv, uint8_t *keybuf, ssize_t pstat) {
setup_aes_key(priv, keybuf, pstat, priv->num_sa);
++(priv->num_sa); ++(priv->num_sa);
} }
@ -464,6 +533,19 @@ static n2n_tostat_t transop_tick_aes( n2n_trans_op_t * arg, time_t now )
return r; return r;
} }
static n2n_tostat_t transop_tick_aes_psk(n2n_trans_op_t * arg, time_t now) {
transop_aes_t * priv = (transop_aes_t *)arg->priv;
n2n_tostat_t r;
memset(&r, 0, sizeof(r));
// Always tx
r.can_tx = 1;
r.tx_spec.t = N2N_TRANSFORM_ID_AESCBC;
r.tx_spec = priv->sa[priv->tx_sa].spec;
return r;
}
int transop_aes_init( n2n_trans_op_t * ttt ) int transop_aes_init( n2n_trans_op_t * ttt )
{ {
@ -477,7 +559,7 @@ int transop_aes_init( n2n_trans_op_t * ttt )
memset( ttt, 0, sizeof( n2n_trans_op_t ) ); memset( ttt, 0, sizeof( n2n_trans_op_t ) );
priv = (transop_aes_t *) malloc( sizeof(transop_aes_t) ); priv = (transop_aes_t *) calloc(1, sizeof(transop_aes_t));
if ( NULL != priv ) if ( NULL != priv )
{ {
@ -488,6 +570,7 @@ int transop_aes_init( n2n_trans_op_t * ttt )
ttt->priv = priv; ttt->priv = priv;
priv->num_sa=0; priv->num_sa=0;
priv->tx_sa=0; /* We will use this sa index for encoding. */ priv->tx_sa=0; /* We will use this sa index for encoding. */
priv->psk_mode = 0;
ttt->transform_id = N2N_TRANSFORM_ID_AESCBC; ttt->transform_id = N2N_TRANSFORM_ID_AESCBC;
ttt->addspec = transop_addspec_aes; ttt->addspec = transop_addspec_aes;
@ -523,19 +606,26 @@ int transop_aes_setup_psk(n2n_trans_op_t *ttt,
n2n_sa_t sa_num, n2n_sa_t sa_num,
uint8_t *encrypt_pwd, uint8_t *encrypt_pwd,
uint32_t encrypt_pwd_len) { uint32_t encrypt_pwd_len) {
static const u_int8_t broadcast_mac[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
int retval = 1; int retval = 1;
transop_aes_t *priv = (transop_aes_t *)ttt->priv; transop_aes_t *priv = (transop_aes_t *)ttt->priv;
if(ttt->priv) { if(ttt->priv) {
sa_aes_t *sa; /* Replace the tick function with the PSK version of it */
ttt->tick = transop_tick_aes_psk;
priv->psk_mode = 1;
memset(priv->mac_sa, 0, sizeof(priv->mac_sa));
priv->encrypt_pwd = encrypt_pwd;
priv->encrypt_pwd_len = encrypt_pwd_len;
priv->num_sa=0; priv->num_sa=0;
priv->tx_sa=0; priv->tx_sa=0;
sa = &(priv->sa[priv->tx_sa]);
sa->sa_id=sa_num;
sa->spec.valid_until = 0x7fffffff;
/* This is a preshared key setup. Both Tx and Rx are using the same security association. */ /* Add the key to be used for broadcast */
add_aes_key(priv, encrypt_pwd, encrypt_pwd_len); add_aes_key(priv, priv->encrypt_pwd, priv->encrypt_pwd_len);
memcpy(priv->mac_sa[0], broadcast_mac, N2N_MAC_SIZE);
priv->sa_to_replace = priv->num_sa;
retval = 0; retval = 0;
} else } else
traceEvent(TRACE_ERROR, "AES priv is not allocated"); traceEvent(TRACE_ERROR, "AES priv is not allocated");

6
transform_null.c

@ -29,7 +29,8 @@ static int transop_encode_null( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len ) size_t in_len,
const uint8_t * peer_mac)
{ {
int retval = -1; int retval = -1;
@ -51,7 +52,8 @@ static int transop_decode_null( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len ) size_t in_len,
const uint8_t * peer_mac)
{ {
int retval = -1; int retval = -1;

6
transform_tf.c

@ -109,7 +109,8 @@ static int transop_encode_twofish( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len ) size_t in_len,
const uint8_t * peer_mac)
{ {
int len=-1; int len=-1;
transop_tf_t * priv = (transop_tf_t *)arg->priv; transop_tf_t * priv = (transop_tf_t *)arg->priv;
@ -209,7 +210,8 @@ static int transop_decode_twofish( n2n_trans_op_t * arg,
uint8_t * outbuf, uint8_t * outbuf,
size_t out_len, size_t out_len,
const uint8_t * inbuf, const uint8_t * inbuf,
size_t in_len ) size_t in_len,
const uint8_t * peer_mac)
{ {
int len=0; int len=0;
transop_tf_t * priv = (transop_tf_t *)arg->priv; transop_tf_t * priv = (transop_tf_t *)arg->priv;

Loading…
Cancel
Save