tls: cert validation config 44/43644/5
authorFlorin Coras <[email protected]>
Thu, 28 Aug 2025 16:42:43 +0000 (12:42 -0400)
committerDave Barach <[email protected]>
Thu, 4 Sep 2025 23:53:55 +0000 (23:53 +0000)
Type: improvement

Change-Id: I7d626ed57bbdcb7810c99a1fe0f617fde0ac014f
Signed-off-by: Florin Coras <[email protected]>
src/plugins/tlsopenssl/tls_openssl.c
src/plugins/tlsopenssl/tls_openssl.h
src/vnet/session/transport_types.h
src/vnet/tls/tls.h

index a791158..6ccb17f 100644 (file)
@@ -773,40 +773,8 @@ openssl_set_ckpair (SSL *ssl, u32 ckpair_index,
 }
 
 static int
-openssl_client_init_verify (SSL *ssl, const char *srv_hostname,
-                           int set_hostname_verification,
-                           int set_hostname_strict_check)
-{
-  if (set_hostname_verification)
-    {
-      X509_VERIFY_PARAM *param = SSL_get0_param (ssl);
-      if (!param)
-       {
-         TLS_DBG (1, "Couldn't fetch SSL param");
-         return -1;
-       }
-
-      if (set_hostname_strict_check)
-       X509_VERIFY_PARAM_set_hostflags (param,
-                                        X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
-
-      if (!X509_VERIFY_PARAM_set1_host (param, srv_hostname, 0))
-       {
-         TLS_DBG (1, "Couldn't set hostname for verification");
-         return -1;
-       }
-      SSL_set_verify (ssl, SSL_VERIFY_PEER, 0);
-    }
-  if (!SSL_set_tlsext_host_name (ssl, srv_hostname))
-    {
-      TLS_DBG (1, "Couldn't set hostname");
-      return -1;
-    }
-  return 0;
-}
-
-static int
-openssl_init_client_ctx (transport_proto_t proto)
+openssl_init_client_ctx (clib_thread_index_t thread_index,
+                        transport_proto_t proto)
 {
   long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
   openssl_main_t *om = &openssl_main;
@@ -857,27 +825,75 @@ openssl_init_client_ctx (transport_proto_t proto)
     }
 
   if (proto == TRANSPORT_PROTO_TLS)
-    om->default_client_ssl_ctx = client_ssl_ctx;
+    om->default_client_ssl_ctx[thread_index] = client_ssl_ctx;
   else
-    om->default_dtls_client_ssl_ctx = client_ssl_ctx;
+    om->default_dtls_client_ssl_ctx[thread_index] = client_ssl_ctx;
 
   return 0;
 }
 
 static inline SSL_CTX *
-openssl_get_client_ssl_ctx (transport_proto_t proto)
+openssl_get_client_ssl_ctx (clib_thread_index_t thread_index,
+                           transport_proto_t proto)
 {
   openssl_main_t *om = &openssl_main;
 
   /* One time init of the default client ssl ctxs */
-  if (PREDICT_FALSE (!om->default_client_ssl_ctx))
+  if (PREDICT_FALSE (!om->default_client_ssl_ctx[thread_index]))
     {
-      openssl_init_client_ctx (TRANSPORT_PROTO_TLS);
-      openssl_init_client_ctx (TRANSPORT_PROTO_DTLS);
+      openssl_init_client_ctx (thread_index, TRANSPORT_PROTO_TLS);
+      openssl_init_client_ctx (thread_index, TRANSPORT_PROTO_DTLS);
+    }
+
+  return proto == TRANSPORT_PROTO_TLS ?
+          om->default_client_ssl_ctx[thread_index] :
+          om->default_dtls_client_ssl_ctx[thread_index];
+}
+
+static int
+openssl_make_verify_flags (tls_verify_cfg_t verify_cfg)
+{
+  int flags = SSL_VERIFY_PEER;
+
+  if (verify_cfg & TLS_VERIFY_F_PEER)
+    flags |= SSL_VERIFY_PEER;
+  if (verify_cfg & TLS_VERIFY_F_PEER_CERT)
+    flags |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+
+  return flags;
+}
+
+static int
+openssl_client_set_verify (tls_ctx_t *ctx)
+{
+  openssl_ctx_t *oc = (openssl_ctx_t *) ctx;
+
+  if (ctx->verify_cfg & (TLS_VERIFY_F_HOSTNAME | TLS_VERIFY_F_HOSTNAME_STRICT))
+    {
+      X509_VERIFY_PARAM *param = SSL_get0_param (oc->ssl);
+      if (!param)
+       {
+         TLS_DBG (1, "Couldn't fetch SSL param");
+         return -1;
+       }
+
+      if (ctx->verify_cfg & TLS_VERIFY_F_HOSTNAME_STRICT)
+       X509_VERIFY_PARAM_set_hostflags (param,
+                                        X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
+
+      if (ctx->verify_cfg & TLS_VERIFY_F_HOSTNAME)
+       {
+         if (!X509_VERIFY_PARAM_set1_host (
+               param, (const char *) ctx->srv_hostname, 0))
+           {
+             TLS_DBG (1, "Couldn't set hostname for verification");
+             return -1;
+           }
+       }
     }
+  SSL_set_verify (oc->ssl, openssl_make_verify_flags (ctx->verify_cfg), 0);
 
-  return proto == TRANSPORT_PROTO_TLS ? om->default_client_ssl_ctx :
-                                       om->default_dtls_client_ssl_ctx;
+  return 0;
 }
 
 static int
@@ -887,7 +903,8 @@ openssl_ctx_init_client (tls_ctx_t *ctx)
   SSL_CTX *client_ssl_ctx;
   int rv, err;
 
-  client_ssl_ctx = openssl_get_client_ssl_ctx (ctx->tls_type);
+  client_ssl_ctx =
+    openssl_get_client_ssl_ctx (ctx->c_thread_index, ctx->tls_type);
   if (PREDICT_FALSE (!client_ssl_ctx))
     return -1;
 
@@ -910,6 +927,26 @@ openssl_ctx_init_client (tls_ctx_t *ctx)
        }
     }
 
+  if (!SSL_set_tlsext_host_name (oc->ssl, (const char *) ctx->srv_hostname))
+    {
+      TLS_DBG (1, "Couldn't set hostname");
+      return -1;
+    }
+
+  if (ctx->verify_cfg)
+    {
+      if (openssl_client_set_verify (ctx))
+       {
+         TLS_DBG (1, "ERROR: setting verify flags failed");
+         return -1;
+       }
+    }
+
+  if (openssl_set_ckpair (oc->ssl, ctx->ckpair_index, ctx->c_thread_index))
+    {
+      TLS_DBG (1, "Couldn't set client certificate-key pair");
+    }
+
   if (ctx->tls_type == TRANSPORT_PROTO_TLS)
     {
       oc->rbio = BIO_new_tls (ctx->tls_session_handle);
@@ -924,19 +961,6 @@ openssl_ctx_init_client (tls_ctx_t *ctx)
   SSL_set_bio (oc->ssl, oc->wbio, oc->rbio);
   SSL_set_connect_state (oc->ssl);
 
-  /* Hostname validation and strict check by name are disabled by default */
-  rv = openssl_client_init_verify (oc->ssl, (const char *) ctx->srv_hostname,
-                                  0, 0);
-  if (rv)
-    {
-      TLS_DBG (1, "ERROR:verify init failed:%d", rv);
-      return -1;
-    }
-  if (openssl_set_ckpair (oc->ssl, ctx->ckpair_index, ctx->c_thread_index))
-    {
-      TLS_DBG (1, "Couldn't set client certificate-key pair");
-    }
-
   /*
    * 2. Do the first steps in the handshake.
    */
@@ -1491,6 +1515,9 @@ tls_openssl_init (vlib_main_t * vm)
   vec_validate (om->ctx_pool, num_threads - 1);
   vec_validate (om->rx_bufs, num_threads - 1);
   vec_validate (om->tx_bufs, num_threads - 1);
+  vec_validate (om->default_client_ssl_ctx, num_threads - 1);
+  vec_validate (om->default_dtls_client_ssl_ctx, num_threads - 1);
+
   for (i = 0; i < num_threads; i++)
     {
       vec_validate (om->rx_bufs[i], DTLSO_MAX_DGRAM);
index ae2197c..3a97362 100644 (file)
@@ -72,8 +72,8 @@ typedef struct openssl_main_
 {
   openssl_ctx_t ***ctx_pool;
   openssl_listen_ctx_t *lctx_pool;
-  SSL_CTX *default_client_ssl_ctx;
-  SSL_CTX *default_dtls_client_ssl_ctx;
+  SSL_CTX **default_client_ssl_ctx;
+  SSL_CTX **default_dtls_client_ssl_ctx;
 
   u8 **rx_bufs;
   u8 **tx_bufs;
index 5088303..d45c376 100644 (file)
@@ -288,12 +288,34 @@ typedef enum transport_endpt_ext_cfg_type_
   TRANSPORT_ENDPT_EXT_CFG_HTTP,
 } transport_endpt_ext_cfg_type_t;
 
+#define foreach_tls_verify_cfg                                                \
+  _ (NONE, "none")                                                            \
+  _ (PEER, "peer")                                                            \
+  _ (PEER_CERT, "peer-cert")                                                  \
+  _ (HOSTNAME, "hostname")                                                    \
+  _ (HOSTNAME_STRICT, "hostname-strict")
+
+enum tls_verify_cfg_bit_
+{
+#define _(sym, name) TLS_VERIFY_CFG_BIT_##sym,
+  foreach_tls_verify_cfg
+#undef _
+};
+
+typedef enum tls_verify_cfg_
+{
+#define _(sym, name) TLS_VERIFY_F_##sym = 1 << TLS_VERIFY_CFG_BIT_##sym,
+  foreach_tls_verify_cfg
+#undef _
+} tls_verify_cfg_t;
+
 typedef struct transport_endpt_crypto_cfg_
 {
   u32 ckpair_index;  /**< index of ck pair in application crypto layer */
   u8 alpn_protos[4]; /**< ordered by preference for server */
   u8 crypto_engine;  /**< crypto engine requested */
-  u8 hostname[256];  /**< full domain len is 255 as per rfc 3986 */
+  tls_verify_cfg_t verify_cfg; /**< cert verification mode */
+  u8 hostname[256];           /**< full domain len is 255 as per rfc 3986 */
 } transport_endpt_crypto_cfg_t;
 
 typedef struct transport_endpt_ext_cfg_
index 3ee0066..768e87b 100644 (file)
@@ -126,6 +126,7 @@ typedef struct tls_ctx_
   transport_proto_t tls_type;
   u8 *alpn_list;
   tls_alpn_proto_t alpn_selected;
+  tls_verify_cfg_t verify_cfg;
 } tls_ctx_t;
 
 typedef struct tls_main_