ipsec: keep crypto data inside SA
Change-Id: Ie8986bd3652d25c4befe681cea77df95aba37ebc
Signed-off-by: Damjan Marion <damarion@cisco.com>
diff --git a/src/vnet/ipsec/ah_decrypt.c b/src/vnet/ipsec/ah_decrypt.c
index 2488fa9..b128dfa 100644
--- a/src/vnet/ipsec/ah_decrypt.c
+++ b/src/vnet/ipsec/ah_decrypt.c
@@ -172,7 +172,7 @@
(&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 @@
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 ce930bd..c6dbe57 100644
--- a/src/vnet/ipsec/ah_encrypt.c
+++ b/src/vnet/ipsec/ah_encrypt.c
@@ -152,7 +152,7 @@
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 @@
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 1730038..74ab1f0 100644
--- a/src/vnet/ipsec/esp.h
+++ b/src/vnet/ipsec/esp.h
@@ -205,19 +205,17 @@
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 @@
#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 1ee7ce8..7860ca3 100644
--- a/src/vnet/ipsec/esp_decrypt.c
+++ b/src/vnet/ipsec/esp_decrypt.c
@@ -82,21 +82,16 @@
}
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 @@
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 @@
(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_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 37c2c95..1e29ee3 100644
--- a/src/vnet/ipsec/esp_encrypt.c
+++ b/src/vnet/ipsec/esp_encrypt.c
@@ -87,21 +87,16 @@
}
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 @@
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 @@
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 @@
}
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 f40e94d..33cac4c 100644
--- a/src/vnet/ipsec/ipsec_if.c
+++ b/src/vnet/ipsec/ipsec_if.c
@@ -493,25 +493,25 @@
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 fc8520d..337ca34 100644
--- a/src/vnet/ipsec/ipsec_sa.c
+++ b/src/vnet/ipsec/ipsec_sa.c
@@ -88,6 +88,26 @@
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 @@
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 2601f51..a6ade60 100644
--- a/src/vnet/ipsec/ipsec_sa.h
+++ b/src/vnet/ipsec/ipsec_sa.h
@@ -106,9 +106,15 @@
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 @@
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,