diff options
author | PiotrX Kleski <piotrx.kleski@intel.com> | 2020-12-11 15:10:31 +0000 |
---|---|---|
committer | Damjan Marion <dmarion@me.com> | 2020-12-18 14:24:32 +0000 |
commit | a9585fd2060e3c8cff89b7f83d8ee10a669c9649 (patch) | |
tree | e1b7ba8b4fbb8be88d3fc1227e9a6a46218b9f6c /src | |
parent | e3e16172070e16e48d88b3e61dd2f3c539655513 (diff) |
ipsec: fixed esp_decrypt pkt len after icv moved
Type: fix
This change makes esp_move_icv() update pd->current_length if the first
buffer's length is updated.
In case that ICV is split over two buffers, esp_move_icv() copies ICV
to last buffer, it also updates the before_last buffer's current_length.
However, in esp_decrypt_post_crypto(), pd->current_lenght is used to update
first buffer lenght, but pd is not updated in esp_move_icv()
and the total pkt lenght ends up incorrect.
This only happens in tunnel mode when ICV is split between 1st and 2nd buffers.
Signed-off-by: PiotrX Kleski <piotrx.kleski@intel.com>
Change-Id: Ic39d87454ec0d022c050775acb64c5c25ccf7f13
Diffstat (limited to 'src')
-rw-r--r-- | src/vnet/ipsec/esp_decrypt.c | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/src/vnet/ipsec/esp_decrypt.c b/src/vnet/ipsec/esp_decrypt.c index a8d890bd2e7..1390f80a1ba 100644 --- a/src/vnet/ipsec/esp_decrypt.c +++ b/src/vnet/ipsec/esp_decrypt.c @@ -202,6 +202,7 @@ esp_remove_tail (vlib_main_t * vm, vlib_buffer_t * b, vlib_buffer_t * last, return pointer to it */ static_always_inline u8 * esp_move_icv (vlib_main_t * vm, vlib_buffer_t * first, + esp_decrypt_packet_data_t * pd, esp_decrypt_packet_data2_t * pd2, u16 icv_sz, u16 * dif) { vlib_buffer_t *before_last, *bp; @@ -220,6 +221,8 @@ esp_move_icv (vlib_main_t * vm, vlib_buffer_t * first, clib_memcpy_fast (lb_curr, vlib_buffer_get_tail (before_last) - first_sz, first_sz); before_last->current_length -= first_sz; + if (before_last == first) + pd->current_length -= first_sz; clib_memset (vlib_buffer_get_tail (before_last), 0, first_sz); if (dif) dif[0] = first_sz; @@ -268,11 +271,12 @@ esp_insert_esn (vlib_main_t * vm, ipsec_sa_t * sa, static_always_inline u8 * esp_move_icv_esn (vlib_main_t * vm, vlib_buffer_t * first, + esp_decrypt_packet_data_t * pd, esp_decrypt_packet_data2_t * pd2, u16 icv_sz, ipsec_sa_t * sa, u8 * extra_esn, u32 * len) { u16 dif = 0; - u8 *digest = esp_move_icv (vm, first, pd2, icv_sz, &dif); + u8 *digest = esp_move_icv (vm, first, pd, pd2, icv_sz, &dif); if (dif) *len -= dif; @@ -398,6 +402,7 @@ esp_decrypt_chain_integ (vlib_main_t * vm, ipsec_per_thread_data_t * ptd, static_always_inline u32 esp_decrypt_chain_crypto (vlib_main_t * vm, ipsec_per_thread_data_t * ptd, + esp_decrypt_packet_data_t * pd, esp_decrypt_packet_data2_t * pd2, ipsec_sa_t * sa0, vlib_buffer_t * b, u8 icv_sz, u8 * start, u32 start_len, u8 ** tag, u16 * n_ch) @@ -424,7 +429,7 @@ esp_decrypt_chain_crypto (vlib_main_t * vm, ipsec_per_thread_data_t * ptd, if (pd2->lb->current_length < icv_sz) { u16 dif = 0; - *tag = esp_move_icv (vm, b, pd2, icv_sz, &dif); + *tag = esp_move_icv (vm, b, pd, pd2, icv_sz, &dif); /* this chunk does not contain crypto data */ n_chunks -= 1; @@ -506,7 +511,7 @@ esp_decrypt_prepare_sync_op (vlib_main_t * vm, vlib_node_runtime_t * node, { u8 extra_esn = 0; op->digest = - esp_move_icv_esn (vm, b, pd2, icv_sz, sa0, + esp_move_icv_esn (vm, b, pd, pd2, icv_sz, sa0, &extra_esn, &op->len); if (extra_esn) @@ -596,7 +601,7 @@ esp_decrypt_prepare_sync_op (vlib_main_t * vm, vlib_node_runtime_t * node, /* buffer is chained */ op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS; op->chunk_index = vec_len (ptd->chunks); - esp_decrypt_chain_crypto (vm, ptd, pd2, sa0, b, icv_sz, + esp_decrypt_chain_crypto (vm, ptd, pd, pd2, sa0, b, icv_sz, payload, len - pd->iv_sz + pd->icv_sz, &op->tag, &op->n_chunks); } @@ -646,7 +651,7 @@ esp_decrypt_prepare_async_frame (vlib_main_t * vm, if (pd2->lb->current_length < icv_sz) { u8 extra_esn = 0; - tag = esp_move_icv_esn (vm, b, pd2, icv_sz, sa0, + tag = esp_move_icv_esn (vm, b, pd, pd2, icv_sz, sa0, &extra_esn, &integ_len); if (extra_esn) @@ -728,7 +733,7 @@ out: /* buffer is chained */ flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS; - crypto_len = esp_decrypt_chain_crypto (vm, ptd, pd2, sa0, b, icv_sz, + crypto_len = esp_decrypt_chain_crypto (vm, ptd, pd, pd2, sa0, b, icv_sz, payload, len - pd->iv_sz + pd->icv_sz, &tag, 0); |