@@ -2699,6 +2699,17 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap)
26992699 ctx->minMlDsaKeySz = MIN_MLDSAKEY_SZ;
27002700#endif /* WOLFSSL_HAVE_MLDSA */
27012701 ctx->verifyDepth = MAX_CHAIN_DEPTH;
2702+ #if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
2703+ defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
2704+ !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK) && \
2705+ !defined(WOLFSSL_ALLOW_LEGACY_SERVER_CONNECT)
2706+ /* RFC 5746 / RFC 9325: a TLS 1.2 client requires the server to acknowledge
2707+ * the renegotiation_info extension on the initial handshake. Enabled by
2708+ * default; define WOLFSSL_ALLOW_LEGACY_SERVER_CONNECT (or call
2709+ * wolfSSL_CTX_set_scr_check_enabled(ctx, 0)) to connect to servers that do
2710+ * not support secure renegotiation. */
2711+ ctx->scr_check_enabled = 1;
2712+ #endif
27022713#ifdef OPENSSL_EXTRA
27032714 ctx->cbioFlag = WOLFSSL_CBIO_NONE;
27042715#endif
@@ -8023,6 +8034,58 @@ static void InitSSL_Multicast(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
80238034}
80248035#endif /* WOLFSSL_MULTICAST */
80258036
8037+ #if defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO)
8038+ /* Set up the client's renegotiation_info advertising. Shared by InitSSL and the
8039+ * ClientHello send paths so the "advertise implies enforce" invariant survives
8040+ * WOLFSSL object reuse: without re-advertising after wolfSSL_clear the client
8041+ * would send no renegotiation_info yet still enforce its presence, failing
8042+ * every reused-object handshake.
8043+ *
8044+ * Willingness to perform a peer-initiated renegotiation is derived from
8045+ * ssl->ctx->useSecureReneg. A per-object wolfSSL_UseSecureRenegotiation() opt-in
8046+ * is not tracked here, so after wolfSSL_clear a reused object reverts to
8047+ * advertise-only; applications that renegotiate on reused objects should opt in
8048+ * at the context level with wolfSSL_CTX_UseSecureRenegotiation(). */
8049+ int SetupClientSecureRenegotiation(WOLFSSL* ssl)
8050+ {
8051+ int ret = WOLFSSL_SUCCESS;
8052+
8053+ if (ssl->options.side == WOLFSSL_CLIENT_END) {
8054+ int useSecureReneg = ssl->ctx->useSecureReneg;
8055+ #ifdef HAVE_SECURE_RENEGOTIATION
8056+ int advertiseOnly = 0;
8057+ #endif
8058+ /* Advertise the empty renegotiation_info extension by default so the
8059+ * client can enforce RFC 5746 / RFC 9325 on the initial handshake.
8060+ * Advertising is always safe: legacy servers ignore it and secure
8061+ * servers echo it. */
8062+ #if defined(WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT)
8063+ /* Integrator asked for secure renegotiation by default: keep the full
8064+ * renegotiation behavior (advertiseOnly stays 0). */
8065+ useSecureReneg = 1;
8066+ #elif !defined(WOLFSSL_NO_TLS12) && defined(HAVE_SERVER_RENEGOTIATION_INFO)
8067+ #ifdef HAVE_SECURE_RENEGOTIATION
8068+ /* Advertising was forced on for the RFC 5746 check, not requested by
8069+ * the application, so do not also grant willingness to perform a
8070+ * peer-initiated renegotiation. */
8071+ if (!useSecureReneg)
8072+ advertiseOnly = 1;
8073+ #endif
8074+ useSecureReneg = 1;
8075+ #endif
8076+ if (useSecureReneg) {
8077+ ret = wolfSSL_UseSecureRenegotiation(ssl);
8078+ #ifdef HAVE_SECURE_RENEGOTIATION
8079+ if (ret == WOLFSSL_SUCCESS && ssl->secure_renegotiation != NULL)
8080+ ssl->secure_renegotiation->advertiseOnly = (byte)advertiseOnly;
8081+ #endif
8082+ }
8083+ }
8084+
8085+ return ret;
8086+ }
8087+ #endif /* HAVE_SECURE_RENEGOTIATION || HAVE_SERVER_RENEGOTIATION_INFO */
8088+
80268089int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
80278090{
80288091 int ret;
@@ -8239,8 +8302,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
82398302 ssl->disabledCurves = ctx->disabledCurves;
82408303#endif
82418304#if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
8242- defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
8243- ssl->scr_check_enabled = 1;
8305+ defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
8306+ !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
8307+ /* Inherit the renegotiation_info enforcement setting from the context. */
8308+ ssl->scr_check_enabled = ctx->scr_check_enabled;
82448309#endif
82458310
82468311 InitCiphers(ssl);
@@ -8366,20 +8431,9 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
83668431
83678432#if defined(HAVE_SECURE_RENEGOTIATION) || \
83688433 defined(HAVE_SERVER_RENEGOTIATION_INFO)
8369- if (ssl->options.side == WOLFSSL_CLIENT_END) {
8370- int useSecureReneg = ssl->ctx->useSecureReneg;
8371- /* use secure renegotiation by default (not recommend) */
8372- #if defined(WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT) || \
8373- (defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_NO_TLS12) && \
8374- !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK))
8375- useSecureReneg = 1;
8376- #endif
8377- if (useSecureReneg) {
8378- ret = wolfSSL_UseSecureRenegotiation(ssl);
8379- if (ret != WOLFSSL_SUCCESS)
8380- return ret;
8381- }
8382- }
8434+ ret = SetupClientSecureRenegotiation(ssl);
8435+ if (ret != WOLFSSL_SUCCESS)
8436+ return ret;
83838437#endif /* HAVE_SECURE_RENEGOTIATION */
83848438
83858439#ifdef WOLFSSL_QUIC
@@ -9428,7 +9482,10 @@ void FreeHandshakeResources(WOLFSSL* ssl)
94289482#endif
94299483
94309484#ifdef HAVE_SECURE_RENEGOTIATION
9431- if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
9485+ /* advertiseOnly clients never renegotiate, so do not retain (and leave
9486+ * unzeroed) the master secret and other handshake resources for them. */
9487+ if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
9488+ !ssl->secure_renegotiation->advertiseOnly) {
94329489 WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources");
94339490 return;
94349491 }
@@ -18573,8 +18630,13 @@ static int DoHelloRequest(WOLFSSL* ssl, word32 size)
1857318630 return FATAL_ERROR;
1857418631 }
1857518632#ifdef HAVE_SECURE_RENEGOTIATION
18576- else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) {
18577- /* WOLFSSL_OP_NO_RENEGOTIATION: caller opted into rejecting
18633+ else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled &&
18634+ !ssl->secure_renegotiation->advertiseOnly) {
18635+ /* advertiseOnly: renegotiation_info was advertised only for the RFC
18636+ * 5746 initial-handshake check, so the application did not opt into
18637+ * secure renegotiation; the else branch below refuses the request.
18638+ *
18639+ * WOLFSSL_OP_NO_RENEGOTIATION: caller opted into rejecting
1857818640 * peer-initiated renegotiation. Respond with a no_renegotiation
1857918641 * warning alert instead of starting a secure renegotiation. */
1858018642 if (ssl->options.mask & WOLFSSL_OP_NO_RENEGOTIATION) {
@@ -32654,6 +32716,17 @@ static void MakePSKPreMasterSecret(Arrays* arrays, byte use_psk_key)
3265432716 return BAD_FUNC_ARG;
3265532717 }
3265632718
32719+ #if defined(HAVE_SECURE_RENEGOTIATION) || defined(HAVE_SERVER_RENEGOTIATION_INFO)
32720+ /* Re-establish renegotiation_info advertising for a reused object
32721+ * (wolfSSL_clear frees it). Only when absent, so an in-progress
32722+ * renegotiation keeps its verify_data state. */
32723+ if (ssl->secure_renegotiation == NULL) {
32724+ ret = SetupClientSecureRenegotiation(ssl);
32725+ if (ret != WOLFSSL_SUCCESS)
32726+ return ret;
32727+ }
32728+ #endif
32729+
3265732730#ifdef WOLFSSL_TLS13
3265832731 if (IsAtLeastTLSv1_3(ssl->version))
3265932732 return SendTls13ClientHello(ssl);
@@ -33346,14 +33419,18 @@ static void MakePSKPreMasterSecret(Arrays* arrays, byte use_psk_key)
3334633419 }
3334733420#endif /* HAVE_TLS_EXTENSIONS */
3334833421
33349- #if defined(WOLFSSL_HARDEN_TLS) && !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
33422+ #if !defined(NO_WOLFSSL_CLIENT) && !defined(WOLFSSL_NO_TLS12) && \
33423+ defined(HAVE_SERVER_RENEGOTIATION_INFO) && \
33424+ !defined(WOLFSSL_HARDEN_TLS_NO_SCR_CHECK)
3335033425 if (ssl->scr_check_enabled && (ssl->secure_renegotiation == NULL ||
3335133426 !ssl->secure_renegotiation->enabled)) {
3335233427 /* If the server does not acknowledge the extension, the client
3335333428 * MUST generate a fatal handshake_failure alert prior to
3335433429 * terminating the connection.
3335533430 * https://www.rfc-editor.org/rfc/rfc9325#name-renegotiation-in-tls-12 */
3335633431 WOLFSSL_MSG("ServerHello did not contain SCR extension");
33432+ WOLFSSL_ERROR_VERBOSE(SECURE_RENEGOTIATION_E);
33433+ (void)SendAlert(ssl, alert_fatal, handshake_failure);
3335733434 return SECURE_RENEGOTIATION_E;
3335833435 }
3335933436#endif
0 commit comments