/*
 * esp_encrypt.c : IPSec ESP encrypt node
 *
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <vnet/vnet.h>
#include <vnet/api_errno.h>
#include <vnet/ip/ip.h>
#include <vnet/udp/udp.h>

#include <vnet/ipsec/ipsec.h>
#include <vnet/ipsec/esp.h>

#define foreach_esp_encrypt_next                   \
_(DROP, "error-drop")                              \
_(IP4_LOOKUP, "ip4-lookup")                        \
_(IP6_LOOKUP, "ip6-lookup")                        \
_(INTERFACE_OUTPUT, "interface-output")

#define _(v, s) ESP_ENCRYPT_NEXT_##v,
typedef enum
{
  foreach_esp_encrypt_next
#undef _
    ESP_ENCRYPT_N_NEXT,
} esp_encrypt_next_t;

#define foreach_esp_encrypt_error                   \
 _(RX_PKTS, "ESP pkts received")                    \
 _(NO_BUFFER, "No buffer (packet dropped)")         \
 _(DECRYPTION_FAILED, "ESP encryption failed")      \
 _(SEQ_CYCLED, "sequence number cycled")


typedef enum
{
#define _(sym,str) ESP_ENCRYPT_ERROR_##sym,
  foreach_esp_encrypt_error
#undef _
    ESP_ENCRYPT_N_ERROR,
} esp_encrypt_error_t;

static char *esp_encrypt_error_strings[] = {
#define _(sym,string) string,
  foreach_esp_encrypt_error
#undef _
};

typedef struct
{
  u32 sa_index;
  u32 spi;
  u32 seq;
  u8 udp_encap;
  ipsec_crypto_alg_t crypto_alg;
  ipsec_integ_alg_t integ_alg;
} esp_encrypt_trace_t;

/* packet trace format function */
static u8 *
format_esp_encrypt_trace (u8 * s, va_list * args)
{
  CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
  CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
  esp_encrypt_trace_t *t = va_arg (*args, esp_encrypt_trace_t *);

  s = format (s, "esp: sa-index %d spi %u seq %u crypto %U integrity %U%s",
	      t->sa_index, t->spi, t->seq,
	      format_ipsec_crypto_alg, t->crypto_alg,
	      format_ipsec_integ_alg, t->integ_alg,
	      t->udp_encap ? " udp-encap-enabled" : "");
  return s;
}

always_inline void
esp_encrypt_cbc (vlib_main_t * vm, ipsec_crypto_alg_t alg,
		 u8 * in, u8 * out, size_t in_len, u8 * key, u8 * iv)
{
  ipsec_proto_main_t *em = &ipsec_proto_main;
  u32 thread_index = vm->thread_index;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
  EVP_CIPHER_CTX *ctx = em->per_thread_data[thread_index].encrypt_ctx;
#else
  EVP_CIPHER_CTX *ctx = &(em->per_thread_data[thread_index].encrypt_ctx);
#endif
  const EVP_CIPHER *cipher = NULL;
  int out_len;

  ASSERT (alg < IPSEC_CRYPTO_N_ALG);

  if (PREDICT_FALSE
      (em->ipsec_proto_main_crypto_algs[alg].type == IPSEC_CRYPTO_ALG_NONE))
    return;

  if (PREDICT_FALSE
      (alg != em->per_thread_data[thread_index].last_encrypt_alg))
    {
      cipher = em->ipsec_proto_main_crypto_algs[alg].type;
      em->per_thread_data[thread_index].last_encrypt_alg = alg;
    }

  EVP_EncryptInit_ex (ctx, cipher, NULL, key, iv);

  EVP_EncryptUpdate (ctx, out, &out_len, in, in_len);
  EVP_EncryptFinal_ex (ctx, out + out_len, &out_len);
}

always_inline uword
esp_encrypt_inline (vlib_main_t * vm,
		    vlib_node_runtime_t * node, vlib_frame_t * from_frame,
		    int is_ip6)
{
  u32 *from = vlib_frame_vector_args (from_frame);
  u32 n_left_from = from_frame->n_vectors;
  ipsec_main_t *im = &ipsec_main;
  ipsec_proto_main_t *em = &ipsec_proto_main;
  u32 new_bufs[VLIB_FRAME_SIZE];
  vlib_buffer_t *i_bufs[VLIB_FRAME_SIZE], **ib = i_bufs;
  vlib_buffer_t *o_bufs[VLIB_FRAME_SIZE], **ob = o_bufs;
  u16 nexts[VLIB_FRAME_SIZE], *next = nexts;
  u32 n_alloc, thread_index = vm->thread_index;

  n_alloc = vlib_buffer_alloc (vm, new_bufs, n_left_from);
  if (n_alloc != n_left_from)
    {
      vlib_node_increment_counter (vm, node->node_index,
				   ESP_ENCRYPT_ERROR_NO_BUFFER,
				   n_left_from - n_alloc);
      if (n_alloc == 0)
	goto done;
      n_left_from = n_alloc;
    }

  vlib_get_buffers (vm, from, ib, n_left_from);
  vlib_get_buffers (vm, new_bufs, ob, n_left_from);

  while (n_left_from > 0)
    {
      u32 sa_index0;
      ipsec_sa_t *sa0;
      ip4_and_esp_header_t *oh0 = 0;
      ip6_and_esp_header_t *ih6_0, *oh6_0 = 0;
      ip4_and_udp_and_esp_header_t *iuh0, *ouh0 = 0;
      esp_header_t *o_esp0;
      esp_footer_t *f0;
      u8 ip_udp_hdr_size;
      u8 next_hdr_type;
      u32 ip_proto = 0;
      u8 transport_mode = 0;
      u32 esp_seq_err;

      next[0] = ESP_ENCRYPT_NEXT_DROP;

      sa_index0 = vnet_buffer (ib[0])->ipsec.sad_index;
      sa0 = pool_elt_at_index (im->sad, sa_index0);

      vlib_prefetch_combined_counter (&ipsec_sa_counters, thread_index,
				      sa_index0);

      esp_seq_err = esp_seq_advance (sa0);

      /* grab free buffer */
      ob[0]->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
      ob[0]->current_data = sizeof (ethernet_header_t);
      iuh0 = vlib_buffer_get_current (ib[0]);

      if (is_ip6)
	{
	  ih6_0 = vlib_buffer_get_current (ib[0]);
	  next_hdr_type = IP_PROTOCOL_IPV6;
	  oh6_0 = vlib_buffer_get_current (ob[0]);

	  oh6_0->ip6.ip_version_traffic_class_and_flow_label =
	    ih6_0->ip6.ip_version_traffic_class_and_flow_label;
	  oh6_0->ip6.protocol = IP_PROTOCOL_IPSEC_ESP;
	  ip_udp_hdr_size = sizeof (ip6_header_t);
	  o_esp0 = vlib_buffer_get_current (ob[0]) + ip_udp_hdr_size;
	  oh6_0->ip6.hop_limit = 254;
	  oh6_0->ip6.src_address.as_u64[0] = ih6_0->ip6.src_address.as_u64[0];
	  oh6_0->ip6.src_address.as_u64[1] = ih6_0->ip6.src_address.as_u64[1];
	  oh6_0->ip6.dst_address.as_u64[0] = ih6_0->ip6.dst_address.as_u64[0];
	  oh6_0->ip6.dst_address.as_u64[1] = ih6_0->ip6.dst_address.as_u64[1];
	  o_esp0->spi = clib_net_to_host_u32 (sa0->spi);
	  o_esp0->seq = clib_net_to_host_u32 (sa0->seq);
	  ip_proto = ih6_0->ip6.protocol;

	  next[0] = ESP_ENCRYPT_NEXT_IP6_LOOKUP;
	}
      else
	{
	  next_hdr_type = IP_PROTOCOL_IP_IN_IP;
	  oh0 = vlib_buffer_get_current (ob[0]);
	  ouh0 = vlib_buffer_get_current (ob[0]);

	  oh0->ip4.ip_version_and_header_length = 0x45;
	  oh0->ip4.tos = iuh0->ip4.tos;
	  oh0->ip4.fragment_id = 0;
	  oh0->ip4.flags_and_fragment_offset = 0;
	  oh0->ip4.ttl = 254;
	  if (sa0->udp_encap)
	    {
	      ouh0->udp.src_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec);
	      ouh0->udp.dst_port = clib_host_to_net_u16 (UDP_DST_PORT_ipsec);
	      ouh0->udp.checksum = 0;
	      ouh0->ip4.protocol = IP_PROTOCOL_UDP;
	      ip_udp_hdr_size = sizeof (udp_header_t) + sizeof (ip4_header_t);
	    }
	  else
	    {
	      oh0->ip4.protocol = IP_PROTOCOL_IPSEC_ESP;
	      ip_udp_hdr_size = sizeof (ip4_header_t);
	    }
	  o_esp0 = vlib_buffer_get_current (ob[0]) + ip_udp_hdr_size;
	  oh0->ip4.src_address.as_u32 = iuh0->ip4.src_address.as_u32;
	  oh0->ip4.dst_address.as_u32 = iuh0->ip4.dst_address.as_u32;
	  o_esp0->spi = clib_net_to_host_u32 (sa0->spi);
	  o_esp0->seq = clib_net_to_host_u32 (sa0->seq);
	  ip_proto = iuh0->ip4.protocol;

	  next[0] = ESP_ENCRYPT_NEXT_IP4_LOOKUP;
	}

      if (PREDICT_TRUE (!is_ip6 && sa0->is_tunnel && !sa0->is_tunnel_ip6))
	{
	  oh0->ip4.src_address.as_u32 = sa0->tunnel_src_addr.ip4.as_u32;
	  oh0->ip4.dst_address.as_u32 = sa0->tunnel_dst_addr.ip4.as_u32;

	  next[0] = sa0->dpo[IPSEC_PROTOCOL_ESP].dpoi_next_node;
	  vnet_buffer (ob[0])->ip.adj_index[VLIB_TX] =
	    sa0->dpo[IPSEC_PROTOCOL_ESP].dpoi_index;
	}
      else if (is_ip6 && sa0->is_tunnel && sa0->is_tunnel_ip6)
	{
	  oh6_0->ip6.src_address.as_u64[0] =
	    sa0->tunnel_src_addr.ip6.as_u64[0];
	  oh6_0->ip6.src_address.as_u64[1] =
	    sa0->tunnel_src_addr.ip6.as_u64[1];
	  oh6_0->ip6.dst_address.as_u64[0] =
	    sa0->tunnel_dst_addr.ip6.as_u64[0];
	  oh6_0->ip6.dst_address.as_u64[1] =
	    sa0->tunnel_dst_addr.ip6.as_u64[1];

	  next[0] = sa0->dpo[IPSEC_PROTOCOL_ESP].dpoi_next_node;
	  vnet_buffer (ob[0])->ip.adj_index[VLIB_TX] =
	    sa0->dpo[IPSEC_PROTOCOL_ESP].dpoi_index;
	}
      else
	{
	  next_hdr_type = ip_proto;
	  if (vnet_buffer (ib[0])->sw_if_index[VLIB_TX] != ~0)
	    {
	      transport_mode = 1;
	      ethernet_header_t *ieh0, *oeh0;
	      ieh0 =
		(ethernet_header_t *) ((u8 *)
				       vlib_buffer_get_current (ib[0]) -
				       sizeof (ethernet_header_t));
	      oeh0 = (ethernet_header_t *) ob[0]->data;
	      clib_memcpy_fast (oeh0, ieh0, sizeof (ethernet_header_t));
	      next[0] = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
	      vnet_buffer (ob[0])->sw_if_index[VLIB_TX] =
		vnet_buffer (ib[0])->sw_if_index[VLIB_TX];
	    }

	  if (is_ip6)
	    vlib_buffer_advance (ib[0], sizeof (ip6_header_t));
	  else
	    vlib_buffer_advance (ib[0], sizeof (ip4_header_t));
	}

      ASSERT (sa0->crypto_alg < IPSEC_CRYPTO_N_ALG);
      vlib_increment_combined_counter
	(&ipsec_sa_counters, thread_index, sa_index0,
	 1, ib[0]->current_length);

      if (PREDICT_TRUE (sa0->crypto_alg != IPSEC_CRYPTO_ALG_NONE))
	{

	  const int BLOCK_SIZE =
	    em->ipsec_proto_main_crypto_algs[sa0->crypto_alg].block_size;
	  const int IV_SIZE =
	    em->ipsec_proto_main_crypto_algs[sa0->crypto_alg].iv_size;
	  int blocks = 1 + (ib[0]->current_length + 1) / BLOCK_SIZE;

	  /* pad packet in input buffer */
	  u8 pad_bytes = BLOCK_SIZE * blocks - 2 - ib[0]->current_length;
	  u8 i;
	  u8 *padding =
	    vlib_buffer_get_current (ib[0]) + ib[0]->current_length;
	  ib[0]->current_length = BLOCK_SIZE * blocks;
	  for (i = 0; i < pad_bytes; ++i)
	    {
	      padding[i] = i + 1;
	    }
	  f0 = vlib_buffer_get_current (ib[0]) + ib[0]->current_length - 2;
	  f0->pad_length = pad_bytes;
	  f0->next_header = next_hdr_type;

	  ob[0]->current_length = ip_udp_hdr_size + sizeof (esp_header_t) +
	    BLOCK_SIZE * blocks + IV_SIZE;

	  vnet_buffer (ob[0])->sw_if_index[VLIB_RX] =
	    vnet_buffer (ib[0])->sw_if_index[VLIB_RX];

	  u8 iv[em->ipsec_proto_main_crypto_algs[sa0->crypto_alg].iv_size];
	  RAND_bytes (iv, sizeof (iv));

	  clib_memcpy_fast ((u8 *) vlib_buffer_get_current (ob[0]) +
			    ip_udp_hdr_size + sizeof (esp_header_t), iv,
			    em->ipsec_proto_main_crypto_algs[sa0->
							     crypto_alg].iv_size);

	  esp_encrypt_cbc (vm, sa0->crypto_alg,
			   (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,
			   sa0->crypto_key.data, iv);
	}

      ob[0]->current_length +=
	hmac_calc (sa0->integ_alg, sa0->integ_key.data,
		   sa0->integ_key.len, (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);


      if (is_ip6)
	{
	  oh6_0->ip6.payload_length =
	    clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, ob[0]) -
				  sizeof (ip6_header_t));
	}
      else
	{
	  oh0->ip4.length =
	    clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, ob[0]));
	  oh0->ip4.checksum = ip4_header_checksum (&oh0->ip4);
	  if (sa0->udp_encap)
	    {
	      ouh0->udp.length =
		clib_host_to_net_u16 (clib_net_to_host_u16
				      (oh0->ip4.length) -
				      ip4_header_bytes (&oh0->ip4));
	    }
	}

      if (transport_mode)
	vlib_buffer_reset (ob[0]);

      if (PREDICT_FALSE (esp_seq_err))
	{
	  ob[0]->error = node->errors[ESP_ENCRYPT_ERROR_SEQ_CYCLED];
	  next[0] = ESP_ENCRYPT_NEXT_DROP;
	}

      if (PREDICT_FALSE (ib[0]->flags & VLIB_BUFFER_IS_TRACED))
	{
	  if (ob[0])
	    {
	      ob[0]->flags |= VLIB_BUFFER_IS_TRACED;
	      ob[0]->trace_index = ib[0]->trace_index;
	      esp_encrypt_trace_t *tr =
		vlib_add_trace (vm, node, ob[0], sizeof (*tr));
	      tr->sa_index = sa_index0;
	      tr->spi = sa0->spi;
	      tr->seq = sa0->seq - 1;
	      tr->udp_encap = sa0->udp_encap;
	      tr->crypto_alg = sa0->crypto_alg;
	      tr->integ_alg = sa0->integ_alg;
	    }
	}

      /* next */
      n_left_from -= 1;
      ib += 1;
      ob += 1;
      next += 1;
    }

  vlib_node_increment_counter (vm, node->node_index,
			       ESP_ENCRYPT_ERROR_RX_PKTS, n_alloc);

  vlib_buffer_enqueue_to_next (vm, node, new_bufs, nexts, n_alloc);
done:
  vlib_buffer_free (vm, from, from_frame->n_vectors);
  return n_alloc;
}

VLIB_NODE_FN (esp4_encrypt_node) (vlib_main_t * vm,
				  vlib_node_runtime_t * node,
				  vlib_frame_t * from_frame)
{
  return esp_encrypt_inline (vm, node, from_frame, 0 /* is_ip6 */ );
}

/* *INDENT-OFF* */
VLIB_REGISTER_NODE (esp4_encrypt_node) = {
  .name = "esp4-encrypt",
  .vector_size = sizeof (u32),
  .format_trace = format_esp_encrypt_trace,
  .type = VLIB_NODE_TYPE_INTERNAL,

  .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
  .error_strings = esp_encrypt_error_strings,

  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
  .next_nodes = {
#define _(s,n) [ESP_ENCRYPT_NEXT_##s] = n,
    foreach_esp_encrypt_next
#undef _
  },
};
/* *INDENT-ON* */

VLIB_NODE_FN (esp6_encrypt_node) (vlib_main_t * vm,
				  vlib_node_runtime_t * node,
				  vlib_frame_t * from_frame)
{
  return esp_encrypt_inline (vm, node, from_frame, 1 /* is_ip6 */ );
}

/* *INDENT-OFF* */
VLIB_REGISTER_NODE (esp6_encrypt_node) = {
  .name = "esp6-encrypt",
  .vector_size = sizeof (u32),
  .format_trace = format_esp_encrypt_trace,
  .type = VLIB_NODE_TYPE_INTERNAL,

  .n_errors = ARRAY_LEN(esp_encrypt_error_strings),
  .error_strings = esp_encrypt_error_strings,

  .n_next_nodes = ESP_ENCRYPT_N_NEXT,
  .next_nodes = {
#define _(s,n) [ESP_ENCRYPT_NEXT_##s] = n,
    foreach_esp_encrypt_next
#undef _
  },
};
/* *INDENT-ON* */

/*
 * fd.io coding-style-patch-verification: ON
 *
 * Local Variables:
 * eval: (c-set-style "gnu")
 * End:
 */
