devicescript icon indicating copy to clipboard operation
devicescript copied to clipboard

broaden crypto suite support on mbedTLS

Open num-lock opened this issue 1 year ago • 2 comments

Did some evaluation and fiddling with DeviceScript on a couple of ESP32 and ESP32-C3 boards. Upon testing the fetch API I noticed that the supported cipher suites compiled into mbedTLS seem pretty conservative? When testing against a couple of IIoT production environments I get mbedTLS handshake errors. It appears none of these are supported (which are the only ones supported server side):

TLS 1.2

  • TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
  • TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)

TLS 1.3

  • TLS_CHACHA20_POLY1305_SHA256 (0x1303)
  • TLS_AES_256_GCM_SHA384 (0x1302)

Servers use 384 bit EC keys.

Works fine with ESP-IDF or even Arduino IDE (which for ESP32 is just an IDF wrapper anyway) on default builds, so I guess mbedTLS got stripped down quite a bit for size here? Unless I test against sites that also still try to support devices running Windows XP with Internet Explorer 6 (like github.com or google.com) I can't really get a working TLS connection.

num-lock avatar Jun 13 '23 06:06 num-lock

This is somewhat surprising, the settings we have are just:

CONFIG_SSL_USING_MBEDTLS=y
CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE=y
CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE=y

We do not enable TLS 1.3 since it's experimental in mbedTLS and I think it also disables TLS 1.2. Could you share some addresses of servers that only accept these cipher suites so I can test it?

mmoskal avatar Jun 18 '23 22:06 mmoskal

I put together a little node script. This will run a server that supports said cipher suites only. Both key and DH curve are 384 bit as it's the case with our production systems. Make sure to add express and to create the key and certificate:

openssl ecparam -name secp384r1 -genkey -out key.pem
openssl req -new -x509 -key key.pem -sha256 -nodes -out cert.pem -days 7
const https = require('node:https')
const fs = require('node:fs')

const express = require('express')

const app = express()

app.get('/example', (_, res) => {
    console.log('request')
    res.status(200).send('ok')
})

const ciphers = [
    // TLSv1.3
    'TLS_CHACHA20_POLY1305_SHA256',
    'TLS_AES_256_GCM_SHA384',
    // TLSv1.2
    'ECDHE-ECDSA-CHACHA20-POLY1305',
    'ECDHE-ECDSA-AES256-GCM-SHA384',
].join(':')

https.createServer({
    key: fs.readFileSync('key.pem'),
    cert: fs.readFileSync('cert.pem'),
    ciphers,
    ecdhCurve: 'P-384',
}, app).listen(8443, '0.0.0.0', () => {
    console.log('listening ...')
})

This will listen on all interfaces and simply return ok on https://<ip>:8443/example. Modify as needed.

num-lock avatar Jun 19 '23 17:06 num-lock