Skip to content

Commit f7c48e7

Browse files
author
lws-bot
committed
feat: implement IANA cipher suite support for mbedtls backend
- Add IANA cipher suite parsing for mbedtls backend using lws_tokenize - Implement ssl_pm_set_ciphersuites() to apply cipher IDs to SSL config - Apply cipher list during TLS handshake in lws_tls_server_vhost_backend_init() - Fix missing mbedtls_ssl_session_save() call in session update case - Add CMake detection for mbedtls_ssl_conf_ciphersuites and mbedtls_ssl_session_save - Standardize macro naming to follow lowercase function pattern This implementation aligns the mbedtls backend with OpenSSL and Schannel by supporting standard IETF/IANA cipher names. The lws_tokenize API provides robust, non-destructive tokenization and eliminates hardcoded cipher lists, allowing automatic updates when new ciphers are added to mbedtls.
1 parent c3857fd commit f7c48e7

File tree

8 files changed

+187
-0
lines changed

8 files changed

+187
-0
lines changed

cmake/lws_config.h.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
#cmakedefine LWS_HAVE_mbedtls_ssl_conf_alpn_protocols
7474
#cmakedefine LWS_HAVE_mbedtls_ssl_get_alpn_protocol
7575
#cmakedefine LWS_HAVE_mbedtls_ssl_conf_sni
76+
#cmakedefine LWS_HAVE_mbedtls_ssl_conf_ciphersuites
77+
#cmakedefine LWS_HAVE_mbedtls_ssl_session_save
7678
#cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_ca_chain
7779
#cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_own_cert
7880
#cmakedefine LWS_HAVE_mbedtls_ssl_set_hs_authmode

lib/tls/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,8 @@ if (LWS_WITH_MBEDTLS)
430430
set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols 1 CACHE BOOL x)
431431
set(LWS_HAVE_mbedtls_ssl_get_alpn_protocol 1 CACHE BOOL x)
432432
set(LWS_HAVE_mbedtls_ssl_conf_sni 1 CACHE BOOL x)
433+
set(LWS_HAVE_mbedtls_ssl_conf_ciphersuites 1 CACHE BOOL x)
434+
set(LWS_HAVE_mbedtls_ssl_session_save 1 CACHE BOOL x)
433435
set(LWS_HAVE_mbedtls_ssl_set_hs_ca_chain 1 CACHE BOOL x)
434436
set(LWS_HAVE_mbedtls_ssl_set_hs_own_cert 1 CACHE BOOL x)
435437
set(LWS_HAVE_mbedtls_ssl_set_hs_authmode 1 CACHE BOOL x)
@@ -445,6 +447,8 @@ if (LWS_WITH_MBEDTLS)
445447

446448
CHECK_FUNCTION_EXISTS(mbedtls_ssl_get_alpn_protocol LWS_HAVE_mbedtls_ssl_get_alpn_protocol PARENT_SCOPE)
447449
CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_sni LWS_HAVE_mbedtls_ssl_conf_sni PARENT_SCOPE)
450+
CHECK_FUNCTION_EXISTS(mbedtls_ssl_conf_ciphersuites LWS_HAVE_mbedtls_ssl_conf_ciphersuites PARENT_SCOPE)
451+
CHECK_FUNCTION_EXISTS(mbedtls_ssl_session_save LWS_HAVE_mbedtls_ssl_session_save PARENT_SCOPE)
448452
CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_ca_chain LWS_HAVE_mbedtls_ssl_set_hs_ca_chain PARENT_SCOPE)
449453
CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_own_cert LWS_HAVE_mbedtls_ssl_set_hs_own_cert PARENT_SCOPE)
450454
CHECK_FUNCTION_EXISTS(mbedtls_ssl_set_hs_authmode LWS_HAVE_mbedtls_ssl_set_hs_authmode PARENT_SCOPE)
@@ -612,6 +616,8 @@ exports_to_parent_scope()
612616
set(LWS_HAVE_MBEDTLS_NET_SOCKETS ${LWS_HAVE_MBEDTLS_NET_SOCKETS} PARENT_SCOPE)
613617
set(LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET ${LWS_HAVE_MBEDTLS_SSL_NEW_SESSION_TICKET} PARENT_SCOPE)
614618
set(LWS_HAVE_mbedtls_ssl_conf_alpn_protocols ${LWS_HAVE_mbedtls_ssl_conf_alpn_protocols} PARENT_SCOPE)
619+
set(LWS_HAVE_mbedtls_ssl_conf_ciphersuites ${LWS_HAVE_mbedtls_ssl_conf_ciphersuites} PARENT_SCOPE)
620+
set(LWS_HAVE_mbedtls_ssl_session_save ${LWS_HAVE_mbedtls_ssl_session_save} PARENT_SCOPE)
615621
set(TEST_SERVER_SSL_KEY "${TEST_SERVER_SSL_KEY}" PARENT_SCOPE)
616622
set(TEST_SERVER_SSL_CERT "${TEST_SERVER_SSL_CERT}" PARENT_SCOPE)
617623
set(TEST_SERVER_DATA ${TEST_SERVER_DATA} PARENT_SCOPE)

lib/tls/mbedtls/mbedtls-server.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,18 @@ lws_tls_server_vhost_backend_init(const struct lws_context_creation_info *info,
249249
if (n)
250250
return n;
251251

252+
/* Apply cipher list if specified */
253+
if (info->ssl_cipher_list) {
254+
if (SSL_CTX_set_cipher_list(vhost->tls.ssl_ctx,
255+
info->ssl_cipher_list) == 0) {
256+
lwsl_err("SSL_CTX_set_cipher_list(%s) failed\n",
257+
info->ssl_cipher_list);
258+
return 1;
259+
}
260+
lwsl_notice("%s: vh %s: applied cipher list: %s\n", __func__,
261+
vhost->name, info->ssl_cipher_list);
262+
}
263+
252264
return 0;
253265
}
254266

lib/tls/mbedtls/mbedtls-session.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,16 @@ lws_tls_reuse_session(struct lws *wsi)
106106

107107
mbedtls_ssl_session_init(&session);
108108

109+
#if defined(LWS_HAVE_mbedtls_ssl_session_save)
109110
if (mbedtls_ssl_session_load(&session, ts->ser_data->data,
110111
ts->ser_data->len)) {
111112
mbedtls_ssl_session_free(&session);
112113
goto bail;
113114
}
115+
#else
116+
/* Session load/save not supported in this mbedtls version */
117+
goto bail;
118+
#endif
114119

115120
lwsl_tlssess("%s: %s\n", __func__, (const char *)&ts[1]);
116121
wsi->tls_session_reused = 1;
@@ -256,13 +261,19 @@ lws_tls_session_new_mbedtls(struct lws *wsi)
256261
goto bail;
257262
}
258263

264+
#if defined(LWS_HAVE_mbedtls_ssl_session_save)
259265
if (mbedtls_ssl_session_save(&temp_session, ts->ser_data->data,
260266
sizeof(ts->ser_data->data),
261267
&ts->ser_data->len)) {
262268
/* Serialization failed, cache entry will be invalid */
263269
lws_free(ts->ser_data);
264270
ts->ser_data = NULL;
265271
}
272+
#else
273+
/* Session save not supported in this mbedtls version */
274+
lws_free(ts->ser_data);
275+
ts->ser_data = NULL;
276+
#endif
266277

267278
lws_dll2_add_tail(&ts->list, &vh->tls_sessions);
268279

@@ -285,13 +296,19 @@ lws_tls_session_new_mbedtls(struct lws *wsi)
285296
goto bail;
286297
}
287298

299+
#if defined(LWS_HAVE_mbedtls_ssl_session_save)
288300
if (mbedtls_ssl_session_save(&temp_session, ts->ser_data->data,
289301
sizeof(ts->ser_data->data),
290302
&ts->ser_data->len)) {
291303
/* Serialization failed, cache entry will be invalid */
292304
lws_free(ts->ser_data);
293305
ts->ser_data = NULL;
294306
}
307+
#else
308+
/* Session save not supported in this mbedtls version */
309+
lws_free(ts->ser_data);
310+
ts->ser_data = NULL;
311+
#endif
295312

296313
/* keep our session list sorted in lru -> mru order */
297314

lib/tls/mbedtls/wrapper/include/internal/ssl_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ struct ssl_ctx_st
195195

196196
int read_buffer_len;
197197

198+
/* optional list of mbedTLS ciphersuite ids, terminated by 0 */
199+
int *ciphersuites;
200+
198201
X509_VERIFY_PARAM param;
199202

200203
void *rngctx;

lib/tls/mbedtls/wrapper/include/platform/ssl_pm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int ssl_pm_get_fd(const SSL *ssl, int mode);
4242
OSSL_HANDSHAKE_STATE ssl_pm_get_state(const SSL *ssl);
4343

4444
void ssl_pm_set_bufflen(SSL *ssl, int len);
45+
int ssl_pm_set_ciphersuites(SSL *ssl, const int *ciphersuites);
4546

4647
int x509_pm_show_info(X509 *x);
4748
int x509_pm_new(X509 *x, X509 *m_x);

lib/tls/mbedtls/wrapper/library/ssl_lib.c

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,86 @@
2121
#include "ssl_cert.h"
2222
#include "ssl_dbg.h"
2323
#include "ssl_port.h"
24+
#include "platform/ssl_pm.h"
25+
#include <string.h>
26+
27+
28+
/* Parse a colon/comma/space separated list of IANA/mbedTLS ciphers
29+
* into a malloc'ed int[] terminated with 0.
30+
*/
31+
static int *parse_cipher_list_to_ids(const char *str)
32+
{
33+
int *result = NULL;
34+
size_t tokens = 0, out = 0;
35+
struct lws_tokenize ts;
36+
lws_tokenize_elem e;
37+
char tok[256];
38+
39+
if (!str || !*str)
40+
return NULL;
41+
42+
/* First pass: count tokens */
43+
lws_tokenize_init(&ts, str, 0);
44+
while (lws_tokenize(&ts) != LWS_TOKZE_ENDED) {
45+
if (ts.e == LWS_TOKZE_TOKEN)
46+
tokens++;
47+
}
48+
49+
if (tokens == 0)
50+
return NULL;
51+
52+
result = ssl_mem_malloc((tokens + 1) * sizeof(int));
53+
if (!result)
54+
return NULL;
55+
56+
/* Second pass: parse and convert tokens */
57+
lws_tokenize_init(&ts, str, 0);
58+
while ((e = lws_tokenize(&ts)) != LWS_TOKZE_ENDED) {
59+
int id = 0;
60+
61+
if (e != LWS_TOKZE_TOKEN)
62+
continue;
63+
64+
/* Copy token to null-terminated buffer */
65+
if (lws_tokenize_cstr(&ts, tok, sizeof(tok)) != 0)
66+
continue; /* token too long, skip it */
67+
68+
/* 1) try mbedTLS native name directly */
69+
id = mbedtls_ssl_get_ciphersuite_id(tok);
70+
71+
/* 2) if that failed and it looks like IANA (TLS_...) convert '_' -> '-' */
72+
if (id <= 0 && strncmp(tok, "TLS_", 4) == 0) {
73+
char name[256];
74+
size_t k;
75+
76+
strncpy(name, tok, sizeof(name) - 1);
77+
name[sizeof(name) - 1] = '\0';
78+
79+
for (k = 0; name[k]; ++k) {
80+
if (name[k] == '_')
81+
name[k] = '-';
82+
}
83+
84+
id = mbedtls_ssl_get_ciphersuite_id(name);
85+
}
86+
87+
if (id > 0) {
88+
result[out++] = id;
89+
} else {
90+
/* Optional: log unknown cipher */
91+
// lws_notice("unknown TLS ciphersuite '%s' in list '%s'\n", tok, str);
92+
}
93+
}
94+
95+
if (!out) {
96+
ssl_mem_free(result);
97+
return NULL;
98+
}
99+
100+
result[out] = 0;
101+
return result;
102+
}
103+
24104

25105
char *
26106
lws_strncpy(char *dest, const char *src, size_t size);
@@ -256,6 +336,11 @@ void SSL_CTX_free(SSL_CTX* ctx)
256336
{
257337
SSL_ASSERT3(ctx);
258338

339+
if (ctx->ciphersuites) {
340+
ssl_mem_free(ctx->ciphersuites);
341+
ctx->ciphersuites = NULL;
342+
}
343+
259344
ssl_cert_free(ctx->cert);
260345

261346
#if defined(LWS_HAVE_mbedtls_x509_crt_parse_file)
@@ -279,6 +364,42 @@ void SSL_CTX_free(SSL_CTX* ctx)
279364
ssl_mem_free(ctx);
280365
}
281366

367+
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
368+
{
369+
int *ids;
370+
371+
SSL_ASSERT1(ctx);
372+
373+
/* free previous list if any */
374+
if (ctx->ciphersuites) {
375+
ssl_mem_free(ctx->ciphersuites);
376+
ctx->ciphersuites = NULL;
377+
}
378+
379+
ids = parse_cipher_list_to_ids(str);
380+
if (!ids)
381+
return 0;
382+
383+
ctx->ciphersuites = ids;
384+
385+
return 1;
386+
}
387+
388+
int SSL_set_cipher_list(SSL *ssl, const char *str)
389+
{
390+
int ok;
391+
392+
SSL_ASSERT1(ssl);
393+
394+
ok = SSL_CTX_set_cipher_list(ssl->ctx, str);
395+
396+
/* if config exists for this ssl instance, apply immediately if possible */
397+
if (ok && ssl->ssl_pm && ssl->ctx && ssl->ctx->ciphersuites) {
398+
ssl_pm_set_ciphersuites(ssl, ssl->ctx->ciphersuites);
399+
}
400+
401+
return ok;
402+
}
282403
/**
283404
* @brief set the SSL context version
284405
*/

lib/tls/mbedtls/wrapper/platform/ssl_pm.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,34 @@ static int ssl_pm_reload_crt(SSL *ssl)
283283
ret = -1;
284284
}
285285

286+
/* if the SSL_CTX has a ciphersuite list, apply it to this config */
287+
#if defined(LWS_HAVE_mbedtls_ssl_conf_ciphersuites)
288+
if (ssl->ctx && ssl->ctx->ciphersuites) {
289+
mbedtls_ssl_conf_ciphersuites(&ssl_pm->conf, ssl->ctx->ciphersuites);
290+
}
291+
#endif
292+
286293
return ret;
287294
}
288295

296+
/*
297+
* Set ciphersuites on an existing SSL connection
298+
*/
299+
int ssl_pm_set_ciphersuites(SSL *ssl, const int *ciphersuites)
300+
{
301+
struct ssl_pm *ssl_pm = (struct ssl_pm *)ssl->ssl_pm;
302+
303+
if (!ssl || !ssl_pm || !ciphersuites)
304+
return 0;
305+
306+
#if defined(LWS_HAVE_mbedtls_ssl_conf_ciphersuites)
307+
mbedtls_ssl_conf_ciphersuites(&ssl_pm->conf, ciphersuites);
308+
return 1;
309+
#else
310+
return 0;
311+
#endif
312+
}
313+
289314
/*
290315
* Perform the mbedtls SSL handshake instead of mbedtls_ssl_handshake.
291316
* We can add debug here.

0 commit comments

Comments
 (0)