@@ -5483,7 +5483,6 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
54835483
54845484 if (args->pv.major != ssl->version.major ||
54855485 args->pv.minor != tls12minor) {
5486- SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version);
54875486 WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
54885487 return VERSION_ERROR;
54895488 }
@@ -5567,39 +5566,42 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
55675566 }
55685567
55695568 if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) {
5570- if (!ssl->options.downgrade) {
5571- /* Fewer than OPAQUE16_LEN bytes remain after the compression
5572- * method, so there is no complete extensions length field. */
5573- if ((args->idx - args->begin) < helloSz) {
5574- /* A partial extensions length field is genuinely malformed:
5575- * report it as a decode error. */
5576- WOLFSSL_MSG("Truncated extensions length in ServerHello");
5577- return BUFFER_ERROR;
5578- }
5579- /* No extensions field at all, so the server is not offering TLS 1.3
5580- * (no supported_versions extension - see RFC 8446 4.2.1) but TLS 1.2
5581- * or below. This is a well-formed message, so a TLS 1.3-only client
5582- * (downgrade disabled) must reject it as a version mismatch, not as
5583- * a malformed message. Returning VERSION_ERROR makes the caller send
5584- * a protocol_version alert (RFC 8446 6.2) rather than decode_error. */
5585- WOLFSSL_MSG("Server offered TLS 1.2 (no supported_versions ext) "
5586- "but downgrade not allowed");
5587- WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
5588- return VERSION_ERROR;
5569+ /* Fewer than OPAQUE16_LEN bytes remain after the compression method, so
5570+ * there is no complete extensions length field. */
5571+ if ((args->idx - args->begin) < helloSz) {
5572+ /* A partial extensions length field is genuinely malformed: report
5573+ * it as a decode error regardless of message type. */
5574+ WOLFSSL_MSG("Truncated extensions length in ServerHello");
5575+ return BUFFER_ERROR;
55895576 }
55905577
5578+ /* No extensions field at all. */
55915579 if (args->extMsgType == hello_retry_request) {
55925580 /* The sentinel Random (RFC 8446 4.1.3) identifies this as a TLS 1.3
55935581 * HelloRetryRequest, which MUST carry supported_versions
5594- * (4.1.4/4.2.1 ). Reaching this downgrade branch means it does not,
5595- * so the HRR is malformed. Reject it before DoServerHello would
5596- * reinterpret the sentinel as a plain TLS 1.2 ServerHello.Random.
5597- * The sentinel has already identified this as an HRR, so report it
5598- * uniformly as an invalid HRR; INVALID_PARAMETER maps to the
5599- * illegal_parameter alert . */
5582+ * (4.2.1/9.2 ). Its complete absence is a missing mandatory
5583+ * extension, so - consistently with the extensions-present case
5584+ * handled later - report it as missing_extension (via
5585+ * INCOMPLETE_DATA), regardless of whether a downgrade would
5586+ * otherwise be allowed. Reject here before DoServerHello would
5587+ * reinterpret the sentinel as a plain TLS 1.2 ServerHello.Random . */
56005588 WOLFSSL_MSG("HelloRetryRequest with no supported_versions");
5601- WOLFSSL_ERROR_VERBOSE(INVALID_PARAMETER);
5602- return INVALID_PARAMETER;
5589+ WOLFSSL_ERROR_VERBOSE(INCOMPLETE_DATA);
5590+ return INCOMPLETE_DATA;
5591+ }
5592+
5593+ if (!ssl->options.downgrade) {
5594+ /* A plain ServerHello with no extensions is not offering TLS 1.3
5595+ * (no supported_versions extension - see RFC 8446 4.2.1) but TLS
5596+ * 1.2 or below. This is a well-formed message, so a TLS 1.3-only
5597+ * client (downgrade disabled) must reject it as a version mismatch,
5598+ * not as a malformed message. Returning VERSION_ERROR makes the
5599+ * caller send a protocol_version alert (RFC 8446 6.2) rather than
5600+ * decode_error. */
5601+ WOLFSSL_MSG("Server offered TLS 1.2 (no supported_versions ext) "
5602+ "but downgrade not allowed");
5603+ WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
5604+ return VERSION_ERROR;
56035605 }
56045606#ifndef WOLFSSL_NO_TLS12
56055607 /* Force client hello version 1.2 to work for static RSA. */
@@ -5620,14 +5622,14 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
56205622#endif
56215623 ssl->options.haveEMS = 0;
56225624 if (args->pv.minor < ssl->options.minDowngrade) {
5623- SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version );
5625+ WOLFSSL_ERROR_VERBOSE(VERSION_ERROR );
56245626 return VERSION_ERROR;
56255627 }
56265628#ifndef WOLFSSL_NO_TLS12
56275629 ssl->options.tls1_3 = 0;
56285630 return DoServerHello(ssl, input, inOutIdx, helloSz);
56295631#else
5630- SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version );
5632+ WOLFSSL_ERROR_VERBOSE(VERSION_ERROR );
56315633 return VERSION_ERROR;
56325634#endif
56335635 }
@@ -5649,28 +5651,27 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
56495651 return ret;
56505652 }
56515653 if (!foundVersion) {
5654+ /* RFC 8446 4.1.4: "The server's extensions MUST contain
5655+ * 'supported_versions'." (also 9.2: "supported_versions" is
5656+ * REQUIRED for all ... HelloRetryRequest messages). The HRR random
5657+ * unambiguously identifies a TLS 1.3 server, so its absence is not
5658+ * a downgrade attempt but a missing mandatory extension, which per
5659+ * the "missing_extension" alert definition must be reported as
5660+ * such. Return INCOMPLETE_DATA (which maps to a missing_extension
5661+ * alert) and let the caller emit the alert via
5662+ * TranslateErrorToAlert(). */
5663+ if (*extMsgType == hello_retry_request) {
5664+ WOLFSSL_MSG("HelloRetryRequest missing supported_versions "
5665+ "extension");
5666+ WOLFSSL_ERROR_VERBOSE(INCOMPLETE_DATA);
5667+ return INCOMPLETE_DATA;
5668+ }
56525669 if (!ssl->options.downgrade) {
56535670 WOLFSSL_MSG("Server trying to downgrade to version less than "
56545671 "TLS v1.3");
5655- SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version);
56565672 WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
56575673 return VERSION_ERROR;
56585674 }
5659-
5660- if (args->extMsgType == hello_retry_request) {
5661- /* The HelloRetryRequest sentinel Random is reserved for TLS 1.3
5662- * (RFC 8446 4.1.3), but supported_versions (which an HRR MUST
5663- * carry, 4.1.4/4.2.1) is absent, so the message is malformed.
5664- * Reject before the downgrade reparses the remaining extensions
5665- * as a TLS 1.2 server_hello, where a recognized-but-not-
5666- * permitted extension (e.g. server_name) would wrongly yield an
5667- * unsupported_extension alert. illegal_parameter (via
5668- * EXT_NOT_ALLOWED) is chosen over missing_extension per the
5669- * RFC 8446 4.2 rule for such extensions. */
5670- WOLFSSL_MSG("HelloRetryRequest without supported_versions");
5671- WOLFSSL_ERROR_VERBOSE(EXT_NOT_ALLOWED);
5672- return EXT_NOT_ALLOWED;
5673- }
56745675#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) || \
56755676 defined(WOLFSSL_WPAS_SMALL)
56765677 /* Check if client has disabled TLS 1.2 */
@@ -5686,14 +5687,12 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
56865687
56875688 if (!ssl->options.dtls &&
56885689 args->pv.minor < ssl->options.minDowngrade) {
5689- SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version);
56905690 WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
56915691 return VERSION_ERROR;
56925692 }
56935693
56945694 if (ssl->options.dtls &&
56955695 args->pv.minor > ssl->options.minDowngrade) {
5696- SendAlert(ssl, alert_fatal, wolfssl_alert_protocol_version);
56975696 WOLFSSL_ERROR_VERBOSE(VERSION_ERROR);
56985697 return VERSION_ERROR;
56995698 }
0 commit comments