@@ -15125,11 +15125,20 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
1512515125{
1512615126 int ret = 0;
1512715127 TLSX* extension;
15128- word16 offset = 0;
15129- word16 length_offset = 0;
15128+ /* Use word32 to symmetrize with TLSX_GetSize -- a single extension can
15129+ * contribute up to 0x10003 bytes (4-byte type/length header + 0xFFFF
15130+ * payload), which would word16-overflow undetectably (e.g. wrap to a
15131+ * value still above prevOffset). Per-iteration and aggregate bounds are
15132+ * checked below before truncating back into the word16 wire fields.
15133+ * Callees that take a word16* offset use the cbShim pattern (init to 0,
15134+ * then add the returned delta to the word32 accumulator). */
15135+ word32 offset = 0;
15136+ word32 length_offset = 0;
1513015137 word32 prevOffset;
15138+ word16 cbShim = 0;
1513115139 byte isRequest = (msgType == client_hello ||
1513215140 msgType == certificate_request);
15141+ (void)cbShim;
1513315142
1513415143 while ((extension = list)) {
1513515144 list = extension->next;
@@ -15249,28 +15258,36 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
1524915258#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY)
1525015259 case TLSX_ENCRYPT_THEN_MAC:
1525115260 WOLFSSL_MSG("Encrypt-Then-Mac extension to write");
15252- ret = ETM_WRITE(extension->data, output, msgType, &offset);
15261+ cbShim = 0;
15262+ ret = ETM_WRITE(extension->data, output, msgType, &cbShim);
15263+ offset += cbShim;
1525315264 break;
1525415265#endif /* HAVE_ENCRYPT_THEN_MAC */
1525515266
1525615267#if defined(WOLFSSL_TLS13) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS)
1525715268 #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
1525815269 case TLSX_PRE_SHARED_KEY:
1525915270 WOLFSSL_MSG("Pre-Shared Key extension to write");
15271+ cbShim = 0;
1526015272 ret = PSK_WRITE((PreSharedKey*)extension->data, output + offset,
15261- msgType, &offset);
15273+ msgType, &cbShim);
15274+ offset += cbShim;
1526215275 break;
1526315276
1526415277 #ifdef WOLFSSL_TLS13
1526515278 case TLSX_PSK_KEY_EXCHANGE_MODES:
1526615279 WOLFSSL_MSG("PSK Key Exchange Modes extension to write");
15280+ cbShim = 0;
1526715281 ret = PKM_WRITE((byte)extension->val, output + offset, msgType,
15268- &offset);
15282+ &cbShim);
15283+ offset += cbShim;
1526915284 break;
1527015285 #ifdef WOLFSSL_CERT_WITH_EXTERN_PSK
1527115286 case TLSX_CERT_WITH_EXTERN_PSK:
1527215287 WOLFSSL_MSG("Cert with external PSK extension to write");
15273- ret = PSK_WITH_CERT_WRITE(output + offset, msgType, &offset);
15288+ cbShim = 0;
15289+ ret = PSK_WITH_CERT_WRITE(output + offset, msgType, &cbShim);
15290+ offset += cbShim;
1527415291 break;
1527515292 #endif
1527615293 #endif
@@ -15284,28 +15301,36 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
1528415301#ifdef WOLFSSL_TLS13
1528515302 case TLSX_SUPPORTED_VERSIONS:
1528615303 WOLFSSL_MSG("Supported Versions extension to write");
15304+ cbShim = 0;
1528715305 ret = SV_WRITE(extension->data, output + offset, msgType,
15288- &offset);
15306+ &cbShim);
15307+ offset += cbShim;
1528915308 break;
1529015309
1529115310 case TLSX_COOKIE:
1529215311 WOLFSSL_MSG("Cookie extension to write");
15312+ cbShim = 0;
1529315313 ret = CKE_WRITE((Cookie*)extension->data, output + offset,
15294- msgType, &offset);
15314+ msgType, &cbShim);
15315+ offset += cbShim;
1529515316 break;
1529615317
1529715318 #ifdef WOLFSSL_EARLY_DATA
1529815319 case TLSX_EARLY_DATA:
1529915320 WOLFSSL_MSG("Early Data extension to write");
15321+ cbShim = 0;
1530015322 ret = EDI_WRITE(extension->val, output + offset, msgType,
15301- &offset);
15323+ &cbShim);
15324+ offset += cbShim;
1530215325 break;
1530315326 #endif
1530415327
1530515328 #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
1530615329 case TLSX_POST_HANDSHAKE_AUTH:
1530715330 WOLFSSL_MSG("Post-Handshake Authentication extension to write");
15308- ret = PHA_WRITE(output + offset, msgType, &offset);
15331+ cbShim = 0;
15332+ ret = PHA_WRITE(output + offset, msgType, &cbShim);
15333+ offset += cbShim;
1530915334 break;
1531015335 #endif
1531115336
@@ -15361,16 +15386,26 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
1536115386#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
1536215387 case TLSX_ECH:
1536315388 WOLFSSL_MSG("ECH extension to write");
15389+ cbShim = 0;
1536415390 ret = ECH_WRITE((WOLFSSL_ECH*)extension->data, msgType,
15365- output + offset, &offset);
15391+ output + offset, &cbShim);
15392+ offset += cbShim;
1536615393 break;
1536715394#endif
1536815395 default:
1536915396 break;
1537015397 }
1537115398
15399+ /* Per-extension data length is a 2-byte wire field; reject any
15400+ * single extension whose payload exceeds that before truncating. */
15401+ if (offset - length_offset > WOLFSSL_MAX_16BIT) {
15402+ WOLFSSL_MSG("TLSX_Write single extension length exceeds word16");
15403+ return BUFFER_E;
15404+ }
15405+
1537215406 /* writes extension data length. */
15373- c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN);
15407+ c16toa((word16)(offset - length_offset),
15408+ output + length_offset - OPAQUE16_LEN);
1537415409
1537515410 /* marks the extension as processed so ctx level */
1537615411 /* extensions don't overlap with ssl level ones. */
@@ -15381,7 +15416,7 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
1538115416 break;
1538215417
1538315418 if (offset <= prevOffset) {
15384- WOLFSSL_MSG("TLSX_Write extension length exceeds word16 ");
15419+ WOLFSSL_MSG("TLSX_Write extension made no progress ");
1538515420 return BUFFER_E;
1538615421 }
1538715422 }
@@ -15391,11 +15426,11 @@ static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
1539115426 * unchanged and return the original failure reason so callers
1539215427 * see the real error instead of a masking BUFFER_E. */
1539315428 if (ret == 0) {
15394- if ((word32)*pOffset + (word32) offset > WOLFSSL_MAX_16BIT) {
15429+ if ((word32)*pOffset + offset > WOLFSSL_MAX_16BIT) {
1539515430 WOLFSSL_MSG("TLSX_Write total extensions length exceeds word16");
1539615431 return BUFFER_E;
1539715432 }
15398- *pOffset += offset;
15433+ *pOffset += (word16) offset;
1539915434 }
1540015435
1540115436 return ret;
0 commit comments