This is an automated email from the ASF dual-hosted git repository.

bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 9ddf262451 TLS curve/group name logging for Ticket Resumption (#12393)
9ddf262451 is described below

commit 9ddf2624516541ca08c482a849e21abbf5a44fe6
Author: Brian Neradt <[email protected]>
AuthorDate: Mon Sep 22 08:53:07 2025 -0500

    TLS curve/group name logging for Ticket Resumption (#12393)
    
    This applies to the cqssu (curve) and cqssg (group name) TLS log fields.
    
    This does two things:
    
    * Updates server session caching logic to provide the TLS group name on
      resumption.
    * Updates the logging of the curve and group name for ticket resumption
      logic so that the TLS curve and group names are properly retrieved
      from the SSL object. For ticket resumption, there is no curve/group
      name stored to retrieve. It is properly retrieved from the SSL object.
    
    Before this change: (1) the SSL group was always retrieved from the SSL
    object when it should have been retrieved from the server session cache
    ex_data for session cache resumption and (2) the curve value for cqssu
    was alway "-" for TLS ticket resumption because there was no cached
    value to retrieve like there is with server session caching.
    
    Fixes: #12398
---
 CMakeLists.txt                                   |  2 +
 include/iocore/net/TLSBasicSupport.h             | 20 +++---
 include/iocore/net/TLSSessionResumptionSupport.h | 87 +++++++++++++++++++++---
 include/proxy/http/HttpUserAgent.h               | 10 +--
 include/tscore/ink_config.h.cmake.in             |  2 +
 src/api/InkAPI.cc                                |  2 +-
 src/iocore/net/P_QUICNetVConnection.h            |  7 +-
 src/iocore/net/P_SSLNetVConnection.h             |  5 +-
 src/iocore/net/P_SSLUtils.h                      |  5 +-
 src/iocore/net/QUICNetVConnection.cc             | 18 ++++-
 src/iocore/net/SSLNetVConnection.cc              | 18 ++++-
 src/iocore/net/SSLSessionCache.cc                | 18 ++++-
 src/iocore/net/SSLSessionCache.h                 | 20 +++++-
 src/iocore/net/SSLUtils.cc                       | 26 +++++++
 src/iocore/net/TLSBasicSupport.cc                | 17 ++---
 src/iocore/net/TLSSessionResumptionSupport.cc    | 65 +++++++++++++-----
 src/proxy/http/HttpSM.cc                         |  2 +-
 17 files changed, 255 insertions(+), 69 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 010d74fc70..65c6ca278b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -476,8 +476,10 @@ check_symbol_exists(SSL_set1_verify_cert_store 
"openssl/ssl.h" TS_HAS_VERIFY_CER
 check_symbol_exists(SSL_get_shared_curve "openssl/ssl.h" 
HAVE_SSL_GET_SHARED_CURVE)
 check_symbol_exists(SSL_get_curve_name "openssl/ssl.h" HAVE_SSL_GET_CURVE_NAME)
 check_symbol_exists(SSL_get0_group_name "openssl/ssl.h" 
HAVE_SSL_GET0_GROUP_NAME)
+check_symbol_exists(SSL_get_negotiated_group "openssl/ssl.h" 
HAVE_SSL_GET_NEGOTIATED_GROUP)
 check_symbol_exists(SSL_get_group_id "openssl/ssl.h" HAVE_SSL_GET_GROUP_ID)
 check_symbol_exists(SSL_get_group_name "openssl/ssl.h" HAVE_SSL_GET_GROUP_NAME)
+check_symbol_exists(SSL_group_to_name "openssl/ssl.h" HAVE_SSL_GROUP_TO_NAME)
 check_symbol_exists(SSL_set_max_early_data "openssl/ssl.h" 
HAVE_SSL_SET_MAX_EARLY_DATA)
 check_symbol_exists(SSL_read_early_data "openssl/ssl.h" 
HAVE_SSL_READ_EARLY_DATA)
 check_symbol_exists(SSL_write_early_data "openssl/ssl.h" 
HAVE_SSL_WRITE_EARLY_DATA)
diff --git a/include/iocore/net/TLSBasicSupport.h 
b/include/iocore/net/TLSBasicSupport.h
index a0b17bae3d..015633607b 100644
--- a/include/iocore/net/TLSBasicSupport.h
+++ b/include/iocore/net/TLSBasicSupport.h
@@ -25,6 +25,7 @@
 #pragma once
 
 #include <string>
+#include <string_view>
 
 #include <openssl/ssl.h>
 
@@ -43,13 +44,13 @@ public:
   static void             bind(SSL *ssl, TLSBasicSupport *srs);
   static void             unbind(SSL *ssl);
 
-  TLSHandle   get_tls_handle() const;
-  const char *get_tls_protocol_name() const;
-  const char *get_tls_cipher_suite() const;
-  const char *get_tls_curve() const;
-  const char *get_tls_group() const;
-  ink_hrtime  get_tls_handshake_begin_time() const;
-  ink_hrtime  get_tls_handshake_end_time() const;
+  TLSHandle        get_tls_handle() const;
+  const char      *get_tls_protocol_name() const;
+  const char      *get_tls_cipher_suite() const;
+  const char      *get_tls_curve() const;
+  std::string_view get_tls_group() const;
+  ink_hrtime       get_tls_handshake_begin_time() const;
+  ink_hrtime       get_tls_handshake_end_time() const;
   /**
    * Returns a certificate that need to be verified.
    *
@@ -80,8 +81,9 @@ public:
 protected:
   void clear();
 
-  virtual SSL         *_get_ssl_object() const = 0;
-  virtual ssl_curve_id _get_tls_curve() const  = 0;
+  virtual SSL             *_get_ssl_object() const = 0;
+  virtual ssl_curve_id     _get_tls_curve() const  = 0;
+  virtual std::string_view _get_tls_group() const  = 0;
 
   void _record_tls_handshake_begin_time();
   void _record_tls_handshake_end_time();
diff --git a/include/iocore/net/TLSSessionResumptionSupport.h 
b/include/iocore/net/TLSSessionResumptionSupport.h
index 6955528096..80c25d96d6 100644
--- a/include/iocore/net/TLSSessionResumptionSupport.h
+++ b/include/iocore/net/TLSSessionResumptionSupport.h
@@ -1,7 +1,8 @@
 /** @file
 
   TLSSessionResumptionSupport implements common methods and members to
-  support TLS Ssssion Resumption
+  support TLS Ssssion Resumption, either via server session caching or
+  TLS session tickets.
 
   @section license License
 
@@ -25,6 +26,7 @@
 #pragma once
 
 #include <openssl/ssl.h>
+#include <string_view>
 
 #include "tscore/ink_inet.h"
 #include "iocore/net/SSLTypes.h"
@@ -36,11 +38,34 @@ class TLSSessionResumptionSupport
 public:
   virtual ~TLSSessionResumptionSupport() = default;
 
+  // 
---------------------------------------------------------------------------
+  // Binding of the TLSSessionResumptionSupport object to the SSL object
+  // 
---------------------------------------------------------------------------
+
   static void                         initialize();
   static TLSSessionResumptionSupport *getInstance(SSL *ssl);
   static void                         bind(SSL *ssl, 
TLSSessionResumptionSupport *srs);
   static void                         unbind(SSL *ssl);
 
+  // 
---------------------------------------------------------------------------
+  // TLS Session Resumption Support Via Session Tickets
+  // 
---------------------------------------------------------------------------
+
+  /** Handles TLS session ticket processing for session resumption.
+   *
+   * This function is called by OpenSSL to either encrypt (create) or decrypt 
(resume) a session ticket,
+   * depending on the value of the @p enc parameter. It selects the 
appropriate ticket key block based on
+   * the local endpoint and certificate context, and then either generates a 
new session ticket or attempts
+   * to decrypt and validate an existing one.
+   *
+   * @param[in]  ssl         The SSL connection object.
+   * @param[out] keyname     Buffer for the session ticket key name.
+   * @param[out] iv          Buffer for the initialization vector.
+   * @param[in,out] cipher_ctx  Cipher context for encryption/decryption.
+   * @param[in,out] hctx        HMAC or MAC context for integrity protection.
+   * @param[in]  enc         Indicates operation: 1 for encrypt (create 
ticket), 0 for decrypt (resume session).
+   * @return            1 on success, 0 if key not found, negative value on 
error, or 2 if ticket should be renewed.
+   */
 #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
   int processSessionTicket(SSL *ssl, unsigned char *keyname, unsigned char 
*iv, EVP_CIPHER_CTX *cipher_ctx, EVP_MAC_CTX *hctx,
                            int enc);
@@ -48,24 +73,63 @@ public:
   int processSessionTicket(SSL *ssl, unsigned char *keyname, unsigned char 
*iv, EVP_CIPHER_CTX *cipher_ctx, HMAC_CTX *hctx,
                            int enc);
 #endif
-  bool         getSSLSessionCacheHit() const;
-  bool         getSSLOriginSessionCacheHit() const;
-  ssl_curve_id getSSLCurveNID() const;
 
-  SSL_SESSION                 *getSession(SSL *ssl, const unsigned char *id, 
int len, int *copy);
+  // 
---------------------------------------------------------------------------
+  // TLS Session Resumption Support Via Server Session Caching
+  // 
---------------------------------------------------------------------------
+
+  /** Retrieves a cached SSL session from the session cache.
+   *
+   * This function is used to retrieve a cached SSL session from the session 
cache.
+   *
+   * @param[in]  ssl         The SSL connection object.
+   * @param[in]  id          The session ID to lookup.
+   * @param[in]  len         The length of the session ID.
+   * @param[out] copy        Pointer to an integer indicating if the session 
ID should be copied.
+   * @return                A pointer to the cached SSL session, or nullptr if 
not found.
+   */
+  SSL_SESSION *getSession(SSL *ssl, const unsigned char *id, int len, int 
*copy);
+
+  /**
+   * @brief Retrieves a cached SSL session from the origin session cache.
+   *
+   * This function is used to retrieve a cached SSL session from the origin 
session cache.
+   *
+   * @param[in]  lookup_key  The key to lookup the session in the cache.
+   * @return                A pointer to the cached SSL session, or nullptr if 
not found.
+   */
   std::shared_ptr<SSL_SESSION> getOriginSession(const std::string &lookup_key);
 
+  // 
---------------------------------------------------------------------------
+  // Getters used for both ticket and session caching
+  // 
---------------------------------------------------------------------------
+
+  bool             getIsResumedSSLSession() const;
+  bool             getIsResumedOriginSSLSession() const;
+  bool             getIsResumedFromSessionCache() const;
+  bool             getIsResumedFromSessionTicket() const;
+  ssl_curve_id     getSSLCurveNID() const;
+  std::string_view getSSLGroupName() const;
+
 protected:
   void                      clear();
   virtual const IpEndpoint &_getLocalEndpoint() = 0;
 
 private:
+  enum class ResumptionType {
+    NOT_RESUMED,
+    RESUMED_FROM_SESSION_CACHE,
+    RESUMED_FROM_SESSION_TICKET,
+  };
+
   static int _ex_data_index;
 
-  bool _sslSessionCacheHit       = false;
-  bool _sslOriginSessionCacheHit = false;
-  int  _sslCurveNID              = NID_undef;
+  ResumptionType _resumptionType         = ResumptionType::NOT_RESUMED;
+  bool           _isResumedOriginSession = false;
+  int            _sslCurveNID            = NID_undef;
+  std::string    _sslGroupName;
 
+private:
 #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
   int _setSessionInformation(ssl_ticket_key_block *keyblock, unsigned char 
*keyname, unsigned char *iv, EVP_CIPHER_CTX *cipher_ctx,
                              EVP_MAC_CTX *hctx);
@@ -78,7 +142,8 @@ private:
                              EVP_CIPHER_CTX *cipher_ctx, HMAC_CTX *hctx);
 #endif
 
-  void _setSSLSessionCacheHit(bool state);
-  void _setSSLOriginSessionCacheHit(bool state);
-  void _setSSLCurveNID(ssl_curve_id curve_nid);
+  constexpr static bool IS_RESUMED_ORIGIN_SESSION = true;
+  void                  _setResumptionType(ResumptionType type, bool isOrigin);
+  void                  _setSSLCurveNID(ssl_curve_id curve_nid);
+  void                  _setSSLGroupName(std::string_view group_name);
 };
diff --git a/include/proxy/http/HttpUserAgent.h 
b/include/proxy/http/HttpUserAgent.h
index a1e22b9515..1dacea0587 100644
--- a/include/proxy/http/HttpUserAgent.h
+++ b/include/proxy/http/HttpUserAgent.h
@@ -33,6 +33,8 @@
 #include "iocore/net/TLSBasicSupport.h"
 #include "iocore/net/TLSSessionResumptionSupport.h"
 
+#include <string>
+
 struct ClientTransactionInfo {
   int id{-1};
   int priority_weight{-1};
@@ -48,7 +50,7 @@ struct ClientConnectionInfo {
   char const *sec_protocol{"-"};
   char const *cipher_suite{"-"};
   char const *curve{"-"};
-  char const *security_group{"-"};
+  std::string security_group{"-"};
 
   int alpn_id{SessionProtocolNameRegistry::INVALID};
 };
@@ -169,7 +171,7 @@ HttpUserAgent::set_txn(ProxyTransaction *txn, 
TransactionMilestones &milestones)
       m_conn_info.curve = "-";
     }
 
-    if (auto group{tbs->get_tls_group()}; group) {
+    if (auto group{tbs->get_tls_group()}; !group.empty()) {
       m_conn_info.security_group = group;
     } else {
       m_conn_info.security_group = "-";
@@ -187,7 +189,7 @@ HttpUserAgent::set_txn(ProxyTransaction *txn, 
TransactionMilestones &milestones)
   }
 
   if (auto tsrs = netvc->get_service<TLSSessionResumptionSupport>()) {
-    m_conn_info.ssl_reused = tsrs->getSSLSessionCacheHit();
+    m_conn_info.ssl_reused = tsrs->getIsResumedSSLSession();
   }
 
   if (auto protocol_str{txn->get_protocol_string()}; protocol_str) {
@@ -266,7 +268,7 @@ HttpUserAgent::get_client_curve() const
 inline char const *
 HttpUserAgent::get_client_security_group() const
 {
-  return m_conn_info.security_group;
+  return m_conn_info.security_group.c_str();
 }
 
 inline int
diff --git a/include/tscore/ink_config.h.cmake.in 
b/include/tscore/ink_config.h.cmake.in
index fcbd98a582..02cc203422 100644
--- a/include/tscore/ink_config.h.cmake.in
+++ b/include/tscore/ink_config.h.cmake.in
@@ -176,8 +176,10 @@ const int DEFAULT_STACKSIZE = @DEFAULT_STACK_SIZE@;
 #cmakedefine01 HAVE_SSL_GET_SHARED_CURVE
 #cmakedefine01 HAVE_SSL_GET_CURVE_NAME
 #cmakedefine01 HAVE_SSL_GET0_GROUP_NAME
+#cmakedefine01 HAVE_SSL_GET_NEGOTIATED_GROUP
 #cmakedefine01 HAVE_SSL_GET_GROUP_ID
 #cmakedefine01 HAVE_SSL_GET_GROUP_NAME
+#cmakedefine01 HAVE_SSL_GROUP_TO_NAME
 #cmakedefine01 HAVE_SSL_ERROR_DESCRIPTION
 #cmakedefine01 HAVE_OSSL_PARAM_CONSTRUCT_END
 #cmakedefine01 TS_USE_TLS_SET_CIPHERSUITES
diff --git a/src/api/InkAPI.cc b/src/api/InkAPI.cc
index 647d04e1e5..41d8fc198a 100644
--- a/src/api/InkAPI.cc
+++ b/src/api/InkAPI.cc
@@ -5467,7 +5467,7 @@ TSVConnIsSslReused(TSVConn sslp)
   NetVConnection    *vc     = reinterpret_cast<NetVConnection *>(sslp);
   SSLNetVConnection *ssl_vc = dynamic_cast<SSLNetVConnection *>(vc);
 
-  return ssl_vc ? ssl_vc->getSSLSessionCacheHit() : 0;
+  return ssl_vc ? ssl_vc->getIsResumedSSLSession() : 0;
 }
 
 const char *
diff --git a/src/iocore/net/P_QUICNetVConnection.h 
b/src/iocore/net/P_QUICNetVConnection.h
index 9869d9d619..4f30e3ba74 100644
--- a/src/iocore/net/P_QUICNetVConnection.h
+++ b/src/iocore/net/P_QUICNetVConnection.h
@@ -157,9 +157,10 @@ protected:
   bool _isReadyToTransferData() const override;
 
   // TLSBasicSupport
-  SSL         *_get_ssl_object() const override;
-  ssl_curve_id _get_tls_curve() const override;
-  int          _verify_certificate(X509_STORE_CTX *ctx) override;
+  SSL             *_get_ssl_object() const override;
+  ssl_curve_id     _get_tls_curve() const override;
+  std::string_view _get_tls_group() const override;
+  int              _verify_certificate(X509_STORE_CTX *ctx) override;
 
   // TLSSNISupport
   in_port_t _get_local_port() override;
diff --git a/src/iocore/net/P_SSLNetVConnection.h 
b/src/iocore/net/P_SSLNetVConnection.h
index dea3328f68..7417477480 100644
--- a/src/iocore/net/P_SSLNetVConnection.h
+++ b/src/iocore/net/P_SSLNetVConnection.h
@@ -320,8 +320,9 @@ protected:
   {
     return this->ssl;
   }
-  ssl_curve_id _get_tls_curve() const override;
-  int          _verify_certificate(X509_STORE_CTX *ctx) override;
+  ssl_curve_id     _get_tls_curve() const override;
+  std::string_view _get_tls_group() const override;
+  int              _verify_certificate(X509_STORE_CTX *ctx) override;
 
   // TLSSessionResumptionSupport
   const IpEndpoint &
diff --git a/src/iocore/net/P_SSLUtils.h b/src/iocore/net/P_SSLUtils.h
index c7a4cad19c..b9d48cbc91 100644
--- a/src/iocore/net/P_SSLUtils.h
+++ b/src/iocore/net/P_SSLUtils.h
@@ -36,9 +36,12 @@ class SSLNetVConnection;
 
 using ssl_error_t = int;
 
-// Return the SSL Curve ID associated to the specified SSL connection
+/// Return the SSL Curve ID associated with the specified SSL connection
 ssl_curve_id SSLGetCurveNID(SSL *ssl);
 
+/// Return the TLS Group Name associated with the specified SSL connection.
+std::string_view SSLGetGroupName(SSL *ssl);
+
 SSL_SESSION *SSLSessionDup(SSL_SESSION *sess);
 
 enum class SSLCertContextType;
diff --git a/src/iocore/net/QUICNetVConnection.cc 
b/src/iocore/net/QUICNetVConnection.cc
index e63fbdebaa..d3bc4a76d1 100644
--- a/src/iocore/net/QUICNetVConnection.cc
+++ b/src/iocore/net/QUICNetVConnection.cc
@@ -808,13 +808,29 @@ QUICNetVConnection::_get_ssl_object() const
 ssl_curve_id
 QUICNetVConnection::_get_tls_curve() const
 {
-  if (getSSLSessionCacheHit()) {
+  // For resumed server side session caching, we have to retrieve the 
curve/group
+  // from our stored data. For non-resumed sessions or from ticket based 
resumption,
+  // simply query the SSL object.
+  if (getIsResumedFromSessionCache()) {
     return getSSLCurveNID();
   } else {
     return SSLGetCurveNID(this->_ssl);
   }
 }
 
+std::string_view
+QUICNetVConnection::_get_tls_group() const
+{
+  // For resumed server side session caching, we have to retrieve the 
curve/group
+  // from our stored data. For non-resumed sessions or from ticket based 
resumption,
+  // simply query the SSL object.
+  if (getIsResumedFromSessionCache()) {
+    return getSSLGroupName();
+  } else {
+    return SSLGetGroupName(this->_ssl);
+  }
+}
+
 int
 QUICNetVConnection::_verify_certificate(X509_STORE_CTX * /* ctx ATS_UNUSED */)
 {
diff --git a/src/iocore/net/SSLNetVConnection.cc 
b/src/iocore/net/SSLNetVConnection.cc
index 4d174d258c..2e24233462 100644
--- a/src/iocore/net/SSLNetVConnection.cc
+++ b/src/iocore/net/SSLNetVConnection.cc
@@ -2102,13 +2102,29 @@ SSLNetVConnection::_migrateFromSSL()
 ssl_curve_id
 SSLNetVConnection::_get_tls_curve() const
 {
-  if (getSSLSessionCacheHit()) {
+  // For resumed server side session caching, we have to retrieve the 
curve/group
+  // from our stored data. For non-resumed sessions or from ticket based 
resumption,
+  // simply query the SSL object.
+  if (getIsResumedFromSessionCache()) {
     return getSSLCurveNID();
   } else {
     return SSLGetCurveNID(ssl);
   }
 }
 
+std::string_view
+SSLNetVConnection::_get_tls_group() const
+{
+  // For resumed server side session caching, we have to retrieve the 
curve/group
+  // from our stored data. For non-resumed sessions or from ticket based 
resumption,
+  // simply query the SSL object.
+  if (getIsResumedFromSessionCache()) {
+    return getSSLGroupName();
+  } else {
+    return SSLGetGroupName(ssl);
+  }
+}
+
 int
 SSLNetVConnection::_verify_certificate(X509_STORE_CTX * /* ctx ATS_UNUSED */)
 {
diff --git a/src/iocore/net/SSLSessionCache.cc 
b/src/iocore/net/SSLSessionCache.cc
index ee36095d5c..7fe5ae9eaf 100644
--- a/src/iocore/net/SSLSessionCache.cc
+++ b/src/iocore/net/SSLSessionCache.cc
@@ -174,6 +174,14 @@ SSLSessionBucket::insertSession(const SSLSessionID &id, 
SSL_SESSION *sess, SSL *
   // This could be moved to a function in charge of populating exdata
   exdata->curve = (ssl == nullptr) ? 0 : SSLGetCurveNID(ssl);
 
+  if (ssl == nullptr) {
+    exdata->group_name[0] = '\0';
+  } else {
+    std::string_view group_name = SSLGetGroupName(ssl);
+    ink_release_assert(group_name.size() < sizeof(exdata->group_name));
+    strcpy(exdata->group_name, group_name.data());
+  }
+
   std::unique_ptr<SSLSession> ssl_session(new SSLSession(id, buf, len, 
buf_exdata));
 
   std::unique_lock w_lock(mutex, std::try_to_lock);
@@ -352,9 +360,11 @@ SSLOriginSessionCache::insert_session(const std::string 
&lookup_key, SSL_SESSION
 
   Dbg(dbg_ctl_ssl_origin_session_cache, "insert session: %s = %p", 
lookup_key.c_str(), sess_ptr);
 
-  ssl_curve_id                      curve = (ssl == nullptr) ? 0 : 
SSLGetCurveNID(ssl);
+  ssl_curve_id curve      = (ssl == nullptr) ? 0 : SSLGetCurveNID(ssl);
+  std::string  group_name = (ssl == nullptr) ? "" : 
std::string{SSLGetGroupName(ssl)};
+
   std::unique_ptr<SSLOriginSession> ssl_orig_session(
-    new SSLOriginSession(lookup_key, curve, 
std::shared_ptr<SSL_SESSION>{sess_ptr, SSLSessDeleter}));
+    new SSLOriginSession(lookup_key, curve, group_name, 
std::shared_ptr<SSL_SESSION>{sess_ptr, SSLSessDeleter}));
   auto new_node = ssl_orig_session.release();
 
   std::unique_lock lock(mutex);
@@ -376,7 +386,7 @@ SSLOriginSessionCache::insert_session(const std::string 
&lookup_key, SSL_SESSION
 }
 
 std::shared_ptr<SSL_SESSION>
-SSLOriginSessionCache::get_session(const std::string &lookup_key, ssl_curve_id 
*curve)
+SSLOriginSessionCache::get_session(const std::string &lookup_key, ssl_curve_id 
*curve, std::string &group_name)
 {
   Dbg(dbg_ctl_ssl_origin_session_cache, "get session: %s", lookup_key.c_str());
 
@@ -390,6 +400,8 @@ SSLOriginSessionCache::get_session(const std::string 
&lookup_key, ssl_curve_id *
     *curve = entry->second->curve_id;
   }
 
+  group_name = entry->second->group_name;
+
   return entry->second->shared_sess;
 }
 
diff --git a/src/iocore/net/SSLSessionCache.h b/src/iocore/net/SSLSessionCache.h
index a2a6535c65..769c20adf1 100644
--- a/src/iocore/net/SSLSessionCache.h
+++ b/src/iocore/net/SSLSessionCache.h
@@ -30,13 +30,25 @@
 
 #include <openssl/ssl.h>
 #include <mutex>
+#include <string>
+#include <string_view>
 #include <utility>
 
+/** Looking at OpenSSL's providers/common/capabilities.c, the current maximum
+ * length of a group name is 20 characters (brainpoolP256r1tls13 and the like).
+ * Reserving 64 characters should be more than enough. If someday we are
+ * surprised and this turns out to be too small, there is an assertion gaurd to
+ * make sure we do not overrun the buffer in SSLSessionCache.cc.
+ */
+#define SSL_MAX_GROUP_NAME_SIZE   64
 #define SSL_MAX_SESSION_SIZE      256
 #define SSL_MAX_ORIG_SESSION_SIZE 4096
 
 struct ssl_session_cache_exdata {
   ssl_curve_id curve = 0;
+
+  /** The TLS group name, gauranteed to be null-terminated. */
+  char group_name[SSL_MAX_GROUP_NAME_SIZE] = {'\0'};
 };
 
 inline void
@@ -193,10 +205,12 @@ class SSLOriginSession
 public:
   std::string                  key;
   ssl_curve_id                 curve_id;
+  std::string                  group_name;
   std::shared_ptr<SSL_SESSION> shared_sess = nullptr;
 
-  SSLOriginSession(const std::string &lookup_key, ssl_curve_id curve, 
std::shared_ptr<SSL_SESSION> session)
-    : key(lookup_key), curve_id(curve), shared_sess(std::move(session))
+  SSLOriginSession(const std::string &lookup_key, ssl_curve_id curve, 
std::string_view group_name,
+                   std::shared_ptr<SSL_SESSION> session)
+    : key(lookup_key), curve_id(curve), group_name(group_name), 
shared_sess(std::move(session))
   {
   }
 
@@ -210,7 +224,7 @@ public:
   ~SSLOriginSessionCache();
 
   void                         insert_session(const std::string &lookup_key, 
SSL_SESSION *sess, SSL *ssl);
-  std::shared_ptr<SSL_SESSION> get_session(const std::string &lookup_key, 
ssl_curve_id *curve);
+  std::shared_ptr<SSL_SESSION> get_session(const std::string &lookup_key, 
ssl_curve_id *curve, std::string &group_name);
   void                         remove_session(const std::string &lookup_key);
 
 private:
diff --git a/src/iocore/net/SSLUtils.cc b/src/iocore/net/SSLUtils.cc
index 59e6f00a7d..0b7bc982ad 100644
--- a/src/iocore/net/SSLUtils.cc
+++ b/src/iocore/net/SSLUtils.cc
@@ -57,6 +57,7 @@
 #include <openssl/engine.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
+#include <openssl/objects.h>
 #include <openssl/pem.h>
 #include <openssl/rand.h>
 #include <openssl/x509.h>
@@ -2521,6 +2522,31 @@ SSLGetCurveNID(SSL *ssl)
 #endif
 }
 
+std::string_view
+SSLGetGroupName([[maybe_unused]] SSL *ssl)
+{
+#if HAVE_SSL_GET0_GROUP_NAME // OpenSSL 3.2+
+  char const *group_name = SSL_get0_group_name(ssl);
+  return group_name != nullptr ? std::string_view(group_name) : "";
+#elif HAVE_SSL_GET_NEGOTIATED_GROUP && HAVE_SSL_GROUP_TO_NAME // OpenSSL 
3.0/3.1
+  int const group_id = SSL_get_negotiated_group(ssl);
+  if (group_id != NID_undef) {
+    char const *group_name = SSL_group_to_name(ssl, group_id);
+    return group_name != nullptr ? std::string_view(group_name) : "";
+  }
+  return "";
+#elif HAVE_SSL_GET_GROUP_ID && HAVE_SSL_GET_GROUP_NAME        // BoringSSL
+  uint16_t const group_id = SSL_get_group_id(ssl);
+  if (group_id == 0) {
+    return "";
+  }
+  char const *group_name = SSL_get_group_name(group_id);
+  return group_name != nullptr ? std::string_view(group_name) : "";
+#else
+  return "";
+#endif // HAVE_SSL_GET0_GROUP_NAME
+}
+
 SSL_SESSION *
 SSLSessionDup(SSL_SESSION *sess)
 {
diff --git a/src/iocore/net/TLSBasicSupport.cc 
b/src/iocore/net/TLSBasicSupport.cc
index 17adaa42dd..bb77dab836 100644
--- a/src/iocore/net/TLSBasicSupport.cc
+++ b/src/iocore/net/TLSBasicSupport.cc
@@ -123,25 +123,16 @@ TLSBasicSupport::get_tls_curve() const
 #endif
 }
 
-const char *
+std::string_view
 TLSBasicSupport::get_tls_group() const
 {
   auto ssl = this->_get_ssl_object();
 
   if (!ssl) {
-    return nullptr;
-  }
-#if HAVE_SSL_GET0_GROUP_NAME // OpenSSL
-  return SSL_get0_group_name(ssl);
-#elif HAVE_SSL_GET_GROUP_ID && HAVE_SSL_GET_GROUP_NAME // BoringSSL
-  uint16_t const group_id = SSL_get_group_id(ssl);
-  if (group_id == 0) {
-    return nullptr;
+    return "";
   }
-  return SSL_get_group_name(group_id);
-#else
-  return nullptr;
-#endif // HAVE_SSL_GET0_GROUP_NAME
+
+  return this->_get_tls_group();
 }
 
 ink_hrtime
diff --git a/src/iocore/net/TLSSessionResumptionSupport.cc 
b/src/iocore/net/TLSSessionResumptionSupport.cc
index af78aba176..68d8607617 100644
--- a/src/iocore/net/TLSSessionResumptionSupport.cc
+++ b/src/iocore/net/TLSSessionResumptionSupport.cc
@@ -26,6 +26,7 @@
 
 #include "iocore/net/TLSSessionResumptionSupport.h"
 #include "P_SSLCertLookup.h"
+#include "P_SSLUtils.h"
 #include "iocore/net/SSLAPIHooks.h"
 
 #include "P_SSLConfig.h"
@@ -124,15 +125,31 @@ TLSSessionResumptionSupport::processSessionTicket(SSL 
*ssl, unsigned char *keyna
 }
 
 bool
-TLSSessionResumptionSupport::getSSLSessionCacheHit() const
+TLSSessionResumptionSupport::getIsResumedSSLSession() const
 {
-  return this->_sslSessionCacheHit;
+  return (this->_resumptionType == ResumptionType::RESUMED_FROM_SESSION_CACHE 
||
+          this->_resumptionType == 
ResumptionType::RESUMED_FROM_SESSION_TICKET) &&
+         !this->_isResumedOriginSession;
 }
 
 bool
-TLSSessionResumptionSupport::getSSLOriginSessionCacheHit() const
+TLSSessionResumptionSupport::getIsResumedOriginSSLSession() const
 {
-  return this->_sslOriginSessionCacheHit;
+  return (this->_resumptionType == ResumptionType::RESUMED_FROM_SESSION_CACHE 
||
+          this->_resumptionType == 
ResumptionType::RESUMED_FROM_SESSION_TICKET) &&
+         this->_isResumedOriginSession;
+}
+
+bool
+TLSSessionResumptionSupport::getIsResumedFromSessionCache() const
+{
+  return this->_resumptionType == ResumptionType::RESUMED_FROM_SESSION_CACHE;
+}
+
+bool
+TLSSessionResumptionSupport::getIsResumedFromSessionTicket() const
+{
+  return this->_resumptionType == ResumptionType::RESUMED_FROM_SESSION_TICKET;
 }
 
 ssl_curve_id
@@ -141,6 +158,12 @@ TLSSessionResumptionSupport::getSSLCurveNID() const
   return this->_sslCurveNID;
 }
 
+std::string_view
+TLSSessionResumptionSupport::getSSLGroupName() const
+{
+  return this->_sslGroupName;
+}
+
 SSL_SESSION *
 TLSSessionResumptionSupport::getSession(SSL *ssl, const unsigned char *id, int 
len, int *copy)
 {
@@ -180,8 +203,9 @@ TLSSessionResumptionSupport::getSession(SSL *ssl, const 
unsigned char *id, int l
       session = nullptr;
     } else {
       Metrics::Counter::increment(ssl_rsb.session_cache_hit);
-      this->_setSSLSessionCacheHit(true);
+      this->_setResumptionType(ResumptionType::RESUMED_FROM_SESSION_CACHE, 
!IS_RESUMED_ORIGIN_SESSION);
       this->_setSSLCurveNID(exdata->curve);
+      this->_setSSLGroupName(exdata->group_name);
     }
   } else {
     Metrics::Counter::increment(ssl_rsb.session_cache_miss);
@@ -192,8 +216,9 @@ TLSSessionResumptionSupport::getSession(SSL *ssl, const 
unsigned char *id, int l
 std::shared_ptr<SSL_SESSION>
 TLSSessionResumptionSupport::getOriginSession(const std::string &lookup_key)
 {
-  ssl_curve_id                 curve       = 0;
-  std::shared_ptr<SSL_SESSION> shared_sess = 
origin_sess_cache->get_session(lookup_key, &curve);
+  ssl_curve_id                 curve = 0;
+  std::string                  group_name;
+  std::shared_ptr<SSL_SESSION> shared_sess = 
origin_sess_cache->get_session(lookup_key, &curve, group_name);
 
   if (shared_sess != nullptr) {
     // Double check the timeout
@@ -203,8 +228,9 @@ TLSSessionResumptionSupport::getOriginSession(const 
std::string &lookup_key)
       shared_sess.reset();
     } else {
       Metrics::Counter::increment(ssl_rsb.origin_session_cache_hit);
-      this->_setSSLOriginSessionCacheHit(true);
+      this->_setResumptionType(ResumptionType::RESUMED_FROM_SESSION_CACHE, 
IS_RESUMED_ORIGIN_SESSION);
       this->_setSSLCurveNID(curve);
+      this->_setSSLGroupName(group_name);
     }
   } else {
     Metrics::Counter::increment(ssl_rsb.origin_session_cache_miss);
@@ -215,7 +241,10 @@ TLSSessionResumptionSupport::getOriginSession(const 
std::string &lookup_key)
 void
 TLSSessionResumptionSupport::clear()
 {
-  this->_sslSessionCacheHit = false;
+  this->_resumptionType         = ResumptionType::NOT_RESUMED;
+  this->_isResumedOriginSession = false;
+  this->_sslCurveNID            = NID_undef;
+  this->_sslGroupName.clear();
 }
 
 #ifdef HAVE_SSL_CTX_SET_TLSEXT_TICKET_KEY_EVP_CB
@@ -297,7 +326,10 @@ 
TLSSessionResumptionSupport::_getSessionInformation(ssl_ticket_key_block *keyblo
         Metrics::Counter::increment(ssl_rsb.total_tickets_verified_old_key);
       }
 
-      this->_setSSLSessionCacheHit(true);
+      this->_setResumptionType(ResumptionType::RESUMED_FROM_SESSION_TICKET, 
!IS_RESUMED_ORIGIN_SESSION);
+      // Do not call _setSSLCurveNID() and _setSSLGroupName() here because the
+      // SSL object is not fully configured for this yet and the curve/group
+      // info is not available. OpenSSL will crash.
 
 #ifdef TLS1_3_VERSION
       if (SSL_version(ssl) >= TLS1_3_VERSION) {
@@ -317,19 +349,20 @@ 
TLSSessionResumptionSupport::_getSessionInformation(ssl_ticket_key_block *keyblo
 }
 
 void
-TLSSessionResumptionSupport::_setSSLSessionCacheHit(bool state)
+TLSSessionResumptionSupport::_setResumptionType(ResumptionType type, bool 
isOrigin)
 {
-  this->_sslSessionCacheHit = state;
+  this->_resumptionType         = type;
+  this->_isResumedOriginSession = isOrigin;
 }
 
 void
-TLSSessionResumptionSupport::_setSSLOriginSessionCacheHit(bool state)
+TLSSessionResumptionSupport::_setSSLCurveNID(ssl_curve_id curve_nid)
 {
-  this->_sslOriginSessionCacheHit = state;
+  this->_sslCurveNID = curve_nid;
 }
 
 void
-TLSSessionResumptionSupport::_setSSLCurveNID(ssl_curve_id curve_nid)
+TLSSessionResumptionSupport::_setSSLGroupName(std::string_view group_name)
 {
-  this->_sslCurveNID = curve_nid;
+  this->_sslGroupName = std::string{group_name};
 }
diff --git a/src/proxy/http/HttpSM.cc b/src/proxy/http/HttpSM.cc
index cc39104926..434044bd75 100644
--- a/src/proxy/http/HttpSM.cc
+++ b/src/proxy/http/HttpSM.cc
@@ -6651,7 +6651,7 @@ HttpSM::attach_server_session()
   }
 
   if (auto tsrs = server_vc->get_service<TLSSessionResumptionSupport>(); tsrs) 
{
-    server_ssl_reused = tsrs->getSSLOriginSessionCacheHit();
+    server_ssl_reused = tsrs->getIsResumedOriginSSLSession();
   }
 
   server_protocol = server_txn->get_protocol_string();

Reply via email to