From 723564aab645c6154dfaf8b90541fc23d51f66bd Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Fri, 11 Jul 2025 17:53:35 -0400 Subject: [PATCH] tls session: track internal tls objects in ckpair Type: improvement Change-Id: Ia38d355facd7af407a26c386327e8ea1a9aec116 Signed-off-by: Florin Coras --- src/plugins/tlsopenssl/tls_openssl.c | 141 ++++++++++++++++++---------------- src/plugins/tlsopenssl/tls_openssl.h | 2 - src/vnet/session/application_crypto.c | 17 ++++ src/vnet/session/application_crypto.h | 31 ++++++++ src/vnet/tls/tls_record.h | 4 +- 5 files changed, 124 insertions(+), 71 deletions(-) diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c index 020971d0b6d..7305fe6afda 100644 --- a/src/plugins/tlsopenssl/tls_openssl.c +++ b/src/plugins/tlsopenssl/tls_openssl.c @@ -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; } diff --git a/src/plugins/tlsopenssl/tls_openssl.h b/src/plugins/tlsopenssl/tls_openssl.h index d52524161ab..f18b579bdb1 100644 --- a/src/plugins/tlsopenssl/tls_openssl.h +++ b/src/plugins/tlsopenssl/tls_openssl.h @@ -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_ diff --git a/src/vnet/session/application_crypto.c b/src/vnet/session/application_crypto.c index a48ee07b4c3..b15799c89ec 100644 --- a/src/vnet/session/application_crypto.c +++ b/src/vnet/session/application_crypto.c @@ -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)) && diff --git a/src/vnet/session/application_crypto.h b/src/vnet/session/application_crypto.h index 20e385e4ae8..f0587eaf38a 100644 --- a/src/vnet/session/application_crypto.h +++ b/src/vnet/session/application_crypto.h @@ -7,12 +7,25 @@ #include +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 */ diff --git a/src/vnet/tls/tls_record.h b/src/vnet/tls/tls_record.h index 3f7723f06d5..8ad0cba6d87 100644 --- a/src/vnet/tls/tls_record.h +++ b/src/vnet/tls/tls_record.h @@ -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; -- 2.16.6