Commit df8f3cc534 for openssl.org

commit df8f3cc5342b848f8e6e00b866847e67684ce89e
Author: Tomas Mraz <tomas@openssl.org>
Date:   Thu Dec 18 11:43:41 2025 +0100

    ECH: Properly apply libctx and propq from SSL_CTX

    And further minor refactoring.

    Reviewed-by: Matt Caswell <matt@openssl.org>
    Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
    MergeDate: Thu Jan  8 09:59:56 2026
    (Merged from https://github.com/openssl/openssl/pull/29439)

diff --git a/ssl/ech/ech_internal.c b/ssl/ech/ech_internal.c
index b20aca50c4..366637bab0 100644
--- a/ssl/ech/ech_internal.c
+++ b/ssl/ech/ech_internal.c
@@ -9,12 +9,13 @@

 #include <openssl/ssl.h>
 #include <openssl/ech.h>
-#include "../ssl_local.h"
-#include "ech_local.h"
 #include <openssl/rand.h>
-#include "../statem/statem_local.h"
-#include "internal/ech_helpers.h"
 #include <openssl/kdf.h>
+#include "internal/ech_helpers.h"
+#include "internal/ssl_unwrap.h"
+#include "../ssl_local.h"
+#include "../statem/statem_local.h"
+#include "ech_local.h"

 #ifndef OPENSSL_NO_ECH

@@ -296,16 +297,11 @@ int ossl_ech_send_grease(SSL_CONNECTION *s, WPACKET *pkt)
     size_t cipher_len = 0, cipher_len_jitter = 0;
     unsigned char cid, senderpub[OSSL_ECH_MAX_GREASE_PUB];
     unsigned char cipher[OSSL_ECH_MAX_GREASE_CT];
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);

-    if (s == NULL)
-        return 0;
-    if (s->ssl.ctx == NULL) {
-        SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
-        return 0;
-    }
     WPACKET_get_total_written(pkt, &pp_at_start);
     /* randomly select cipher_len to be one of 144, 176, 208, 244 */
-    if (RAND_bytes_ex(s->ssl.ctx->libctx, &cid, 1, 0) <= 0) {
+    if (RAND_bytes_ex(sctx->libctx, &cid, 1, 0) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
     }
@@ -313,7 +309,7 @@ int ossl_ech_send_grease(SSL_CONNECTION *s, WPACKET *pkt)
     cipher_len = 144;
     cipher_len += 32 * cipher_len_jitter;
     /* generate a random (1 octet) client id */
-    if (RAND_bytes_ex(s->ssl.ctx->libctx, &cid, 1, 0) <= 0) {
+    if (RAND_bytes_ex(sctx->libctx, &cid, 1, 0) <= 0) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
     }
@@ -329,7 +325,7 @@ int ossl_ech_send_grease(SSL_CONNECTION *s, WPACKET *pkt)
     if (OSSL_HPKE_get_grease_value(hpke_suite_in_p, &hpke_suite,
             senderpub, &senderpub_len,
             cipher, cipher_len,
-            s->ssl.ctx->libctx, NULL)
+            sctx->libctx, sctx->propq)
         != 1) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
         return 0;
@@ -1028,6 +1024,7 @@ int ossl_ech_calc_confirm(SSL_CONNECTION *s, int for_hrr,
         + SSL3_RANDOM_SIZE - OSSL_ECH_SIGNAL_LEN;
     unsigned int hashlen = 0;
     unsigned char hashval[EVP_MAX_MD_SIZE];
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);

     if ((md = (EVP_MD *)ssl_handshake_md(s)) == NULL) {
         SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_ECH_REQUIRED);
@@ -1055,7 +1052,7 @@ int ossl_ech_calc_confirm(SSL_CONNECTION *s, int for_hrr,
         } else {
             if (s->ext.ech.hrrsignal_p == NULL) {
                 /* No ECH found so we'll exit, but set random output */
-                if (RAND_bytes_ex(s->ssl.ctx->libctx, acbuf,
+                if (RAND_bytes_ex(sctx->libctx, acbuf,
                         OSSL_ECH_SIGNAL_LEN, 0)
                     <= 0) {
                     SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_ECH_REQUIRED);
@@ -1747,6 +1744,7 @@ static unsigned char *hpke_decrypt_encch(SSL_CONNECTION *s,
     size_t info_len = OSSL_ECH_MAX_INFO_LEN;
     int rv = 0;
     OSSL_HPKE_CTX *hctx = NULL;
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
 #ifdef OSSL_ECH_SUPERVERBOSE
     size_t publen = 0;
     unsigned char *pub = NULL;
@@ -1800,7 +1798,7 @@ static unsigned char *hpke_decrypt_encch(SSL_CONNECTION *s,
     ERR_set_mark();
     /* Use OSSL_HPKE_* APIs */
     hctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite, OSSL_HPKE_ROLE_RECEIVER,
-        NULL, NULL);
+        sctx->libctx, sctx->propq);
     if (hctx == NULL)
         goto clearerrs;
     rv = OSSL_HPKE_decap(hctx, senderpub, senderpublen, ee->keyshare,
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index cc0b5d9f34..e323e21cf3 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -1449,7 +1449,7 @@ dopsksess:
             return EXT_RETURN_FAIL;
         }
         /* for outer CH allocate a similar sized random value */
-        if (RAND_bytes_ex(s->ssl.ctx->libctx, rndbuf, totalrndsize, 0) <= 0) {
+        if (RAND_bytes_ex(sctx->libctx, rndbuf, totalrndsize, 0) <= 0) {
             OPENSSL_free(rndbuf);
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             return EXT_RETURN_FAIL;
@@ -2569,6 +2569,7 @@ EXT_RETURN tls_construct_ctos_ech(SSL_CONNECTION *s, WPACKET *pkt,
     size_t chainidx)
 {
     int rv = 0, hpke_mode = OSSL_HPKE_MODE_BASE;
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
     OSSL_ECHSTORE_ENTRY *ee = NULL;
     OSSL_HPKE_SUITE hpke_suite = OSSL_HPKE_SUITE_DEFAULT;
     unsigned char config_id_to_use = 0x00, info[OSSL_ECH_MAX_INFO_LEN];
@@ -2650,7 +2651,7 @@ EXT_RETURN tls_construct_ctos_ech(SSL_CONNECTION *s, WPACKET *pkt,
     OSSL_TRACE_END(TLS);
     config_id_to_use = ee->config_id; /* if requested, use a random config_id instead */
     if ((s->options & SSL_OP_ECH_IGNORE_CID) != 0) {
-        if (RAND_bytes_ex(s->ssl.ctx->libctx, &config_id_to_use, 1, 0) <= 0) {
+        if (RAND_bytes_ex(sctx->libctx, &config_id_to_use, 1, 0) <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             return 0;
         }
@@ -2691,7 +2692,7 @@ EXT_RETURN tls_construct_ctos_ech(SSL_CONNECTION *s, WPACKET *pkt,
 #endif
         s->ext.ech.hpke_ctx = OSSL_HPKE_CTX_new(hpke_mode, hpke_suite,
             OSSL_HPKE_ROLE_SENDER,
-            NULL, NULL);
+            sctx->libctx, sctx->propq);
         if (s->ext.ech.hpke_ctx == NULL) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
             goto err;
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 3535d06483..51159de03f 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -2514,6 +2514,7 @@ EXT_RETURN tls_construct_stoc_ech(SSL_CONNECTION *s, WPACKET *pkt,
 {
     unsigned char *rcfgs = NULL;
     size_t rcfgslen = 0;
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);

     if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
         && (s->ext.ech.success == 1 || s->ext.ech.backend == 1)
@@ -2538,7 +2539,7 @@ EXT_RETURN tls_construct_stoc_ech(SSL_CONNECTION *s, WPACKET *pkt,
         && s->ext.ech.attempted == 1) {
         unsigned char randomconf[8];

-        if (RAND_bytes_ex(s->ssl.ctx->libctx, randomconf, 8,
+        if (RAND_bytes_ex(sctx->libctx, randomconf, 8,
                 RAND_DRBG_STRENGTH)
             <= 0) {
             SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index b65aded0b6..e4d77a0980 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1216,6 +1216,7 @@ __owur CON_FUNC_RETURN tls_construct_client_hello(SSL_CONNECTION *s,
     BUF_MEM *inner_mem = NULL;
     PACKET rpkt; /* we'll decode back the inner ch to help make the outer */
     SSL_SESSION *sess = NULL;
+    SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
     size_t sess_id_len = 0, innerlen = 0;
     int mt = SSL3_MT_CLIENT_HELLO, rv = 0;
     OSSL_HPKE_SUITE suite;
@@ -1273,7 +1274,7 @@ __owur CON_FUNC_RETURN tls_construct_client_hello(SSL_CONNECTION *s,
             sess_id_len = sizeof(s->tmp_session_id);
             s->tmp_session_id_len = sess_id_len;
             if (s->hello_retry_request == SSL_HRR_NONE
-                && RAND_bytes_ex(s->ssl.ctx->libctx, s->tmp_session_id,
+                && RAND_bytes_ex(sctx->libctx, s->tmp_session_id,
                        sess_id_len, 0)
                     <= 0) {
                 SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);