Morse Micro CMSIS Pack 1.9.0 mbedTLS fork writes wrong record version on ChangeCipherSpec / Finished (TLS 1.2)

Hi,

On the Morse Micro CMSIS Pack 1.9.0 of mbedTLS (v3.6.x), an outbound TLS 1.2 handshake completes correctly up through ServerHelloDone, but the subsequent ChangeCipherSpec and Finished records are emitted with the SSL 3.0 wire version (03 00) instead of TLS 1.2 (03 03). Strict clients (OpenSSL s_client, Python ssl) reject this with fatal protocol_version / WRONG_VERSION_NUMBER and abort.

The root cause is that ssl->tls_version is clobbered to 0x0300 between the CCS state and the Finished state — almost certainly due to the fork’s badmac_seen_or_in_hsfraglen union member aliasing a neighboring field in mbedtls_ssl_context.

Debug evidence:

output record: msgtype = 20, version = [3:3], msglen = zu
0000:  14 03 03 00 01 01          <-- CCS correct

output record: msgtype = 22, version = [3:0], msglen = zu
0000:  16 03 00 00 28 ...          <-- Finished WRONG

Client sees:

SSL routines:tls_validate_record_header:wrong version number

Where it goes wrong: library/ssl_msg.c, mbedtls_ssl_write_record():

mbedtls_ssl_protocol_version tls_ver = ssl->tls_version;   // <-- 0x0300 here
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
    if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) {
        tls_ver = MBEDTLS_SSL_VERSION_TLS1_2;
    }
#endif
mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport, tls_ver);

I did a small patch which made things work:

mbedtls_ssl_protocol_version tls_ver = ssl->tls_version;
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
    if (tls_ver == MBEDTLS_SSL_VERSION_TLS1_3) {
        tls_ver = MBEDTLS_SSL_VERSION_TLS1_2;
    }
#endif

    /* Force the TLS 1.2 wire version. The fork clobbers ssl->tls_version
     * to 0x0300 on the CCS -> Finished transition, causing strict clients
     * to abort with a fatal protocol_version alert. */
    if (tls_ver != MBEDTLS_SSL_VERSION_TLS1_2) {
        tls_ver = MBEDTLS_SSL_VERSION_TLS1_2;
    }

mbedtls_ssl_write_version(ssl->out_hdr + 1, ssl->conf->transport, tls_ver);

I hope this doesn’t affect is anything uses this and this is patched in next cmsis version.

Hi @Rohit_Anandakumar ,

Thanks for the details, we think there are a few possible causes.

  1. CMSIS-Pack 1.9.0 incorporated the MM-IoT-SDK 2.11.2, which had an upstep of mbedTLS from 3.6.2 to 3.6.5. So it is perhaps this change that is causing the issue (CMSIS passes through the SDK’s version of mbedTLS).
  2. As you mention, the problem could be that a neighbouring field is clobbering the tls_version.
  3. It could also be that the tls_version is being updated from an offset value (for example, the memory looks like 0x00,03,03,00 and the read from this memory is off by one).

We will look into this, but it would be helpful to know where you are starting from. Could you tell us:

  1. What your mbedtls_config.h is?
  2. Which example your are running (is it the sslclient example?)?
  3. What additional build defines you might be using?
  4. The details of how you’re testing the SSL 1.2 connection?

Also, if you have the time, could you see if the same behaviour exists in CMSIS 1.8?

Thanks again,

Andrew

1 Like