bfd: use vnet crypto

Type: improvement

Change-Id: I873a99c1258a97ed5ed195b9756e8302f865e7f0
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ebf03bd..1730e7b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -176,7 +176,7 @@
 if(VPP_HOST_TOOLS_ONLY)
   set(SUBDIRS tools/vppapigen cmake)
 elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
-  find_package(OpenSSL REQUIRED)
+  find_package(OpenSSL)
   set(SUBDIRS
     vppinfra svm vlib vlibmemory vlibapi vnet vpp vat vat2 vcl plugins
     vpp-api tools/vppapigen tools/g2 tools/perftool cmake pkg
diff --git a/src/plugins/quic/CMakeLists.txt b/src/plugins/quic/CMakeLists.txt
index 7a121e5..dfed91f 100644
--- a/src/plugins/quic/CMakeLists.txt
+++ b/src/plugins/quic/CMakeLists.txt
@@ -48,7 +48,7 @@
       quic.c
       quic_crypto.c
 
-      LINK_LIBRARIES ${QUIC_LINK_LIBRARIES}
+      LINK_LIBRARIES ${QUIC_LINK_LIBRARIES} ${OPENSSL_LIBRARIES}
     )
     message(STATUS "Found quicly ${EXPECTED_QUICLY_VERSION} in ${QUICLY_INCLUDE_DIR}")
   else()
diff --git a/src/plugins/wireguard/CMakeLists.txt b/src/plugins/wireguard/CMakeLists.txt
index db74f9c..6dddc67 100755
--- a/src/plugins/wireguard/CMakeLists.txt
+++ b/src/plugins/wireguard/CMakeLists.txt
@@ -16,6 +16,8 @@
   return()
 endif()
 
+include_directories(${OPENSSL_INCLUDE_DIR})
+
 list(APPEND WG_BLAKE_SOURCES
   blake/blake2s.h
   blake/blake2s.c
@@ -49,6 +51,8 @@
   wireguard_index_table.h
   wireguard_api.c
 
+  LINK_LIBRARIES ${OPENSSL_LIBRARIES}
+
   API_FILES
   wireguard.api
 
diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt
index 03ace21..47d7b56 100644
--- a/src/vnet/CMakeLists.txt
+++ b/src/vnet/CMakeLists.txt
@@ -11,9 +11,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-add_definitions (-DWITH_LIBSSL=1)
-include_directories(${OPENSSL_INCLUDE_DIR})
-
 unset(VNET_SOURCES)
 unset(VNET_HEADERS)
 unset(VNET_API_FILES)
@@ -1489,7 +1486,7 @@
   MULTIARCH_SOURCES ${VNET_MULTIARCH_SOURCES}
   INSTALL_HEADERS ${VNET_HEADERS}
   API_FILES ${VNET_API_FILES}
-  LINK_LIBRARIES vppinfra svm vlib ${OPENSSL_LIBRARIES}
+  LINK_LIBRARIES vppinfra svm vlib
   DEPENDS vpp_version_h api_headers
 )
 
diff --git a/src/vnet/bfd/bfd_main.c b/src/vnet/bfd/bfd_main.c
index 9e575af..c67317f 100644
--- a/src/vnet/bfd/bfd_main.c
+++ b/src/vnet/bfd/bfd_main.c
@@ -17,14 +17,6 @@
  * @brief BFD nodes implementation
  */
 
-#if WITH_LIBSSL > 0
-#include <openssl/sha.h>
-#endif
-
-#if __SSE4_2__
-#include <x86intrin.h>
-#endif
-
 #include <vlibmemory/api.h>
 #include <vppinfra/random.h>
 #include <vppinfra/error.h>
@@ -36,6 +28,7 @@
 #include <vnet/bfd/bfd_protocol.h>
 #include <vnet/bfd/bfd_main.h>
 #include <vlib/log.h>
+#include <vnet/crypto/crypto.h>
 
 static u64
 bfd_calc_echo_checksum (u32 discriminator, u64 expire_time, u32 secret)
@@ -784,9 +777,9 @@
   return 0;
 }
 
-#if WITH_LIBSSL > 0
 static void
-bfd_add_sha1_auth_section (vlib_buffer_t * b, bfd_session_t * bs)
+bfd_add_sha1_auth_section (vlib_main_t *vm, vlib_buffer_t *b,
+			   bfd_session_t *bs)
 {
   bfd_pkt_with_sha1_auth_t *pkt = vlib_buffer_get_current (b);
   bfd_auth_sha1_t *auth = &pkt->sha1_auth;
@@ -810,14 +803,19 @@
   clib_memcpy (auth->hash, bs->auth.curr_key->key,
 	       sizeof (bs->auth.curr_key->key));
   unsigned char hash[sizeof (auth->hash)];
-  SHA1 ((unsigned char *) pkt, sizeof (*pkt), hash);
+
+  vnet_crypto_op_t op;
+  vnet_crypto_op_init (&op, VNET_CRYPTO_OP_SHA1_HASH);
+  op.src = (u8 *) pkt;
+  op.len = sizeof (*pkt);
+  op.digest = hash;
+  vnet_crypto_process_ops (vm, &op, 1);
   BFD_DBG ("hashing: %U", format_hex_bytes, pkt, sizeof (*pkt));
   clib_memcpy (auth->hash, hash, sizeof (hash));
 }
-#endif
 
 static void
-bfd_add_auth_section (vlib_buffer_t * b, bfd_session_t * bs)
+bfd_add_auth_section (vlib_main_t *vm, vlib_buffer_t *b, bfd_session_t *bs)
 {
   bfd_main_t *bm = &bfd_main;
   if (bs->auth.curr_key)
@@ -836,21 +834,11 @@
 			 "internal error, unexpected BFD auth type '%d'",
 			 auth_type);
 	  break;
-#if WITH_LIBSSL > 0
 	case BFD_AUTH_TYPE_keyed_sha1:
 	  /* fallthrough */
 	case BFD_AUTH_TYPE_meticulous_keyed_sha1:
-	  bfd_add_sha1_auth_section (b, bs);
+	  bfd_add_sha1_auth_section (vm, b, bs);
 	  break;
-#else
-	case BFD_AUTH_TYPE_keyed_sha1:
-	  /* fallthrough */
-	case BFD_AUTH_TYPE_meticulous_keyed_sha1:
-	  vlib_log_crit (bm->log_class,
-			 "internal error, unexpected BFD auth type '%d'",
-			 auth_type);
-	  break;
-#endif
 	}
     }
 }
@@ -1016,7 +1004,7 @@
 	  /* fallthrough */
 	  break;
 	}
-      bfd_add_auth_section (b, bs);
+      bfd_add_auth_section (vm, b, bs);
       bfd_add_transport_layer (vm, bi, bs);
       if (!bfd_transport_control_frame (vm, bi, bs))
 	{
@@ -1041,7 +1029,7 @@
   BFD_DBG ("Send final control frame for bs_idx=%lu", bs->bs_idx);
   bfd_init_control_frame (bm, bs, b);
   bfd_pkt_set_final (vlib_buffer_get_current (b));
-  bfd_add_auth_section (b, bs);
+  bfd_add_auth_section (vm, b, bs);
   u32 bi = vlib_get_buffer_index (vm, b);
   bfd_add_transport_layer (vm, bi, bs);
   bs->last_tx_nsec = bfd_time_now_nsec (vm, NULL);
@@ -1592,14 +1580,13 @@
 }
 
 static int
-bfd_verify_pkt_auth_key_sha1 (const bfd_pkt_t * pkt, u32 pkt_size,
-			      bfd_session_t * bs, u8 bfd_key_id,
-			      bfd_auth_key_t * auth_key)
+bfd_verify_pkt_auth_key_sha1 (vlib_main_t *vm, const bfd_pkt_t *pkt,
+			      u32 pkt_size, bfd_session_t *bs, u8 bfd_key_id,
+			      bfd_auth_key_t *auth_key)
 {
   ASSERT (auth_key->auth_type == BFD_AUTH_TYPE_keyed_sha1 ||
 	  auth_key->auth_type == BFD_AUTH_TYPE_meticulous_keyed_sha1);
 
-  u8 result[SHA_DIGEST_LENGTH];
   bfd_pkt_with_common_auth_t *with_common = (void *) pkt;
   if (pkt_size < sizeof (*with_common))
     {
@@ -1634,36 +1621,29 @@
 	 auth.is_delayed ? " (but a delayed auth change is scheduled)" : "");
       return 0;
     }
-  SHA_CTX ctx;
-  if (!SHA1_Init (&ctx))
+
+  u8 hash_from_packet[STRUCT_SIZE_OF (bfd_auth_sha1_t, hash)];
+  u8 calculated_hash[STRUCT_SIZE_OF (bfd_auth_sha1_t, hash)];
+  clib_memcpy (hash_from_packet, with_sha1->sha1_auth.hash,
+	       sizeof (with_sha1->sha1_auth.hash));
+  clib_memcpy (with_sha1->sha1_auth.hash, auth_key->key,
+	       sizeof (auth_key->key));
+  vnet_crypto_op_t op;
+  vnet_crypto_op_init (&op, VNET_CRYPTO_OP_SHA1_HASH);
+  op.src = (u8 *) with_sha1;
+  op.len = sizeof (*with_sha1);
+  op.digest = calculated_hash;
+  vnet_crypto_process_ops (vm, &op, 1);
+  if (0 ==
+      memcmp (calculated_hash, hash_from_packet, sizeof (calculated_hash)))
     {
-      BFD_ERR ("SHA1_Init failed");
-      return 0;
-    }
-  /* ignore last 20 bytes - use the actual key data instead pkt data */
-  if (!SHA1_Update (&ctx, with_sha1,
-		    sizeof (*with_sha1) - sizeof (with_sha1->sha1_auth.hash)))
-    {
-      BFD_ERR ("SHA1_Update failed");
-      return 0;
-    }
-  if (!SHA1_Update (&ctx, auth_key->key, sizeof (auth_key->key)))
-    {
-      BFD_ERR ("SHA1_Update failed");
-      return 0;
-    }
-  if (!SHA1_Final (result, &ctx))
-    {
-      BFD_ERR ("SHA1_Final failed");
-      return 0;
-    }
-  if (0 == memcmp (result, with_sha1->sha1_auth.hash, SHA_DIGEST_LENGTH))
-    {
+      clib_memcpy (with_sha1->sha1_auth.hash, hash_from_packet,
+		   sizeof (hash_from_packet));
       return 1;
     }
   BFD_ERR ("SHA1 hash: %U doesn't match the expected value: %U",
-	   format_hex_bytes, with_sha1->sha1_auth.hash, SHA_DIGEST_LENGTH,
-	   format_hex_bytes, result, SHA_DIGEST_LENGTH);
+	   format_hex_bytes, hash_from_packet, sizeof (hash_from_packet),
+	   format_hex_bytes, calculated_hash, sizeof (calculated_hash));
   return 0;
 }
 
@@ -1698,25 +1678,18 @@
     case BFD_AUTH_TYPE_keyed_sha1:
       /* fallthrough */
     case BFD_AUTH_TYPE_meticulous_keyed_sha1:
-#if WITH_LIBSSL > 0
       do
 	{
 	  const u32 seq_num = clib_net_to_host_u32 (((bfd_pkt_with_sha1_auth_t
 						      *) pkt)->
 						    sha1_auth.seq_num);
-	  return bfd_verify_pkt_auth_seq_num (vm, bs, seq_num,
-					      bfd_auth_type_is_meticulous
-					      (auth_key->auth_type))
-	    && bfd_verify_pkt_auth_key_sha1 (pkt, pkt_size, bs, bfd_key_id,
-					     auth_key);
+	  return bfd_verify_pkt_auth_seq_num (
+		   vm, bs, seq_num,
+		   bfd_auth_type_is_meticulous (auth_key->auth_type)) &&
+		 bfd_verify_pkt_auth_key_sha1 (vm, pkt, pkt_size, bs,
+					       bfd_key_id, auth_key);
 	}
       while (0);
-#else
-      vlib_log_err
-	(bm->log_class,
-	 "internal error, attempt to use SHA1 without SSL support");
-      return 0;
-#endif
     }
   return 0;
 }
@@ -2082,7 +2055,6 @@
 bfd_auth_deactivate (bfd_session_t * bs, u8 is_delayed)
 {
   bfd_main_t *bm = &bfd_main;
-#if WITH_LIBSSL > 0
   if (!is_delayed)
     {
       /* not delayed - deactivate the current key right now */
@@ -2113,11 +2085,6 @@
   vlib_log_info (bm->log_class, "session auth modified: %U",
 		 format_bfd_session_brief, bs);
   return 0;
-#else
-  vlib_log_err (bm->log_class,
-		"SSL missing, cannot deactivate BFD authentication");
-  return VNET_API_ERROR_BFD_NOTSUPP;
-#endif
 }
 
 vnet_api_error_t
@@ -2187,7 +2154,6 @@
 		  const u8 * key_data)
 {
   bfd_main_t *bm = &bfd_main;
-#if WITH_LIBSSL > 0
   bfd_auth_key_t *auth_key = NULL;
   if (!key_len || key_len > bfd_max_key_len_for_auth_type (auth_type))
     {
@@ -2231,17 +2197,11 @@
   clib_memset (auth_key->key, 0, sizeof (auth_key->key));
   clib_memcpy (auth_key->key, key_data, key_len);
   return 0;
-#else
-  vlib_log_err (bm->log_class,
-		"SSL missing, cannot manipulate authentication keys");
-  return VNET_API_ERROR_BFD_NOTSUPP;
-#endif
 }
 
 vnet_api_error_t
 bfd_auth_del_key (u32 conf_key_id)
 {
-#if WITH_LIBSSL > 0
   bfd_auth_key_t *auth_key = NULL;
   bfd_main_t *bm = &bfd_main;
   uword *key_idx_p = hash_get (bm->auth_key_by_conf_key_id, conf_key_id);
@@ -2271,11 +2231,6 @@
       return VNET_API_ERROR_BFD_ENOENT;
     }
   return 0;
-#else
-  vlib_log_err (bm->log_class,
-		"SSL missing, cannot manipulate authentication keys");
-  return VNET_API_ERROR_BFD_NOTSUPP;
-#endif
 }
 
 bfd_main_t bfd_main;
diff --git a/src/vnet/bfd/bfd_udp.c b/src/vnet/bfd/bfd_udp.c
index 1facb73..4ad5660 100644
--- a/src/vnet/bfd/bfd_udp.c
+++ b/src/vnet/bfd/bfd_udp.c
@@ -763,14 +763,8 @@
     }
   if (!rv && is_authenticated)
     {
-#if WITH_LIBSSL > 0
       rv = bfd_auth_activate (bs, conf_key_id, bfd_key_id,
 			      0 /* is not delayed */ );
-#else
-      vlib_log_err (bfd_udp_main.log_class,
-		    "SSL missing, cannot add authenticated BFD session");
-      rv = VNET_API_ERROR_BFD_NOTSUPP;
-#endif
       if (rv)
 	{
 	  bfd_udp_del_session_internal (vlib_get_main (), bs);
@@ -864,7 +858,6 @@
   bfd_lock (bm);
   vnet_api_error_t error;
 
-#if WITH_LIBSSL > 0
   bfd_session_t *bs = NULL;
   vnet_api_error_t rv =
     bfd_udp_find_session_by_api_input (sw_if_index, local_addr, peer_addr,
@@ -877,12 +870,6 @@
   error = bfd_auth_activate (bs, conf_key_id, key_id, is_delayed);
   bfd_unlock (bm);
   return error;
-#else
-  vlib_log_err (bfd_udp_main->log_class,
-		"SSL missing, cannot activate BFD authentication");
-  bfd_unlock (bm);
-  return VNET_API_ERROR_BFD_NOTSUPP;
-#endif
 }
 
 vnet_api_error_t
diff --git a/test/test_bfd.py b/test/test_bfd.py
index 01b468c..e6a710d 100644
--- a/test/test_bfd.py
+++ b/test/test_bfd.py
@@ -212,7 +212,7 @@
             session.add_vpp_config()
 
     def test_shared_sha1_key(self):
-        """ share single SHA1 key between multiple BFD sessions """
+        """ single SHA1 key shared by multiple BFD sessions """
         key = self.factory.create_random_key(self)
         key.add_vpp_config()
         sessions = [