aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamjan Marion <damarion@cisco.com>2019-03-20 16:07:09 +0100
committerNeale Ranns <nranns@cisco.com>2019-03-20 17:23:04 +0000
commitb966e8bfdd3c63e2436ab6e5d250c8b1bf4dd102 (patch)
tree7f3faba13dd462adc577bdc9798da99c209bee9c
parentc372dc2190f2376f9b816f71120354fd53732fa7 (diff)
ipsec: keep crypto data inside SA
Change-Id: Ie8986bd3652d25c4befe681cea77df95aba37ebc Signed-off-by: Damjan Marion <damarion@cisco.com>
-rw-r--r--src/vnet/ipsec/ah_decrypt.c6
-rw-r--r--src/vnet/ipsec/ah_encrypt.c9
-rw-r--r--src/vnet/ipsec/esp.h16
-rw-r--r--src/vnet/ipsec/esp_decrypt.c24
-rw-r--r--src/vnet/ipsec/esp_encrypt.c26
-rw-r--r--src/vnet/ipsec/ipsec_if.c8
-rw-r--r--src/vnet/ipsec/ipsec_sa.c24
-rw-r--r--src/vnet/ipsec/ipsec_sa.h10
8 files changed, 65 insertions, 58 deletions
diff --git a/src/vnet/ipsec/ah_decrypt.c b/src/vnet/ipsec/ah_decrypt.c
index 2488fa918f6..b128dfaf26b 100644
--- a/src/vnet/ipsec/ah_decrypt.c
+++ b/src/vnet/ipsec/ah_decrypt.c
@@ -172,7 +172,7 @@ ah_decrypt_inline (vlib_main_t * vm,
(&ipsec_sa_counters, thread_index, sa_index0,
1, i_b0->current_length);
- icv_size = im->integ_algs[sa0->integ_alg].trunc_size;
+ icv_size = sa0->integ_trunc_size;
if (PREDICT_TRUE (sa0->integ_alg != IPSEC_INTEG_ALG_NONE))
{
u8 sig[64];
@@ -203,9 +203,7 @@ ah_decrypt_inline (vlib_main_t * vm,
icv_padding_len =
ah_calc_icv_padding_len (icv_size, 0 /* is_ipv6 */ );
}
- hmac_calc (vm, sa0->integ_alg, sa0->integ_key.data,
- sa0->integ_key.len, (u8 *) ih4, i_b0->current_length,
- sig, sa0->use_esn, sa0->seq_hi);
+ hmac_calc (vm, sa0, (u8 *) ih4, i_b0->current_length, sig);
if (PREDICT_FALSE (memcmp (digest, sig, icv_size)))
{
diff --git a/src/vnet/ipsec/ah_encrypt.c b/src/vnet/ipsec/ah_encrypt.c
index ce930bd5529..c6dbe57f73b 100644
--- a/src/vnet/ipsec/ah_encrypt.c
+++ b/src/vnet/ipsec/ah_encrypt.c
@@ -152,7 +152,7 @@ ah_encrypt_inline (vlib_main_t * vm,
adv = -sizeof (ah_header_t);
}
- icv_size = im->integ_algs[sa0->integ_alg].trunc_size;
+ icv_size = sa0->integ_trunc_size;
const u8 padding_len = ah_calc_icv_padding_len (icv_size, is_ip6);
adv -= padding_len;
/* transport mode save the eth header before it is overwritten */
@@ -265,11 +265,8 @@ ah_encrypt_inline (vlib_main_t * vm,
sizeof (ah_header_t);
clib_memset (digest, 0, icv_size);
- unsigned size = hmac_calc (vm, sa0->integ_alg, sa0->integ_key.data,
- sa0->integ_key.len,
- vlib_buffer_get_current (i_b0),
- i_b0->current_length, sig, sa0->use_esn,
- sa0->seq_hi);
+ unsigned size = hmac_calc (vm, sa0, vlib_buffer_get_current (i_b0),
+ i_b0->current_length, sig);
memcpy (digest, sig, size);
if (is_ip6)
diff --git a/src/vnet/ipsec/esp.h b/src/vnet/ipsec/esp.h
index 17300383e16..74ab1f05778 100644
--- a/src/vnet/ipsec/esp.h
+++ b/src/vnet/ipsec/esp.h
@@ -205,19 +205,17 @@ esp_seq_advance (ipsec_sa_t * sa)
always_inline unsigned int
-hmac_calc (vlib_main_t * vm, ipsec_integ_alg_t alg, u8 * key, int key_len,
- u8 * data, int data_len, u8 * signature, u8 use_esn, u32 seq_hi)
+hmac_calc (vlib_main_t * vm, ipsec_sa_t * sa, u8 * data, int data_len,
+ u8 * signature)
{
- ipsec_main_t *im = &ipsec_main;
vnet_crypto_op_t _op, *op = &_op;
- ASSERT (alg < IPSEC_INTEG_N_ALG);
- if (PREDICT_FALSE (im->integ_algs[alg].op_type == 0))
+ if (PREDICT_FALSE (sa->integ_op_type == 0))
return 0;
- op->op = im->integ_algs[alg].op_type;
- op->key = key;
- op->key_len = key_len;
+ op->op = sa->integ_op_type;
+ op->key = sa->integ_key.data;
+ op->key_len = sa->integ_key.len;
op->src = data;
op->len = data_len;
op->dst = signature;
@@ -233,7 +231,7 @@ hmac_calc (vlib_main_t * vm, ipsec_integ_alg_t alg, u8 * key, int key_len,
#endif
vnet_crypto_process_ops (vm, op, 1);
- return im->integ_algs[alg].trunc_size;
+ return sa->integ_trunc_size;
}
#endif /* __ESP_H__ */
diff --git a/src/vnet/ipsec/esp_decrypt.c b/src/vnet/ipsec/esp_decrypt.c
index 1ee7ce8fd0a..7860ca33d18 100644
--- a/src/vnet/ipsec/esp_decrypt.c
+++ b/src/vnet/ipsec/esp_decrypt.c
@@ -82,21 +82,16 @@ format_esp_decrypt_trace (u8 * s, va_list * args)
}
always_inline void
-esp_decrypt_cbc (vlib_main_t * vm, ipsec_crypto_alg_t alg,
+esp_decrypt_cbc (vlib_main_t * vm, ipsec_sa_t * sa,
u8 * in, u8 * out, size_t in_len, u8 * key, u8 * iv)
{
- ipsec_main_t *im = &ipsec_main;
- ipsec_main_crypto_alg_t *a;
vnet_crypto_op_t _op, *op = &_op;
- ASSERT (alg < IPSEC_CRYPTO_N_ALG);
-
- a = &im->crypto_algs[alg];
- if (PREDICT_FALSE (a->dec_op_type == VNET_CRYPTO_OP_NONE))
+ if (PREDICT_FALSE (sa->crypto_dec_op_type == VNET_CRYPTO_OP_NONE))
return;
- op->op = a->dec_op_type;
+ op->op = sa->crypto_dec_op_type;
op->iv = iv;
op->src = in;
op->dst = out;
@@ -181,15 +176,13 @@ esp_decrypt_inline (vlib_main_t * vm,
if (PREDICT_TRUE (sa0->integ_alg != IPSEC_INTEG_ALG_NONE))
{
u8 sig[64];
- int icv_size = im->integ_algs[sa0->integ_alg].trunc_size;
+ int icv_size = sa0->integ_trunc_size;
clib_memset (sig, 0, sizeof (sig));
u8 *icv = vlib_buffer_get_current (ib[0]) + ib[0]->current_length -
icv_size;
ib[0]->current_length -= icv_size;
- hmac_calc (vm, sa0->integ_alg, sa0->integ_key.data,
- sa0->integ_key.len, (u8 *) esp0,
- ib[0]->current_length, sig, sa0->use_esn, sa0->seq_hi);
+ hmac_calc (vm, sa0, (u8 *) esp0, ib[0]->current_length, sig);
if (PREDICT_FALSE (memcmp (icv, sig, icv_size)))
{
@@ -217,8 +210,8 @@ esp_decrypt_inline (vlib_main_t * vm,
(sa0->crypto_alg >= IPSEC_CRYPTO_ALG_DES_CBC &&
sa0->crypto_alg <= IPSEC_CRYPTO_ALG_3DES_CBC))
{
- const int BLOCK_SIZE = im->crypto_algs[sa0->crypto_alg].block_size;
- const int IV_SIZE = im->crypto_algs[sa0->crypto_alg].iv_size;
+ const int BLOCK_SIZE = sa0->crypto_block_size;
+ const int IV_SIZE = sa0->crypto_block_size;
esp_footer_t *f0;
u8 ip_hdr_size = 0;
@@ -251,8 +244,7 @@ esp_decrypt_inline (vlib_main_t * vm,
}
}
- esp_decrypt_cbc (vm, sa0->crypto_alg,
- esp0->data + IV_SIZE,
+ esp_decrypt_cbc (vm, sa0, esp0->data + IV_SIZE,
(u8 *) vlib_buffer_get_current (ob[0]) +
ip_hdr_size, BLOCK_SIZE * blocks,
sa0->crypto_key.data, esp0->data);
diff --git a/src/vnet/ipsec/esp_encrypt.c b/src/vnet/ipsec/esp_encrypt.c
index 37c2c953c87..1e29ee34f3b 100644
--- a/src/vnet/ipsec/esp_encrypt.c
+++ b/src/vnet/ipsec/esp_encrypt.c
@@ -87,21 +87,16 @@ format_esp_encrypt_trace (u8 * s, va_list * args)
}
always_inline void
-esp_encrypt_cbc (vlib_main_t * vm, ipsec_crypto_alg_t alg,
+esp_encrypt_cbc (vlib_main_t * vm, ipsec_sa_t * sa,
u8 * in, u8 * out, size_t in_len, u8 * key, u8 * iv)
{
- ipsec_main_t *im = &ipsec_main;
- ipsec_main_crypto_alg_t *a;
vnet_crypto_op_t _op, *op = &_op;
- ASSERT (alg < IPSEC_CRYPTO_N_ALG);
-
- a = &im->crypto_algs[alg];
- if (PREDICT_FALSE (a->enc_op_type == VNET_CRYPTO_OP_NONE))
+ if (PREDICT_FALSE (sa->crypto_enc_op_type == VNET_CRYPTO_OP_NONE))
return;
- op->op = a->enc_op_type;
+ op->op = sa->crypto_enc_op_type;
op->flags = VNET_CRYPTO_OP_FLAG_INIT_IV;
op->iv = iv;
op->src = in;
@@ -282,8 +277,8 @@ esp_encrypt_inline (vlib_main_t * vm,
if (PREDICT_TRUE (sa0->crypto_alg != IPSEC_CRYPTO_ALG_NONE))
{
- const int BLOCK_SIZE = im->crypto_algs[sa0->crypto_alg].block_size;
- const int IV_SIZE = im->crypto_algs[sa0->crypto_alg].iv_size;
+ const int BLOCK_SIZE = sa0->crypto_block_size;
+ const int IV_SIZE = sa0->crypto_iv_size;
int blocks = 1 + (ib[0]->current_length + 1) / BLOCK_SIZE;
/* pad packet in input buffer */
@@ -311,10 +306,9 @@ esp_encrypt_inline (vlib_main_t * vm,
clib_memcpy_fast ((u8 *) vlib_buffer_get_current (ob[0]) +
ip_udp_hdr_size + sizeof (esp_header_t), iv,
- im->crypto_algs[sa0->crypto_alg].iv_size);
+ IV_SIZE);
- esp_encrypt_cbc (vm, sa0->crypto_alg,
- (u8 *) vlib_buffer_get_current (ib[0]),
+ esp_encrypt_cbc (vm, sa0, (u8 *) vlib_buffer_get_current (ib[0]),
(u8 *) vlib_buffer_get_current (ob[0]) +
ip_udp_hdr_size + sizeof (esp_header_t) +
IV_SIZE, BLOCK_SIZE * blocks,
@@ -322,11 +316,9 @@ esp_encrypt_inline (vlib_main_t * vm,
}
ob[0]->current_length +=
- hmac_calc (vm, sa0->integ_alg, sa0->integ_key.data,
- sa0->integ_key.len, (u8 *) o_esp0,
+ hmac_calc (vm, sa0, (u8 *) o_esp0,
ob[0]->current_length - ip_udp_hdr_size,
- vlib_buffer_get_current (ob[0]) + ob[0]->current_length,
- sa0->use_esn, sa0->seq_hi);
+ vlib_buffer_get_current (ob[0]) + ob[0]->current_length);
if (is_ip6)
diff --git a/src/vnet/ipsec/ipsec_if.c b/src/vnet/ipsec/ipsec_if.c
index f40e94dbe84..33cac4c3cbd 100644
--- a/src/vnet/ipsec/ipsec_if.c
+++ b/src/vnet/ipsec/ipsec_if.c
@@ -493,25 +493,25 @@ ipsec_set_interface_key (vnet_main_t * vnm, u32 hw_if_index,
if (type == IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO)
{
sa = pool_elt_at_index (im->sad, t->output_sa_index);
- sa->crypto_alg = alg;
+ ipsec_sa_set_crypto_alg (sa, alg);
ipsec_mk_key (&sa->crypto_key, key, vec_len (key));
}
else if (type == IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG)
{
sa = pool_elt_at_index (im->sad, t->output_sa_index);
- sa->integ_alg = alg;
+ ipsec_sa_set_integ_alg (sa, alg);
ipsec_mk_key (&sa->integ_key, key, vec_len (key));
}
else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO)
{
sa = pool_elt_at_index (im->sad, t->input_sa_index);
- sa->crypto_alg = alg;
+ ipsec_sa_set_crypto_alg (sa, alg);
ipsec_mk_key (&sa->crypto_key, key, vec_len (key));
}
else if (type == IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG)
{
sa = pool_elt_at_index (im->sad, t->input_sa_index);
- sa->integ_alg = alg;
+ ipsec_sa_set_integ_alg (sa, alg);
ipsec_mk_key (&sa->integ_key, key, vec_len (key));
}
else
diff --git a/src/vnet/ipsec/ipsec_sa.c b/src/vnet/ipsec/ipsec_sa.c
index fc8520d5ebb..337ca34eae9 100644
--- a/src/vnet/ipsec/ipsec_sa.c
+++ b/src/vnet/ipsec/ipsec_sa.c
@@ -88,6 +88,26 @@ ipsec_sa_stack (ipsec_sa_t * sa)
dpo_reset (&tmp);
}
+void
+ipsec_sa_set_crypto_alg (ipsec_sa_t * sa, ipsec_crypto_alg_t crypto_alg)
+{
+ ipsec_main_t *im = &ipsec_main;
+ sa->crypto_alg = crypto_alg;
+ sa->crypto_iv_size = im->crypto_algs[crypto_alg].iv_size;
+ sa->crypto_block_size = im->crypto_algs[crypto_alg].block_size;
+ sa->crypto_enc_op_type = im->crypto_algs[crypto_alg].enc_op_type;
+ sa->crypto_dec_op_type = im->crypto_algs[crypto_alg].dec_op_type;
+}
+
+void
+ipsec_sa_set_integ_alg (ipsec_sa_t * sa, ipsec_integ_alg_t integ_alg)
+{
+ ipsec_main_t *im = &ipsec_main;
+ sa->integ_alg = integ_alg;
+ sa->integ_trunc_size = im->integ_algs[integ_alg].trunc_size;
+ sa->integ_op_type = im->integ_algs[integ_alg].op_type;
+}
+
int
ipsec_sa_add (u32 id,
u32 spi,
@@ -123,9 +143,9 @@ ipsec_sa_add (u32 id,
sa->spi = spi;
sa->stat_index = sa_index;
sa->protocol = proto;
- sa->crypto_alg = crypto_alg;
+ ipsec_sa_set_crypto_alg (sa, crypto_alg);
clib_memcpy (&sa->crypto_key, ck, sizeof (sa->crypto_key));
- sa->integ_alg = integ_alg;
+ ipsec_sa_set_integ_alg (sa, integ_alg);
clib_memcpy (&sa->integ_key, ik, sizeof (sa->integ_key));
ip46_address_copy (&sa->tunnel_src_addr, tun_src);
ip46_address_copy (&sa->tunnel_dst_addr, tun_dst);
diff --git a/src/vnet/ipsec/ipsec_sa.h b/src/vnet/ipsec/ipsec_sa.h
index 2601f51038a..a6ade604b20 100644
--- a/src/vnet/ipsec/ipsec_sa.h
+++ b/src/vnet/ipsec/ipsec_sa.h
@@ -106,9 +106,15 @@ typedef struct
ipsec_crypto_alg_t crypto_alg;
ipsec_key_t crypto_key;
+ u8 crypto_iv_size;
+ u8 crypto_block_size;
+ vnet_crypto_op_type_t crypto_enc_op_type;
+ vnet_crypto_op_type_t crypto_dec_op_type;
ipsec_integ_alg_t integ_alg;
ipsec_key_t integ_key;
+ vnet_crypto_op_type_t integ_op_type;
+ u8 integ_trunc_size;
u8 use_esn;
u8 use_anti_replay;
@@ -156,6 +162,10 @@ extern int ipsec_sa_add (u32 id,
u32 * sa_index);
extern u32 ipsec_sa_del (u32 id);
extern void ipsec_sa_stack (ipsec_sa_t * sa);
+extern void ipsec_sa_set_crypto_alg (ipsec_sa_t * sa,
+ ipsec_crypto_alg_t crypto_alg);
+extern void ipsec_sa_set_integ_alg (ipsec_sa_t * sa,
+ ipsec_integ_alg_t integ_alg);
extern u8 ipsec_is_sa_used (u32 sa_index);
extern int ipsec_set_sa_key (u32 id,