- const int BLOCK_SIZE = 16;
- const int IV_SIZE = 16;
- esp_footer_t *f0;
- u8 ip_hdr_size = 0;
-
- int blocks =
- (i_b0->current_length - sizeof (esp_header_t) -
- IV_SIZE) / BLOCK_SIZE;
-
- o_b0->current_data = sizeof (ethernet_header_t);
-
- /* transport mode */
- if (PREDICT_FALSE (!sa0->is_tunnel && !sa0->is_tunnel_ip6))
- {
- tunnel_mode = 0;
- ih4 =
- (ip4_header_t *) (i_b0->data +
- sizeof (ethernet_header_t));
- if (PREDICT_TRUE
- ((ih4->ip_version_and_header_length & 0xF0) != 0x40))
- {
- if (PREDICT_TRUE
- ((ih4->ip_version_and_header_length & 0xF0) ==
- 0x60))
- {
- transport_ip6 = 1;
- ip_hdr_size = sizeof (ip6_header_t);
- ih6 =
- (ip6_header_t *) (i_b0->data +
- sizeof (ethernet_header_t));
- oh6 = vlib_buffer_get_current (o_b0);
- }
- else
- {
- vlib_node_increment_counter (vm,
- esp_decrypt_node.index,
- ESP_DECRYPT_ERROR_NOT_IP,
- 1);
- o_b0 = 0;
- goto trace;
- }
- }
- else
- {
- oh4 = vlib_buffer_get_current (o_b0);
- ip_hdr_size = sizeof (ip4_header_t);
- }
- }
-
- esp_decrypt_aes_cbc (sa0->crypto_alg,
- esp0->data + IV_SIZE,
- (u8 *) vlib_buffer_get_current (o_b0) +
- ip_hdr_size, BLOCK_SIZE * blocks,
- sa0->crypto_key, esp0->data);
-
- o_b0->current_length = (blocks * 16) - 2 + ip_hdr_size;
- o_b0->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
- f0 =
- (esp_footer_t *) ((u8 *) vlib_buffer_get_current (o_b0) +
- o_b0->current_length);
- o_b0->current_length -= f0->pad_length;
-
- /* tunnel mode */
- if (PREDICT_TRUE (tunnel_mode))
- {
- if (PREDICT_TRUE (f0->next_header == IP_PROTOCOL_IP_IN_IP))
- {
- next0 = ESP_DECRYPT_NEXT_IP4_INPUT;
- oh4 = vlib_buffer_get_current (o_b0);
- }
- else if (f0->next_header == IP_PROTOCOL_IPV6)
- next0 = ESP_DECRYPT_NEXT_IP6_INPUT;
- else
- {
- clib_warning ("next header: 0x%x", f0->next_header);
- vlib_node_increment_counter (vm, esp_decrypt_node.index,
- ESP_DECRYPT_ERROR_DECRYPTION_FAILED,
- 1);
- o_b0 = 0;
- goto trace;
- }
- }
- /* transport mode */
- else
- {
- if (PREDICT_FALSE (transport_ip6))
- {
- next0 = ESP_DECRYPT_NEXT_IP6_INPUT;
- oh6->ip_version_traffic_class_and_flow_label =
- ih6->ip_version_traffic_class_and_flow_label;
- oh6->protocol = f0->next_header;
- oh6->hop_limit = ih6->hop_limit;
- oh6->src_address.as_u64[0] = ih6->src_address.as_u64[0];
- oh6->src_address.as_u64[1] = ih6->src_address.as_u64[1];
- oh6->dst_address.as_u64[0] = ih6->dst_address.as_u64[0];
- oh6->dst_address.as_u64[1] = ih6->dst_address.as_u64[1];
- oh6->payload_length =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain
- (vm,
- o_b0) - sizeof (ip6_header_t));
- }
- else
- {
- next0 = ESP_DECRYPT_NEXT_IP4_INPUT;
- oh4->ip_version_and_header_length = 0x45;
- oh4->tos = ih4->tos;
- oh4->fragment_id = 0;
- oh4->flags_and_fragment_offset = 0;
- oh4->ttl = ih4->ttl;
- oh4->protocol = f0->next_header;
- oh4->src_address.as_u32 = ih4->src_address.as_u32;
- oh4->dst_address.as_u32 = ih4->dst_address.as_u32;
- oh4->length =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain
- (vm, o_b0));
- oh4->checksum = ip4_header_checksum (oh4);
- }
- }
-
- /* for IPSec-GRE tunnel next node is ipsec-gre-input */
- if (PREDICT_FALSE
- ((vnet_buffer (i_b0)->ipsec.flags) &
- IPSEC_FLAG_IPSEC_GRE_TUNNEL))
- next0 = ESP_DECRYPT_NEXT_IPSEC_GRE_INPUT;
-
- vnet_buffer (o_b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
- vnet_buffer (o_b0)->sw_if_index[VLIB_RX] =
- vnet_buffer (i_b0)->sw_if_index[VLIB_RX];