From b966e8bfdd3c63e2436ab6e5d250c8b1bf4dd102 Mon Sep 17 00:00:00 2001 From: Damjan Marion Date: Wed, 20 Mar 2019 16:07:09 +0100 Subject: [PATCH] ipsec: keep crypto data inside SA Change-Id: Ie8986bd3652d25c4befe681cea77df95aba37ebc Signed-off-by: Damjan Marion --- src/vnet/ipsec/ah_decrypt.c | 6 ++---- src/vnet/ipsec/ah_encrypt.c | 9 +++------ src/vnet/ipsec/esp.h | 16 +++++++--------- src/vnet/ipsec/esp_decrypt.c | 24 ++++++++---------------- src/vnet/ipsec/esp_encrypt.c | 26 +++++++++----------------- src/vnet/ipsec/ipsec_if.c | 8 ++++---- src/vnet/ipsec/ipsec_sa.c | 24 ++++++++++++++++++++++-- src/vnet/ipsec/ipsec_sa.h | 10 ++++++++++ 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, -- 2.16.6