tls session: track internal tls objects in ckpair 37/43437/5
authorFlorin Coras <[email protected]>
Fri, 11 Jul 2025 21:53:35 +0000 (17:53 -0400)
committerDave Barach <[email protected]>
Thu, 17 Jul 2025 19:39:51 +0000 (19:39 +0000)
Type: improvement

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

index 020971d..7305fe6 100644 (file)
@@ -687,13 +687,58 @@ openssl_ctx_read (tls_ctx_t *ctx, session_t *ts)
     return openssl_ctx_read_dtls (ctx, ts);
 }
 
+static void
+openssl_cleanup_certkey_int_ctx (app_certkey_int_ctx_t *cki)
+{
+  X509_free (cki->cert);
+  EVP_PKEY_free (cki->key);
+}
+
+static app_certkey_int_ctx_t *
+openssl_init_certkey_init_ctx (app_cert_key_pair_t *ckpair,
+                              clib_thread_index_t thread_index)
+{
+  app_certkey_int_ctx_t *cki = 0;
+  EVP_PKEY *pkey;
+  X509 *cert;
+  BIO *bio;
+
+  cki = app_certkey_alloc_int_ctx (ckpair, thread_index);
+  bio = BIO_new (BIO_s_mem ());
+  BIO_write (bio, ckpair->cert, vec_len (ckpair->cert));
+  cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL);
+  if (!cert)
+    {
+      clib_warning ("unable to parse certificate");
+      BIO_free (bio);
+      return 0;
+    }
+  cki->cert = cert;
+  BIO_free (bio);
+
+  bio = BIO_new (BIO_s_mem ());
+  BIO_write (bio, ckpair->key, vec_len (ckpair->key));
+  pkey = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL);
+  if (!pkey)
+    {
+      clib_warning ("unable to parse pkey");
+      BIO_free (bio);
+      return 0;
+    }
+  cki->key = pkey;
+  BIO_free (bio);
+
+  cki->cleanup_cb = openssl_cleanup_certkey_int_ctx;
+
+  return cki;
+}
+
 static int
-openssl_set_ckpair (SSL *ssl, u32 ckpair_index)
+openssl_set_ckpair (SSL *ssl, u32 ckpair_index,
+                   clib_thread_index_t thread_index)
 {
   app_cert_key_pair_t *ckpair;
-  BIO *cert_bio;
-  EVP_PKEY *pkey;
-  X509 *srvcert;
+  app_certkey_int_ctx_t *cki;
 
   /* Configure a ckpair index only if non-default/test provided */
   if (ckpair_index == 0)
@@ -708,32 +753,21 @@ openssl_set_ckpair (SSL *ssl, u32 ckpair_index)
       TLS_DBG (1, "tls cert and/or key not configured");
       return -1;
     }
-  /*
-   * Set the key and cert
-   */
-  cert_bio = BIO_new (BIO_s_mem ());
-  BIO_write (cert_bio, ckpair->cert, vec_len (ckpair->cert));
-  srvcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
-  if (!srvcert)
-    {
-      clib_warning ("unable to parse certificate");
-      return -1;
-    }
-  SSL_use_certificate (ssl, srvcert);
-  BIO_free (cert_bio);
-  X509_free (srvcert);
 
-  cert_bio = BIO_new (BIO_s_mem ());
-  BIO_write (cert_bio, ckpair->key, vec_len (ckpair->key));
-  pkey = PEM_read_bio_PrivateKey (cert_bio, NULL, NULL, NULL);
-  if (!pkey)
+  cki = app_certkey_get_int_ctx (ckpair, thread_index);
+  if (!cki || !cki->cert)
     {
-      clib_warning ("unable to parse pkey");
-      return -1;
+      cki = openssl_init_certkey_init_ctx (ckpair, thread_index);
+      if (!cki)
+       {
+         clib_warning ("unable to initialize certificate/key pair");
+         return -1;
+       }
     }
-  SSL_use_PrivateKey (ssl, pkey);
-  BIO_free (cert_bio);
-  EVP_PKEY_free (pkey);
+
+  SSL_use_certificate (ssl, cki->cert);
+  SSL_use_PrivateKey (ssl, cki->key);
+
   TLS_DBG (1, "TLS client using ckpair index: %d", ckpair_index);
   return 0;
 }
@@ -858,7 +892,7 @@ openssl_ctx_init_client (tls_ctx_t * ctx)
       TLS_DBG (1, "ERROR:verify init failed:%d", rv);
       return -1;
     }
-  if (openssl_set_ckpair (oc->ssl, ctx->ckpair_index))
+  if (openssl_set_ckpair (oc->ssl, ctx->ckpair_index, ctx->c_thread_index))
     {
       TLS_DBG (1, "Couldn't set client certificate-key pair");
     }
@@ -922,12 +956,10 @@ openssl_start_listen (tls_ctx_t * lctx)
   const SSL_METHOD *method;
   SSL_CTX *ssl_ctx;
   int rv;
-  BIO *cert_bio;
-  X509 *srvcert;
-  EVP_PKEY *pkey;
   u32 olc_index;
   openssl_listen_ctx_t *olc;
   app_cert_key_pair_t *ckpair;
+  app_certkey_int_ctx_t *cki;
 
   long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
   openssl_main_t *om = &openssl_main;
@@ -1014,52 +1046,31 @@ openssl_start_listen (tls_ctx_t * lctx)
   /*
    * Set the key and cert
    */
-  cert_bio = BIO_new (BIO_s_mem ());
-  if (!cert_bio)
+  cki = app_certkey_get_int_ctx (ckpair, lctx->c_thread_index);
+  if (!cki || !cki->cert)
     {
-      clib_warning ("unable to allocate memory");
-      return -1;
-    }
-  BIO_write (cert_bio, ckpair->cert, vec_len (ckpair->cert));
-  srvcert = PEM_read_bio_X509 (cert_bio, NULL, NULL, NULL);
-  if (!srvcert)
-    {
-      clib_warning ("unable to parse certificate");
-      goto err;
+      cki = openssl_init_certkey_init_ctx (ckpair, lctx->c_thread_index);
+      if (!cki)
+       {
+         clib_warning ("unable to initialize certificate/key pair");
+         return -1;
+       }
     }
-  rv = SSL_CTX_use_certificate (ssl_ctx, srvcert);
+
+  rv = SSL_CTX_use_certificate (ssl_ctx, cki->cert);
   if (rv != 1)
     {
       clib_warning ("unable to use SSL certificate");
       goto err;
     }
 
-  BIO_free (cert_bio);
-  X509_free (srvcert);
-
-  cert_bio = BIO_new (BIO_s_mem ());
-  if (!cert_bio)
-    {
-      clib_warning ("unable to allocate memory");
-      return -1;
-    }
-  BIO_write (cert_bio, ckpair->key, vec_len (ckpair->key));
-  pkey = PEM_read_bio_PrivateKey (cert_bio, NULL, NULL, NULL);
-  if (!pkey)
-    {
-      clib_warning ("unable to parse pkey");
-      goto err;
-    }
-  rv = SSL_CTX_use_PrivateKey (ssl_ctx, pkey);
+  rv = SSL_CTX_use_PrivateKey (ssl_ctx, cki->key);
   if (rv != 1)
     {
       clib_warning ("unable to use SSL PrivateKey");
       goto err;
     }
 
-  BIO_free (cert_bio);
-  EVP_PKEY_free (pkey);
-
   if (lctx->alpn_list)
     SSL_CTX_set_alpn_select_cb (ssl_ctx, openssl_alpn_select_cb,
                                (void *) lctx->alpn_list);
@@ -1067,8 +1078,6 @@ openssl_start_listen (tls_ctx_t * lctx)
   olc_index = openssl_listen_ctx_alloc ();
   olc = openssl_lctx_get (olc_index);
   olc->ssl_ctx = ssl_ctx;
-  olc->srvcert = srvcert;
-  olc->pkey = pkey;
 
   /* store SSL_CTX into TLS level structure */
   lctx->tls_ssl_ctx = olc_index;
@@ -1076,8 +1085,6 @@ openssl_start_listen (tls_ctx_t * lctx)
   return 0;
 
 err:
-  if (cert_bio)
-    BIO_free (cert_bio);
   return -1;
 }
 
index d525241..f18b579 100644 (file)
@@ -66,8 +66,6 @@ typedef struct tls_listen_ctx_opensl_
   u32 openssl_lctx_index;
   SSL_CTX *ssl_ctx;
   SSL *ssl;
-  X509 *srvcert;
-  EVP_PKEY *pkey;
 } openssl_listen_ctx_t;
 
 typedef struct openssl_main_
index a48ee07..b15799c 100644 (file)
@@ -68,6 +68,21 @@ vnet_app_add_cert_key_interest (u32 index, u32 app_index)
   return 0;
 }
 
+static void
+app_certkey_free_int_ctx (app_cert_key_pair_t *ck)
+{
+  app_certkey_int_ctx_t *cki;
+
+  vec_foreach (cki, ck->cki)
+    {
+      if (cki->cleanup_cb)
+       (cki->cleanup_cb) (cki);
+      cki->cert = 0;
+      cki->key = 0;
+    }
+  vec_free (ck->cki);
+}
+
 int
 vnet_app_del_cert_key_pair (u32 index)
 {
@@ -78,6 +93,8 @@ vnet_app_del_cert_key_pair (u32 index)
   if (!(ckpair = app_cert_key_pair_get_if_valid (index)))
     return SESSION_E_INVALID;
 
+  app_certkey_free_int_ctx (ckpair);
+
   vec_foreach (app_index, ckpair->app_interests)
     {
       if ((app = application_get_if_valid (*app_index)) &&
index 20e385e..f0587ea 100644 (file)
@@ -7,12 +7,25 @@
 
 #include <vnet/tls/tls_test.h>
 
+struct app_certkey_int_;
+
+typedef void (*app_certkey_cleanup_it_ctx_fn) (struct app_certkey_int_ *cki);
+
+typedef struct app_certkey_int_
+{
+  void *cert;      /**< cert of cert chain, possible format X509 */
+  void *key;       /**< key, possible format EVP_PKEY */
+  u32 ckpair_index; /**< parent certkey */
+  app_certkey_cleanup_it_ctx_fn cleanup_cb; /**< cleanup callback */
+} app_certkey_int_ctx_t;
+
 typedef struct certificate_
 {
   u32 *app_interests; /* vec of application index asking for deletion cb */
   u32 cert_key_index; /* index in cert & key pool */
   u8 *key;
   u8 *cert;
+  app_certkey_int_ctx_t *cki; /**< per-thread internal cert/key */
 } app_cert_key_pair_t;
 
 typedef enum crypto_engine_type_
@@ -55,6 +68,24 @@ int vnet_app_add_cert_key_pair (vnet_app_add_cert_key_pair_args_t *a);
 int vnet_app_add_cert_key_interest (u32 index, u32 app_index);
 int vnet_app_del_cert_key_pair (u32 index);
 
+static inline app_certkey_int_ctx_t *
+app_certkey_get_int_ctx (app_cert_key_pair_t *ck,
+                        clib_thread_index_t thread_index)
+{
+  if (vec_len (ck->cki) <= thread_index)
+    return 0;
+  return vec_elt_at_index (ck->cki, thread_index);
+}
+
+static inline app_certkey_int_ctx_t *
+app_certkey_alloc_int_ctx (app_cert_key_pair_t *ck,
+                          clib_thread_index_t thread_index)
+{
+  if (!ck->cki)
+    vec_validate (ck->cki, vlib_num_workers () + 1);
+  return vec_elt_at_index (ck->cki, thread_index);
+}
+
 /*
  * Crypto engine management
  */
index 3f7723f..8ad0cba 100644 (file)
@@ -100,7 +100,7 @@ tls_handshake_message_len (tls_handshake_msg_t *msg)
 /**
  * https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml
  */
-#define foreach_tls_hanshake_extensions                                       \
+#define foreach_tls_handshake_extensions                                      \
   _ (SERVER_NAME, 0)                                                          \
   _ (MAX_FRAGMENT_LENGTH, 1)                                                  \
   _ (STATUS_REQUEST, 5)                                                       \
@@ -133,7 +133,7 @@ tls_handshake_message_len (tls_handshake_msg_t *msg)
 typedef enum tls_handshake_extension_type_
 {
 #define _(sym, val) TLS_EXT_##sym = val,
-  foreach_tls_hanshake_extensions
+  foreach_tls_handshake_extensions
 #undef _
 } tls_handshake_ext_type_t;