Add API call to set keys on IPsec tunnel intf 64/8764/2
authorMatthew Smith <mgsmith@netgate.com>
Fri, 6 Oct 2017 00:03:05 +0000 (19:03 -0500)
committerDamjan Marion <dmarion.lists@gmail.com>
Sat, 14 Oct 2017 09:11:52 +0000 (09:11 +0000)
There was already a CLI command and a libvnet function
to set the keys on an existing IPsec tunnel interface.
Expose this via the API.

Change-Id: I226a9616f680fc022f04447177a2e8232690657f
Signed-off-by: Matthew Smith <mgsmith@netgate.com>
src/vat/api_format.c
src/vnet/ipsec/ipsec.api
src/vnet/ipsec/ipsec_api.c

index 615e9cb..35b46f4 100644 (file)
@@ -5077,6 +5077,7 @@ _(ipsec_spd_add_del_entry_reply)                        \
 _(ipsec_sad_add_del_entry_reply)                        \
 _(ipsec_sa_set_key_reply)                               \
 _(ipsec_tunnel_if_add_del_reply)                        \
+_(ipsec_tunnel_if_set_key_reply)                        \
 _(ikev2_profile_add_del_reply)                          \
 _(ikev2_profile_set_auth_reply)                         \
 _(ikev2_profile_set_id_reply)                           \
@@ -5310,6 +5311,7 @@ _(IPSEC_SAD_ADD_DEL_ENTRY_REPLY, ipsec_sad_add_del_entry_reply)         \
 _(IPSEC_SA_DETAILS, ipsec_sa_details)                                   \
 _(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply)                       \
 _(IPSEC_TUNNEL_IF_ADD_DEL_REPLY, ipsec_tunnel_if_add_del_reply)         \
+_(IPSEC_TUNNEL_IF_SET_KEY_REPLY, ipsec_tunnel_if_set_key_reply)         \
 _(IKEV2_PROFILE_ADD_DEL_REPLY, ikev2_profile_add_del_reply)             \
 _(IKEV2_PROFILE_SET_AUTH_REPLY, ikev2_profile_set_auth_reply)           \
 _(IKEV2_PROFILE_SET_ID_REPLY, ikev2_profile_set_id_reply)               \
@@ -14284,6 +14286,79 @@ api_ipsec_sa_dump (vat_main_t * vam)
   return ret;
 }
 
+static int
+api_ipsec_tunnel_if_set_key (vat_main_t * vam)
+{
+  unformat_input_t *i = vam->input;
+  vl_api_ipsec_tunnel_if_set_key_t *mp;
+  u32 sw_if_index = ~0;
+  u8 key_type = IPSEC_IF_SET_KEY_TYPE_NONE;
+  u8 *key = 0;
+  u32 alg = ~0;
+  int ret;
+
+  while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+    {
+      if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index))
+       ;
+      else
+       if (unformat (i, "local crypto %U", unformat_ipsec_crypto_alg, &alg))
+       key_type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO;
+      else
+       if (unformat (i, "remote crypto %U", unformat_ipsec_crypto_alg, &alg))
+       key_type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO;
+      else if (unformat (i, "local integ %U", unformat_ipsec_integ_alg, &alg))
+       key_type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG;
+      else
+       if (unformat (i, "remote integ %U", unformat_ipsec_integ_alg, &alg))
+       key_type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG;
+      else if (unformat (i, "%U", unformat_hex_string, &key))
+       ;
+      else
+       {
+         clib_warning ("parse error '%U'", format_unformat_error, i);
+         return -99;
+       }
+    }
+
+  if (sw_if_index == ~0)
+    {
+      errmsg ("interface must be specified");
+      return -99;
+    }
+
+  if (key_type == IPSEC_IF_SET_KEY_TYPE_NONE)
+    {
+      errmsg ("key type must be specified");
+      return -99;
+    }
+
+  if (alg == ~0)
+    {
+      errmsg ("algorithm must be specified");
+      return -99;
+    }
+
+  if (vec_len (key) == 0)
+    {
+      errmsg ("key must be specified");
+      return -99;
+    }
+
+  M (IPSEC_TUNNEL_IF_SET_KEY, mp);
+
+  mp->sw_if_index = htonl (sw_if_index);
+  mp->alg = alg;
+  mp->key_type = key_type;
+  mp->key_len = vec_len (key);
+  clib_memcpy (mp->key, key, vec_len (key));
+
+  S (mp);
+  W (ret);
+
+  return ret;
+}
+
 static int
 api_ikev2_profile_add_del (vat_main_t * vam)
 {
@@ -21547,6 +21622,8 @@ _(ipsec_tunnel_if_add_del, "local_spi <n> remote_spi <n>\n"             \
   "  integ_alg <alg> local_integ_key <hex> remote_integ_key <hex>\n"    \
   "  local_ip <addr> remote_ip <addr> [esn] [anti_replay] [del]\n")     \
 _(ipsec_sa_dump, "[sa_id <n>]")                                         \
+_(ipsec_tunnel_if_set_key, "<intfc> <local|remote> <crypto|integ>\n"    \
+  "  <alg> <hex>\n")                                                    \
 _(ikev2_profile_add_del, "name <profile_name> [del]")                   \
 _(ikev2_profile_set_auth, "name <profile_name> auth_method <method>\n"  \
   "(auth_data 0x<data> | auth_data <data>)")                            \
index 14d6c18..67c3336 100644 (file)
@@ -615,6 +615,25 @@ define ipsec_sa_details {
   u64 total_data_size;
 };
 
+/** \brief Set key on IPsec interface
+    @param client_index - opaque cookie to identify the sender
+    @param context - sender context, to match reply w/ request
+    @param sw_if_index - index of tunnel interface
+    @param key_type - type of key being set
+    @param alg - algorithm used with key
+    @param key_len - length key in bytes
+    @param key - key
+*/
+autoreply define ipsec_tunnel_if_set_key {
+  u32 client_index;
+  u32 context;
+  u32 sw_if_index;
+  u8 key_type;
+  u8 alg;
+  u8 key_len;
+  u8 key[128];
+};
+
 /*
  * Local Variables:
  * eval: (c-set-style "gnu")
index ae62ade..c3f5745 100644 (file)
@@ -56,6 +56,7 @@ _(IPSEC_SA_SET_KEY, ipsec_sa_set_key)                                   \
 _(IPSEC_SA_DUMP, ipsec_sa_dump)                                         \
 _(IPSEC_SPD_DUMP, ipsec_spd_dump)                                       \
 _(IPSEC_TUNNEL_IF_ADD_DEL, ipsec_tunnel_if_add_del)                     \
+_(IPSEC_TUNNEL_IF_SET_KEY, ipsec_tunnel_if_set_key)                     \
 _(IKEV2_PROFILE_ADD_DEL, ikev2_profile_add_del)                         \
 _(IKEV2_PROFILE_SET_AUTH, ikev2_profile_set_auth)                       \
 _(IKEV2_PROFILE_SET_ID, ikev2_profile_set_id)                           \
@@ -509,6 +510,61 @@ vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp)
 }
 
 
+static void
+vl_api_ipsec_tunnel_if_set_key_t_handler (vl_api_ipsec_tunnel_if_set_key_t *
+                                         mp)
+{
+  vl_api_ipsec_tunnel_if_set_key_reply_t *rmp;
+  ipsec_main_t *im = &ipsec_main;
+  vnet_main_t *vnm = im->vnet_main;
+  vnet_sw_interface_t *sw;
+  u8 *key = 0;
+  int rv;
+
+#if WITH_LIBSSL > 0
+  sw = vnet_get_sw_interface (vnm, ntohl (mp->sw_if_index));
+
+  switch (mp->key_type)
+    {
+    case IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO:
+    case IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO:
+      if (mp->alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
+         mp->alg > IPSEC_CRYPTO_N_ALG)
+       {
+         rv = VNET_API_ERROR_UNIMPLEMENTED;
+         goto out;
+       }
+      break;
+    case IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG:
+    case IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG:
+      if (mp->alg > IPSEC_INTEG_N_ALG)
+       {
+         rv = VNET_API_ERROR_UNIMPLEMENTED;
+         goto out;
+       }
+      break;
+    case IPSEC_IF_SET_KEY_TYPE_NONE:
+    default:
+      rv = VNET_API_ERROR_UNIMPLEMENTED;
+      goto out;
+      break;
+    }
+
+  key = vec_new (u8, mp->key_len);
+  clib_memcpy (key, mp->key, mp->key_len);
+
+  rv = ipsec_set_interface_key (vnm, sw->hw_if_index, mp->key_type, mp->alg,
+                               key);
+  vec_free (key);
+#else
+  clib_warning ("unimplemented");
+#endif
+
+out:
+  REPLY_MACRO (VL_API_IPSEC_TUNNEL_IF_SET_KEY_REPLY);
+}
+
+
 static void
 vl_api_ikev2_profile_add_del_t_handler (vl_api_ikev2_profile_add_del_t * mp)
 {